diff --git a/.gitignore b/.gitignore index 331bf634f..7774f1f3a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ .project .settings .directory +.vscode CMakeCache.txt CMakeFiles diff --git a/AUTHORS.txt b/AUTHORS.txt index 15e3e13d4..160869776 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -28,6 +28,7 @@ Development contributors, in last name alphabetical order: Adam Reichold Philip Rinn Jan Rinze + Alberto Romei Ben S. Andrey Skvortsov Fabio Suprani diff --git a/CMakeLists.txt b/CMakeLists.txt index d62d191e1..a2bcc5e5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,6 +136,9 @@ option(TRACE_MYRWMUTEX "Trace custom R/W Mutex (Debug builds only); redirecting option(AUTO_GDK_FLUSH "Use gdk_flush on all gdk_thread_leave other than the GUI thread; set it ON if you experience X Server warning/errors" OFF) #option(TARGET32BIT "Build for 32-bit architecture when ON, otherwise 64-bit. Default is OFF" OFF) +option(ENABLE_TCMALLOC "Use the tcmalloc library if available" OFF) +set(TCMALLOC_LIB_DIR "" CACHE PATH "Custom path for the tcmalloc library") + # Set installation directories: if(WIN32 OR APPLE) if(BUILD_BUNDLE) @@ -409,7 +412,7 @@ if(WITH_PROF) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") endif() -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wuninitialized -Wno-deprecated-declarations -Wno-unused-result") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wuninitialized -Wcast-qual -Wno-deprecated-declarations -Wno-unused-result") if(OPTION_OMP) find_package(OpenMP) if(OPENMP_FOUND) @@ -584,6 +587,23 @@ int main() return 0; }" LENSFUN_HAS_LOAD_DIRECTORY) +set(TCMALLOC_LIB_DIR) +if(ENABLE_TCMALLOC) + if(TCMALLOC_LIB_DIR) + find_library(TCMALLOC_LIBRARIES tcmalloc PATHS ${TCMALLOC_LIB_DIR} NO_DEFAULT_PATH) + else() + find_library(TCMALLOC_LIBRARIES tcmalloc) + endif() + if(TCMALLOC_LIBRARIES) + message(STATUS "using tcmalloc library in ${TCMALLOC_LIBRARIES}") + else() + set(TCMALLOC_LIBRARIES "" CACHE INTERNAL "" FORCE) + message(STATUS "tcmalloc not found") + endif() +else() + set(TCMALLOC_LIBRARIES "" CACHE INTERNAL "" FORCE) +endif() + add_subdirectory(rtengine) add_subdirectory(rtgui) diff --git a/LICENSE.txt b/LICENSE.txt index 0aa0df7c8..653f0ac50 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -13,7 +13,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . + along with this program. If not, see . GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 diff --git a/README.md b/README.md index 6d2c04875..ae9efd9c8 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,41 @@ -![RawTherapee logo](http://rawtherapee.com/images/logos/rawtherapee_logo_discuss.png) +![RawTherapee logo](https://www.rawtherapee.com/images/logos/rawtherapee_logo_discuss.png) -RawTherapee is a powerful, cross-platform raw photo processing program, released as [libre software](https://en.wikipedia.org/wiki/Free_software) under the [GNU General Public License Version 3](https://opensource.org/licenses/gpl-3.0.html). It is written mostly in C++ using a [GTK+](http://www.gtk.org/) front-end. It uses a patched version of [dcraw](http://www.cybercom.net/~dcoffin/dcraw/) for reading raw files, with an in-house solution which adds the highest quality support for certain camera models unsupported by dcraw and enhances the accuracy of certain raw files already supported by dcraw. It is notable for the advanced control it gives the user over the demosaicing and development process. +RawTherapee is a powerful, cross-platform raw photo processing program, released as [libre software](https://en.wikipedia.org/wiki/Free_software) under the [GNU General Public License Version 3](https://opensource.org/licenses/gpl-3.0.html). It is written mostly in C++ using a [GTK+](https://www.gtk.org) front-end. It uses a patched version of [dcraw](https://www.dechifro.org/dcraw/) for reading raw files, with an in-house solution which adds the highest quality support for certain camera models unsupported by dcraw and enhances the accuracy of certain raw files already supported by dcraw. It is notable for the advanced control it gives the user over the demosaicing and development process. -## Target audience +## Target Audience -RawTherapee is designed for developing raw files from a broad range of digital cameras, as well as [HDR DNG](https://helpx.adobe.com/photoshop/digital-negative.html) files and non-raw image formats ([JPEG](https://en.wikipedia.org/wiki/JPEG), [TIFF](https://en.wikipedia.org/wiki/Tagged_Image_File_Format) and [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics)). The target audience ranges from enthusiast newcomers who wish to broaden their understanding of how digital imaging works to semi-professional photographers. Knowledge in color science is not compulsory, but it is recommended that you are eager to learn and ready to read our documentation ([RawPedia](http://rawpedia.rawtherapee.com/)) as well as look up basic concepts which lie outside the scope of RawPedia, such as [color balance](https://en.wikipedia.org/wiki/Color_balance), elsewhere. +RawTherapee is designed for developing raw files from a broad range of digital cameras, as well as [HDR DNG](https://helpx.adobe.com/photoshop/digital-negative.html) files and non-raw image formats ([JPEG](https://en.wikipedia.org/wiki/JPEG), [TIFF](https://en.wikipedia.org/wiki/Tagged_Image_File_Format) and [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics)). The target audience ranges from enthusiast newcomers who wish to broaden their understanding of how digital imaging works to semi-professional photographers. Knowledge in color science is not compulsory, but it is recommended that you are eager to learn and ready to read our documentation ([RawPedia](https://rawpedia.rawtherapee.com/)) as well as look up basic concepts which lie outside the scope of RawPedia, such as [color balance](https://en.wikipedia.org/wiki/Color_balance), elsewhere. -Of course, professionals may use RawTherapee too while enjoying complete freedom, but will probably lack some peripheral features such as [Digital Asset Management](https://en.wikipedia.org/wiki/Digital_asset_management), printing, uploading, etc. RawTherapee is not aimed at being an inclusive all-in-one program, and the [open-source community](https://en.wikipedia.org/wiki/Open-source_movement) is sufficiently developed by now to offer all those peripheral features in other specialized software. +Professionals may use RawTherapee as well while enjoying complete freedom, but will probably lack some peripheral features such as [Digital Asset Management](https://en.wikipedia.org/wiki/Digital_asset_management), printing, uploading, etc. RawTherapee is not aimed at being an inclusive all-in-one program, and the [open-source community](https://en.wikipedia.org/wiki/Open-source_movement) is sufficiently developed by now to offer all those peripheral features in other specialized software. ## Links Website: -http://rawtherapee.com/ +https://www.rawtherapee.com/ Forum: https://discuss.pixls.us/c/software/rawtherapee Features: -http://rawpedia.rawtherapee.com/Features +https://rawpedia.rawtherapee.com/Features -Official documentation: -http://rawpedia.rawtherapee.com/ +Documentation: +https://rawpedia.rawtherapee.com/ Download RawTherapee: -http://rawtherapee.com/downloads +https://www.rawtherapee.com/downloads Download source code tarballs: -http://rawtherapee.com/shared/source/ +https://www.rawtherapee.com/shared/source/ -## Compilation, branches and Git +## Compilation, Branches and Git Refer to RawPedia for a detailed explanation of how to get the necessary dependencies and how to compile RawTherapee. Linux: -http://rawpedia.rawtherapee.com/Linux +https://rawpedia.rawtherapee.com/Linux Windows: -http://rawpedia.rawtherapee.com/Windows +https://rawpedia.rawtherapee.com/Windows macOS: -http://rawpedia.rawtherapee.com/macOS +https://rawpedia.rawtherapee.com/macOS diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 17cf14fd6..33a984c1c 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,9 +1,9 @@ -RAWTHERAPEE 5.6-dev RELEASE NOTES +RAWTHERAPEE 5.7-dev RELEASE NOTES This is a development version of RawTherapee. We update the code almost daily. Every few months, once enough changes have accumulated and the code is stabilized, we make a new official release. Every code change between these releases is known as a "development" version, and this is one of them. Start by reading the "Getting Started" article on RawPedia: -http://rawpedia.rawtherapee.com/ +https://rawpedia.rawtherapee.com/ While we only commit tested and relatively stable code and so the development versions should be fairly stable, you should be aware that: - Development versions only had limited testing, so there may be bugs unknown to us. @@ -26,16 +26,20 @@ In order to use RawTherapee efficiently you should know that: - All curves support the Shift and Ctrl keys while dragging a point. Shift+drag makes the point snap to a meaningful axis (top, bottom, diagonal, other), while Ctrl+drag makes your mouse movement super-fine for precise point positioning. - There are many keyboard shortcuts which make working with RawTherapee much faster and give you greater control. Make sure you familiarize yourself with them on RawPedia's "Keyboard Shortcuts" page! -New features since 5.6: -TODO. +New features since 5.7: +- TODO NEWS RELEVANT TO PACKAGE MAINTAINERS +New since 5.7: +- TODO + In general: -- To get the source code, either clone from git or use the tarball from http://rawtherapee.com/shared/source/ . Do not use the auto-generated GitHub release tarballs. -- Requires GTK+ version >=3.16, though >=3.22.24 is recommended. GTK+ versions 3.24.2 - 3.24.6 have an issue with missing combobox menu arrows and are to be avoided. +- To get the source code, either clone from git or use the tarball from https://rawtherapee.com/shared/source/ . Do not use the auto-generated GitHub release tarballs. +- Requires GTK+ version >=3.16, though >=3.22.24 is recommended. +- GTK+ versions 3.24.2 - 3.24.6 have an issue where combobox menu scroll-arrows are missing when the combobox list does not fit vertically on the screen. As a result, users would not be able to scroll in the following comboboxes: Processing Profiles, Film Simulation, and the camera and lens profiles in Profiled Lens Correction. - RawTherapee 5 requires GCC-4.9 or higher, or Clang. - Do not use -ffast-math, it will not make RawTherapee faster but will introduce artifacts. - Use -O3, it will make RawTherapee faster with no known side-effects. @@ -52,15 +56,14 @@ See CONTRIBUTING.md DOCUMENTATION -http://rawpedia.rawtherapee.com/ -http://rawtherapee.com/blog/documentation +https://rawpedia.rawtherapee.com/ REPORTING BUGS If you found a problem, don't keep it to yourself. Read the "How to write useful bug reports" article to get the problem fixed: -http://rawpedia.rawtherapee.com/How_to_write_useful_bug_reports +https://rawpedia.rawtherapee.com/How_to_write_useful_bug_reports @@ -78,8 +81,8 @@ Server: chat.freenode.net Channel: #rawtherapee You can use freenode webchat to communicate without installing anything: -http://webchat.freenode.net/?randomnick=1&channels=rawtherapee&prompt=1 -More information here: http://rawpedia.rawtherapee.com/IRC +https://webchat.freenode.net/?randomnick=1&channels=rawtherapee&prompt=1 +More information here: https://rawpedia.rawtherapee.com/IRC diff --git a/cmake/modules/FindUnalignedMalloc.cmake b/cmake/modules/FindUnalignedMalloc.cmake index 4ddfb2afc..bce150c14 100644 --- a/cmake/modules/FindUnalignedMalloc.cmake +++ b/cmake/modules/FindUnalignedMalloc.cmake @@ -13,7 +13,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with RawTherapee. If not, see . +# along with RawTherapee. If not, see . include(CheckCXXSourceCompiles) diff --git a/cmake/modules/FindX87Math.cmake b/cmake/modules/FindX87Math.cmake index b25ba3292..c079c584b 100644 --- a/cmake/modules/FindX87Math.cmake +++ b/cmake/modules/FindX87Math.cmake @@ -13,7 +13,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with RawTherapee. If not, see . +# along with RawTherapee. If not, see . include(CheckCXXSourceCompiles) diff --git a/com.rawtherapee.RawTherapee.appdata.xml b/com.rawtherapee.RawTherapee.appdata.xml index a53ccbf06..3a55109ba 100644 --- a/com.rawtherapee.RawTherapee.appdata.xml +++ b/com.rawtherapee.RawTherapee.appdata.xml @@ -8,34 +8,21 @@ Zaawansowany program do wywoływania zdjęć typu raw rawtherapee -

- RawTherapee is a powerful, cross-platform raw photo processing program. It is written mostly in C++ using a GTK+ front-end. It uses a patched version of dcraw for reading raw files, with an in-house solution which adds the highest quality support for certain camera models unsupported by dcraw and enhances the accuracy of certain raw files already supported by dcraw. It is notable for the advanced control it gives the user over the demosaicing and development process. -

-

- RawTherapee is designed for developing raw files from a broad range of digital cameras, as well as HDR DNG files and non-raw image formats (JPEG, TIFF and PNG). The target audience ranges from enthusiast newcomers who wish to broaden their understanding of how digital imaging works to semi-professional photographers. Knowledge in color science is not compulsory, but it is recommended that you are eager to learn and ready to read our documentation (RawPedia) as well as look up basic concepts which lie outside the scope of RawPedia, such as color balance, elsewhere. -

-

- Of course, professionals may use RawTherapee too while enjoying complete freedom, but will probably lack some peripheral features such as Digital Asset Management, printing, uploading, etc. RawTherapee is not aimed at being an inclusive all-in-one program, and the open-source community is sufficiently developed by now to offer all those peripheral features in other specialized software. -

+

RawTherapee is a powerful, cross-platform raw photo processing program. It is written mostly in C++ using a GTK+ front-end. It uses a patched version of dcraw for reading raw files, with an in-house solution which adds the highest quality support for certain camera models unsupported by dcraw and enhances the accuracy of certain raw files already supported by dcraw. It is notable for the advanced control it gives the user over the demosaicing and development process.

+

RawTherapee is designed for developing raw files from a broad range of digital cameras, as well as HDR DNG files and non-raw image formats (JPEG, TIFF and PNG). The target audience ranges from enthusiast newcomers who wish to broaden their understanding of how digital imaging works to semi-professional photographers. Knowledge in color science is not compulsory, but it is recommended that you are eager to learn and ready to read our documentation (RawPedia) as well as look up basic concepts which lie outside the scope of RawPedia, such as color balance, elsewhere.

+

Of course, professionals may use RawTherapee too while enjoying complete freedom, but will probably lack some peripheral features such as Digital Asset Management, printing, uploading, etc. RawTherapee is not aimed at being an inclusive all-in-one program, and the open-source community is sufficiently developed by now to offer all those peripheral features in other specialized software.

- - raw - photo - photography - develop - pp3 - graphics - CC-BY-SA-4.0 GPL-3.0+ - https://github.com/Beep6581/RawTherapee/issues/new + https://github.com/Beep6581/RawTherapee/issues https://www.paypal.me/rawtherapee - http://rawpedia.rawtherapee.com/ - http://rawtherapee.com/ + https://rawpedia.rawtherapee.com + https://www.rawtherapee.com https://discuss.pixls.us/t/localization-how-to-translate-rawtherapee-and-rawpedia/2594 rawtherapee.desktop + @@ -47,16 +34,20 @@ - HDR DNG of a misty morning in the countryside - http://rawtherapee.com/images/screenshots/rt540_1.jpg + Color correction + https://rawtherapee.com/images/screenshots/rt57_drosera_rotundifolia.png - Straight-out-of-camera vs RawTherapee - http://rawtherapee.com/images/screenshots/rt540_2.jpg + File browser + https://rawtherapee.com/images/screenshots/rt57_file_browser.png - - RawTherapee using the Auto-Matched Tone Curve tool - http://rawtherapee.com/images/screenshots/rt540_3.jpg + + High dynamic range compression + https://rawtherapee.com/images/screenshots/rt57_field_sunset.png + + + Developing a film negative + https://rawtherapee.com/images/screenshots/rt57_film_negative.png contactus@rawtherapee.com diff --git a/header b/header index c42b87574..966153c0e 100644 --- a/header +++ b/header @@ -14,5 +14,5 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ diff --git a/rtdata/dcpprofiles/camera_model_aliases.json b/rtdata/dcpprofiles/camera_model_aliases.json index 61fc2bf57..32db0db52 100644 --- a/rtdata/dcpprofiles/camera_model_aliases.json +++ b/rtdata/dcpprofiles/camera_model_aliases.json @@ -16,6 +16,8 @@ "Canon EOS 1000D": ["Canon EOS Kiss Digital F", "Canon EOS DIGITAL REBEL XS"], "Canon EOS 1200D": ["Canon EOS Kiss X70", "Canon EOS REBEL T5"], "Canon EOS 1300D": ["Canon EOS Kiss X80", "Canon EOS Rebel T6"], + "Canon EOS 2000D": ["Canon EOS 1500D", "Canon EOS Kiss X90", "Canon EOS Rebel T7"], + "Canon EOS 4000D": ["Canon EOS 3000D", "Canon EOS Rebel T100"], "MINOLTA DYNAX 5D": ["Minolta Maxxum 5D", "Minolta Alpha 5D", "Minolta Alpha Sweet"], "MINOLTA DYNAX 7D": ["Minolta Maxxum 7D", "Minolta Alpha 7D"], diff --git a/rtdata/images/svg/splash.svg b/rtdata/images/svg/splash.svg index 2e46f0e6d..0989bfdb6 100644 --- a/rtdata/images/svg/splash.svg +++ b/rtdata/images/svg/splash.svg @@ -15,7 +15,7 @@ viewBox="0 0 146.05 91.545836" version="1.1" id="svg783" - inkscape:version="0.92.2 2405546, 2018-03-11" + inkscape:version="0.92.4 5da689c313, 2019-01-14" sodipodi:docname="splash.svg" inkscape:export-filename="/tmp/splash.png" inkscape:export-xdpi="96" @@ -479,8 +479,8 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="0.93979686" - inkscape:cx="-66.836581" + inkscape:zoom="0.90075514" + inkscape:cx="-60.984253" inkscape:cy="136.82017" inkscape:document-units="px" inkscape:current-layer="layer1" @@ -574,7 +574,7 @@ RawTherapee splash screen - 2019-02-27 + Maciej Dworak @@ -996,7 +996,7 @@ id="tspan595" x="283.85016" y="2.2370076" - style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:49.34799576px;line-height:1.25;font-family:'Eras Bold ITC';-inkscape-font-specification:'Eras Bold ITC Bold';letter-spacing:-7.09514618px">. 6 + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:49.34799576px;line-height:1.25;font-family:'Eras Bold ITC';-inkscape-font-specification:'Eras Bold ITC Bold';letter-spacing:-7.09514618px">. 8 Raw + id="text191"> + id="path193" /> + id="path195" /> + id="g180"> + id="text178"> + d="m 491.97892,49.720543 c 0.35766,-3.779712 0.50216,-7.579331 0.525,-11.374999 3.49046,0.443312 8.13144,-1.363048 10.53958,2.077082 2.06476,3.531904 -0.001,9.387903 -4.57968,9.241667 -2.15889,0.129374 -4.32419,-0.02526 -6.4849,0.05625 z m 3.6,-2.508333 c 5.08666,1.944261 6.57694,-7.524029 1.04583,-6.462496 -1.51765,0.07086 -0.55297,2.611495 -0.92921,3.817997 -0.0389,0.881499 -0.0777,1.762999 -0.11662,2.644499 z" + id="path182" + inkscape:connector-curvature="0" /> + d="m 512.24558,47.203876 c 0.52141,4.243467 -6.54348,3.268808 -8.01041,0.668753 -1.60517,-3.045601 0.78554,-7.314219 4.38541,-6.885416 2.83009,-1.160482 6.54312,4.736022 3.01361,4.785125 -1.52676,0.0022 -3.05351,0.0043 -4.58027,0.0065 -0.10363,2.874436 3.58483,1.929793 5.19166,1.42503 z m -5.125,-2.699999 c 1.63658,0.459668 4.34329,-0.405987 1.51633,-1.575 -0.87243,-0.02294 -1.46212,0.769347 -1.51633,1.575 z" + id="path184" + inkscape:connector-curvature="0" /> + d="m 515.32058,49.720543 c -0.89608,-2.856903 -1.90527,-5.67603 -2.875,-8.508333 4.00292,-1.488552 4.10167,3.245809 4.90451,5.232714 0.59217,-1.75459 1.25338,-3.486278 1.87049,-5.232714 2.56625,-0.335933 4.13116,-0.124958 2.35362,2.287869 -0.9018,2.070641 -1.83023,4.13055 -2.68695,6.220464 -1.18878,-0.02218 -2.37788,-0.02114 -3.56667,0 z" + id="path186" + inkscape:connector-curvature="0" /> + d="m 530.27891,47.203876 c 0.52141,4.243466 -6.54347,3.268809 -8.01041,0.668753 -1.60517,-3.045602 0.78554,-7.314218 4.38541,-6.885416 2.83009,-1.160482 6.54312,4.736022 3.01361,4.785125 -1.52676,0.0022 -3.05351,0.0043 -4.58027,0.0065 -0.10363,2.874436 3.58479,1.929795 5.19166,1.42503 z m -5.12499,-2.699999 c 1.63658,0.45967 4.34327,-0.405989 1.51632,-1.575 -0.87243,-0.02294 -1.46213,0.769344 -1.51632,1.575 z" + id="path188" + inkscape:connector-curvature="0" /> + d="m 531.04558,49.71221 c 0.30065,-3.781668 0.47414,-7.574189 0.5667,-11.366666 2.51426,-0.447643 4.06213,-0.083 3.225,2.558333 -0.13223,2.938617 -0.32432,5.874975 -0.37504,8.816666 -1.13879,-0.02585 -2.27775,-0.0128 -3.41666,-0.0083 z" + id="path190" + inkscape:connector-curvature="0" /> + d="m 540.25391,40.995543 c 3.01725,-0.298693 5.7229,2.653473 4.72396,5.623958 -1.09074,4.689975 -9.56531,4.40163 -9.89531,-0.591666 -0.42534,-2.962386 2.38271,-5.18724 5.17135,-5.032292 z m -0.0583,2.45 c -4.24412,0.537467 0.25374,7.084332 1.54583,2.45625 0.26905,-1.066587 -0.2405,-2.522332 -1.54583,-2.45625 z" + id="path192" + inkscape:connector-curvature="0" /> + d="m 545.04558,53.620543 c 0.35496,-4.053817 0.59136,-8.121391 0.6,-12.191666 2.97411,-0.291852 7.40962,-1.515461 9.14322,1.785934 1.76018,3.142194 -1.08502,8.159132 -4.89322,6.414066 -2.7439,-2.317277 -0.35353,3.728125 -1.92448,3.984374 -0.97516,-0.01651 -1.95042,-0.0079 -2.92552,0.0073 z m 3.84166,-10.066666 c -1.84548,2.987641 2.95745,6.020885 3.12496,1.783333 0.15011,-1.803962 -1.73874,-2.3203 -3.12496,-1.783333 z" + id="path194" + inkscape:connector-curvature="0" /> + d="m 555.45391,49.720543 c 0.16034,-2.834333 0.35688,-5.66874 0.38337,-8.508333 1.15151,0.2957 3.7136,-0.830715 3.10003,1.108333 1.30955,-2.529937 4.72122,-0.53374 5.64375,-0.452079 3.42124,-2.856178 6.52957,1.306413 5.04717,4.754947 1.14945,2.896676 -2.16476,4.132344 -3.39923,2.534636 0.3676,-1.51179 0.62085,-7.734534 -1.76662,-4.462496 -0.99613,1.534445 1.11226,5.830528 -1.92507,5.00833 -4.04278,1.499834 0.86,-8.028853 -3.29167,-5.374996 -1.40096,2.809083 1.91426,6.388064 -3.79173,5.391658 z" + id="path196" + inkscape:connector-curvature="0" /> + d="m 578.51224,47.203876 c 0.52141,4.243467 -6.54348,3.268808 -8.01041,0.668753 -1.60517,-3.045601 0.78554,-7.314219 4.38541,-6.885416 2.83009,-1.160482 6.54312,4.736022 3.01361,4.785125 -1.52676,0.0022 -3.05351,0.0043 -4.58027,0.0065 -0.10363,2.874436 3.58483,1.929793 5.19166,1.42503 z m -5.125,-2.699999 c 1.63658,0.459668 4.34329,-0.405987 1.51633,-1.575 -0.87243,-0.02294 -1.46212,0.769347 -1.51633,1.575 z" + id="path198" + inkscape:connector-curvature="0" /> + d="m 579.21224,49.720543 c 0.93465,-2.56639 -0.64881,-7.469587 1.45625,-8.49583 1.0983,0.09576 2.93645,-0.553409 2.32712,1.12083 2.39227,-3.020404 7.77608,-0.814174 6.26354,3.128332 -0.35525,1.853997 0.77815,5.186306 -2.22355,4.231037 -2.77419,0.701084 0.4362,-9.35128 -3.9318,-4.784372 -1.3168,3.048475 1.7868,5.470432 -3.89156,4.800003 z" + id="path200" + inkscape:connector-curvature="0" /> + d="m 596.02891,47.270543 c 0.87876,3.579834 -5.40876,3.65248 -5.43333,0.483333 -0.27646,-1.191085 0.79838,-3.603899 -0.17082,-4.124999 -1.63908,0.457718 -1.14045,-3.314326 0.60379,-2.291667 -0.78331,-2.571711 4.86457,-3.264417 3.13337,0 2.1881,-1.157251 2.856,2.651389 0.78214,2.291667 -1.64157,-0.379018 -1.16187,3.704272 -0.0989,3.849999 l 0.41666,-0.025 0.76667,-0.183333 z" + id="path202" + inkscape:connector-curvature="0" /> + diff --git a/rtdata/languages/Catala b/rtdata/languages/Catala index 974e51c38..407348417 100644 --- a/rtdata/languages/Catala +++ b/rtdata/languages/Catala @@ -1314,6 +1314,8 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1421,7 +1423,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !MAIN_MSG_TOOMANYOPENEDITORS;Too many open editors.\nPlease close an editor to continue. !MAIN_MSG_WRITEFAILED;Failed to write\n"%1"\n\nMake sure that the folder exists and that you have write permission to it. !MAIN_TAB_ADVANCED;Advanced -!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-w +!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-a !MAIN_TAB_FAVORITES;Favorites !MAIN_TAB_FAVORITES_TOOLTIP;Shortcut: Alt-u !MAIN_TAB_INSPECT; Inspect @@ -1447,6 +1449,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !PARTIALPASTE_COLORTONING;Color toning !PARTIALPASTE_DEHAZE;Haze removal !PARTIALPASTE_EQUALIZER;Wavelet levels +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PARTIALPASTE_FILMSIMULATION;Film simulation !PARTIALPASTE_FLATFIELDCLIPCONTROL;Flat-field clip control !PARTIALPASTE_GRADIENT;Graduated filter @@ -1851,6 +1854,12 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/Chinese (Simplified) b/rtdata/languages/Chinese (Simplified) index 82c8ddfa6..b93aed7af 100644 --- a/rtdata/languages/Chinese (Simplified) +++ b/rtdata/languages/Chinese (Simplified) @@ -1361,6 +1361,8 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1466,7 +1468,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !MAIN_MSG_TOOMANYOPENEDITORS;Too many open editors.\nPlease close an editor to continue. !MAIN_MSG_WRITEFAILED;Failed to write\n"%1"\n\nMake sure that the folder exists and that you have write permission to it. !MAIN_TAB_ADVANCED;Advanced -!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-w +!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-a !MAIN_TAB_FAVORITES;Favorites !MAIN_TAB_FAVORITES_TOOLTIP;Shortcut: Alt-u !MAIN_TOOLTIP_BACKCOLOR0;Background color of the preview: theme-based\nShortcut: 9 @@ -1485,6 +1487,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !OPTIONS_DEFRAW_MISSING;The default profile for raw photos could not be found or is not set.\n\nPlease check your profiles' directory, it may be missing or damaged.\n\n"%1" will be used instead. !PARTIALPASTE_ADVANCEDGROUP;Advanced Settings !PARTIALPASTE_DEHAZE;Haze removal +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PARTIALPASTE_LOCALCONTRAST;Local contrast !PARTIALPASTE_METADATA;Metadata mode !PARTIALPASTE_PREPROCESS_PDAFLINESFILTER;PDAF lines filter @@ -1798,6 +1801,12 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/Czech b/rtdata/languages/Czech index 5df69dd3a..d0b4d89f3 100644 --- a/rtdata/languages/Czech +++ b/rtdata/languages/Czech @@ -934,7 +934,7 @@ MAIN_MSG_SETPATHFIRST;K použití této funkce musíte nejprve zadat cílovou ce MAIN_MSG_TOOMANYOPENEDITORS;Příliš mnoho otevřených editorů.\nPro pokračování nejprve některý ukončete. MAIN_MSG_WRITEFAILED;Chyba zápisu\n"%1"\n\nUjistěte se, že složka existuje a máte práva do ní zapisovat. MAIN_TAB_ADVANCED;Pokročilé -MAIN_TAB_ADVANCED_TOOLTIP;Zkratka: Alt-w +MAIN_TAB_ADVANCED_TOOLTIP;Zkratka: Alt-a MAIN_TAB_COLOR;Barvy MAIN_TAB_COLOR_TOOLTIP;Zkratka: Alt-c MAIN_TAB_DETAIL;Detaily @@ -2323,4 +2323,13 @@ ZOOMPANEL_ZOOMOUT;Oddálit\nZkratka: - !FILEBROWSER_POPUPREMOVE;Delete permanently !FILEBROWSER_POPUPREMOVEINCLPROC;Delete permanently, including queue-processed version !FILEBROWSER_SHOWNOTTRASHHINT;Show only images not in trash. +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PREFERENCES_APPEARANCE_PSEUDOHIDPI;Pseudo-HiDPI mode +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 950a33f45..57236e1e6 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -82,6 +82,7 @@ #81 15.04.2019 Erweiterung (TooWaBoo) RT 5.6 #82 25.05.2019 Erweiterung (TooWaBoo) RT 5.6 #83 06.07.2019 Erweiterung (TooWaBoo) RT 5.6 +#84 18.07.2019 Erweiterung (TooWaBoo) RT 5.6 ABOUT_TAB_BUILD;Version ABOUT_TAB_CREDITS;Danksagungen @@ -241,6 +242,8 @@ FILEBROWSER_POPUPRANK2;Bewertung 2 ** FILEBROWSER_POPUPRANK3;Bewertung 3 *** FILEBROWSER_POPUPRANK4;Bewertung 4 **** FILEBROWSER_POPUPRANK5;Bewertung 5 ***** +FILEBROWSER_POPUPREMOVE;Unwiderruflich löschen +FILEBROWSER_POPUPREMOVEINCLPROC;Unwiderruflich löschen\n(einschl. aller Dateien der Stabelverarbeitung) FILEBROWSER_POPUPRENAME;Umbenennen FILEBROWSER_POPUPSELECTALL;Alle auswählen FILEBROWSER_POPUPTRASH;In den Papierkorb verschieben @@ -267,6 +270,7 @@ FILEBROWSER_SHOWDIRHINT;Alle Filter zurücksetzen.\nTaste: d FILEBROWSER_SHOWEDITEDHINT;Nur bearbeitete Bilder anzeigen.\nTaste: 7 FILEBROWSER_SHOWEDITEDNOTHINT;Nur unbearbeitete Bilder anzeigen.\nTaste: 6 FILEBROWSER_SHOWEXIFINFO;Bildinformationen ein-/ausblenden.\n\nIm Multi-Reitermodus:\nTaste: i\nIm Ein-Reitermodus:\nTaste: Alt + i +FILEBROWSER_SHOWNOTTRASHHINT;Nur Bilder außerhalb des Papierkorbs anzeigen. FILEBROWSER_SHOWORIGINALHINT;Zeige nur das Originalbild.\n\nWenn mehrere Bilder mit dem gleichen Dateinamen und unterschiedlichen Dateitypen existieren, ist das Originalbild das Bild, welches in der Liste "Dateitypen anzeigen" unter Einstellungen > Dateiverwaltung als erstes gefunden wird. FILEBROWSER_SHOWRANK1HINT;Nur mit 1 Stern bewertete Bilder anzeigen.\nTaste: 1 FILEBROWSER_SHOWRANK2HINT;Nur mit 2 Sternen bewertete Bilder anzeigen.\nTaste: 2 @@ -825,6 +829,8 @@ HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;(Bildschleier entfernen)\nMaske anzeigen HISTORY_MSG_DEHAZE_STRENGTH;(Bildschleier entfernen)\nIntensität HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;(Sensor—Matrix)\nFarbinterpolation\nAuto-Kontrastschwelle HISTORY_MSG_DUALDEMOSAIC_CONTRAST;(Sensor-Matrix)\nFarbinterpolation\nKontrastschwelle +HISTORY_MSG_FILMNEGATIVE_ENABLED;(Filmnegativ) +HISTORY_MSG_FILMNEGATIVE_VALUES;(Filmnegativ) - Werte HISTORY_MSG_HISTMATCHING;(Belichtung)\nAuto-Tonwertkurve HISTORY_MSG_ICM_OUTPUT_PRIMARIES;(Farbmanagement)\nAusgabeprofil\nVorlagen HISTORY_MSG_ICM_OUTPUT_TEMP;(Farbmanagement)\nAusgabeprofil\nIccV4-Illuminant D @@ -978,7 +984,7 @@ MAIN_MSG_SETPATHFIRST;Um diese Funktion zu nutzen, müssen Sie zuerst in den Ein MAIN_MSG_TOOMANYOPENEDITORS;Zu viele geöffnete Editorfenster.\nUm fortzufahren, schließen sie bitte ein Editorfenster. MAIN_MSG_WRITEFAILED;Fehler beim Schreiben von\n\n"%1"\n\nStellen Sie sicher, dass das Verzeichnis existiert und dass Sie Schreibrechte besitzen. MAIN_TAB_ADVANCED;Erweitert -MAIN_TAB_ADVANCED_TOOLTIP;Taste: Alt + w +MAIN_TAB_ADVANCED_TOOLTIP;Taste: Alt + a MAIN_TAB_COLOR;Farbe MAIN_TAB_COLOR_TOOLTIP;Taste: Alt + c MAIN_TAB_DETAIL;Details @@ -1061,6 +1067,7 @@ PARTIALPASTE_EQUALIZER;Wavelet PARTIALPASTE_EVERYTHING;Alle Parameter aktivieren / deaktivieren PARTIALPASTE_EXIFCHANGES;Änderungen an Exif-Daten PARTIALPASTE_EXPOSURE;Belichtung +PARTIALPASTE_FILMNEGATIVE;Filmnegativ PARTIALPASTE_FILMSIMULATION;Filmsimulation PARTIALPASTE_FLATFIELDAUTOSELECT;Weißbild: Automatische Auswahl PARTIALPASTE_FLATFIELDBLURRADIUS;Weißbild: Unschärferadius @@ -1714,6 +1721,12 @@ TP_EXPOSURE_TCMODE_STANDARD;Standard TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Gewichteter Standard TP_EXPOS_BLACKPOINT_LABEL;Schwarzpunkt TP_EXPOS_WHITEPOINT_LABEL;Weißpunkt +TP_FILMNEGATIVE_BLUE;Blauverhältnis +TP_FILMNEGATIVE_GREEN;Bezugsexponent (Kontrast) +TP_FILMNEGATIVE_GUESS_TOOLTIP;Berechnet die Exponenten durch Auswahl zweier neutraler\nReferenzpunkte im Bild. Weiß (Hellgrau) und Schwarz (Dunkelgrau).\nDie Reihenfolge spielt keine Rolle. Die Exponenten werden aktualisiert,\nnachdem der zweite Punkt ausgewählt wurde. +TP_FILMNEGATIVE_LABEL;Filmnegativ +TP_FILMNEGATIVE_PICK;Weißen und schwarzen Bereich auswählen +TP_FILMNEGATIVE_RED;Rotverhältnis TP_FILMSIMULATION_LABEL;Filmsimulation TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee sucht nach Hald-CLUT-Bildern, die für die Filmsimulation benötigt werden, in einem Ordner, der viel Zeit benötigt.\nGehen Sie zu\n< Einstellungen > Bildbearbeitung > Filmsimulation >\nund prüfen Sie welcher Order benutzt wird. Wählen Sie den Ordner aus, der nur die Hald-CLUT-Bilder beinhaltet, oder einen leeren Ordner, wenn Sie die Filsimulation nicht verwenden möchten.\n\nWeitere Informationen über die Filmsimulation finden Sie auf RawPedia.\n\nMöchten Sie die Suche beenden? TP_FILMSIMULATION_STRENGTH;Intensität @@ -2358,10 +2371,3 @@ ZOOMPANEL_ZOOMFITSCREEN;An Bildschirm anpassen.\nTaste: Alt + f ZOOMPANEL_ZOOMIN;Hineinzoomen\nTaste: + ZOOMPANEL_ZOOMOUT;Herauszoomen\nTaste: - -!!!!!!!!!!!!!!!!!!!!!!!!! -! Untranslated keys follow; remove the ! prefix after an entry is translated. -!!!!!!!!!!!!!!!!!!!!!!!!! - -FILEBROWSER_POPUPREMOVE;Unwiderruflich löschen -FILEBROWSER_POPUPREMOVEINCLPROC;Unwiderruflich löschen\n(einschl. aller Dateien der Stabelverarbeitung) -FILEBROWSER_SHOWNOTTRASHHINT;Nur Bilder außerhalb des Papierkorbs anzeigen. diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index 6d1c7c09c..c6b521c12 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -838,6 +838,8 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -988,7 +990,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !MAIN_MSG_TOOMANYOPENEDITORS;Too many open editors.\nPlease close an editor to continue. !MAIN_MSG_WRITEFAILED;Failed to write\n"%1"\n\nMake sure that the folder exists and that you have write permission to it. !MAIN_TAB_ADVANCED;Advanced -!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-w +!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-a !MAIN_TAB_COLOR_TOOLTIP;Shortcut: Alt-c !MAIN_TAB_DETAIL;Detail !MAIN_TAB_DETAIL_TOOLTIP;Shortcut: Alt-d @@ -1064,6 +1066,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !PARTIALPASTE_EVERYTHING;Everything !PARTIALPASTE_EXIFCHANGES;Exif !PARTIALPASTE_EXPOSURE;Exposure +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PARTIALPASTE_FILMSIMULATION;Film simulation !PARTIALPASTE_FLATFIELDAUTOSELECT;Flat-field auto-selection !PARTIALPASTE_FLATFIELDBLURRADIUS;Flat-field blur radius @@ -1665,6 +1668,12 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index 7f810f71f..9b8eda038 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -748,6 +748,8 @@ !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -900,7 +902,7 @@ !MAIN_MSG_TOOMANYOPENEDITORS;Too many open editors.\nPlease close an editor to continue. !MAIN_MSG_WRITEFAILED;Failed to write\n"%1"\n\nMake sure that the folder exists and that you have write permission to it. !MAIN_TAB_ADVANCED;Advanced -!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-w +!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-a !MAIN_TAB_COLOR;Color !MAIN_TAB_COLOR_TOOLTIP;Shortcut: Alt-c !MAIN_TAB_DETAIL;Detail @@ -983,6 +985,7 @@ !PARTIALPASTE_EVERYTHING;Everything !PARTIALPASTE_EXIFCHANGES;Exif !PARTIALPASTE_EXPOSURE;Exposure +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PARTIALPASTE_FILMSIMULATION;Film simulation !PARTIALPASTE_FLATFIELDAUTOSELECT;Flat-field auto-selection !PARTIALPASTE_FLATFIELDBLURRADIUS;Flat-field blur radius @@ -1636,6 +1639,12 @@ !TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/Espanol b/rtdata/languages/Espanol index 15a4d81f5..1e3b84371 100644 --- a/rtdata/languages/Espanol +++ b/rtdata/languages/Espanol @@ -954,7 +954,7 @@ MAIN_MSG_SETPATHFIRST;Para poder usar esta función, primero tiene que establece MAIN_MSG_TOOMANYOPENEDITORS;Demasiados editores abiertos.\nPor favor cierre un editor para continuar. MAIN_MSG_WRITEFAILED;Falla al escribir\n\n"%1"\n\nAsegurese de que el folder exista y que usted tenga permiso de escritura sobre él. MAIN_TAB_ADVANCED;Avanzado -MAIN_TAB_ADVANCED_TOOLTIP;Tecla de Atajo: Alt-w +MAIN_TAB_ADVANCED_TOOLTIP;Tecla de Atajo: Alt-a MAIN_TAB_COLOR;Color MAIN_TAB_COLOR_TOOLTIP;Tecla de Atajo: Alt-C MAIN_TAB_DETAIL;Detalle @@ -2321,10 +2321,13 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nTecla de Atajo: - !FILEBROWSER_POPUPREMOVE;Delete permanently !FILEBROWSER_POPUPREMOVEINCLPROC;Delete permanently, including queue-processed version !FILEBROWSER_SHOWNOTTRASHHINT;Show only images not in trash. +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_SHARPENING_BLUR;Sharpening - Blur radius !MAIN_FRAME_PLACES_DEL;Remove !MAIN_TAB_FAVORITES;Favorites !MAIN_TAB_FAVORITES_TOOLTIP;Shortcut: Alt-u +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PREFERENCES_APPEARANCE_PSEUDOHIDPI;Pseudo-HiDPI mode !PREFERENCES_CHUNKSIZES;Tiles per thread !PREFERENCES_CHUNKSIZE_RAW_AMAZE;AMaZE demosaic @@ -2342,6 +2345,12 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nTecla de Atajo: - !PROGRESSBAR_RAWCACORR;Raw CA correction... !QUEUE_LOCATION_TITLE;Output Location !TP_CROP_PPI;PPI +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected !TP_LENSPROFILE_MODE_HEADER;Lens Profile diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index d7141f8b2..082cff1f1 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -889,7 +889,7 @@ MAIN_MSG_SETPATHFIRST;Vous devez d'abord choisir un dossier cible dans Préfére MAIN_MSG_TOOMANYOPENEDITORS;Too many open editors.\nPlease close an editor to continue. MAIN_MSG_WRITEFAILED;Échec de l'enregistrement du fichier\n\n"%1"\n\nAssurez-vous que le dossier existe et qu'il est permis d'y écrire. MAIN_TAB_ADVANCED;Avancé -MAIN_TAB_ADVANCED_TOOLTIP;Raccourci: Alt-w +MAIN_TAB_ADVANCED_TOOLTIP;Raccourci: Alt-a MAIN_TAB_COLOR;Couleur MAIN_TAB_COLOR_TOOLTIP;Raccourci:Alt-c MAIN_TAB_DETAIL;Détail @@ -2266,7 +2266,10 @@ ZOOMPANEL_ZOOMOUT;Zoom Arrière\nRaccourci: - !FILEBROWSER_POPUPREMOVE;Delete permanently !FILEBROWSER_POPUPREMOVEINCLPROC;Delete permanently, including queue-processed version !FILEBROWSER_SHOWNOTTRASHHINT;Show only images not in trash. +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !MAIN_FRAME_PLACES_DEL;Remove +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PROGRESSBAR_DECODING;Decoding... !PROGRESSBAR_GREENEQUIL;Green equilibration... !PROGRESSBAR_HLREC;Highlight reconstruction... @@ -2275,6 +2278,12 @@ ZOOMPANEL_ZOOMOUT;Zoom Arrière\nRaccourci: - !PROGRESSBAR_RAWCACORR;Raw CA correction... !QUEUE_LOCATION_TITLE;Output Location !TP_CROP_PPI;PPI +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected !TP_LENSPROFILE_MODE_HEADER;Lens Profile diff --git a/rtdata/languages/Italiano b/rtdata/languages/Italiano index 6d44a132f..f11423d7a 100644 --- a/rtdata/languages/Italiano +++ b/rtdata/languages/Italiano @@ -1539,6 +1539,8 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1638,7 +1640,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !MAIN_FRAME_PLACES_DEL;Remove !MAIN_MSG_TOOMANYOPENEDITORS;Too many open editors.\nPlease close an editor to continue. !MAIN_TAB_ADVANCED;Advanced -!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-w +!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-a !MAIN_TAB_FAVORITES;Favorites !MAIN_TAB_FAVORITES_TOOLTIP;Shortcut: Alt-u !MAIN_TAB_INSPECT; Inspect @@ -1652,6 +1654,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !PARTIALPASTE_COLORTONING;Color toning !PARTIALPASTE_DEHAZE;Haze removal !PARTIALPASTE_EQUALIZER;Wavelet levels +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PARTIALPASTE_FILMSIMULATION;Film simulation !PARTIALPASTE_FLATFIELDCLIPCONTROL;Flat-field clip control !PARTIALPASTE_LOCALCONTRAST;Local contrast @@ -1903,6 +1906,12 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/Japanese b/rtdata/languages/Japanese index 2cec023e5..16dafb297 100644 --- a/rtdata/languages/Japanese +++ b/rtdata/languages/Japanese @@ -152,8 +152,12 @@ FILEBROWSER_COLORLABEL_TOOLTIP;カラー・ラベル\n\nドロップダウン・ FILEBROWSER_COPYPROFILE;プロファイルをコピー FILEBROWSER_CURRENT_NAME;現在の名前: FILEBROWSER_DARKFRAME;ダークフレーム +FILEBROWSER_DELETEDIALOG_ALL;ゴミ箱の中にある%1枚のファイル全てを完全に削除しますか? FILEBROWSER_DELETEDIALOG_HEADER;ファイル削除確認 +FILEBROWSER_DELETEDIALOG_SELECTED;選択した%1枚のファイルを完全に削除しますか? +FILEBROWSER_DELETEDIALOG_SELECTEDINCLPROC;キュー処理に保持されているファイルを含め、選択した%1枚のファイルを完全に削除しますか? FILEBROWSER_EMPTYTRASH;ゴミ箱を空にする +FILEBROWSER_EMPTYTRASHHINT;ゴミ箱の中のファイルを全て完全に 削除します FILEBROWSER_EXTPROGMENU;..で開く FILEBROWSER_FLATFIELD;フラットフィールド FILEBROWSER_MOVETODARKFDIR;ダークフレーム・ディレクトリに移動 @@ -187,6 +191,8 @@ FILEBROWSER_POPUPRANK2;ランク 2 ** FILEBROWSER_POPUPRANK3;ランク 3 *** FILEBROWSER_POPUPRANK4;ランク 4 **** FILEBROWSER_POPUPRANK5;ランク 5 ***** +FILEBROWSER_POPUPREMOVE;完全に削除 +FILEBROWSER_POPUPREMOVEINCLPROC;キュー処理に保持されているファイルを含めて完全に削除 FILEBROWSER_POPUPRENAME;名前変更 FILEBROWSER_POPUPSELECTALL;全選択 FILEBROWSER_POPUPTRASH;ゴミ箱へ移動 @@ -213,6 +219,7 @@ FILEBROWSER_SHOWDIRHINT;全ての絞り込みをクリア\nショートカット FILEBROWSER_SHOWEDITEDHINT;編集済み画像を表示\nショートカット: 7 FILEBROWSER_SHOWEDITEDNOTHINT;未編集画像を表示\nショートカット: 6 FILEBROWSER_SHOWEXIFINFO;EXIF情報を表示\nショートカット: i\n\nシングル・エディタ・タブのショートカット: Alt-i +FILEBROWSER_SHOWNOTTRASHHINT;ゴミ箱の中にある画像だけを表示 FILEBROWSER_SHOWORIGINALHINT;元画像だけを表示\n\nファイル名は同じだが拡張子が異なる画像がある場合は、環境設定の中のファイルブラウザタブにある拡張子リストの上位に位置する拡張子を持った画像を元画像とする。 FILEBROWSER_SHOWRANK1HINT;1つ星ランクを表示\nショートカット: 1 FILEBROWSER_SHOWRANK2HINT;2つ星ランクを表示\nショートカット: 2 @@ -771,6 +778,8 @@ HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;霞除去 - 深度マップの表示 HISTORY_MSG_DEHAZE_STRENGTH;霞除去 - 強さ HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;デュアルデモザイク - 自動しきい値 HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - コントラストのしきい値 +HISTORY_MSG_FILMNEGATIVE_ENABLED;ネガフィルム +HISTORY_MSG_FILMNEGATIVE_VALUES;ネガフィルムの値 HISTORY_MSG_HISTMATCHING;トーンカーブの自動調節 HISTORY_MSG_ICM_OUTPUT_PRIMARIES;出力 - プライマリ HISTORY_MSG_ICM_OUTPUT_TEMP;出力 - ICC-v4 光源 D @@ -924,7 +933,7 @@ MAIN_MSG_SETPATHFIRST;この関数を使用するには、最初に環境設定 MAIN_MSG_TOOMANYOPENEDITORS;編集画面が多すぎます\n操作を続けるには何れかの画面を閉じてください MAIN_MSG_WRITEFAILED;書き込みに失敗しました\n\n"%1"\n\nフォルダが在るか書き込み権限を持っているか確認してください MAIN_TAB_ADVANCED;高度な機能 -MAIN_TAB_ADVANCED_TOOLTIP;ショートカット: Alt-w +MAIN_TAB_ADVANCED_TOOLTIP;ショートカット: Alt-a MAIN_TAB_COLOR;カラー MAIN_TAB_COLOR_TOOLTIP;ショートカット: Alt-c MAIN_TAB_DETAIL;CbDL @@ -1007,6 +1016,7 @@ PARTIALPASTE_EQUALIZER;ウェーブレット PARTIALPASTE_EVERYTHING;すべて PARTIALPASTE_EXIFCHANGES;exifデータを変える PARTIALPASTE_EXPOSURE;露光量 +PARTIALPASTE_FILMNEGATIVE;ネガフィルム PARTIALPASTE_FILMSIMULATION;フィルムシミュレーション PARTIALPASTE_FLATFIELDAUTOSELECT;フラットフィールド 自動選択 PARTIALPASTE_FLATFIELDBLURRADIUS;フラットフィールド ぼかし半径 @@ -1065,6 +1075,7 @@ PREFERENCES_APPEARANCE_COLORPICKERFONT;カラーピッカーのフォント PREFERENCES_APPEARANCE_CROPMASKCOLOR;切り抜きのマスクカラー PREFERENCES_APPEARANCE_MAINFONT;メインフォント PREFERENCES_APPEARANCE_NAVGUIDECOLOR;ナビゲーターのガイドカラー +PREFERENCES_APPEARANCE_PSEUDOHIDPI;擬似HiDPIモード PREFERENCES_APPEARANCE_THEME;テーマ PREFERENCES_APPLNEXTSTARTUP;要再起動 PREFERENCES_AUTOMONPROFILE;OSのメインモニター・プロファイルを使用 @@ -1284,6 +1295,7 @@ QUEUE_FORMAT_TITLE;ファイル形式 QUEUE_LOCATION_FOLDER;フォルダに保存 QUEUE_LOCATION_TEMPLATE;テンプレートを使う QUEUE_LOCATION_TEMPLATE_TOOLTIP;次の書式文字を使用することができます:\n%f, %d1, %d2, ..., %p1, %p2, ...%r\n\nこれらの書式文字は画像パス名のそれぞれ別々の部分、画像の属性を参照します\n\n例えば、次の画像を処理中の場合は:\n\n/home/tom/photos/2010-10-31/dsc0042.nef\n書式文字の意味するものは:\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tom/photos/2010-10-31/\n%p2 = /home/tom/photos/\n%p3 = /home/tom/\n%p4 = /home/\n\n%rは写真のランクに置き換えられます。評価なしは%rは'0 'に置換されます。画像がごみ箱にある場合、%rは'X'に置換されます\n\n元画像と同じ場所に出力したい場合はこのように書きます:\n%p1/%f\n\n処理画像のディレクトリ下 "converted" という名前のディレクトリに出力画像を保存したい場合このように書きます:\n%p1/converted/%f\n\n"/home/tom/photos/converted/2010-10-31" という名前のディレクトリに出力画像を保存したい場合はこのように書きます:\n%p2/converted/%d1/%f +QUEUE_LOCATION_TITLE;出力の場所 QUEUE_STARTSTOP_TOOLTIP;キューにある画像の現像を始める、或いは中止する\n\nショートカット: Ctrl+s SAMPLEFORMAT_0;データ形式不明 SAMPLEFORMAT_1;符号なし8ビット @@ -1658,6 +1670,12 @@ TP_EXPOSURE_TCMODE_STANDARD;標準 TP_EXPOSURE_TCMODE_WEIGHTEDSTD;加重平均 TP_EXPOS_BLACKPOINT_LABEL;raw ブラック・ポイント TP_EXPOS_WHITEPOINT_LABEL;raw ホワイト・ポイント +TP_FILMNEGATIVE_BLUE;ブルーの比率 +TP_FILMNEGATIVE_GREEN;参考指数(コントラスト) +TP_FILMNEGATIVE_GUESS_TOOLTIP;画像の中でニュートラルな参考ポイントを2点選んで指数を計算します;白い(明るいグレー)1点と黒い(暗いグレー)1点を選びます。順番は関係ありません。2つ目のポイントが選択されると指数が更新されます。 +TP_FILMNEGATIVE_LABEL;ネガフィルム +TP_FILMNEGATIVE_PICK;白と黒のポイントをピックアップする +TP_FILMNEGATIVE_RED;レッドの比率 TP_FILMSIMULATION_LABEL;フィルムシミュレーション TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapeeはフィルムシミュレーション機能に使う画像をHald CLUTフォルダーの中から探すよう設計されています(プログラムに組み込むにはフォルダーが大き過ぎるため)。\n変更するには、環境設定 > 画像処理 > フィルムシミュレーションと進み\nどのフォルダーが使われているか確認します。機能を利用する場合は、Hald CLUTだけが入っているフォルダーを指定するか、 この機能を使わない場合はそのフォルダーを空にしておきます。\n\n詳しくはRawPediaを参照して下さい。\n\nフィルム画像のスキャンを止めますか? TP_FILMSIMULATION_STRENGTH;強さ @@ -2301,16 +2319,3 @@ ZOOMPANEL_ZOOMFITSCREEN;画像全体を画面に合わせる\nショートカッ ZOOMPANEL_ZOOMIN;ズームイン\nショートカット: + ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - -!!!!!!!!!!!!!!!!!!!!!!!!! -! Untranslated keys follow; remove the ! prefix after an entry is translated. -!!!!!!!!!!!!!!!!!!!!!!!!! - -!FILEBROWSER_DELETEDIALOG_ALL;Are you sure you want to permanently delete all %1 files in trash? -!FILEBROWSER_DELETEDIALOG_SELECTED;Are you sure you want to permanently delete the selected %1 files? -!FILEBROWSER_DELETEDIALOG_SELECTEDINCLPROC;Are you sure you want to permanently delete the selected %1 files, including a queue-processed version? -!FILEBROWSER_EMPTYTRASHHINT;Permanently delete all files in trash. -!FILEBROWSER_POPUPREMOVE;Delete permanently -!FILEBROWSER_POPUPREMOVEINCLPROC;Delete permanently, including queue-processed version -!FILEBROWSER_SHOWNOTTRASHHINT;Show only images not in trash. -!PREFERENCES_APPEARANCE_PSEUDOHIDPI;Pseudo-HiDPI mode -!QUEUE_LOCATION_TITLE;Output Location diff --git a/rtdata/languages/LICENSE b/rtdata/languages/LICENSE index fbc14b67e..b269339a6 100755 --- a/rtdata/languages/LICENSE +++ b/rtdata/languages/LICENSE @@ -13,6 +13,6 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with RawTherapee. If not, see . +# along with RawTherapee. If not, see . # diff --git a/rtdata/languages/Magyar b/rtdata/languages/Magyar index 6286ba63c..5879bf130 100644 --- a/rtdata/languages/Magyar +++ b/rtdata/languages/Magyar @@ -1248,6 +1248,8 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1355,7 +1357,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !MAIN_MSG_TOOMANYOPENEDITORS;Too many open editors.\nPlease close an editor to continue. !MAIN_MSG_WRITEFAILED;Failed to write\n"%1"\n\nMake sure that the folder exists and that you have write permission to it. !MAIN_TAB_ADVANCED;Advanced -!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-w +!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-a !MAIN_TAB_FAVORITES;Favorites !MAIN_TAB_FAVORITES_TOOLTIP;Shortcut: Alt-u !MAIN_TAB_INSPECT; Inspect @@ -1385,6 +1387,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !PARTIALPASTE_COLORTONING;Color toning !PARTIALPASTE_DEHAZE;Haze removal !PARTIALPASTE_EQUALIZER;Wavelet levels +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PARTIALPASTE_FILMSIMULATION;Film simulation !PARTIALPASTE_FLATFIELDCLIPCONTROL;Flat-field clip control !PARTIALPASTE_GRADIENT;Graduated filter @@ -1816,6 +1819,12 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/Nederlands b/rtdata/languages/Nederlands index 7317038a3..d39173a52 100644 --- a/rtdata/languages/Nederlands +++ b/rtdata/languages/Nederlands @@ -2036,6 +2036,8 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -2109,7 +2111,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !MAIN_FRAME_PLACES_DEL;Remove !MAIN_MSG_TOOMANYOPENEDITORS;Too many open editors.\nPlease close an editor to continue. !MAIN_TAB_ADVANCED;Advanced -!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-w +!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-a !MAIN_TAB_FAVORITES;Favorites !MAIN_TAB_FAVORITES_TOOLTIP;Shortcut: Alt-u !MAIN_TOOLTIP_BACKCOLOR3;Background color of the preview: middle grey\nShortcut: 9 @@ -2119,6 +2121,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !OPTIONS_DEFRAW_MISSING;The default profile for raw photos could not be found or is not set.\n\nPlease check your profiles' directory, it may be missing or damaged.\n\n"%1" will be used instead. !PARTIALPASTE_ADVANCEDGROUP;Advanced Settings !PARTIALPASTE_DEHAZE;Haze removal +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PARTIALPASTE_LOCALCONTRAST;Local contrast !PARTIALPASTE_METADATA;Metadata mode !PARTIALPASTE_PREPROCESS_PDAFLINESFILTER;PDAF lines filter @@ -2230,6 +2233,12 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !TP_EXPOSURE_CLAMPOOG;Clip out-of-gamut colors !TP_EXPOSURE_HISTMATCHING;Auto-Matched Tone Curve !TP_EXPOSURE_HISTMATCHING_TOOLTIP;Automatically adjust sliders and curves (except exposure compensation) to match the look of the embedded JPEG thumbnail. +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_ICM_WORKING_TRC;Tone response curve: !TP_ICM_WORKING_TRC_CUSTOM;Custom !TP_ICM_WORKING_TRC_GAMMA;Gamma diff --git a/rtdata/languages/Polish b/rtdata/languages/Polish index d1e27f0dc..a631353c3 100644 --- a/rtdata/languages/Polish +++ b/rtdata/languages/Polish @@ -1621,6 +1621,8 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1720,7 +1722,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !MAIN_FRAME_PLACES_DEL;Remove !MAIN_MSG_TOOMANYOPENEDITORS;Too many open editors.\nPlease close an editor to continue. !MAIN_TAB_ADVANCED;Advanced -!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-w +!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-a !MAIN_TAB_FAVORITES;Favorites !MAIN_TAB_FAVORITES_TOOLTIP;Shortcut: Alt-u !MAIN_TAB_INSPECT; Inspect @@ -1733,6 +1735,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !PARTIALPASTE_ADVANCEDGROUP;Advanced Settings !PARTIALPASTE_DEHAZE;Haze removal !PARTIALPASTE_EQUALIZER;Wavelet levels +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PARTIALPASTE_LOCALCONTRAST;Local contrast !PARTIALPASTE_METADATA;Metadata mode !PARTIALPASTE_PREPROCESS_PDAFLINESFILTER;PDAF lines filter @@ -1929,6 +1932,12 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_EXPOSURE_HISTMATCHING_TOOLTIP;Automatically adjust sliders and curves (except exposure compensation) to match the look of the embedded JPEG thumbnail. !TP_EXPOSURE_TCMODE_LUMINANCE;Luminance !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_ICM_APPLYBASELINEEXPOSUREOFFSET;Baseline exposure !TP_ICM_APPLYBASELINEEXPOSUREOFFSET_TOOLTIP;Employ the embedded DCP baseline exposure offset. The setting is only available if the selected DCP has one. diff --git a/rtdata/languages/Portugues b/rtdata/languages/Portugues index 7e5713093..766b14e0b 100644 --- a/rtdata/languages/Portugues +++ b/rtdata/languages/Portugues @@ -889,7 +889,7 @@ MAIN_MSG_SETPATHFIRST;Para usar esta função, primeiro tem de configurar um cam MAIN_MSG_TOOMANYOPENEDITORS;Existem demasiados editores abertos.\nPor favor, feche um editor para continuar. MAIN_MSG_WRITEFAILED;Falha ao gravar\n"%1"\n\nVerifique se a pasta existe e se tem permissão para gravar nela. MAIN_TAB_ADVANCED;Avançado -MAIN_TAB_ADVANCED_TOOLTIP;Atalho: Alt-w +MAIN_TAB_ADVANCED_TOOLTIP;Atalho: Alt-a MAIN_TAB_COLOR;Cor MAIN_TAB_COLOR_TOOLTIP;Atalho: Alt-c MAIN_TAB_DETAIL;Detalhe @@ -2264,7 +2264,10 @@ ZOOMPANEL_ZOOMOUT;Afastar\nAtalho: - !FILEBROWSER_POPUPREMOVE;Delete permanently !FILEBROWSER_POPUPREMOVEINCLPROC;Delete permanently, including queue-processed version !FILEBROWSER_SHOWNOTTRASHHINT;Show only images not in trash. +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !MAIN_FRAME_PLACES_DEL;Remove +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PREFERENCES_APPEARANCE_PSEUDOHIDPI;Pseudo-HiDPI mode !PROGRESSBAR_DECODING;Decoding... !PROGRESSBAR_GREENEQUIL;Green equilibration... @@ -2274,6 +2277,12 @@ ZOOMPANEL_ZOOMOUT;Afastar\nAtalho: - !PROGRESSBAR_RAWCACORR;Raw CA correction... !QUEUE_LOCATION_TITLE;Output Location !TP_CROP_PPI;PPI +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected !TP_LENSPROFILE_MODE_HEADER;Lens Profile diff --git a/rtdata/languages/Portugues (Brasil) b/rtdata/languages/Portugues (Brasil) index beffbb9a8..aef5fcde9 100644 --- a/rtdata/languages/Portugues (Brasil) +++ b/rtdata/languages/Portugues (Brasil) @@ -888,7 +888,7 @@ MAIN_MSG_SETPATHFIRST;Para usar esta função primeiro defina um objetivo em Pre MAIN_MSG_TOOMANYOPENEDITORS;Muitos editores abertos.\nPor favor, feche um editor para continuar. MAIN_MSG_WRITEFAILED;Falha ao escrever\n"%1"\n\nVerifique se a pasta existe e se tens permissão para gravar nela. MAIN_TAB_ADVANCED;Avançado -MAIN_TAB_ADVANCED_TOOLTIP;Atalho: Alt-w +MAIN_TAB_ADVANCED_TOOLTIP;Atalho: Alt-a MAIN_TAB_COLOR;Cor MAIN_TAB_COLOR_TOOLTIP;Atalho: Alt-c MAIN_TAB_DETAIL;Detalhe @@ -2258,7 +2258,10 @@ ZOOMPANEL_ZOOMOUT;Menos Zoom\nAtalho: - !FILEBROWSER_SHOWNOTTRASHHINT;Show only images not in trash. !HISTORY_MSG_COLORTONING_LABREGION_OFFSET;CT - region offset !HISTORY_MSG_COLORTONING_LABREGION_POWER;CT - region power +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !MAIN_FRAME_PLACES_DEL;Remove +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PREFERENCES_APPEARANCE_PSEUDOHIDPI;Pseudo-HiDPI mode !PREFERENCES_CACHECLEAR_SAFETY;Only files in the cache are cleared. Processing profiles stored alongside the source images are not touched. !PROGRESSBAR_DECODING;Decoding... @@ -2271,6 +2274,12 @@ ZOOMPANEL_ZOOMOUT;Menos Zoom\nAtalho: - !TP_COLORTONING_LABREGION_OFFSET;Offset !TP_COLORTONING_LABREGION_POWER;Power !TP_CROP_PPI;PPI +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected !TP_LENSPROFILE_LENS_WARNING;Warning: the crop factor used for lens profiling is larger than the crop factor of the camera, the results might be wrong. diff --git a/rtdata/languages/Russian b/rtdata/languages/Russian index 870895dd7..79c6bebfc 100644 --- a/rtdata/languages/Russian +++ b/rtdata/languages/Russian @@ -589,7 +589,7 @@ MAIN_MSG_QOVERWRITE;Вы хотите перезаписать его? MAIN_MSG_SETPATHFIRST;Прежде необходимо установить целевой каталог в настройках\nчтоб использовать эту функцию! MAIN_MSG_WRITEFAILED;Не удалось записать\n\n"%1".\n\nУбедитесь, что каталог существует и у вас есть права на запись в него. MAIN_TAB_ADVANCED;Дополнительные -MAIN_TAB_ADVANCED_TOOLTIP;Горячая клавиша: Alt-W +MAIN_TAB_ADVANCED_TOOLTIP;Горячая клавиша: Alt-a MAIN_TAB_COLOR;Цвет MAIN_TAB_COLOR_TOOLTIP;Горячая клавиша: Alt-C MAIN_TAB_DETAIL;Детализация @@ -1706,6 +1706,8 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !HISTORY_MSG_COLORTONING_LABREGION_SLOPE;CT - region slope !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D !HISTORY_MSG_ICM_OUTPUT_TYPE;Output - Type @@ -1775,6 +1777,7 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !PARTIALPASTE_COLORTONING;Color toning !PARTIALPASTE_DEHAZE;Haze removal !PARTIALPASTE_EQUALIZER;Wavelet levels +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PARTIALPASTE_FILMSIMULATION;Film simulation !PARTIALPASTE_FLATFIELDCLIPCONTROL;Flat-field clip control !PARTIALPASTE_PREPROCESS_PDAFLINESFILTER;PDAF lines filter @@ -1974,6 +1977,12 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !TP_DISTORTION_AUTO_TIP;Automatically corrects lens distortion in raw files by matching it against the embedded JPEG image if one exists and has had its lens disortion auto-corrected by the camera. !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FLATFIELD_CLIPCONTROL;Clip control !TP_FLATFIELD_CLIPCONTROL_TOOLTIP;Clip control avoids clipped highlights caused by applying the flat field. If there are already clipped highlights before applying the flat field, clip control can lead to color cast. diff --git a/rtdata/languages/Serbian (Cyrilic Characters) b/rtdata/languages/Serbian (Cyrilic Characters) index edcf1d2d6..2b98cfe2a 100644 --- a/rtdata/languages/Serbian (Cyrilic Characters) +++ b/rtdata/languages/Serbian (Cyrilic Characters) @@ -1514,6 +1514,8 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1612,7 +1614,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !MAIN_FRAME_PLACES_DEL;Remove !MAIN_MSG_TOOMANYOPENEDITORS;Too many open editors.\nPlease close an editor to continue. !MAIN_TAB_ADVANCED;Advanced -!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-w +!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-a !MAIN_TAB_FAVORITES;Favorites !MAIN_TAB_FAVORITES_TOOLTIP;Shortcut: Alt-u !MAIN_TAB_INSPECT; Inspect @@ -1636,6 +1638,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !PARTIALPASTE_COLORTONING;Color toning !PARTIALPASTE_DEHAZE;Haze removal !PARTIALPASTE_EQUALIZER;Wavelet levels +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PARTIALPASTE_FILMSIMULATION;Film simulation !PARTIALPASTE_FLATFIELDCLIPCONTROL;Flat-field clip control !PARTIALPASTE_LOCALCONTRAST;Local contrast @@ -1902,6 +1905,12 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/Swedish b/rtdata/languages/Swedish index 2263584cd..220339a45 100644 --- a/rtdata/languages/Swedish +++ b/rtdata/languages/Swedish @@ -1863,6 +1863,8 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1961,7 +1963,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !MAIN_FRAME_PLACES_DEL;Remove !MAIN_MSG_TOOMANYOPENEDITORS;Too many open editors.\nPlease close an editor to continue. !MAIN_TAB_ADVANCED;Advanced -!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-w +!MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-a !MAIN_TAB_FAVORITES;Favorites !MAIN_TAB_FAVORITES_TOOLTIP;Shortcut: Alt-u !MAIN_TOOLTIP_BACKCOLOR3;Background color of the preview: middle grey\nShortcut: 9 @@ -1972,6 +1974,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !PARTIALPASTE_ADVANCEDGROUP;Advanced Settings !PARTIALPASTE_COLORTONING;Color toning !PARTIALPASTE_DEHAZE;Haze removal +!PARTIALPASTE_FILMNEGATIVE;Film Negative !PARTIALPASTE_FLATFIELDCLIPCONTROL;Flat-field clip control !PARTIALPASTE_LOCALCONTRAST;Local contrast !PARTIALPASTE_METADATA;Metadata mode @@ -2117,6 +2120,12 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !TP_EXPOSURE_CLAMPOOG;Clip out-of-gamut colors !TP_EXPOSURE_HISTMATCHING;Auto-Matched Tone Curve !TP_EXPOSURE_HISTMATCHING_TOOLTIP;Automatically adjust sliders and curves (except exposure compensation) to match the look of the embedded JPEG thumbnail. +!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red ratio !TP_FLATFIELD_CLIPCONTROL;Clip control !TP_FLATFIELD_CLIPCONTROL_TOOLTIP;Clip control avoids clipped highlights caused by applying the flat field. If there are already clipped highlights before applying the flat field, clip control can lead to color cast. !TP_ICM_APPLYBASELINEEXPOSUREOFFSET_TOOLTIP;Employ the embedded DCP baseline exposure offset. The setting is only available if the selected DCP has one. diff --git a/rtdata/languages/default b/rtdata/languages/default index 31e704d7d..c8c223a9a 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -726,6 +726,7 @@ HISTORY_MSG_490;DRC - Amount HISTORY_MSG_491;White Balance HISTORY_MSG_492;RGB Curves HISTORY_MSG_493;L*a*b* Adjustments +HISTORY_MSG_494;Capture Sharpening HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction HISTORY_MSG_COLORTONING_LABREGION_AB;CT - Color correction @@ -743,10 +744,13 @@ HISTORY_MSG_COLORTONING_LABREGION_SHOWMASK;CT - region show mask HISTORY_MSG_COLORTONING_LABREGION_SLOPE;CT - region slope HISTORY_MSG_DEHAZE_DEPTH;Dehaze - Depth HISTORY_MSG_DEHAZE_ENABLED;Haze Removal +HISTORY_MSG_DEHAZE_LUMINANCE;Dehaze - Luminance only HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;Dehaze - Show depth map HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values HISTORY_MSG_HISTMATCHING;Auto-matched tone curve HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -761,6 +765,13 @@ HISTORY_MSG_LOCALCONTRAST_LIGHTNESS;Local Contrast - Lightness HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius HISTORY_MSG_METADATA_MODE;Metadata copy mode HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +HISTORY_MSG_PDSHARPEN_CONTRAST;CAS - Contrast threshold +HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CAS - Auto threshold +HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CAS - Auto radius +HISTORY_MSG_PDSHARPEN_GAMMA;CAS - Gamma +HISTORY_MSG_PDSHARPEN_ITERATIONS;CAS - Iterations +HISTORY_MSG_PDSHARPEN_RADIUS;CAS - Radius +HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CAS - Corner radius boost HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter @@ -771,6 +782,7 @@ HISTORY_MSG_RAW_BORDER;Raw border HISTORY_MSG_RESIZE_ALLOWUPSCALING;Resize - Allow upscaling HISTORY_MSG_SHARPENING_BLUR;Sharpening - Blur radius HISTORY_MSG_SHARPENING_CONTRAST;Sharpening - Contrast threshold +HISTORY_MSG_SHARPENING_GAMMA;Sharpening - Gamma HISTORY_MSG_SH_COLORSPACE;S/H - Colorspace HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength @@ -899,7 +911,7 @@ MAIN_MSG_SETPATHFIRST;You first have to set a target path in Preferences in orde MAIN_MSG_TOOMANYOPENEDITORS;Too many open editors.\nPlease close an editor to continue. MAIN_MSG_WRITEFAILED;Failed to write\n"%1"\n\nMake sure that the folder exists and that you have write permission to it. MAIN_TAB_ADVANCED;Advanced -MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-w +MAIN_TAB_ADVANCED_TOOLTIP;Shortcut: Alt-a MAIN_TAB_COLOR;Color MAIN_TAB_COLOR_TOOLTIP;Shortcut: Alt-c MAIN_TAB_DETAIL;Detail @@ -982,6 +994,7 @@ PARTIALPASTE_EQUALIZER;Wavelet levels PARTIALPASTE_EVERYTHING;Everything PARTIALPASTE_EXIFCHANGES;Exif PARTIALPASTE_EXPOSURE;Exposure +PARTIALPASTE_FILMNEGATIVE;Film Negative PARTIALPASTE_FILMSIMULATION;Film simulation PARTIALPASTE_FLATFIELDAUTOSELECT;Flat-field auto-selection PARTIALPASTE_FLATFIELDBLURRADIUS;Flat-field blur radius @@ -1527,6 +1540,7 @@ TP_DEFRINGE_RADIUS;Radius TP_DEFRINGE_THRESHOLD;Threshold TP_DEHAZE_DEPTH;Depth TP_DEHAZE_LABEL;Haze Removal +TP_DEHAZE_LUMINANCE;Luminance only TP_DEHAZE_SHOW_DEPTH_MAP;Show depth map TP_DEHAZE_STRENGTH;Strength TP_DIRPYRDENOISE_CHROMINANCE_AMZ;Auto multi-zones @@ -1635,6 +1649,12 @@ TP_EXPOSURE_TCMODE_STANDARD;Standard TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +TP_FILMNEGATIVE_BLUE;Blue ratio +TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) +TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked. +TP_FILMNEGATIVE_LABEL;Film Negative +TP_FILMNEGATIVE_PICK;Pick white and black spots +TP_FILMNEGATIVE_RED;Red ratio TP_FILMSIMULATION_LABEL;Film Simulation TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? TP_FILMSIMULATION_STRENGTH;Strength @@ -1783,6 +1803,7 @@ TP_PCVIGNETTE_ROUNDNESS;Roundness TP_PCVIGNETTE_ROUNDNESS_TOOLTIP;Roundness:\n0 = rectangle,\n50 = fitted ellipse,\n100 = circle. TP_PCVIGNETTE_STRENGTH;Strength TP_PCVIGNETTE_STRENGTH_TOOLTIP;Filter strength in stops (reached in corners). +TP_PDSHARPENING_LABEL;Capture Sharpening TP_PERSPECTIVE_HORIZONTAL;Horizontal TP_PERSPECTIVE_LABEL;Perspective TP_PERSPECTIVE_VERTICAL;Vertical @@ -2011,12 +2032,14 @@ TP_SHARPENING_BLUR;Blur radius TP_SHARPENING_CONTRAST;Contrast threshold TP_SHARPENING_EDRADIUS;Radius TP_SHARPENING_EDTOLERANCE;Edge tolerance +TP_SHARPENING_GAMMA;Gamma TP_SHARPENING_HALOCONTROL;Halo control TP_SHARPENING_HCAMOUNT;Amount TP_SHARPENING_LABEL;Sharpening TP_SHARPENING_METHOD;Method TP_SHARPENING_ONLYEDGES;Sharpen only edges TP_SHARPENING_RADIUS;Radius +TP_SHARPENING_RADIUS_BOOST;Corner radius boost TP_SHARPENING_RLD;RL Deconvolution TP_SHARPENING_RLD_AMOUNT;Amount TP_SHARPENING_RLD_DAMPING;Damping diff --git a/rtdata/profiles/Auto-Matched Curve - ISO Low.pp3 b/rtdata/profiles/Auto-Matched Curve - ISO Low.pp3 index 882c0130f..c94077b21 100644 --- a/rtdata/profiles/Auto-Matched Curve - ISO Low.pp3 +++ b/rtdata/profiles/Auto-Matched Curve - ISO Low.pp3 @@ -21,3 +21,6 @@ DCPIlluminant=0 [RAW] CA=true + +[PostDemosaicSharpening] +Enabled=true diff --git a/rtdata/profiles/Standard Film Curve - ISO Low.pp3 b/rtdata/profiles/Standard Film Curve - ISO Low.pp3 index c23b5b8a4..45fcca730 100644 --- a/rtdata/profiles/Standard Film Curve - ISO Low.pp3 +++ b/rtdata/profiles/Standard Film Curve - ISO Low.pp3 @@ -23,3 +23,6 @@ DCPIlluminant=0 [RAW] CA=true + +[PostDemosaicSharpening] +Enabled=true diff --git a/rtdata/rawtherapee.desktop.in b/rtdata/rawtherapee.desktop.in index 233a737b6..c6c675c4d 100644 --- a/rtdata/rawtherapee.desktop.in +++ b/rtdata/rawtherapee.desktop.in @@ -1,8 +1,8 @@ [Desktop Entry] Type=Application -Version=1.0 +Version=1.1 Name=RawTherapee -GenericName=Raw photo editor +GenericName=Raw Photo Editor GenericName[cs]=Editor raw obrázků GenericName[fr]=Éditeur d'images raw GenericName[pl]=Edytor zdjęć raw @@ -11,9 +11,10 @@ Comment[cs]=Program pro konverzi a zpracování digitálních raw fotografií Comment[fr]=Logiciel de conversion et de traitement de photos numériques de format raw (but de capteur) Comment[pl]=Zaawansowany program do wywoływania zdjęć typu raw Icon=rawtherapee +TryExec=rawtherapee Exec=rawtherapee %f Terminal=false MimeType=image/jpeg;image/png;image/tiff;image/x-adobe-dng;image/x-canon-cr2;image/x-canon-crf;image/x-canon-crw;image/x-fuji-raf;image/x-hasselblad-3fr;image/x-hasselblad-fff;image/x-jpg;image/x-kodak-dcr;image/x-kodak-k25;image/x-kodak-kdc;image/x-leaf-mos;image/x-leica-rwl;image/x-mamiya-mef;image/x-minolta-mrw;image/x-nikon-nef;image/x-nikon-nrw;image/x-olympus-orf;image/x-panasonic-raw;image/x-panasonic-rw2;image/x-pentax-pef;image/x-pentax-raw;image/x-phaseone-iiq;image/x-raw;image/x-rwz;image/x-samsung-srw;image/x-sigma-x3f;image/x-sony-arq;image/x-sony-arw;image/x-sony-sr2;image/x-sony-srf;image/x-tif; -Categories=Photography;Graphics;2DGraphics;RasterGraphics;GTK; -Keywords=raw;photography;develop;pp3;graphics; +Categories=Graphics;Photography;2DGraphics;RasterGraphics;GTK; +Keywords=raw;photo;photography;develop;pp3;graphics; StartupWMClass=rawtherapee diff --git a/rtdata/themes/RawTherapee-GTK3-20_.css b/rtdata/themes/RawTherapee-GTK3-20_.css index 45dec6e39..3f5072f48 100644 --- a/rtdata/themes/RawTherapee-GTK3-20_.css +++ b/rtdata/themes/RawTherapee-GTK3-20_.css @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with RawTherapee. If not, see . + along with RawTherapee. If not, see . */ /***************************/ diff --git a/rtdata/themes/RawTherapee-GTK3-_19.css b/rtdata/themes/RawTherapee-GTK3-_19.css index a796b60a1..58742e8ca 100644 --- a/rtdata/themes/RawTherapee-GTK3-_19.css +++ b/rtdata/themes/RawTherapee-GTK3-_19.css @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with RawTherapee. If not, see . + along with RawTherapee. If not, see . */ * { diff --git a/rtdata/themes/TooWaBlue - Bright-GTK3-20_.css b/rtdata/themes/TooWaBlue - Bright-GTK3-20_.css index d1bb4fdbc..19e2eb049 100644 --- a/rtdata/themes/TooWaBlue - Bright-GTK3-20_.css +++ b/rtdata/themes/TooWaBlue - Bright-GTK3-20_.css @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with RawTherapee. If not, see . + along with RawTherapee. If not, see . */ diff --git a/rtdata/themes/TooWaBlue - Dark-GTK3-20_.css b/rtdata/themes/TooWaBlue - Dark-GTK3-20_.css index 581549750..5875e2132 100644 --- a/rtdata/themes/TooWaBlue - Dark-GTK3-20_.css +++ b/rtdata/themes/TooWaBlue - Dark-GTK3-20_.css @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with RawTherapee. If not, see . + along with RawTherapee. If not, see . */ diff --git a/rtdata/themes/TooWaBlue-GTK3-20_.css b/rtdata/themes/TooWaBlue-GTK3-20_.css index 7b5089430..ce4bb8d28 100644 --- a/rtdata/themes/TooWaBlue-GTK3-20_.css +++ b/rtdata/themes/TooWaBlue-GTK3-20_.css @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with RawTherapee. If not, see . + along with RawTherapee. If not, see . */ /*** Change me *** rgb(red,green,blue) *** allowed values from 0 to 255 for each color ***/ diff --git a/rtdata/themes/TooWaBlue-GTK3-_19.css b/rtdata/themes/TooWaBlue-GTK3-_19.css index 530ae3d3a..31676ca8d 100644 --- a/rtdata/themes/TooWaBlue-GTK3-_19.css +++ b/rtdata/themes/TooWaBlue-GTK3-_19.css @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with RawTherapee. If not, see . + along with RawTherapee. If not, see . */ /*** Change me *** rgb(red,green,blue) *** allowed values from 0 to 255 for each color ***/ diff --git a/rtdata/themes/TooWaGrey - Average Surround-GTK3-20_.css b/rtdata/themes/TooWaGrey - Average Surround-GTK3-20_.css index 29ebd6c96..8f045e206 100644 --- a/rtdata/themes/TooWaGrey - Average Surround-GTK3-20_.css +++ b/rtdata/themes/TooWaGrey - Average Surround-GTK3-20_.css @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with RawTherapee. If not, see . + along with RawTherapee. If not, see . */ diff --git a/rtdata/themes/TooWaGrey - Bright-GTK3-20_.css b/rtdata/themes/TooWaGrey - Bright-GTK3-20_.css index 74dd5c7f0..579ca7a00 100644 --- a/rtdata/themes/TooWaGrey - Bright-GTK3-20_.css +++ b/rtdata/themes/TooWaGrey - Bright-GTK3-20_.css @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with RawTherapee. If not, see . + along with RawTherapee. If not, see . */ diff --git a/rtdata/themes/TooWaGrey - Dark-GTK3-20_.css b/rtdata/themes/TooWaGrey - Dark-GTK3-20_.css index 0f61e0935..8d6d05152 100644 --- a/rtdata/themes/TooWaGrey - Dark-GTK3-20_.css +++ b/rtdata/themes/TooWaGrey - Dark-GTK3-20_.css @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with RawTherapee. If not, see . + along with RawTherapee. If not, see . */ diff --git a/rtdata/themes/TooWaGrey-GTK3-20_.css b/rtdata/themes/TooWaGrey-GTK3-20_.css index f681ef374..0b29ed2e7 100644 --- a/rtdata/themes/TooWaGrey-GTK3-20_.css +++ b/rtdata/themes/TooWaGrey-GTK3-20_.css @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with RawTherapee. If not, see . + along with RawTherapee. If not, see . */ diff --git a/rtengine/CA_correct_RT.cc b/rtengine/CA_correct_RT.cc index bad95a4d8..a2d68402f 100644 --- a/rtengine/CA_correct_RT.cc +++ b/rtengine/CA_correct_RT.cc @@ -18,7 +18,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// @@ -106,6 +106,10 @@ bool LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* pfSolution) //end of linear equation solver } +namespace rtengine { + extern const Settings* settings; +} + using namespace std; using namespace rtengine; @@ -701,7 +705,9 @@ float* RawImageSource::CA_correct_RT( blockvar[dir][c] = blocksqave[dir][c] / blockdenom[dir][c] - SQR(blockave[dir][c] / blockdenom[dir][c]); } else { processpasstwo = false; - std::cout << "blockdenom vanishes" << std::endl; + if (settings->verbose) { + std::cout << "blockdenom vanishes" << std::endl; + } break; } } @@ -801,7 +807,9 @@ float* RawImageSource::CA_correct_RT( numpar = 4; if (numblox[1] < 10) { - std::cout << "numblox = " << numblox[1] << std::endl; + if (settings->verbose) { + std::cout << "numblox = " << numblox[1] << std::endl; + } processpasstwo = false; } } diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 92aec23b0..fa06de002 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -33,6 +33,7 @@ set(CAMCONSTSFILE "camconst.json") set(RTENGINESOURCEFILES badpixels.cc CA_correct_RT.cc + capturesharpening.cc EdgePreservingDecomposition.cc FTblockDN.cc PF_correct_RT.cc @@ -62,6 +63,8 @@ set(RTENGINESOURCEFILES eahd_demosaic.cc fast_demo.cc ffmanager.cc + filmnegativeproc.cc + filmnegativethumb.cc flatcurves.cc gauss.cc green_equil_RT.cc diff --git a/rtengine/EdgePreservingDecomposition.cc b/rtengine/EdgePreservingDecomposition.cc index 6bda5d437..85b7ce243 100644 --- a/rtengine/EdgePreservingDecomposition.cc +++ b/rtengine/EdgePreservingDecomposition.cc @@ -401,13 +401,10 @@ bool MultiDiagonalSymmetricMatrix::CreateIncompleteCholeskyFactorization(int Max //How many diagonals in the decomposition? MaxFillAbove++; //Conceptually, now "fill" includes an existing diagonal. Simpler in the math that follows. - int j, mic, fp; - mic = 1; - fp = 1; + int mic = 1; for(int ii = 1; ii < m; ii++) { - fp = rtengine::min(StartRows[ii] - StartRows[ii - 1], MaxFillAbove); //Guaranteed positive since StartRows must be created in increasing order. - mic = mic + fp; + mic += rtengine::min(StartRows[ii] - StartRows[ii - 1], MaxFillAbove); //Guaranteed positive since StartRows must be created in increasing order. } //Initialize the decomposition - setup memory, start rows, etc. @@ -421,7 +418,7 @@ bool MultiDiagonalSymmetricMatrix::CreateIncompleteCholeskyFactorization(int Max for(int ii = 1; ii < m; ii++) { //Set j to the number of diagonals to be created corresponding to a diagonal on this source matrix... - j = rtengine::min(StartRows[ii] - StartRows[ii - 1], MaxFillAbove); + int j = rtengine::min(StartRows[ii] - StartRows[ii - 1], MaxFillAbove); //...and create those diagonals. I want to take a moment to tell you about how much I love minimalistic loops: very much. while(j-- != 0) @@ -491,7 +488,7 @@ bool MultiDiagonalSymmetricMatrix::CreateIncompleteCholeskyFactorization(int Max findmap[j] = FindIndex( icStartRows[j]); } - for(j = 0; j < n; j++) { + for(int j = 0; j < n; j++) { //Calculate d for this column. d[j] = Diagonals[0][j]; @@ -557,12 +554,11 @@ void MultiDiagonalSymmetricMatrix::CholeskyBackSolve(float* RESTRICT x, float* R float* RESTRICT *d = IncompleteCholeskyFactorization->Diagonals; int* RESTRICT s = IncompleteCholeskyFactorization->StartRows; int M = IncompleteCholeskyFactorization->m, N = IncompleteCholeskyFactorization->n; - int i, j; if(M != DIAGONALSP1) { // can happen in theory - for(j = 0; j < N; j++) { + for(int j = 0; j < N; j++) { float sub = b[j]; // using local var to reduce memory writes, gave a big speedup - i = 1; + int i = 1; int c = j - s[i]; while(c >= 0) { @@ -574,9 +570,9 @@ void MultiDiagonalSymmetricMatrix::CholeskyBackSolve(float* RESTRICT x, float* R x[j] = sub; // only one memory-write per j } } else { // that's the case almost every time - for(j = 0; j <= s[M - 1]; j++) { + for(int j = 0; j <= s[M - 1]; j++) { float sub = b[j]; // using local var to reduce memory writes, gave a big speedup - i = 1; + int i = 1; int c = j - s[1]; while(c >= 0) { @@ -588,7 +584,7 @@ void MultiDiagonalSymmetricMatrix::CholeskyBackSolve(float* RESTRICT x, float* R x[j] = sub; // only one memory-write per j } - for(j = s[M - 1] + 1; j < N; j++) { + for(int j = s[M - 1] + 1; j < N; j++) { float sub = b[j]; // using local var to reduce memory writes, gave a big speedup for(int i = DIAGONALSP1 - 1; i > 0; i--) { // using a constant upperbound allows the compiler to unroll this loop (gives a good speedup) @@ -605,14 +601,15 @@ void MultiDiagonalSymmetricMatrix::CholeskyBackSolve(float* RESTRICT x, float* R #pragma omp parallel for #endif - for(j = 0; j < N; j++) { + for(int j = 0; j < N; j++) { x[j] = x[j] / d[0][j]; } if(M != DIAGONALSP1) { // can happen in theory + int j = N; while(j-- > 0) { float sub = x[j]; // using local var to reduce memory writes, gave a big speedup - i = 1; + int i = 1; int c = j + s[1]; while(c < N) { @@ -624,9 +621,9 @@ void MultiDiagonalSymmetricMatrix::CholeskyBackSolve(float* RESTRICT x, float* R x[j] = sub; // only one memory-write per j } } else { // that's the case almost every time - for(j = N - 1; j >= (N - 1) - s[M - 1]; j--) { + for(int j = N - 1; j >= (N - 1) - s[M - 1]; j--) { float sub = x[j]; // using local var to reduce memory writes, gave a big speedup - i = 1; + int i = 1; int c = j + s[1]; while(c < N) { @@ -638,7 +635,7 @@ void MultiDiagonalSymmetricMatrix::CholeskyBackSolve(float* RESTRICT x, float* R x[j] = sub; // only one memory-write per j } - for(j = (N - 2) - s[M - 1]; j >= 0; j--) { + for(int j = (N - 2) - s[M - 1]; j >= 0; j--) { float sub = x[j]; // using local var to reduce memory writes, gave a big speedup for(int i = DIAGONALSP1 - 1; i > 0; i--) { // using a constant upperbound allows the compiler to unroll this loop (gives a good speedup) diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc index ccffbe59c..d1e659114 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -18,7 +18,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// diff --git a/rtengine/LUT.h b/rtengine/LUT.h index 6584eefe6..34f572f58 100644 --- a/rtengine/LUT.h +++ b/rtengine/LUT.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ /* diff --git a/rtengine/PF_correct_RT.cc b/rtengine/PF_correct_RT.cc index fe89a7b65..7df042663 100644 --- a/rtengine/PF_correct_RT.cc +++ b/rtengine/PF_correct_RT.cc @@ -23,7 +23,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// diff --git a/rtengine/StopWatch.h b/rtengine/StopWatch.h index 9e4400b94..94be402e4 100644 --- a/rtengine/StopWatch.h +++ b/rtengine/StopWatch.h @@ -14,14 +14,14 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * Author: reine */ +#pragma once -#ifndef STOPWATCH_H -#define STOPWATCH_H #include +#include #include "mytime.h" #ifdef BENCHMARK @@ -36,45 +36,34 @@ class StopWatch { public: - explicit StopWatch( const char* msg, bool microseconds = false ) : microseconds(microseconds) + explicit StopWatch(const char* msg, bool microSeconds = false) : message(msg), unit(microSeconds ? " us" : " ms"), divisor(microSeconds ? 1 : 1000) { - message = msg; start(); stopped = false; } ~StopWatch() { - if(!stopped) { + if (!stopped) { stop(); } } void start() { startTime.set(); - }; + } void stop() { stopTime.set(); - if(!microseconds) { - long elapsedTime = stopTime.etime(startTime) / 1000; - std::cout << message << " took " << elapsedTime << " ms" << std::endl; - } else { - long elapsedTime = stopTime.etime(startTime); - std::cout << message << " took " << elapsedTime << " us" << std::endl; - } + const long elapsedTime = stopTime.etime(startTime) / divisor; + std::cout << message << " took " << elapsedTime << unit << std::endl; stopped = true; } - void stop(const char *msg) - { - message = msg; - stop(); - }; + private: - bool microseconds; MyTime startTime; MyTime stopTime; - const char *message; + const std::string message; + const std::string unit; + const int divisor; bool stopped; }; - -#endif /* STOPWATCH_H */ diff --git a/rtengine/ahd_demosaic_RT.cc b/rtengine/ahd_demosaic_RT.cc index de331fd53..b3a34295c 100644 --- a/rtengine/ahd_demosaic_RT.cc +++ b/rtengine/ahd_demosaic_RT.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ // @@ -40,7 +40,7 @@ void RawImageSource::ahd_demosaic() { BENCHFUN - constexpr int dir[4] = { -1, 1, -TS, TS }; + constexpr int dirs[4] = { -1, 1, -TS, TS }; float xyz_cam[3][3]; LUTf cbrt(65536); @@ -55,9 +55,10 @@ void RawImageSource::ahd_demosaic() constexpr float d65_white[3] = { 0.950456, 1, 1.088754 }; double progress = 0.0; + if (plistener) { plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), M("TP_RAW_AHD"))); - plistener->setProgress (0.0); + plistener->setProgress (progress); } for (int i = 0; i < 65536; i++) { @@ -65,16 +66,17 @@ void RawImageSource::ahd_demosaic() cbrt[i] = r > 0.008856 ? std::cbrt(r) : 7.787 * r + 16 / 116.0; } - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { for (unsigned int j = 0; j < 3; j++) { xyz_cam[i][j] = 0; for (int k = 0; k < 3; k++) { xyz_cam[i][j] += xyz_rgb[i][k] * imatrices.rgb_cam[k][j] / d65_white[i]; } } - + } border_interpolate2(W, H, 5, rawData, red, green, blue); + #ifdef _OPENMP #pragma omp parallel #endif @@ -153,9 +155,9 @@ void RawImageSource::ahd_demosaic() auto lix = &lab[d][tr][tc]; for (int i = 0; i < 4; i++) { - ldiff[d][i] = std::fabs(lix[0][0] - lix[dir[i]][0]); - abdiff[d][i] = SQR(lix[0][1] - lix[dir[i]][1]) - + SQR(lix[0][2] - lix[dir[i]][2]); + ldiff[d][i] = std::fabs(lix[0][0] - lix[dirs[i]][0]); + abdiff[d][i] = SQR(lix[0][1] - lix[dirs[i]][1]) + + SQR(lix[0][2] - lix[dirs[i]][2]); } } diff --git a/rtengine/alignedbuffer.h b/rtengine/alignedbuffer.h index 846c4c47d..b2c720bd8 100644 --- a/rtengine/alignedbuffer.h +++ b/rtengine/alignedbuffer.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _ALIGNEDBUFFER_ #define _ALIGNEDBUFFER_ diff --git a/rtengine/amaze_demosaic_RT.cc b/rtengine/amaze_demosaic_RT.cc index ffb68dbdd..43aef0f71 100644 --- a/rtengine/amaze_demosaic_RT.cc +++ b/rtengine/amaze_demosaic_RT.cc @@ -22,7 +22,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// @@ -49,11 +49,11 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c stop.reset(new StopWatch("amaze demosaic")); } - volatile double progress = 0.0; + double progress = 0.0; if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), M("TP_RAW_AMAZE"))); - plistener->setProgress (0.0); + plistener->setProgressStr(Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), M("TP_RAW_AMAZE"))); + plistener->setProgress(progress); } const int width = winw, height = winh; @@ -768,7 +768,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c //if both agree on interpolation direction, choose the one with strongest directional discrimination; //otherwise, choose the u/d and l/r difference fluctuation weights - if ((0.5 - varwt) * (0.5 - diffwt) > 0 && fabsf(0.5 - diffwt) < fabsf(0.5 - varwt)) { + if ((0.5f - varwt) * (0.5f - diffwt) > 0.f && fabsf(0.5f - diffwt) < fabsf(0.5f - varwt)) { hvwt[indx >> 1] = varwt; } else { hvwt[indx >> 1] = diffwt; @@ -1236,7 +1236,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c //first ask if one gets more directional discrimination from nearby B/R sites float pmwtalt = xdivf(pmwt[(indx - m1) >> 1] + pmwt[(indx + p1) >> 1] + pmwt[(indx - p1) >> 1] + pmwt[(indx + m1) >> 1], 2); - if (fabsf(0.5 - pmwt[indx1]) < fabsf(0.5 - pmwtalt)) { + if (fabsf(0.5f - pmwt[indx1]) < fabsf(0.5f - pmwtalt)) { pmwt[indx1] = pmwtalt; //a better result was obtained from the neighbours } @@ -1304,7 +1304,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c for (int cc = 12 + (FC(rr, 2) & 1), indx = rr * ts + cc, indx1 = indx >> 1; cc < cc1 - 12; cc += 2, indx += 2, indx1++) { - if (fabsf(0.5 - pmwt[indx >> 1]) < fabsf(0.5 - hvwt[indx >> 1]) ) { + if (fabsf(0.5f - pmwt[indx >> 1]) < fabsf(0.5f - hvwt[indx >> 1]) ) { continue; } diff --git a/rtengine/array2D.h b/rtengine/array2D.h index 48a789bf8..7713cd55c 100644 --- a/rtengine/array2D.h +++ b/rtengine/array2D.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ /* @@ -214,6 +214,12 @@ public: return ptr; } + // use as pointer to T** + operator const T* const *() + { + return ptr; + } + // use as pointer to data operator T*() { diff --git a/rtengine/badpixels.cc b/rtengine/badpixels.cc index 376e58b3b..79b8187f7 100644 --- a/rtengine/badpixels.cc +++ b/rtengine/badpixels.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "array2D.h" diff --git a/rtengine/bilateral2.h b/rtengine/bilateral2.h index e754ac891..d0496810d 100644 --- a/rtengine/bilateral2.h +++ b/rtengine/bilateral2.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _BILATERAL2_ #define _BILATERAL2_ diff --git a/rtengine/boxblur.h b/rtengine/boxblur.h index d686ad43e..27aa9d2fc 100644 --- a/rtengine/boxblur.h +++ b/rtengine/boxblur.h @@ -14,18 +14,20 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _BOXBLUR_H_ #define _BOXBLUR_H_ #include +#include #include #include #include #include "alignedbuffer.h" #include "rt_math.h" #include "opthelper.h" +#include "StopWatch.h" namespace rtengine @@ -204,15 +206,15 @@ template void boxblur (T** src, A** dst, T* buffer, int radx, tempv = tempv / lenv; temp1v = temp1v / lenv; - STVFU( dst[0][col], tempv); - STVFU( dst[0][col + 4], temp1v); + STVFU(dst[0][col], tempv); + STVFU(dst[0][col + 4], temp1v); for (int row = 1; row <= rady; row++) { lenp1v = lenv + onev; tempv = (tempv * lenv + LVFU(temp[(row + rady) * W + col])) / lenp1v; temp1v = (temp1v * lenv + LVFU(temp[(row + rady) * W + col + 4])) / lenp1v; - STVFU( dst[row][col], tempv); - STVFU( dst[row][col + 4], temp1v); + STVFU(dst[row][col], tempv); + STVFU(dst[row][col + 4], temp1v); lenv = lenp1v; } @@ -221,16 +223,16 @@ template void boxblur (T** src, A** dst, T* buffer, int radx, for (int row = rady + 1; row < H - rady; row++) { tempv = tempv + (LVFU(temp[(row + rady) * W + col]) - LVFU(temp[(row - rady - 1) * W + col])) * rlenv ; temp1v = temp1v + (LVFU(temp[(row + rady) * W + col + 4]) - LVFU(temp[(row - rady - 1) * W + col + 4])) * rlenv ; - STVFU( dst[row][col], tempv); - STVFU( dst[row][col + 4], temp1v); + STVFU(dst[row][col], tempv); + STVFU(dst[row][col + 4], temp1v); } for (int row = H - rady; row < H; row++) { lenm1v = lenv - onev; tempv = (tempv * lenv - LVFU(temp[(row - rady - 1) * W + col])) / lenm1v; temp1v = (temp1v * lenv - LVFU(temp[(row - rady - 1) * W + col + 4])) / lenm1v; - STVFU( dst[row][col], tempv); - STVFU( dst[row][col + 4], temp1v); + STVFU(dst[row][col], tempv); + STVFU(dst[row][col + 4], temp1v); lenv = lenm1v; } } @@ -312,6 +314,223 @@ template void boxblur (T** src, A** dst, T* buffer, int radx, } +inline void boxblur (float** src, float** dst, int radius, int W, int H, bool multiThread) +{ + //box blur using rowbuffers and linebuffers instead of a full size buffer + + if (radius == 0) { + if (src != dst) { +#ifdef _OPENMP + #pragma omp parallel for if (multiThread) +#endif + + for (int row = 0; row < H; row++) { + for (int col = 0; col < W; col++) { + dst[row][col] = src[row][col]; + } + } + } + return; + } + + constexpr int numCols = 8; // process numCols columns at once for better usage of L1 cpu cache +#ifdef _OPENMP + #pragma omp parallel if (multiThread) +#endif + { + std::unique_ptr buffer(new float[std::max(W, 8 * H)]); + + //horizontal blur + float* const lineBuffer = buffer.get(); +#ifdef _OPENMP + #pragma omp for +#endif + for (int row = 0; row < H; row++) { + float len = radius + 1; + float tempval = src[row][0]; + lineBuffer[0] = tempval; + for (int j = 1; j <= radius; j++) { + tempval += src[row][j]; + } + + tempval /= len; + dst[row][0] = tempval; + + for (int col = 1; col <= radius; col++) { + lineBuffer[col] = src[row][col]; + tempval = (tempval * len + src[row][col + radius]) / (len + 1); + dst[row][col] = tempval; + ++len; + } + + for (int col = radius + 1; col < W - radius; col++) { + lineBuffer[col] = src[row][col]; + dst[row][col] = tempval = tempval + (src[row][col + radius] - lineBuffer[col - radius - 1]) / len; + } + + for (int col = W - radius; col < W; col++) { + dst[row][col] = tempval = (tempval * len - lineBuffer[col - radius - 1]) / (len - 1); + --len; + } + } + + //vertical blur +#ifdef __SSE2__ + vfloat (* const rowBuffer)[2] = (vfloat(*)[2]) buffer.get(); + const vfloat leninitv = F2V(radius + 1); + const vfloat onev = F2V(1.f); + vfloat tempv, temp1v, lenv, lenp1v, lenm1v, rlenv; + +#ifdef _OPENMP + #pragma omp for nowait +#endif + + for (int col = 0; col < W - 7; col += 8) { + lenv = leninitv; + tempv = LVFU(dst[0][col]); + temp1v = LVFU(dst[0][col + 4]); + rowBuffer[0][0] = tempv; + rowBuffer[0][1] = temp1v; + + for (int i = 1; i <= radius; i++) { + tempv = tempv + LVFU(dst[i][col]); + temp1v = temp1v + LVFU(dst[i][col + 4]); + } + + tempv = tempv / lenv; + temp1v = temp1v / lenv; + STVFU(dst[0][col], tempv); + STVFU(dst[0][col + 4], temp1v); + + for (int row = 1; row <= radius; row++) { + rowBuffer[row][0] = LVFU(dst[row][col]); + rowBuffer[row][1] = LVFU(dst[row][col + 4]); + lenp1v = lenv + onev; + tempv = (tempv * lenv + LVFU(dst[row + radius][col])) / lenp1v; + temp1v = (temp1v * lenv + LVFU(dst[row + radius][col + 4])) / lenp1v; + STVFU(dst[row][col], tempv); + STVFU(dst[row][col + 4], temp1v); + lenv = lenp1v; + } + + rlenv = onev / lenv; + + for (int row = radius + 1; row < H - radius; row++) { + rowBuffer[row][0] = LVFU(dst[row][col]); + rowBuffer[row][1] = LVFU(dst[row][col + 4]); + tempv = tempv + (LVFU(dst[row + radius][col]) - rowBuffer[row - radius - 1][0]) * rlenv ; + temp1v = temp1v + (LVFU(dst[row + radius][col + 4]) - rowBuffer[row - radius - 1][1]) * rlenv ; + STVFU(dst[row][col], tempv); + STVFU(dst[row][col + 4], temp1v); + } + + for (int row = H - radius; row < H; row++) { + lenm1v = lenv - onev; + tempv = (tempv * lenv - rowBuffer[row - radius - 1][0]) / lenm1v; + temp1v = (temp1v * lenv - rowBuffer[row - radius - 1][1]) / lenm1v; + STVFU(dst[row][col], tempv); + STVFU(dst[row][col + 4], temp1v); + lenv = lenm1v; + } + } + +#else + float (* const rowBuffer)[8] = (float(*)[8]) buffer.get(); +#ifdef _OPENMP + #pragma omp for nowait +#endif + + for (int col = 0; col < W - numCols + 1; col += 8) { + float len = radius + 1; + + for (int k = 0; k < numCols; k++) { + rowBuffer[0][k] = dst[0][col + k]; + } + + for (int i = 1; i <= radius; i++) { + for (int k = 0; k < numCols; k++) { + dst[0][col + k] += dst[i][col + k]; + } + } + + for(int k = 0; k < numCols; k++) { + dst[0][col + k] /= len; + } + + for (int row = 1; row <= radius; row++) { + for(int k = 0; k < numCols; k++) { + rowBuffer[row][k] = dst[row][col + k]; + dst[row][col + k] = (dst[row - 1][col + k] * len + dst[row + radius][col + k]) / (len + 1); + } + + len ++; + } + + for (int row = radius + 1; row < H - radius; row++) { + for(int k = 0; k < numCols; k++) { + rowBuffer[row][k] = dst[row][col + k]; + dst[row][col + k] = dst[row - 1][col + k] + (dst[row + radius][col + k] - rowBuffer[row - radius - 1][k]) / len; + } + } + + for (int row = H - radius; row < H; row++) { + for(int k = 0; k < numCols; k++) { + dst[row][col + k] = (dst[row - 1][col + k] * len - rowBuffer[row - radius - 1][k]) / (len - 1); + } + + len --; + } + } + +#endif + //vertical blur, remaining columns +#ifdef _OPENMP + #pragma omp single +#endif + { + const int remaining = W % numCols; + + if (remaining > 0) { + float (* const rowBuffer)[8] = (float(*)[8]) buffer.get(); + const int col = W - remaining; + + float len = radius + 1; + for(int k = 0; k < remaining; ++k) { + rowBuffer[0][k] = dst[0][col + k]; + } + for (int row = 1; row <= radius; ++row) { + for(int k = 0; k < remaining; ++k) { + dst[0][col + k] += dst[row][col + k]; + } + } + for(int k = 0; k < remaining; ++k) { + dst[0][col + k] /= len; + } + for (int row = 1; row <= radius; ++row) { + for(int k = 0; k < remaining; ++k) { + rowBuffer[row][k] = dst[row][col + k]; + dst[row][col + k] = (dst[row - 1][col + k] * len + dst[row + radius][col + k]) / (len + 1); + } + len ++; + } + const float rlen = 1.f / len; + for (int row = radius + 1; row < H - radius; ++row) { + for(int k = 0; k < remaining; ++k) { + rowBuffer[row][k] = dst[row][col + k]; + dst[row][col + k] = dst[row - 1][col + k] + (dst[row + radius][col + k] - rowBuffer[row - radius - 1][k]) * rlen; + } + } + for (int row = H - radius; row < H; ++row) { + for(int k = 0; k < remaining; ++k) { + dst[row][col + k] = (dst[(row - 1)][col + k] * len - rowBuffer[row - radius - 1][k]) / (len - 1); + } + len --; + } + } + } + } +} + template void boxblur (T* src, A* dst, A* buffer, int radx, int rady, int W, int H) { //box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1) @@ -382,15 +601,15 @@ template void boxblur (T* src, A* dst, A* buffer, int radx, in tempv = tempv / lenv; temp1v = temp1v / lenv; - STVFU( dst[0 * W + col], tempv); - STVFU( dst[0 * W + col + 4], temp1v); + STVFU(dst[0 * W + col], tempv); + STVFU(dst[0 * W + col + 4], temp1v); for (int row = 1; row <= rady; row++) { lenp1v = lenv + onev; tempv = (tempv * lenv + LVFU(temp[(row + rady) * W + col])) / lenp1v; temp1v = (temp1v * lenv + LVFU(temp[(row + rady) * W + col + 4])) / lenp1v; - STVFU( dst[row * W + col], tempv); - STVFU( dst[row * W + col + 4], temp1v); + STVFU(dst[row * W + col], tempv); + STVFU(dst[row * W + col + 4], temp1v); lenv = lenp1v; } @@ -399,16 +618,16 @@ template void boxblur (T* src, A* dst, A* buffer, int radx, in for (int row = rady + 1; row < H - rady; row++) { tempv = tempv + (LVFU(temp[(row + rady) * W + col]) - LVFU(temp[(row - rady - 1) * W + col])) * rlenv ; temp1v = temp1v + (LVFU(temp[(row + rady) * W + col + 4]) - LVFU(temp[(row - rady - 1) * W + col + 4])) * rlenv ; - STVFU( dst[row * W + col], tempv); - STVFU( dst[row * W + col + 4], temp1v); + STVFU(dst[row * W + col], tempv); + STVFU(dst[row * W + col + 4], temp1v); } for (int row = H - rady; row < H; row++) { lenm1v = lenv - onev; tempv = (tempv * lenv - LVFU(temp[(row - rady - 1) * W + col])) / lenm1v; temp1v = (temp1v * lenv - LVFU(temp[(row - rady - 1) * W + col + 4])) / lenm1v; - STVFU( dst[row * W + col], tempv); - STVFU( dst[row * W + col + 4], temp1v); + STVFU(dst[row * W + col], tempv); + STVFU(dst[row * W + col + 4], temp1v); lenv = lenm1v; } } @@ -422,12 +641,12 @@ template void boxblur (T* src, A* dst, A* buffer, int radx, in } tempv = tempv / lenv; - STVFU( dst[0 * W + col], tempv); + STVFU(dst[0 * W + col], tempv); for (int row = 1; row <= rady; row++) { lenp1v = lenv + onev; tempv = (tempv * lenv + LVFU(temp[(row + rady) * W + col])) / lenp1v; - STVFU( dst[row * W + col], tempv); + STVFU(dst[row * W + col], tempv); lenv = lenp1v; } @@ -435,13 +654,13 @@ template void boxblur (T* src, A* dst, A* buffer, int radx, in for (int row = rady + 1; row < H - rady; row++) { tempv = tempv + (LVFU(temp[(row + rady) * W + col]) - LVFU(temp[(row - rady - 1) * W + col])) * rlenv ; - STVFU( dst[row * W + col], tempv); + STVFU(dst[row * W + col], tempv); } for (int row = H - rady; row < H; row++) { lenm1v = lenv - onev; tempv = (tempv * lenv - LVFU(temp[(row - rady - 1) * W + col])) / lenm1v; - STVFU( dst[row * W + col], tempv); + STVFU(dst[row * W + col], tempv); lenv = lenm1v; } } diff --git a/rtengine/cache.h b/rtengine/cache.h index ec284b2ae..6c1dacf43 100644 --- a/rtengine/cache.h +++ b/rtengine/cache.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 97a14f66e..7f481e104 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -48,7 +48,7 @@ Examples: // For new models that are still not supported by the dcraw version used in current RT, we have to fill all the // alternate names or else RT will not recognize the alternate model names. // For models supported by dcraw, filling the alternate names is simply desired (for better user info). - // The format of multiple naming is to write all names in brackets i.e instead of + // The format of multiple naming is to write all names in brackets i.e instead of // "make_model": "Canon EOS 550D", // type // "make_model": [ "Canon EOS 550D", "Canon EOS Rebel T2i", "Canon EOS Kiss X4" ], @@ -115,9 +115,9 @@ How to Measure White Levels: dcraw provides the default values used by RawTherapee, but often provides too high white levels, and only provides a single value regardless of color channel, ISO or aperture. If you open an image with a large clipped area and that is rendered in a pink/magenta color rather than white it usually means that the white level constant is too high. You can - fix this by adjusting the"Raw White Point" in the raw tab inside RawTherapee, or permanently fix it by measuring and + fix this by adjusting white-point correction in the Raw tab > Raw White Points, or permanently fix it by measuring and providing a more exact white level in camconst.json so RawTherapee gets to know from start where the camera actually - clips. Providing a complete and detailed white-level profile can be a quite large and complicated effort. As an + clips. Providing a complete and detailed white-level profile can be a quite large and complicated effort. As an alternative you can provide a simpler profile.We suggest one of the following alternatives in rising difficulty (and generally diminishing return): A) Provide a single white-level value measured on the native ISO (base ISO). For many cameras this will actually be @@ -159,7 +159,7 @@ How to Measure White Levels: histogram. While it's common to with very little variation, say only +/-2 units, some can have +/-500 or more (some may have different variation depending on ISO). There can also be camera-to-camera variation. - If the white level is set too high RawTherapee will not think the pixels are clipped and you can get discoloured + If the white level is set too high RawTherapee will not think the pixels are clipped and you can get discolored highlights (usually pink), this is what we want to avoid. If white level is set too low RawTherapee will clip early, ie you lose a little highlight detail, but the color is rendered correctly and highlight reconstruction can work properly, so this is not as bad. This is why we want conservative values. @@ -167,21 +167,21 @@ How to Measure White Levels: By conservative values we mean that if you see a white level of most often 15760 and occasionally 15759 (i.e. very small variation of white level which is a common case), you set the white level around 50-100 14-bit units below or 10-20 12-bit units. Say at 15700 in this example, or 4080 instead of 4095 for 12-bit raws. This way we get a little margin - from noise and camera variation. Since sensor raw values are linear, you lose, for example, + from noise and camera variation. Since sensor raw values are linear, you lose, for example, log2(1-50/15760) = -0.005 stops of detail, i.e. irrelevant. Thus it is better to provide RawTherapee with knowledge where the image clips rather than keeping that last 0.005 stop of highlight information and risking that clipping will not be detected properly. It is very usual for white level to be a bell distribution instead of a candle when the camera applies long exposure noise reduction (LENR) by subtracting a black frame and/or when the system is destabilized due to temperature. Some models have - always a bell distribution at WL. If you have a fuzzy white level look at the linear histogram; you will probably see a + always a bell distribution at WL. If you have a fuzzy white level look at the linear histogram; you will probably see a normal/Gaussian distribution (bell shape) noise peak at clipping and probably also a peak at a hard raw data clip level usually at or close to a power of two - 1, such as 4095 or 16383. Then you pick a value just before the bell shape rises, i.e. to the left of the bell meaning that you cut away the whole fuzzy noise peak. If a little of the starting edge - of the noise will be included it's not harmful, but 99% of it should be above. This would mean that it's better to + of the noise will be included it's not harmful, but 99% of it should be above. This would mean that it's better to measure white level on long exposure/high temp raws but since this if difficult and time consuming we choose to measure - on normal raws and cover the abnormalities with the conservative WL values. A more detailed approach when we only have - non-LENR measures is to subtract a value according to per ISO read noise. We can find data regarding read noise (stdev + on normal raws and cover the abnormalities with the conservative WL values. A more detailed approach when we only have + non-LENR measures is to subtract a value according to per ISO read noise. We can find data regarding read noise (stdev of Gaussian distribution) at http://www.photonstophotos.net/Charts/RN_ADU.htm . We find the per ISO tead_noise and subtract from the measured value 6*read_noise. This gives confidence that 99.5% of the bell is clipped out. @@ -201,7 +201,7 @@ How to Measure White Levels: need a margin on white_max as it clips there as a result of an in-camera math operation. Note that aperture scaling can be quite small, for the 5D mark II it's only 0.2 stop down to f/1.2 and then it can be - discussed if it's worthwhile to care. The "worst" cameras scale about 0.6 stops though, and then it's more valuable to + discussed if it's worthwhile to care. The "worst" cameras scale about 0.6 stops though, and then it's more valuable to compensate. If you skip aperture scaling RawTherapee will clip the files a little bit too early and you miss that last fraction of highlight detail, but you get no processing problems. Setting un-conservative scale factors can on the other hand cause a too high white level and break highlight processing, so be careful. @@ -209,7 +209,7 @@ How to Measure White Levels: Scaling can vary slightly depending on ISO (if white levels vary) so make sure to provide conservative scalings so regardless of ISO you don't get a too high white level. We recommend to keep a small margin here also white levels, i.e. 0.5% lower or so. For example if base (not conservative!) white level is 15750 and the scaled is 16221 we have a - scaling factor of 16221/15750=1.0299 i.e. +2.9% we set the factor to 1.025 to keep a margin. The abnormal cases are + scaling factor of 16221/15750=1.0299 i.e. +2.9% we set the factor to 1.025 to keep a margin. The abnormal cases are already covered by setting conservative per ISO White levels. The scale factor you provide here is applied on the white level before black level subtraction (if any), i.e. directly on @@ -239,10 +239,10 @@ How to Measure White Levels: You can use RawTherapee for analysis too, it's safer as you are using it's own raw decoder but it's not as user-friendly: enable verbose mode in options so you get output on the console. When you load a file you will see a - message of current black and white levels and if they came from dcraw or camconst.json. If you're adjusting an existing + message of current black and white levels and if they came from dcraw or camconst.json. If you're adjusting an existing camconst.json value you can just read what it is in the file and not need to enable verbose output. - Reset exposure sliders to neutral, and zoom in on a large clipped highlight. Move around the mouse pointer within, it + Reset exposure sliders to neutral, and zoom in on a large clipped highlight. Move around the mouse pointer within, it should show stable 100% on R G B. If so, the white level is not too high, it could however be too low. To test that, go to the raw tab and adjust the "white point linear correction factor", reduce it until one of the channels is no longer 100%, and then increase in steps of 0.01 until all are 100 again. Usually you play around in the range 0.90 to 0.99, i.e. @@ -438,7 +438,7 @@ Camera constants: { "iso": [ 160 ], "levels": 13000 }, // nominal f8-13105 { "iso": [ 320, 640, 1250, 2500 ], "levels": 13300 }, // G1,G2 F4.0-13422-F2.8-13562-13616 { "iso": [ 5000, 10000, 20000 ], "levels": 13200 }, // G1,G2 F4.0-13422-F2.8-13562-13616 - { "iso": [ 400, 500, 800, 1000, 1600, 2000, 3200, 4000 ], "levels": 16100 }, // nominal 16383, + { "iso": [ 400, 500, 800, 1000, 1600, 2000, 3200, 4000 ], "levels": 16100 }, // nominal 16383, { "iso": [ 6400, 8000, 12800, 16000, 25600, 32000 ], "levels": 16000 }, // R,G1,G2 16383, LENR? { "iso": [ 40000, 51200, 102400 ], "levels": 15800 } // 16383, LENR? ], @@ -462,7 +462,7 @@ Camera constants: "make_model": [ "Canon EOS 5DS R", "Canon EOS 5DS" ], //"dcraw_matrix": [ 6848,-1661,-221,-3904,10931,3434,-470,1251,6039 ], // DNG_V9.0 A "dcraw_matrix": [ 6250,-711,-808,-5153,12794,2636,-1249,2198,5610 ], // DNG_V9.0 D65 - "raw_crop": [ 192, 96, 8696, 5800 ], // 800, 300, 7500, 4700 - 160,64,8730x5800 - sensor 8896x5920 top64, left160, official crop left196, top100, right 8883, bottom 5891, 8688X5792 + "raw_crop": [ 192, 96, 8696, 5800 ], // 800, 300, 7500, 4700 - 160,64,8730x5800 - sensor 8896x5920 top64, left160, official crop left196, top100, right 8883, bottom 5891, 8688X5792 "masked_areas": [ 100, 40, 5892, 158 ], // left out 40 first columns from calculations because possibly the BL is still imbalanced there "ranges": { "white": [ @@ -497,7 +497,7 @@ Camera constants: { "iso": [ 160, 320, 640, 1250, 2500 ], "levels": 13100 }, // typical 13225 { "iso": [ 5000, 10000 ], "levels": 13000 }, // typical 13225 { "iso": [ 20000 ], "levels": 12800 }, // typical 13225 - { "iso": [ 51200, 102400 ], "levels": 15900 } // typical 16383 + { "iso": [ 51200, 102400 ], "levels": 15900 } // typical 16383 ], "white_max": 16383, "aperture_scaling": [ @@ -522,7 +522,7 @@ Camera constants: "dcraw_matrix": [ 6875,-970,-932,-4691,12459,2501,-874,1953,5809 ], // DNG v_9.12 D65 "raw_crop": [ 120, 44, 6264, 4180 ], // fullraw size 6384x4224 useful 120,44,6264x4180 // "raw_crop": [ 128, 52, 6248, 4168 ], // official jpeg crop 120+12,44+12,6240x4160 - "masked_areas": [ 44, 4, 4220, 116 ], + "masked_areas": [ 44, 4, 4220, 116 ], "ranges": { "white": [ { "iso": [ 50, 100, 125, 200, 250, 400, 500, 800, 1000, 1600, 2000, 3200 ], "levels": 16300 }, // typical 16383 @@ -532,7 +532,7 @@ Camera constants: { "iso": [ 320, 640, 1250, 2500 ], "levels": 13250 }, // typical 13337 { "iso": [ 5000, 10000 ], "levels": 13100 }, // typical 13367 { "iso": [ 20000, 40000 ], "levels": 12900 }, // typical 13367 - { "iso": [ 51200, 102400 ], "levels": 15900 } // typical 16383 + { "iso": [ 51200, 102400 ], "levels": 15900 } // typical 16383 ], "white_max": 16383, "aperture_scaling": [ @@ -588,8 +588,8 @@ Camera constants: { "iso": [ 100, 125 ], "levels": 13500 }, // typical 13583 - LENR 13550 { "iso": [ 160, 320, 640, 1250, 2500, 5000 ], "levels": 12500 }, // typical 12559 { "iso": [ 200, 250, 400, 500, 800, 1000, 1600, 2000, 3200, 4000 ], "levels": 15200 }, // typical 15303 - LENR 15270,15260,15240,15220, - { "iso": [ 6400, 8000, 10000, 12800, 16000, 20000, 25600 ], "levels": 15100 }, // typical G1,G2 15303, R,B = 15430 LENR 15200 .. 15100 - { "iso": 51200, "levels": 16300 } // typical 16383 red 16371 + { "iso": [ 6400, 8000, 10000, 12800, 16000, 20000, 25600 ], "levels": 15100 }, // typical G1,G2 15303, R,B = 15430 LENR 15200 .. 15100 + { "iso": 51200, "levels": 16300 } // typical 16383 red 16371 ], "white_max": 16383, "aperture_scaling": [ @@ -620,7 +620,7 @@ Camera constants: { "iso": [ 200, 400 ], "levels": 16100 }, // typical 16224 { "iso": 800, "levels": 15900 }, // gaussian histogram 15900-16224 { "iso": 1600, "levels": 14900 }, // gaussian histogram 14900-15750 - { "iso": 1250, "levels": 11900 } // gaussian histogram 11900-12500 + { "iso": 1250, "levels": 11900 } // gaussian histogram 11900-12500 ], "white_max": 16383, "aperture_scaling": [ @@ -805,6 +805,13 @@ Camera constants: // Canon mid-range DSLRs (Rebels) + { // Quality C + "make_model": [ "Canon EOS 400D DIGITAL" ], + "ranges": { + "white": 4056 + } + }, + { // Quality B, ISO and aperture WL data by ..... at RawTherapee forums, missing samples safely guessed "make_model": [ "Canon EOS 550D", "Canon EOS Rebel T2i", "Canon EOS Kiss X4" ], "dcraw_matrix": [ 6941,-1164,-857,-3825,11597,2534,-416,1540,6039 ], // dcraw 550d @@ -1075,9 +1082,9 @@ Camera constants: "masked_areas": [ 40, 16, 4000, 54 ], "ranges": { "white": [ - { "iso": [ 100, 125, 160 ], "levels": 16300 }, // 16383 - { "iso": [ 320, 640, 1250, 2500, 5000, 10000 ], "levels": 12600 }, // 12632..14500 - { "iso": [ 200, 250, 400, 500, 800, 1000, 1600, 2000, 3200, 4000 ], "levels": 15000 }, // 15095, 15488 + { "iso": [ 100, 125, 160 ], "levels": 16300 }, // 16383 + { "iso": [ 320, 640, 1250, 2500, 5000, 10000 ], "levels": 12600 }, // 12632..14500 + { "iso": [ 200, 250, 400, 500, 800, 1000, 1600, 2000, 3200, 4000 ], "levels": 15000 }, // 15095, 15488 { "iso": [ 6400, 8000, 12800, 25600 ], "levels": 16200 } // 16383 ], "white_max": 16383, @@ -1097,10 +1104,10 @@ Camera constants: }, { // Quality C, White Levels not properly indicated, aperture scaling..missing factors are guessed - "make_model": [ "Canon EOS M5","Canon EOS M6" ], + "make_model": [ "Canon EOS M5","Canon EOS M6" ], "dcraw_matrix": [ 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 ], // DNG_V9.8 D65 "raw_crop": [ 264, 36, 6024, 4020 ], // full size 6288x4056, - //"raw_crop": [ 272, 44, 6008, 4008 ], // matched to official crop 276,48,6275,4047 - official jpeg 6000X4000 + //"raw_crop": [ 272, 44, 6008, 4008 ], // matched to official crop 276,48,6275,4047 - official jpeg 6000X4000 "masked_areas": [ 40, 96, 4000, 260 ], "ranges": { "white": [ @@ -1109,9 +1116,9 @@ Camera constants: { "iso": [ 320 ], "levels": 13100 }, // nominal green 13200, 13528-14466-14380-14368 - blue13262-14186, { "iso": [ 640, 1250 ], "levels": 13200 }, // iso 640 G1,G2 13260-13450 - blue13230-13430 -iso 1250 13430 { "iso": [ 2500, 5000, 10000 ], "levels": 13000 }, // - { "iso": [ 400, 500, 800, 1000, 1600, 2000, 3200, 4000, 6400 ], "levels": 16100 }, // 16383 - // { "iso": [ 1600 ], "levels": 15000 }, // one sample of m6 = 15100 !! - // { "iso": [ 6400 ], "levels": 15500 }, // one sample of m6 = 15600 !! + { "iso": [ 400, 500, 800, 1000, 1600, 2000, 3200, 4000, 6400 ], "levels": 16100 }, // 16383 + // { "iso": [ 1600 ], "levels": 15000 }, // one sample of m6 = 15100 !! + // { "iso": [ 6400 ], "levels": 15500 }, // one sample of m6 = 15600 !! { "iso": [ 8000, 12800, 16000, 25600 ], "levels": 16000 } // R,G1,G2 16383, B 16243 ], "white_max": 16383, @@ -1169,7 +1176,7 @@ Camera constants: "dcraw_matrix": [ 7378,-1255,-1043,-4088,12251,2048,-876,1946,5805 ], // D65 matrix from adobe dcp //"raw_crop": [ 80, 50, 4400, 3316 ], // full frame 4480x3366 borders 80,50 - much shade in corners, no/wrong auto distortion //"raw_crop": [ 104, 144, 4360, 3128 ], // Mixed best average frame, width is 4352 from 3/2, height 3120 from 4/3 - auto distortion does not work correctly - //"raw_crop": [ 200, 144, 4168, 3128 ], // Optional official 4/3 frame 4160x3120, 4pix borders, Left Border 204-4, Top Border 148-4 + //"raw_crop": [ 200, 144, 4168, 3128 ], // Optional official 4/3 frame 4160x3120, 4pix borders, Left Border 204-4, Top Border 148-4 "raw_crop": [ 104, 252, 4360, 2912 ], // Default official 3/2 frame 4352x2904, 4pix borders, Left Border 108-4, Top border 256-4 "masked_areas": [ 148, 2, 3340, 78 ], "ranges": { "white": 16300 } @@ -1339,8 +1346,8 @@ Camera constants: { // Quality C, only raw crop "make_model": [ "FUJIFILM X-T3", "FUJIFILM X-T30" ], "raw_crop": [ 0, 5, 6252, 4176] - }, - + }, + { // Quality B "make_model": "FUJIFILM X30", "dcraw_matrix": [ 12328,-5256,-1144,-4469,12927,1675,-87,1291,4351 ], // DNG_v8.7 D65 @@ -1359,6 +1366,11 @@ Camera constants: "raw_crop": [ 4, 4, -4, -4 ] // full raw 6016x4016, Official 6000x4000 }, + { // Quality C + "make_model": "LEICA Q2", + "raw_crop": [ 0, 0, 8392, 5624 ] + }, + { // Quality B, Matrix from Adobe's dcp D65 instead of the internal in Leica's DNG "make_model": "LEICA SL (Typ 601)", "dcraw_matrix": [ 11492,-4930,-1188,-5593,14673,873,-609,1474,6343 ], // DNGv9.3 D65 @@ -1610,14 +1622,14 @@ Camera constants: "ranges": { "white": 3980 } // 12-bit files. }, - { // Quality C, only colour matrix and PDAF lines info + { // Quality C, only color matrix and PDAF lines info "make_model" : "Nikon Z 7", "dcraw_matrix" : [10405,-3755,-1270,-5461,13787,1793,-1040,2015,6785], // Adobe DNG Converter 11.0 ColorMatrix2 "pdaf_pattern" : [0, 12], "pdaf_offset" : 29 }, - { // Quality C, only colour matrix and PDAF lines info + { // Quality C, only color matrix and PDAF lines info "make_model" : "Nikon Z 6", "dcraw_matrix" : [8210, -2534, -683, -5355, 13338, 2212, -1143, 1929, 6464], // Adobe DNG Converter 11.1 Beta ColorMatrix2 "pdaf_pattern" : [0, 12], @@ -1713,9 +1725,15 @@ Camera constants: { // Quality B, "make_model": "OLYMPUS TG-5", "dcraw_matrix": [ 10899,-3833,-1082,-2112,10736,1575,-267,1452,5269 ], // DNG_V9.12 D65 + "raw_crop": [ 0, 0, -18, 0 ], // 18 pixels at right are garbage "ranges": { "white": 4050 } // safe for worst case detected, nominal is 4093 }, + { // Quality C, only raw crop + "make_model": "OLYMPUS TG-6", + "raw_crop": [ 0, 0, -24, 0 ] // 24 pixels at right are garbage + }, + { // Quality C, only green equilibration "make_model" : ["OLYMPUS E-3", "OLYMPUS E-520"], "global_green_equilibration" : true @@ -1741,6 +1759,15 @@ Camera constants: } }, + { // Quality C, only color matrix + "make_model" : "Panasonic DC-GF10", + "dcraw_matrix": [ 7610, -2780, -576, -4614, 12195, 2733, -1375, 2393, 6490 ], // ColorMatrix2 from Adobe DNG Converter 11.3 + "raw_crop": [ 0, 0, 4600, 0 ], // SensorWidth=4816 SensorHeight=3464. Width=4600 to match DNG. + "ranges": { + "black": 15 + } + }, + { // Quality B, CameraPhone, some samples are missing but has the same sensor as FZ1000 .. "make_model": [ "Panasonic DMC-CM1", "Panasonic DMC-CM10" ], "dcraw_matrix": [ 8770,-3194,-820,-2871,11281,1803,-513,1552,4434 ], // dcp_v8.7 d65 @@ -1788,7 +1815,7 @@ Camera constants: { // Quality B, "make_model": [ "Panasonic DMC-FZ2500", "Panasonic DMC-FZ2000", "Panasonic DMC-FZH1" ], - "dcraw_matrix": [ 7386,-2443,-743,-3437,11864,1757,-608,1660,4766 ], // dcp_v9.8 d65 + "dcraw_matrix": [ 7386,-2443,-743,-3437,11864,1757,-608,1660,4766 ], // dcp_v9.8 d65 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset "white": [ @@ -1879,7 +1906,8 @@ Camera constants: "dcraw_matrix": [ 7122,-2092,-419,-4643,11769,3283,-1363,2413,5944 ], // RT "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset - "white": 4060 } // Exif:4095 normal distribution 4080-4095, 4070-4095 on long exposure NR + "white": 4060 // Exif:4095 normal distribution 4080-4095, 4070-4095 on long exposure NR + } }, { // Quality A, Replicated from rawimage.cc @@ -1899,7 +1927,8 @@ Camera constants: "dcraw_matrix": [ 7694,-1791,-745,-4917,12818,2332,-1221,2322,7197 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset - "white": 4050 } // Exif:4095 normal distribution 4080-4095, 4050-4095 on long exposure NR + "white": 4050 // Exif:4095 normal distribution 4080-4095, 4050-4095 on long exposure NR + } }, { // Quality A, Replicated from rawimage.cc @@ -1907,7 +1936,8 @@ Camera constants: "dcraw_matrix": [ 8074,-1846,-861,-5026,12999,2239,-1320,2375,7422 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset - "white": 4050 } // Exif:4095 normal distribution 4080-4095, 4050-4095 on long exposure NR + "white": 4050 // Exif:4095 normal distribution 4080-4095, 4050-4095 on long exposure NR + } }, { // Quality A, Replicated from rawimage.cc @@ -2220,7 +2250,12 @@ Camera constants: } }, - { // Quality B, corrections for raw crop vs dcraw9.21, matched to Samsung's default + { // Quality C, only raw crop + "make_model": "Samsung EX2F", + "raw_crop": [ 16, 7, -4, -4 ] + }, + + { // Quality B, corrections for raw crop vs dcraw9.21, matched to Samsung's default "make_model": "Samsung NX mini", "dcraw_matrix": [ 5222,-1196,-550,-6540,14649,2009,-1666,2819,5657 ], // dng 8.6 d65 "raw_crop": [ 128, 36, 5480, 3656 ], // jpeg 5472x3648 - full raw: 5664 x 3710 - Samsung's official crop: 132, 40, 5604, 3688 @@ -2243,8 +2278,8 @@ Camera constants: { "iso": 100, "levels": 16000 }, // 16000 typical 16084, LE 16120 and 16383, LENR 16280 { "iso": [ 200, 400, 800, 1600, 3200, 6400, 12800 ], "levels": 16300 }, // 16383 { "iso": [ 25600, 51200 ], "levels": 16300 } // 16383 - ] - } + ] + } }, { // Quality C, corrections for frame size, black and white levels not declared properly @@ -2283,7 +2318,7 @@ Camera constants: //"dcraw_matrix": [ 5666,139,-892,3780,5428,270,1366,9757,4526 ], // experimental inverted icc sunny8161 //"dcraw_matrix": [ 10288,-2449,-1718,8976,1868,-1608,7011,5039,-249 ], // experimental inverted icc tungsten8130 wp11 //"dcraw_matrix": [ 5864,679,-1491,2963,7635,-919,-640,13738,2790 ], // experimental inverted icc sunny8160 - //"dcraw_matrix": [ 14032,-2231,-1016,-5263,14816,170,-112,183,9113 ], // hardcoded + //"dcraw_matrix": [ 14032,-2231,-1016,-5263,14816,170,-112,183,9113 ], // hardcoded "ranges": { "black": 16, "white": 4070 }, // BL is 16 or 31, should be measured at the horizontal black stripe at the top "raw_crop": [ 12, 52, -110, -8 ] // for small size all numbers/2 }, @@ -2367,7 +2402,7 @@ Camera constants: "ranges": { "black": 512, "white": 16300 }, // contributed by Horshak from https://www.dpreview.com/forums/post/60873077 "pdaf_pattern" : [ 0,12,36,54,72,90,114,126,144,162,180,204,216,240,252,270,294,306,324,342,366,384,396,414,432,450,474,492,504,522,540,564,576,594,606,630 ], - "pdaf_offset" : 3 + "pdaf_offset" : 3 }, { // Quality A, correction for frame width @@ -2402,8 +2437,8 @@ Camera constants: { // Quality C, color matrix copied from ILCE-9, LongExposures 2-3sec only "make_model": "Sony ILCE-7M3", "dcraw_matrix": [ 6389,-1703,-378,-4562,12265,2587,-670,1489,6550 ], // ILCE-9, DNG_v9.12 D65 - // "raw_crop": [ 8, 8, 6008, 4008 ], // full raw frame 6048x4024 Dcraw auto identify 6024x4024, jpeg 12,12,6000x4000 - // "ranges": { "black": 512, "white": 16300 } + // "raw_crop": [ 8, 8, 6008, 4008 ], // full raw frame 6048x4024 Dcraw auto identify 6024x4024, jpeg 12,12,6000x4000 + // "ranges": { "black": 512, "white": 16300 } "ranges": { "black": 512, "white": [ @@ -2437,6 +2472,11 @@ Camera constants: "pdaf_offset" : 31 }, + { // Quality C, + "make_model": "Sony ILCE-7RM4", + "raw_crop": [ 0, 0, 9568, 0 ] // full raw frame 9600x6376 - 32 rightmost columns are garbage + }, + { // Quality B, color matrix copied from a7rm2 "make_model": "Sony ILCE-9", "dcraw_matrix": [ 6389,-1703,-378,-4562,12265,2587,-670,1489,6550 ], // DNG_v9.12 D65 diff --git a/rtengine/capturesharpening.cc b/rtengine/capturesharpening.cc new file mode 100644 index 000000000..e08243713 --- /dev/null +++ b/rtengine/capturesharpening.cc @@ -0,0 +1,812 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2019 Ingo Weyrich (heckflosse67@gmx.de) + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . +*/ +#include +#include + +#include "rtengine.h" +#include "rawimagesource.h" +#include "rt_math.h" +#include "improcfun.h" +#include "procparams.h" +#include "color.h" +#include "gauss.h" +#include "rt_algo.h" +//#define BENCHMARK +#include "StopWatch.h" +#ifdef _OPENMP +#include +#endif +#include "opthelper.h" +#include "../rtgui/multilangmgr.h" + +namespace { + +void compute7x7kernel(float sigma, float kernel[7][7]) { + + const double temp = -2.f * rtengine::SQR(sigma); + float sum = 0.f; + for (int i = -3; i <= 3; ++i) { + for (int j = -3; j <= 3; ++j) { + if((rtengine::SQR(i) + rtengine::SQR(j)) <= rtengine::SQR(3.0 * 1.15)) { + kernel[i + 3][j + 3] = std::exp((rtengine::SQR(i) + rtengine::SQR(j)) / temp); + sum += kernel[i + 3][j + 3]; + } else { + kernel[i + 3][j + 3] = 0.f; + } + } + } + + for (int i = 0; i < 7; ++i) { + for (int j = 0; j < 7; ++j) { + kernel[i][j] /= sum; + } + } +} + +void compute5x5kernel(float sigma, float kernel[5][5]) { + + const double temp = -2.f * rtengine::SQR(sigma); + float sum = 0.f; + for (int i = -2; i <= 2; ++i) { + for (int j = -2; j <= 2; ++j) { + if((rtengine::SQR(i) + rtengine::SQR(j)) <= rtengine::SQR(3.0 * 0.84)) { + kernel[i + 2][j + 2] = std::exp((rtengine::SQR(i) + rtengine::SQR(j)) / temp); + sum += kernel[i + 2][j + 2]; + } else { + kernel[i + 2][j + 2] = 0.f; + } + } + } + + for (int i = 0; i < 5; ++i) { + for (int j = 0; j < 5; ++j) { + kernel[i][j] /= sum; + } + } +} + +void compute3x3kernel(float sigma, float kernel[3][3]) { + + const double temp = -2.f * rtengine::SQR(sigma); + float sum = 0.f; + for (int i = -1; i <= 1; ++i) { + for (int j = -1; j <= 1; ++j) { + if((rtengine::SQR(i) + rtengine::SQR(j)) <= rtengine::SQR(3.0 * 0.84)) { + kernel[i + 1][j + 1] = std::exp((rtengine::SQR(i) + rtengine::SQR(j)) / temp); + sum += kernel[i + 1][j + 1]; + } else { + kernel[i + 1][j + 1] = 0.f; + } + } + } + + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + kernel[i][j] /= sum; + } + } +} + +inline void gauss3x3div (float** RESTRICT src, float** RESTRICT dst, float** RESTRICT divBuffer, const int W, const int H, const float kernel[3][3]) +{ + + const float c11 = kernel[0][0]; + const float c10 = kernel[0][1]; + const float c00 = kernel[1][1]; + + for (int i = 1; i < H - 1; i++) { + dst[i][0] = 1.f; + for (int j = 1; j < W - 1; j++) { + const float val = c11 * (src[i - 1][j - 1] + src[i - 1][j + 1] + src[i + 1][j - 1] + src[i + 1][j + 1]) + + c10 * (src[i - 1][j] + src[i][j - 1] + src[i][j + 1] + src[i + 1][j]) + + c00 * src[i][j]; + dst[i][j] = divBuffer[i][j] / std::max(val, 0.00001f); + } + dst[i][W - 1] = 1.f; + } + // first and last row + for (int j = 0; j < W; ++j) { + dst[0][j] = 1.f; + } + for (int j = 0; j < W; ++j) { + dst[H - 1][j] = 1.f; + } +} + +inline void gauss5x5div (float** RESTRICT src, float** RESTRICT dst, float** RESTRICT divBuffer, const int W, const int H, const float kernel[5][5]) +{ + + const float c21 = kernel[0][1]; + const float c20 = kernel[0][2]; + const float c11 = kernel[1][1]; + const float c10 = kernel[1][2]; + const float c00 = kernel[2][2]; + + for (int i = 2; i < H - 2; ++i) { + dst[i][0] = dst[i][1] = 1.f; + // I tried hand written SSE code but gcc vectorizes better + for (int j = 2; j < W - 2; ++j) { + const float val = c21 * (src[i - 2][j - 1] + src[i - 2][j + 1] + src[i - 1][j - 2] + src[i - 1][j + 2] + src[i + 1][j - 2] + src[i + 1][j + 2] + src[i + 2][j - 1] + src[i + 2][j + 1]) + + c20 * (src[i - 2][j] + src[i][j - 2] + src[i][j + 2] + src[i + 2][j]) + + c11 * (src[i - 1][j - 1] + src[i - 1][j + 1] + src[i + 1][j - 1] + src[i + 1][j + 1]) + + c10 * (src[i - 1][j] + src[i][j - 1] + src[i][j + 1] + src[i + 1][j]) + + c00 * src[i][j]; + + dst[i][j] = divBuffer[i][j] / std::max(val, 0.00001f); + } + dst[i][W - 2] = dst[i][W - 1] = 1.f; + } + + // first and last rows + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < W; ++j) { + dst[i][j] = 1.f; + } + } + for (int i = H - 2 ; i < H; ++i) { + for (int j = 0; j < W; ++j) { + dst[i][j] = 1.f; + } + } +} + +inline void gauss7x7div(float** RESTRICT src, float** RESTRICT dst, float** RESTRICT divBuffer, const int W, const int H, const float kernel[7][7]) +{ + + const float c31 = kernel[0][2]; + const float c30 = kernel[0][3]; + const float c22 = kernel[1][1]; + const float c21 = kernel[1][2]; + const float c20 = kernel[1][3]; + const float c11 = kernel[2][2]; + const float c10 = kernel[2][3]; + const float c00 = kernel[3][3]; + + for (int i = 3; i < H - 3; ++i) { + dst[i][0] = dst[i][1] = dst[i][2] = 1.f; + // I tried hand written SSE code but gcc vectorizes better + for (int j = 3; j < W - 3; ++j) { + const float val = c31 * (src[i - 3][j - 1] + src[i - 3][j + 1] + src[i - 1][j - 3] + src[i - 1][j + 3] + src[i + 1][j - 3] + src[i + 1][j + 3] + src[i + 3][j - 1] + src[i + 3][j + 1]) + + c30 * (src[i - 3][j] + src[i][j - 3] + src[i][j + 3] + src[i + 3][j]) + + c22 * (src[i - 2][j - 2] + src[i - 2][j + 2] + src[i + 2][j - 2] + src[i + 2][j + 2]) + + c21 * (src[i - 2][j - 1] + src[i - 2][j + 1] * c21 + src[i - 1][j - 2] + src[i - 1][j + 2] + src[i + 1][j - 2] + src[i + 1][j + 2] + src[i + 2][j - 1] + src[i + 2][j + 1]) + + c20 * (src[i - 2][j] + src[i][j - 2] + src[i][j + 2] + src[i + 2][j]) + + c11 * (src[i - 1][j - 1] + src[i - 1][j + 1] + src[i + 1][j - 1] + src[i + 1][j + 1]) + + c10 * (src[i - 1][j] + src[i][j - 1] + src[i][j + 1] + src[i + 1][j]) + + c00 * src[i][j]; + + dst[i][j] = divBuffer[i][j] / std::max(val, 0.00001f); + } + dst[i][W - 3] = dst[i][W - 2] = dst[i][W - 1] = 1.f; + } + + // first and last rows + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < W; ++j) { + dst[i][j] = 1.f; + } + } + for (int i = H - 3 ; i < H; ++i) { + for (int j = 0; j < W; ++j) { + dst[i][j] = 1.f; + } + } +} + +inline void gauss3x3mult(float** RESTRICT src, float** RESTRICT dst, const int W, const int H, const float kernel[3][3]) +{ + const float c11 = kernel[0][0]; + const float c10 = kernel[0][1]; + const float c00 = kernel[1][1]; + + for (int i = 1; i < H - 1; i++) { + for (int j = 1; j < W - 1; j++) { + const float val = c11 * (src[i - 1][j - 1] + src[i - 1][j + 1] + src[i + 1][j - 1] + src[i + 1][j + 1]) + + c10 * (src[i - 1][j] + src[i][j - 1] + src[i][j + 1] + src[i + 1][j]) + + c00 * src[i][j]; + dst[i][j] *= val; + } + } + +} + +inline void gauss5x5mult (float** RESTRICT src, float** RESTRICT dst, const int W, const int H, const float kernel[5][5]) +{ + + const float c21 = kernel[0][1]; + const float c20 = kernel[0][2]; + const float c11 = kernel[1][1]; + const float c10 = kernel[1][2]; + const float c00 = kernel[2][2]; + + for (int i = 2; i < H - 2; ++i) { + // I tried hand written SSE code but gcc vectorizes better + for (int j = 2; j < W - 2; ++j) { + const float val = c21 * (src[i - 2][j - 1] + src[i - 2][j + 1] + src[i - 1][j - 2] + src[i - 1][j + 2] + src[i + 1][j - 2] + src[i + 1][j + 2] + src[i + 2][j - 1] + src[i + 2][j + 1]) + + c20 * (src[i - 2][j] + src[i][j - 2] + src[i][j + 2] + src[i + 2][j]) + + c11 * (src[i - 1][j - 1] + src[i - 1][j + 1] + src[i + 1][j - 1] + src[i + 1][j + 1]) + + c10 * (src[i - 1][j] + src[i][j - 1] + src[i][j + 1] + src[i + 1][j]) + + c00 * src[i][j]; + + dst[i][j] *= val; + } + } +} + +inline void gauss7x7mult(float** RESTRICT src, float** RESTRICT dst, const int W, const int H, const float kernel[7][7]) +{ + + const float c31 = kernel[0][2]; + const float c30 = kernel[0][3]; + const float c22 = kernel[1][1]; + const float c21 = kernel[1][2]; + const float c20 = kernel[1][3]; + const float c11 = kernel[2][2]; + const float c10 = kernel[2][3]; + const float c00 = kernel[3][3]; + + for (int i = 3; i < H - 3; ++i) { + // I tried hand written SSE code but gcc vectorizes better + for (int j = 3; j < W - 3; ++j) { + const float val = c31 * (src[i - 3][j - 1] + src[i - 3][j + 1] + src[i - 1][j - 3] + src[i - 1][j + 3] + src[i + 1][j - 3] + src[i + 1][j + 3] + src[i + 3][j - 1] + src[i + 3][j + 1]) + + c30 * (src[i - 3][j] + src[i][j - 3] + src[i][j + 3] + src[i + 3][j]) + + c22 * (src[i - 2][j - 2] + src[i - 2][j + 2] + src[i + 2][j - 2] + src[i + 2][j + 2]) + + c21 * (src[i - 2][j - 1] + src[i - 2][j + 1] * c21 + src[i - 1][j - 2] + src[i - 1][j + 2] + src[i + 1][j - 2] + src[i + 1][j + 2] + src[i + 2][j - 1] + src[i + 2][j + 1]) + + c20 * (src[i - 2][j] + src[i][j - 2] + src[i][j + 2] + src[i + 2][j]) + + c11 * (src[i - 1][j - 1] + src[i - 1][j + 1] + src[i + 1][j - 1] + src[i + 1][j + 1]) + + c10 * (src[i - 1][j] + src[i][j - 1] + src[i][j + 1] + src[i + 1][j]) + + c00 * src[i][j]; + + dst[i][j] *= val; + } + } +} + +void buildClipMaskBayer(const float * const *rawData, int W, int H, float** clipMask, const float whites[2][2]) +{ + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) +#endif + for (int row = 0; row < H; ++row) { + for (int col = 0; col < W; ++col) { + clipMask[row][col] = 1.f; + } + } +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) +#endif + for (int row = 2; row < H - 2; ++row) { + float clip0 = whites[row & 1][0]; + float clip1 = whites[row & 1][1]; + for (int col = 2; col < W - 2; ++col) { + if (rawData[row][col] >= clip0) { + clipMask[row - 2][col - 1] = clipMask[row - 2][col] = clipMask[row - 2][col + 1] = 0.f; + clipMask[row - 1][col - 2] = clipMask[row - 1][col - 1] = clipMask[row - 1][col] = clipMask[row - 1][col + 1] = clipMask[row - 1][col + 2] = 0.f; + clipMask[row][col - 2] = clipMask[row][col - 1] = clipMask[row][col] = clipMask[row][col + 1] = clipMask[row][col + 2] = 0.f; + clipMask[row + 1][col - 2] = clipMask[row + 1][col - 1] = clipMask[row + 1][col] = clipMask[row + 1][col + 1] = clipMask[row + 1][col + 2] = 0.f; + clipMask[row + 2][col - 1] = clipMask[row + 2][col] = clipMask[row + 2][col + 1] = 0.f; + } + std::swap(clip0, clip1); + } + } +} + +void buildClipMaskXtrans(const float * const *rawData, int W, int H, float** clipMask, const float whites[6][6]) +{ + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) +#endif + for (int row = 0; row < H; ++row) { + for (int col = 0; col < W; ++col) { + clipMask[row][col] = 1.f; + } + } + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) +#endif + for (int row = 2; row < H - 2; ++row) { + for (int col = 2; col < W - 2; ++col) { + const float clip = whites[row % 6][col % 6]; + if (rawData[row][col] >= clip) { + clipMask[row - 2][col - 1] = clipMask[row - 2][col] = clipMask[row - 2][col + 1] = 0.f; + clipMask[row - 1][col - 2] = clipMask[row - 1][col - 1] = clipMask[row - 1][col] = clipMask[row - 1][col + 1] = clipMask[row - 1][col + 2] = 0.f; + clipMask[row][col - 2] = clipMask[row][col - 1] = clipMask[row][col] = clipMask[row][col + 1] = clipMask[row][col + 2] = 0.f; + clipMask[row + 1][col - 2] = clipMask[row + 1][col - 1] = clipMask[row + 1][col] = clipMask[row + 1][col + 1] = clipMask[row + 1][col + 2] = 0.f; + clipMask[row + 2][col - 1] = clipMask[row + 2][col] = clipMask[row + 2][col + 1] = 0.f; + } + } + } +} + +void buildClipMaskMono(const float * const *rawData, int W, int H, float** clipMask, float white) +{ + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) +#endif + for (int row = 0; row < H; ++row) { + for (int col = 0; col < W; ++col) { + clipMask[row][col] = 1.f; + } + } + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) +#endif + for (int row = 2; row < H - 2; ++row) { + for (int col = 2; col < W - 2; ++col) { + if (rawData[row][col] >= white) { + clipMask[row - 2][col - 1] = clipMask[row - 2][col] = clipMask[row - 2][col + 1] = 0.f; + clipMask[row - 1][col - 2] = clipMask[row - 1][col - 1] = clipMask[row - 1][col] = clipMask[row - 1][col + 1] = clipMask[row - 1][col + 2] = 0.f; + clipMask[row][col - 2] = clipMask[row][col - 1] = clipMask[row][col] = clipMask[row][col + 1] = clipMask[row][col + 2] = 0.f; + clipMask[row + 1][col - 2] = clipMask[row + 1][col - 1] = clipMask[row + 1][col] = clipMask[row + 1][col + 1] = clipMask[row + 1][col + 2] = 0.f; + clipMask[row + 2][col - 1] = clipMask[row + 2][col] = clipMask[row + 2][col + 1] = 0.f; + } + } + } +} + +float calcRadiusBayer(const float * const *rawData, int W, int H, float lowerLimit, float upperLimit, const unsigned int fc[2]) +{ + + float maxRatio = 1.f; +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxRatio) schedule(dynamic, 16) +#endif + for (int row = 4; row < H - 4; ++row) { + for (int col = 5 + (fc[row & 1] & 1); col < W - 4; col += 2) { + const float val00 = rawData[row][col]; + if (val00 > 0.f) { + const float val1m1 = rawData[row + 1][col - 1]; + const float val1p1 = rawData[row + 1][col + 1]; + const float maxVal0 = std::max(val00, val1m1); + if (val1m1 > 0.f && maxVal0 > lowerLimit) { + const float minVal = std::min(val00, val1m1); + if (UNLIKELY(maxVal0 > maxRatio * minVal)) { + bool clipped = false; + if (maxVal0 == val00) { // check for influence by clipped green in neighborhood + if (rtengine::max(rawData[row - 1][col - 1], rawData[row - 1][col + 1], val1p1) >= upperLimit) { + clipped = true; + } + } else { // check for influence by clipped green in neighborhood + if (rtengine::max(rawData[row][col - 2], val00, rawData[row + 2][col - 2], rawData[row + 2][col]) >= upperLimit) { + clipped = true; + } + } + if (!clipped) { + maxRatio = maxVal0 / minVal; + } + } + } + const float maxVal1 = std::max(val00, val1p1); + if (val1p1 > 0.f && maxVal1 > lowerLimit) { + const float minVal = std::min(val00, val1p1); + if (UNLIKELY(maxVal1 > maxRatio * minVal)) { + if (maxVal1 == val00) { // check for influence by clipped green in neighborhood + if (rtengine::max(rawData[row - 1][col - 1], rawData[row - 1][col + 1], val1p1) >= upperLimit) { + continue; + } + } else { // check for influence by clipped green in neighborhood + if (rtengine::max(val00, rawData[row][col + 2], rawData[row + 2][col], rawData[row + 2][col + 2]) >= upperLimit) { + continue; + } + } + maxRatio = maxVal1 / minVal; + } + } + } + } + } + return std::sqrt((1.f / (std::log(1.f / maxRatio) / 2.f)) / -2.f); +} + +float calcRadiusXtrans(const float * const *rawData, int W, int H, float lowerLimit, float upperLimit, unsigned int starty, unsigned int startx) +{ + + float maxRatio = 1.f; +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxRatio) schedule(dynamic, 16) +#endif + for (int row = starty + 3; row < H - 4; row += 3) { + for (int col = startx + 3; col < W - 4; col += 3) { + const float valtl = rawData[row][col]; + const float valtr = rawData[row][col + 1]; + const float valbl = rawData[row + 1][col]; + const float valbr = rawData[row + 1][col + 1]; + if (valtl > 1.f) { + const float maxValtltr = std::max(valtl, valtr); + if (valtr > 1.f && maxValtltr > lowerLimit) { + const float minVal = std::min(valtl, valtr); + if (UNLIKELY(maxValtltr > maxRatio * minVal)) { + bool clipped = false; + if (maxValtltr == valtl) { // check for influence by clipped green in neighborhood + if (rtengine::max(rawData[row - 1][col - 1], valtr, valbl, valbr) >= upperLimit) { + clipped = true; + } + } else { // check for influence by clipped green in neighborhood + if (rtengine::max(rawData[row - 1][col + 2], valtl, valbl, valbr) >= upperLimit) { + clipped = true; + } + } + if (!clipped) { + maxRatio = maxValtltr / minVal; + } + } + } + const float maxValtlbl = std::max(valtl, valbl); + if (valbl > 1.f && maxValtlbl > lowerLimit) { + const float minVal = std::min(valtl, valbl); + if (UNLIKELY(maxValtlbl > maxRatio * minVal)) { + bool clipped = false; + if (maxValtlbl == valtl) { // check for influence by clipped green in neighborhood + if (rtengine::max(rawData[row - 1][col - 1], valtr, valbl, valbr) >= upperLimit) { + clipped = true; + } + } else { // check for influence by clipped green in neighborhood + if (rtengine::max(valtl, valtr, rawData[row + 2][col - 1], valbr) >= upperLimit) { + clipped = true; + } + } + if (!clipped) { + maxRatio = maxValtlbl / minVal; + } + } + } + } + if (valbr > 1.f) { + const float maxValblbr = std::max(valbl, valbr); + if (valbl > 1.f && maxValblbr > lowerLimit) { + const float minVal = std::min(valbl, valbr); + if (UNLIKELY(maxValblbr > maxRatio * minVal)) { + bool clipped = false; + if (maxValblbr == valbr) { // check for influence by clipped green in neighborhood + if (rtengine::max(valtl, valtr, valbl, rawData[row + 2][col + 2]) >= upperLimit) { + clipped = true; + } + } else { // check for influence by clipped green in neighborhood + if (rtengine::max(valtl, valtr, rawData[row + 2][col - 1], valbr) >= upperLimit) { + clipped = true; + } + } + if (!clipped) { + maxRatio = maxValblbr / minVal; + } + } + } + const float maxValtrbr = std::max(valtr, valbr); + if (valtr > 1.f && maxValtrbr > lowerLimit) { + const float minVal = std::min(valtr, valbr); + if (UNLIKELY(maxValtrbr > maxRatio * minVal)) { + if (maxValtrbr == valbr) { // check for influence by clipped green in neighborhood + if (rtengine::max(valtl, valtr, valbl, rawData[row + 2][col + 2]) >= upperLimit) { + continue; + } + } else { // check for influence by clipped green in neighborhood + if (rtengine::max(rawData[row - 1][col + 2], valtl, valbl, valbr) >= upperLimit) { + continue; + } + } + maxRatio = maxValtrbr / minVal; + } + } + } + } + } + return std::sqrt((1.f / (std::log(1.f / maxRatio))) / -2.f); +} +void CaptureDeconvSharpening (float** luminance, float** oldLuminance, const float * const * blend, int W, int H, double sigma, double sigmaCornerOffset, int iterations, rtengine::ProgressListener* plistener, double startVal, double endVal) +{ +BENCHFUN + const bool is5x5 = (sigma <= 0.84 && sigmaCornerOffset == 0.0); + const bool is3x3 = (sigma < 0.6 && sigmaCornerOffset == 0.0); + float kernel7[7][7]; + float kernel5[5][5]; + float kernel3[3][3]; + if (is3x3) { + compute3x3kernel(sigma, kernel3); + } else if (is5x5) { + compute5x5kernel(sigma, kernel5); + } else { + compute7x7kernel(sigma, kernel7); + } + + constexpr int tileSize = 194; + constexpr int border = 5; + constexpr int fullTileSize = tileSize + 2 * border; + const float maxRadius = std::min(1.15f, sigma + sigmaCornerOffset); + const float maxDistance = sqrt(rtengine::SQR(W * 0.5f) + rtengine::SQR(H * 0.5f)); + const float distanceFactor = (maxRadius - sigma) / maxDistance; + + double progress = startVal; + const double progressStep = (endVal - startVal) * rtengine::SQR(tileSize) / (W * H); +#ifdef _OPENMP + #pragma omp parallel +#endif + { + int progresscounter = 0; + array2D tmpIThr(fullTileSize, fullTileSize); + array2D tmpThr(fullTileSize, fullTileSize); + array2D lumThr(fullTileSize, fullTileSize); +#pragma omp for schedule(dynamic,2) collapse(2) + for (int i = border; i < H - border; i+= tileSize) { + for(int j = border; j < W - border; j+= tileSize) { + const bool endOfCol = (i + tileSize + border) >= H; + const bool endOfRow = (j + tileSize + border) >= W; + // fill tiles + if (endOfRow || endOfCol) { + // special handling for small tiles at end of row or column + for (int k = 0, ii = endOfCol ? H - fullTileSize : i; k < fullTileSize; ++k, ++ii) { + for (int l = 0, jj = endOfRow ? W - fullTileSize : j; l < fullTileSize; ++l, ++jj) { + tmpIThr[k][l] = oldLuminance[ii - border][jj - border]; + lumThr[k][l] = oldLuminance[ii - border][jj - border]; + } + } + } else { + for (int ii = i; ii < i + fullTileSize; ++ii) { + for (int jj = j; jj < j + fullTileSize; ++jj) { + tmpIThr[ii - i][jj - j] = oldLuminance[ii - border][jj - border]; + lumThr[ii - i][jj - j] = oldLuminance[ii - border][jj - border]; + } + } + } + if (is3x3) { + for (int k = 0; k < iterations; ++k) { + // apply 3x3 gaussian blur and divide luminance by result of gaussian blur + gauss3x3div(tmpIThr, tmpThr, lumThr, fullTileSize, fullTileSize, kernel3); + gauss3x3mult(tmpThr, tmpIThr, fullTileSize, fullTileSize, kernel3); + } + } else if (is5x5) { + for (int k = 0; k < iterations; ++k) { + // apply 5x5 gaussian blur and divide luminance by result of gaussian blur + gauss5x5div(tmpIThr, tmpThr, lumThr, fullTileSize, fullTileSize, kernel5); + gauss5x5mult(tmpThr, tmpIThr, fullTileSize, fullTileSize, kernel5); + } + } else { + if (sigmaCornerOffset > 0.0) { + float lkernel7[7][7]; + const float distance = sqrt(rtengine::SQR(i + tileSize / 2 - H / 2) + rtengine::SQR(j + tileSize / 2 - W / 2)); + compute7x7kernel(sigma + distanceFactor * distance, lkernel7); + for (int k = 0; k < iterations - 1; ++k) { + // apply 7x7 gaussian blur and divide luminance by result of gaussian blur + gauss7x7div(tmpIThr, tmpThr, lumThr, fullTileSize, fullTileSize, lkernel7); + gauss7x7mult(tmpThr, tmpIThr, fullTileSize, fullTileSize, lkernel7); + } + } else { + for (int k = 0; k < iterations; ++k) { + // apply 7x7 gaussian blur and divide luminance by result of gaussian blur + gauss7x7div(tmpIThr, tmpThr, lumThr, fullTileSize, fullTileSize, kernel7); + gauss7x7mult(tmpThr, tmpIThr, fullTileSize, fullTileSize, kernel7); + } + } + } + if (endOfRow || endOfCol) { + // special handling for small tiles at end of row or column + for (int k = border, ii = endOfCol ? H - fullTileSize - border : i - border; k < fullTileSize - border; ++k) { + for (int l = border, jj = endOfRow ? W - fullTileSize - border : j - border; l < fullTileSize - border; ++l) { + luminance[ii + k][jj + l] = rtengine::intp(blend[ii + k][jj + l], max(tmpIThr[k][l], 0.0f), luminance[ii + k][jj + l]); + } + } + } else { + for (int ii = border; ii < fullTileSize - border; ++ii) { + for (int jj = border; jj < fullTileSize - border; ++jj) { + luminance[i + ii - border][j + jj - border] = rtengine::intp(blend[i + ii - border][j + jj - border], max(tmpIThr[ii][jj], 0.0f), luminance[i + ii - border][j + jj - border]); + } + } + } + if (plistener) { + if (++progresscounter % 16 == 0) { +#ifdef _OPENMP + #pragma omp critical(csprogress) +#endif + { + progress += 16.0 * progressStep; + progress = rtengine::min(progress, endVal); + plistener->setProgress(progress); + } + } + } + } + } + } +} + +} + +namespace rtengine +{ + +void RawImageSource::captureSharpening(const procparams::CaptureSharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold, double &radius) { + + if (plistener) { + plistener->setProgressStr(M("TP_PDSHARPENING_LABEL")); + plistener->setProgress(0.0); + } +BENCHFUN + const float xyz_rgb[3][3] = { // XYZ from RGB + { 0.412453, 0.357580, 0.180423 }, + { 0.212671, 0.715160, 0.072169 }, + { 0.019334, 0.119193, 0.950227 } + }; + + float contrast = conrastThreshold / 100.f; + + const float clipVal = (ri->get_white(1) - ri->get_cblack(1)) * scale_mul[1]; + + array2D& redVals = redCache ? *redCache : red; + array2D& greenVals = greenCache ? *greenCache : green; + array2D& blueVals = blueCache ? *blueCache : blue; + + array2D clipMask(W, H); + constexpr float clipLimit = 0.95f; + if (ri->getSensorType() == ST_BAYER) { + const float whites[2][2] = { + {(ri->get_white(FC(0,0)) - c_black[FC(0,0)]) * scale_mul[FC(0,0)] * clipLimit, (ri->get_white(FC(0,1)) - c_black[FC(0,1)]) * scale_mul[FC(0,1)] * clipLimit}, + {(ri->get_white(FC(1,0)) - c_black[FC(1,0)]) * scale_mul[FC(1,0)] * clipLimit, (ri->get_white(FC(1,1)) - c_black[FC(1,1)]) * scale_mul[FC(1,1)] * clipLimit} + }; + buildClipMaskBayer(rawData, W, H, clipMask, whites); + const unsigned int fc[2] = {FC(0,0), FC(1,0)}; + if (sharpeningParams.autoRadius) { + radius = calcRadiusBayer(rawData, W, H, 1000.f, clipVal, fc); + } + } else if (ri->getSensorType() == ST_FUJI_XTRANS) { + float whites[6][6]; + for (int i = 0; i < 6; ++i) { + for (int j = 0; j < 6; ++j) { + const auto color = ri->XTRANSFC(i, j); + whites[i][j] = (ri->get_white(color) - c_black[color]) * scale_mul[color] * clipLimit; + } + } + buildClipMaskXtrans(rawData, W, H, clipMask, whites); + bool found = false; + int i, j; + for (i = 6; i < 12 && !found; ++i) { + for (j = 6; j < 12 && !found; ++j) { + if (ri->XTRANSFC(i, j) == 1) { + if (ri->XTRANSFC(i, j - 1) != ri->XTRANSFC(i, j + 1)) { + if (ri->XTRANSFC(i - 1, j) != 1) { + if (ri->XTRANSFC(i, j - 1) != 1) { + found = true; + break; + } + } + } + } + } + } + if (sharpeningParams.autoRadius) { + radius = calcRadiusXtrans(rawData, W, H, 1000.f, clipVal, i, j); + } + + } else if (ri->get_colors() == 1) { + buildClipMaskMono(rawData, W, H, clipMask, (ri->get_white(0) - c_black[0]) * scale_mul[0] * clipLimit); + if (sharpeningParams.autoRadius) { + const unsigned int fc[2] = {0, 0}; + radius = calcRadiusBayer(rawData, W, H, 1000.f, clipVal, fc); + } + } + + if (showMask) { + array2D& L = blue; // blue will be overridden anyway => we can use its buffer to store L +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H; ++i) { + Color::RGB2L(redVals[i], greenVals[i], blueVals[i], L[i], xyz_rgb, W); + } + if (plistener) { + plistener->setProgress(0.1); + } + + array2D& blend = red; // red will be overridden anyway => we can use its buffer to store the blend mask + buildBlendMask(L, blend, W, H, contrast, 1.f, sharpeningParams.autoContrast, clipMask); + if (plistener) { + plistener->setProgress(0.2); + } + conrastThreshold = contrast * 100.f; +#ifdef _OPENMP + #pragma omp parallel for +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + red[i][j] = green[i][j] = blue[i][j] = blend[i][j] * 16384.f; + } + } + if (plistener) { + plistener->setProgress(1.0); + } + return; + } + + array2D* Lbuffer = nullptr; + if (!redCache) { + Lbuffer = new array2D(W, H); + } + + array2D* YOldbuffer = nullptr; + if (!greenCache) { + YOldbuffer = new array2D(W, H); + } + + array2D* YNewbuffer = nullptr; + if (!blueCache) { + YNewbuffer = new array2D(W, H); + } + array2D& L = Lbuffer ? *Lbuffer : red; + array2D& YOld = YOldbuffer ? * YOldbuffer : green; + array2D& YNew = YNewbuffer ? * YNewbuffer : blue; + const float gamma = sharpeningParams.gamma; + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) +#endif + for (int i = 0; i < H; ++i) { + Color::RGB2L(redVals[i], greenVals[i], blueVals[i], L[i], xyz_rgb, W); + Color::RGB2Y(redVals[i], greenVals[i], blueVals[i], YOld[i], YNew[i], gamma, W); + } + if (plistener) { + plistener->setProgress(0.1); + } + // calculate contrast based blend factors to reduce sharpening in regions with low contrast + array2D& blend = clipMask; // we can share blend and clipMask buffer here + buildBlendMask(L, blend, W, H, contrast, 1.f, sharpeningParams.autoContrast, clipMask); + if (plistener) { + plistener->setProgress(0.2); + } + conrastThreshold = contrast * 100.f; + + CaptureDeconvSharpening(YNew, YOld, blend, W, H, radius, sharpeningParams.deconvradiusOffset, sharpeningParams.deconviter, plistener, 0.2, 0.9); + if (plistener) { + plistener->setProgress(0.9); + } +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) +#endif + for (int i = 0; i < H; ++i) { + int j = 0; +#ifdef __SSE2__ + const vfloat gammav = F2V(gamma); + for (; j < W - 3; j += 4) { + const vfloat factor = pow_F(vmaxf(LVFU(YNew[i][j]), ZEROV) / vmaxf(LVFU(YOld[i][j]), F2V(0.00001f)), gammav); + STVFU(red[i][j], LVFU(redVals[i][j]) * factor); + STVFU(green[i][j], LVFU(greenVals[i][j]) * factor); + STVFU(blue[i][j], LVFU(blueVals[i][j]) * factor); + } + +#endif + for (; j < W; ++j) { + const float factor = pow_F(std::max(YNew[i][j], 0.f) / std::max(YOld[i][j], 0.00001f), gamma); + red[i][j] = redVals[i][j] * factor; + green[i][j] = greenVals[i][j] * factor; + blue[i][j] = blueVals[i][j] * factor; + } + } + + delete Lbuffer; + delete YOldbuffer; + delete YNewbuffer; + if (plistener) { + plistener->setProgress(1.0); + } +} + +} /* namespace */ diff --git a/rtengine/cfa_linedn_RT.cc b/rtengine/cfa_linedn_RT.cc index b5d171034..5f6e46f8f 100644 --- a/rtengine/cfa_linedn_RT.cc +++ b/rtengine/cfa_linedn_RT.cc @@ -18,7 +18,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// @@ -54,15 +54,15 @@ void RawImageSource::CLASS cfa_linedn(float noise, bool horizontal, bool vertica // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + double progress = 0.0; if (plistener) { - plistener->setProgressStr ("PROGRESSBAR_LINEDENOISE"); - plistener->setProgress (0.0); + plistener->setProgressStr("PROGRESSBAR_LINEDENOISE"); + plistener->setProgress(progress); } // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% float noisevar = SQR(3 * noise * 65535); // _noise_ (as a fraction of saturation) is input to the algorithm float noisevarm4 = 4.0f * noisevar; - volatile double progress = 0.0; float* RawDataTmp = (float*)malloc( width * height * sizeof(float)); #ifdef _OPENMP #pragma omp parallel diff --git a/rtengine/ciecam02.cc b/rtengine/ciecam02.cc index 86b67e000..dfef273d6 100644 --- a/rtengine/ciecam02.cc +++ b/rtengine/ciecam02.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "ciecam02.h" #include "rtengine.h" diff --git a/rtengine/ciecam02.h b/rtengine/ciecam02.h index 68763b965..fea35ab12 100644 --- a/rtengine/ciecam02.h +++ b/rtengine/ciecam02.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CIECAM02_ #define _CIECAM02_ diff --git a/rtengine/cieimage.h b/rtengine/cieimage.h index 23b080ae3..660d40e78 100644 --- a/rtengine/cieimage.h +++ b/rtengine/cieimage.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CIEIMAGE_H_ #define _CIEIMAGE_H_ diff --git a/rtengine/color.cc b/rtengine/color.cc index 3f2a75788..7a91f0073 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with RawTherapee. If not, see . +* along with RawTherapee. If not, see . */ #include "rtengine.h" @@ -1835,21 +1835,21 @@ void Color::RGB2L(float *R, float *G, float *B, float *L, const float wp[3][3], { #ifdef __SSE2__ - vfloat minvalfv = F2V(0.f); - vfloat maxvalfv = F2V(MAXVALF); + const vfloat maxvalfv = F2V(MAXVALF); + const vfloat rmv = F2V(wp[1][0]); + const vfloat gmv = F2V(wp[1][1]); + const vfloat bmv = F2V(wp[1][2]); #endif int i = 0; #ifdef __SSE2__ - for(;i < width - 3; i+=4) { + for(; i < width - 3; i+=4) { const vfloat rv = LVFU(R[i]); const vfloat gv = LVFU(G[i]); const vfloat bv = LVFU(B[i]); - const vfloat yv = F2V(wp[1][0]) * rv + F2V(wp[1][1]) * gv + F2V(wp[1][2]) * bv; + const vfloat yv = rmv * rv + gmv * gv + bmv * bv; - vmask maxMask = vmaskf_gt(yv, maxvalfv); - vmask minMask = vmaskf_lt(yv, minvalfv); - if (_mm_movemask_ps((vfloat)vorm(maxMask, minMask))) { + if (_mm_movemask_ps((vfloat)vorm(vmaskf_gt(yv, maxvalfv), vmaskf_lt(yv, ZEROV)))) { // take slower code path for all 4 pixels if one of the values is > MAXVALF. Still faster than non SSE2 version for(int k = 0; k < 4; ++k) { float y = yv[k]; @@ -1860,7 +1860,7 @@ void Color::RGB2L(float *R, float *G, float *B, float *L, const float wp[3][3], } } #endif - for(;i < width; ++i) { + for(; i < width; ++i) { const float rv = R[i]; const float gv = G[i]; const float bv = B[i]; @@ -2016,45 +2016,6 @@ void Color::Lch2Luv(float c, float h, float &u, float &v) v = c * sincosval.y; } -// NOT TESTED -void Color::XYZ2Luv (float X, float Y, float Z, float &L, float &u, float &v) -{ - - X /= 65535.f; - Y /= 65535.f; - Z /= 65535.f; - - if (Y > float(eps)) { - L = 116.f * std::cbrt(Y) - 16.f; - } else { - L = float(kappa) * Y; - } - - u = 13.f * L * float(u0); - v = 13.f * L * float(v0); -} - -// NOT TESTED -void Color::Luv2XYZ (float L, float u, float v, float &X, float &Y, float &Z) -{ - if (L > float(epskap)) { - float t = (L + 16.f) / 116.f; - Y = t * t * t; - } else { - Y = L / float(kappa); - } - - float a = ((52.f * L) / (u + 13.f * L * float(u0)) - 1.f) / 3.f; - float d = Y * (((39 * L) / (v + 13 * float(v0))) - 5.f); - float b = -5.f * Y; - X = (d - b) / (a + 1.f / 3.f); - - Z = X * a + b; - - X *= 65535.f; - Y *= 65535.f; - Z *= 65535.f; -} /* * Gamut mapping algorithm diff --git a/rtengine/color.h b/rtengine/color.h index fb4eea458..1031ca150 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once @@ -210,6 +210,11 @@ public: return r * workingspace[1][0] + g * workingspace[1][1] + b * workingspace[1][2]; } + static vfloat rgbLuminance(vfloat r, vfloat g, vfloat b, const vfloat workingspace[3]) + { + return r * workingspace[0] + g * workingspace[1] + b * workingspace[2]; + } + /** * @brief Convert red/green/blue to L*a*b * @brief Convert red/green/blue to hue/saturation/luminance @@ -240,20 +245,20 @@ public: static inline void rgb2slfloat(float r, float g, float b, float &s, float &l) { - float m = min(r, g, b); - float M = max(r, g, b); - float C = M - m; + float minVal = min(r, g, b); + float maxVal = max(r, g, b); + float C = maxVal - minVal; - l = (M + m) * 7.6295109e-6f; // (0.5f / 65535.f) + l = (maxVal + minVal) * 7.6295109e-6f; // (0.5f / 65535.f) if (C < 0.65535f) { // 0.00001f * 65535.f s = 0.f; } else { if (l <= 0.5f) { - s = C / (M + m); + s = C / (maxVal + minVal); } else { - s = C / (131070.f - (M + m)); // 131070.f = 2.f * 65535.f + s = C / (131070.f - (maxVal + minVal)); // 131070.f = 2.f * 65535.f } } } @@ -261,11 +266,11 @@ public: static inline void rgb2hslfloat(float r, float g, float b, float &h, float &s, float &l) { - float m = min(r, g, b); - float M = max(r, g, b); - float C = M - m; + float minVal = min(r, g, b); + float maxVal = max(r, g, b); + float C = maxVal - minVal; - l = (M + m) * 7.6295109e-6f; // (0.5f / 65535.f) + l = (maxVal + minVal) * 7.6295109e-6f; // (0.5f / 65535.f) if (C < 0.65535f) { // 0.00001f * 65535.f h = 0.f; @@ -273,14 +278,14 @@ public: } else { if (l <= 0.5f) { - s = C / (M + m); + s = C / (maxVal + minVal); } else { - s = C / (131070.f - (M + m)); // 131070.f = 2.f * 65535.f + s = C / (131070.f - (maxVal + minVal)); // 131070.f = 2.f * 65535.f } - if ( r == M ) { + if ( r == maxVal ) { h = (g - b); - } else if ( g == M ) { + } else if ( g == maxVal ) { h = (2.f * C) + (b - r); } else { h = (4.f * C) + (r - g); @@ -686,32 +691,6 @@ public: static void Lch2Luv(float c, float h, float &u, float &v); - /** - * @brief Convert the XYZ values to Luv values - * Warning: this method has never been used/tested so far - * @param x X coordinate [0 ; 65535] ; can be negative or superior to 65535 - * @param y Y coordinate [0 ; 65535] ; can be negative or superior to 65535 - * @param z Z coordinate [0 ; 65535] ; can be negative or superior to 65535 - * @param L 'L' channel [0 ; 32768] (return value) - * @param u 'u' channel [-42000 ; 42000] ; can be more than 42000 (return value) - * @param v 'v' channel [-42000 ; 42000] ; can be more than 42000 (return value) - */ - static void XYZ2Luv (float X, float Y, float Z, float &L, float &u, float &v); - - - /** - * @brief Convert the Luv values to XYZ values - * Warning: this method has never been used/tested so far - * @param L 'L' channel [0 ; 32768] - * @param u 'u' channel [-42000 ; 42000] ; can be more than 42000 - * @param v 'v' channel [-42000 ; 42000] ; can be more than 42000 - * @param x X coordinate [0 ; 65535] ; can be negative or superior to 65535 (return value) - * @param y Y coordinate [0 ; 65535] ; can be negative or superior to 65535 (return value) - * @param z Z coordinate [0 ; 65535] ; can be negative or superior to 65535 (return value) - */ - static void Luv2XYZ (float L, float u, float v, float &X, float &Y, float &Z); - - /** * @brief Return "f" in function of CIE's kappa and epsilon constants * @param f f can be fx fy fz where: @@ -1830,6 +1809,31 @@ public: return (hr); } + static inline void RGB2Y(const float* R, const float* G, const float* B, float* Y1, float * Y2, float gamma, int W) { + gamma = 1.f / gamma; + int i = 0; +#ifdef __SSE2__ + const vfloat gammav = F2V(gamma); + const vfloat c1v = F2V(0.2627f); + const vfloat c2v = F2V(0.6780f); + const vfloat c3v = F2V(0.0593f); + for (; i < W - 3; i += 4) { + const vfloat Rv = vmaxf(LVFU(R[i]), ZEROV); + const vfloat Gv = vmaxf(LVFU(G[i]), ZEROV); + const vfloat Bv = vmaxf(LVFU(B[i]), ZEROV); + vfloat yv = pow_F(c1v * Rv + c2v * Gv + c3v * Bv, gammav); + STVFU(Y1[i], yv); + STVFU(Y2[i], yv); + } +#endif + for (; i < W; ++i) { + const float r = std::max(R[i], 0.f); + const float g = std::max(G[i], 0.f); + const float b = std::max(B[i], 0.f); + Y1[i] = Y2[i] = pow_F(0.2627f * r + 0.6780f * g + 0.0593f * b, gamma); + } + } + }; } diff --git a/rtengine/colortemp.cc b/rtengine/colortemp.cc index a7a769d93..3ddbdc28a 100644 --- a/rtengine/colortemp.cc +++ b/rtengine/colortemp.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "colortemp.h" #include "rtengine.h" @@ -1088,11 +1088,11 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, //}; gmul /= green; //printf("rmul=%f gmul=%f bmul=%f\n",rmul, gmul, bmul); - double max = rtengine::max(rmul, gmul, bmul); + double maxRGB = rtengine::max(rmul, gmul, bmul); - rmul /= max; - gmul /= max; - bmul /= max; + rmul /= maxRGB; + gmul /= maxRGB; + bmul /= maxRGB; if(settings->CRI_color != 0) { //activate if CRi_color !=0 @@ -1104,7 +1104,6 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, // and calcul with : blackbody at equivalent temp of lamp // CRI_color-1 = display Lab values of color CRI_color -1 const double whiteD50[3] = {0.9646019585, 1.0, 0.8244507152}; //calculate with this tool : spect 5nm - double CAM02BB00, CAM02BB01, CAM02BB02, CAM02BB10, CAM02BB11, CAM02BB12, CAM02BB20, CAM02BB21, CAM02BB22; //for CIECAT02 double Xchk[50], Ychk[50], Zchk[50]; //50 : I think it's a good limit for number of color : for CRI and Palette double Xcam02[50], Ycam02[50], Zcam02[50]; @@ -1113,9 +1112,6 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, const double epsilon = 0.008856; //Lab double xr[50], yr[50], zr[50]; - double fx[50], fy[50], fz[50]; - double x, y, z; - double Ywb = 1.0; int illum; int numero_color = settings->CRI_color - 1; @@ -1223,6 +1219,9 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, } if (CRI_type) { + double x, y, z; + double Ywb = 1.0; + const double* spect_illum[] = { Daylight5300_spect, Cloudy6200_spect, Shade7600_spect, A2856_spect, FluoF1_spect, FluoF2_spect, FluoF3_spect, FluoF4_spect, FluoF5_spect, FluoF6_spect, FluoF7_spect, FluoF8_spect, FluoF9_spect, FluoF10_spect, FluoF11_spect, @@ -1281,6 +1280,7 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, //calculate Matrix CAM02 : better than Von Kries and Bradford==> for Lamp double adap = 1.0; + double CAM02BB00, CAM02BB01, CAM02BB02, CAM02BB10, CAM02BB11, CAM02BB12, CAM02BB20, CAM02BB21, CAM02BB22; //for CIECAT02 cieCAT02(Xwb, Ywb, Zwb, CAM02BB00, CAM02BB01, CAM02BB02, CAM02BB10, CAM02BB11, CAM02BB12, CAM02BB20, CAM02BB21, CAM02BB22, adap); //here new value of X,Y,Z for lamp with chromatic CAM02 adaptation @@ -1306,6 +1306,7 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, //now conversion to Lab // Lamp + double fx[50], fy[50], fz[50]; for(int i = 0; i < N_c; i++) { xr[i] = Xcam02Lamp[i] / whiteD50[0]; diff --git a/rtengine/colortemp.h b/rtengine/colortemp.h index d529d844e..da83177be 100644 --- a/rtengine/colortemp.h +++ b/rtengine/colortemp.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _COLORTEMP_ #define _COLORTEMP_ diff --git a/rtengine/coord.cc b/rtengine/coord.cc index bf9ee816e..0a73cc29d 100644 --- a/rtengine/coord.cc +++ b/rtengine/coord.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "coord.h" diff --git a/rtengine/coord.h b/rtengine/coord.h index 2f1325434..5f16cf606 100644 --- a/rtengine/coord.h +++ b/rtengine/coord.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __COORD__ diff --git a/rtengine/coord2d.h b/rtengine/coord2d.h index bc030f22e..252219e47 100644 --- a/rtengine/coord2d.h +++ b/rtengine/coord2d.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __COORD2D__ #define __COORD2D__ diff --git a/rtengine/cplx_wavelet_dec.cc b/rtengine/cplx_wavelet_dec.cc index a43a7b8b6..5b3650adc 100644 --- a/rtengine/cplx_wavelet_dec.cc +++ b/rtengine/cplx_wavelet_dec.cc @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * 2010 Ilya Popov * 2012 Emil Martinec diff --git a/rtengine/cplx_wavelet_dec.h b/rtengine/cplx_wavelet_dec.h index ccecef819..91e71fcd5 100644 --- a/rtengine/cplx_wavelet_dec.h +++ b/rtengine/cplx_wavelet_dec.h @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * 2010 Ilya Popov * 2012 Emil Martinec @@ -45,7 +45,6 @@ private: static const int maxlevels = 10;//should be greater than any conceivable order of decimation int lvltot, subsamp; - int numThreads; int m_w, m_h;//dimensions int wavfilt_len, wavfilt_offset; @@ -97,7 +96,7 @@ public: template wavelet_decomposition::wavelet_decomposition(E * src, int width, int height, int maxlvl, int subsampling, int skipcrop, int numThreads, int Daub4Len) - : coeff0(nullptr), memoryAllocationFailed(false), lvltot(0), subsamp(subsampling), numThreads(numThreads), m_w(width), m_h(height) + : coeff0(nullptr), memoryAllocationFailed(false), lvltot(0), subsamp(subsampling), m_w(width), m_h(height) { //initialize wavelet filters diff --git a/rtengine/cplx_wavelet_filter_coeffs.h b/rtengine/cplx_wavelet_filter_coeffs.h index bd333d4b9..6b8255b89 100644 --- a/rtengine/cplx_wavelet_filter_coeffs.h +++ b/rtengine/cplx_wavelet_filter_coeffs.h @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * 2012 Emil Martinec * 2014 Jacques Desmis diff --git a/rtengine/cplx_wavelet_level.h b/rtengine/cplx_wavelet_level.h index cab0d8e3e..4c98addfe 100644 --- a/rtengine/cplx_wavelet_level.h +++ b/rtengine/cplx_wavelet_level.h @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * 2010 Ilya Popov * 2012 Emil Martinec diff --git a/rtengine/curves.cc b/rtengine/curves.cc index f03a43e60..a7e3337c8 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -641,15 +641,15 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou } // gamma correction - float val = Color::gammatab_srgb1[0]; + float val0 = Color::gammatab_srgb1[0]; // apply brightness curve if (brightcurve) { - val = brightcurve->getVal(val); // TODO: getVal(double) is very slow! Optimize with a LUTf + val0 = brightcurve->getVal(val0); // TODO: getVal(double) is very slow! Optimize with a LUTf } // store result in a temporary array - dcurve[0] = LIM01(val); + dcurve[0] = LIM01(val0); for (int i = 1; i < 0x10000; i++) { @@ -1508,10 +1508,10 @@ void ColorGradientCurve::SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3], Color::gamutLchonly(h1, Lr, c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f); #endif L1 = Lr * 327.68f; - float a, b, X, Y, Z; + float La, Lb, X, Y, Z; // converting back to rgb - Color::Lch2Lab(c1, h1, a, b); - Color::Lab2XYZ(L1, a, b, X, Y, Z); + Color::Lch2Lab(c1, h1, La, Lb); + Color::Lab2XYZ(L1, La, Lb, X, Y, Z); lut1[i] = X; lut2[i] = Y; lut3[i] = Z; @@ -1822,12 +1822,12 @@ float PerceptualToneCurve::calculateToneCurveContrastValue() const { // look at midtone slope const float xd = 0.07; - const float tx[] = { 0.30, 0.35, 0.40, 0.45 }; // we only look in the midtone range + const float tx0[] = { 0.30, 0.35, 0.40, 0.45 }; // we only look in the midtone range - for (size_t i = 0; i < sizeof(tx) / sizeof(tx[0]); i++) { - float x0 = tx[i] - xd; + for (size_t i = 0; i < sizeof(tx0) / sizeof(tx0[0]); i++) { + float x0 = tx0[i] - xd; float y0 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x0) * 65535.f] / 65535.f) - k * x0; - float x1 = tx[i] + xd; + float x1 = tx0[i] + xd; float y1 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x1) * 65535.f] / 65535.f) - k * x1; float slope = 1.0 + (y1 - y0) / (x1 - x0); @@ -1967,15 +1967,15 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float saturated_scale_factor = 1.f; } else if (C < hilim) { // S-curve transition between low and high limit - float x = (C - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim + float cx = (C - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim - if (x < 0.5f) { - x = 2.f * SQR(x); + if (cx < 0.5f) { + cx = 2.f * SQR(cx); } else { - x = 1.f - 2.f * SQR(1 - x); + cx = 1.f - 2.f * SQR(1.f - cx); } - saturated_scale_factor = (1.f - x) + saturated_scale_factor * x; + saturated_scale_factor = (1.f - cx) + saturated_scale_factor * cx; } else { // do nothing, high saturation color, keep scale factor } @@ -1995,15 +1995,15 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float // do nothing, keep scale factor } else if (nL < hilim) { // S-curve transition - float x = (nL - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim + float cx = (nL - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim - if (x < 0.5f) { - x = 2.f * SQR(x); + if (cx < 0.5f) { + cx = 2.f * SQR(cx); } else { - x = 1.f - 2.f * SQR(1 - x); + cx = 1.f - 2.f * SQR(1 - cx); } - dark_scale_factor = dark_scale_factor * (1.0f - x) + x; + dark_scale_factor = dark_scale_factor * (1.0f - cx) + cx; } else { dark_scale_factor = 1.f; } @@ -2021,15 +2021,15 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float // do nothing, keep scale factor } else if (J < hilim) { // S-curve transition - float x = (J - lolim) / (hilim - lolim); + float cx = (J - lolim) / (hilim - lolim); - if (x < 0.5f) { - x = 2.f * SQR(x); + if (cx < 0.5f) { + cx = 2.f * SQR(cx); } else { - x = 1.f - 2.f * SQR(1 - x); + cx = 1.f - 2.f * SQR(1 - cx); } - dark_scale_factor = dark_scale_factor * (1.f - x) + x; + dark_scale_factor = dark_scale_factor * (1.f - cx) + cx; } else { dark_scale_factor = 1.f; } @@ -2089,15 +2089,15 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float keep = 1.f; } else if (sat_scale < hilim) { // S-curve transition - float x = (sat_scale - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim + float cx = (sat_scale - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim - if (x < 0.5f) { - x = 2.f * SQR(x); + if (cx < 0.5f) { + cx = 2.f * SQR(cx); } else { - x = 1.f - 2.f * SQR(1 - x); + cx = 1.f - 2.f * SQR(1 - cx); } - keep = (1.f - x) + keep * x; + keep = (1.f - cx) + keep * cx; } else { // do nothing, very high increase, keep minimum amount } diff --git a/rtengine/curves.h b/rtengine/curves.h index deed5d0fe..25272d44c 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __CURVES_H__ #define __CURVES_H__ @@ -31,7 +31,7 @@ #include "../rtgui/mydiagonalcurve.h" #include "color.h" #include "pipettebuffer.h" - +#include "noncopyable.h" #include "LUT.h" #define CURVES_MIN_POLY_POINTS 1000 @@ -468,7 +468,7 @@ protected: void NURBS_set (); public: - DiagonalCurve (const std::vector& points, int ppn = CURVES_MIN_POLY_POINTS); + explicit DiagonalCurve (const std::vector& points, int ppn = CURVES_MIN_POLY_POINTS); ~DiagonalCurve () override; double getVal (double t) const override; @@ -479,7 +479,7 @@ public: }; }; -class FlatCurve : public Curve +class FlatCurve : public Curve, public rtengine::NonCopyable { private: @@ -493,7 +493,7 @@ private: public: - FlatCurve (const std::vector& points, bool isPeriodic = true, int ppn = CURVES_MIN_POLY_POINTS); + explicit FlatCurve (const std::vector& points, bool isPeriodic = true, int ppn = CURVES_MIN_POLY_POINTS); ~FlatCurve () override; double getVal (double t) const override; diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index 614c5a426..f53ff2d4c 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with RawTherapee. If not, see . +* along with RawTherapee. If not, see . */ #include @@ -333,8 +333,6 @@ double xyCoordToTemperature(const std::array& white_xy) // Search for line pair coordinate is between. double last_dt = 0.0; - double last_dv = 0.0; - double last_du = 0.0; for (uint32_t index = 1; index <= 30; ++index) { // Convert slope to delta-u and delta-v, with length 1. @@ -370,23 +368,11 @@ double xyCoordToTemperature(const std::array& white_xy) // Interpolate the temperature. res = 1.0e6 / (temp_table[index - 1].r * f + temp_table[index].r * (1.0 - f)); - - // Find delta from black body point to test coordinate. - uu = u - (temp_table [index - 1].u * f + temp_table [index].u * (1.0 - f)); - vv = v - (temp_table [index - 1].v * f + temp_table [index].v * (1.0 - f)); - // Interpolate vectors along slope. - du = du * (1.0 - f) + last_du * f; - dv = dv * (1.0 - f) + last_dv * f; - len = sqrt (du * du + dv * dv); - du /= len; - dv /= len; break; } // Try next line pair. last_dt = dt; - last_du = du; - last_dv = dv; } return res; @@ -2179,8 +2165,7 @@ void DCPStore::init(const Glib::ustring& rt_profile_dir, bool loadAll) && lastdot <= sname.size() - 4 && !sname.casefold().compare(lastdot, 4, ".dcp") ) { - const Glib::ustring cam_short_name = sname.substr(0, lastdot).uppercase(); - file_std_profiles[cam_short_name] = fname; // They will be loaded and cached on demand + file_std_profiles[sname.substr(0, lastdot).casefold_collate_key()] = fname; // They will be loaded and cached on demand } } else { // Directory @@ -2191,11 +2176,10 @@ void DCPStore::init(const Glib::ustring& rt_profile_dir, bool loadAll) for (const auto& alias : getAliases(rt_profile_dir)) { const Glib::ustring alias_name = Glib::ustring(alias.first).uppercase(); - const Glib::ustring real_name = Glib::ustring(alias.second).uppercase(); - const std::map::const_iterator real = file_std_profiles.find(real_name); + const std::map::const_iterator real = file_std_profiles.find(Glib::ustring(alias.second).casefold_collate_key()); if (real != file_std_profiles.end()) { - file_std_profiles[alias_name] = real->second; + file_std_profiles[alias_name.casefold_collate_key()] = real->second; } } } @@ -2217,19 +2201,19 @@ bool DCPStore::isValidDCPFileName(const Glib::ustring& filename) const DCPProfile* DCPStore::getProfile(const Glib::ustring& filename) const { + const auto key = filename.casefold_collate_key(); MyMutex::MyLock lock(mutex); + const std::map::const_iterator iter = profile_cache.find(key); - const std::map::iterator r = profile_cache.find(filename); - - if (r != profile_cache.end()) { - return r->second; + if (iter != profile_cache.end()) { + return iter->second; } DCPProfile* const res = new DCPProfile(filename); if (res->isValid()) { // Add profile - profile_cache[filename] = res; + profile_cache[key] = res; if (options.rtSettings.verbose) { printf("DCP profile '%s' loaded from disk\n", filename.c_str()); } @@ -2242,13 +2226,9 @@ DCPProfile* DCPStore::getProfile(const Glib::ustring& filename) const DCPProfile* DCPStore::getStdProfile(const Glib::ustring& requested_cam_short_name) const { - const Glib::ustring name = requested_cam_short_name.uppercase(); - - // Warning: do NOT use map.find(), since it does not seem to work reliably here - for (const auto& file_std_profile : file_std_profiles) { - if (file_std_profile.first == name) { - return getProfile(file_std_profile.second); - } + const std::map::const_iterator iter = file_std_profiles.find(requested_cam_short_name.casefold_collate_key()); + if (iter != file_std_profiles.end()) { + return getProfile(iter->second); } // profile not found, looking if we're in loadAll=false mode diff --git a/rtengine/dcp.h b/rtengine/dcp.h index dc6915d26..826f073a5 100644 --- a/rtengine/dcp.h +++ b/rtengine/dcp.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with RawTherapee. If not, see . +* along with RawTherapee. If not, see . */ #pragma once @@ -169,10 +169,10 @@ private: std::vector profileDir; // these contain standard profiles from RT. keys are all in uppercase, file path is value - std::map file_std_profiles; + std::map file_std_profiles; // Maps file name to profile as cache - mutable std::map profile_cache; + mutable std::map profile_cache; }; } diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 280b692e7..ef209118b 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -240,7 +240,7 @@ int CLASS fcol (int row, int col) #ifndef __GLIBC__ char *my_memmem (char *haystack, size_t haystacklen, - char *needle, size_t needlelen) + const char *needle, size_t needlelen) { char *c; for (c = haystack; c <= haystack + haystacklen - needlelen; c++) @@ -2417,59 +2417,78 @@ void CLASS hasselblad_correct() void CLASS hasselblad_load_raw() { - struct jhead jh; - int shot, row, col, *back[5], len[2], diff[12], pred, sh, f, s, c; - unsigned upix, urow, ucol; - ushort *ip; + struct jhead jh; + int *back[5], diff[12]; - if (!ljpeg_start (&jh, 0)) return; - order = 0x4949; - ph1_bithuff_t ph1_bithuff(this, ifp, order); - hb_bits(-1); - back[4] = (int *) calloc (raw_width, 3*sizeof **back); - merror (back[4], "hasselblad_load_raw()"); - FORC3 back[c] = back[4] + c*raw_width; - cblack[6] >>= sh = tiff_samples > 1; - shot = LIM(shot_select, 1, tiff_samples) - 1; - for (row=0; row < raw_height; row++) { - FORC4 back[(c+3) & 3] = back[c]; - for (col=0; col < raw_width; col+=2) { - for (s=0; s < tiff_samples*2; s+=2) { - FORC(2) len[c] = ph1_huff(jh.huff[0]); - FORC(2) { - diff[s+c] = hb_bits(len[c]); - if ((diff[s+c] & (1 << (len[c]-1))) == 0) - diff[s+c] -= (1 << len[c]) - 1; - if (diff[s+c] == 65535) diff[s+c] = -32768; - } - } - for (s=col; s < col+2; s++) { - pred = 0x8000 + load_flags; - if (col) pred = back[2][s-2]; - if (col && row > 1) switch (jh.psv) { - case 11: pred += back[0][s]/2 - back[0][s-2]/2; break; - } - f = (row & 1)*3 ^ ((col+s) & 1); - FORC (tiff_samples) { - pred += diff[(s & 1)*tiff_samples+c]; - upix = pred >> sh & 0xffff; - if (raw_image && c == shot) - RAW(row,s) = upix; - if (image) { - urow = row-top_margin + (c & 1); - ucol = col-left_margin - ((c >> 1) & 1); - ip = &image[urow*width+ucol][f]; - if (urow < height && ucol < width) - *ip = c < 4 ? upix : (*ip + upix) >> 1; - } - } - back[2][s] = pred; - } + if (!ljpeg_start (&jh, 0)) { + return; + } + order = 0x4949; + ph1_bithuff_t ph1_bithuff(this, ifp, order); + hb_bits(-1); + back[4] = (int *) calloc(raw_width, 3 * sizeof **back); + merror(back[4], "hasselblad_load_raw()"); + for (int c = 0; c < 3; ++c) { + back[c] = back[4] + c * raw_width; + } + const int sh = tiff_samples > 1; + cblack[6] >>= sh; + const int shot = LIM(shot_select, 1, tiff_samples) - 1; + for (int row = 0; row < raw_height; ++row) { + for (int c = 0; c < 4; ++c) { + back[(c + 3) & 3] = back[c]; + } + for (int col = 0; col < raw_width; col += 2) { + for (int s = 0; s < tiff_samples * 2; s += 2) { + const int len[2]= { + static_cast(ph1_huff(jh.huff[0])), + static_cast(ph1_huff(jh.huff[0])) + }; + for (int c = 0; c < 2; ++c) { + diff[s + c] = hb_bits(len[c]); + if ((diff[s + c] & (1 << (len[c] - 1))) == 0) { + diff[s + c] -= (1 << len[c]) - 1; + } + if (diff[s + c] == 65535) { + diff[s + c] = -32768; + } + } + } + for (int s = col; s < col + 2; ++s) { + int pred; + if (col) { + pred = back[2][s - 2]; + if (row > 1 && jh.psv == 11) { + pred += back[0][s] / 2 - back[0][s - 2] / 2; + } + } else { + pred = 0x8000 + load_flags; + } + for (int c = 0; c < tiff_samples; ++c) { + pred += diff[(s & 1) * tiff_samples + c]; + const unsigned upix = pred >> sh & 0xffff; + if (raw_image && c == shot) { + RAW(row, s) = upix; + } + if (image) { + const int f = (row & 1) * 3 ^ ((col + s) & 1); + const unsigned urow = row - top_margin + (c & 1); + const unsigned ucol = col - left_margin - ((c >> 1) & 1); + ushort* const ip = &image[urow * width + ucol][f]; + if (urow < height && ucol < width) { + *ip = c < 4 ? upix : (*ip + upix) >> 1; + } + } + } + back[2][s] = pred; + } + } + } + free(back[4]); + ljpeg_end(&jh); + if (image) { + mix_green = 1; } - } - free (back[4]); - ljpeg_end (&jh); - if (image) mix_green = 1; } void CLASS leaf_hdr_load_raw() @@ -4216,8 +4235,8 @@ void CLASS foveon_interpolate() foveon_avg (image[row*width]+c, dscr[1], cfilt) * 3 - ddft[0][c][0] ) / 4 - ddft[0][c][1]; } - memcpy (black, black+8, sizeof *black*8); - memcpy (black+height-11, black+height-22, 11*sizeof *black); + memmove (black, black+8, sizeof *black*8); + memmove (black+height-11, black+height-22, 11*sizeof *black); memcpy (last, black, sizeof last); for (row=1; row < height-1; row++) { @@ -6549,6 +6568,31 @@ guess_cfa_pc: cblack[4] = cblack[5] = MIN(sqrt(len),64); case 50714: /* BlackLevel */ RT_blacklevel_from_constant = ThreeValBool::F; +//----------------------------------------------------------------------------- +// taken from LibRaw. +/* + Copyright 2008-2019 LibRaw LLC (info@libraw.org) + +LibRaw is free software; you can redistribute it and/or modify +it under the terms of the one of two licenses as you choose: + +1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 + (See file LICENSE.LGPL provided in LibRaw distribution archive for details). + +2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 + (See file LICENSE.CDDL provided in LibRaw distribution archive for details). +*/ + if (tiff_ifd[ifd].samples > 1 && tiff_ifd[ifd].samples == len) // LinearDNG, per-channel black + { + for (i = 0; i < 4 && i < len; i++) + { + double b = getreal(type); + cblack[i] = b+0.5; + } + + black = 0; + } else +//----------------------------------------------------------------------------- if(cblack[4] * cblack[5] == 0) { int dblack[] = { 0,0,0,0 }; black = getreal(type); @@ -9233,8 +9277,8 @@ void CLASS identify() fseek (ifp, 0, SEEK_SET); fread (head, 1, 32, ifp); /* RT: changed string constant */ - if ((cp = (char *) memmem (head, 32, (char*)"MMMM", 4)) || - (cp = (char *) memmem (head, 32, (char*)"IIII", 4))) { + if ((cp = (char *) memmem (head, 32, "MMMM", 4)) || + (cp = (char *) memmem (head, 32, "IIII", 4))) { parse_phase_one (cp-head); if (cp-head && parse_tiff(0)) apply_tiff(); } else if (order == 0x4949 || order == 0x4d4d) { diff --git a/rtengine/dcraw.h b/rtengine/dcraw.h index 81da41718..fdebda0cc 100644 --- a/rtengine/dcraw.h +++ b/rtengine/dcraw.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef DCRAW_H diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 6acbc0047..61b96b3a3 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "curves.h" #include "dcrop.h" @@ -204,10 +204,8 @@ void Crop::update(int todo) } int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; - int kall = 2; - parent->ipf.Tile_calc(tilesize, overlap, kall, widIm, heiIm, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); - kall = 0; + parent->ipf.Tile_calc(tilesize, overlap, 2, widIm, heiIm, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); float *min_b = new float [9]; float *min_r = new float [9]; @@ -653,10 +651,9 @@ void Crop::update(int todo) if (todo & M_LINDENOISE) { if (skip == 1 && denoiseParams.enabled) { - int kall = 0; float nresi, highresi; - parent->ipf.RGB_denoise(kall, origCrop, origCrop, calclum, parent->denoiseInfoStore.ch_M, parent->denoiseInfoStore.max_r, parent->denoiseInfoStore.max_b, parent->imgsrc->isRAW(), /*Roffset,*/ denoiseParams, parent->imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, noiseCCurve, nresi, highresi); + parent->ipf.RGB_denoise(0, origCrop, origCrop, calclum, parent->denoiseInfoStore.ch_M, parent->denoiseInfoStore.max_r, parent->denoiseInfoStore.max_b, parent->imgsrc->isRAW(), /*Roffset,*/ denoiseParams, parent->imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, noiseCCurve, nresi, highresi); if (parent->adnListener) { parent->adnListener->noiseChanged(nresi, highresi); @@ -885,9 +882,6 @@ void Crop::update(int todo) if (skip == 1) { if ((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { parent->ipf.impulsedenoise(labnCrop); - } - - if ((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { parent->ipf.defringe(labnCrop); } @@ -900,7 +894,6 @@ void Crop::update(int todo) } // if (skip==1) { - WaveletParams WaveParams = params.wavelet; if (params.dirpyrequalizer.cbdlMethod == "aft") { if (((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled))) { @@ -909,81 +902,81 @@ void Crop::update(int todo) } } - int kall = 0; - int minwin = min(labnCrop->W, labnCrop->H); - int maxlevelcrop = 10; - - // if(cp.mul[9]!=0)maxlevelcrop=10; - // adap maximum level wavelet to size of crop - if (minwin * skip < 1024) { - maxlevelcrop = 9; //sampling wavelet 512 - } - - if (minwin * skip < 512) { - maxlevelcrop = 8; //sampling wavelet 256 - } - - if (minwin * skip < 256) { - maxlevelcrop = 7; //sampling 128 - } - - if (minwin * skip < 128) { - maxlevelcrop = 6; - } - - if (minwin < 64) { - maxlevelcrop = 5; - } - - int realtile; - - if (params.wavelet.Tilesmethod == "big") { - realtile = 22; - } else /*if (params.wavelet.Tilesmethod == "lit")*/ { - realtile = 12; - } - - int tilesize = 128 * realtile; - int overlap = (int) tilesize * 0.125f; - - int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; - - parent->ipf.Tile_calc(tilesize, overlap, kall, labnCrop->W, labnCrop->H, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); - //now we have tile dimensions, overlaps - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - int minsizetile = min(tilewidth, tileheight); - int maxlev2 = 10; - - if (minsizetile < 1024 && maxlevelcrop == 10) { - maxlev2 = 9; - } - - if (minsizetile < 512) { - maxlev2 = 8; - } - - if (minsizetile < 256) { - maxlev2 = 7; - } - - if (minsizetile < 128) { - maxlev2 = 6; - } - - int maxL = min(maxlev2, maxlevelcrop); - - if (parent->awavListener) { - parent->awavListener->wavChanged(float (maxL)); - } - if ((params.wavelet.enabled)) { + WaveletParams WaveParams = params.wavelet; + int kall = 0; + int minwin = min(labnCrop->W, labnCrop->H); + int maxlevelcrop = 10; + + // if(cp.mul[9]!=0)maxlevelcrop=10; + // adap maximum level wavelet to size of crop + if (minwin * skip < 1024) { + maxlevelcrop = 9; //sampling wavelet 512 + } + + if (minwin * skip < 512) { + maxlevelcrop = 8; //sampling wavelet 256 + } + + if (minwin * skip < 256) { + maxlevelcrop = 7; //sampling 128 + } + + if (minwin * skip < 128) { + maxlevelcrop = 6; + } + + if (minwin < 64) { + maxlevelcrop = 5; + } + + int realtile; + + if (params.wavelet.Tilesmethod == "big") { + realtile = 22; + } else /*if (params.wavelet.Tilesmethod == "lit")*/ { + realtile = 12; + } + + int tilesize = 128 * realtile; + int overlap = (int) tilesize * 0.125f; + + int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; + + parent->ipf.Tile_calc(tilesize, overlap, kall, labnCrop->W, labnCrop->H, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); + //now we have tile dimensions, overlaps + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + int minsizetile = min(tilewidth, tileheight); + int maxlev2 = 10; + + if (minsizetile < 1024 && maxlevelcrop == 10) { + maxlev2 = 9; + } + + if (minsizetile < 512) { + maxlev2 = 8; + } + + if (minsizetile < 256) { + maxlev2 = 7; + } + + if (minsizetile < 128) { + maxlev2 = 6; + } + + int maxL = min(maxlev2, maxlevelcrop); + + if (parent->awavListener) { + parent->awavListener->wavChanged(float (maxL)); + } + WavCurve wavCLVCurve; WavOpacityCurveRG waOpacityCurveRG; WavOpacityCurveBY waOpacityCurveBY; WavOpacityCurveW waOpacityCurveW; WavOpacityCurveWL waOpacityCurveWL; LUTf wavclCurve; - LUTu dummy; params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL); diff --git a/rtengine/dcrop.h b/rtengine/dcrop.h index 04274ca0c..6ce034f3f 100644 --- a/rtengine/dcrop.h +++ b/rtengine/dcrop.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index dc12bc01a..51db8bb3f 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -1121,7 +1121,7 @@ void RawImageSource::lmmse_interpolate_omp(int winw, int winh, array2D &r * Contact info: luis.sanz.rodriguez@gmail.com * * This code is distributed under a GNU General Public License, version 3. -* Visit for more information. +* Visit for more information. * ***/ // Adapted to RawTherapee by Jacques Desmis 3/2013 @@ -2024,7 +2024,8 @@ void RawImageSource::refinement(int PassCount) // Refinement based on EECI demozaicing algorithm by L. Chang and Y.P. Tan // from "Lassus" : Luis Sanz Rodriguez, adapted by Jacques Desmis - JDC - and Oliver Duis for RawTherapee -// increases the signal to noise ratio (PSNR) # +1 to +2 dB : tested with Dcraw : eg: Lighthouse + AMaZE : whitout refinement:39.96dB, with refinement:41.86 dB +// increases the signal to noise ratio (PSNR) # +1 to +2 dB : tested with Dcraw : +// eg: Lighthouse + AMaZE : without refinement:39.96 dB, with refinement:41.86 dB // reduce color artifacts, improves the interpolation // but it's relatively slow // diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc index db89dd4c2..55e37ec00 100644 --- a/rtengine/dfmanager.cc +++ b/rtengine/dfmanager.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "dfmanager.h" #include "../rtgui/options.h" @@ -328,8 +328,8 @@ void DFManager::init(const Glib::ustring& pathname) } else { printf( "%s: MEAN of \n ", i.key().c_str()); - for( std::list::iterator iter = i.pathNames.begin(); iter != i.pathNames.end(); ++iter ) { - printf( "%s, ", iter->c_str() ); + for(std::list::iterator path = i.pathNames.begin(); path != i.pathNames.end(); ++path) { + printf("%s, ", path->c_str()); } printf("\n"); diff --git a/rtengine/dfmanager.h b/rtengine/dfmanager.h index 2e55c3c22..23ca97d14 100644 --- a/rtengine/dfmanager.h +++ b/rtengine/dfmanager.h @@ -14,12 +14,16 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ -#include -#include -#include +#pragma once + #include +#include +#include + +#include + #include "pixelsmap.h" #include "rawimage.h" diff --git a/rtengine/diagonalcurves.cc b/rtengine/diagonalcurves.cc index b4c88fd68..bb20b7cc1 100644 --- a/rtengine/diagonalcurves.cc +++ b/rtengine/diagonalcurves.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -230,7 +230,6 @@ void DiagonalCurve::NURBS_set () poly_x.clear(); poly_y.clear(); unsigned int sc_xsize = j - 1; - j = 0; // adding the initial horizontal segment, if any if (x[0] > 0.) { @@ -314,18 +313,13 @@ inline void catmull_rom_spline(int n_points, double space = (t2-t1) / n_points; - double t; - int i; - double c, d, A1_x, A1_y, A2_x, A2_y, A3_x, A3_y; - double B1_x, B1_y, B2_x, B2_y, C_x, C_y; - res_x.push_back(p1_x); res_y.push_back(p1_y); // special case, a segment at 0 or 1 is computed exactly if (p1_y == p2_y && (p1_y == 0 || p1_y == 1)) { - for (i = 1; i < n_points-1; ++i) { - t = p1_x + space * i; + for (int i = 1; i < n_points-1; ++i) { + double t = p1_x + space * i; if (t >= p2_x) { break; } @@ -333,38 +327,38 @@ inline void catmull_rom_spline(int n_points, res_y.push_back(p1_y); } } else { - for (i = 1; i < n_points-1; ++i) { - t = t1 + space * i; + for (int i = 1; i < n_points-1; ++i) { + double t = t1 + space * i; - c = (t1 - t)/(t1 - t0); - d = (t - t0)/(t1 - t0); - A1_x = c * p0_x + d * p1_x; - A1_y = c * p0_y + d * p1_y; + double c = (t1 - t)/(t1 - t0); + double d = (t - t0)/(t1 - t0); + double A1_x = c * p0_x + d * p1_x; + double A1_y = c * p0_y + d * p1_y; c = (t2 - t)/(t2 - t1); d = (t - t1)/(t2 - t1); - A2_x = c * p1_x + d * p2_x; - A2_y = c * p1_y + d * p2_y; + double A2_x = c * p1_x + d * p2_x; + double A2_y = c * p1_y + d * p2_y; c = (t3 - t)/(t3 - t2); d = (t - t2)/(t3 - t2); - A3_x = c * p2_x + d * p3_x; - A3_y = c * p2_y + d * p3_y; + double A3_x = c * p2_x + d * p3_x; + double A3_y = c * p2_y + d * p3_y; c = (t2 - t)/(t2 - t0); d = (t - t0)/(t2 - t0); - B1_x = c * A1_x + d * A2_x; - B1_y = c * A1_y + d * A2_y; + double B1_x = c * A1_x + d * A2_x; + double B1_y = c * A1_y + d * A2_y; c = (t3 - t)/(t3 - t1); d = (t - t1)/(t3 - t1); - B2_x = c * A2_x + d * A3_x; - B2_y = c * A2_y + d * A3_y; + double B2_x = c * A2_x + d * A3_x; + double B2_y = c * A2_y + d * A3_y; c = (t2 - t)/(t2 - t1); d = (t - t1)/(t2 - t1); - C_x = c * B1_x + d * B2_x; - C_y = c * B1_y + d * B2_y; + double C_x = c * B1_x + d * B2_x; + double C_y = c * B1_y + d * B2_y; res_x.push_back(C_x); res_y.push_back(C_y); @@ -512,7 +506,6 @@ double DiagonalCurve::getVal (double t) const ++d; } return LIM01(*(poly_y.begin() + d)); - break; } case DCT_NURBS : { diff --git a/rtengine/dirpyr_equalizer.cc b/rtengine/dirpyr_equalizer.cc index 4a30b48a8..e822d8492 100644 --- a/rtengine/dirpyr_equalizer.cc +++ b/rtengine/dirpyr_equalizer.cc @@ -12,11 +12,11 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * (C) 2010 Emil Martinec * - */ +*/ #include #include @@ -25,404 +25,55 @@ #include "rt_math.h" #include "opthelper.h" -#define RANGEFN(i) ((1000.0f / (i + 1000.0f))) -#define DIRWT(i1,j1,i,j) ( domker[(i1-i)/scale+halfwin][(j1-j)/scale+halfwin] * RANGEFN(fabsf((data_fine[i1][j1]-data_fine[i][j]))) ) - -namespace rtengine -{ - -constexpr int maxlevel = 6; -constexpr float noise = 2000; - -//sequence of scales -constexpr int scales[maxlevel] = {1, 2, 4, 8, 16, 32}; -extern const Settings* settings; - -//sequence of scales - -void ImProcFunctions :: dirpyr_equalizer(float ** src, float ** dst, int srcwidth, int srcheight, float ** l_a, float ** l_b, const double * mult, const double dirpyrThreshold, const double skinprot, float b_l, float t_l, float t_r, int scaleprev) -{ - int lastlevel = maxlevel; - - float atten123 = (float) settings->level123_cbdl; - - if(atten123 > 50.f) { - atten123 = 50.f; - } - - if(atten123 < 0.f) { - atten123 = 0.f; - } - - float atten0 = (float) settings->level0_cbdl; - - if(atten0 > 40.f) { - atten123 = 40.f; - } - - if(atten0 < 0.f) { - atten0 = 0.f; - } - - if((t_r - t_l) < 0.55f) { - t_l = t_r + 0.55f; //avoid too small range - } - - - while (lastlevel > 0 && fabs(mult[lastlevel - 1] - 1) < 0.001) { - lastlevel--; - //printf("last level to process %d \n",lastlevel); - } - - if (lastlevel == 0) { - return; - } - - int level; - float multi[maxlevel] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f}; - float scalefl[maxlevel]; - - for(int lv = 0; lv < maxlevel; lv++) { - scalefl[lv] = ((float) scales[lv]) / (float) scaleprev; - - if(lv >= 1) { - if(scalefl[lv] < 1.f) { - multi[lv] = (atten123 * ((float) mult[lv] - 1.f) / 100.f) + 1.f; //modulate action if zoom < 100% - } else { - multi[lv] = (float) mult[lv]; - } - } else { - if(scalefl[lv] < 1.f) { - multi[lv] = (atten0 * ((float) mult[lv] - 1.f) / 100.f) + 1.f; //modulate action if zoom < 100% - } else { - multi[lv] = (float) mult[lv]; - } - } - - } - - multi_array2D dirpyrlo (srcwidth, srcheight); - - level = 0; - - //int thresh = 100 * mult[5]; - int scale = (int)(scales[level]) / scaleprev; - - if(scale < 1) { - scale = 1; - } - - - dirpyr_channel(src, dirpyrlo[0], srcwidth, srcheight, 0, scale); - - level = 1; - - while(level < lastlevel) { - - scale = (int)(scales[level]) / scaleprev; - - if(scale < 1) { - scale = 1; - } - - dirpyr_channel(dirpyrlo[level - 1], dirpyrlo[level], srcwidth, srcheight, level, scale); - - level ++; - } - - float **tmpHue = nullptr, **tmpChr = nullptr; - - if(skinprot != 0.f) { - // precalculate hue and chroma, use SSE, if available - // by precalculating these values we can greatly reduce the number of calculations in idirpyr_eq_channel() - // but we need two additional buffers for this preprocessing - tmpHue = new float*[srcheight]; - - for (int i = 0; i < srcheight; i++) { - tmpHue[i] = new float[srcwidth]; - } - -#ifdef __SSE2__ -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for(int i = 0; i < srcheight; i++) { - int j; - - for(j = 0; j < srcwidth - 3; j += 4) { - _mm_storeu_ps(&tmpHue[i][j], xatan2f(LVFU(l_b[i][j]), LVFU(l_a[i][j]))); - } - - for(; j < srcwidth; j++) { - tmpHue[i][j] = xatan2f(l_b[i][j], l_a[i][j]); - } - } - -#else -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for(int i = 0; i < srcheight; i++) { - for(int j = 0; j < srcwidth; j++) { - tmpHue[i][j] = xatan2f(l_b[i][j], l_a[i][j]); - } - } - -#endif - tmpChr = new float*[srcheight]; - - for (int i = 0; i < srcheight; i++) { - tmpChr[i] = new float[srcwidth]; - } - -#ifdef __SSE2__ -#ifdef _OPENMP - #pragma omp parallel -#endif - { - __m128 div = _mm_set1_ps(327.68f); -#ifdef _OPENMP - #pragma omp for -#endif - - for(int i = 0; i < srcheight; i++) { - int j; - - for(j = 0; j < srcwidth - 3; j += 4) { - _mm_storeu_ps(&tmpChr[i][j], vsqrtf(SQRV(LVFU(l_b[i][j])) + SQRV(LVFU(l_a[i][j]))) / div); - } - - for(; j < srcwidth; j++) { - tmpChr[i][j] = sqrtf(SQR((l_b[i][j])) + SQR((l_a[i][j]))) / 327.68f; - } - } - } -#else -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for(int i = 0; i < srcheight; i++) { - for(int j = 0; j < srcwidth; j++) { - tmpChr[i][j] = sqrtf(SQR((l_b[i][j])) + SQR((l_a[i][j]))) / 327.68f; - } - } - -#endif - } - - // with the current implementation of idirpyr_eq_channel we can safely use the buffer from last level as buffer, saves some memory - float ** buffer = dirpyrlo[lastlevel - 1]; - - for(int level = lastlevel - 1; level > 0; level--) { - idirpyr_eq_channel(dirpyrlo[level], dirpyrlo[level - 1], buffer, srcwidth, srcheight, level, multi, dirpyrThreshold, tmpHue, tmpChr, skinprot, b_l, t_l, t_r); - } - - scale = scales[0]; - - idirpyr_eq_channel(dirpyrlo[0], dst, buffer, srcwidth, srcheight, 0, multi, dirpyrThreshold, tmpHue, tmpChr, skinprot, b_l, t_l, t_r); - - if(skinprot != 0.f) { - for (int i = 0; i < srcheight; i++) { - delete [] tmpChr[i]; - } - - delete [] tmpChr; - - for (int i = 0; i < srcheight; i++) { - delete [] tmpHue[i]; - } - - delete [] tmpHue; - } - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = 0; i < srcheight; i++) - for (int j = 0; j < srcwidth; j++) { - dst[i][j] = /*CLIP*/(buffer[i][j]); // TODO: Really a clip necessary? - } +namespace { +float rangeFn(float i) { + return 1.f / (i + 1000.f); } - - -void ImProcFunctions :: dirpyr_equalizercam (CieImage *ncie, float ** src, float ** dst, int srcwidth, int srcheight, float ** h_p, float ** C_p, const double * mult, const double dirpyrThreshold, const double skinprot, bool execdir, float b_l, float t_l, float t_r, int scaleprev) -{ - int lastlevel = maxlevel; - - if(settings->verbose) { - printf("CAM dirpyr scaleprev=%i\n", scaleprev); - } - - float atten123 = (float) settings->level123_cbdl; - - if(atten123 > 50.f) { - atten123 = 50.f; - } - - if(atten123 < 0.f) { - atten123 = 0.f; - } - -// printf("atten=%f\n",atten); - float atten0 = (float) settings->level0_cbdl; - - if(atten0 > 40.f) { - atten123 = 40.f; - } - - if(atten0 < 0.f) { - atten0 = 0.f; - } - - if((t_r - t_l) < 0.55f) { - t_l = t_r + 0.55f; //avoid too small range - } - - while (fabs(mult[lastlevel - 1] - 1) < 0.001 && lastlevel > 0) { - lastlevel--; - //printf("last level to process %d \n",lastlevel); - } - - if (lastlevel == 0) { - return; - } - - int level; - - float multi[maxlevel] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f}; - float scalefl[maxlevel]; - - for(int lv = 0; lv < maxlevel; lv++) { - scalefl[lv] = ((float) scales[lv]) / (float) scaleprev; - - // if(scalefl[lv] < 1.f) multi[lv] = 1.f; else multi[lv]=(float) mult[lv]; - if (lv >= 1) { - if(scalefl[lv] < 1.f) { - multi[lv] = (atten123 * ((float) mult[lv] - 1.f) / 100.f) + 1.f; - } else { - multi[lv] = (float) mult[lv]; - } - } else { - if(scalefl[lv] < 1.f) { - multi[lv] = (atten0 * ((float) mult[lv] - 1.f) / 100.f) + 1.f; - } else { - multi[lv] = (float) mult[lv]; - } - } - - - } - - if(settings->verbose) { - printf("CAM CbDL mult0=%f 1=%f 2=%f 3=%f 4=%f 5=%f\n", multi[0], multi[1], multi[2], multi[3], multi[4], multi[5]); - } - - - - - multi_array2D dirpyrlo (srcwidth, srcheight); - - level = 0; - - int scale = (int)(scales[level]) / scaleprev; - - if(scale < 1) { - scale = 1; - } - - dirpyr_channel(src, dirpyrlo[0], srcwidth, srcheight, 0, scale); - - level = 1; - - while(level < lastlevel) { - scale = (int)(scales[level]) / scaleprev; - - if(scale < 1) { - scale = 1; - } - - dirpyr_channel(dirpyrlo[level - 1], dirpyrlo[level], srcwidth, srcheight, level, scale); - - level ++; - } - - - // with the current implementation of idirpyr_eq_channel we can safely use the buffer from last level as buffer, saves some memory - float ** buffer = dirpyrlo[lastlevel - 1]; - - for(int level = lastlevel - 1; level > 0; level--) { - idirpyr_eq_channelcam(dirpyrlo[level], dirpyrlo[level - 1], buffer, srcwidth, srcheight, level, multi, dirpyrThreshold , h_p, C_p, skinprot, b_l, t_l, t_r); - } - - idirpyr_eq_channelcam(dirpyrlo[0], dst, buffer, srcwidth, srcheight, 0, multi, dirpyrThreshold, h_p, C_p, skinprot, b_l, t_l, t_r); - - - if(execdir) { -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int i = 0; i < srcheight; i++) - for (int j = 0; j < srcwidth; j++) { - if(ncie->J_p[i][j] > 8.f && ncie->J_p[i][j] < 92.f) { - dst[i][j] = /*CLIP*/( buffer[i][j] ); // TODO: Really a clip necessary? - } else { - dst[i][j] = src[i][j]; - } - } - } else { - for (int i = 0; i < srcheight; i++) - for (int j = 0; j < srcwidth; j++) { - dst[i][j] = /*CLIP*/( buffer[i][j] ); // TODO: Really a clip necessary? - } - } -} - -void ImProcFunctions::dirpyr_channel(float ** data_fine, float ** data_coarse, int width, int height, int level, int scale) +void dirpyr_channel(const float * const * data_fine, float ** data_coarse, int width, int height, int level, int scale) { // scale is spacing of directional averaging weights // calculate weights, compute directionally weighted average - if(level > 1) { + if (level > 1) { //generate domain kernel - int domker[5][5] = {{1, 1, 1, 1, 1}, {1, 2, 2, 2, 1}, {1, 2, 2, 2, 1}, {1, 2, 2, 2, 1}, {1, 1, 1, 1, 1}}; - // int domker[5][5] = {{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1}}; - static const int halfwin = 2; - const int scalewin = halfwin * scale; + // multiplied each value of domker by 1000 to avoid multiplication by 1000 inside the loop +#ifdef __SSE2__ + const float domkerv[5][5][4] ALIGNED16 = {{{1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}}, + {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, + {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, + {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, + {{1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}}}; +#endif + const float domker[5][5] = {{1000, 1000, 1000, 1000, 1000}, + {1000, 2000, 2000, 2000, 1000}, + {1000, 2000, 2000, 2000, 1000}, + {1000, 2000, 2000, 2000, 1000}, + {1000, 1000, 1000, 1000, 1000}}; + constexpr int halfwin = 2; #ifdef _OPENMP #pragma omp parallel #endif { + const int scalewin = halfwin * scale; #ifdef __SSE2__ - __m128 thousandv = _mm_set1_ps( 1000.0f ); - __m128 dirwtv, valv, normv, dftemp1v, dftemp2v; -// multiplied each value of domkerv by 1000 to avoid multiplication by 1000 inside the loop - float domkerv[5][5][4] ALIGNED16 = {{{1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}}}; -#endif // __SSE2__ - - int j; -#ifdef _OPENMP - #pragma omp for //schedule (dynamic,8) + const vfloat thousandv = F2V(1000.f); #endif - for(int i = 0; i < height; i++) { - float dirwt; +#ifdef _OPENMP + #pragma omp for +#endif - for(j = 0; j < scalewin; j++) { + for (int i = 0; i < height; i++) { + int j; + for (j = 0; j < scalewin; j++) { float val = 0.f; float norm = 0.f; - - for(int inbr = max(0, i - scalewin); inbr <= min(height - 1, i + scalewin); inbr += scale) { + for (int inbr = max(0, i - scalewin); inbr <= min(height - 1, i + scalewin); inbr += scale) { for (int jnbr = max(0, j - scalewin); jnbr <= j + scalewin; jnbr += scale) { - //printf("i=%d ",(inbr-i)/scale+halfwin); - dirwt = DIRWT(inbr, jnbr, i, j); + const float dirwt = domker[(inbr - i) / scale + halfwin][(jnbr - j)/ scale + halfwin] * rangeFn(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); val += dirwt * data_fine[inbr][jnbr]; norm += dirwt; } @@ -433,174 +84,125 @@ void ImProcFunctions::dirpyr_channel(float ** data_fine, float ** data_coarse, i #ifdef __SSE2__ - for(; j < width - scalewin - 3; j += 4) { - valv = _mm_setzero_ps(); - normv = _mm_setzero_ps(); - dftemp1v = LVFU(data_fine[i][j]); + for (; j < width - scalewin - 3; j += 4) { + vfloat valv = ZEROV; + vfloat normv = ZEROV; + const vfloat dftemp1v = LVFU(data_fine[i][j]); - for(int inbr = MAX(0, i - scalewin); inbr <= MIN(height - 1, i + scalewin); inbr += scale) { - int indexihlp = (inbr - i) / scale + halfwin; - - for (int jnbr = j - scalewin, indexjhlp = 0; jnbr <= j + scalewin; jnbr += scale, indexjhlp++) { - dftemp2v = LVFU(data_fine[inbr][jnbr]); - dirwtv = LVF(domkerv[indexihlp][indexjhlp]) / (vabsf(dftemp1v - dftemp2v) + thousandv); + for (int inbr = MAX(0, i - scalewin); inbr <= MIN(height - 1, i + scalewin); inbr += scale) { + const int indexihlp = (inbr - i) / scale + halfwin; + for (int jnbr = j - scalewin, indexjhlp = 0; jnbr <= j + scalewin; jnbr += scale, ++indexjhlp) { + const vfloat dftemp2v = LVFU(data_fine[inbr][jnbr]); + const vfloat dirwtv = LVF(domkerv[indexihlp][indexjhlp]) / (vabsf(dftemp1v - dftemp2v) + thousandv); valv += dirwtv * dftemp2v; normv += dirwtv; } } - - _mm_storeu_ps( &data_coarse[i][j], valv / normv); //low pass filter + STVFU(data_coarse[i][j], valv / normv); //low pass filter } - - for(; j < width - scalewin; j++) { - float val = 0.f; - float norm = 0.f; - - for(int inbr = max(0, i - scalewin); inbr <= min(height - 1, i + scalewin); inbr += scale) { - for (int jnbr = j - scalewin; jnbr <= j + scalewin; jnbr += scale) { - dirwt = DIRWT(inbr, jnbr, i, j); - val += dirwt * data_fine[inbr][jnbr]; - norm += dirwt; - } - } - - data_coarse[i][j] = val / norm; //low pass filter - } - -#else - - for(; j < width - scalewin; j++) { - float val = 0.f; - float norm = 0.f; - - for(int inbr = max(0, i - scalewin); inbr <= min(height - 1, i + scalewin); inbr += scale) { - for (int jnbr = j - scalewin; jnbr <= j + scalewin; jnbr += scale) { - dirwt = DIRWT(inbr, jnbr, i, j); - val += dirwt * data_fine[inbr][jnbr]; - norm += dirwt; - } - } - - data_coarse[i][j] = val / norm; //low pass filter - } - #endif - - for(; j < width; j++) { + for (; j < width - scalewin; j++) { float val = 0.f; float norm = 0.f; - for(int inbr = max(0, i - scalewin); inbr <= min(height - 1, i + scalewin); inbr += scale) { - for (int jnbr = j - scalewin; jnbr <= min(width - 1, j + scalewin); jnbr += scale) { - dirwt = DIRWT(inbr, jnbr, i, j); + for (int inbr = max(0, i - scalewin); inbr <= min(height - 1, i + scalewin); inbr += scale) { + for (int jnbr = j - scalewin; jnbr <= j + scalewin; jnbr += scale) { + const float dirwt = domker[(inbr - i) / scale + halfwin][(jnbr - j)/ scale + halfwin] * rangeFn(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); val += dirwt * data_fine[inbr][jnbr]; norm += dirwt; } } + data_coarse[i][j] = val / norm; //low pass filter + } + for (; j < width; j++) { + float val = 0.f; + float norm = 0.f; + + for (int inbr = max(0, i - scalewin); inbr <= min(height - 1, i + scalewin); inbr += scale) { + for (int jnbr = j - scalewin; jnbr <= min(width - 1, j + scalewin); jnbr += scale) { + const float dirwt = domker[(inbr - i) / scale + halfwin][(jnbr - j)/ scale + halfwin] * rangeFn(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); + val += dirwt * data_fine[inbr][jnbr]; + norm += dirwt; + } + } data_coarse[i][j] = val / norm; //low pass filter } } } } else { // level <=1 means that all values of domker would be 1.0f, so no need for multiplication -// const int scalewin = scale; #ifdef _OPENMP #pragma omp parallel #endif { #ifdef __SSE2__ - __m128 thousandv = _mm_set1_ps( 1000.0f ); - __m128 dirwtv, valv, normv, dftemp1v, dftemp2v; -#endif // __SSE2__ - int j; + const vfloat thousandv = F2V(1000.0f); +#endif #ifdef _OPENMP #pragma omp for schedule(dynamic,16) #endif - for(int i = 0; i < height; i++) + for (int i = 0; i < height; i++) { - float dirwt; - - for(j = 0; j < scale; j++) { + int j = 0; + for (; j < scale; j++) { float val = 0.f; float norm = 0.f; - for(int inbr = max(0, i - scale); inbr <= min(height - 1, i + scale); inbr += scale) { + for (int inbr = max(0, i - scale); inbr <= min(height - 1, i + scale); inbr += scale) { for (int jnbr = max(0, j - scale); jnbr <= j + scale; jnbr += scale) { - dirwt = RANGEFN(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); + const float dirwt = rangeFn(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); val += dirwt * data_fine[inbr][jnbr]; norm += dirwt; } } - data_coarse[i][j] = val / norm; //low pass filter } #ifdef __SSE2__ - for(; j < width - scale - 3; j += 4) { - valv = _mm_setzero_ps(); - normv = _mm_setzero_ps(); - dftemp1v = LVFU(data_fine[i][j]); + for (; j < width - scale - 3; j += 4) { + vfloat valv = ZEROV; + vfloat normv = ZEROV; + const vfloat dftemp1v = LVFU(data_fine[i][j]); - for(int inbr = MAX(0, i - scale); inbr <= MIN(height - 1, i + scale); inbr += scale) { + for (int inbr = MAX(0, i - scale); inbr <= MIN(height - 1, i + scale); inbr += scale) { for (int jnbr = j - scale; jnbr <= j + scale; jnbr += scale) { - dftemp2v = LVFU(data_fine[inbr][jnbr]); - dirwtv = thousandv / (vabsf(dftemp2v - dftemp1v) + thousandv); + const vfloat dftemp2v = LVFU(data_fine[inbr][jnbr]); + const vfloat dirwtv = thousandv / (vabsf(dftemp2v - dftemp1v) + thousandv); valv += dirwtv * dftemp2v; normv += dirwtv; } } - - _mm_storeu_ps( &data_coarse[i][j], valv / normv); //low pass filter + STVFU(data_coarse[i][j], valv / normv); //low pass filter } - - for(; j < width - scale; j++) { - float val = 0.f; - float norm = 0.f; - - for(int inbr = max(0, i - scale); inbr <= min(height - 1, i + scale); inbr += scale) { - for (int jnbr = j - scale; jnbr <= j + scale; jnbr += scale) { - dirwt = RANGEFN(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); - val += dirwt * data_fine[inbr][jnbr]; - norm += dirwt; - } - } - - data_coarse[i][j] = val / norm; //low pass filter - } - -#else - - for(; j < width - scale; j++) { - float val = 0.f; - float norm = 0.f; - - for(int inbr = max(0, i - scale); inbr <= min(height - 1, i + scale); inbr += scale) { - for (int jnbr = j - scale; jnbr <= j + scale; jnbr += scale) { - dirwt = RANGEFN(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); - val += dirwt * data_fine[inbr][jnbr]; - norm += dirwt; - } - } - - data_coarse[i][j] = val / norm; //low pass filter - } - #endif - for(; j < width; j++) { + for (; j < width - scale; j++) { float val = 0.f; float norm = 0.f; - for(int inbr = max(0, i - scale); inbr <= min(height - 1, i + scale); inbr += scale) { - for (int jnbr = j - scale; jnbr <= min(width - 1, j + scale); jnbr += scale) { - dirwt = RANGEFN(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); + for (int inbr = max(0, i - scale); inbr <= min(height - 1, i + scale); inbr += scale) { + for (int jnbr = j - scale; jnbr <= j + scale; jnbr += scale) { + const float dirwt = rangeFn(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); val += dirwt * data_fine[inbr][jnbr]; norm += dirwt; } } + data_coarse[i][j] = val / norm; //low pass filter + } + for (; j < width; j++) { + float val = 0.f; + float norm = 0.f; + + for (int inbr = max(0, i - scale); inbr <= min(height - 1, i + scale); inbr += scale) { + for (int jnbr = j - scale; jnbr <= min(width - 1, j + scale); jnbr += scale) { + const float dirwt = rangeFn(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); + val += dirwt * data_fine[inbr][jnbr]; + norm += dirwt; + } + } data_coarse[i][j] = val / norm; //low pass filter } } @@ -608,218 +210,297 @@ void ImProcFunctions::dirpyr_channel(float ** data_fine, float ** data_coarse, i } } -void ImProcFunctions::idirpyr_eq_channel(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float mult[maxlevel], const double dirpyrThreshold, float ** hue, float ** chrom, const double skinprot, float b_l, float t_l, float t_r) +void fillLut(LUTf &irangefn, int level, double dirpyrThreshold, float mult, float skinprot) { + + float multbis; + if (level == 4 && mult > 1.f) { + multbis = 1.f + 0.65f * (mult - 1.f); + } else if (level == 5 && mult > 1.f) { + multbis = 1.f + 0.45f * (mult - 1.f); + } else { + multbis = mult; //multbis to reduce artifacts for high values mult + } + + const float offs = skinprot == 0.f ? 0.f : -1.f; + constexpr float noise = 2000.f; + const float noisehi = 1.33f * noise * dirpyrThreshold / expf(level * log(3.0)), noiselo = 0.66f * noise * dirpyrThreshold / expf(level * log(3.0)); + + for (int i = 0; i < 0x20000; i++) { + if (abs(i - 0x10000) > noisehi || multbis < 1.0) { + irangefn[i] = multbis + offs; + } else { + if (abs(i - 0x10000) < noiselo) { + irangefn[i] = 1.f + offs; + } else { + irangefn[i] = 1.f + offs + (multbis - 1.f) * (noisehi - abs(i - 0x10000)) / (noisehi - noiselo + 0.01f); + } + } + } +} + +void idirpyr_eq_channel(const float * const * data_coarse, const float * const * data_fine, float ** buffer, int width, int height, int level, float mult, const double dirpyrThreshold, const float * const * hue, const float * const * chrom, const double skinprot, float b_l, float t_l, float t_r) { const float skinprotneg = -skinprot; const float factorHard = (1.f - skinprotneg / 100.f); - float offs; + LUTf irangefn(0x20000); + fillLut(irangefn, level, dirpyrThreshold, mult, skinprot); - if(skinprot == 0.f) { - offs = 0.f; - } else { - offs = -1.f; - } - - float multbis[maxlevel]; - - multbis[level] = mult[level]; //multbis to reduce artifacts for high values mult - - if(level == 4 && mult[level] > 1.f) { - multbis[level] = 1.f + 0.65f * (mult[level] - 1.f); - } - - if(level == 5 && mult[level] > 1.f) { - multbis[level] = 1.f + 0.45f * (mult[level] - 1.f); - } - - LUTf irangefn (0x20000); - { - const float noisehi = 1.33f * noise * dirpyrThreshold / expf(level * log(3.0)), noiselo = 0.66f * noise * dirpyrThreshold / expf(level * log(3.0)); - //printf("level=%i multlev=%f noisehi=%f noiselo=%f skinprot=%f\n",level,mult[level], noisehi, noiselo, skinprot); - - for (int i = 0; i < 0x20000; i++) { - if (abs(i - 0x10000) > noisehi || multbis[level] < 1.0) { - irangefn[i] = multbis[level] + offs; - } else { - if (abs(i - 0x10000) < noiselo) { - irangefn[i] = 1.f + offs ; - } else { - irangefn[i] = 1.f + offs + (multbis[level] - 1.f) * (noisehi - abs(i - 0x10000)) / (noisehi - noiselo + 0.01f) ; - } - } - } - } - - if(skinprot == 0.f) + if (!skinprot) { #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif - for(int i = 0; i < height; i++) { - for(int j = 0; j < width; j++) { - float hipass = (data_fine[i][j] - data_coarse[i][j]); + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + const float hipass = data_fine[i][j] - data_coarse[i][j]; buffer[i][j] += irangefn[hipass + 0x10000] * hipass; } } - else if(skinprot > 0.f) + } else if (skinprot > 0.f) { #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif - for(int i = 0; i < height; i++) { - for(int j = 0; j < width; j++) { + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { float scale = 1.f; - float hipass = (data_fine[i][j] - data_coarse[i][j]); - // These values are precalculated now - float modhue = hue[i][j]; - float modchro = chrom[i][j]; - Color::SkinSatCbdl ((data_fine[i][j]) / 327.68f, modhue, modchro, skinprot, scale, true, b_l, t_l, t_r); - buffer[i][j] += (1.f + (irangefn[hipass + 0x10000]) * scale) * hipass ; + const float hipass = data_fine[i][j] - data_coarse[i][j]; + rtengine::Color::SkinSatCbdl(data_fine[i][j] / 327.68f, hue[i][j], chrom[i][j], skinprot, scale, true, b_l, t_l, t_r); + buffer[i][j] += (1.f + (irangefn[hipass + 0x10000]) * scale) * hipass; } } - else + } else { #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif - for(int i = 0; i < height; i++) { - for(int j = 0; j < width; j++) { + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { float scale = 1.f; - float hipass = (data_fine[i][j] - data_coarse[i][j]); - // These values are precalculated now - float modhue = hue[i][j]; - float modchro = chrom[i][j]; - Color::SkinSatCbdl ((data_fine[i][j]) / 327.68f, modhue, modchro, skinprotneg, scale, false, b_l, t_l, t_r); - float correct = irangefn[hipass + 0x10000]; + const float hipass = data_fine[i][j] - data_coarse[i][j]; + rtengine::Color::SkinSatCbdl(data_fine[i][j] / 327.68f, hue[i][j], chrom[i][j], skinprotneg, scale, false, b_l, t_l, t_r); + const float correct = irangefn[hipass + 0x10000]; if (scale == 1.f) {//image hard - buffer[i][j] += (1.f + (correct) * (factorHard)) * hipass ; + buffer[i][j] += (1.f + correct * factorHard) * hipass; } else { //image soft with scale < 1 ==> skin - buffer[i][j] += (1.f + (correct)) * hipass ; + buffer[i][j] += (1.f + correct) * hipass; } } } + } } - -void ImProcFunctions::idirpyr_eq_channelcam(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float mult[maxlevel], const double dirpyrThreshold, float ** l_a_h, float ** l_b_c, const double skinprot, float b_l, float t_l, float t_r) +void idirpyr_eq_channelcam(const float * const * data_coarse, const float * const * data_fine, float ** buffer, int width, int height, int level, float mult, const double dirpyrThreshold, const float * const * h_p, const float * const * C_p, const double skinprot, float b_l, float t_l, float t_r) { const float skinprotneg = -skinprot; - const float factorHard = (1.f - skinprotneg / 100.f); + const float factorHard = 1.f - skinprotneg / 100.f; - float offs; + LUTf irangefn(0x20000); + fillLut(irangefn, level, dirpyrThreshold, mult, skinprot); - if(skinprot == 0.f) { - offs = 0.f; + if (!skinprot) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + const float hipass = data_fine[i][j] - data_coarse[i][j]; + buffer[i][j] += irangefn[hipass + 0x10000] * hipass; + } + } + } else if (skinprot > 0.f) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + const float hipass = data_fine[i][j] - data_coarse[i][j]; + float scale = 1.f; + rtengine::Color::SkinSatCbdlCam(data_fine[i][j] / 327.68f, h_p[i][j] , C_p[i][j], skinprot, scale, true, b_l, t_l, t_r); + buffer[i][j] += (1.f + (irangefn[hipass + 0x10000]) * scale) * hipass; + } + } } else { - offs = -1.f; - } - - float multbis[maxlevel]; - - multbis[level] = mult[level]; //multbis to reduce artifacts for high values mult - - if(level == 4 && mult[level] > 1.f) { - multbis[level] = 1.f + 0.65f * (mult[level] - 1.f); - } - - if(level == 5 && mult[level] > 1.f) { - multbis[level] = 1.f + 0.45f * (mult[level] - 1.f); - } - - LUTf irangefn (0x20000); - { - const float noisehi = 1.33f * noise * dirpyrThreshold / expf(level * log(3.0)), noiselo = 0.66f * noise * dirpyrThreshold / expf(level * log(3.0)); - - //printf("level=%i multlev=%f noisehi=%f noiselo=%f skinprot=%f\n",level,mult[level], noisehi, noiselo, skinprot); - for (int i = 0; i < 0x20000; i++) { - if (abs(i - 0x10000) > noisehi || multbis[level] < 1.0) { - irangefn[i] = multbis[level] + offs; - } else { - if (abs(i - 0x10000) < noiselo) { - irangefn[i] = 1.f + offs ; - } else { - irangefn[i] = 1.f + offs + (multbis[level] - 1.f) * (noisehi - abs(i - 0x10000)) / (noisehi - noiselo + 0.01f) ; - } - } - } - } - - if(skinprot == 0.f) #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif - for(int i = 0; i < height; i++) { - for(int j = 0; j < width; j++) { - float hipass = (data_fine[i][j] - data_coarse[i][j]); - buffer[i][j] += irangefn[hipass + 0x10000] * hipass ; - } - } - else if(skinprot > 0.f) -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - for(int i = 0; i < height; i++) { - for(int j = 0; j < width; j++) { - float hipass = (data_fine[i][j] - data_coarse[i][j]); + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + const float hipass = data_fine[i][j] - data_coarse[i][j]; float scale = 1.f; - Color::SkinSatCbdlCam ((data_fine[i][j]) / 327.68f, l_a_h[i][j] , l_b_c[i][j], skinprot, scale, true, b_l, t_l, t_r); - buffer[i][j] += (1.f + (irangefn[hipass + 0x10000]) * scale) * hipass ; - } - } - else -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - for(int i = 0; i < height; i++) { - for(int j = 0; j < width; j++) { - float hipass = (data_fine[i][j] - data_coarse[i][j]); - float scale = 1.f; - float correct; - correct = irangefn[hipass + 0x10000]; - Color::SkinSatCbdlCam ((data_fine[i][j]) / 327.68f, l_a_h[i][j], l_b_c[i][j] , skinprotneg, scale, false, b_l, t_l, t_r); + const float correct = irangefn[hipass + 0x10000]; + rtengine::Color::SkinSatCbdlCam(data_fine[i][j] / 327.68f, h_p[i][j], C_p[i][j], skinprotneg, scale, false, b_l, t_l, t_r); if (scale == 1.f) {//image hard - buffer[i][j] += (1.f + (correct) * factorHard) * hipass ; - + buffer[i][j] += (1.f + correct * factorHard) * hipass; } else { //image soft - buffer[i][j] += (1.f + (correct)) * hipass ; + buffer[i][j] += (1.f + correct) * hipass; } } } + } +} - // if(gamutlab) { - // ImProcFunctions::badpixcam (buffer[i][j], 6.0, 10, 2);//for bad pixels - // } +} - /* if(gamutlab) {//disabled - float Lprov1=(buffer[i][j])/327.68f; - float R,G,B; - #ifdef _DEBUG - bool neg=false; - bool more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(modhue,Lprov1,modchro, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb); - #else - //gamut control : Lab values are in gamut - Color::gamutLchonly(modhue,Lprov1,modchro, R, G, B, wip, highlight, 0.15f, 0.96f); - #endif - // Color::gamutLchonly(modhue,Lprov1,modchro, R, G, B, wip, highlight, 0.15f, 0.96f);//gamut control in Lab mode ..not in CIECAM - buffer[i][j]=Lprov1*327.68f; - float2 sincosval = xsincosf(modhue); - l_a_h[i][j]=327.68f*modchro*sincosval.y; - l_b_c[i][j]=327.68f*modchro*sincosval.x; +namespace rtengine +{ + +extern const Settings* settings; + +void ImProcFunctions::dirpyr_equalizer(const float * const * src, float ** dst, int srcwidth, int srcheight, const float * const * l_a, const float * const * l_b, const double * mult, const double dirpyrThreshold, const double skinprot, float b_l, float t_l, float t_r, int scaleprev) +{ + //sequence of scales + constexpr int maxlevel = 6; + constexpr int scales[maxlevel] = {1, 2, 4, 8, 16, 32}; + const float atten123 = rtengine::LIM(settings->level123_cbdl, 0.f, 50.f); + const float atten0 = rtengine::LIM(settings->level0_cbdl, 0.f, 40.f); + + int lastlevel = maxlevel; + while (lastlevel > 0 && fabs(mult[lastlevel - 1] - 1) < 0.001) { + --lastlevel; + } + + if (lastlevel == 0) { + return; + } + + float multi[maxlevel]; + + for (int lv = 0; lv < maxlevel; ++lv) { + if (scales[lv] < scaleprev) { + const float factor = lv >= 1 ? atten123 : atten0; + multi[lv] = (factor * ((float) mult[lv] - 1.f) / 100.f) + 1.f; //modulate action if zoom < 100% + } else { + multi[lv] = mult[lv]; + } + } + + multi_array2D dirpyrlo (srcwidth, srcheight); + + dirpyr_channel(src, dirpyrlo[0], srcwidth, srcheight, 0, std::max(scales[0] / scaleprev, 1)); + + for (int level = 1; level < lastlevel; ++level) { + dirpyr_channel(dirpyrlo[level - 1], dirpyrlo[level], srcwidth, srcheight, level, std::max(scales[level] / scaleprev, 1)); + } + + array2D tmpHue, tmpChr; + + if (skinprot) { + // precalculate hue and chroma, use SSE, if available + // by precalculating these values we can greatly reduce the number of calculations in idirpyr_eq_channel() + // but we need two additional buffers for this preprocessing + tmpHue(srcwidth, srcheight); + tmpChr(srcwidth, srcheight); + +#ifdef _OPENMP + #pragma omp parallel +#endif + { +#ifdef __SSE2__ + const vfloat div = F2V(327.68f); +#endif +#ifdef _OPENMP + #pragma omp for +#endif + + for (int i = 0; i < srcheight; i++) { + int j = 0; +#ifdef __SSE2__ + for (; j < srcwidth - 3; j += 4) { + const vfloat lav = LVFU(l_a[i][j]); + const vfloat lbv = LVFU(l_b[i][j]); + STVFU(tmpHue[i][j], xatan2f(lbv, lav)); + STVFU(tmpChr[i][j], vsqrtf(SQRV(lbv) + SQRV(lav)) / div); + } +#endif + for (; j < srcwidth; j++) { + tmpHue[i][j] = xatan2f(l_b[i][j], l_a[i][j]); + tmpChr[i][j] = sqrtf(SQR((l_b[i][j])) + SQR((l_a[i][j]))) / 327.68f; + } } - */ + } + } + + // with the current implementation of idirpyr_eq_channel we can safely use the buffer from last level as buffer, saves some memory + float** buffer = dirpyrlo[lastlevel - 1]; + + for (int level = lastlevel - 1; level > 0; --level) { + idirpyr_eq_channel(dirpyrlo[level], dirpyrlo[level - 1], buffer, srcwidth, srcheight, level, multi[level], dirpyrThreshold, tmpHue, tmpChr, skinprot, b_l, t_l, t_r); + } + + idirpyr_eq_channel(dirpyrlo[0], dst, buffer, srcwidth, srcheight, 0, multi[0], dirpyrThreshold, tmpHue, tmpChr, skinprot, b_l, t_l, t_r); + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < srcheight; i++) { + for (int j = 0; j < srcwidth; j++) { + dst[i][j] = buffer[i][j]; + } + } } -// float hipass = (data_fine[i][j]-data_coarse[i][j]); -// buffer[i][j] += irangefn[hipass+0x10000] * hipass ; +void ImProcFunctions::dirpyr_equalizercam(const CieImage *ncie, float ** src, float ** dst, int srcwidth, int srcheight, const float * const * h_p, const float * const * C_p, const double * mult, const double dirpyrThreshold, const double skinprot, float b_l, float t_l, float t_r, int scaleprev) +{ -#undef DIRWT_L -#undef DIRWT_AB + //sequence of scales + constexpr int maxlevel = 6; + constexpr int scales[maxlevel] = {1, 2, 4, 8, 16, 32}; + const float atten123 = rtengine::LIM(settings->level123_cbdl, 0.f, 50.f); + const float atten0 = rtengine::LIM(settings->level0_cbdl, 0.f, 40.f); -#undef NRWT_L -#undef NRWT_AB + int lastlevel = maxlevel; + while (fabs(mult[lastlevel - 1] - 1) < 0.001 && lastlevel > 0) { + --lastlevel; + } + if (lastlevel == 0) { + return; + } + + float multi[maxlevel]; + + for (int lv = 0; lv < maxlevel; lv++) { + if (scales[lv] < scaleprev) { + const float factor = lv >= 1 ? atten123 : atten0; + multi[lv] = (factor * ((float) mult[lv] - 1.f) / 100.f) + 1.f; + } else { + multi[lv] = mult[lv]; + } + } + + multi_array2D dirpyrlo (srcwidth, srcheight); + + dirpyr_channel(src, dirpyrlo[0], srcwidth, srcheight, 0, std::max(scales[0] / scaleprev, 1)); + + for (int level = 1; level < lastlevel; ++level) { + dirpyr_channel(dirpyrlo[level - 1], dirpyrlo[level], srcwidth, srcheight, level, std::max(scales[level] / scaleprev, 1)); + } + + // with the current implementation of idirpyr_eq_channel we can safely use the buffer from last level as buffer, saves some memory + float ** buffer = dirpyrlo[lastlevel - 1]; + + for (int level = lastlevel - 1; level > 0; --level) { + idirpyr_eq_channelcam(dirpyrlo[level], dirpyrlo[level - 1], buffer, srcwidth, srcheight, level, multi[level], dirpyrThreshold , h_p, C_p, skinprot, b_l, t_l, t_r); + } + + idirpyr_eq_channelcam(dirpyrlo[0], dst, buffer, srcwidth, srcheight, 0, multi[0], dirpyrThreshold, h_p, C_p, skinprot, b_l, t_l, t_r); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int i = 0; i < srcheight; i++) { + for (int j = 0; j < srcwidth; j++) { + if (ncie->J_p[i][j] > 8.f && ncie->J_p[i][j] < 92.f) { + dst[i][j] = buffer[i][j]; + } else { + dst[i][j] = src[i][j]; + } + } + } } +} diff --git a/rtengine/dual_demosaic_RT.cc b/rtengine/dual_demosaic_RT.cc index 4873ee670..60cce506b 100644 --- a/rtengine/dual_demosaic_RT.cc +++ b/rtengine/dual_demosaic_RT.cc @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// diff --git a/rtengine/dynamicprofile.cc b/rtengine/dynamicprofile.cc index 7939936e9..00a15c3e2 100644 --- a/rtengine/dynamicprofile.cc +++ b/rtengine/dynamicprofile.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "../rtengine/dynamicprofile.h" diff --git a/rtengine/dynamicprofile.h b/rtengine/dynamicprofile.h index fc5c85e4c..aaffc5c4f 100644 --- a/rtengine/dynamicprofile.h +++ b/rtengine/dynamicprofile.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _DYNAMICPROFILE_H_ #define _DYNAMICPROFILE_H_ diff --git a/rtengine/eahd_demosaic.cc b/rtengine/eahd_demosaic.cc index 1663a087d..aa8fdf485 100644 --- a/rtengine/eahd_demosaic.cc +++ b/rtengine/eahd_demosaic.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtengine/ex1simple.cc b/rtengine/ex1simple.cc deleted file mode 100644 index ddaa89177..000000000 --- a/rtengine/ex1simple.cc +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is part of RawTherapee. - * - * Copyright (c) 2004-2010 Gabor Horvath - * - * RawTherapee is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RawTherapee is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - */ -#include "rtengine.h" -#include -//#include -#include - -class PListener : - public rtengine::ProgressListener -{ -public: - void setProgressStr(const Glib::ustring& str) - { - std::cout << str << std::endl; - } - void setProgress (double p) - { - std::cout << p << std::endl; - } - void setProgressState(bool inProcessing) - { - } - void error(const Glib::ustring& descr) - { - } -}; - -int main (int argc, char* argv[]) -{ - if (argc < 4) { - std::cout << "Usage: rtcmd " << std::endl; - exit(1); - } - - Glib::thread_init (); - - // create and fill settings - rtengine::Settings* s = rtengine::Settings::create (); - s->demosaicMethod = "hphd"; - s->colorCorrectionSteps = 2; - s->iccDirectory = ""; - s->colorimetricIntent = 1; - s->monitorProfile = ""; - // init rtengine - rtengine::init (s); - // the settings can be modified later through the "s" pointer without calling any api function - - // Create a listener object. Any class is appropriate that inherits from rtengine::ProgressListener - PListener pl; - - // Load the image given in the first command line parameter - rtengine::InitialImage* ii; - int errorCode; - ii = rtengine::InitialImage::load (argv[1], true, errorCode, &pl); - - if (!ii) { - ii = rtengine::InitialImage::load (argv[1], false, errorCode, &pl); - } - - if (!ii) { - std::cout << "Input file not supported." << std::endl; - exit(2); - } - - // create an instance of ProcParams structure that holds the image processing settings. You find the memory map in a separate file and the non-basic types like strings and vectors can be manipulated through helper functions - rtengine::procparams::ProcParams params; - params.load (argv[2]); - - /* First, simplest scenario. Develop image and save it in a file */ - // create a processing job with the loaded image and the current processing parameters - rtengine::ProcessingJob* job = ProcessingJob::create (i, params); - // process image. The error is given back in errorcode. - rtengine::IImage16* res = rtengine::processImage (job, errorCode, &pl); - // save image to disk - res->saveToFile (argv[3]); - // through "res" you can access width/height and pixel data, too -} - diff --git a/rtengine/fast_demo.cc b/rtengine/fast_demo.cc index 4e3fbdabe..a40f107af 100644 --- a/rtengine/fast_demo.cc +++ b/rtengine/fast_demo.cc @@ -18,7 +18,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// diff --git a/rtengine/ffmanager.cc b/rtengine/ffmanager.cc index 3de343198..910aada77 100644 --- a/rtengine/ffmanager.cc +++ b/rtengine/ffmanager.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "ffmanager.h" #include "../rtgui/options.h" @@ -277,8 +277,8 @@ void FFManager::init(const Glib::ustring& pathname) } else { printf( "%s: MEAN of \n ", i.key().c_str()); - for( std::list::iterator iter = i.pathNames.begin(); iter != i.pathNames.end(); ++iter ) { - printf( "%s, ", iter->c_str() ); + for(std::list::iterator path = i.pathNames.begin(); path != i.pathNames.end(); ++path) { + printf("%s, ", path->c_str()); } printf("\n"); diff --git a/rtengine/ffmanager.h b/rtengine/ffmanager.h index 9068216ef..537f8ee46 100644 --- a/rtengine/ffmanager.h +++ b/rtengine/ffmanager.h @@ -14,12 +14,16 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ -#include -#include -#include +#pragma once + #include +#include +#include + +#include + #include "rawimage.h" namespace rtengine diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc new file mode 100644 index 000000000..4293c6b2a --- /dev/null +++ b/rtengine/filmnegativeproc.cc @@ -0,0 +1,403 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2019 Alberto Romei + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include +#include + +#ifdef _OPENMP +#include +#endif + +#include "rawimagesource.h" + +#include "mytime.h" +#include "opthelper.h" +#include "procparams.h" +#include "rt_algo.h" +#include "rtengine.h" + +//#define BENCHMARK +#include "StopWatch.h" + +namespace rtengine +{ + +extern const Settings* settings; + +} + +namespace +{ + +bool channelsAvg( + const rtengine::RawImage* ri, + int width, + int height, + const float* cblacksom, + rtengine::Coord spotPos, + int spotSize, + const rtengine::procparams::FilmNegativeParams& params, + std::array& avgs +) +{ + avgs = {}; // Channel averages + + if (ri->getSensorType() != rtengine::ST_BAYER && ri->getSensorType() != rtengine::ST_FUJI_XTRANS) { + return false; + } + + if (rtengine::settings->verbose) { + printf("Spot coord: x=%d y=%d\n", spotPos.x, spotPos.y); + } + + const int half_spot_size = spotSize / 2; + + const int& x1 = spotPos.x - half_spot_size; + const int& x2 = spotPos.x + half_spot_size; + const int& y1 = spotPos.y - half_spot_size; + const int& y2 = spotPos.y + half_spot_size; + + if (x1 < 0 || x2 > width || y1 < 0 || y2 > height) { + return false; // Spot goes outside bounds, bail out. + } + + std::array pxCount = {}; // Per-channel sample counts + for (int c = x1; c < x2; ++c) { + for (int r = y1; r < y2; ++r) { + const int ch = ri->getSensorType() == rtengine::ST_BAYER ? ri->FC(r,c) : ri->XTRANSFC(r,c); + + ++pxCount[ch]; + + // Sample the original unprocessed values from RawImage, subtracting black levels. + // Scaling is irrelevant, as we are only interested in the ratio between two spots. + avgs[ch] += ri->data[r][c] - cblacksom[ch]; + } + } + + for (int ch = 0; ch < 3; ++ch) { + avgs[ch] /= pxCount[ch]; + } + + return true; +} + +} + +bool rtengine::RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, std::array& newExps) +{ + newExps = { + static_cast(currentParams.redRatio * currentParams.greenExp), + static_cast(currentParams.greenExp), + static_cast(currentParams.blueRatio * currentParams.greenExp) + }; + + constexpr int spotSize = 32; // TODO: Make this configurable? + + Coord spot; + std::array clearVals; + std::array denseVals; + + // Sample first spot + transformPosition(spotA.x, spotA.y, tran, spot.x, spot.y); + if (!channelsAvg(ri, W, H, cblacksom, spot, spotSize, currentParams, clearVals)) { + return false; + } + + // Sample second spot + transformPosition(spotB.x, spotB.y, tran, spot.x, spot.y); + if (!channelsAvg(ri, W, H, cblacksom, spot, spotSize, currentParams, denseVals)) { + return false; + } + + // Detect which one is the dense spot, based on green channel + if (clearVals[1] < denseVals[1]) { + std::swap(clearVals, denseVals); + } + + if (settings->verbose) { + printf("Clear film values: R=%g G=%g B=%g\n", clearVals[0], clearVals[1], clearVals[2]); + printf("Dense film values: R=%g G=%g B=%g\n", denseVals[0], denseVals[1], denseVals[2]); + } + + const float denseGreenRatio = clearVals[1] / denseVals[1]; + + // Calculate logarithms in arbitrary base + const auto logBase = + [](float base, float num) -> float + { + return std::log(num) / std::log(base); + }; + + // Calculate exponents for each channel, based on the ratio between the bright and dark values, + // compared to the ratio in the reference channel (green) + for (int ch = 0; ch < 3; ++ch) { + if (ch == 1) { + newExps[ch] = 1.f; // Green is the reference channel + } else { + newExps[ch] = CLAMP(logBase(clearVals[ch] / denseVals[ch], denseGreenRatio), 0.3f, 4.f); + } + } + + if (settings->verbose) { + printf("New exponents: R=%g G=%g B=%g\n", newExps[0], newExps[1], newExps[2]); + } + + return true; +} + +void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams ¶ms) +{ +// BENCHFUNMICRO + + if (!params.enabled) { + return; + } + + // Exponents are expressed as positive in the parameters, so negate them in order + // to get the reciprocals. + const std::array exps = { + static_cast(-params.redRatio * params.greenExp), + static_cast(-params.greenExp), + static_cast(-params.blueRatio * params.greenExp) + }; + + MyTime t1, t2, t3,t4, t5; + + t1.set(); + + // Channel vectors to calculate medians + std::array, 3> cvs; + + // Sample one every 5 pixels, and push the value in the appropriate channel vector. + // Choose an odd step, not a multiple of the CFA size, to get a chance to visit each channel. + if (ri->getSensorType() == ST_BAYER) { + for (int row = 0; row < H; row += 5) { + const int c0 = ri->FC(row, 0); + const int c1 = ri->FC(row, 5); + int col = 0; + for (; col < W - 5; col += 10) { + cvs[c0].push_back(rawData[row][col]); + cvs[c1].push_back(rawData[row][col + 5]); + } + if (col < W) { + cvs[c0].push_back(rawData[row][col]); + } + } + } + else if (ri->getSensorType() == ST_FUJI_XTRANS) { + for (int row = 0; row < H; row += 5) { + const std::array cs = { + ri->XTRANSFC(row, 0), + ri->XTRANSFC(row, 5), + ri->XTRANSFC(row, 10), + ri->XTRANSFC(row, 15), + ri->XTRANSFC(row, 20), + ri->XTRANSFC(row, 25) + }; + int col = 0; + for (; col < W - 25; col += 30) { + for (int c = 0; c < 6; ++c) { + cvs[cs[c]].push_back(rawData[row][col + c * 5]); + } + } + for (int c = 0; col < W; col += 5, ++c) { + cvs[cs[c]].push_back(rawData[row][col]); + } + } + } + + constexpr float MAX_OUT_VALUE = 65000.f; + + t2.set(); + + if (settings->verbose) { + printf("Median vector fill loop time us: %d\n", t2.etime(t1)); + } + + t2.set(); + + std::array medians; // Channel median values + std::array mults = { + 1.f, + 1.f, + 1.f + }; // Channel normalization multipliers + + for (int c = 0; c < 3; ++c) { + // Find median values for each channel + if (!cvs[c].empty()) { + findMinMaxPercentile(cvs[c].data(), cvs[c].size(), 0.5f, medians[c], 0.5f, medians[c], true); + medians[c] = pow_F(rtengine::max(medians[c], 1.f), exps[c]); + // Determine the channel multiplier so that N times the median becomes 65k. This clips away + // the values in the dark border surrounding the negative (due to the film holder, for example), + // the reciprocal of which have blown up to stellar values. + mults[c] = MAX_OUT_VALUE / (medians[c] * 24.f); + } + } + + t3.set(); + + if (settings->verbose) { + printf("Sample count: %zu, %zu, %zu\n", cvs[0].size(), cvs[1].size(), cvs[2].size()); + printf("Medians: %g %g %g\n", medians[0], medians[1], medians[2] ); + printf("Computed multipliers: %g %g %g\n", mults[0], mults[1], mults[2] ); + printf("Median calc time us: %d\n", t3.etime(t2)); + } + + constexpr float CLIP_VAL = 65535.f; + + t3.set(); + + if (ri->getSensorType() == ST_BAYER) { +#ifdef __SSE2__ + const vfloat onev = F2V(1.f); + const vfloat clipv = F2V(CLIP_VAL); +#endif + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) +#endif + for (int row = 0; row < H; ++row) { + int col = 0; + // Avoid trouble with zeroes, minimum pixel value is 1. + const float exps0 = exps[FC(row, col)]; + const float exps1 = exps[FC(row, col + 1)]; + const float mult0 = mults[FC(row, col)]; + const float mult1 = mults[FC(row, col + 1)]; +#ifdef __SSE2__ + const vfloat expsv = _mm_setr_ps(exps0, exps1, exps0, exps1); + const vfloat multsv = _mm_setr_ps(mult0, mult1, mult0, mult1); + for (; col < W - 3; col += 4) { + STVFU(rawData[row][col], vminf(multsv * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv), clipv)); + } +#endif // __SSE2__ + for (; col < W - 1; col += 2) { + rawData[row][col] = rtengine::min(mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0), CLIP_VAL); + rawData[row][col + 1] = rtengine::min(mult1 * pow_F(rtengine::max(rawData[row][col + 1], 1.f), exps1), CLIP_VAL); + } + if (col < W) { + rawData[row][col] = rtengine::min(mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0), CLIP_VAL); + } + } + } else if (ri->getSensorType() == ST_FUJI_XTRANS) { +#ifdef __SSE2__ + const vfloat onev = F2V(1.f); + const vfloat clipv = F2V(CLIP_VAL); +#endif + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) +#endif + for (int row = 0; row < H; row ++) { + int col = 0; + // Avoid trouble with zeroes, minimum pixel value is 1. + const std::array expsc = { + exps[ri->XTRANSFC(row, 0)], + exps[ri->XTRANSFC(row, 1)], + exps[ri->XTRANSFC(row, 2)], + exps[ri->XTRANSFC(row, 3)], + exps[ri->XTRANSFC(row, 4)], + exps[ri->XTRANSFC(row, 5)] + }; + const std::array multsc = { + mults[ri->XTRANSFC(row, 0)], + mults[ri->XTRANSFC(row, 1)], + mults[ri->XTRANSFC(row, 2)], + mults[ri->XTRANSFC(row, 3)], + mults[ri->XTRANSFC(row, 4)], + mults[ri->XTRANSFC(row, 5)] + }; +#ifdef __SSE2__ + const vfloat expsv0 = _mm_setr_ps(expsc[0], expsc[1], expsc[2], expsc[3]); + const vfloat expsv1 = _mm_setr_ps(expsc[4], expsc[5], expsc[0], expsc[1]); + const vfloat expsv2 = _mm_setr_ps(expsc[2], expsc[3], expsc[4], expsc[5]); + const vfloat multsv0 = _mm_setr_ps(multsc[0], multsc[1], multsc[2], multsc[3]); + const vfloat multsv1 = _mm_setr_ps(multsc[4], multsc[5], multsc[0], multsc[1]); + const vfloat multsv2 = _mm_setr_ps(multsc[2], multsc[3], multsc[4], multsc[5]); + for (; col < W - 11; col += 12) { + STVFU(rawData[row][col], vminf(multsv0 * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv0), clipv)); + STVFU(rawData[row][col + 4], vminf(multsv1 * pow_F(vmaxf(LVFU(rawData[row][col + 4]), onev), expsv1), clipv)); + STVFU(rawData[row][col + 8], vminf(multsv2 * pow_F(vmaxf(LVFU(rawData[row][col + 8]), onev), expsv2), clipv)); + } +#endif // __SSE2__ + for (; col < W - 5; col += 6) { + for (int c = 0; c < 6; ++c) { + rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]), CLIP_VAL); + } + } + for (int c = 0; col < W; col++, c++) { + rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]), CLIP_VAL); + } + } + } + + t4.set(); + + if (settings->verbose) { + printf("Pow loop time us: %d\n", t4.etime(t3)); + } + + t4.set(); + + PixelsMap bitmapBads(W, H); + + int totBP = 0; // Hold count of bad pixels to correct + + if (ri->getSensorType() == ST_BAYER) { +#ifdef _OPENMP + #pragma omp parallel for reduction(+:totBP) schedule(dynamic,16) +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + if (rawData[i][j] >= MAX_OUT_VALUE) { + bitmapBads.set(j, i); + ++totBP; + } + } + } + + if (totBP > 0) { + interpolateBadPixelsBayer(bitmapBads, rawData); + } + + } + else if (ri->getSensorType() == ST_FUJI_XTRANS) { +#ifdef _OPENMP + #pragma omp parallel for reduction(+:totBP) schedule(dynamic,16) +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + if (rawData[i][j] >= MAX_OUT_VALUE) { + bitmapBads.set(j, i); + totBP++; + } + } + } + + if (totBP > 0) { + interpolateBadPixelsXtrans(bitmapBads); + } + } + + t5.set(); + + if (settings->verbose) { + printf("Bad pixels count: %d\n", totBP); + printf("Bad pixels interpolation time us: %d\n", t5.etime(t4)); + } +} diff --git a/rtengine/filmnegativethumb.cc b/rtengine/filmnegativethumb.cc new file mode 100644 index 000000000..6a4da31b0 --- /dev/null +++ b/rtengine/filmnegativethumb.cc @@ -0,0 +1,130 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2019 Alberto Romei + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include + +#include "rtengine.h" +#include "rtthumbnail.h" +#include "opthelper.h" +#include "rt_algo.h" +#include "rtengine.h" +#include "settings.h" +#include "procparams.h" +#define BENCHMARK +#include "StopWatch.h" + +namespace rtengine +{ + +extern const Settings* settings; + +} + +void rtengine::Thumbnail::processFilmNegative( + const procparams::ProcParams ¶ms, + const Imagefloat* baseImg, + const int rwidth, const int rheight, + float &rmi, float &gmi, float &bmi +) { + + // Channel exponents + const float rexp = -params.filmNegative.redRatio * params.filmNegative.greenExp; + const float gexp = -params.filmNegative.greenExp; + const float bexp = -params.filmNegative.blueRatio * params.filmNegative.greenExp; + + // Need to calculate channel averages, to fake the same conditions + // found in rawimagesource, where get_ColorsCoeff is called with + // forceAutoWB=true. + float rsum = 0.f, gsum = 0.f, bsum = 0.f; + + // Channel vectors to calculate medians + std::vector rv, gv, bv; + + for (int i = 0; i < rheight; i++) { + for (int j = 0; j < rwidth; j++) { + const float r = baseImg->r(i, j); + const float g = baseImg->g(i, j); + const float b = baseImg->b(i, j); + + rsum += r; + gsum += g; + bsum += b; + + rv.push_back(r); + gv.push_back(g); + bv.push_back(b); + } + } + + const float ravg = rsum / (rheight*rwidth); + const float gavg = gsum / (rheight*rwidth); + const float bavg = bsum / (rheight*rwidth); + + // Shifting current WB multipliers, based on channel averages. + rmi /= (gavg/ravg); + // gmi /= (gAvg/gAvg); green chosen as reference channel + bmi /= (gavg/bavg); + + float rmed, gmed, bmed; + findMinMaxPercentile(rv.data(), rv.size(), 0.5f, rmed, 0.5f, rmed, true); + findMinMaxPercentile(gv.data(), gv.size(), 0.5f, gmed, 0.5f, gmed, true); + findMinMaxPercentile(bv.data(), bv.size(), 0.5f, bmed, 0.5f, bmed, true); + + rmed = powf(rmed, rexp); + gmed = powf(gmed, gexp); + bmed = powf(bmed, bexp); + + const float MAX_OUT_VALUE = 65000.f; + const float rmult = (MAX_OUT_VALUE / (rmed * 24)) ; + const float gmult = (MAX_OUT_VALUE / (gmed * 24)) ; + const float bmult = (MAX_OUT_VALUE / (bmed * 24)) ; + + if (settings->verbose) { + printf("Thumbnail channel medians: %g %g %g\n", rmed, gmed, bmed); + printf("Thumbnail computed multipliers: %g %g %g\n", rmult, gmult, bmult); + } + +#ifdef __SSE2__ + const vfloat clipv = F2V(MAXVALF); + const vfloat rexpv = F2V(rexp); + const vfloat gexpv = F2V(gexp); + const vfloat bexpv = F2V(bexp); + const vfloat rmultv = F2V(rmult); + const vfloat gmultv = F2V(gmult); + const vfloat bmultv = F2V(bmult); +#endif + + for (int i = 0; i < rheight; i++) { + float *rline = baseImg->r(i); + float *gline = baseImg->g(i); + float *bline = baseImg->b(i); + int j = 0; +#ifdef __SSE2__ + for (; j < rwidth - 3; j +=4) { + STVFU(rline[j], vminf(rmultv * pow_F(LVFU(rline[j]), rexpv), clipv)); + STVFU(gline[j], vminf(gmultv * pow_F(LVFU(gline[j]), gexpv), clipv)); + STVFU(bline[j], vminf(bmultv * pow_F(LVFU(bline[j]), bexpv), clipv)); + } +#endif + for (; j < rwidth; ++j) { + rline[j] = CLIP(rmult * pow_F(rline[j], rexp)); + gline[j] = CLIP(gmult * pow_F(gline[j], gexp)); + bline[j] = CLIP(bmult * pow_F(bline[j], bexp)); + } + } +} diff --git a/rtengine/flatcurves.cc b/rtengine/flatcurves.cc index fe5ecc5e1..d24c20a70 100644 --- a/rtengine/flatcurves.cc +++ b/rtengine/flatcurves.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "curves.h" #include diff --git a/rtengine/gamutwarning.cc b/rtengine/gamutwarning.cc index c76e2a285..3fc20d43a 100644 --- a/rtengine/gamutwarning.cc +++ b/rtengine/gamutwarning.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ /** diff --git a/rtengine/gamutwarning.h b/rtengine/gamutwarning.h index 19a27cdfd..e0aaa98d9 100644 --- a/rtengine/gamutwarning.h +++ b/rtengine/gamutwarning.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ /** diff --git a/rtengine/gauss.cc b/rtengine/gauss.cc index b7de67851..ca330f9b9 100644 --- a/rtengine/gauss.cc +++ b/rtengine/gauss.cc @@ -14,17 +14,59 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "gauss.h" +#include "rt_math.h" #include #include #include "opthelper.h" #include "boxblur.h" - namespace { +void compute7x7kernel(float sigma, float kernel[7][7]) { + const double temp = -2.f * rtengine::SQR(sigma); + float sum = 0.f; + for (int i = -3; i <= 3; ++i) { + for (int j = -3; j <= 3; ++j) { + if((rtengine::SQR(i) + rtengine::SQR(j)) <= rtengine::SQR(3.0 * 1.15)) { + kernel[i + 3][j + 3] = std::exp((rtengine::SQR(i) + rtengine::SQR(j)) / temp); + sum += kernel[i + 3][j + 3]; + } else { + kernel[i + 3][j + 3] = 0.f; + } + } + } + + for (int i = 0; i < 7; ++i) { + for (int j = 0; j < 7; ++j) { + kernel[i][j] /= sum; + } + } +} + +void compute5x5kernel(float sigma, float kernel[5][5]) { + const double temp = -2.f * rtengine::SQR(sigma); + float sum = 0.f; + for (int i = -2; i <= 2; ++i) { + for (int j = -2; j <= 2; ++j) { + if((rtengine::SQR(i) + rtengine::SQR(j)) <= rtengine::SQR(3.0 * 0.84)) { + kernel[i + 2][j + 2] = std::exp((rtengine::SQR(i) + rtengine::SQR(j)) / temp); + sum += kernel[i + 2][j + 2]; + } else { + kernel[i + 2][j + 2] = 0.f; + } + } + } + + for (int i = 0; i < 5; ++i) { + for (int j = 0; j < 5; ++j) { + kernel[i][j] /= sum; + } + } +} + template void calculateYvVFactors( const T sigma, T &b1, T &b2, T &b3, T &B, T M[3][3]) { // coefficient calculation @@ -207,6 +249,174 @@ template void gauss3x3div (T** RESTRICT src, T** RESTRICT dst, T** REST } } +template void gauss7x7div (T** RESTRICT src, T** RESTRICT dst, T** RESTRICT divBuffer, const int W, const int H, float sigma) +{ + + float kernel[7][7]; + compute7x7kernel(sigma, kernel); + + const float c31 = kernel[0][2]; + const float c30 = kernel[0][3]; + const float c22 = kernel[1][1]; + const float c21 = kernel[1][2]; + const float c20 = kernel[1][3]; + const float c11 = kernel[2][2]; + const float c10 = kernel[2][3]; + const float c00 = kernel[3][3]; + +#ifdef _OPENMP + #pragma omp for schedule(dynamic, 16) nowait +#endif + + for (int i = 3; i < H - 3; ++i) { + dst[i][0] = dst[i][1] = dst[i][2] = 1.f; + // I tried hand written SSE code but gcc vectorizes better + for (int j = 3; j < W - 3; ++j) { + const float val = c31 * (src[i - 3][j - 1] + src[i - 3][j + 1] + src[i - 1][j - 3] + src[i - 1][j + 3] + src[i + 1][j - 3] + src[i + 1][j + 3] + src[i + 3][j - 1] + src[i + 3][j + 1]) + + c30 * (src[i - 3][j] + src[i][j - 3] + src[i][j + 3] + src[i + 3][j]) + + c22 * (src[i - 2][j - 2] + src[i - 2][j + 2] + src[i + 2][j - 2] + src[i + 2][j + 2]) + + c21 * (src[i - 2][j - 1] + src[i - 2][j + 1] * c21 + src[i - 1][j - 2] + src[i - 1][j + 2] + src[i + 1][j - 2] + src[i + 1][j + 2] + src[i + 2][j - 1] + src[i + 2][j + 1]) + + c20 * (src[i - 2][j] + src[i][j - 2] + src[i][j + 2] + src[i + 2][j]) + + c11 * (src[i - 1][j - 1] + src[i - 1][j + 1] + src[i + 1][j - 1] + src[i + 1][j + 1]) + + c10 * (src[i - 1][j] + src[i][j - 1] + src[i][j + 1] + src[i + 1][j]) + + c00 * src[i][j]; + + dst[i][j] = divBuffer[i][j] / std::max(val, 0.00001f); + } + dst[i][W - 3] = dst[i][W - 2] = dst[i][W - 1] = 1.f; + } + + // first and last rows +#ifdef _OPENMP + #pragma omp single +#endif + { + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < W; ++j) { + dst[i][j] = 1.f; + } + } + for (int i = H - 3 ; i < H; ++i) { + for (int j = 0; j < W; ++j) { + dst[i][j] = 1.f; + } + } + } +} + +template void gauss5x5div (T** RESTRICT src, T** RESTRICT dst, T** RESTRICT divBuffer, const int W, const int H, float sigma) +{ + + float kernel[5][5]; + compute5x5kernel(sigma, kernel); + + const float c21 = kernel[0][1]; + const float c20 = kernel[0][2]; + const float c11 = kernel[1][1]; + const float c10 = kernel[1][2]; + const float c00 = kernel[2][2]; + +#ifdef _OPENMP + #pragma omp for schedule(dynamic, 16) nowait +#endif + + for (int i = 2; i < H - 2; ++i) { + dst[i][0] = dst[i][1] = 1.f; + // I tried hand written SSE code but gcc vectorizes better + for (int j = 2; j < W - 2; ++j) { + const float val = c21 * (src[i - 2][j - 1] + src[i - 2][j + 1] + src[i - 1][j - 2] + src[i - 1][j + 2] + src[i + 1][j - 2] + src[i + 1][j + 2] + src[i + 2][j - 1] + src[i + 2][j + 1]) + + c20 * (src[i - 2][j] + src[i][j - 2] + src[i][j + 2] + src[i + 2][j]) + + c11 * (src[i - 1][j - 1] + src[i - 1][j + 1] + src[i + 1][j - 1] + src[i + 1][j + 1]) + + c10 * (src[i - 1][j] + src[i][j - 1] + src[i][j + 1] + src[i + 1][j]) + + c00 * src[i][j]; + + dst[i][j] = divBuffer[i][j] / std::max(val, 0.00001f); + } + dst[i][W - 2] = dst[i][W - 1] = 1.f; + } + + // first and last rows +#ifdef _OPENMP + #pragma omp single +#endif + { + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < W; ++j) { + dst[i][j] = 1.f; + } + } + for (int i = H - 2 ; i < H; ++i) { + for (int j = 0; j < W; ++j) { + dst[i][j] = 1.f; + } + } + } +} + +template void gauss7x7mult (T** RESTRICT src, T** RESTRICT dst, const int W, const int H, float sigma) +{ + + float kernel[7][7]; + compute7x7kernel(sigma, kernel); + const float c31 = kernel[0][2]; + const float c30 = kernel[0][3]; + const float c22 = kernel[1][1]; + const float c21 = kernel[1][2]; + const float c20 = kernel[1][3]; + const float c11 = kernel[2][2]; + const float c10 = kernel[2][3]; + const float c00 = kernel[3][3]; + +#ifdef _OPENMP + #pragma omp for schedule(dynamic, 16) +#endif + + for (int i = 3; i < H - 3; ++i) { + // I tried hand written SSE code but gcc vectorizes better + for (int j = 3; j < W - 3; ++j) { + const float val = c31 * (src[i - 3][j - 1] + src[i - 3][j + 1] + src[i - 1][j - 3] + src[i - 1][j + 3] + src[i + 1][j - 3] + src[i + 1][j + 3] + src[i + 3][j - 1] + src[i + 3][j + 1]) + + c30 * (src[i - 3][j] + src[i][j - 3] + src[i][j + 3] + src[i + 3][j]) + + c22 * (src[i - 2][j - 2] + src[i - 2][j + 2] + src[i + 2][j - 2] + src[i + 2][j + 2]) + + c21 * (src[i - 2][j - 1] + src[i - 2][j + 1] * c21 + src[i - 1][j - 2] + src[i - 1][j + 2] + src[i + 1][j - 2] + src[i + 1][j + 2] + src[i + 2][j - 1] + src[i + 2][j + 1]) + + c20 * (src[i - 2][j] + src[i][j - 2] + src[i][j + 2] + src[i + 2][j]) + + c11 * (src[i - 1][j - 1] + src[i - 1][j + 1] + src[i + 1][j - 1] + src[i + 1][j + 1]) + + c10 * (src[i - 1][j] + src[i][j - 1] + src[i][j + 1] + src[i + 1][j]) + + c00 * src[i][j]; + + dst[i][j] *= val; + } + } +} + +template void gauss5x5mult (T** RESTRICT src, T** RESTRICT dst, const int W, const int H, float sigma) +{ + + float kernel[5][5]; + compute5x5kernel(sigma, kernel); + + const float c21 = kernel[0][1]; + const float c20 = kernel[0][2]; + const float c11 = kernel[1][1]; + const float c10 = kernel[1][2]; + const float c00 = kernel[2][2]; + +#ifdef _OPENMP + #pragma omp for schedule(dynamic, 16) +#endif + + for (int i = 2; i < H - 2; ++i) { + // I tried hand written SSE code but gcc vectorizes better + for (int j = 2; j < W - 2; ++j) { + const float val = c21 * (src[i - 2][j - 1] + src[i - 2][j + 1] + src[i - 1][j - 2] + src[i - 1][j + 2] + src[i + 1][j - 2] + src[i + 1][j + 2] + src[i + 2][j - 1] + src[i + 2][j + 1]) + + c20 * (src[i - 2][j] + src[i][j - 2] + src[i][j + 2] + src[i + 2][j]) + + c11 * (src[i - 1][j - 1] + src[i - 1][j + 1] + src[i + 1][j - 1] + src[i + 1][j + 1]) + + c10 * (src[i - 1][j] + src[i][j - 1] + src[i][j + 1] + src[i + 1][j]) + + c00 * src[i][j]; + + dst[i][j] *= val; + } + } +} // use separated filter if the support window is small and src == dst template void gaussHorizontal3 (T** src, T** dst, int W, int H, const float c0, const float c1) @@ -1143,6 +1353,8 @@ template void gaussianBlurImpl(T** src, T** dst, const int W, const int { static constexpr auto GAUSS_SKIP = 0.25; static constexpr auto GAUSS_3X3_LIMIT = 0.6; + static constexpr auto GAUSS_5X5_LIMIT = 0.84; + static constexpr auto GAUSS_7X7_LIMIT = 1.15; static constexpr auto GAUSS_DOUBLE = 25.0; if(buffer) { @@ -1241,14 +1453,26 @@ template void gaussianBlurImpl(T** src, T** dst, const int W, const int if (sigma < GAUSS_DOUBLE) { switch (gausstype) { case GAUSS_MULT : { - gaussHorizontalSse (src, src, W, H, sigma); - gaussVerticalSsemult (src, dst, W, H, sigma); + if (sigma <= GAUSS_5X5_LIMIT && src != dst) { + gauss5x5mult(src, dst, W, H, sigma); + } else if (sigma <= GAUSS_7X7_LIMIT && src != dst) { + gauss7x7mult(src, dst, W, H, sigma); + } else { + gaussHorizontalSse (src, src, W, H, sigma); + gaussVerticalSsemult (src, dst, W, H, sigma); + } break; } case GAUSS_DIV : { - gaussHorizontalSse (src, dst, W, H, sigma); - gaussVerticalSsediv (dst, dst, buffer2, W, H, sigma); + if (sigma <= GAUSS_5X5_LIMIT && src != dst) { + gauss5x5div (src, dst, buffer2, W, H, sigma); + } else if (sigma <= GAUSS_7X7_LIMIT && src != dst) { + gauss7x7div (src, dst, buffer2, W, H, sigma); + } else { + gaussHorizontalSse (src, dst, W, H, sigma); + gaussVerticalSsediv (dst, dst, buffer2, W, H, sigma); + } break; } @@ -1268,14 +1492,26 @@ template void gaussianBlurImpl(T** src, T** dst, const int W, const int if (sigma < GAUSS_DOUBLE) { switch (gausstype) { case GAUSS_MULT : { - gaussHorizontal (src, src, W, H, sigma); - gaussVerticalmult (src, dst, W, H, sigma); + if (sigma <= GAUSS_5X5_LIMIT && src != dst) { + gauss5x5mult(src, dst, W, H, sigma); + } else if (sigma <= GAUSS_7X7_LIMIT && src != dst) { + gauss7x7mult(src, dst, W, H, sigma); + } else { + gaussHorizontal (src, src, W, H, sigma); + gaussVerticalmult (src, dst, W, H, sigma); + } break; } case GAUSS_DIV : { - gaussHorizontal (src, dst, W, H, sigma); - gaussVerticaldiv (dst, dst, buffer2, W, H, sigma); + if (sigma <= GAUSS_5X5_LIMIT && src != dst) { + gauss5x5div (src, dst, buffer2, W, H, sigma); + } else if (sigma <= GAUSS_7X7_LIMIT && src != dst) { + gauss7x7div (src, dst, buffer2, W, H, sigma); + } else { + gaussHorizontal (src, dst, W, H, sigma); + gaussVerticaldiv (dst, dst, buffer2, W, H, sigma); + } break; } diff --git a/rtengine/gauss.h b/rtengine/gauss.h index 72f115cc4..b63301d2b 100644 --- a/rtengine/gauss.h +++ b/rtengine/gauss.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _GAUSS_H_ #define _GAUSS_H_ diff --git a/rtengine/green_equil_RT.cc b/rtengine/green_equil_RT.cc index 361bde882..fc4f18548 100644 --- a/rtengine/green_equil_RT.cc +++ b/rtengine/green_equil_RT.cc @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// diff --git a/rtengine/guidedfilter.cc b/rtengine/guidedfilter.cc index e7fe9b8af..159e89504 100644 --- a/rtengine/guidedfilter.cc +++ b/rtengine/guidedfilter.cc @@ -3,6 +3,7 @@ * This file is part of RawTherapee. * * Copyright (c) 2018 Alberto Griggio + * Optimized 2019 Ingo Weyrich * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,10 +16,10 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - */ + * along with RawTherapee. If not, see . +*/ -/** +/* * This is a Fast Guided Filter implementation, derived directly from the * pseudo-code of the paper: * @@ -26,32 +27,16 @@ * by Kaiming He, Jian Sun * * available at https://arxiv.org/abs/1505.00996 - */ +*/ #include "guidedfilter.h" #include "boxblur.h" #include "rescale.h" #include "imagefloat.h" - +#define BENCHMARK +#include "StopWatch.h" namespace rtengine { -#if 0 -# define DEBUG_DUMP(arr) \ - do { \ - Imagefloat im(arr.width(), arr.height()); \ - const char *out = "/tmp/" #arr ".tif"; \ - for (int y = 0; y < im.getHeight(); ++y) { \ - for (int x = 0; x < im.getWidth(); ++x) { \ - im.r(y, x) = im.g(y, x) = im.b(y, x) = arr[y][x] * 65535.f; \ - } \ - } \ - im.saveTIFF(out, 16); \ - } while (false) -#else -# define DEBUG_DUMP(arr) -#endif - - namespace { int calculate_subsampling(int w, int h, int r) @@ -78,18 +63,10 @@ int calculate_subsampling(int w, int h, int r) void guidedFilter(const array2D &guide, const array2D &src, array2D &dst, int r, float epsilon, bool multithread, int subsampling) { - - const int W = src.width(); - const int H = src.height(); - - if (subsampling <= 0) { - subsampling = calculate_subsampling(W, H, r); - } - - enum Op { MUL, DIVEPSILON, ADD, SUB, ADDMUL, SUBMUL }; + enum Op {MUL, DIVEPSILON, SUBMUL}; const auto apply = - [=](Op op, array2D &res, const array2D &a, const array2D &b, const array2D &c=array2D()) -> void + [multithread, epsilon](Op op, array2D &res, const array2D &a, const array2D &b, const array2D &c=array2D()) -> void { const int w = res.width(); const int h = res.height(); @@ -99,137 +76,109 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 #endif for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { - float r; - float aa = a[y][x]; - float bb = b[y][x]; switch (op) { - case MUL: - r = aa * bb; - break; - case DIVEPSILON: - r = aa / (bb + epsilon); - break; - case ADD: - r = aa + bb; - break; - case SUB: - r = aa - bb; - break; - case ADDMUL: - r = aa * bb + c[y][x]; - break; - case SUBMUL: - r = c[y][x] - (aa * bb); - break; - default: - assert(false); - r = 0; - break; + case MUL: + res[y][x] = a[y][x] * b[y][x]; + break; + case DIVEPSILON: + res[y][x] = a[y][x] / (b[y][x] + epsilon); // note: the value of epsilon intentionally has an impact on the result. It is not only to avoid divisions by zero + break; + case SUBMUL: + res[y][x] = c[y][x] - (a[y][x] * b[y][x]); + break; + default: + assert(false); + res[y][x] = 0; + break; } - res[y][x] = r; } } }; - // use the terminology of the paper (Algorithm 2) - const array2D &I = guide; - const array2D &p = src; - array2D &q = dst; - const auto f_subsample = - [=](array2D &d, const array2D &s) -> void + [multithread](array2D &d, const array2D &s) -> void { rescaleBilinear(s, d, multithread); }; - const auto f_upsample = f_subsample; - - const size_t w = W / subsampling; - const size_t h = H / subsampling; - - AlignedBuffer blur_buf(w * h); const auto f_mean = - [&](array2D &d, array2D &s, int rad) -> void + [multithread](array2D &d, array2D &s, int rad) -> void { rad = LIM(rad, 0, (min(s.width(), s.height()) - 1) / 2 - 1); - float **src = s; - float **dst = d; -#ifdef _OPENMP - #pragma omp parallel if (multithread) -#endif - boxblur(src, dst, blur_buf.data, rad, rad, s.width(), s.height()); + boxblur(s, d, rad, s.width(), s.height(), multithread); }; + const int W = src.width(); + const int H = src.height(); + + if (subsampling <= 0) { + subsampling = calculate_subsampling(W, H, r); + } + + const size_t w = W / subsampling; + const size_t h = H / subsampling; + const float r1 = float(r) / subsampling; + array2D I1(w, h); array2D p1(w, h); - f_subsample(I1, I); - f_subsample(p1, p); + f_subsample(I1, guide); - DEBUG_DUMP(I); - DEBUG_DUMP(p); - DEBUG_DUMP(I1); - DEBUG_DUMP(p1); + if (&guide == &src) { + f_mean(p1, I1, r1); - float r1 = float(r) / subsampling; + apply(MUL, I1, I1, I1); // I1 = I1 * I1 - array2D meanI(w, h); - f_mean(meanI, I1, r1); - DEBUG_DUMP(meanI); + f_mean(I1, I1, r1); - array2D meanp(w, h); - f_mean(meanp, p1, r1); - DEBUG_DUMP(meanp); + apply(SUBMUL, I1, p1, p1, I1); // I1 = I1 - p1 * p1 + apply(DIVEPSILON, I1, I1, I1); // I1 = I1 / (I1 + epsilon) + apply(SUBMUL, p1, I1, p1, p1); // p1 = p1 - I1 * p1 - array2D &corrIp = p1; - apply(MUL, corrIp, I1, p1); - f_mean(corrIp, corrIp, r1); - DEBUG_DUMP(corrIp); + } else { + f_subsample(p1, src); - array2D &corrI = I1; - apply(MUL, corrI, I1, I1); - f_mean(corrI, corrI, r1); - DEBUG_DUMP(corrI); + array2D meanI(w, h); + f_mean(meanI, I1, r1); - array2D &varI = corrI; - apply(SUBMUL, varI, meanI, meanI, corrI); - DEBUG_DUMP(varI); + array2D meanp(w, h); + f_mean(meanp, p1, r1); - array2D &covIp = corrIp; - apply(SUBMUL, covIp, meanI, meanp, corrIp); - DEBUG_DUMP(covIp); + apply(MUL, p1, I1, p1); - array2D &a = varI; - apply(DIVEPSILON, a, covIp, varI); - DEBUG_DUMP(a); + f_mean(p1, p1, r1); - array2D &b = covIp; - apply(SUBMUL, b, a, meanI, meanp); - DEBUG_DUMP(b); + apply(MUL, I1, I1, I1); - meanI.free(); // frees w * h * 4 byte - meanp.free(); // frees w * h * 4 byte + f_mean(I1, I1, r1); - array2D &meana = a; - f_mean(meana, a, r1); - DEBUG_DUMP(meana); + apply(SUBMUL, I1, meanI, meanI, I1); + apply(SUBMUL, p1, meanI, meanp, p1); + apply(DIVEPSILON, I1, p1, I1); + apply(SUBMUL, p1, I1, meanI, meanp); + } - array2D &meanb = b; - f_mean(meanb, b, r1); - DEBUG_DUMP(meanb); + f_mean(I1, I1, r1); + f_mean(p1, p1, r1); - blur_buf.resize(0); // frees w * h * 4 byte + const int Ws = I1.width(); + const int Hs = I1.height(); + const int Wd = dst.width(); + const int Hd = dst.height(); - array2D meanA(W, H); - f_upsample(meanA, meana); - DEBUG_DUMP(meanA); + const float col_scale = static_cast(Ws) / static_cast(Wd); + const float row_scale = static_cast(Hs) / static_cast(Hd); - array2D &meanB = q; - f_upsample(meanB, meanb); - DEBUG_DUMP(meanB); +#ifdef _OPENMP + #pragma omp parallel for if (multithread) +#endif - apply(ADDMUL, q, meanA, I, meanB); - DEBUG_DUMP(q); + for (int y = 0; y < Hd; ++y) { + const float ymrs = y * row_scale; + for (int x = 0; x < Wd; ++x) { + dst[y][x] = getBilinearValue(I1, x * col_scale, ymrs) * guide[y][x] + getBilinearValue(p1, x * col_scale, ymrs); + } + } } } // namespace rtengine diff --git a/rtengine/guidedfilter.h b/rtengine/guidedfilter.h index 6691af251..af8ed0901 100644 --- a/rtengine/guidedfilter.h +++ b/rtengine/guidedfilter.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtengine/helpersse2.h b/rtengine/helpersse2.h index 74780cf48..e8c489b04 100644 --- a/rtengine/helpersse2.h +++ b/rtengine/helpersse2.h @@ -29,7 +29,7 @@ typedef __m128 vfloat; typedef __m128i vint2; // -#define LVF(x) _mm_load_ps((float*)&x) +#define LVF(x) _mm_load_ps((const float*)&x) #define LVFU(x) _mm_loadu_ps(&x) #define STVF(x,y) _mm_store_ps(&x,y) #define STVFU(x,y) _mm_storeu_ps(&x,y) diff --git a/rtengine/hilite_recon.cc b/rtengine/hilite_recon.cc index 699d42071..35dd74463 100644 --- a/rtengine/hilite_recon.cc +++ b/rtengine/hilite_recon.cc @@ -3,9 +3,11 @@ // Highlight reconstruction // // copyright (c) 2008-2011 Emil Martinec +// copyright (c) 2019 Ingo Weyrich // // // code dated: June 16, 2011 +// code dated: July 09, 2019, speedups by Ingo Weyrich // // hilite_recon.cc is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -18,200 +20,108 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// -#include +#include #include +#include + #include "array2D.h" +#include "opthelper.h" #include "rawimagesource.h" #include "rt_math.h" -#include "opthelper.h" -namespace rtengine + +namespace { -extern const Settings* settings; - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::boxblur2(float** src, float** dst, float** temp, int H, int W, int box ) +void boxblur2(const float* const* src, float** dst, float** temp, int startY, int startX, int H, int W, int bufferW, int box) { + constexpr int numCols = 16; + assert((bufferW % numCols) == 0); + //box blur image channel; box size = 2*box+1 //horizontal blur #ifdef _OPENMP #pragma omp parallel for #endif - - for (int row = 0; row < H; row++) { + for (int row = 0; row < H; ++row) { int len = box + 1; - temp[row][0] = src[row][0] / len; + temp[row][0] = src[row + startY][startX] / len; - for (int j = 1; j <= box; j++) { - temp[row][0] += src[row][j] / len; + for (int j = 1; j <= box; ++j) { + temp[row][0] += src[row + startY][j + startX] / len; } - for (int col = 1; col <= box; col++) { - temp[row][col] = (temp[row][col - 1] * len + src[row][col + box]) / (len + 1); - len ++; + for (int col = 1; col <= box; ++col, ++len) { + temp[row][col] = (temp[row][col - 1] * len + src[row + startY][col + box + startX]) / (len + 1); } - for (int col = box + 1; col < W - box; col++) { - temp[row][col] = temp[row][col - 1] + (src[row][col + box] - src[row][col - box - 1]) / len; + for (int col = box + 1; col < W - box; ++col) { + temp[row][col] = temp[row][col - 1] + (src[row + startY][col + box + startX] - src[row + startY][col - box - 1 + startX]) / len; } - for (int col = W - box; col < W; col++) { - temp[row][col] = (temp[row][col - 1] * len - src[row][col - box - 1]) / (len - 1); - len --; + for (int col = W - box; col < W; ++col, --len) { + temp[row][col] = (temp[row][col - 1] * len - src[row + startY][col - box - 1 + startX]) / (len - 1); } } -#ifdef __SSE2__ //vertical blur #ifdef _OPENMP #pragma omp parallel #endif { - float len = box + 1; - vfloat lenv = F2V( len ); - vfloat lenp1v = F2V( len + 1.0f ); - vfloat onev = F2V( 1.0f ); - vfloat tempv, temp2v; + float tempvalN[numCols] ALIGNED64; #ifdef _OPENMP - #pragma omp for nowait + #pragma omp for #endif + for (int col = 0; col < bufferW - numCols + 1; col += numCols) { + float len = box + 1; - for (int col = 0; col < W - 7; col += 8) { - tempv = LVFU(temp[0][col]) / lenv; - temp2v = LVFU(temp[0][col + 4]) / lenv; - - for (int i = 1; i <= box; i++) { - tempv = tempv + LVFU(temp[i][col]) / lenv; - temp2v = temp2v + LVFU(temp[i][col + 4]) / lenv; + for (int n = 0; n < numCols; ++n) { + tempvalN[n] = temp[0][col + n] / len; } - _mm_storeu_ps( &dst[0][col], tempv); - _mm_storeu_ps( &dst[0][col + 4], temp2v); - - for (int row = 1; row <= box; row++) { - tempv = (tempv * lenv + LVFU(temp[(row + box)][col])) / lenp1v; - temp2v = (temp2v * lenv + LVFU(temp[(row + box)][col + 4])) / lenp1v; - _mm_storeu_ps( &dst[row][col], tempv); - _mm_storeu_ps( &dst[row][col + 4], temp2v); - lenv = lenp1v; - lenp1v = lenp1v + onev; - } - - for (int row = box + 1; row < H - box; row++) { - tempv = tempv + (LVFU(temp[(row + box)][col]) - LVFU(temp[(row - box - 1)][col])) / lenv; - temp2v = temp2v + (LVFU(temp[(row + box)][col + 4]) - LVFU(temp[(row - box - 1)][col + 4])) / lenv; - _mm_storeu_ps( &dst[row][col], tempv); - _mm_storeu_ps( &dst[row][col + 4], temp2v); - } - - for (int row = H - box; row < H; row++) { - lenp1v = lenv; - lenv = lenv - onev; - tempv = (tempv * lenp1v - LVFU(temp[(row - box - 1)][col])) / lenv; - temp2v = (temp2v * lenp1v - LVFU(temp[(row - box - 1)][col + 4])) / lenv; - _mm_storeu_ps( &dst[row][col], tempv ); - _mm_storeu_ps( &dst[row][col + 4], temp2v ); - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - for (int col = W - (W % 8); col < W - 3; col += 4) { - tempv = LVFU(temp[0][col]) / lenv; - - for (int i = 1; i <= box; i++) { - tempv = tempv + LVFU(temp[i][col]) / lenv; - } - - _mm_storeu_ps( &dst[0][col], tempv); - - for (int row = 1; row <= box; row++) { - tempv = (tempv * lenv + LVFU(temp[(row + box)][col])) / lenp1v; - _mm_storeu_ps( &dst[row][col], tempv); - lenv = lenp1v; - lenp1v = lenp1v + onev; - } - - for (int row = box + 1; row < H - box; row++) { - tempv = tempv + (LVFU(temp[(row + box)][col]) - LVFU(temp[(row - box - 1)][col])) / lenv; - _mm_storeu_ps( &dst[row][col], tempv); - } - - for (int row = H - box; row < H; row++) { - lenp1v = lenv; - lenv = lenv - onev; - tempv = (tempv * lenp1v - LVFU(temp[(row - box - 1)][col])) / lenv; - _mm_storeu_ps( &dst[row][col], tempv ); + for (int i = 1; i <= box; ++i) { + for (int n = 0; n < numCols; ++n) { + tempvalN[n] += temp[i][col + n] / len; } } - for (int col = W - (W % 4); col < W; col++) { - int len = box + 1; - dst[0][col] = temp[0][col] / len; + for (int n = 0; n < numCols; ++n) { + dst[0][col + n] = tempvalN[n]; + } - for (int i = 1; i <= box; i++) { - dst[0][col] += temp[i][col] / len; + for (int row = 1; row <= box; ++row, ++len) { + for (int n = 0; n < numCols; ++n) { + tempvalN[n] = (tempvalN[n] * len + temp[(row + box)][col + n]) / (len + 1); + dst[row][col + n] = tempvalN[n]; } + } - for (int row = 1; row <= box; row++) { - dst[row][col] = (dst[(row - 1)][col] * len + temp[(row + box)][col]) / (len + 1); - len ++; + const float rlen = 1.f / len; + + for (int row = box + 1; row < H - box; ++row) { + for (int n = 0; n < numCols; ++n) { + tempvalN[n] += (temp[(row + box)][col + n] - temp[(row - box - 1)][col + n]) * rlen; + dst[row][col + n] = tempvalN[n]; } + } - for (int row = box + 1; row < H - box; row++) { - dst[row][col] = dst[(row - 1)][col] + (temp[(row + box)][col] - temp[(row - box - 1)][col]) / len; - } - - for (int row = H - box; row < H; row++) { - dst[row][col] = (dst[(row - 1)][col] * len - temp[(row - box - 1)][col]) / (len - 1); - len --; + for (int row = H - box; row < H; ++row, --len) { + for (int n = 0; n < numCols; ++n) { + tempvalN[n] = (dst[(row - 1)][col + n] * len - temp[(row - box - 1)][col + n]) / (len - 1); + dst[row][col + n] = tempvalN[n]; } } } } - -#else - //vertical blur -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int col = 0; col < W; col++) { - int len = box + 1; - dst[0][col] = temp[0][col] / len; - - for (int i = 1; i <= box; i++) { - dst[0][col] += temp[i][col] / len; - } - - for (int row = 1; row <= box; row++) { - dst[row][col] = (dst[(row - 1)][col] * len + temp[(row + box)][col]) / (len + 1); - len ++; - } - - for (int row = box + 1; row < H - box; row++) { - dst[row][col] = dst[(row - 1)][col] + (temp[(row + box)][col] - temp[(row - box - 1)][col]) / len; - } - - for (int row = H - box; row < H; row++) { - dst[row][col] = (dst[(row - 1)][col] * len - temp[(row - box - 1)][col]) / (len - 1); - len --; - } - } - -#endif - } -void RawImageSource::boxblur_resamp(float **src, float **dst, float ** temp, int H, int W, int box, int samp ) +void boxblur_resamp(const float* const* src, float** dst, float** temp, int H, int W, int box, int samp) { + assert(samp != 0); #ifdef _OPENMP #pragma omp parallel @@ -220,118 +130,111 @@ void RawImageSource::boxblur_resamp(float **src, float **dst, float ** temp, int #ifdef _OPENMP #pragma omp for #endif - //box blur image channel; box size = 2*box+1 //horizontal blur - for (int row = 0; row < H; row++) - { + for (int row = 0; row < H; ++row) { int len = box + 1; float tempval = src[row][0] / len; - for (int j = 1; j <= box; j++) { + for (int j = 1; j <= box; ++j) { tempval += src[row][j] / len; } temp[row][0] = tempval; - for (int col = 1; col <= box; col++) { + for (int col = 1; col <= box; ++col, ++len) { tempval = (tempval * len + src[row][col + box]) / (len + 1); - if(col % samp == 0) { + if (col % samp == 0) { temp[row][col / samp] = tempval; } - - len ++; } - float oneByLen = 1.f / (float)len; + const float oneByLen = 1.f / static_cast(len); - for (int col = box + 1; col < W - box; col++) { + for (int col = box + 1; col < W - box; ++col) { tempval = tempval + (src[row][col + box] - src[row][col - box - 1]) * oneByLen; - if(col % samp == 0) { + if (col % samp == 0) { temp[row][col / samp] = tempval; } } - for (int col = W - box; col < W; col++) { + for (int col = W - box; col < W; ++col, --len) { tempval = (tempval * len - src[row][col - box - 1]) / (len - 1); - if(col % samp == 0) { + if (col % samp == 0) { temp[row][col / samp] = tempval; } - - len --; } } } - static const int numCols = 8; // process numCols columns at once for better L1 CPU cache usage + constexpr int numCols = 8; // process numCols columns at once for better L1 CPU cache usage + #ifdef _OPENMP #pragma omp parallel #endif { - float tempvalN[numCols] ALIGNED16; + float tempvalN[numCols] ALIGNED64; + #ifdef _OPENMP #pragma omp for nowait #endif - //vertical blur for (int col = 0; col < (W / samp) - (numCols - 1); col += numCols) { - int len = box + 1; + float len = box + 1; - for(int n = 0; n < numCols; n++) { + for (int n = 0; n < numCols; ++n) { tempvalN[n] = temp[0][col + n] / len; } - for (int i = 1; i <= box; i++) { - for(int n = 0; n < numCols; n++) { + for (int i = 1; i <= box; ++i) { + for (int n = 0; n < numCols; ++n) { tempvalN[n] += temp[i][col + n] / len; } } - for(int n = 0; n < numCols; n++) { + for (int n = 0; n < numCols; ++n) { dst[0][col + n] = tempvalN[n]; } - for (int row = 1; row <= box; row++) { - for(int n = 0; n < numCols; n++) { + for (int row = 1; row <= box; ++row, ++len) { + for (int n = 0; n < numCols; ++n) { tempvalN[n] = (tempvalN[n] * len + temp[(row + box)][col + n]) / (len + 1); } - if(row % samp == 0) { - for(int n = 0; n < numCols; n++) { - dst[row / samp][col + n] = tempvalN[n]; - } - } - - len ++; - } - - for (int row = box + 1; row < H - box; row++) { - for(int n = 0; n < numCols; n++) { - tempvalN[n] = tempvalN[n] + (temp[(row + box)][col + n] - temp[(row - box - 1)][col + n]) / len; - } - - if(row % samp == 0) { - for(int n = 0; n < numCols; n++) { + if (row % samp == 0) { + for (int n = 0; n < numCols; ++n) { dst[row / samp][col + n] = tempvalN[n]; } } } - for (int row = H - box; row < H; row++) { - for(int n = 0; n < numCols; n++) { + const float rlen = 1.f / len; + + for (int row = box + 1; row < H - box; ++row) { + for (int n = 0; n < numCols; ++n) { + tempvalN[n] += (temp[(row + box)][col + n] - temp[(row - box - 1)][col + n]) * rlen; + } + + if (row % samp == 0) { + for (int n = 0; n < numCols; ++n) { + dst[row / samp][col + n] = tempvalN[n]; + } + } + } + + for (int row = H - box; row < H; ++row, --len) { + for (int n = 0; n < numCols; ++n) { tempvalN[n] = (tempvalN[n] * len - temp[(row - box - 1)][col + n]) / (len - 1); } - if(row % samp == 0) { - for(int n = 0; n < numCols; n++) { + if (row % samp == 0) { + for (int n = 0; n < numCols; ++n) { dst[row / samp][col + n] = tempvalN[n]; } } - - len --; } } @@ -342,61 +245,62 @@ void RawImageSource::boxblur_resamp(float **src, float **dst, float ** temp, int { //vertical blur - for (int col = (W / samp) - ((W / samp) % numCols); col < W / samp; col++) { + for (int col = (W / samp) - ((W / samp) % numCols); col < W / samp; ++col) { int len = box + 1; float tempval = temp[0][col] / len; - for (int i = 1; i <= box; i++) { + for (int i = 1; i <= box; ++i) { tempval += temp[i][col] / len; } dst[0][col] = tempval; - for (int row = 1; row <= box; row++) { + for (int row = 1; row <= box; ++row, ++len) { tempval = (tempval * len + temp[(row + box)][col]) / (len + 1); - if(row % samp == 0) { - dst[row / samp][col] = tempval; - } - - len ++; - } - - for (int row = box + 1; row < H - box; row++) { - tempval = tempval + (temp[(row + box)][col] - temp[(row - box - 1)][col]) / len; - - if(row % samp == 0) { + if (row % samp == 0) { dst[row / samp][col] = tempval; } } - for (int row = H - box; row < H; row++) { + for (int row = box + 1; row < H - box; ++row) { + tempval += (temp[(row + box)][col] - temp[(row - box - 1)][col]) / len; + + if (row % samp == 0) { + dst[row / samp][col] = tempval; + } + } + + for (int row = H - box; row < H; ++row, --len) { tempval = (tempval * len - temp[(row - box - 1)][col]) / (len - 1); - if(row % samp == 0) { + if (row % samp == 0) { dst[row / samp][col] = tempval; } - - len --; } } } } - +} } -void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** blue) +namespace rtengine +{ + +extern const Settings* settings; + +void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue) { double progress = 0.0; if (plistener) { - plistener->setProgressStr ("PROGRESSBAR_HLREC"); - plistener->setProgress (progress); + plistener->setProgressStr("PROGRESSBAR_HLREC"); + plistener->setProgress(progress); } - int height = H; - int width = W; + const int height = H; + const int width = W; constexpr int range = 2; constexpr int pitch = 4; @@ -407,29 +311,35 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b //%%%%%%%%%%%%%%%%%%%% //for blend algorithm: constexpr float blendthresh = 1.0; - constexpr int ColorCount = 3; // Transform matrixes rgb>lab and back - constexpr float trans[ColorCount][ColorCount] = - { { 1.f, 1.f, 1.f }, { 1.7320508f, -1.7320508f, 0.f }, { -1.f, -1.f, 2.f } }; - constexpr float itrans[ColorCount][ColorCount] = - { { 1.f, 0.8660254f, -0.5f }, { 1.f, -0.8660254f, -0.5f }, { 1.f, 0.f, 1.f } }; + constexpr float trans[3][3] = { + {1.f, 1.f, 1.f}, + {1.7320508f, -1.7320508f, 0.f}, + {-1.f, -1.f, 2.f} + }; + constexpr float itrans[3][3] = { + {1.f, 0.8660254f, -0.5f}, + {1.f, -0.8660254f, -0.5f}, + {1.f, 0.f, 1.f} + }; - if(settings->verbose) - for(int c = 0; c < 3; c++) { + if (settings->verbose) { + for (int c = 0; c < 3; ++c) { printf("chmax[%d] : %f\tclmax[%d] : %f\tratio[%d] : %f\n", c, chmax[c], c, clmax[c], c, chmax[c] / clmax[c]); } + } float factor[3]; - for(int c = 0; c < ColorCount; c++) { + for (int c = 0; c < 3; ++c) { factor[c] = chmax[c] / clmax[c]; } - float minFactor = min(factor[0], factor[1], factor[2]); + const float minFactor = min(factor[0], factor[1], factor[2]); - if(minFactor > 1.f) { // all 3 channels clipped + if (minFactor > 1.f) { // all 3 channels clipped // calculate clip factor per channel - for (int c = 0; c < ColorCount; c++) { + for (int c = 0; c < 3; ++c) { factor[c] /= minFactor; } @@ -437,70 +347,108 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b int maxpos = 0; float maxValNew = 0.f; - for (int c = 0; c < ColorCount; c++) { - if(chmax[c] / factor[c] > maxValNew) { + for (int c = 0; c < 3; ++c) { + if (chmax[c] / factor[c] > maxValNew) { maxValNew = chmax[c] / factor[c]; maxpos = c; } } - float clipFactor = clmax[maxpos] / maxValNew; - - if(clipFactor < maxpct) + const float clipFactor = clmax[maxpos] / maxValNew; + if (clipFactor < maxpct) { // if max clipFactor < maxpct (0.95) adjust per channel factors - for (int c = 0; c < ColorCount; c++) { + for (int c = 0; c < 3; ++c) { factor[c] *= (maxpct / clipFactor); } + } } else { factor[0] = factor[1] = factor[2] = 1.f; } - if(settings->verbose) - for (int c = 0; c < ColorCount; c++) { + if (settings->verbose) { + for (int c = 0; c < 3; ++c) { printf("correction factor[%d] : %f\n", c, factor[c]); } + } - float max_f[3], thresh[3]; + float max_f[3]; + float thresh[3]; - for (int c = 0; c < ColorCount; c++) { + for (int c = 0; c < 3; ++c) { thresh[c] = chmax[c] * threshpct / factor[c]; max_f[c] = chmax[c] * maxpct / factor[c]; } - float whitept = max(max_f[0], max_f[1], max_f[2]); - float clippt = min(max_f[0], max_f[1], max_f[2]); - float medpt = max_f[0] + max_f[1] + max_f[2] - whitept - clippt; - float blendpt = blendthresh * clippt; + const float whitept = max(max_f[0], max_f[1], max_f[2]); + const float clippt = min(max_f[0], max_f[1], max_f[2]); + const float medpt = max_f[0] + max_f[1] + max_f[2] - whitept - clippt; + const float blendpt = blendthresh * clippt; + float medFactor[3]; - for (int c = 0; c < ColorCount; c++) { - medFactor[c] = max(1.0f, max_f[c] / medpt) / (-blendpt); + for (int c = 0; c < 3; ++c) { + medFactor[c] = max(1.0f, max_f[c] / medpt) / -blendpt; } - multi_array2D channelblur(width, height, 0, 48); - array2D temp(width, height); // allocate temporary buffer + int minx = width - 1; + int maxx = 0; + int miny = height - 1; + int maxy = 0; + + #pragma omp parallel for reduction(min:minx,miny) reduction(max:maxx,maxy) schedule(dynamic, 16) + for (int i = 0; i < height; ++i) { + for (int j = 0; j< width; ++j) { + if (red[i][j] >= max_f[0] || green[i][j] >= max_f[1] || blue[i][j] >= max_f[2]) { + minx = std::min(minx, j); + maxx = std::max(maxx, j); + miny = std::min(miny, i); + maxy = std::max(maxy, i); + } + } + } + + if (minx > maxx || miny > maxy) { // nothing to reconstruct + return; + } + + if (plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + + constexpr int blurBorder = 256; + minx = std::max(0, minx - blurBorder); + miny = std::max(0, miny - blurBorder); + maxx = std::min(width - 1, maxx + blurBorder); + maxy = std::min(height - 1, maxy + blurBorder); + const int blurWidth = maxx - minx + 1; + const int blurHeight = maxy - miny + 1; + const int bufferWidth = blurWidth + ((16 - (blurWidth % 16)) & 15); + + multi_array2D channelblur(bufferWidth, blurHeight, 0, 48); + array2D temp(bufferWidth, blurHeight); // allocate temporary buffer // blur RGB channels - boxblur2(red, channelblur[0], temp, height, width, 4); + boxblur2(red, channelblur[0], temp, miny, minx, blurHeight, blurWidth, bufferWidth, 4); - if(plistener) { - progress += 0.05; + if (plistener) { + progress += 0.07; plistener->setProgress(progress); } - boxblur2(green, channelblur[1], temp, height, width, 4); + boxblur2(green, channelblur[1], temp, miny, minx, blurHeight, blurWidth, bufferWidth, 4); - if(plistener) { - progress += 0.05; + if (plistener) { + progress += 0.07; plistener->setProgress(progress); } - boxblur2(blue, channelblur[2], temp, height, width, 4); - - if(plistener) { - progress += 0.05; + boxblur2(blue, channelblur[2], temp, miny, minx, blurHeight, blurWidth, bufferWidth, 4); + + if (plistener) { + progress += 0.07; plistener->setProgress(progress); } @@ -508,79 +456,83 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b #ifdef _OPENMP #pragma omp parallel for #endif - - for(int i = 0; i < height; i++) - for(int j = 0; j < width; j++) { - channelblur[0][i][j] = fabsf(channelblur[0][i][j] - red[i][j]) + fabsf(channelblur[1][i][j] - green[i][j]) + fabsf(channelblur[2][i][j] - blue[i][j]); + for (int i = 0; i < blurHeight; ++i) { + for (int j = 0; j < blurWidth; ++j) { + channelblur[0][i][j] = fabsf(channelblur[0][i][j] - red[i + miny][j + minx]) + fabsf(channelblur[1][i][j] - green[i + miny][j + minx]) + fabsf(channelblur[2][i][j] - blue[i + miny][j + minx]); } + } - for (int c = 1; c < 3; c++) { + for (int c = 1; c < 3; ++c) { channelblur[c].free(); //free up some memory } - if(plistener) { + if (plistener) { progress += 0.05; plistener->setProgress(progress); } - multi_array2D hilite_full(width, height, ARRAY2D_CLEAR_DATA, 32); + multi_array2D hilite_full(bufferWidth, blurHeight, ARRAY2D_CLEAR_DATA, 32); - if(plistener) { - progress += 0.10; + if (plistener) { + progress += 0.05; plistener->setProgress(progress); } - double hipass_sum = 0.f; + double hipass_sum = 0.0; int hipass_norm = 0; // set up which pixels are clipped or near clipping #ifdef _OPENMP #pragma omp parallel for reduction(+:hipass_sum,hipass_norm) schedule(dynamic,16) #endif - - for (int i = 0; i < height; i++) { - for (int j = 0; j < width; j++) { - //if one or more channels is highlight but none are blown, add to highlight accumulator - if ((red[i][j] > thresh[0] || green[i][j] > thresh[1] || blue[i][j] > thresh[2]) && - (red[i][j] < max_f[0] && green[i][j] < max_f[1] && blue[i][j] < max_f[2])) { - + for (int i = 0; i < blurHeight; ++i) { + for (int j = 0; j < blurWidth; ++j) { + if ( + ( + red[i + miny][j + minx] > thresh[0] + || green[i + miny][j + minx] > thresh[1] + || blue[i + miny][j + minx] > thresh[2] + ) + && red[i + miny][j + minx] < max_f[0] + && green[i + miny][j + minx] < max_f[1] + && blue[i + miny][j + minx] < max_f[2] + ) { + // if one or more channels is highlight but none are blown, add to highlight accumulator hipass_sum += channelblur[0][i][j]; - hipass_norm ++; + ++hipass_norm; - hilite_full[0][i][j] = red[i][j]; - hilite_full[1][i][j] = green[i][j]; - hilite_full[2][i][j] = blue[i][j]; + hilite_full[0][i][j] = red[i + miny][j + minx]; + hilite_full[1][i][j] = green[i + miny][j + minx]; + hilite_full[2][i][j] = blue[i + miny][j + minx]; hilite_full[3][i][j] = 1.f; - } } - }//end of filling highlight array + } - float hipass_ave = 2.f * hipass_sum / (hipass_norm + epsilon); + const float hipass_ave = 2.f * hipass_sum / (hipass_norm + epsilon); - if(plistener) { + if (plistener) { progress += 0.05; plistener->setProgress(progress); } - array2D hilite_full4(width, height); + array2D hilite_full4(bufferWidth, blurHeight); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //blur highlight data - boxblur2(hilite_full[3], hilite_full4, temp, height, width, 1); + boxblur2(hilite_full[3], hilite_full4, temp, 0, 0, blurHeight, blurWidth, bufferWidth, 1); temp.free(); // free temporary buffer - if(plistener) { - progress += 0.05; + if (plistener) { + progress += 0.07; plistener->setProgress(progress); } #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif - - for (int i = 0; i < height; i++) { - for (int j = 0; j < width; j++) { + for (int i = 0; i < blurHeight; ++i) { + for (int j = 0; j < blurWidth; ++j) { if (channelblur[0][i][j] > hipass_ave) { //too much variation hilite_full[0][i][j] = hilite_full[1][i][j] = hilite_full[2][i][j] = hilite_full[3][i][j] = 0.f; @@ -597,20 +549,20 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b channelblur[0].free(); //free up some memory hilite_full4.free(); //free up some memory - int hfh = (height - (height % pitch)) / pitch; - int hfw = (width - (width % pitch)) / pitch; + const int hfh = (blurHeight - blurHeight % pitch) / pitch; + const int hfw = (blurWidth - blurWidth % pitch) / pitch; multi_array2D hilite(hfw + 1, hfh + 1, ARRAY2D_CLEAR_DATA, 48); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // blur and resample highlight data; range=size of blur, pitch=sample spacing - array2D temp2((width / pitch) + ((width % pitch) == 0 ? 0 : 1), height); + array2D temp2(blurWidth / pitch + (blurWidth % pitch == 0 ? 0 : 1), blurHeight); - for (int m = 0; m < 4; m++) { - boxblur_resamp(hilite_full[m], hilite[m], temp2, height, width, range, pitch); + for (int m = 0; m < 4; ++m) { + boxblur_resamp(hilite_full[m], hilite[m], temp2, blurHeight, blurWidth, range, pitch); - if(plistener) { + if (plistener) { progress += 0.05; plistener->setProgress(progress); } @@ -618,7 +570,7 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b temp2.free(); - for (int c = 0; c < 4; c++) { + for (int c = 0; c < 4; ++c) { hilite_full[c].free(); //free up some memory } @@ -627,15 +579,15 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b multi_array2D hilite_dir0(hfh, hfw, ARRAY2D_CLEAR_DATA, 64); multi_array2D hilite_dir4(hfh, hfw, ARRAY2D_CLEAR_DATA, 64); - if(plistener) { + if (plistener) { progress += 0.05; plistener->setProgress(progress); } //fill gaps in highlight map by directional extension //raster scan from four corners - for (int j = 1; j < hfw - 1; j++) { - for (int i = 2; i < hfh - 2; i++) { + for (int j = 1; j < hfw - 1; ++j) { + for (int i = 2; i < hfh - 2; ++i) { //from left if (hilite[3][i][j] > epsilon) { hilite_dir0[3][j][i] = 1.f; @@ -644,253 +596,277 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b } } - if(hilite[3][2][j] <= epsilon) { + if (hilite[3][2][j] <= epsilon) { hilite_dir[0 + 3][0][j] = hilite_dir0[3][j][2]; } - if(hilite[3][3][j] <= epsilon) { + if (hilite[3][3][j] <= epsilon) { hilite_dir[0 + 3][1][j] = hilite_dir0[3][j][3]; } - if(hilite[3][hfh - 3][j] <= epsilon) { + if (hilite[3][hfh - 3][j] <= epsilon) { hilite_dir[4 + 3][hfh - 1][j] = hilite_dir0[3][j][hfh - 3]; } - if(hilite[3][hfh - 4][j] <= epsilon) { + if (hilite[3][hfh - 4][j] <= epsilon) { hilite_dir[4 + 3][hfh - 2][j] = hilite_dir0[3][j][hfh - 4]; } } - for (int i = 2; i < hfh - 2; i++) { - if(hilite[3][i][hfw - 2] <= epsilon) { + for (int i = 2; i < hfh - 2; ++i) { + if (hilite[3][i][hfw - 2] <= epsilon) { hilite_dir4[3][hfw - 1][i] = hilite_dir0[3][hfw - 2][i]; } } - #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel #endif + { +#ifdef _OPENMP + #pragma omp for nowait +#endif + for (int c = 0; c < 3; ++c) { + for (int j = 1; j < hfw - 1; ++j) { + for (int i = 2; i < hfh - 2; ++i) { + //from left + if (hilite[3][i][j] > epsilon) { + hilite_dir0[c][j][i] = hilite[c][i][j] / hilite[3][i][j]; + } else { + hilite_dir0[c][j][i] = 0.1f * ((hilite_dir0[0 + c][j - 1][i - 2] + hilite_dir0[0 + c][j - 1][i - 1] + hilite_dir0[0 + c][j - 1][i] + hilite_dir0[0 + c][j - 1][i + 1] + hilite_dir0[0 + c][j - 1][i + 2]) / + (hilite_dir0[0 + 3][j - 1][i - 2] + hilite_dir0[0 + 3][j - 1][i - 1] + hilite_dir0[0 + 3][j - 1][i] + hilite_dir0[0 + 3][j - 1][i + 1] + hilite_dir0[0 + 3][j - 1][i + 2] + epsilon)); + } + } - for (int c = 0; c < 3; c++) { - for (int j = 1; j < hfw - 1; j++) { - for (int i = 2; i < hfh - 2; i++) { - //from left - if (hilite[3][i][j] > epsilon) { - hilite_dir0[c][j][i] = hilite[c][i][j] / hilite[3][i][j]; - } else { - hilite_dir0[c][j][i] = 0.1f * ((hilite_dir0[0 + c][j - 1][i - 2] + hilite_dir0[0 + c][j - 1][i - 1] + hilite_dir0[0 + c][j - 1][i] + hilite_dir0[0 + c][j - 1][i + 1] + hilite_dir0[0 + c][j - 1][i + 2]) / - (hilite_dir0[0 + 3][j - 1][i - 2] + hilite_dir0[0 + 3][j - 1][i - 1] + hilite_dir0[0 + 3][j - 1][i] + hilite_dir0[0 + 3][j - 1][i + 1] + hilite_dir0[0 + 3][j - 1][i + 2] + epsilon)); + if (hilite[3][2][j] <= epsilon) { + hilite_dir[0 + c][0][j] = hilite_dir0[c][j][2]; + } + + if (hilite[3][3][j] <= epsilon) { + hilite_dir[0 + c][1][j] = hilite_dir0[c][j][3]; + } + + if (hilite[3][hfh - 3][j] <= epsilon) { + hilite_dir[4 + c][hfh - 1][j] = hilite_dir0[c][j][hfh - 3]; + } + + if (hilite[3][hfh - 4][j] <= epsilon) { + hilite_dir[4 + c][hfh - 2][j] = hilite_dir0[c][j][hfh - 4]; } } - if(hilite[3][2][j] <= epsilon) { - hilite_dir[0 + c][0][j] = hilite_dir0[c][j][2]; - } - - if(hilite[3][3][j] <= epsilon) { - hilite_dir[0 + c][1][j] = hilite_dir0[c][j][3]; - } - - if(hilite[3][hfh - 3][j] <= epsilon) { - hilite_dir[4 + c][hfh - 1][j] = hilite_dir0[c][j][hfh - 3]; - } - - if(hilite[3][hfh - 4][j] <= epsilon) { - hilite_dir[4 + c][hfh - 2][j] = hilite_dir0[c][j][hfh - 4]; - } - } - - for (int i = 2; i < hfh - 2; i++) { - if(hilite[3][i][hfw - 2] <= epsilon) { - hilite_dir4[c][hfw - 1][i] = hilite_dir0[c][hfw - 2][i]; - } - } - } - - if(plistener) { - progress += 0.05; - plistener->setProgress(progress); - } - - for (int j = hfw - 2; j > 0; j--) { - for (int i = 2; i < hfh - 2; i++) { - //from right - if (hilite[3][i][j] > epsilon) { - hilite_dir4[3][j][i] = 1.f; - } else { - hilite_dir4[3][j][i] = (hilite_dir4[3][(j + 1)][(i - 2)] + hilite_dir4[3][(j + 1)][(i - 1)] + hilite_dir4[3][(j + 1)][(i)] + hilite_dir4[3][(j + 1)][(i + 1)] + hilite_dir4[3][(j + 1)][(i + 2)]) == 0.f ? 0.f : 0.1f; - } - } - - if(hilite[3][2][j] <= epsilon) { - hilite_dir[0 + 3][0][j] += hilite_dir4[3][j][2]; - } - - if(hilite[3][hfh - 3][j] <= epsilon) { - hilite_dir[4 + 3][hfh - 1][j] += hilite_dir4[3][j][hfh - 3]; - } - } - - for (int i = 2; i < hfh - 2; i++) { - if(hilite[3][i][0] <= epsilon) { - hilite_dir[0 + 3][i - 2][0] += hilite_dir4[3][0][i]; - hilite_dir[4 + 3][i + 2][0] += hilite_dir4[3][0][i]; - } - - if(hilite[3][i][1] <= epsilon) { - hilite_dir[0 + 3][i - 2][1] += hilite_dir4[3][1][i]; - hilite_dir[4 + 3][i + 2][1] += hilite_dir4[3][1][i]; - } - - if(hilite[3][i][hfw - 2] <= epsilon) { - hilite_dir[0 + 3][i - 2][hfw - 2] += hilite_dir4[3][hfw - 2][i]; - hilite_dir[4 + 3][i + 2][hfw - 2] += hilite_dir4[3][hfw - 2][i]; - } - } - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int c = 0; c < 3; c++) { - for (int j = hfw - 2; j > 0; j--) { - for (int i = 2; i < hfh - 2; i++) { - //from right - if (hilite[3][i][j] > epsilon) { - hilite_dir4[c][j][i] = hilite[c][i][j] / hilite[3][i][j]; - } else { - hilite_dir4[c][j][i] = 0.1 * ((hilite_dir4[c][(j + 1)][(i - 2)] + hilite_dir4[c][(j + 1)][(i - 1)] + hilite_dir4[c][(j + 1)][(i)] + hilite_dir4[c][(j + 1)][(i + 1)] + hilite_dir4[c][(j + 1)][(i + 2)]) / - (hilite_dir4[3][(j + 1)][(i - 2)] + hilite_dir4[3][(j + 1)][(i - 1)] + hilite_dir4[3][(j + 1)][(i)] + hilite_dir4[3][(j + 1)][(i + 1)] + hilite_dir4[3][(j + 1)][(i + 2)] + epsilon)); - } - } - - if(hilite[3][2][j] <= epsilon) { - hilite_dir[0 + c][0][j] += hilite_dir4[c][j][2]; - } - - if(hilite[3][hfh - 3][j] <= epsilon) { - hilite_dir[4 + c][hfh - 1][j] += hilite_dir4[c][j][hfh - 3]; - } - } - - for (int i = 2; i < hfh - 2; i++) { - if(hilite[3][i][0] <= epsilon) { - hilite_dir[0 + c][i - 2][0] += hilite_dir4[c][0][i]; - hilite_dir[4 + c][i + 2][0] += hilite_dir4[c][0][i]; - } - - if(hilite[3][i][1] <= epsilon) { - hilite_dir[0 + c][i - 2][1] += hilite_dir4[c][1][i]; - hilite_dir[4 + c][i + 2][1] += hilite_dir4[c][1][i]; - } - - if(hilite[3][i][hfw - 2] <= epsilon) { - hilite_dir[0 + c][i - 2][hfw - 2] += hilite_dir4[c][hfw - 2][i]; - hilite_dir[4 + c][i + 2][hfw - 2] += hilite_dir4[c][hfw - 2][i]; - } - } - } - - if(plistener) { - progress += 0.05; - plistener->setProgress(progress); - } - - - for (int i = 1; i < hfh - 1; i++) - for (int j = 2; j < hfw - 2; j++) { - //from top - if (hilite[3][i][j] > epsilon) { - hilite_dir[0 + 3][i][j] = 1.f; - } else { - hilite_dir[0 + 3][i][j] = (hilite_dir[0 + 3][i - 1][j - 2] + hilite_dir[0 + 3][i - 1][j - 1] + hilite_dir[0 + 3][i - 1][j] + hilite_dir[0 + 3][i - 1][j + 1] + hilite_dir[0 + 3][i - 1][j + 2]) == 0.f ? 0.f : 0.1f; - } - } - - for (int j = 2; j < hfw - 2; j++) { - if(hilite[3][hfh - 2][j] <= epsilon) { - hilite_dir[4 + 3][hfh - 1][j] += hilite_dir[0 + 3][hfh - 2][j]; - } - } - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int c = 0; c < 3; c++) { - for (int i = 1; i < hfh - 1; i++) { - for (int j = 2; j < hfw - 2; j++) { - //from top - if (hilite[3][i][j] > epsilon) { - hilite_dir[0 + c][i][j] = hilite[c][i][j] / hilite[3][i][j]; - } else { - hilite_dir[0 + c][i][j] = 0.1 * ((hilite_dir[0 + c][i - 1][j - 2] + hilite_dir[0 + c][i - 1][j - 1] + hilite_dir[0 + c][i - 1][j] + hilite_dir[0 + c][i - 1][j + 1] + hilite_dir[0 + c][i - 1][j + 2]) / - (hilite_dir[0 + 3][i - 1][j - 2] + hilite_dir[0 + 3][i - 1][j - 1] + hilite_dir[0 + 3][i - 1][j] + hilite_dir[0 + 3][i - 1][j + 1] + hilite_dir[0 + 3][i - 1][j + 2] + epsilon)); + for (int i = 2; i < hfh - 2; ++i) { + if (hilite[3][i][hfw - 2] <= epsilon) { + hilite_dir4[c][hfw - 1][i] = hilite_dir0[c][hfw - 2][i]; } } } - for (int j = 2; j < hfw - 2; j++) { - if(hilite[3][hfh - 2][j] <= epsilon) { - hilite_dir[4 + c][hfh - 1][j] += hilite_dir[0 + c][hfh - 2][j]; +#ifdef _OPENMP + #pragma omp single +#endif + { + for (int j = hfw - 2; j > 0; --j) { + for (int i = 2; i < hfh - 2; ++i) { + //from right + if (hilite[3][i][j] > epsilon) { + hilite_dir4[3][j][i] = 1.f; + } else { + hilite_dir4[3][j][i] = (hilite_dir4[3][(j + 1)][(i - 2)] + hilite_dir4[3][(j + 1)][(i - 1)] + hilite_dir4[3][(j + 1)][(i)] + hilite_dir4[3][(j + 1)][(i + 1)] + hilite_dir4[3][(j + 1)][(i + 2)]) == 0.f ? 0.f : 0.1f; + } + } + + if (hilite[3][2][j] <= epsilon) { + hilite_dir[0 + 3][0][j] += hilite_dir4[3][j][2]; + } + + if (hilite[3][hfh - 3][j] <= epsilon) { + hilite_dir[4 + 3][hfh - 1][j] += hilite_dir4[3][j][hfh - 3]; + } + } + + for (int i = 2; i < hfh - 2; ++i) { + if (hilite[3][i][0] <= epsilon) { + hilite_dir[0 + 3][i - 2][0] += hilite_dir4[3][0][i]; + hilite_dir[4 + 3][i + 2][0] += hilite_dir4[3][0][i]; + } + + if (hilite[3][i][1] <= epsilon) { + hilite_dir[0 + 3][i - 2][1] += hilite_dir4[3][1][i]; + hilite_dir[4 + 3][i + 2][1] += hilite_dir4[3][1][i]; + } + + if (hilite[3][i][hfw - 2] <= epsilon) { + hilite_dir[0 + 3][i - 2][hfw - 2] += hilite_dir4[3][hfw - 2][i]; + hilite_dir[4 + 3][i + 2][hfw - 2] += hilite_dir4[3][hfw - 2][i]; + } } } } - - if(plistener) { + if (plistener) { progress += 0.05; plistener->setProgress(progress); } - for (int i = hfh - 2; i > 0; i--) - for (int j = 2; j < hfw - 2; j++) { - //from bottom - if (hilite[3][i][j] > epsilon) { - hilite_dir[4 + 3][i][j] = 1.f; - } else { - hilite_dir[4 + 3][i][j] = (hilite_dir[4 + 3][(i + 1)][(j - 2)] + hilite_dir[4 + 3][(i + 1)][(j - 1)] + hilite_dir[4 + 3][(i + 1)][(j)] + hilite_dir[4 + 3][(i + 1)][(j + 1)] + hilite_dir[4 + 3][(i + 1)][(j + 2)]) == 0.f ? 0.f : 0.1f; +#ifdef _OPENMP + #pragma omp parallel +#endif + { +#ifdef _OPENMP + #pragma omp for nowait +#endif + for (int c = 0; c < 3; ++c) { + for (int j = hfw - 2; j > 0; --j) { + for (int i = 2; i < hfh - 2; ++i) { + //from right + if (hilite[3][i][j] > epsilon) { + hilite_dir4[c][j][i] = hilite[c][i][j] / hilite[3][i][j]; + } else { + hilite_dir4[c][j][i] = 0.1f * ((hilite_dir4[c][(j + 1)][(i - 2)] + hilite_dir4[c][(j + 1)][(i - 1)] + hilite_dir4[c][(j + 1)][(i)] + hilite_dir4[c][(j + 1)][(i + 1)] + hilite_dir4[c][(j + 1)][(i + 2)]) / + (hilite_dir4[3][(j + 1)][(i - 2)] + hilite_dir4[3][(j + 1)][(i - 1)] + hilite_dir4[3][(j + 1)][(i)] + hilite_dir4[3][(j + 1)][(i + 1)] + hilite_dir4[3][(j + 1)][(i + 2)] + epsilon)); + } + } + + if (hilite[3][2][j] <= epsilon) { + hilite_dir[0 + c][0][j] += hilite_dir4[c][j][2]; + } + + if (hilite[3][hfh - 3][j] <= epsilon) { + hilite_dir[4 + c][hfh - 1][j] += hilite_dir4[c][j][hfh - 3]; + } + } + + for (int i = 2; i < hfh - 2; ++i) { + if (hilite[3][i][0] <= epsilon) { + hilite_dir[0 + c][i - 2][0] += hilite_dir4[c][0][i]; + hilite_dir[4 + c][i + 2][0] += hilite_dir4[c][0][i]; + } + + if (hilite[3][i][1] <= epsilon) { + hilite_dir[0 + c][i - 2][1] += hilite_dir4[c][1][i]; + hilite_dir[4 + c][i + 2][1] += hilite_dir4[c][1][i]; + } + + if (hilite[3][i][hfw - 2] <= epsilon) { + hilite_dir[0 + c][i - 2][hfw - 2] += hilite_dir4[c][hfw - 2][i]; + hilite_dir[4 + c][i + 2][hfw - 2] += hilite_dir4[c][hfw - 2][i]; + } } } +#ifdef _OPENMP + #pragma omp single +#endif + { + for (int i = 1; i < hfh - 1; ++i) + for (int j = 2; j < hfw - 2; ++j) { + //from top + if (hilite[3][i][j] > epsilon) { + hilite_dir[0 + 3][i][j] = 1.f; + } else { + hilite_dir[0 + 3][i][j] = (hilite_dir[0 + 3][i - 1][j - 2] + hilite_dir[0 + 3][i - 1][j - 1] + hilite_dir[0 + 3][i - 1][j] + hilite_dir[0 + 3][i - 1][j + 1] + hilite_dir[0 + 3][i - 1][j + 2]) == 0.f ? 0.f : 0.1f; + } + } + + for (int j = 2; j < hfw - 2; ++j) { + if (hilite[3][hfh - 2][j] <= epsilon) { + hilite_dir[4 + 3][hfh - 1][j] += hilite_dir[0 + 3][hfh - 2][j]; + } + } + } + } + if (plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + +#ifdef _OPENMP + #pragma omp parallel +#endif + { +#ifdef _OPENMP + #pragma omp for nowait +#endif + for (int c = 0; c < 3; ++c) { + for (int i = 1; i < hfh - 1; ++i) { + for (int j = 2; j < hfw - 2; ++j) { + //from top + if (hilite[3][i][j] > epsilon) { + hilite_dir[0 + c][i][j] = hilite[c][i][j] / hilite[3][i][j]; + } else { + hilite_dir[0 + c][i][j] = 0.1f * ((hilite_dir[0 + c][i - 1][j - 2] + hilite_dir[0 + c][i - 1][j - 1] + hilite_dir[0 + c][i - 1][j] + hilite_dir[0 + c][i - 1][j + 1] + hilite_dir[0 + c][i - 1][j + 2]) / + (hilite_dir[0 + 3][i - 1][j - 2] + hilite_dir[0 + 3][i - 1][j - 1] + hilite_dir[0 + 3][i - 1][j] + hilite_dir[0 + 3][i - 1][j + 1] + hilite_dir[0 + 3][i - 1][j + 2] + epsilon)); + } + } + } + + for (int j = 2; j < hfw - 2; ++j) { + if (hilite[3][hfh - 2][j] <= epsilon) { + hilite_dir[4 + c][hfh - 1][j] += hilite_dir[0 + c][hfh - 2][j]; + } + } + } + + +#ifdef _OPENMP + #pragma omp single +#endif + for (int i = hfh - 2; i > 0; --i) { + for (int j = 2; j < hfw - 2; ++j) { + //from bottom + if (hilite[3][i][j] > epsilon) { + hilite_dir[4 + 3][i][j] = 1.f; + } else { + hilite_dir[4 + 3][i][j] = (hilite_dir[4 + 3][(i + 1)][(j - 2)] + hilite_dir[4 + 3][(i + 1)][(j - 1)] + hilite_dir[4 + 3][(i + 1)][(j)] + hilite_dir[4 + 3][(i + 1)][(j + 1)] + hilite_dir[4 + 3][(i + 1)][(j + 2)]) == 0.f ? 0.f : 0.1f; + } + } + } + } + + if (plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + #ifdef _OPENMP #pragma omp parallel for #endif - - for (int c = 0; c < 4; c++) { - for (int i = hfh - 2; i > 0; i--) { - for (int j = 2; j < hfw - 2; j++) { + for (int c = 0; c < 4; ++c) { + for (int i = hfh - 2; i > 0; --i) { + for (int j = 2; j < hfw - 2; ++j) { //from bottom if (hilite[3][i][j] > epsilon) { hilite_dir[4 + c][i][j] = hilite[c][i][j] / hilite[3][i][j]; } else { - hilite_dir[4 + c][i][j] = 0.1 * ((hilite_dir[4 + c][(i + 1)][(j - 2)] + hilite_dir[4 + c][(i + 1)][(j - 1)] + hilite_dir[4 + c][(i + 1)][(j)] + hilite_dir[4 + c][(i + 1)][(j + 1)] + hilite_dir[4 + c][(i + 1)][(j + 2)]) / + hilite_dir[4 + c][i][j] = 0.1f * ((hilite_dir[4 + c][(i + 1)][(j - 2)] + hilite_dir[4 + c][(i + 1)][(j - 1)] + hilite_dir[4 + c][(i + 1)][(j)] + hilite_dir[4 + c][(i + 1)][(j + 1)] + hilite_dir[4 + c][(i + 1)][(j + 2)]) / (hilite_dir[4 + 3][(i + 1)][(j - 2)] + hilite_dir[4 + 3][(i + 1)][(j - 1)] + hilite_dir[4 + 3][(i + 1)][(j)] + hilite_dir[4 + 3][(i + 1)][(j + 1)] + hilite_dir[4 + 3][(i + 1)][(j + 2)] + epsilon)); } } } } - if(plistener) { + if (plistener) { progress += 0.05; plistener->setProgress(progress); } //fill in edges - for (int dir = 0; dir < 2; dir++) { - for (int i = 1; i < hfh - 1; i++) - for (int c = 0; c < 4; c++) { + for (int dir = 0; dir < 2; ++dir) { + for (int i = 1; i < hfh - 1; ++i) { + for (int c = 0; c < 4; ++c) { hilite_dir[dir * 4 + c][i][0] = hilite_dir[dir * 4 + c][i][1]; hilite_dir[dir * 4 + c][i][hfw - 1] = hilite_dir[dir * 4 + c][i][hfw - 2]; } + } - for (int j = 1; j < hfw - 1; j++) - for (int c = 0; c < 4; c++) { + for (int j = 1; j < hfw - 1; ++j) { + for (int c = 0; c < 4; ++c) { hilite_dir[dir * 4 + c][0][j] = hilite_dir[dir * 4 + c][1][j]; hilite_dir[dir * 4 + c][hfh - 1][j] = hilite_dir[dir * 4 + c][hfh - 2][j]; } + } - for (int c = 0; c < 4; c++) { + for (int c = 0; c < 4; ++c) { hilite_dir[dir * 4 + c][0][0] = hilite_dir[dir * 4 + c][1][0] = hilite_dir[dir * 4 + c][0][1] = hilite_dir[dir * 4 + c][1][1] = hilite_dir[dir * 4 + c][2][2]; hilite_dir[dir * 4 + c][0][hfw - 1] = hilite_dir[dir * 4 + c][1][hfw - 1] = hilite_dir[dir * 4 + c][0][hfw - 2] = hilite_dir[dir * 4 + c][1][hfw - 2] = hilite_dir[dir * 4 + c][2][hfw - 3]; hilite_dir[dir * 4 + c][hfh - 1][0] = hilite_dir[dir * 4 + c][hfh - 2][0] = hilite_dir[dir * 4 + c][hfh - 1][1] = hilite_dir[dir * 4 + c][hfh - 2][1] = hilite_dir[dir * 4 + c][hfh - 3][2]; @@ -898,51 +874,55 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b } } - for (int i = 1; i < hfh - 1; i++) - for (int c = 0; c < 4; c++) { + for (int i = 1; i < hfh - 1; ++i) { + for (int c = 0; c < 4; ++c) { hilite_dir0[c][0][i] = hilite_dir0[c][1][i]; hilite_dir0[c][hfw - 1][i] = hilite_dir0[c][hfw - 2][i]; } + } - for (int j = 1; j < hfw - 1; j++) - for (int c = 0; c < 4; c++) { + for (int j = 1; j < hfw - 1; ++j) { + for (int c = 0; c < 4; ++c) { hilite_dir0[c][j][0] = hilite_dir0[c][j][1]; hilite_dir0[c][j][hfh - 1] = hilite_dir0[c][j][hfh - 2]; } + } - for (int c = 0; c < 4; c++) { + for (int c = 0; c < 4; ++c) { hilite_dir0[c][0][0] = hilite_dir0[c][0][1] = hilite_dir0[c][1][0] = hilite_dir0[c][1][1] = hilite_dir0[c][2][2]; hilite_dir0[c][hfw - 1][0] = hilite_dir0[c][hfw - 1][1] = hilite_dir0[c][hfw - 2][0] = hilite_dir0[c][hfw - 2][1] = hilite_dir0[c][hfw - 3][2]; hilite_dir0[c][0][hfh - 1] = hilite_dir0[c][0][hfh - 2] = hilite_dir0[c][1][hfh - 1] = hilite_dir0[c][1][hfh - 2] = hilite_dir0[c][2][hfh - 3]; hilite_dir0[c][hfw - 1][hfh - 1] = hilite_dir0[c][hfw - 1][hfh - 2] = hilite_dir0[c][hfw - 2][hfh - 1] = hilite_dir0[c][hfw - 2][hfh - 2] = hilite_dir0[c][hfw - 3][hfh - 3]; } - for (int i = 1; i < hfh - 1; i++) - for (int c = 0; c < 4; c++) { + for (int i = 1; i < hfh - 1; ++i) { + for (int c = 0; c < 4; ++c) { hilite_dir4[c][0][i] = hilite_dir4[c][1][i]; hilite_dir4[c][hfw - 1][i] = hilite_dir4[c][hfw - 2][i]; } + } - for (int j = 1; j < hfw - 1; j++) - for (int c = 0; c < 4; c++) { + for (int j = 1; j < hfw - 1; ++j) { + for (int c = 0; c < 4; ++c) { hilite_dir4[c][j][0] = hilite_dir4[c][j][1]; hilite_dir4[c][j][hfh - 1] = hilite_dir4[c][j][hfh - 2]; } + } - for (int c = 0; c < 4; c++) { + for (int c = 0; c < 4; ++c) { hilite_dir4[c][0][0] = hilite_dir4[c][0][1] = hilite_dir4[c][1][0] = hilite_dir4[c][1][1] = hilite_dir4[c][2][2]; hilite_dir4[c][hfw - 1][0] = hilite_dir4[c][hfw - 1][1] = hilite_dir4[c][hfw - 2][0] = hilite_dir4[c][hfw - 2][1] = hilite_dir4[c][hfw - 3][2]; hilite_dir4[c][0][hfh - 1] = hilite_dir4[c][0][hfh - 2] = hilite_dir4[c][1][hfh - 1] = hilite_dir4[c][1][hfh - 2] = hilite_dir4[c][2][hfh - 3]; hilite_dir4[c][hfw - 1][hfh - 1] = hilite_dir4[c][hfw - 1][hfh - 2] = hilite_dir4[c][hfw - 2][hfh - 1] = hilite_dir4[c][hfw - 2][hfh - 2] = hilite_dir4[c][hfw - 3][hfh - 3]; } - if(plistener) { + if (plistener) { progress += 0.05; plistener->setProgress(progress); } //free up some memory - for(int c = 0; c < 4; c++) { + for (int c = 0; c < 4; ++c) { hilite[c].free(); } @@ -952,90 +932,92 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif + for (int i = 0; i < blurHeight; ++i) { + const int i1 = min((i - i % pitch) / pitch, hfh - 1); - for (int i = 0; i < height; i++) { - int i1 = min((i - (i % pitch)) / pitch, hfh - 1); - - for (int j = 0; j < width; j++) { - - float pixel[3] = {red[i][j], green[i][j], blue[i][j]}; + for (int j = 0; j < blurWidth; ++j) { + const float pixel[3] = { + red[i + miny][j + minx], + green[i + miny][j + minx], + blue[i + miny][j + minx] + }; if (pixel[0] < max_f[0] && pixel[1] < max_f[1] && pixel[2] < max_f[2]) { continue; //pixel not clipped } - int j1 = min((j - (j % pitch)) / pitch, hfw - 1); + const int j1 = min((j - j % pitch) / pitch, hfw - 1); //estimate recovered values using modified HLRecovery_blend algorithm - float rgb[ColorCount], rgb_blend[ColorCount] = {}, cam[2][ColorCount], lab[2][ColorCount], sum[2], chratio; - - // Copy input pixel to rgb so it's easier to access in loops - rgb[0] = pixel[0]; - rgb[1] = pixel[1]; - rgb[2] = pixel[2]; + float rgb[3] = { + pixel[0], + pixel[1], + pixel[2] + };// Copy input pixel to rgb so it's easier to access in loops + float rgb_blend[3] = {}; + float cam[2][3]; + float lab[2][3]; + float sum[2]; // Initialize cam with raw input [0] and potentially clipped input [1] - for (int c = 0; c < ColorCount; c++) { + for (int c = 0; c < 3; ++c) { cam[0][c] = rgb[c]; cam[1][c] = min(cam[0][c], clippt); } // Calculate the lightness correction ratio (chratio) - for (int i2 = 0; i2 < 2; i2++) { - for (int c = 0; c < ColorCount; c++) { + for (int i2 = 0; i2 < 2; ++i2) { + for (int c = 0; c < 3; ++c) { lab[i2][c] = 0; - for (int j = 0; j < ColorCount; j++) { - lab[i2][c] += trans[c][j] * cam[i2][j]; + for (int j2 = 0; j2 < 3; ++j2) { + lab[i2][c] += trans[c][j2] * cam[i2][j2]; } } sum[i2] = 0.f; - for (int c = 1; c < ColorCount; c++) { + for (int c = 1; c < 3; ++c) { sum[i2] += SQR(lab[i2][c]); } } - if(sum[0] == 0.f) { // avoid division by zero - sum[0] = epsilon; - } - - chratio = sqrtf(sum[1] / sum[0]); + // avoid division by zero + sum[0] = std::max(sum[0], epsilon); + const float chratio = sqrtf(sum[1] / sum[0]); // Apply ratio to lightness in lab space - for (int c = 1; c < ColorCount; c++) { + for (int c = 1; c < 3; ++c) { lab[0][c] *= chratio; } // Transform back from lab to RGB - for (int c = 0; c < ColorCount; c++) { - cam[0][c] = 0; + for (int c = 0; c < 3; ++c) { + cam[0][c] = 0.f; - for (int j = 0; j < ColorCount; j++) { - cam[0][c] += itrans[c][j] * lab[0][j]; + for (int j2 = 0; j2 < 3; ++j2) { + cam[0][c] += itrans[c][j2] * lab[0][j2]; } } - for (int c = 0; c < ColorCount; c++) { - rgb[c] = cam[0][c] / ColorCount; + for (int c = 0; c < 3; ++c) { + rgb[c] = cam[0][c] / 3; } // Copy converted pixel back - float rfrac = max(0.f, min(1.f, medFactor[0] * (pixel[0] - blendpt))); - float gfrac = max(0.f, min(1.f, medFactor[1] * (pixel[1] - blendpt))); - float bfrac = max(0.f, min(1.f, medFactor[2] * (pixel[2] - blendpt))); - if (pixel[0] > blendpt) { + const float rfrac = LIM01(medFactor[0] * (pixel[0] - blendpt)); rgb_blend[0] = rfrac * rgb[0] + (1.f - rfrac) * pixel[0]; } if (pixel[1] > blendpt) { + const float gfrac = LIM01(medFactor[1] * (pixel[1] - blendpt)); rgb_blend[1] = gfrac * rgb[1] + (1.f - gfrac) * pixel[1]; } if (pixel[2] > blendpt) { + const float bfrac = LIM01(medFactor[2] * (pixel[2] - blendpt)); rgb_blend[2] = bfrac * rgb[2] + (1.f - bfrac) * pixel[2]; } @@ -1044,37 +1026,35 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b //there are clipped highlights //first, determine weighted average of unclipped extensions (weighting is by 'hue' proximity) - float totwt = 0.f; + bool totwt = false; float clipfix[3] = {0.f, 0.f, 0.f}; float Y = epsilon + rgb_blend[0] + rgb_blend[1] + rgb_blend[2]; - for (int c = 0; c < ColorCount; c++) { + for (int c = 0; c < 3; ++c) { rgb_blend[c] /= Y; } float Yhi = 1.f / (hilite_dir0[0][j1][i1] + hilite_dir0[1][j1][i1] + hilite_dir0[2][j1][i1]); if (Yhi < 2.f) { - float dirwt = 1.f / (1.f + 65535.f * (SQR(rgb_blend[0] - hilite_dir0[0][j1][i1] * Yhi) + + const float dirwt = 1.f / ((1.f + 65535.f * (SQR(rgb_blend[0] - hilite_dir0[0][j1][i1] * Yhi) + SQR(rgb_blend[1] - hilite_dir0[1][j1][i1] * Yhi) + - SQR(rgb_blend[2] - hilite_dir0[2][j1][i1] * Yhi))); - totwt = dirwt; - dirwt /= (hilite_dir0[3][j1][i1] + epsilon); + SQR(rgb_blend[2] - hilite_dir0[2][j1][i1] * Yhi))) * (hilite_dir0[3][j1][i1] + epsilon)); + totwt = true; clipfix[0] = dirwt * hilite_dir0[0][j1][i1]; clipfix[1] = dirwt * hilite_dir0[1][j1][i1]; clipfix[2] = dirwt * hilite_dir0[2][j1][i1]; } - for (int dir = 0; dir < 2; dir++) { - float Yhi = 1.f / ( hilite_dir[dir * 4 + 0][i1][j1] + hilite_dir[dir * 4 + 1][i1][j1] + hilite_dir[dir * 4 + 2][i1][j1]); + for (int dir = 0; dir < 2; ++dir) { + const float Yhi2 = 1.f / ( hilite_dir[dir * 4 + 0][i1][j1] + hilite_dir[dir * 4 + 1][i1][j1] + hilite_dir[dir * 4 + 2][i1][j1]); - if (Yhi < 2.f) { - float dirwt = 1.f / (1.f + 65535.f * (SQR(rgb_blend[0] - hilite_dir[dir * 4 + 0][i1][j1] * Yhi) + - SQR(rgb_blend[1] - hilite_dir[dir * 4 + 1][i1][j1] * Yhi) + - SQR(rgb_blend[2] - hilite_dir[dir * 4 + 2][i1][j1] * Yhi))); - totwt += dirwt; - dirwt /= (hilite_dir[dir * 4 + 3][i1][j1] + epsilon); + if (Yhi2 < 2.f) { + const float dirwt = 1.f / ((1.f + 65535.f * (SQR(rgb_blend[0] - hilite_dir[dir * 4 + 0][i1][j1] * Yhi2) + + SQR(rgb_blend[1] - hilite_dir[dir * 4 + 1][i1][j1] * Yhi2) + + SQR(rgb_blend[2] - hilite_dir[dir * 4 + 2][i1][j1] * Yhi2))) * (hilite_dir[dir * 4 + 3][i1][j1] + epsilon)); + totwt = true; clipfix[0] += dirwt * hilite_dir[dir * 4 + 0][i1][j1]; clipfix[1] += dirwt * hilite_dir[dir * 4 + 1][i1][j1]; clipfix[2] += dirwt * hilite_dir[dir * 4 + 2][i1][j1]; @@ -1085,70 +1065,67 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b Yhi = 1.f / (hilite_dir4[0][j1][i1] + hilite_dir4[1][j1][i1] + hilite_dir4[2][j1][i1]); if (Yhi < 2.f) { - float dirwt = 1.f / (1.f + 65535.f * (SQR(rgb_blend[0] - hilite_dir4[0][j1][i1] * Yhi) + + const float dirwt = 1.f / ((1.f + 65535.f * (SQR(rgb_blend[0] - hilite_dir4[0][j1][i1] * Yhi) + SQR(rgb_blend[1] - hilite_dir4[1][j1][i1] * Yhi) + - SQR(rgb_blend[2] - hilite_dir4[2][j1][i1] * Yhi))); - totwt += dirwt; - dirwt /= (hilite_dir4[3][j1][i1] + epsilon); + SQR(rgb_blend[2] - hilite_dir4[2][j1][i1] * Yhi))) * (hilite_dir4[3][j1][i1] + epsilon)); + totwt = true; clipfix[0] += dirwt * hilite_dir4[0][j1][i1]; clipfix[1] += dirwt * hilite_dir4[1][j1][i1]; clipfix[2] += dirwt * hilite_dir4[2][j1][i1]; } - if(totwt == 0.f) { + if (UNLIKELY(!totwt)) { continue; } - clipfix[0] /= totwt; - clipfix[1] /= totwt; - clipfix[2] /= totwt; - //now correct clipped channels if (pixel[0] > max_f[0] && pixel[1] > max_f[1] && pixel[2] > max_f[2]) { //all channels clipped - float Y = (0.299 * clipfix[0] + 0.587 * clipfix[1] + 0.114 * clipfix[2]); - float factor = whitept / Y; - red[i][j] = clipfix[0] * factor; - green[i][j] = clipfix[1] * factor; - blue[i][j] = clipfix[2] * factor; + const float mult = whitept / (0.299f * clipfix[0] + 0.587f * clipfix[1] + 0.114f * clipfix[2]); + red[i + miny][j + minx] = clipfix[0] * mult; + green[i + miny][j + minx] = clipfix[1] * mult; + blue[i + miny][j + minx] = clipfix[2] * mult; } else {//some channels clipped - float notclipped[3] = {pixel[0] <= max_f[0] ? 1.f : 0.f, pixel[1] <= max_f[1] ? 1.f : 0.f, pixel[2] <= max_f[2] ? 1.f : 0.f}; + const float notclipped[3] = { + pixel[0] <= max_f[0] ? 1.f : 0.f, + pixel[1] <= max_f[1] ? 1.f : 0.f, + pixel[2] <= max_f[2] ? 1.f : 0.f + }; if (notclipped[0] == 0.f) { //red clipped - red[i][j] = max(red[i][j], (clipfix[0] * ((notclipped[1] * pixel[1] + notclipped[2] * pixel[2]) / - (notclipped[1] * clipfix[1] + notclipped[2] * clipfix[2] + epsilon)))); + red[i + miny][j + minx] = max(pixel[0], clipfix[0] * ((notclipped[1] * pixel[1] + notclipped[2] * pixel[2]) / + (notclipped[1] * clipfix[1] + notclipped[2] * clipfix[2] + epsilon))); } if (notclipped[1] == 0.f) { //green clipped - green[i][j] = max(green[i][j], (clipfix[1] * ((notclipped[2] * pixel[2] + notclipped[0] * pixel[0]) / - (notclipped[2] * clipfix[2] + notclipped[0] * clipfix[0] + epsilon)))); + green[i + miny][j + minx] = max(pixel[1], clipfix[1] * ((notclipped[2] * pixel[2] + notclipped[0] * pixel[0]) / + (notclipped[2] * clipfix[2] + notclipped[0] * clipfix[0] + epsilon))); } if (notclipped[2] == 0.f) { //blue clipped - blue[i][j] = max(blue[i][j], (clipfix[2] * ((notclipped[0] * pixel[0] + notclipped[1] * pixel[1]) / - (notclipped[0] * clipfix[0] + notclipped[1] * clipfix[1] + epsilon)))); + blue[i + miny][j + minx] = max(pixel[2], clipfix[2] * ((notclipped[0] * pixel[0] + notclipped[1] * pixel[1]) / + (notclipped[0] * clipfix[0] + notclipped[1] * clipfix[1] + epsilon))); } } - Y = (0.299 * red[i][j] + 0.587 * green[i][j] + 0.114 * blue[i][j]); + Y = 0.299f * red[i + miny][j + minx] + 0.587f * green[i + miny][j + minx] + 0.114f * blue[i + miny][j + minx]; if (Y > whitept) { - float factor = whitept / Y; + const float mult = whitept / Y; - red[i][j] *= factor; - green[i][j] *= factor; - blue[i][j] *= factor; + red[i + miny][j + minx] *= mult; + green[i + miny][j + minx] *= mult; + blue[i + miny][j + minx] *= mult; } } } - if(plistener) { + if (plistener) { plistener->setProgress(1.00); } }// end of HLReconstruction - } diff --git a/rtengine/histmatching.cc b/rtengine/histmatching.cc index 322775ca4..6705432d5 100644 --- a/rtengine/histmatching.cc +++ b/rtengine/histmatching.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "rawimagesource.h" @@ -327,8 +327,8 @@ void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, st int tw = target->getWidth(), th = target->getHeight(); float thumb_ratio = float(std::max(sw, sh)) / float(std::min(sw, sh)); float target_ratio = float(std::max(tw, th)) / float(std::min(tw, th)); - int cx = 0, cy = 0; if (std::abs(thumb_ratio - target_ratio) > 0.01) { + int cx = 0, cy = 0; if (thumb_ratio > target_ratio) { // crop the height int ch = th - (tw * float(sh) / float(sw)); diff --git a/rtengine/hphd_demosaic_RT.cc b/rtengine/hphd_demosaic_RT.cc index 7e27b90a5..0e56eae48 100644 --- a/rtengine/hphd_demosaic_RT.cc +++ b/rtengine/hphd_demosaic_RT.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtengine/iccjpeg.h b/rtengine/iccjpeg.h index ce715948d..5197d1602 100644 --- a/rtengine/iccjpeg.h +++ b/rtengine/iccjpeg.h @@ -15,6 +15,7 @@ * with ICC profiles exceeding 64K bytes in size. See iccprofile.c * for details. */ +#pragma once #include /* needed to define "FILE", "NULL" */ #include "jpeglib.h" diff --git a/rtengine/iccmatrices.h b/rtengine/iccmatrices.h index 29426c62d..3e0d0b5d6 100644 --- a/rtengine/iccmatrices.h +++ b/rtengine/iccmatrices.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _ICCMATRICES_ #define _ICCMATRICES_ diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index 268a6b1c2..a8d54b810 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtengine/iccstore.h b/rtengine/iccstore.h index 6b57fd072..5c76660e5 100644 --- a/rtengine/iccstore.h +++ b/rtengine/iccstore.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtengine/iimage.cc b/rtengine/iimage.cc index c9a4f223a..a1ec979a1 100644 --- a/rtengine/iimage.cc +++ b/rtengine/iimage.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "procparams.h" diff --git a/rtengine/iimage.h b/rtengine/iimage.h index ff016df1a..b04b4bf9a 100644 --- a/rtengine/iimage.h +++ b/rtengine/iimage.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _IIMAGE_ #define _IIMAGE_ diff --git a/rtengine/image16.cc b/rtengine/image16.cc index c0e97557a..0cdcc578f 100644 --- a/rtengine/image16.cc +++ b/rtengine/image16.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "image16.h" #include "imagefloat.h" @@ -74,7 +74,7 @@ void Image16::getScanline(int row, unsigned char* buffer, int bps, bool isFloat) } } -void Image16::setScanline(int row, unsigned char* buffer, int bps, unsigned int numSamples) +void Image16::setScanline(int row, const unsigned char* buffer, int bps, unsigned int numSamples) { if (data == nullptr) { @@ -101,7 +101,7 @@ void Image16::setScanline(int row, unsigned char* buffer, int bps, unsigned int } case (IIOSF_UNSIGNED_SHORT): { - unsigned short* sbuffer = (unsigned short*) buffer; + const unsigned short* sbuffer = (const unsigned short*) buffer; int ix = 0; for (int i = 0; i < width; ++i) { diff --git a/rtengine/image16.h b/rtengine/image16.h index 9762af990..07747a172 100644 --- a/rtengine/image16.h +++ b/rtengine/image16.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ // // A class representing a 16 bit rgb image with separate planes and 16 byte aligned data @@ -56,7 +56,7 @@ public: } void getScanline(int row, unsigned char* buffer, int bps, bool isFloat = false) const override; - void setScanline(int row, unsigned char* buffer, int bps, unsigned int numSamples) override; + void setScanline(int row, const unsigned char* buffer, int bps, unsigned int numSamples) override; // functions inherited from IImage16: MyMutex& getMutex() override diff --git a/rtengine/image8.cc b/rtengine/image8.cc index 513b0049e..abcd4efae 100644 --- a/rtengine/image8.cc +++ b/rtengine/image8.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -55,7 +55,7 @@ void Image8::getScanline (int row, unsigned char* buffer, int bps, bool isFloat) } } -void Image8::setScanline (int row, unsigned char* buffer, int bps, unsigned int numSamples) +void Image8::setScanline (int row, const unsigned char* buffer, int bps, unsigned int numSamples) { if (data == nullptr) { @@ -74,7 +74,7 @@ void Image8::setScanline (int row, unsigned char* buffer, int bps, unsigned int break; case (IIOSF_UNSIGNED_SHORT): { - unsigned short* sbuffer = (unsigned short*) buffer; + const unsigned short* sbuffer = (const unsigned short*) buffer; for (int i = 0, ix = row * width * 3; i < width * 3; ++i, ++ix) { data[ix] = uint16ToUint8Rounded(sbuffer[i]); diff --git a/rtengine/image8.h b/rtengine/image8.h index 8928cf85b..969627f69 100644 --- a/rtengine/image8.h +++ b/rtengine/image8.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ // // A class representing a 8 bit rgb image without alpha channel @@ -53,7 +53,7 @@ public: } void getScanline (int row, unsigned char* buffer, int bps, bool isFloat = false) const override; - void setScanline (int row, unsigned char* buffer, int bps, unsigned int numSamples) override; + void setScanline (int row, const unsigned char* buffer, int bps, unsigned int numSamples) override; // functions inherited from IImage*: MyMutex& getMutex () override diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 6897490ac..4469c367d 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -68,8 +68,8 @@ FramesData::FramesData(const Glib::ustring &fname) : ok_(false), fname_(fname), dcrawFrameCount(0), - time(), - timeStamp(), + time{}, + timeStamp{}, iso_speed(0), aperture(0.), focal_len(0.), @@ -80,20 +80,12 @@ FramesData::FramesData(const Glib::ustring &fname) : make("Unknown"), model("Unknown"), orientation("Unknown"), + rating(0), // FIXME: Implement lens("Unknown"), sampleFormat(IIOSF_UNKNOWN), isPixelShift(false), isHDR(false) { - memset(&time, 0, sizeof(time)); - timeStamp = 0; - iso_speed = 0; - aperture = 0.0; - focal_len = 0.0; - focal_len35mm = 0.0; - focus_dist = 0.0f; - shutter = 0.0; - expcomp = 0.0; make.clear(); model.clear(); serial.clear(); @@ -567,6 +559,12 @@ std::string FramesData::getOrientation() const } +int FramesData::getRating() const +{ + return rating; +} + + void FramesData::setDCRawFrameCount(unsigned int frameCount) { dcrawFrameCount = frameCount; diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index eeeefdc58..dadec755f 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once @@ -52,6 +52,7 @@ private: double expcomp; std::string make, model, serial; std::string orientation; + int rating; std::string lens; IIOSampleFormat sampleFormat; bool isPixelShift; @@ -81,6 +82,7 @@ public: std::string getLens() const override; std::string getSerialNumber() const; std::string getOrientation() const override; + int getRating() const override; Glib::ustring getFileName() const override; }; diff --git a/rtengine/imagedimensions.cc b/rtengine/imagedimensions.cc index 7dec1358a..5b60e5da7 100644 --- a/rtengine/imagedimensions.cc +++ b/rtengine/imagedimensions.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "imagedimensions.h" diff --git a/rtengine/imagedimensions.h b/rtengine/imagedimensions.h index 63b1a1062..eb92798c3 100644 --- a/rtengine/imagedimensions.h +++ b/rtengine/imagedimensions.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtengine/imagefloat.cc b/rtengine/imagefloat.cc index d98a817a2..8a9a511a6 100644 --- a/rtengine/imagefloat.cc +++ b/rtengine/imagefloat.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include "imagefloat.h" @@ -45,7 +45,7 @@ Imagefloat::~Imagefloat () } // Call this method to handle floating points input values of different size -void Imagefloat::setScanline (int row, unsigned char* buffer, int bps, unsigned int numSamples) +void Imagefloat::setScanline (int row, const unsigned char* buffer, int bps, unsigned int numSamples) { if (data == nullptr) { @@ -58,7 +58,7 @@ void Imagefloat::setScanline (int row, unsigned char* buffer, int bps, unsigned switch (sampleFormat) { case (IIOSF_FLOAT16): { int ix = 0; - uint16_t* sbuffer = (uint16_t*) buffer; + const uint16_t* sbuffer = (const uint16_t*) buffer; for (int i = 0; i < width; i++) { r(row, i) = 65535.f * DNG_HalfToFloat(sbuffer[ix++]); @@ -71,7 +71,7 @@ void Imagefloat::setScanline (int row, unsigned char* buffer, int bps, unsigned //case (IIOSF_FLOAT24): case (IIOSF_FLOAT32): { int ix = 0; - float* sbuffer = (float*) buffer; + const float* sbuffer = (const float*) buffer; for (int i = 0; i < width; i++) { r(row, i) = 65535.f * sbuffer[ix++]; @@ -85,7 +85,7 @@ void Imagefloat::setScanline (int row, unsigned char* buffer, int bps, unsigned case (IIOSF_LOGLUV24): case (IIOSF_LOGLUV32): { int ix = 0; - float* sbuffer = (float*) buffer; + const float* sbuffer = (const float*) buffer; float xyzvalues[3], rgbvalues[3]; for (int i = 0; i < width; i++) { diff --git a/rtengine/imagefloat.h b/rtengine/imagefloat.h index e1e5086b8..261a0677c 100644 --- a/rtengine/imagefloat.h +++ b/rtengine/imagefloat.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ // // A class representing a 16 bit rgb image with separate planes and 16 byte aligned data @@ -62,7 +62,7 @@ public: } void getScanline (int row, unsigned char* buffer, int bps, bool isFloat = false) const override; - void setScanline (int row, unsigned char* buffer, int bps, unsigned int numSamples) override; + void setScanline (int row, const unsigned char* buffer, int bps, unsigned int numSamples) override; // functions inherited from IImagefloat: MyMutex& getMutex () override diff --git a/rtengine/imageformat.h b/rtengine/imageformat.h index 22708daef..dc40cf147 100644 --- a/rtengine/imageformat.h +++ b/rtengine/imageformat.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _IMAGEFORMAT_ #define _IMAGEFORMAT_ diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index d7c074b34..4fbc9f537 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -837,12 +837,12 @@ int ImageIO::loadPPMFromMemory(const char* buffer, int width, int height, bool s char swapped[line_length]; for ( int row = 0; row < height; ++row ) { - ::rtengine::swab(((char*)buffer) + (row * line_length), swapped, line_length); + ::rtengine::swab(((const char*)buffer) + (row * line_length), swapped, line_length); setScanline(row, (unsigned char*)&swapped[0], bps); } } else { for ( int row = 0; row < height; ++row ) { - setScanline(row, ((unsigned char*)buffer) + (row * line_length), bps); + setScanline(row, ((const unsigned char*)buffer) + (row * line_length), bps); } } diff --git a/rtengine/imageio.h b/rtengine/imageio.h index f0eafc701..4781aa750 100644 --- a/rtengine/imageio.h +++ b/rtengine/imageio.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _IMAGEIO_ #define _IMAGEIO_ @@ -103,7 +103,7 @@ public: virtual void getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, PreviewProps pp) const = 0; virtual int getBPS () const = 0; virtual void getScanline (int row, unsigned char* buffer, int bps, bool isFloat = false) const = 0; - virtual void setScanline (int row, unsigned char* buffer, int bps, unsigned int numSamples = 3) = 0; + virtual void setScanline (int row, const unsigned char* buffer, int bps, unsigned int numSamples = 3) = 0; virtual const char* getType () const = 0; int load (const Glib::ustring &fname); diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 8ce3ee2e9..e224a644f 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -14,22 +14,24 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ -#ifndef _IMAGESOURCE_ -#define _IMAGESOURCE_ +#pragma once + +#include +#include #include -#include -#include "rtengine.h" + #include "colortemp.h" #include "coord2d.h" #include "dcp.h" -#include "LUT.h" -#include "imagedata.h" -#include "image8.h" #include "image16.h" +#include "image8.h" +#include "imagedata.h" #include "imagefloat.h" +#include "LUT.h" +#include "rtengine.h" namespace rtengine { @@ -39,11 +41,12 @@ namespace procparams struct CoarseTransformParams; struct ColorManagementParams; +struct FilmNegativeParams; struct LensProfParams; struct RAWParams; struct RetinexParams; struct ToneCurveParams; - +struct CaptureSharpeningParams; } class ImageMatrices @@ -56,6 +59,7 @@ public: double cam_xyz[3][3] = {}; }; +// TODO: Move implementation to .cc (Flössie) class ImageSource : public InitialImage { @@ -77,7 +81,9 @@ public: ~ImageSource () override {} virtual int load (const Glib::ustring &fname) = 0; virtual void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, bool prepareDenoise = true) {}; - virtual void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold) {}; + virtual void filmNegativeProcess (const procparams::FilmNegativeParams ¶ms) {}; + virtual bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams& currentParams, std::array& newExps) { return false; }; + virtual void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold, bool cache = false) {}; virtual void retinex (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &deh, const procparams::ToneCurveParams& Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) {}; virtual void retinexPrepareCurves (const procparams::RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) {}; virtual void retinexPrepareBuffers (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI) {}; @@ -176,6 +182,7 @@ public: return this; } virtual void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) = 0; + virtual void captureSharpening(const procparams::CaptureSharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold, double &radius) = 0; }; + } -#endif diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 2ffcd1125..f57597500 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "improccoordinator.h" #include "curves.h" @@ -53,6 +53,7 @@ ImProcCoordinator::ImProcCoordinator() : softProof(false), gamutCheck(false), sharpMask(false), + sharpMaskChanged(false), scale(10), highDetailPreprocessComputed(false), highDetailRawComputed(false), @@ -120,6 +121,8 @@ ImProcCoordinator::ImProcCoordinator() : flatFieldAutoClipListener(nullptr), bayerAutoContrastListener(nullptr), xtransAutoContrastListener(nullptr), + pdSharpenAutoContrastListener(nullptr), + pdSharpenAutoRadiusListener(nullptr), frameCountListener(nullptr), imageTypeListener(nullptr), actListener(nullptr), @@ -277,6 +280,18 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) imgsrc->getRAWHistogram(histRedRaw, histGreenRaw, histBlueRaw); highDetailPreprocessComputed = highDetailNeeded; + + // After preprocess, run film negative processing if enabled + if ( + (todo & M_RAW) + && ( + imgsrc->getSensorType() == ST_BAYER + || imgsrc->getSensorType() == ST_FUJI_XTRANS + ) + && params->filmNegative.enabled + ) { + imgsrc->filmNegativeProcess(params->filmNegative); + } } /* @@ -318,18 +333,35 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) } bool autoContrast = imgsrc->getSensorType() == ST_BAYER ? params->raw.bayersensor.dualDemosaicAutoContrast : params->raw.xtranssensor.dualDemosaicAutoContrast; double contrastThreshold = imgsrc->getSensorType() == ST_BAYER ? params->raw.bayersensor.dualDemosaicContrast : params->raw.xtranssensor.dualDemosaicContrast; - imgsrc->demosaic(rp, autoContrast, contrastThreshold); //enabled demosaic + imgsrc->demosaic(rp, autoContrast, contrastThreshold, params->pdsharpening.enabled); if (imgsrc->getSensorType() == ST_BAYER && bayerAutoContrastListener && autoContrast) { - bayerAutoContrastListener->autoContrastChanged(autoContrast ? contrastThreshold : -1.0); - } - if (imgsrc->getSensorType() == ST_FUJI_XTRANS && xtransAutoContrastListener && autoContrast) { + bayerAutoContrastListener->autoContrastChanged(contrastThreshold); + } else if (imgsrc->getSensorType() == ST_FUJI_XTRANS && xtransAutoContrastListener && autoContrast) { xtransAutoContrastListener->autoContrastChanged(autoContrast ? contrastThreshold : -1.0); } - // if a demosaic happened we should also call getimage later, so we need to set the M_INIT flag - todo |= M_INIT; + todo |= (M_INIT | M_CSHARP); + } + + if ((todo & (M_RAW | M_CSHARP)) && params->pdsharpening.enabled) { + double pdSharpencontrastThreshold = params->pdsharpening.contrast; + double pdSharpenRadius = params->pdsharpening.deconvradius; + imgsrc->captureSharpening(params->pdsharpening, sharpMask, pdSharpencontrastThreshold, pdSharpenRadius); + if (pdSharpenAutoContrastListener && params->pdsharpening.autoContrast) { + pdSharpenAutoContrastListener->autoContrastChanged(pdSharpencontrastThreshold); + } + if (pdSharpenAutoRadiusListener && params->pdsharpening.autoRadius) { + pdSharpenAutoRadiusListener->autoRadiusChanged(pdSharpenRadius); + } + } + + + if ((todo & M_RAW) + || (!highDetailRawComputed && highDetailNeeded) + || (params->toneCurve.hrenabled && params->toneCurve.method != "Color" && imgsrc->isRGBSourceModified()) + || (!params->toneCurve.hrenabled && params->toneCurve.method == "Color" && imgsrc->isRGBSourceModified())) { if (highDetailNeeded) { highDetailRawComputed = true; } else { @@ -1240,6 +1272,31 @@ void ImProcCoordinator::getSpotWB(int x, int y, int rect, double& temp, double& } } +bool ImProcCoordinator::getFilmNegativeExponents(int xA, int yA, int xB, int yB, std::array& newExps) +{ + MyMutex::MyLock lock(mProcessing); + + const auto xlate = + [this](int x, int y) -> Coord2D + { + const std::vector points = {Coord2D(x, y)}; + + std::vector red; + std::vector green; + std::vector blue; + ipf.transCoord(fw, fh, points, red, green, blue); + + return green[0]; + }; + + const int tr = getCoarseBitMask(params->coarse); + + const Coord2D p1 = xlate(xA, yA); + const Coord2D p2 = xlate(xB, yB); + + return imgsrc->getFilmNegativeExponents(p1, p2, tr, params->filmNegative, newExps); +} + void ImProcCoordinator::getAutoCrop(double ratio, int &x, int &y, int &w, int &h) { @@ -1297,9 +1354,16 @@ void ImProcCoordinator::getSoftProofing(bool &softProof, bool &gamutCheck) gamutCheck = this->gamutCheck; } -void ImProcCoordinator::setSharpMask (bool sharpMask) +ProcEvent ImProcCoordinator::setSharpMask (bool sharpMask) { - this->sharpMask = sharpMask; + if (this->sharpMask != sharpMask) { + sharpMaskChanged = true; + this->sharpMask = sharpMask; + return params->pdsharpening.enabled ? rtengine::EvPdShrMaskToggled : rtengine::EvShrEnabled; + } else { + sharpMaskChanged = false; + return rtengine::EvShrEnabled; + } } void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool apply_wb) @@ -1467,13 +1531,13 @@ void ImProcCoordinator::process() while (changeSinceLast) { const bool panningRelatedChange = - params->toneCurve != nextParams->toneCurve + params->toneCurve.isPanningRelatedChange(nextParams->toneCurve) || params->labCurve != nextParams->labCurve || params->localContrast != nextParams->localContrast || params->rgbCurves != nextParams->rgbCurves || params->colorToning != nextParams->colorToning || params->vibrance != nextParams->vibrance - || params->wb != nextParams->wb + || params->wb.isPanningRelatedChange(nextParams->wb) || params->colorappearance != nextParams->colorappearance || params->epd != nextParams->epd || params->fattal != nextParams->fattal @@ -1499,8 +1563,11 @@ void ImProcCoordinator::process() || params->retinex != nextParams->retinex || params->wavelet != nextParams->wavelet || params->dirpyrequalizer != nextParams->dirpyrequalizer - || params->dehaze != nextParams->dehaze; + || params->dehaze != nextParams->dehaze + || params->pdsharpening != nextParams->pdsharpening + || sharpMaskChanged; + sharpMaskChanged = false; *params = *nextParams; int change = changeSinceLast; changeSinceLast = 0; diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index c293f0c16..379a3fb20 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _IMPROCCOORDINATOR_H_ #define _IMPROCCOORDINATOR_H_ @@ -77,7 +77,7 @@ protected: bool softProof; bool gamutCheck; bool sharpMask; - + bool sharpMaskChanged; int scale; bool highDetailPreprocessComputed; bool highDetailRawComputed; @@ -161,6 +161,8 @@ protected: FlatFieldAutoClipListener *flatFieldAutoClipListener; AutoContrastListener *bayerAutoContrastListener; AutoContrastListener *xtransAutoContrastListener; + AutoContrastListener *pdSharpenAutoContrastListener; + AutoRadiusListener *pdSharpenAutoRadiusListener; FrameCountListener *frameCountListener; ImageTypeListener *imageTypeListener; @@ -269,6 +271,7 @@ public: bool getAutoWB (double& temp, double& green, double equal, double tempBias) override; void getCamWB (double& temp, double& green) override; void getSpotWB (int x, int y, int rectSize, double& temp, double& green) override; + bool getFilmNegativeExponents(int xA, int yA, int xB, int yB, std::array& newExps) override; void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) override; bool getHighQualComputed() override; void setHighQualComputed() override; @@ -276,7 +279,7 @@ public: void getMonitorProfile (Glib::ustring& profile, RenderingIntent& intent) const override; void setSoftProofing (bool softProof, bool gamutCheck) override; void getSoftProofing (bool &softProof, bool &gamutCheck) override; - void setSharpMask (bool sharpMask) override; + ProcEvent setSharpMask (bool sharpMask) override; bool updateTryLock () override { return updaterThreadStart.trylock(); @@ -362,6 +365,16 @@ public: xtransAutoContrastListener = acl; } + void setpdSharpenAutoRadiusListener (AutoRadiusListener* acl) override + { + pdSharpenAutoRadiusListener = acl; + } + + void setpdSharpenAutoContrastListener (AutoContrastListener* acl) override + { + pdSharpenAutoContrastListener = acl; + } + void setImageTypeListener (ImageTypeListener* itl) override { imageTypeListener = itl; diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index e917930de..985c3472c 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -1720,7 +1720,7 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int pW, int pw float t_l = static_cast (params->dirpyrequalizer.hueskin.getTopLeft()) / 100.0f; float t_r = static_cast (params->dirpyrequalizer.hueskin.getTopRight()) / 100.0f; lab->deleteLab(); - dirpyr_equalizercam (ncie, ncie->sh_p, ncie->sh_p, ncie->W, ncie->H, ncie->h_p, ncie->C_p, params->dirpyrequalizer.mult, params->dirpyrequalizer.threshold, params->dirpyrequalizer.skinprotect, true, b_l, t_l, t_r, scale); //contrast by detail adapted to CIECAM + dirpyr_equalizercam (ncie, ncie->sh_p, ncie->sh_p, ncie->W, ncie->H, ncie->h_p, ncie->C_p, params->dirpyrequalizer.mult, params->dirpyrequalizer.threshold, params->dirpyrequalizer.skinprotect, b_l, t_l, t_r, scale); //contrast by detail adapted to CIECAM lab->reallocLab(); } @@ -2255,7 +2255,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer bool hasColorToningLabGrid = params->colorToning.enabled && params->colorToning.method == "LabGrid"; // float satLimit = float(params->colorToning.satProtectionThreshold)/100.f*0.7f+0.3f; // float satLimitOpacity = 1.f-(float(params->colorToning.saturatedOpacity)/100.f); - float strProtect = (float (params->colorToning.strength) / 100.f); + float strProtect = pow_F((float (params->colorToning.strength) / 100.f), 0.4f); /* // Debug output - Color LUTf points @@ -2793,7 +2793,6 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer const float krh = rh / (rh + gh + bh); const float kgh = gh / (rh + gh + bh); const float kbh = bh / (rh + gh + bh); - strProtect = pow_F(strProtect, 0.4f); constexpr int mode = 0; for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { @@ -2806,7 +2805,6 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer else if (params->colorToning.method == "Splitco") { constexpr float reducac = 0.3f; constexpr int mode = 0; - strProtect = pow_F(strProtect, 0.4f); for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { const float r = rtemp[ti * TS + tj]; @@ -3483,7 +3481,6 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer const float krh = rh / (rh + gh + bh); const float kgh = gh / (rh + gh + bh); const float kbh = bh / (rh + gh + bh); - strProtect = pow_F(strProtect, 0.4f); constexpr int mode = 1; #ifdef _OPENMP #pragma omp parallel for schedule(dynamic, 5) @@ -3788,11 +3785,12 @@ void ImProcFunctions::toningsmh(float r, float g, float b, float &ro, float &go, { const float corr = 20000.f * RedLow * kl * rlo; + if (RedLow > 0.f) { + r += corr; + } else { g -= corr; b -= corr; - } else { - r += corr; } // r = CLIP(r); @@ -3802,27 +3800,28 @@ void ImProcFunctions::toningsmh(float r, float g, float b, float &ro, float &go, { const float corr = 20000.f * GreenLow * kl * rlo; + if (GreenLow > 0.f) { + g += corr; + } else { r -= corr; b -= corr; - } else { - g += corr; } // r = CLIP(r); - // b = CLIP(b); // g = CLIP(g); + // b = CLIP(b); } { - const float corr = 20000.f * BlueLow * kl * rlob; + const float corr = 20000.f * BlueLow * kl * rlo; if (BlueLow > 0.f) { + b += corr; + } else { r -= corr; g -= corr; - } else { - b += corr; } // r = CLIP(r); @@ -4248,11 +4247,9 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW if (params->labCurve.chromaticity > -100) { chCurve = new FlatCurve (params->labCurve.chcurve); - if (!chCurve || chCurve->isIdentity()) { - if (chCurve) { - delete chCurve; - chCurve = nullptr; - } + if (chCurve->isIdentity()) { + delete chCurve; + chCurve = nullptr; }//do not use "Munsell" if Chcurve not used else { chutili = true; @@ -4265,11 +4262,9 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW if (params->labCurve.chromaticity > -100) { lhCurve = new FlatCurve (params->labCurve.lhcurve); - if (!lhCurve || lhCurve->isIdentity()) { - if (lhCurve) { - delete lhCurve; - lhCurve = nullptr; - } + if (lhCurve->isIdentity()) { + delete lhCurve; + lhCurve = nullptr; }//do not use "Munsell" if Chcurve not used else { lhutili = true; @@ -4282,11 +4277,9 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW if (params->labCurve.chromaticity > -100) { hhCurve = new FlatCurve (params->labCurve.hhcurve); - if (!hhCurve || hhCurve->isIdentity()) { - if (hhCurve) { - delete hhCurve; - hhCurve = nullptr; - } + if (hhCurve->isIdentity()) { + delete hhCurve; + hhCurve = nullptr; }//do not use "Munsell" if Chcurve not used else { hhutili = true; @@ -5653,7 +5646,7 @@ void ImProcFunctions::getAutoExp (const LUTu &histogram, int histcompr, double double ImProcFunctions::getAutoDistor (const Glib::ustring &fname, int thumb_size) { - if (fname != "") { + if (!fname.empty()) { // TODO: std::unique_ptr<> to the rescue int w_raw = -1, h_raw = thumb_size; int w_thumb = -1, h_thumb = thumb_size; @@ -5816,7 +5809,7 @@ void ImProcFunctions::lab2rgb (const LabImage &src, Imagefloat &dst, const Glib: GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with darktable. If not, see . + along with darktable. If not, see . */ void ImProcFunctions::colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread) { diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index cd1650f6e..84da1cacc 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _IMPROCFUN_H_ #define _IMPROCFUN_H_ @@ -77,116 +77,6 @@ class ImProcFunctions bool needsLensfun(); // static cmsUInt8Number* Mempro = NULL; - inline void interpolateTransformCubic(Imagefloat* src, int xs, int ys, double Dx, double Dy, float *r, float *g, float *b, double mul) - { - const double A = -0.85; - - double w[4]; - - { - double t1, t2; - t1 = -A * (Dx - 1.0) * Dx; - t2 = (3.0 - 2.0 * Dx) * Dx * Dx; - w[3] = t1 * Dx; - w[2] = t1 * (Dx - 1.0) + t2; - w[1] = -t1 * Dx + 1.0 - t2; - w[0] = -t1 * (Dx - 1.0); - } - - double rd, gd, bd; - double yr[4] = {0.0}, yg[4] = {0.0}, yb[4] = {0.0}; - - for (int k = ys, kx = 0; k < ys + 4; k++, kx++) { - rd = gd = bd = 0.0; - - for (int i = xs, ix = 0; i < xs + 4; i++, ix++) { - rd += src->r(k, i) * w[ix]; - gd += src->g(k, i) * w[ix]; - bd += src->b(k, i) * w[ix]; - } - - yr[kx] = rd; - yg[kx] = gd; - yb[kx] = bd; - } - - - { - double t1, t2; - - t1 = -A * (Dy - 1.0) * Dy; - t2 = (3.0 - 2.0 * Dy) * Dy * Dy; - w[3] = t1 * Dy; - w[2] = t1 * (Dy - 1.0) + t2; - w[1] = -t1 * Dy + 1.0 - t2; - w[0] = -t1 * (Dy - 1.0); - } - - rd = gd = bd = 0.0; - - for (int i = 0; i < 4; i++) { - rd += yr[i] * w[i]; - gd += yg[i] * w[i]; - bd += yb[i] * w[i]; - } - - *r = rd * mul; - *g = gd * mul; - *b = bd * mul; - - // if (xs==100 && ys==100) - // printf ("r=%g, g=%g\n", *r, *g); - } - - inline void interpolateTransformChannelsCubic(float** src, int xs, int ys, double Dx, double Dy, float *r, double mul) - { - const double A = -0.85; - - double w[4]; - - { - double t1, t2; - t1 = -A * (Dx - 1.0) * Dx; - t2 = (3.0 - 2.0 * Dx) * Dx * Dx; - w[3] = t1 * Dx; - w[2] = t1 * (Dx - 1.0) + t2; - w[1] = -t1 * Dx + 1.0 - t2; - w[0] = -t1 * (Dx - 1.0); - } - - double rd; - double yr[4] = {0.0}; - - for (int k = ys, kx = 0; k < ys + 4; k++, kx++) { - rd = 0.0; - - for (int i = xs, ix = 0; i < xs + 4; i++, ix++) { - rd += src[k][i] * w[ix]; - } - - yr[kx] = rd; - } - - - { - double t1, t2; - t1 = -A * (Dy - 1.0) * Dy; - t2 = (3.0 - 2.0 * Dy) * Dy * Dy; - w[3] = t1 * Dy; - w[2] = t1 * (Dy - 1.0) + t2; - w[1] = -t1 * Dy + 1.0 - t2; - w[0] = -t1 * (Dy - 1.0); - } - - rd = 0.0; - - for (int i = 0; i < 4; i++) { - rd += yr[i] * w[i]; - } - - *r = rd * mul; - } - public: enum class Median { @@ -200,7 +90,7 @@ public: double lumimul[3]; - ImProcFunctions(const ProcParams* iparams, bool imultiThread = true) + explicit ImProcFunctions(const ProcParams* iparams, bool imultiThread = true) : monitorTransform(nullptr), params(iparams), scale(1), multiThread(imultiThread), lumimul{} {} ~ImProcFunctions(); bool needsLuminanceOnly() @@ -248,7 +138,7 @@ public: void Lanczos(const LabImage* src, LabImage* dst, float scale); void Lanczos(const Imagefloat* src, Imagefloat* dst, float scale); - void deconvsharpening(float** luminance, float** buffer, int W, int H, const procparams::SharpeningParams &sharpenParam); + void deconvsharpening(float** luminance, float** buffer, const float* const * blend, int W, int H, const procparams::SharpeningParams &sharpenParam, double Scale); void MLsharpen(LabImage* lab); // Manuel's clarity / sharpening void MLmicrocontrast(float** luminance, int W, int H); //Manuel's microcontrast void MLmicrocontrast(LabImage* lab); //Manuel's microcontrast @@ -332,11 +222,8 @@ public: float MadRgb(const float * DataList, int datalen); // pyramid wavelet - void dirpyr_equalizer(float ** src, float ** dst, int srcwidth, int srcheight, float ** l_a, float ** l_b, const double * mult, const double dirpyrThreshold, const double skinprot, float b_l, float t_l, float t_r, int scale); //Emil's directional pyramid wavelet - void dirpyr_equalizercam(CieImage* ncie, float ** src, float ** dst, int srcwidth, int srcheight, float ** h_p, float ** C_p, const double * mult, const double dirpyrThreshold, const double skinprot, bool execdir, float b_l, float t_l, float t_r, int scale); //Emil's directional pyramid wavelet - void dirpyr_channel(float ** data_fine, float ** data_coarse, int width, int height, int level, int scale); - void idirpyr_eq_channel(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float multi[6], const double dirpyrThreshold, float ** l_a_h, float ** l_b_c, const double skinprot, float b_l, float t_l, float t_r); - void idirpyr_eq_channelcam(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float multi[6], const double dirpyrThreshold, float ** l_a_h, float ** l_b_c, const double skinprot, float b_l, float t_l, float t_r); + void dirpyr_equalizer(const float * const * src, float ** dst, int srcwidth, int srcheight, const float * const * l_a, const float * const * l_b, const double * mult, double dirpyrThreshold, double skinprot, float b_l, float t_l, float t_r, int scale); //Emil's directional pyramid wavelet + void dirpyr_equalizercam(const CieImage* ncie, float ** src, float ** dst, int srcwidth, int srcheight, const float * const * h_p, const float * const * C_p, const double * mult, const double dirpyrThreshold, const double skinprot, float b_l, float t_l, float t_r, int scale); //Emil's directional pyramid wavelet void defringe(LabImage* lab); void defringecam(CieImage* ncie); void badpixcam(CieImage* ncie, double rad, int thr, int mode, float chrom, bool hotbad); diff --git a/rtengine/impulse_denoise.cc b/rtengine/impulse_denoise.cc index 907afc1a1..c08f55700 100644 --- a/rtengine/impulse_denoise.cc +++ b/rtengine/impulse_denoise.cc @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * 2010 Emil Martinec * diff --git a/rtengine/init.cc b/rtengine/init.cc index 8d7ee451f..8d3ee96cb 100644 --- a/rtengine/init.cc +++ b/rtengine/init.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include "../rtgui/profilestorecombobox.h" diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc index c1092e335..e7bf71ba6 100644 --- a/rtengine/ipdehaze.cc +++ b/rtengine/ipdehaze.cc @@ -15,8 +15,8 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - */ + * along with RawTherapee. If not, see . +*/ /* * Haze removal using the algorithm described in the paper: @@ -26,15 +26,16 @@ * * using a guided filter for the "soft matting" of the transmission map * - */ +*/ +#include #include -#include +#include #include "guidedfilter.h" #include "improcfun.h" #include "procparams.h" -#include "rt_algo.h" +#include "rescale.h" #include "rt_math.h" extern Options options; @@ -43,24 +44,103 @@ namespace rtengine { namespace { -#if 0 -# define DEBUG_DUMP(arr) \ - do { \ - Imagefloat im(arr.width(), arr.height()); \ - const char *out = "/tmp/" #arr ".tif"; \ - for (int y = 0; y < im.getHeight(); ++y) { \ - for (int x = 0; x < im.getWidth(); ++x) { \ - im.r(y, x) = im.g(y, x) = im.b(y, x) = arr[y][x] * 65535.f; \ - } \ - } \ - im.saveTIFF(out, 16); \ - } while (false) -#else -# define DEBUG_DUMP(arr) +float normalize(Imagefloat *rgb, bool multithread) +{ + float maxval = 0.f; + const int W = rgb->getWidth(); + const int H = rgb->getHeight(); +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxval) schedule(dynamic, 16) if (multithread) #endif + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + maxval = max(maxval, rgb->r(y, x), rgb->g(y, x), rgb->b(y, x)); + } + } + maxval = max(maxval * 2.f, 65535.f); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) if (multithread) +#endif + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + rgb->r(y, x) /= maxval; + rgb->g(y, x) /= maxval; + rgb->b(y, x) /= maxval; + } + } + return maxval; +} +void restore(Imagefloat *rgb, float maxval, bool multithread) +{ + const int W = rgb->getWidth(); + const int H = rgb->getHeight(); + if (maxval > 0.f && maxval != 1.f) { +#ifdef _OPENMP +# pragma omp parallel for if (multithread) +#endif + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + rgb->r(y, x) *= maxval; + rgb->g(y, x) *= maxval; + rgb->b(y, x) *= maxval; + } + } + } +} -int get_dark_channel(const array2D &R, const array2D &G, const array2D &B, array2D &dst, int patchsize, const float ambient[3], bool clip, bool multithread) +int get_dark_channel(const array2D &R, const array2D &G, const array2D &B, const array2D &dst, int patchsize, const float ambient[3], bool clip, bool multithread, float strength) +{ + const int W = R.width(); + const int H = R.height(); + +#ifdef _OPENMP + #pragma omp parallel for if (multithread) +#endif + for (int y = 0; y < H; y += patchsize) { + const int pH = min(y + patchsize, H); + for (int x = 0; x < W; x += patchsize) { + float minR = RT_INFINITY_F; + float minG = RT_INFINITY_F; + float minB = RT_INFINITY_F; +#ifdef __SSE2__ + vfloat minRv = F2V(minR); + vfloat minGv = F2V(minG); + vfloat minBv = F2V(minB); +#endif + const int pW = min(x + patchsize, W); + for (int yy = y; yy < pH; ++yy) { + int xx = x; +#ifdef __SSE2__ + for (; xx < pW - 3; xx += 4) { + minRv = vminf(minRv, LVFU(R[yy][xx])); + minGv = vminf(minGv, LVFU(G[yy][xx])); + minBv = vminf(minBv, LVFU(B[yy][xx])); + } +#endif + for (; xx < pW; ++xx) { + minR = min(minR, R[yy][xx]); + minG = min(minG, G[yy][xx]); + minB = min(minB, B[yy][xx]); + } + } +#ifdef __SSE2__ + minR = min(minR, vhmin(minRv)); + minG = min(minG, vhmin(minGv)); + minB = min(minB, vhmin(minBv)); +#endif + float val = min(minR / ambient[0], minG / ambient[1], minB / ambient[2]); + val = 1.f - strength * LIM01(val); + for (int yy = y; yy < pH; ++yy) { + std::fill(dst[yy] + x, dst[yy] + pW, val); + } + } + } + + return (W / patchsize + ((W % patchsize) > 0)) * (H / patchsize + ((H % patchsize) > 0)); +} + +int get_dark_channel_downsized(const array2D &R, const array2D &G, const array2D &B, const array2D &dst, int patchsize, bool multithread) { const int W = R.width(); const int H = R.height(); @@ -73,22 +153,11 @@ int get_dark_channel(const array2D &R, const array2D &G, const arr for (int x = 0; x < W; x += patchsize) { float val = RT_INFINITY_F; const int pW = min(x + patchsize, W); - for (int yy = y; yy < pH; ++yy) { - for (int xx = x; xx < pW; ++xx) { - float r = R[yy][xx]; - float g = G[yy][xx]; - float b = B[yy][xx]; - if (ambient) { - r /= ambient[0]; - g /= ambient[1]; - b /= ambient[2]; - } - val = min(val, r, g, b); + for (int xx = x; xx < pW; ++xx) { + for (int yy = y; yy < pH; ++yy) { + val = min(val, R[yy][xx], G[yy][xx], B[yy][xx]); } } - if (clip) { - val = LIM01(val); - } for (int yy = y; yy < pH; ++yy) { std::fill(dst[yy] + x, dst[yy] + pW, val); } @@ -98,33 +167,24 @@ int get_dark_channel(const array2D &R, const array2D &G, const arr return (W / patchsize + ((W % patchsize) > 0)) * (H / patchsize + ((H % patchsize) > 0)); } - float estimate_ambient_light(const array2D &R, const array2D &G, const array2D &B, const array2D &dark, int patchsize, int npatches, float ambient[3]) { const int W = R.width(); const int H = R.height(); - const auto get_percentile = - [](std::priority_queue &q, float prcnt) -> float - { - size_t n = LIM(q.size() * prcnt, 1, q.size()); - while (q.size() > n) { - q.pop(); - } - return q.top(); - }; - float darklim = RT_INFINITY_F; { - std::priority_queue p; + std::vector p; for (int y = 0; y < H; y += patchsize) { for (int x = 0; x < W; x += patchsize) { if (!OOG(dark[y][x], 1.f - 1e-5f)) { - p.push(dark[y][x]); + p.push_back(dark[y][x]); } } } - darklim = get_percentile(p, 0.95); + const int pos = p.size() * 0.95; + std::nth_element(p.begin(), p.begin() + pos, p.end()); + darklim = p[pos]; } std::vector> patches; @@ -145,7 +205,8 @@ float estimate_ambient_light(const array2D &R, const array2D &G, c float bright_lim = RT_INFINITY_F; { - std::priority_queue l; + std::vector l; + l.reserve(patches.size() * patchsize * patchsize); for (auto &p : patches) { const int pW = min(p.first+patchsize, W); @@ -153,12 +214,13 @@ float estimate_ambient_light(const array2D &R, const array2D &G, c for (int y = p.second; y < pH; ++y) { for (int x = p.first; x < pW; ++x) { - l.push(R[y][x] + G[y][x] + B[y][x]); + l.push_back(R[y][x] + G[y][x] + B[y][x]); } } } - - bright_lim = get_percentile(l, 0.95); + const int pos = l.size() * 0.95; + std::nth_element(l.begin(), l.begin() + pos, l.end()); + bright_lim = l[pos]; } double rr = 0, gg = 0, bb = 0; @@ -190,7 +252,6 @@ float estimate_ambient_light(const array2D &R, const array2D &G, c return darklim > 0 ? -1.125f * std::log(darklim) : std::log(std::numeric_limits::max()) / 2; } - void extract_channels(Imagefloat *img, array2D &r, array2D &g, array2D &b, int radius, float epsilon, bool multithread) { const int W = img->getWidth(); @@ -211,12 +272,12 @@ void extract_channels(Imagefloat *img, array2D &r, array2D &g, arr void ImProcFunctions::dehaze(Imagefloat *img) { - if (!params->dehaze.enabled) { + if (!params->dehaze.enabled || params->dehaze.strength == 0.0) { return; } - img->normalizeFloatTo1(); - + const float maxChannel = normalize(img, multiThread); + const int W = img->getWidth(); const int H = img->getHeight(); const float strength = LIM01(float(params->dehaze.strength) / 100.f * 0.9f); @@ -228,22 +289,48 @@ void ImProcFunctions::dehaze(Imagefloat *img) array2D dark(W, H); int patchsize = max(int(5 / scale), 2); - int npatches = 0; float ambient[3]; - array2D &t_tilde = dark; - float max_t = 0.f; + float maxDistance = 0.f; { - array2D R(W, H); + array2D& R = dark; // R and dark can safely use the same buffer, which is faster and reduces memory allocations/deallocations array2D G(W, H); array2D B(W, H); extract_channels(img, R, G, B, patchsize, 1e-1, multiThread); - - patchsize = max(max(W, H) / 600, 2); - npatches = get_dark_channel(R, G, B, dark, patchsize, nullptr, false, multiThread); - DEBUG_DUMP(dark); - max_t = estimate_ambient_light(R, G, B, dark, patchsize, npatches, ambient); + { + constexpr int sizecap = 200; + const float r = static_cast(W) / static_cast(H); + const int hh = r >= 1.f ? sizecap : sizecap / r; + const int ww = r >= 1.f ? sizecap * r : sizecap; + + if (W <= ww && H <= hh) { + // don't rescale small thumbs + array2D D(W, H); + const int npatches = get_dark_channel_downsized(R, G, B, D, 2, multiThread); + maxDistance = estimate_ambient_light(R, G, B, D, patchsize, npatches, ambient); + } else { + array2D RR(ww, hh); + array2D GG(ww, hh); + array2D BB(ww, hh); + rescaleNearest(R, RR, multiThread); + rescaleNearest(G, GG, multiThread); + rescaleNearest(B, BB, multiThread); + array2D D(ww, hh); + + const int npatches = get_dark_channel_downsized(RR, GG, BB, D, 2, multiThread); + maxDistance = estimate_ambient_light(RR, GG, BB, D, patchsize, npatches, ambient); + } + } + + if (min(ambient[0], ambient[1], ambient[2]) < 0.01f) { + if (options.rtSettings.verbose) { + std::cout << "dehaze: no haze detected" << std::endl; + } + restore(img, maxChannel, multiThread); + return; // probably no haze at all + } + patchsize = max(max(W, H) / 600, 2); if (options.rtSettings.verbose) { std::cout << "dehaze: ambient light is " @@ -251,78 +338,95 @@ void ImProcFunctions::dehaze(Imagefloat *img) << std::endl; } - get_dark_channel(R, G, B, dark, patchsize, ambient, true, multiThread); - } - - if (min(ambient[0], ambient[1], ambient[2]) < 0.01f) { - if (options.rtSettings.verbose) { - std::cout << "dehaze: no haze detected" << std::endl; - } - img->normalizeFloatTo65535(); - return; // probably no haze at all - } - - DEBUG_DUMP(t_tilde); - -#ifdef _OPENMP - #pragma omp parallel for if (multiThread) -#endif - for (int y = 0; y < H; ++y) { - for (int x = 0; x < W; ++x) { - dark[y][x] = 1.f - strength * dark[y][x]; - } + get_dark_channel(R, G, B, dark, patchsize, ambient, true, multiThread, strength); } const int radius = patchsize * 4; - const float epsilon = 1e-5; - array2D &t = t_tilde; + constexpr float epsilon = 1e-5f; - { - array2D guideB(W, H, img->b.ptrs, ARRAY2D_BYREFERENCE); - guidedFilter(guideB, t_tilde, t, radius, epsilon, multiThread); - } + array2D guideB(W, H, img->b.ptrs, ARRAY2D_BYREFERENCE); + guidedFilter(guideB, dark, dark, radius, epsilon, multiThread); - DEBUG_DUMP(t); - if (options.rtSettings.verbose) { - std::cout << "dehaze: max distance is " << max_t << std::endl; + std::cout << "dehaze: max distance is " << maxDistance << std::endl; } - float depth = -float(params->dehaze.depth) / 100.f; - const float t0 = max(1e-3f, std::exp(depth * max_t)); + const float depth = -float(params->dehaze.depth) / 100.f; + const float t0 = max(1e-3f, std::exp(depth * maxDistance)); const float teps = 1e-3f; + + const bool luminance = params->dehaze.luminance; + const TMatrix ws = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile); +#ifdef __SSE2__ + const vfloat wsv[3] = {F2V(ws[1][0]), F2V(ws[1][1]),F2V(ws[1][2])}; +#endif + const float ambientY = Color::rgbLuminance(ambient[0], ambient[1], ambient[2], ws); #ifdef _OPENMP #pragma omp parallel for if (multiThread) #endif for (int y = 0; y < H; ++y) { - for (int x = 0; x < W; ++x) { + int x = 0; +#ifdef __SSE2__ + const vfloat onev = F2V(1.f); + const vfloat ambient0v = F2V(ambient[0]); + const vfloat ambient1v = F2V(ambient[1]); + const vfloat ambient2v = F2V(ambient[2]); + const vfloat ambientYv = F2V(ambientY); + const vfloat epsYv = F2V(1e-5f); + const vfloat t0v = F2V(t0); + const vfloat tepsv = F2V(teps); + const vfloat cmaxChannelv = F2V(maxChannel); + for (; x < W - 3; x += 4) { // ensure that the transmission is such that to avoid clipping... - float rgb[3] = { img->r(y, x), img->g(y, x), img->b(y, x) }; + const vfloat r = LVFU(img->r(y, x)); + const vfloat g = LVFU(img->g(y, x)); + const vfloat b = LVFU(img->b(y, x)); // ... t >= tl to avoid negative values - float tl = 1.f - min(rgb[0]/ambient[0], rgb[1]/ambient[1], rgb[2]/ambient[2]); - // ... t >= tu to avoid values > 1 - float tu = t0 - teps; - for (int c = 0; c < 3; ++c) { - if (ambient[c] < 1) { - tu = max(tu, (rgb[c] - ambient[c])/(1.f - ambient[c])); - } - } - float mt = max(t[y][x], t0, tl + teps, tu + teps); + const vfloat tlv = onev - vminf(r / ambient0v, vminf(g / ambient1v, b / ambient2v)); + const vfloat mtv = vmaxf(LVFU(dark[y][x]), vmaxf(tlv + tepsv, t0v)); if (params->dehaze.showDepthMap) { - img->r(y, x) = img->g(y, x) = img->b(y, x) = LIM01(1.f - mt); + const vfloat valv = vclampf(onev - mtv, ZEROV, onev) * cmaxChannelv; + STVFU(img->r(y, x), valv); + STVFU(img->g(y, x), valv); + STVFU(img->b(y, x), valv); + } else if (luminance) { + const vfloat Yv = Color::rgbLuminance(r, g, b, wsv); + const vfloat YYv = (Yv - ambientYv) / mtv + ambientYv; + const vfloat fv = vself(vmaskf_gt(Yv, epsYv), cmaxChannelv * YYv / Yv, cmaxChannelv); + STVFU(img->r(y, x), r * fv); + STVFU(img->g(y, x), g * fv); + STVFU(img->b(y, x), b * fv); } else { - float r = (rgb[0] - ambient[0]) / mt + ambient[0]; - float g = (rgb[1] - ambient[1]) / mt + ambient[1]; - float b = (rgb[2] - ambient[2]) / mt + ambient[2]; - - img->r(y, x) = r; - img->g(y, x) = g; - img->b(y, x) = b; + STVFU(img->r(y, x), ((r - ambient0v) / mtv + ambient0v) * cmaxChannelv); + STVFU(img->g(y, x), ((g - ambient1v) / mtv + ambient1v) * cmaxChannelv); + STVFU(img->b(y, x), ((b - ambient2v) / mtv + ambient2v) * cmaxChannelv); + } + } +#endif + for (; x < W; ++x) { + // ensure that the transmission is such that to avoid clipping... + const float r = img->r(y, x); + const float g = img->g(y, x); + const float b = img->b(y, x); + // ... t >= tl to avoid negative values + const float tl = 1.f - min(r / ambient[0], g / ambient[1], b / ambient[2]); + const float mt = max(dark[y][x], t0, tl + teps); + if (params->dehaze.showDepthMap) { + img->r(y, x) = img->g(y, x) = img->b(y, x) = LIM01(1.f - mt) * maxChannel; + } else if (luminance) { + const float Y = Color::rgbLuminance(img->r(y, x), img->g(y, x), img->b(y, x), ws); + const float YY = (Y - ambientY) / mt + ambientY; + const float f = Y > 1e-5f ? maxChannel * YY / Y : maxChannel; + img->r(y, x) *= f; + img->g(y, x) *= f; + img->b(y, x) *= f; + } else { + img->r(y, x) = ((r - ambient[0]) / mt + ambient[0]) * maxChannel; + img->g(y, x) = ((g - ambient[1]) / mt + ambient[1]) * maxChannel; + img->b(y, x) = ((b - ambient[2]) / mt + ambient[2]) * maxChannel; } } } - - img->normalizeFloatTo65535(); } diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index 8790f003c..14aeb4049 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "rtengine.h" #include "improcfun.h" @@ -356,24 +356,19 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, { const TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile); - double dx = Color::D50x; - double dz = Color::D50z; - { - dx = dz = 1.0; - } const float toxyz[3][3] = { { - static_cast(wprof[0][0] / (dx * (normalizeIn ? 65535.0 : 1.0))), //I have suppressed / Color::D50x - static_cast(wprof[0][1] / (dx * (normalizeIn ? 65535.0 : 1.0))), - static_cast(wprof[0][2] / (dx * (normalizeIn ? 65535.0 : 1.0))) + static_cast(wprof[0][0] / ((normalizeIn ? 65535.0 : 1.0))), //I have suppressed / Color::D50x + static_cast(wprof[0][1] / ((normalizeIn ? 65535.0 : 1.0))), + static_cast(wprof[0][2] / ((normalizeIn ? 65535.0 : 1.0))) }, { static_cast(wprof[1][0] / (normalizeIn ? 65535.0 : 1.0)), static_cast(wprof[1][1] / (normalizeIn ? 65535.0 : 1.0)), static_cast(wprof[1][2] / (normalizeIn ? 65535.0 : 1.0)) }, { - static_cast(wprof[2][0] / (dz * (normalizeIn ? 65535.0 : 1.0))), //I have suppressed / Color::D50z - static_cast(wprof[2][1] / (dz * (normalizeIn ? 65535.0 : 1.0))), - static_cast(wprof[2][2] / (dz * (normalizeIn ? 65535.0 : 1.0))) + static_cast(wprof[2][0] / ((normalizeIn ? 65535.0 : 1.0))), //I have suppressed / Color::D50z + static_cast(wprof[2][1] / ((normalizeIn ? 65535.0 : 1.0))), + static_cast(wprof[2][2] / ((normalizeIn ? 65535.0 : 1.0))) } }; diff --git a/rtengine/iplabregions.cc b/rtengine/iplabregions.cc index 5945398d2..af6567c3c 100644 --- a/rtengine/iplabregions.cc +++ b/rtengine/iplabregions.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifdef _OPENMP diff --git a/rtengine/iplocalcontrast.cc b/rtengine/iplocalcontrast.cc index 1bf21829e..6143f48a3 100644 --- a/rtengine/iplocalcontrast.cc +++ b/rtengine/iplocalcontrast.cc @@ -19,7 +19,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifdef _OPENMP diff --git a/rtengine/ipresize.cc b/rtengine/ipresize.cc index 823beb23e..0c1fb1ad8 100644 --- a/rtengine/ipresize.cc +++ b/rtengine/ipresize.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "improcfun.h" @@ -186,8 +186,8 @@ void ImProcFunctions::Lanczos (const Imagefloat* src, Imagefloat* dst, float sca void ImProcFunctions::Lanczos (const LabImage* src, LabImage* dst, float scale) { const float delta = 1.0f / scale; - const float a = 3.0f; - const float sc = min (scale, 1.0f); + constexpr float a = 3.0f; + const float sc = min(scale, 1.0f); const int support = static_cast (2.0f * a / sc) + 1; // storage for precomputed parameters for horizontal interpolation @@ -268,66 +268,61 @@ void ImProcFunctions::Lanczos (const LabImage* src, LabImage* dst, float scale) } // Do vertical interpolation. Store results. + int j = 0; #ifdef __SSE2__ - int j; __m128 Lv, av, bv, wkv; for (j = 0; j < src->W - 3; j += 4) { - Lv = _mm_setzero_ps(); - av = _mm_setzero_ps(); - bv = _mm_setzero_ps(); + Lv = ZEROV; + av = ZEROV; + bv = ZEROV; for (int ii = ii0; ii < ii1; ii++) { int k = ii - ii0; - wkv = _mm_set1_ps (w[k]); - Lv += wkv * LVFU (src->L[ii][j]); - av += wkv * LVFU (src->a[ii][j]); - bv += wkv * LVFU (src->b[ii][j]); + wkv = F2V(w[k]); + Lv += wkv * LVFU(src->L[ii][j]); + av += wkv * LVFU(src->a[ii][j]); + bv += wkv * LVFU(src->b[ii][j]); } - STVF (lL[j], Lv); - STVF (la[j], av); - STVF (lb[j], bv); + STVF(lL[j], Lv); + STVF(la[j], av); + STVF(lb[j], bv); } - -#else - int j = 0; #endif - for (; j < src->W; j++) { - float L = 0.0f, a = 0.0f, b = 0.0f; + for (; j < src->W; ++j) { + float Ll = 0.0f, La = 0.0f, Lb = 0.0f; - for (int ii = ii0; ii < ii1; ii++) { + for (int ii = ii0; ii < ii1; ++ii) { int k = ii - ii0; - L += w[k] * src->L[ii][j]; - a += w[k] * src->a[ii][j]; - b += w[k] * src->b[ii][j]; + Ll += w[k] * src->L[ii][j]; + La += w[k] * src->a[ii][j]; + Lb += w[k] * src->b[ii][j]; } - lL[j] = L; - la[j] = a; - lb[j] = b; + lL[j] = Ll; + la[j] = La; + lb[j] = Lb; } // Do horizontal interpolation - for (int j = 0; j < dst->W; j++) { + for (int x = 0; x < dst->W; ++x) { + float * wh = wwh + support * x; + float Ll = 0.0f, La = 0.0f, Lb = 0.0f; - float * wh = wwh + support * j; + for (int jj = jj0[x]; jj < jj1[x]; ++jj) { + int k = jj - jj0[x]; - float L = 0.0f, a = 0.0f, b = 0.0f; - - for (int jj = jj0[j]; jj < jj1[j]; jj++) { - int k = jj - jj0[j]; - - L += wh[k] * lL[jj]; - a += wh[k] * la[jj]; - b += wh[k] * lb[jj]; + Ll += wh[k] * lL[jj]; + La += wh[k] * la[jj]; + Lb += wh[k] * lb[jj]; } - dst->L[i][j] = L; - dst->a[i][j] = a; - dst->b[i][j] = b; + dst->L[i][x] = Ll; + dst->a[i][x] = La; + dst->b[i][x] = Lb; } } } diff --git a/rtengine/ipretinex.cc b/rtengine/ipretinex.cc index 309c7073b..7117c9f2a 100644 --- a/rtengine/ipretinex.cc +++ b/rtengine/ipretinex.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with RawTherapee. If not, see . +* along with RawTherapee. If not, see . * adaptation to RawTherapee * 2015 Jacques Desmis diff --git a/rtengine/ipshadowshighlights.cc b/rtengine/ipshadowshighlights.cc index 6ce66d9b3..cddc8734b 100644 --- a/rtengine/ipshadowshighlights.cc +++ b/rtengine/ipshadowshighlights.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "improcfun.h" @@ -106,10 +106,10 @@ void ImProcFunctions::shadowsHighlights(LabImage *lab) #pragma omp parallel for if (multiThread) #endif for (int l = 0; l < 32768; ++l) { - auto base = pow_F(l / 32768.f, gamma); + auto val = pow_F(l / 32768.f, gamma); // get a bit more contrast in the shadows - base = sh_contrast.getVal(base); - f[l] = base * 32768.f; + val = sh_contrast.getVal(val); + f[l] = val * 32768.f; } } else { #ifdef _OPENMP @@ -119,10 +119,10 @@ void ImProcFunctions::shadowsHighlights(LabImage *lab) float l, a, b; float R = c, G = c, B = c; rgb2lab(R, G, B, l, a, b); - auto base = pow_F(l / 32768.f, gamma); + auto val = pow_F(l / 32768.f, gamma); // get a bit more contrast in the shadows - base = sh_contrast.getVal(base); - l = base * 32768.f; + val = sh_contrast.getVal(val); + l = val * 32768.f; lab2rgb(l, a, b, R, G, B); f[c] = G; } @@ -133,8 +133,8 @@ void ImProcFunctions::shadowsHighlights(LabImage *lab) #pragma omp parallel for if (multiThread) #endif for (int l = 0; l < 32768; ++l) { - auto base = pow_F(l / 32768.f, gamma); - f[l] = base * 32768.f; + auto val = pow_F(l / 32768.f, gamma); + f[l] = val * 32768.f; } } else { #ifdef _OPENMP @@ -144,8 +144,8 @@ void ImProcFunctions::shadowsHighlights(LabImage *lab) float l, a, b; float R = c, G = c, B = c; rgb2lab(R, G, B, l, a, b); - auto base = pow_F(l / 32768.f, gamma); - l = base * 32768.f; + auto val = pow_F(l / 32768.f, gamma); + l = val * 32768.f; lab2rgb(l, a, b, R, G, B); f[c] = G; } diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index 9d7358fa9..bbd1de155 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "improcfun.h" @@ -158,7 +158,7 @@ namespace rtengine extern const Settings* settings; -void ImProcFunctions::deconvsharpening (float** luminance, float** tmp, int W, int H, const SharpeningParams &sharpenParam) +void ImProcFunctions::deconvsharpening (float** luminance, float** tmp, const float * const * blend, int W, int H, const SharpeningParams &sharpenParam, double Scale) { if (sharpenParam.deconvamount == 0 && sharpenParam.blurradius < 0.25f) { return; @@ -175,10 +175,6 @@ BENCHFUN } } - // calculate contrast based blend factors to reduce sharpening in regions with low contrast - JaggedArray blend(W, H); - float contrast = sharpenParam.contrast / 100.f; - buildBlendMask(luminance, blend, W, H, contrast, 1.f); JaggedArray* blurbuffer = nullptr; if (sharpenParam.blurradius >= 0.25f) { @@ -201,7 +197,7 @@ BENCHFUN } const float damping = sharpenParam.deconvdamping / 5.0; const bool needdamp = sharpenParam.deconvdamping > 0; - const double sigma = sharpenParam.deconvradius / scale; + const double sigma = sharpenParam.deconvradius / Scale; const float amount = sharpenParam.deconvamount / 100.f; #ifdef _OPENMP @@ -254,11 +250,12 @@ void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpen int W = lab->W, H = lab->H; + // calculate contrast based blend factors to reduce sharpening in regions with low contrast + JaggedArray blend(W, H); + float contrast = sharpenParam.contrast / 100.f; + buildBlendMask(lab->L, blend, W, H, contrast, 1.f); + if(showMask) { - // calculate contrast based blend factors to reduce sharpening in regions with low contrast - JaggedArray blend(W, H); - float contrast = sharpenParam.contrast / 100.f; - buildBlendMask(lab->L, blend, W, H, contrast, 1.f); #ifdef _OPENMP #pragma omp parallel for #endif @@ -274,7 +271,7 @@ void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpen JaggedArray b2(W, H); if (sharpenParam.method == "rld") { - deconvsharpening (lab->L, b2, lab->W, lab->H, sharpenParam); + deconvsharpening (lab->L, b2, blend, lab->W, lab->H, sharpenParam, scale); return; } BENCHFUN @@ -290,11 +287,6 @@ BENCHFUN } } - // calculate contrast based blend factors to reduce sharpening in regions with low contrast - JaggedArray blend(W, H); - float contrast = sharpenParam.contrast / 100.f; - buildBlendMask(lab->L, blend, W, H, contrast); - JaggedArray blur(W, H); if (sharpenParam.blurradius >= 0.25f) { @@ -886,11 +878,11 @@ void ImProcFunctions::sharpeningcam (CieImage* ncie, float** b2, bool showMask) int W = ncie->W, H = ncie->H; + // calculate contrast based blend factors to reduce sharpening in regions with low contrast + JaggedArray blend(W, H); + float contrast = params->sharpening.contrast / 100.f; + buildBlendMask(ncie->sh_p, blend, W, H, contrast); if(showMask) { - // calculate contrast based blend factors to reduce sharpening in regions with low contrast - JaggedArray blend(W, H); - float contrast = params->sharpening.contrast / 100.f; - buildBlendMask(ncie->sh_p, blend, W, H, contrast); #ifdef _OPENMP #pragma omp parallel for #endif @@ -903,9 +895,8 @@ void ImProcFunctions::sharpeningcam (CieImage* ncie, float** b2, bool showMask) return; } - if (params->sharpening.method == "rld") { - deconvsharpening (ncie->sh_p, b2, ncie->W, ncie->H, params->sharpening); + deconvsharpening (ncie->sh_p, b2, blend, ncie->W, ncie->H, params->sharpening, scale); return; } @@ -921,11 +912,6 @@ void ImProcFunctions::sharpeningcam (CieImage* ncie, float** b2, bool showMask) } } - // calculate contrast based blend factors to reduce sharpening in regions with low contrast - JaggedArray blend(W, H); - float contrast = params->sharpening.contrast / 100.f; - buildBlendMask(ncie->sh_p, blend, W, H, contrast); - #ifdef _OPENMP #pragma omp parallel #endif diff --git a/rtengine/ipsoftlight.cc b/rtengine/ipsoftlight.cc index 6aca9b8eb..cd49e858f 100644 --- a/rtengine/ipsoftlight.cc +++ b/rtengine/ipsoftlight.cc @@ -3,6 +3,7 @@ * This file is part of RawTherapee. * * Copyright 2018 Alberto Griggio + * Optimized 2019 Ingo Weyrich * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,62 +16,116 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ -#ifdef _OPENMP -#include -#endif - #include "improcfun.h" #include "procparams.h" -namespace rtengine { - namespace { inline float sl(float blend, float x) { - if (!OOG(x)) { - const float orig = 1.f - blend; - float v = Color::gamma_srgb(x) / MAXVALF; - // Pegtop's formula from + if (!rtengine::OOG(x)) { + float v = rtengine::Color::gamma_srgb(x) / rtengine::MAXVALF; + // using Pegtop's formula from // https://en.wikipedia.org/wiki/Blend_modes#Soft_Light - float v2 = v * v; - float v22 = v2 * 2.f; - v = v2 + v22 - v22 * v; - x = blend * Color::igamma_srgb(v * MAXVALF) + orig * x; + // const float orig = 1.f - blend; + // float v2 = v * v; + // float v22 = v2 * 2.f; + // v = v2 + v22 - v22 * v; + // return blend * Color::igamma_srgb(v * MAXVALF) + orig * x; + + // using optimized formula (heckflosse67@gmx.de) + return rtengine::intp(blend, rtengine::Color::igamma_srgb(v * v * (3.f - 2.f * v) * rtengine::MAXVALF), x); } return x; } +#ifdef __SSE2__ +inline vfloat sl(vfloat blend, vfloat x) +{ + const vfloat v = rtengine::Color::gammatab_srgb[x] / F2V(rtengine::MAXVALF); + return vself(vmaskf_gt(x, F2V(rtengine::MAXVALF)), x, vself(vmaskf_lt(x, ZEROV), x, vintpf(blend, rtengine::Color::igammatab_srgb[v * v * (F2V(3.f) - (v + v)) * rtengine::MAXVALF], x))); +} +#endif + } // namespace - -void ImProcFunctions::softLight(LabImage *lab) +void rtengine::ImProcFunctions::softLight(LabImage *lab) { if (!params->softlight.enabled || !params->softlight.strength) { return; } - Imagefloat working(lab->W, lab->H); - lab2rgb(*lab, working, params->icm.workingProfile); + const TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile); + const float wp[3][3] = { + {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])}, + {static_cast(wprof[1][0]), static_cast(wprof[1][1]), static_cast(wprof[1][2])}, + {static_cast(wprof[2][0]), static_cast(wprof[2][1]), static_cast(wprof[2][2])} + }; - const float blend = params->softlight.strength / 100.f; + const TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix(params->icm.workingProfile); + const float wip[3][3] = { + {static_cast(wiprof[0][0]), static_cast(wiprof[0][1]), static_cast(wiprof[0][2])}, + {static_cast(wiprof[1][0]), static_cast(wiprof[1][1]), static_cast(wiprof[1][2])}, + {static_cast(wiprof[2][0]), static_cast(wiprof[2][1]), static_cast(wiprof[2][2])} + }; + +#ifdef __SSE2__ + const vfloat wpv[3][3] = { + {F2V(wprof[0][0]), F2V(wprof[0][1]), F2V(wprof[0][2])}, + {F2V(wprof[1][0]), F2V(wprof[1][1]), F2V(wprof[1][2])}, + {F2V(wprof[2][0]), F2V(wprof[2][1]), F2V(wprof[2][2])} + }; + + const vfloat wipv[3][3] = { + {F2V(wiprof[0][0]), F2V(wiprof[0][1]), F2V(wiprof[0][2])}, + {F2V(wiprof[1][0]), F2V(wiprof[1][1]), F2V(wiprof[1][2])}, + {F2V(wiprof[2][0]), F2V(wiprof[2][1]), F2V(wiprof[2][2])} + }; +#endif #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel #endif - for (int y = 0; y < working.getHeight(); ++y) { - for (int x = 0; x < working.getWidth(); ++x) { - working.r(y, x) = sl(blend, working.r(y, x)); - working.g(y, x) = sl(blend, working.g(y, x)); - working.b(y, x) = sl(blend, working.b(y, x)); + { + const float blend = params->softlight.strength / 100.f; +#ifdef __SSE2__ + const vfloat blendv = F2V(blend); +#endif +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) +#endif + for (int i = 0; i < lab->H; ++i) { + int j = 0; +#ifdef __SSE2__ + for (; j < lab->W - 3; j += 4) { + vfloat Xv, Yv, Zv; + vfloat Rv, Gv, Bv; + Color::Lab2XYZ(LVFU(lab->L[i][j]),LVFU (lab->a[i][j]),LVFU (lab->b[i][j]), Xv, Yv, Zv); + Color::xyz2rgb(Xv, Yv, Zv, Rv, Gv, Bv, wipv); + Rv = sl(blendv, Rv); + Gv = sl(blendv, Gv); + Bv = sl(blendv, Bv); + Color::rgbxyz(Rv, Gv, Bv, Xv, Yv, Zv, wpv); + for (int k = 0; k < 4; ++k) { + Color::XYZ2Lab(Xv[k], Yv[k], Zv[k], lab->L[i][j + k], lab->a[i][j + k], lab->b[i][j+ k]); + } + } +#endif + for (; j < lab->W; j++) { + float X, Y, Z; + float R, G, B; + Color::Lab2XYZ(lab->L[i][j], lab->a[i][j], lab->b[i][j], X, Y, Z); + Color::xyz2rgb(X, Y, Z, R, G, B, wip); + R = sl(blend, R); + G = sl(blend, G); + B = sl(blend, B); + Color::rgbxyz(R, G, B, X, Y, Z, wp); + Color::XYZ2Lab(X, Y, Z, lab->L[i][j], lab->a[i][j], lab->b[i][j]); + } } } - - rgb2lab(working, *lab, params->icm.workingProfile); } - -} // namespace rtengine diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index beca624a8..99fd39f7e 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -14,19 +14,22 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ -#include "rtengine.h" -#include "improcfun.h" -#include "procparams.h" +#include + #ifdef _OPENMP #include #endif -#include "mytime.h" -#include "rt_math.h" -#include "sleef.c" -#include "rtlensfun.h" +#include "improcfun.h" + +#include "mytime.h" +#include "procparams.h" +#include "rt_math.h" +#include "rtengine.h" +#include "rtlensfun.h" +#include "sleef.c" using namespace std; @@ -87,6 +90,114 @@ float normn (float a, float b, int n) } } +#ifdef __SSE2__ +inline void interpolateTransformCubic(rtengine::Imagefloat* src, int xs, int ys, float Dx, float Dy, float &r, float &g, float &b, float mul) +{ + constexpr float A = -0.85f; + + // Vertical + const float t1Vert = A * (Dy - Dy * Dy); + const float t2Vert = (3.f - 2.f * Dy) * Dy * Dy; + const vfloat w3Vert = F2V(t1Vert * Dy); + const vfloat w2Vert = F2V(t1Vert * Dy - t1Vert + t2Vert); + const vfloat w1Vert = F2V(1.f - (t1Vert * Dy) - t2Vert); + const vfloat w0Vert = F2V(t1Vert - (t1Vert * Dy)); + + const vfloat rv = (w0Vert * LVFU(src->r(ys, xs)) + w1Vert * LVFU(src->r(ys + 1, xs))) + (w2Vert * LVFU(src->r(ys + 2, xs)) + w3Vert * LVFU(src->r(ys + 3, xs))); + const vfloat gv = (w0Vert * LVFU(src->g(ys, xs)) + w1Vert * LVFU(src->g(ys + 1, xs))) + (w2Vert * LVFU(src->g(ys + 2, xs)) + w3Vert * LVFU(src->g(ys + 3, xs))); + const vfloat bv = (w0Vert * LVFU(src->b(ys, xs)) + w1Vert * LVFU(src->b(ys + 1, xs))) + (w2Vert * LVFU(src->b(ys + 2, xs)) + w3Vert * LVFU(src->b(ys + 3, xs))); + + // Horizontal + const float t1Hor = A * (Dx - Dx * Dx); + const float t2Hor = (3.f - 2.f * Dx) * Dx * Dx; + const vfloat weight = _mm_set_ps(t1Hor * Dx, t1Hor * Dx - t1Hor + t2Hor, 1.f - (t1Hor * Dx) - t2Hor, t1Hor - (t1Hor * Dx)) * F2V(mul); + r = vhadd(weight * rv); + g = vhadd(weight * gv); + b = vhadd(weight * bv); +} +#else +inline void interpolateTransformCubic(rtengine::Imagefloat* src, int xs, int ys, float Dx, float Dy, float &r, float &g, float &b, float mul) +{ + constexpr float A = -0.85f; + + // Vertical + const float t1Vert = A * (Dy - Dy * Dy); + const float t2Vert = (3.f - 2.f * Dy) * Dy * Dy; + const float w3Vert = t1Vert * Dy; + const float w2Vert = t1Vert * Dy - t1Vert + t2Vert; + const float w1Vert = 1.f - (t1Vert * Dy) - t2Vert; + const float w0Vert = t1Vert - (t1Vert * Dy); + + float rv[4], gv[4], bv[4]; + for (int i = 0; i < 4; ++i) { + rv[i] = w0Vert * src->r(ys, xs + i) + w1Vert * src->r(ys + 1, xs + i) + w2Vert * src->r(ys + 2, xs + i) + w3Vert * src->r(ys + 3, xs + i); + gv[i] = w0Vert * src->g(ys, xs + i) + w1Vert * src->g(ys + 1, xs + i) + w2Vert * src->g(ys + 2, xs + i) + w3Vert * src->g(ys + 3, xs + i); + bv[i] = w0Vert * src->b(ys, xs + i) + w1Vert * src->b(ys + 1, xs + i) + w2Vert * src->b(ys + 2, xs + i) + w3Vert * src->b(ys + 3, xs + i); + } + + // Horizontal + const float t1Hor = A * (Dx - Dx * Dx); + const float t2Hor = (3.f - 2.f * Dx) * Dx * Dx; + const float w3Hor = t1Hor * Dx; + const float w2Hor = t1Hor * Dx - t1Hor + t2Hor; + const float w1Hor = 1.f - (t1Hor * Dx) - t2Hor; + const float w0Hor = t1Hor - (t1Hor * Dx); + + r = mul * (rv[0] * w0Hor + rv[1] * w1Hor + rv[2] * w2Hor + rv[3] * w3Hor); + g = mul * (gv[0] * w0Hor + gv[1] * w1Hor + gv[2] * w2Hor + gv[3] * w3Hor); + b = mul * (bv[0] * w0Hor + bv[1] * w1Hor + bv[2] * w2Hor + bv[3] * w3Hor); +} +#endif +#ifdef __SSE2__ +inline void interpolateTransformChannelsCubic(const float* const* src, int xs, int ys, float Dx, float Dy, float& dest, float mul) +{ + constexpr float A = -0.85f; + + // Vertical + const float t1Vert = A * (Dy - Dy * Dy); + const float t2Vert = (3.f - 2.f * Dy) * Dy * Dy; + const vfloat w3Vert = F2V(t1Vert * Dy); + const vfloat w2Vert = F2V(t1Vert * Dy - t1Vert + t2Vert); + const vfloat w1Vert = F2V(1.f - (t1Vert * Dy) - t2Vert); + const vfloat w0Vert = F2V(t1Vert - (t1Vert * Dy)); + + const vfloat cv = (w0Vert * LVFU(src[ys][xs]) + w1Vert * LVFU(src[ys + 1][xs])) + (w2Vert * LVFU(src[ys + 2][xs]) + w3Vert * LVFU(src[ys + 3][xs])); + + // Horizontal + const float t1Hor = A * (Dx - Dx * Dx); + const float t2Hor = (3.f - 2.f * Dx) * Dx * Dx; + const vfloat weight = _mm_set_ps(t1Hor * Dx, t1Hor * Dx - t1Hor + t2Hor, 1.f - (t1Hor * Dx) - t2Hor, t1Hor - (t1Hor * Dx)); + dest = mul * vhadd(weight * cv); +} +#else +inline void interpolateTransformChannelsCubic(const float* const* src, int xs, int ys, float Dx, float Dy, float& dest, float mul) +{ + constexpr float A = -0.85f; + + // Vertical + const float t1Vert = A * (Dy - Dy * Dy); + const float t2Vert = (3.f - 2.f * Dy) * Dy * Dy; + const float w3Vert = t1Vert * Dy; + const float w2Vert = t1Vert * Dy - t1Vert + t2Vert; + const float w1Vert = 1.f - (t1Vert * Dy) - t2Vert; + const float w0Vert = t1Vert - (t1Vert * Dy); + + float cv[4]; + for (int i = 0; i < 4; ++i) { + cv[i] = w0Vert * src[ys][xs + i] + w1Vert * src[ys + 1][xs + i] + w2Vert * src[ys + 2][xs + i] + w3Vert * src[ys + 3][xs + i]; + } + + // Horizontal + const float t1Hor = A * (Dx - Dx * Dx); + const float t2Hor = (3.f - 2.f * Dx) * Dx * Dx; + const float w3Hor = t1Hor * Dx; + const float w2Hor = t1Hor * Dx - t1Hor + t2Hor; + const float w1Hor = 1.f - (t1Hor * Dx) - t2Hor; + const float w0Hor = t1Hor - (t1Hor * Dx); + + dest = mul * (cv[0] * w0Hor + cv[1] * w1Hor + cv[2] * w2Hor + cv[3] * w3Hor); +} +#endif } @@ -435,12 +546,7 @@ static void calcGradientParams (int oW, int oH, const GradientParams& gradient, if (gp.transpose) { gp.bright_top = !gp.bright_top; - } - - if (gp.transpose) { - int tmp = w; - w = h; - h = tmp; + std::swap(w, h); } gp.scale = 1.0 / pow (2, gradient_stops); @@ -746,87 +852,92 @@ void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat* void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap) { // set up stuff, depending on the mode we are - bool enableLCPDist = pLCPMap && params->lensProf.useDist; - bool enableCA = highQuality && needsCA(); - bool enableGradient = needsGradient(); - bool enablePCVignetting = needsPCVignetting(); - bool enableVignetting = needsVignetting(); - bool enablePerspective = needsPerspective(); - bool enableDistortion = needsDistortion(); + const bool enableLCPDist = pLCPMap && params->lensProf.useDist; + const bool enableCA = highQuality && needsCA(); + const bool enableGradient = needsGradient(); + const bool enablePCVignetting = needsPCVignetting(); + const bool enableVignetting = needsVignetting(); + const bool enablePerspective = needsPerspective(); + const bool enableDistortion = needsDistortion(); - double w2 = (double) oW / 2.0 - 0.5; - double h2 = (double) oH / 2.0 - 0.5; + const double w2 = static_cast(oW) / 2.0 - 0.5; + const double h2 = static_cast(oH) / 2.0 - 0.5; double vig_w2, vig_h2, maxRadius, v, b, mul; - calcVignettingParams (oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul); + calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul); - struct grad_params gp; + grad_params gp; if (enableGradient) { - calcGradientParams (oW, oH, params->gradient, gp); + calcGradientParams(oW, oH, params->gradient, gp); } - struct pcv_params pcv; + pcv_params pcv; if (enablePCVignetting) { - calcPCVignetteParams (fW, fH, oW, oH, params->pcvignette, params->crop, pcv); + calcPCVignetteParams(fW, fH, oW, oH, params->pcvignette, params->crop, pcv); } - float** chOrig[3]; - chOrig[0] = original->r.ptrs; - chOrig[1] = original->g.ptrs; - chOrig[2] = original->b.ptrs; - - float** chTrans[3]; - chTrans[0] = transformed->r.ptrs; - chTrans[1] = transformed->g.ptrs; - chTrans[2] = transformed->b.ptrs; + const std::array chOrig = { + original->r.ptrs, + original->g.ptrs, + original->b.ptrs + }; + const std::array chTrans = { + transformed->r.ptrs, + transformed->g.ptrs, + transformed->b.ptrs + }; // auxiliary variables for c/a correction - double chDist[3]; - chDist[0] = enableCA ? params->cacorrection.red : 0.0; - chDist[1] = 0.0; - chDist[2] = enableCA ? params->cacorrection.blue : 0.0; + const std::array chDist = { + enableCA + ? params->cacorrection.red + : 0.0, + 0.0, + enableCA + ? params->cacorrection.blue + : 0.0 + }; // auxiliary variables for distortion correction - double distAmount = params->distortion.amount; + const double distAmount = params->distortion.amount; // auxiliary variables for rotation - double cost = cos (params->rotate.degree * rtengine::RT_PI / 180.0); - double sint = sin (params->rotate.degree * rtengine::RT_PI / 180.0); + const double cost = cos(params->rotate.degree * rtengine::RT_PI / 180.0); + const double sint = sin(params->rotate.degree * rtengine::RT_PI / 180.0); // auxiliary variables for vertical perspective correction - double vpdeg = params->perspective.vertical / 100.0 * 45.0; - double vpalpha = (90.0 - vpdeg) / 180.0 * rtengine::RT_PI; - double vpteta = fabs (vpalpha - rtengine::RT_PI / 2) < 3e-4 ? 0.0 : acos ((vpdeg > 0 ? 1.0 : -1.0) * sqrt ((-SQR (oW * tan (vpalpha)) + (vpdeg > 0 ? 1.0 : -1.0) * - oW * tan (vpalpha) * sqrt (SQR (4 * maxRadius) + SQR (oW * tan (vpalpha)))) / (SQR (maxRadius) * 8))); - double vpcospt = (vpdeg >= 0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); + const double vpdeg = params->perspective.vertical / 100.0 * 45.0; + const double vpalpha = (90.0 - vpdeg) / 180.0 * rtengine::RT_PI; + const double vpteta = fabs(vpalpha - rtengine::RT_PI / 2) < 3e-4 ? 0.0 : acos((vpdeg > 0 ? 1.0 : -1.0) * sqrt((-SQR(oW * tan(vpalpha)) + (vpdeg > 0 ? 1.0 : -1.0) * + oW * tan(vpalpha) * sqrt(SQR(4 * maxRadius) + SQR(oW * tan(vpalpha)))) / (SQR(maxRadius) * 8))); + const double vpcospt = (vpdeg >= 0 ? 1.0 : -1.0) * cos(vpteta); + const double vptanpt = tan(vpteta); // auxiliary variables for horizontal perspective correction - double hpdeg = params->perspective.horizontal / 100.0 * 45.0; - double hpalpha = (90.0 - hpdeg) / 180.0 * rtengine::RT_PI; - double hpteta = fabs (hpalpha - rtengine::RT_PI / 2) < 3e-4 ? 0.0 : acos ((hpdeg > 0 ? 1.0 : -1.0) * sqrt ((-SQR (oH * tan (hpalpha)) + (hpdeg > 0 ? 1.0 : -1.0) * - oH * tan (hpalpha) * sqrt (SQR (4 * maxRadius) + SQR (oH * tan (hpalpha)))) / (SQR (maxRadius) * 8))); - double hpcospt = (hpdeg >= 0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); + const double hpdeg = params->perspective.horizontal / 100.0 * 45.0; + const double hpalpha = (90.0 - hpdeg) / 180.0 * rtengine::RT_PI; + const double hpteta = fabs(hpalpha - rtengine::RT_PI / 2) < 3e-4 ? 0.0 : acos((hpdeg > 0 ? 1.0 : -1.0) * sqrt((-SQR(oH * tan(hpalpha)) + (hpdeg > 0 ? 1.0 : -1.0) * + oH * tan(hpalpha) * sqrt(SQR(4 * maxRadius) + SQR(oH * tan(hpalpha)))) / (SQR(maxRadius) * 8))); + const double hpcospt = (hpdeg >= 0 ? 1.0 : -1.0) * cos(hpteta); + const double hptanpt = tan(hpteta); - double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0; + const double ascale = params->commonTrans.autofill ? getTransformAutoFill(oW, oH, pLCPMap) : 1.0; + + const bool darkening = (params->vignetting.amount <= 0.0); + const double centerFactorx = cx - w2; + const double centerFactory = cy - h2; -#if defined( __GNUC__ ) && __GNUC__ >= 7// silence warning -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" -#endif -#if defined( __GNUC__ ) && __GNUC__ >= 7 -#pragma GCC diagnostic pop -#endif // main cycle - bool darkening = (params->vignetting.amount <= 0.0); #ifdef _OPENMP - #pragma omp parallel for if (multiThread) + #pragma omp parallel for schedule(dynamic, 16) if(multiThread) #endif - for (int y = 0; y < transformed->getHeight(); y++) { - for (int x = 0; x < transformed->getWidth(); x++) { - double x_d = x, y_d = y; + for (int y = 0; y < transformed->getHeight(); ++y) { + for (int x = 0; x < transformed->getWidth(); ++x) { + double x_d = x; + double y_d = y; if (enableLCPDist) { pLCPMap->correctDistortion(x_d, y_d, cx, cy, ascale); // must be first transform @@ -835,15 +946,8 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I y_d *= ascale; } - x_d += ascale * (cx - w2); // centering x coord & scale - y_d += ascale * (cy - h2); // centering y coord & scale - - double vig_x_d = 0., vig_y_d = 0.; - - if (enableVignetting) { - vig_x_d = ascale * (x + cx - vig_w2); // centering x coord & scale - vig_y_d = ascale * (y + cy - vig_h2); // centering y coord & scale - } + x_d += ascale * centerFactorx; // centering x coord & scale + y_d += ascale * centerFactory; // centering y coord & scale if (enablePerspective) { // horizontal perspective transformation @@ -856,26 +960,18 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I } // rotate - double Dxc = x_d * cost - y_d * sint; - double Dyc = x_d * sint + y_d * cost; + const double Dxc = x_d * cost - y_d * sint; + const double Dyc = x_d * sint + y_d * cost; // distortion correction - double s = 1; + double s = 1.0; if (enableDistortion) { - double r = sqrt (Dxc * Dxc + Dyc * Dyc) / maxRadius; // sqrt is slow - s = 1.0 - distAmount + distAmount * r ; + const double r = sqrt(Dxc * Dxc + Dyc * Dyc) / maxRadius; + s = 1.0 - distAmount + distAmount * r; } - double r2 = 0.; - - if (enableVignetting) { - double vig_Dx = vig_x_d * cost - vig_y_d * sint; - double vig_Dy = vig_x_d * sint + vig_y_d * cost; - r2 = sqrt (vig_Dx * vig_Dx + vig_Dy * vig_Dy); - } - - for (int c = 0; c < (enableCA ? 3 : 1); c++) { + for (int c = 0; c < (enableCA ? 3 : 1); ++c) { double Dx = Dxc * (s + chDist[c]); double Dy = Dyc * (s + chDist[c]); @@ -884,59 +980,63 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I Dy += h2; // Extract integer and fractions of source screen coordinates - int xc = (int)Dx; - Dx -= (double)xc; + int xc = Dx; + Dx -= xc; xc -= sx; - int yc = (int)Dy; - Dy -= (double)yc; + int yc = Dy; + Dy -= yc; yc -= sy; // Convert only valid pixels if (yc >= 0 && yc < original->getHeight() && xc >= 0 && xc < original->getWidth()) { - // multiplier for vignetting correction double vignmul = 1.0; if (enableVignetting) { + const double vig_x_d = ascale * (x + cx - vig_w2); // centering x coord & scale + const double vig_y_d = ascale * (y + cy - vig_h2); // centering y coord & scale + const double vig_Dx = vig_x_d * cost - vig_y_d * sint; + const double vig_Dy = vig_x_d * sint + vig_y_d * cost; + const double r2 = sqrt(vig_Dx * vig_Dx + vig_Dy * vig_Dy); if (darkening) { - vignmul /= std::max (v + mul * tanh (b * (maxRadius - s * r2) / maxRadius), 0.001); + vignmul /= std::max(v + mul * tanh(b * (maxRadius - s * r2) / maxRadius), 0.001); } else { - vignmul *= (v + mul * tanh (b * (maxRadius - s * r2) / maxRadius)); + vignmul *= (v + mul * tanh(b * (maxRadius - s * r2) / maxRadius)); } } if (enableGradient) { - vignmul *= calcGradientFactor (gp, cx + x, cy + y); + vignmul *= calcGradientFactor(gp, cx + x, cy + y); } if (enablePCVignetting) { - vignmul *= calcPCVignetteFactor (pcv, cx + x, cy + y); + vignmul *= calcPCVignetteFactor(pcv, cx + x, cy + y); } if (yc > 0 && yc < original->getHeight() - 2 && xc > 0 && xc < original->getWidth() - 2) { // all interpolation pixels inside image if (enableCA) { - interpolateTransformChannelsCubic (chOrig[c], xc - 1, yc - 1, Dx, Dy, & (chTrans[c][y][x]), vignmul); + interpolateTransformChannelsCubic(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], vignmul); } else if (!highQuality) { - transformed->r (y, x) = vignmul * (original->r (yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->r (yc, xc + 1) * Dx * (1.0 - Dy) + original->r (yc + 1, xc) * (1.0 - Dx) * Dy + original->r (yc + 1, xc + 1) * Dx * Dy); - transformed->g (y, x) = vignmul * (original->g (yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g (yc, xc + 1) * Dx * (1.0 - Dy) + original->g (yc + 1, xc) * (1.0 - Dx) * Dy + original->g (yc + 1, xc + 1) * Dx * Dy); - transformed->b (y, x) = vignmul * (original->b (yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b (yc, xc + 1) * Dx * (1.0 - Dy) + original->b (yc + 1, xc) * (1.0 - Dx) * Dy + original->b (yc + 1, xc + 1) * Dx * Dy); + transformed->r(y, x) = vignmul * (original->r(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->r(yc, xc + 1) * Dx * (1.0 - Dy) + original->r(yc + 1, xc) * (1.0 - Dx) * Dy + original->r(yc + 1, xc + 1) * Dx * Dy); + transformed->g(y, x) = vignmul * (original->g(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g(yc, xc + 1) * Dx * (1.0 - Dy) + original->g(yc + 1, xc) * (1.0 - Dx) * Dy + original->g(yc + 1, xc + 1) * Dx * Dy); + transformed->b(y, x) = vignmul * (original->b(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b(yc, xc + 1) * Dx * (1.0 - Dy) + original->b(yc + 1, xc) * (1.0 - Dx) * Dy + original->b(yc + 1, xc + 1) * Dx * Dy); } else { - interpolateTransformCubic (original, xc - 1, yc - 1, Dx, Dy, & (transformed->r (y, x)), & (transformed->g (y, x)), & (transformed->b (y, x)), vignmul); + interpolateTransformCubic(original, xc - 1, yc - 1, Dx, Dy, transformed->r(y, x), transformed->g(y, x), transformed->b(y, x), vignmul); } } else { // edge pixels - int y1 = LIM (yc, 0, original->getHeight() - 1); - int y2 = LIM (yc + 1, 0, original->getHeight() - 1); - int x1 = LIM (xc, 0, original->getWidth() - 1); - int x2 = LIM (xc + 1, 0, original->getWidth() - 1); + const int y1 = LIM(yc, 0, original->getHeight() - 1); + const int y2 = LIM(yc + 1, 0, original->getHeight() - 1); + const int x1 = LIM(xc, 0, original->getWidth() - 1); + const int x2 = LIM(xc + 1, 0, original->getWidth() - 1); if (enableCA) { chTrans[c][y][x] = vignmul * (chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); } else { - transformed->r (y, x) = vignmul * (original->r (y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->r (y1, x2) * Dx * (1.0 - Dy) + original->r (y2, x1) * (1.0 - Dx) * Dy + original->r (y2, x2) * Dx * Dy); - transformed->g (y, x) = vignmul * (original->g (y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->g (y1, x2) * Dx * (1.0 - Dy) + original->g (y2, x1) * (1.0 - Dx) * Dy + original->g (y2, x2) * Dx * Dy); - transformed->b (y, x) = vignmul * (original->b (y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->b (y1, x2) * Dx * (1.0 - Dy) + original->b (y2, x1) * (1.0 - Dx) * Dy + original->b (y2, x2) * Dx * Dy); + transformed->r(y, x) = vignmul * (original->r(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->r(y1, x2) * Dx * (1.0 - Dy) + original->r(y2, x1) * (1.0 - Dx) * Dy + original->r(y2, x2) * Dx * Dy); + transformed->g(y, x) = vignmul * (original->g(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->g(y1, x2) * Dx * (1.0 - Dy) + original->g(y2, x1) * (1.0 - Dx) * Dy + original->g(y2, x2) * Dx * Dy); + transformed->b(y, x) = vignmul * (original->b(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->b(y1, x2) * Dx * (1.0 - Dy) + original->b(y2, x1) * (1.0 - Dx) * Dy + original->b(y2, x2) * Dx * Dy); } } } else { @@ -944,9 +1044,9 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I // not valid (source pixel x,y not inside source image, etc.) chTrans[c][y][x] = 0; } else { - transformed->r (y, x) = 0; - transformed->g (y, x) = 0; - transformed->b (y, x) = 0; + transformed->r(y, x) = 0; + transformed->g(y, x) = 0; + transformed->b(y, x) = 0; } } } @@ -993,7 +1093,7 @@ void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *trans // multiplier for vignetting correction if (yc > 0 && yc < original->getHeight() - 2 && xc > 0 && xc < original->getWidth() - 2) { // all interpolation pixels inside image - interpolateTransformChannelsCubic (chOrig[c], xc - 1, yc - 1, Dx, Dy, & (chTrans[c][y][x]), 1.0); + interpolateTransformChannelsCubic (chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], 1.0); } else { // edge pixels int y1 = LIM (yc, 0, original->getHeight() - 1); diff --git a/rtengine/ipvibrance.cc b/rtengine/ipvibrance.cc index ca938fbbe..a7199064a 100644 --- a/rtengine/ipvibrance.cc +++ b/rtengine/ipvibrance.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "rt_math.h" diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index ff7aefa19..07e9da85b 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -16,7 +16,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // * 2014 Jacques Desmis // * 2014 Ingo Weyrich diff --git a/rtengine/jaggedarray.h b/rtengine/jaggedarray.h index 01da776a6..59c1485d8 100644 --- a/rtengine/jaggedarray.h +++ b/rtengine/jaggedarray.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtengine/labimage.cc b/rtengine/labimage.cc index 81b1a4303..b31bc89a1 100644 --- a/rtengine/labimage.cc +++ b/rtengine/labimage.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtengine/labimage.h b/rtengine/labimage.h index 28bb891a9..bcc2484ab 100644 --- a/rtengine/labimage.h +++ b/rtengine/labimage.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _LABIMAGE_H_ #define _LABIMAGE_H_ diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index 7156f17e2..b456fc478 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with RawTherapee. If not, see . +* along with RawTherapee. If not, see . */ #include @@ -234,8 +234,6 @@ rtengine::LCPProfile::LCPProfile(const Glib::ustring& fname) : pCurCommon(nullptr), aPersModel{} { - const int BufferSize = 8192; - char buf[BufferSize]; XML_Parser parser = XML_ParserCreate(nullptr); @@ -250,6 +248,8 @@ rtengine::LCPProfile::LCPProfile(const Glib::ustring& fname) : FILE* const pFile = g_fopen(fname.c_str (), "rb"); if (pFile) { + constexpr int BufferSize = 8192; + char buf[BufferSize]; bool done; do { @@ -362,9 +362,8 @@ void rtengine::LCPProfile::calcParams( const float focDist = aPersModel[pm]->focDist; const float focDistLog = std::log(focDist) + euler; - double meanErr = 0.0; - if (aPersModel[pm]->hasModeData(mode)) { + double meanErr = 0.0; double lowMeanErr = 0.0; double highMeanErr = 0.0; diff --git a/rtengine/lcp.h b/rtengine/lcp.h index 2d9707907..30b7e5191 100644 --- a/rtengine/lcp.h +++ b/rtengine/lcp.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with RawTherapee. If not, see . +* along with RawTherapee. If not, see . */ #pragma once diff --git a/rtengine/loadinitial.cc b/rtengine/loadinitial.cc index 6192ca6db..00dbbf836 100644 --- a/rtengine/loadinitial.cc +++ b/rtengine/loadinitial.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "rtengine.h" #include "stdimagesource.h" diff --git a/rtengine/median.h b/rtengine/median.h index 30adbacb3..acd92235c 100644 --- a/rtengine/median.h +++ b/rtengine/median.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * These median implementations from Flössie and Ingo Weyrich are inspired by this work: * diff --git a/rtengine/myfile.cc b/rtengine/myfile.cc index 28d187e4c..259e08565 100644 --- a/rtengine/myfile.cc +++ b/rtengine/myfile.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "myfile.h" #include diff --git a/rtengine/myfile.h b/rtengine/myfile.h index e4609c697..f2ed4150c 100644 --- a/rtengine/myfile.h +++ b/rtengine/myfile.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _MYFILE_ #define _MYFILE_ diff --git a/rtengine/mytime.h b/rtengine/mytime.h index f73d563d2..80fb0899a 100644 --- a/rtengine/mytime.h +++ b/rtengine/mytime.h @@ -14,10 +14,9 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ -#ifndef _MYTIME_ -#define _MYTIME_ +#pragma once #ifdef WIN32 #include @@ -58,11 +57,11 @@ public: t.tv_sec = tv.tv_sec; t.tv_nsec = tv.tv_usec * 1000; #else - clock_gettime (CLOCK_REALTIME, &t); + clock_gettime(CLOCK_REALTIME, &t); #endif } - int etime (MyTime a) + int etime (const MyTime &a) const { #ifndef WIN32 return (t.tv_sec - a.t.tv_sec) * 1000000 + (t.tv_nsec - a.t.tv_nsec) / 1000; @@ -71,6 +70,3 @@ public: #endif } }; - - -#endif diff --git a/rtengine/noncopyable.h b/rtengine/noncopyable.h index d34c42441..d915a6f78 100644 --- a/rtengine/noncopyable.h +++ b/rtengine/noncopyable.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtengine/opthelper.h b/rtengine/opthelper.h index ce1f620e1..b65ede227 100644 --- a/rtengine/opthelper.h +++ b/rtengine/opthelper.h @@ -15,7 +15,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// diff --git a/rtengine/pdaflinesfilter.cc b/rtengine/pdaflinesfilter.cc index 0c5b2d786..d0694fd11 100644 --- a/rtengine/pdaflinesfilter.cc +++ b/rtengine/pdaflinesfilter.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "pdaflinesfilter.h" diff --git a/rtengine/pdaflinesfilter.h b/rtengine/pdaflinesfilter.h index b1f7bf650..7f4c7985b 100644 --- a/rtengine/pdaflinesfilter.h +++ b/rtengine/pdaflinesfilter.h @@ -15,17 +15,19 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once -#include "rawimagesource.h" #include +#include "rawimagesource.h" +#include "noncopyable.h" namespace rtengine { -class PDAFLinesFilter { +class PDAFLinesFilter: public rtengine::NonCopyable +{ public: explicit PDAFLinesFilter(RawImage *ri); ~PDAFLinesFilter(); diff --git a/rtengine/pipettebuffer.cc b/rtengine/pipettebuffer.cc index 34a52a5c0..d915381ef 100644 --- a/rtengine/pipettebuffer.cc +++ b/rtengine/pipettebuffer.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "pipettebuffer.h" @@ -176,9 +176,11 @@ void PipetteBuffer::getPipetteData(int x, int y, const int squareSize) } } - dataProvider->setPipetteVal1(-1.f); - dataProvider->setPipetteVal2(-1.f); - dataProvider->setPipetteVal3(-1.f); + if (dataProvider) { + dataProvider->setPipetteVal1(-1.f); + dataProvider->setPipetteVal2(-1.f); + dataProvider->setPipetteVal3(-1.f); + } } } diff --git a/rtengine/pipettebuffer.h b/rtengine/pipettebuffer.h index ab9ba6197..01b24720c 100644 --- a/rtengine/pipettebuffer.h +++ b/rtengine/pipettebuffer.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc index b31ff62c9..4b93f3f61 100644 --- a/rtengine/pixelshift.cc +++ b/rtengine/pixelshift.cc @@ -16,7 +16,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// diff --git a/rtengine/pixelsmap.h b/rtengine/pixelsmap.h index b359d61d9..f747c52d9 100644 --- a/rtengine/pixelsmap.h +++ b/rtengine/pixelsmap.h @@ -16,7 +16,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtengine/previewimage.cc b/rtengine/previewimage.cc index 944e2e0ce..d2a7e201a 100644 --- a/rtengine/previewimage.cc +++ b/rtengine/previewimage.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "previewimage.h" diff --git a/rtengine/previewimage.h b/rtengine/previewimage.h index 26b9a85d2..71ddefe8a 100644 --- a/rtengine/previewimage.h +++ b/rtengine/previewimage.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PREVIEWIMAGE_ #define _PREVIEWIMAGE_ diff --git a/rtengine/processingjob.cc b/rtengine/processingjob.cc index a377e3963..2f9c15196 100644 --- a/rtengine/processingjob.cc +++ b/rtengine/processingjob.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "processingjob.h" diff --git a/rtengine/processingjob.h b/rtengine/processingjob.h index b2a81e4c2..004eb006f 100644 --- a/rtengine/processingjob.h +++ b/rtengine/processingjob.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PROCESSINGJOB_ #define _PROCESSINGJOB_ diff --git a/rtengine/procevents.h b/rtengine/procevents.h index bb6a30038..ca098f216 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __PROCEVENT__ #define __PROCEVENT__ @@ -520,7 +520,8 @@ enum ProcEventCode { EvWBEnabled = 490, EvRGBEnabled = 491, EvLEnabled = 492, -// EvPixelShiftOneGreen = 493, can be reused + EvPdShrEnabled = 493, + EvPdShrMaskToggled = 494, NUMOFEVENTS diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 4b9f1adbd..679f5daca 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -39,11 +39,11 @@ namespace Glib::ustring expandRelativePath(const Glib::ustring &procparams_fname, const Glib::ustring &prefix, Glib::ustring embedded_fname) { - if (embedded_fname == "" || !Glib::path_is_absolute(procparams_fname)) { + if (embedded_fname.empty() || !Glib::path_is_absolute(procparams_fname)) { return embedded_fname; } - if (prefix != "") { + if (!prefix.empty()) { if (embedded_fname.length() < prefix.length() || embedded_fname.substr(0, prefix.length()) != prefix) { return embedded_fname; } @@ -61,11 +61,11 @@ Glib::ustring expandRelativePath(const Glib::ustring &procparams_fname, const Gl Glib::ustring relativePathIfInside(const Glib::ustring &procparams_fname, bool fnameAbsolute, Glib::ustring embedded_fname) { - if (fnameAbsolute || embedded_fname == "" || !Glib::path_is_absolute(procparams_fname)) { + if (fnameAbsolute || embedded_fname.empty() || !Glib::path_is_absolute(procparams_fname)) { return embedded_fname; } - Glib::ustring prefix = ""; + Glib::ustring prefix; if (embedded_fname.length() > 5 && embedded_fname.substr(0, 5) == "file:") { embedded_fname = embedded_fname.substr(5); @@ -358,6 +358,29 @@ ToneCurveParams::ToneCurveParams() : { } +bool ToneCurveParams::isPanningRelatedChange(const ToneCurveParams& other) const +{ + return ! + (autoexp == other.autoexp + && clip == other.clip + && hrenabled == other.hrenabled + && method == other.method + && expcomp == other.expcomp + && curve == other.curve + && curve2 == other.curve2 + && curveMode == other.curveMode + && curveMode2 == other.curveMode2 + && brightness == other.brightness + && black == other.black + && contrast == other.contrast + && saturation == other.saturation + && shcompr == other.shcompr + && hlcompr == other.hlcompr + && hlcomprthresh == other.hlcomprthresh + && histmatching == other.histmatching + && clampOOG == other.clampOOG); +} + bool ToneCurveParams::operator ==(const ToneCurveParams& other) const { return @@ -1107,7 +1130,9 @@ void ColorToningParams::getCurves(ColorGradientCurve& colorCurveLUT, OpacityCurv SharpeningParams::SharpeningParams() : enabled(false), contrast(20.0), + autoContrast(false), blurradius(0.2), + gamma(1.0), radius(0.5), amount(200), threshold(20, 80, 2000, 1200, false), @@ -1130,9 +1155,11 @@ bool SharpeningParams::operator ==(const SharpeningParams& other) const enabled == other.enabled && contrast == other.contrast && blurradius == other.blurradius + && gamma == other.gamma && radius == other.radius && amount == other.amount && threshold == other.threshold + && autoContrast == other.autoContrast && edgesonly == other.edgesonly && edges_radius == other.edges_radius && edges_tolerance == other.edges_tolerance @@ -1150,6 +1177,36 @@ bool SharpeningParams::operator !=(const SharpeningParams& other) const return !(*this == other); } +CaptureSharpeningParams::CaptureSharpeningParams() : + enabled(false), + autoContrast(true), + autoRadius(true), + contrast(10.0), + gamma(1.00), + deconvradius(0.75), + deconvradiusOffset(0.0), + deconviter(20) +{ +} + +bool CaptureSharpeningParams::operator ==(const CaptureSharpeningParams& other) const +{ + return + enabled == other.enabled + && contrast == other.contrast + && gamma == other.gamma + && autoContrast == other.autoContrast + && autoRadius == other.autoRadius + && deconvradius == other.deconvradius + && deconvradiusOffset == other.deconvradiusOffset + && deconviter == other.deconviter; +} + +bool CaptureSharpeningParams::operator !=(const CaptureSharpeningParams& other) const +{ + return !(*this == other); +} + SharpenEdgeParams::SharpenEdgeParams() : enabled(false), passes(2), @@ -1238,6 +1295,21 @@ WBParams::WBParams() : { } +bool WBParams::isPanningRelatedChange(const WBParams& other) const +{ + return ! + (enabled == other.enabled + && ((method == "Camera" && other.method == "Camera") + || + (method == other.method + && temperature == other.temperature + && green == other.green + && equal == other.equal + && tempBias == other.tempBias) + ) + ); +} + bool WBParams::operator ==(const WBParams& other) const { return @@ -2475,7 +2547,8 @@ DehazeParams::DehazeParams() : enabled(false), strength(50), showDepthMap(false), - depth(25) + depth(25), + luminance(false) { } @@ -2485,7 +2558,8 @@ bool DehazeParams::operator ==(const DehazeParams& other) const enabled == other.enabled && strength == other.strength && showDepthMap == other.showDepthMap - && depth == other.depth; + && depth == other.depth + && luminance == other.luminance; } bool DehazeParams::operator !=(const DehazeParams& other) const @@ -2762,6 +2836,27 @@ bool MetaDataParams::operator!=(const MetaDataParams &other) const return !(*this == other); } +FilmNegativeParams::FilmNegativeParams() : + enabled(false), + redRatio(1.36), + greenExp(1.5), + blueRatio(0.86) +{ +} + +bool FilmNegativeParams::operator ==(const FilmNegativeParams& other) const +{ + return + enabled == other.enabled + && redRatio == other.redRatio + && greenExp == other.greenExp + && blueRatio == other.blueRatio; +} + +bool FilmNegativeParams::operator !=(const FilmNegativeParams& other) const +{ + return !(*this == other); +} ProcParams::ProcParams() { @@ -2794,6 +2889,8 @@ void ProcParams::setDefaults() prsharpening.deconviter = 100; prsharpening.deconvdamping = 0; + pdsharpening = {}; + vibrance = {}; wb = {}; @@ -2860,7 +2957,10 @@ void ProcParams::setDefaults() exif.clear(); iptc.clear(); - rank = 0; + // -1 means that there's no pp3 data with rank yet. In this case, the + // embedded Rating metadata should take precedence. -1 should never be + // written to pp3 on disk. + rank = -1; colorlabel = 0; inTrash = false; @@ -3170,6 +3270,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->dehaze.strength, "Dehaze", "Strength", dehaze.strength, keyFile); saveToKeyfile(!pedited || pedited->dehaze.showDepthMap, "Dehaze", "ShowDepthMap", dehaze.showDepthMap, keyFile); saveToKeyfile(!pedited || pedited->dehaze.depth, "Dehaze", "Depth", dehaze.depth, keyFile); + saveToKeyfile(!pedited || pedited->dehaze.depth, "Dehaze", "Luminance", dehaze.luminance, keyFile); // Directional pyramid denoising saveToKeyfile(!pedited || pedited->dirpyrDenoise.enabled, "Directional Pyramid Denoising", "Enabled", dirpyrDenoise.enabled, keyFile); @@ -3300,6 +3401,16 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->resize.height, "Resize", "Height", resize.height, keyFile); saveToKeyfile(!pedited || pedited->resize.allowUpscaling, "Resize", "AllowUpscaling", resize.allowUpscaling, keyFile); +// Post demosaic sharpening + saveToKeyfile(!pedited || pedited->pdsharpening.enabled, "PostDemosaicSharpening", "Enabled", pdsharpening.enabled, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.contrast, "PostDemosaicSharpening", "Contrast", pdsharpening.contrast, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.autoContrast, "PostDemosaicSharpening", "AutoContrast", pdsharpening.autoContrast, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.autoRadius, "PostDemosaicSharpening", "AutoRadius", pdsharpening.autoRadius, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.gamma, "PostDemosaicSharpening", "DeconvGamma", pdsharpening.gamma, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.deconvradius, "PostDemosaicSharpening", "DeconvRadius", pdsharpening.deconvradius, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.deconvradiusOffset, "PostDemosaicSharpening", "DeconvRadiusOffset", pdsharpening.deconvradiusOffset, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.deconviter, "PostDemosaicSharpening", "DeconvIterations", pdsharpening.deconviter, keyFile); + // Post resize sharpening saveToKeyfile(!pedited || pedited->prsharpening.enabled, "PostResizeSharpening", "Enabled", prsharpening.enabled, keyFile); saveToKeyfile(!pedited || pedited->prsharpening.contrast, "PostResizeSharpening", "Contrast", prsharpening.contrast, keyFile); @@ -3594,6 +3705,12 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo // MetaData saveToKeyfile(!pedited || pedited->metadata.mode, "MetaData", "Mode", metadata.mode, keyFile); +// Film negative + saveToKeyfile(!pedited || pedited->filmNegative.enabled, "Film Negative", "Enabled", filmNegative.enabled, keyFile); + saveToKeyfile(!pedited || pedited->filmNegative.redRatio, "Film Negative", "RedRatio", filmNegative.redRatio, keyFile); + saveToKeyfile(!pedited || pedited->filmNegative.greenExp, "Film Negative", "GreenExponent", filmNegative.greenExp, keyFile); + saveToKeyfile(!pedited || pedited->filmNegative.blueRatio, "Film Negative", "BlueRatio", filmNegative.blueRatio, keyFile); + // EXIF change list if (!pedited || pedited->exif) { std::map m; @@ -4388,6 +4505,18 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) } } + if (keyFile.has_group("PostDemosaicSharpening")) { + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "Enabled", pedited, pdsharpening.enabled, pedited->pdsharpening.enabled); + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "Contrast", pedited, pdsharpening.contrast, pedited->pdsharpening.contrast); + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "AutoContrast", pedited, pdsharpening.autoContrast, pedited->pdsharpening.autoContrast); + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "AutoRadius", pedited, pdsharpening.autoRadius, pedited->pdsharpening.autoRadius); + + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "DeconvGamma", pedited, pdsharpening.gamma, pedited->pdsharpening.gamma); + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "DeconvRadius", pedited, pdsharpening.deconvradius, pedited->pdsharpening.deconvradius); + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "DeconvRadiusOffset", pedited, pdsharpening.deconvradiusOffset, pedited->pdsharpening.deconvradiusOffset); + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "DeconvIterations", pedited, pdsharpening.deconviter, pedited->pdsharpening.deconviter); + } + if (keyFile.has_group("PostResizeSharpening")) { assignFromKeyfile(keyFile, "PostResizeSharpening", "Enabled", pedited, prsharpening.enabled, pedited->prsharpening.enabled); assignFromKeyfile(keyFile, "PostResizeSharpening", "Contrast", pedited, prsharpening.contrast, pedited->prsharpening.contrast); @@ -4798,6 +4927,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Dehaze", "Strength", pedited, dehaze.strength, pedited->dehaze.strength); assignFromKeyfile(keyFile, "Dehaze", "ShowDepthMap", pedited, dehaze.showDepthMap, pedited->dehaze.showDepthMap); assignFromKeyfile(keyFile, "Dehaze", "Depth", pedited, dehaze.depth, pedited->dehaze.depth); + assignFromKeyfile(keyFile, "Dehaze", "Luminance", pedited, dehaze.luminance, pedited->dehaze.luminance); } if (keyFile.has_group("Film Simulation")) { @@ -5151,6 +5281,13 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "RAW X-Trans", "PreBlackBlue", pedited, raw.xtranssensor.blackblue, pedited->raw.xtranssensor.exBlackBlue); } + if (keyFile.has_group("Film Negative")) { + assignFromKeyfile(keyFile, "Film Negative", "Enabled", pedited, filmNegative.enabled, pedited->filmNegative.enabled); + assignFromKeyfile(keyFile, "Film Negative", "RedRatio", pedited, filmNegative.redRatio, pedited->filmNegative.redRatio); + assignFromKeyfile(keyFile, "Film Negative", "GreenExponent", pedited, filmNegative.greenExp, pedited->filmNegative.greenExp); + assignFromKeyfile(keyFile, "Film Negative", "BlueRatio", pedited, filmNegative.blueRatio, pedited->filmNegative.blueRatio); + } + if (keyFile.has_group("MetaData")) { int mode = int(MetaDataParams::TUNNEL); assignFromKeyfile(keyFile, "MetaData", "Mode", pedited, mode, pedited->metadata.mode); @@ -5282,7 +5419,8 @@ bool ProcParams::operator ==(const ProcParams& other) const && metadata == other.metadata && exif == other.exif && iptc == other.iptc - && dehaze == other.dehaze; + && dehaze == other.dehaze + && filmNegative == other.filmNegative; } bool ProcParams::operator !=(const ProcParams& other) const diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 07ec2a5fa..4133c4621 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once @@ -284,6 +284,7 @@ struct ToneCurveParams { ToneCurveParams(); + bool isPanningRelatedChange(const ToneCurveParams& other) const; bool operator ==(const ToneCurveParams& other) const; bool operator !=(const ToneCurveParams& other) const; @@ -493,7 +494,9 @@ struct ColorToningParams { struct SharpeningParams { bool enabled; double contrast; + bool autoContrast; double blurradius; + double gamma; double radius; int amount; Threshold threshold; @@ -539,6 +542,22 @@ struct SharpenMicroParams { bool operator !=(const SharpenMicroParams& other) const; }; +struct CaptureSharpeningParams { + bool enabled; + bool autoContrast; + bool autoRadius; + double contrast; + double gamma; + double deconvradius; + double deconvradiusOffset; + int deconviter; + + CaptureSharpeningParams(); + + bool operator ==(const CaptureSharpeningParams& other) const; + bool operator !=(const CaptureSharpeningParams& other) const; +}; + /** * Parameters of the vibrance */ @@ -597,6 +616,7 @@ struct WBParams { WBParams(); + bool isPanningRelatedChange(const WBParams& other) const; bool operator ==(const WBParams& other) const; bool operator !=(const WBParams& other) const; @@ -728,7 +748,6 @@ struct DirPyrDenoiseParams { bool operator !=(const DirPyrDenoiseParams& other) const; void getCurves(NoiseCurve& lCurve, NoiseCurve& cCurve) const; - }; // EPD related parameters. @@ -1056,7 +1075,6 @@ struct ColorManagementParams { bool operator !=(const ColorManagementParams& other) const; }; - /** * Parameters for metadata handling */ @@ -1309,7 +1327,6 @@ struct HSVEqualizerParams { bool operator !=(const HSVEqualizerParams& other) const; }; - /** * Film simualtion params */ @@ -1324,7 +1341,6 @@ struct FilmSimulationParams { bool operator !=(const FilmSimulationParams& other) const; }; - struct SoftLightParams { bool enabled; int strength; @@ -1341,6 +1357,7 @@ struct DehazeParams { int strength; bool showDepthMap; int depth; + bool luminance; DehazeParams(); @@ -1348,7 +1365,6 @@ struct DehazeParams { bool operator!=(const DehazeParams &other) const; }; - /** * Parameters for RAW demosaicing, common to all sensor type */ @@ -1515,6 +1531,21 @@ struct RAWParams { static Glib::ustring getFlatFieldBlurTypeString(FlatFieldBlurType type); }; +/** + * Parameters of film negative + */ +struct FilmNegativeParams { + bool enabled; + double redRatio; + double greenExp; + double blueRatio; + + FilmNegativeParams(); + + bool operator ==(const FilmNegativeParams& other) const; + bool operator !=(const FilmNegativeParams& other) const; +}; + /** * This class holds all the processing parameters applied on the images */ @@ -1530,6 +1561,7 @@ public: ColorToningParams colorToning; ///< Color Toning parameters SharpeningParams sharpening; ///< Sharpening parameters SharpeningParams prsharpening; ///< Sharpening parameters for post resize sharpening + CaptureSharpeningParams pdsharpening; ///< Sharpening parameters for post demosaic sharpening SharpenEdgeParams sharpenEdge; ///< Sharpen edge parameters SharpenMicroParams sharpenMicro; ///< Sharpen microcontrast parameters VibranceParams vibrance; ///< Vibrance parameters @@ -1563,6 +1595,7 @@ public: FilmSimulationParams filmSimulation; ///< film simulation parameters SoftLightParams softlight; ///< softlight parameters DehazeParams dehaze; ///< dehaze parameters + FilmNegativeParams filmNegative; ///< Film negative parameters int rank; ///< Custom image quality ranking int colorlabel; ///< Custom color label bool inTrash; ///< Marks deleted image @@ -1637,8 +1670,8 @@ class PartialProfile : { public: PartialProfile(bool createInstance = false, bool paramsEditedValue = false); - PartialProfile(ProcParams* pp, ParamsEdited* pe = nullptr, bool fullCopy = false); - PartialProfile(const ProcParams* pp, const ParamsEdited* pe = nullptr); + explicit PartialProfile(ProcParams* pp, ParamsEdited* pe = nullptr, bool fullCopy = false); + explicit PartialProfile(const ProcParams* pp, const ParamsEdited* pe = nullptr); void deleteInstance(); void clearGeneral(); int load(const Glib::ustring& fName); diff --git a/rtengine/profilestore.cc b/rtengine/profilestore.cc index 437ef6ec6..5c38cf705 100644 --- a/rtengine/profilestore.cc +++ b/rtengine/profilestore.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "profilestore.h" @@ -261,12 +261,12 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath return fileFound; } -int ProfileStore::findFolderId (const Glib::ustring &path) +int ProfileStore::findFolderId (const Glib::ustring &path) const { // initialization must have been done when calling this - for (std::vector::iterator i = folders.begin(); i != folders.end(); ++i) { - if (*i == path) { - return i - folders.begin(); + for (size_t i = 0; i < folders.size(); ++i) { + if (folders[i] == path) { + return i; } } @@ -454,7 +454,7 @@ const PartialProfile* ProfileStore::getDefaultPartialProfile (bool isRaw) return pProf; } -const Glib::ustring ProfileStore::getPathFromId (int folderId) +const Glib::ustring ProfileStore::getPathFromId (int folderId) const { // initialization must have been done when calling this return folders.at (folderId); @@ -535,7 +535,7 @@ PartialProfile *ProfileStore::loadDynamicProfile (const FramesMetaData *im) return ret; } -ProfileStoreEntry::ProfileStoreEntry() : label (""), type (PSET_FOLDER), parentFolderId (0), folderId (0) {} +ProfileStoreEntry::ProfileStoreEntry() : type (PSET_FOLDER), parentFolderId (0), folderId (0) {} ProfileStoreEntry::ProfileStoreEntry (Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder) : label (label), type (type), parentFolderId (parentFolder), folderId (folder) {} diff --git a/rtengine/profilestore.h b/rtengine/profilestore.h index 5b4c94b20..384aa2a46 100644 --- a/rtengine/profilestore.h +++ b/rtengine/profilestore.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PROFILESTORE_ #define _PROFILESTORE_ @@ -185,7 +185,7 @@ public: bool init (bool loadAll = true); void parseProfiles (); - int findFolderId (const Glib::ustring &path); + int findFolderId (const Glib::ustring &path) const; const ProfileStoreEntry* findEntryFromFullPath (Glib::ustring path); const rtengine::procparams::PartialProfile* getProfile (Glib::ustring path); const rtengine::procparams::PartialProfile* getProfile (const ProfileStoreEntry* entry); @@ -193,13 +193,13 @@ public: void releaseFileList (); const rtengine::procparams::ProcParams* getDefaultProcParams (bool isRaw); const rtengine::procparams::PartialProfile* getDefaultPartialProfile (bool isRaw); - const Glib::ustring getPathFromId (int folderId); - const ProfileStoreEntry* getInternalDefaultPSE() + const Glib::ustring getPathFromId (int folderId) const; + const ProfileStoreEntry* getInternalDefaultPSE() const { return internalDefaultEntry; } - const ProfileStoreEntry* getInternalDynamicPSE() + const ProfileStoreEntry* getInternalDynamicPSE() const { return internalDynamicEntry; } diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index 1fa1630ab..0134d4d16 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -67,7 +67,7 @@ RawImage::~RawImage() } } -eSensorType RawImage::getSensorType() +eSensorType RawImage::getSensorType() const { if (isBayer()) { return ST_BAYER; diff --git a/rtengine/rawimage.h b/rtengine/rawimage.h index 8e92495a1..9c6d42969 100644 --- a/rtengine/rawimage.h +++ b/rtengine/rawimage.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __RAWIMAGE_H #define __RAWIMAGE_H @@ -113,7 +113,7 @@ public: return float_raw_image; } - eSensorType getSensorType(); + eSensorType getSensorType() const; void getRgbCam (float rgbcam[3][4]); void getXtransMatrix ( int xtransMatrix[6][6]); diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 5c91a3f09..7b053a45b 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -37,6 +37,9 @@ #include "pdaflinesfilter.h" #include "camconst.h" #include "procparams.h" +#include "color.h" +//#define BENCHMARK +//#include "StopWatch.h" #ifdef _OPENMP #include #endif @@ -429,6 +432,7 @@ RawImageSource::RawImageSource () , plistener(nullptr) , scale_mul{} , c_black{} + , c_white{} , cblacksom{} , ref_pre_mul{} , refwb_red(0.0) @@ -452,6 +456,9 @@ RawImageSource::RawImageSource () , green(0, 0) , red(0, 0) , blue(0, 0) + , greenCache(nullptr) + , redCache(nullptr) + , blueCache(nullptr) , rawDirty(true) , histMatchingParams(new procparams::ColorManagementParams) { @@ -469,6 +476,9 @@ RawImageSource::~RawImageSource () { delete idata; + delete redCache; + delete greenCache; + delete blueCache; for(size_t i = 0; i < numFrames; ++i) { delete riFrames[i]; @@ -998,11 +1008,43 @@ int RawImageSource::load (const Glib::ustring &fname, bool firstFrameOnly) if (errCode) { return errCode; } - numFrames = firstFrameOnly ? 1 : ri->getFrameCount(); + numFrames = firstFrameOnly ? (numFrames < 7 ? 1 : ri->getFrameCount()) : ri->getFrameCount(); errCode = 0; - if(numFrames > 1) { + if(numFrames >= 7) { + // special case to avoid crash when loading Hasselblad H6D-100cMS pixelshift files + // limit to 6 frames and skip first frame, as first frame is not bayer + if (firstFrameOnly) { + numFrames = 1; + } else { + numFrames = 6; + } +#ifdef _OPENMP + #pragma omp parallel +#endif + { + int errCodeThr = 0; +#ifdef _OPENMP + #pragma omp for nowait +#endif + for(unsigned int i = 0; i < numFrames; ++i) { + if(i == 0) { + riFrames[i] = ri; + errCodeThr = riFrames[i]->loadRaw (true, i + 1, true, plistener, 0.8); + } else { + riFrames[i] = new RawImage(fname); + errCodeThr = riFrames[i]->loadRaw (true, i + 1); + } + } +#ifdef _OPENMP + #pragma omp critical +#endif + { + errCode = errCodeThr ? errCodeThr : errCode; + } + } + } else if(numFrames > 1) { #ifdef _OPENMP #pragma omp parallel #endif @@ -1518,7 +1560,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::demosaic(const RAWParams &raw, bool autoContrast, double &contrastThreshold) +void RawImageSource::demosaic(const RAWParams &raw, bool autoContrast, double &contrastThreshold, bool cache) { MyTime t1, t2; t1.set(); @@ -1589,7 +1631,49 @@ void RawImageSource::demosaic(const RAWParams &raw, bool autoContrast, double &c rgbSourceModified = false; - + if (cache) { + if (!redCache) { + redCache = new array2D(W, H); + greenCache = new array2D(W, H); + blueCache = new array2D(W, H); + } +#ifdef _OPENMP + #pragma omp parallel sections +#endif + { +#ifdef _OPENMP + #pragma omp section +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + (*redCache)[i][j] = red[i][j]; + } + } +#ifdef _OPENMP + #pragma omp section +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + (*greenCache)[i][j] = green[i][j]; + } + } +#ifdef _OPENMP + #pragma omp section +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + (*blueCache)[i][j] = blue[i][j]; + } + } + } + } else { + delete redCache; + redCache = nullptr; + delete greenCache; + greenCache = nullptr; + delete blueCache; + blueCache = nullptr; + } if( settings->verbose ) { if (getSensorType() == ST_BAYER) { printf("Demosaicing Bayer data: %s - %d usec\n", raw.bayersensor.method.c_str(), t2.etime(t1)); @@ -3823,7 +3907,7 @@ bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embed return false; } - if (inProfile == "(embedded)" && embedded) { + if (embedded && inProfile == "(embedded)") { in = embedded; } else if (inProfile == "(cameraICC)") { // DCPs have higher quality, so use them first @@ -3832,7 +3916,7 @@ bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embed if (*dcpProf == nullptr) { in = ICCStore::getInstance()->getStdProfile(camName); } - } else if (inProfile != "(camera)" && inProfile != "") { + } else if (inProfile != "(camera)" && !inProfile.empty()) { Glib::ustring normalName = inProfile; if (!inProfile.compare (0, 5, "file:")) { @@ -4929,9 +5013,7 @@ void RawImageSource::getRawValues(int x, int y, int rotate, int &R, int &G, int ynew = H - 1 - ynew; } else if (rotate == 270) { std::swap(xnew,ynew); - ynew = H - 1 - ynew; xnew = W - 1 - xnew; - ynew = H - 1 - ynew; } xnew = LIM(xnew, 0, W - 1); diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 4c7b0ba21..e52adea18 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -14,11 +14,11 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ -#ifndef _RAWIMAGESOURCE_ -#define _RAWIMAGESOURCE_ +#pragma once +#include #include #include @@ -37,7 +37,6 @@ namespace rtengine class RawImageSource : public ImageSource { - private: static DiagonalCurve *phaseOneIccCurve; static DiagonalCurve *phaseOneIccCurveInv; @@ -75,13 +74,13 @@ protected: bool rgbSourceModified; RawImage* ri; // Copy of raw pixels, NOT corrected for initial gain, blackpoint etc. - RawImage* riFrames[4] = {nullptr}; + RawImage* riFrames[6] = {nullptr}; unsigned int currFrame = 0; unsigned int numFrames = 0; int flatFieldAutoClipValue = 0; array2D rawData; // holds preprocessed pixel values, rowData[i][j] corresponds to the ith row and jth column - array2D *rawDataFrames[4] = {nullptr}; - array2D *rawDataBuffer[3] = {nullptr}; + array2D *rawDataFrames[6] = {nullptr}; + array2D *rawDataBuffer[5] = {nullptr}; // the interpolated green plane: array2D green; @@ -89,6 +88,12 @@ protected: array2D red; // the interpolated blue plane: array2D blue; + // the interpolated green plane: + array2D* greenCache; + // the interpolated red plane: + array2D* redCache; + // the interpolated blue plane: + array2D* blueCache; bool rawDirty; float psRedBrightness[4]; float psGreenBrightness[4]; @@ -109,7 +114,6 @@ protected: inline void getRowStartEnd (int x, int &start, int &end); static void getProfilePreprocParams(cmsHPROFILE in, float& gammafac, float& lineFac, float& lineSum); - public: RawImageSource (); ~RawImageSource () override; @@ -117,7 +121,9 @@ public: int load(const Glib::ustring &fname) override { return load(fname, false); } int load(const Glib::ustring &fname, bool firstFrameOnly); void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, bool prepareDenoise = true) override; - void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold) override; + void filmNegativeProcess (const procparams::FilmNegativeParams ¶ms) override; + bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, std::array& newExps) override; + void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold, bool cache = false) override; void retinex (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &deh, const procparams::ToneCurveParams& Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) override; void retinexPrepareCurves (const procparams::RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) override; void retinexPrepareBuffers (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI) override; @@ -195,8 +201,6 @@ public: } static void inverse33 (const double (*coeff)[3], double (*icoeff)[3]); - void boxblur2(float** src, float** dst, float** temp, int H, int W, int box ); - void boxblur_resamp(float **src, float **dst, float** temp, int H, int W, int box, int samp ); void MSR(float** luminance, float **originalLuminance, float **exLuminance, LUTf & mapcurve, bool &mapcontlutili, int width, int height, const RetinexParams &deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax); void HLRecovery_inpaint (float** red, float** green, float** blue) override; static void HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval); @@ -307,7 +311,7 @@ protected: void hflip (Imagefloat* im); void vflip (Imagefloat* im); void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) override; - + void captureSharpening(const procparams::CaptureSharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold, double &radius) override; }; + } -#endif diff --git a/rtengine/rawimagesource_i.h b/rtengine/rawimagesource_i.h index b24115e0a..485205d9d 100644 --- a/rtengine/rawimagesource_i.h +++ b/rtengine/rawimagesource_i.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef RAWIMAGESOURCE_I_H_INCLUDED diff --git a/rtengine/rcd_demosaic.cc b/rtengine/rcd_demosaic.cc index 904daea71..48c3ad334 100644 --- a/rtengine/rcd_demosaic.cc +++ b/rtengine/rcd_demosaic.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -49,11 +49,11 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure) stop.reset(new StopWatch("rcd demosaic")); } - volatile double progress = 0.0; + double progress = 0.0; if (plistener) { plistener->setProgressStr(Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), M("TP_RAW_RCD"))); - plistener->setProgress(0); + plistener->setProgress(progress); } constexpr int rcdBorder = 9; diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index d741b1744..6917d856e 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "refreshmap.h" #include "procevents.h" @@ -519,7 +519,10 @@ int refreshmap[rtengine::NUMOFEVENTS] = { HDR, // EvTMFattalAmount ALLNORAW, // EvWBEnabled RGBCURVE, // EvRGBEnabled - LUMINANCECURVE // EvLEnabled + LUMINANCECURVE, // EvLEnabled + DEMOSAIC, // EvPdShrEnabled + CAPTURESHARPEN // EvPdShrMaskToggled + }; diff --git a/rtengine/refreshmap.h b/rtengine/refreshmap.h index b9ccc2b65..3f4831329 100644 --- a/rtengine/refreshmap.h +++ b/rtengine/refreshmap.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __REFRESHMAP__ #define __REFRESHMAP__ @@ -32,6 +32,7 @@ // Elementary functions that can be done to // the preview image when an event occurs +#define M_CSHARP (1<<18) #define M_MONITOR (1<<14) #define M_RETINEX (1<<13) #define M_CROP (1<<12) @@ -56,6 +57,7 @@ #define FLATFIELD (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) #define DEMOSAIC (M_RAW|M_INIT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) #define ALLNORAW (M_INIT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) +#define CAPTURESHARPEN (M_INIT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR|M_CSHARP) #define HDR (M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) #define TRANSFORM (M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) #define AUTOEXP (M_HDR|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) diff --git a/rtengine/rescale.h b/rtengine/rescale.h index ba9a01c99..e9d476fea 100644 --- a/rtengine/rescale.h +++ b/rtengine/rescale.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtengine/rt_algo.cc b/rtengine/rt_algo.cc index 1011ae7b7..dd7783c1d 100644 --- a/rtengine/rt_algo.cc +++ b/rtengine/rt_algo.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -52,7 +52,7 @@ vfloat calcBlendFactor(vfloat valv, vfloat thresholdv) { } #endif -float tileAverage(float **data, size_t tileY, size_t tileX, size_t tilesize) { +float tileAverage(const float * const *data, size_t tileY, size_t tileX, size_t tilesize) { float avg = 0.f; #ifdef __SSE2__ @@ -75,7 +75,7 @@ float tileAverage(float **data, size_t tileY, size_t tileX, size_t tilesize) { return avg / rtengine::SQR(tilesize); } -float tileVariance(float **data, size_t tileY, size_t tileX, size_t tilesize, float avg) { +float tileVariance(const float * const *data, size_t tileY, size_t tileX, size_t tilesize, float avg) { float var = 0.f; #ifdef __SSE2__ @@ -99,7 +99,7 @@ float tileVariance(float **data, size_t tileY, size_t tileX, size_t tilesize, fl return var / (rtengine::SQR(tilesize) * avg); } -float calcContrastThreshold(float** luminance, int tileY, int tileX, int tilesize) { +float calcContrastThreshold(const float* const * luminance, int tileY, int tileX, int tilesize) { constexpr float scale = 0.0625f / 327.68f; std::vector> blend(tilesize - 4, std::vector(tilesize - 4)); @@ -156,7 +156,7 @@ float calcContrastThreshold(float** luminance, int tileY, int tileX, int tilesiz } } - return c / 100.f; + return (c + 1) / 100.f; } } @@ -299,7 +299,7 @@ void findMinMaxPercentile(const float* data, size_t size, float minPrct, float& maxOut = rtengine::LIM(maxOut, minVal, maxVal); } -void buildBlendMask(float** luminance, float **blend, int W, int H, float &contrastThreshold, float amount, bool autoContrast) { +void buildBlendMask(const float* const * luminance, float **blend, int W, int H, float &contrastThreshold, float amount, bool autoContrast, float ** clipMask) { if (autoContrast) { constexpr float minLuminance = 2000.f; @@ -394,7 +394,7 @@ void buildBlendMask(float** luminance, float **blend, int W, int H, float &contr } } - contrastThreshold = minvar <= 4.f ? calcContrastThreshold(luminance, topLeftYStart + minI, topLeftXStart + minJ, tilesize) : 0.f; + contrastThreshold = minvar <= 8.f ? calcContrastThreshold(luminance, topLeftYStart + minI, topLeftXStart + minJ, tilesize) : 0.f; } } } @@ -424,11 +424,20 @@ void buildBlendMask(float** luminance, float **blend, int W, int H, float &contr for(int j = 2; j < H - 2; ++j) { int i = 2; #ifdef __SSE2__ - for(; i < W - 5; i += 4) { - vfloat contrastv = vsqrtf(SQRV(LVFU(luminance[j][i+1]) - LVFU(luminance[j][i-1])) + SQRV(LVFU(luminance[j+1][i]) - LVFU(luminance[j-1][i])) + - SQRV(LVFU(luminance[j][i+2]) - LVFU(luminance[j][i-2])) + SQRV(LVFU(luminance[j+2][i]) - LVFU(luminance[j-2][i]))) * scalev; + if (clipMask) { + for(; i < W - 5; i += 4) { + vfloat contrastv = vsqrtf(SQRV(LVFU(luminance[j][i+1]) - LVFU(luminance[j][i-1])) + SQRV(LVFU(luminance[j+1][i]) - LVFU(luminance[j-1][i])) + + SQRV(LVFU(luminance[j][i+2]) - LVFU(luminance[j][i-2])) + SQRV(LVFU(luminance[j+2][i]) - LVFU(luminance[j-2][i]))) * scalev; - STVFU(blend[j][i], amountv * calcBlendFactor(contrastv, contrastThresholdv)); + STVFU(blend[j][i], LVFU(clipMask[j][i]) * amountv * calcBlendFactor(contrastv, contrastThresholdv)); + } + } else { + for(; i < W - 5; i += 4) { + vfloat contrastv = vsqrtf(SQRV(LVFU(luminance[j][i+1]) - LVFU(luminance[j][i-1])) + SQRV(LVFU(luminance[j+1][i]) - LVFU(luminance[j-1][i])) + + SQRV(LVFU(luminance[j][i+2]) - LVFU(luminance[j][i-2])) + SQRV(LVFU(luminance[j+2][i]) - LVFU(luminance[j-2][i]))) * scalev; + + STVFU(blend[j][i], amountv * calcBlendFactor(contrastv, contrastThresholdv)); + } } #endif for(; i < W - 2; ++i) { @@ -436,7 +445,7 @@ void buildBlendMask(float** luminance, float **blend, int W, int H, float &contr float contrast = sqrtf(rtengine::SQR(luminance[j][i+1] - luminance[j][i-1]) + rtengine::SQR(luminance[j+1][i] - luminance[j-1][i]) + rtengine::SQR(luminance[j][i+2] - luminance[j][i-2]) + rtengine::SQR(luminance[j+2][i] - luminance[j-2][i])) * scale; - blend[j][i] = amount * calcBlendFactor(contrast, contrastThreshold); + blend[j][i] = (clipMask ? clipMask[j][i] : 1.f) * amount * calcBlendFactor(contrast, contrastThreshold); } } diff --git a/rtengine/rt_algo.h b/rtengine/rt_algo.h index a8e2e3e23..5485346c7 100644 --- a/rtengine/rt_algo.h +++ b/rtengine/rt_algo.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once @@ -24,5 +24,5 @@ namespace rtengine { void findMinMaxPercentile(const float* data, size_t size, float minPrct, float& minOut, float maxPrct, float& maxOut, bool multiThread = true); -void buildBlendMask(float** luminance, float **blend, int W, int H, float &contrastThreshold, float amount = 1.f, bool autoContrast = false); +void buildBlendMask(const float* const * luminance, float **blend, int W, int H, float &contrastThreshold, float amount = 1.f, bool autoContrast = false, float ** clipmask = nullptr); } diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index bdb94fe4a..ee234d922 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -14,23 +14,28 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ -#ifndef _RTENGINE_ -#define _RTENGINE_ +#pragma once -#include "imageformat.h" -#include "rt_math.h" -#include "procevents.h" -#include -#include -#include +#include #include +#include + +#include + +#include + #include "iimage.h" -#include "utils.h" -#include "../rtgui/threadutils.h" -#include "settings.h" +#include "imageformat.h" #include "LUT.h" +#include "procevents.h" +#include "rt_math.h" +#include "settings.h" +#include "utils.h" + +#include "../rtgui/threadutils.h" + /** * @file * This file contains the main functionality of the RawTherapee engine. @@ -109,6 +114,8 @@ public: virtual std::string getLens() const = 0; /** @return the orientation of the image */ virtual std::string getOrientation() const = 0; + /** @return the rating of the image */ + virtual int getRating () const = 0; /** @return true if the file is a PixelShift shot (Pentax and Sony bodies) */ virtual bool getPixelShift () const = 0; @@ -385,6 +392,13 @@ public : virtual void autoContrastChanged (double autoContrast) = 0; }; +class AutoRadiusListener +{ +public : + virtual ~AutoRadiusListener() = default; + virtual void autoRadiusChanged (double autoRadius) = 0; +}; + class WaveletListener { public: @@ -477,6 +491,7 @@ public: virtual bool getAutoWB (double& temp, double& green, double equal, double tempBias) = 0; virtual void getCamWB (double& temp, double& green) = 0; virtual void getSpotWB (int x, int y, int rectSize, double& temp, double& green) = 0; + virtual bool getFilmNegativeExponents(int xA, int yA, int xB, int yB, std::array& newExps) = 0; virtual void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) = 0; virtual void saveInputICCReference (const Glib::ustring& fname, bool apply_wb) = 0; @@ -492,6 +507,8 @@ public: virtual void setFrameCountListener (FrameCountListener* l) = 0; virtual void setBayerAutoContrastListener (AutoContrastListener* l) = 0; virtual void setXtransAutoContrastListener (AutoContrastListener* l) = 0; + virtual void setpdSharpenAutoContrastListener (AutoContrastListener* l) = 0; + virtual void setpdSharpenAutoRadiusListener (AutoRadiusListener* l) = 0; virtual void setAutoBWListener (AutoBWListener* l) = 0; virtual void setAutoWBListener (AutoWBListener* l) = 0; virtual void setAutoColorTonListener (AutoColorTonListener* l) = 0; @@ -504,7 +521,7 @@ public: virtual void getMonitorProfile (Glib::ustring& monitorProfile, RenderingIntent& intent) const = 0; virtual void setSoftProofing (bool softProof, bool gamutCheck) = 0; virtual void getSoftProofing (bool &softProof, bool &gamutCheck) = 0; - virtual void setSharpMask (bool sharpMask) = 0; + virtual ProcEvent setSharpMask (bool sharpMask) = 0; virtual ~StagedImageProcessor () {} @@ -590,6 +607,3 @@ void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl); extern MyMutex* lcmsMutex; } - -#endif - diff --git a/rtengine/rtetest.cc b/rtengine/rtetest.cc deleted file mode 100644 index bd81dbb0d..000000000 --- a/rtengine/rtetest.cc +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of RawTherapee. - * - * Copyright (c) 2004-2010 Gabor Horvath - * - * RawTherapee is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RawTherapee is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - */ -#include "rtengine.h" -#include -//#include -#include - -class PListener : - public rtengine::ProgressListener -{ -public: - void setProgressStr(const Glib::ustring& str) - { - std::cout << str << std::endl; - } - void setProgress(double p) - { - std::cout << p << std::endl; - } - void setProgressState(bool inProcessing) - { - } - void error(const Glib::ustring& descr) - { - } -}; - -int main (int argc, char* argv[]) -{ - if (argc < 4) { - std::cout << "Usage: rtcmd " << std::endl; - exit(1); - } - - rtengine::Settings s; - s.demosaicMethod = "hphd"; - s.colorCorrectionSteps = 2; - s.iccDirectory = ""; - s.colorimetricIntent = 1; - s.monitorProfile = ""; - - Glib::thread_init (); - rtengine::init (s, ""); - PListener pl; - - rtengine::InitialImage* ii; - int errorCode; - ii = rtengine::InitialImage::load (argv[1], true, errorCode, &pl); - - if (!ii) { - ii = rtengine::InitialImage::load (argv[1], false, errorCode, &pl); - } - - if (!ii) { - std::cout << "Input file not supported." << std::endl; - exit(2); - } - - rtengine::procparams::ProcParams params; - params.load (argv[2]); - - rtengine::ProcessingJob* job = ProcessingJob::create (ii, params); - rtengine::IImage16* res = rtengine::processImage (job, errorCode, &pl); - res->saveToFile (argv[3]); -} - diff --git a/rtengine/rtlensfun.cc b/rtengine/rtlensfun.cc index 3cea8c484..8c634eaa8 100644 --- a/rtengine/rtlensfun.cc +++ b/rtengine/rtlensfun.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "rtlensfun.h" @@ -132,7 +132,7 @@ Glib::ustring LFModifier::getDisplayString() const return "NONE"; } else { Glib::ustring ret; - Glib::ustring sep = ""; + Glib::ustring sep; if (flags_ & LF_MODIFY_DISTORTION) { ret += "distortion"; sep = ", "; diff --git a/rtengine/rtlensfun.h b/rtengine/rtlensfun.h index 8b097b30e..092e2bf01 100644 --- a/rtengine/rtlensfun.h +++ b/rtengine/rtlensfun.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index eb241bca5..24525388d 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "rtengine.h" #include "rtthumbnail.h" @@ -522,6 +522,17 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, eSensorType &sens return nullptr; } + if (ri->getFrameCount() == 7) { + // special case for Hasselblad H6D-100cMS pixelshift files + // first frame is not bayer, load second frame + int r = ri->loadRaw (1, 1, 0); + + if ( r ) { + delete ri; + sensorType = ST_NONE; + return nullptr; + } + } sensorType = ri->getSensorType(); int width = ri->get_width(); @@ -1130,6 +1141,10 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT Imagefloat* baseImg = resizeTo (rwidth, rheight, interp, thumbImg); + if (isRaw && params.filmNegative.enabled) { + processFilmNegative(params, baseImg, rwidth, rheight, rmi, gmi, bmi); + } + if (params.coarse.rotate) { baseImg->rotate (params.coarse.rotate); rwidth = baseImg->getWidth(); @@ -1439,19 +1454,22 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT } myscale = 1.0 / myscale; - /* // apply crop - if (params.crop.enabled) { - int ix = 0; - for (int i=0; i(params.crop.y+params.crop.h)/myscale || j(params.crop.x+params.crop.w)/myscale) { - readyImg->data[ix++] /= 3; - readyImg->data[ix++] /= 3; - readyImg->data[ix++] /= 3; - } - else - ix += 3; - }*/ + // apply crop + if (params.crop.enabled) { + int ix = 0; + for (int i = 0; i < fh; ++i) { + for (int j = 0; j < fw; ++j) { + if (i < params.crop.y * myscale || i > (params.crop.y + params.crop.h) * myscale || j < params.crop.x * myscale || j > (params.crop.x + params.crop.w) * myscale) { + readyImg->data[ix++] /= 3; + readyImg->data[ix++] /= 3; + readyImg->data[ix++] /= 3; + } else { + ix += 3; + } + } + } + } + return readyImg; } diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h index a2839e83d..c039baaae 100644 --- a/rtengine/rtthumbnail.h +++ b/rtengine/rtthumbnail.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _THUMBPROCESSINGPARAMETERS_ #define _THUMBPROCESSINGPARAMETERS_ @@ -67,6 +67,8 @@ class Thumbnail bool gammaCorrected; double colorMatrix[3][3]; + void processFilmNegative(const procparams::ProcParams& params, const Imagefloat* baseImg, int rwidth, int rheight, float &rmi, float &gmi, float &bmi); + public: bool isRaw; diff --git a/rtengine/settings.h b/rtengine/settings.h index 1fc3b222c..8852c05c8 100644 --- a/rtengine/settings.h +++ b/rtengine/settings.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _RTSETTINGS_ #define _RTSETTINGS_ diff --git a/rtengine/shmap.cc b/rtengine/shmap.cc index 1eb911220..6b59c4b40 100644 --- a/rtengine/shmap.cc +++ b/rtengine/shmap.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "shmap.h" #include "gauss.h" diff --git a/rtengine/shmap.h b/rtengine/shmap.h index 4234e203d..539ef99ff 100644 --- a/rtengine/shmap.h +++ b/rtengine/shmap.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __SHMAP__ #define __SHMAP__ diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 999617c4c..4fd19f598 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "rtengine.h" #include "colortemp.h" @@ -209,13 +209,21 @@ private: imgsrc->setCurrentFrame (params.raw.bayersensor.imageNum); imgsrc->preprocess ( params.raw, params.lensProf, params.coarse, params.dirpyrDenoise.enabled); + // After preprocess, run film negative processing if enabled + if ((imgsrc->getSensorType() == ST_BAYER || (imgsrc->getSensorType() == ST_FUJI_XTRANS)) && params.filmNegative.enabled) { + imgsrc->filmNegativeProcess (params.filmNegative); + } + if (pl) { pl->setProgress (0.20); } bool autoContrast = imgsrc->getSensorType() == ST_BAYER ? params.raw.bayersensor.dualDemosaicAutoContrast : params.raw.xtranssensor.dualDemosaicAutoContrast; double contrastThreshold = imgsrc->getSensorType() == ST_BAYER ? params.raw.bayersensor.dualDemosaicContrast : params.raw.xtranssensor.dualDemosaicContrast; - imgsrc->demosaic (params.raw, autoContrast, contrastThreshold); + imgsrc->demosaic (params.raw, autoContrast, contrastThreshold, params.pdsharpening.enabled && pl); + if (params.pdsharpening.enabled) { + imgsrc->captureSharpening(params.pdsharpening, false, params.pdsharpening.contrast, params.pdsharpening.deconvradius); + } if (pl) { @@ -1320,7 +1328,7 @@ private: } else { // use the selected output profile if present, otherwise use LCMS2 profile generate by lab2rgb16 w/ gamma - if (params.icm.outputProfile != "" && params.icm.outputProfile != ColorManagementParams::NoICMString) { + if (!params.icm.outputProfile.empty() && params.icm.outputProfile != ColorManagementParams::NoICMString) { // if ICCStore::getInstance()->getProfile send back an object, then ICCStore::getInstance()->getContent will do too cmsHPROFILE jprof = ICCStore::getInstance()->getProfile (params.icm.outputProfile); //get outProfile diff --git a/rtengine/sleefsseavx.c b/rtengine/sleefsseavx.c index 3000c1c10..cce88df5d 100644 --- a/rtengine/sleefsseavx.c +++ b/rtengine/sleefsseavx.c @@ -1390,6 +1390,18 @@ static inline float vhadd( vfloat a ) { return _mm_cvtss_f32(_mm_add_ss(a, _mm_shuffle_ps(a, a, 1))); } +static inline float vhmin(vfloat a) { + // returns min(a[0], a[1], a[2], a[3]) + a = vminf(a, _mm_movehl_ps(a, a)); + return _mm_cvtss_f32(vminf(a, _mm_shuffle_ps(a, a, 1))); +} + +static inline float vhmax(vfloat a) { + // returns max(a[0], a[1], a[2], a[3]) + a = vmaxf(a, _mm_movehl_ps(a, a)); + return _mm_cvtss_f32(vmaxf(a, _mm_shuffle_ps(a, a, 1))); +} + static INLINE vfloat vmul2f(vfloat a){ // fastest way to multiply by 2 return a + a; diff --git a/rtengine/slicer.cc b/rtengine/slicer.cc index 72a42e07e..96c0a0ee8 100644 --- a/rtengine/slicer.cc +++ b/rtengine/slicer.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtengine/slicer.h b/rtengine/slicer.h index 06e1522cd..658133e5f 100644 --- a/rtengine/slicer.h +++ b/rtengine/slicer.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _SLICER_ #define _SLICER_ diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc index 6ca3091a3..2ec1529f7 100644 --- a/rtengine/stdimagesource.cc +++ b/rtengine/stdimagesource.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "stdimagesource.h" @@ -224,7 +224,7 @@ void StdImageSource::colorSpaceConversion (Imagefloat* im, const ColorManagement cmsHPROFILE in = nullptr; cmsHPROFILE out = ICCStore::getInstance()->workingSpace (cmp.workingProfile); - if (cmp.inputProfile == "(embedded)" || cmp.inputProfile == "" || cmp.inputProfile == "(camera)" || cmp.inputProfile == "(cameraICC)") { + if (cmp.inputProfile == "(embedded)" || cmp.inputProfile.empty() || cmp.inputProfile == "(camera)" || cmp.inputProfile == "(cameraICC)") { if (embedded) { in = embedded; } else { diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index 8f16880dc..0dffe2fd0 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _STDIMAGESOURCE_ #define _STDIMAGESOURCE_ @@ -102,7 +102,7 @@ public: void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) override { R = G = B = 0;} void flushRGB () override; - + void captureSharpening(const procparams::CaptureSharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold, double &radius) override {}; }; } #endif diff --git a/rtengine/tmo_fattal02.cc b/rtengine/tmo_fattal02.cc index 32755319e..6b5460ffd 100644 --- a/rtengine/tmo_fattal02.cc +++ b/rtengine/tmo_fattal02.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ /** @@ -476,14 +476,14 @@ void tmo_fattal02 (size_t width, Array2Df* H = new Array2Df (width, height); float temp = 100.f / maxLum; - float eps = 1e-4f; #ifdef _OPENMP #pragma omp parallel if(multithread) #endif { + const float eps = 1e-4f; #ifdef __SSE2__ - vfloat epsv = F2V (eps); - vfloat tempv = F2V (temp); + const vfloat epsv = F2V(eps); + const vfloat tempv = F2V(temp); #endif #ifdef _OPENMP #pragma omp for schedule(dynamic,16) @@ -926,13 +926,13 @@ void solve_pde_fft (Array2Df *F, Array2Df *U, Array2Df *buf, bool multithread)/* // a solution which has no positive values: U_new(x,y)=U(x,y)-max // (not really needed but good for numerics as we later take exp(U)) //DEBUG_STR << "solve_pde_fft: removing constant from solution" << std::endl; - float max = 0.f; + float maxVal = 0.f; #ifdef _OPENMP - #pragma omp parallel for reduction(max:max) if(multithread) + #pragma omp parallel for reduction(max:maxVal) if(multithread) #endif for (int i = 0; i < width * height; i++) { - max = std::max (max, (*U) (i)); + maxVal = std::max(maxVal, (*U)(i)); } #ifdef _OPENMP @@ -940,7 +940,7 @@ void solve_pde_fft (Array2Df *F, Array2Df *U, Array2Df *buf, bool multithread)/* #endif for (int i = 0; i < width * height; i++) { - (*U) (i) -= max; + (*U) (i) -= maxVal; } } diff --git a/rtengine/utils.cc b/rtengine/utils.cc index 613b67be8..a07a1235f 100644 --- a/rtengine/utils.cc +++ b/rtengine/utils.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include diff --git a/rtengine/utils.h b/rtengine/utils.h index 14593edae..e0097d76e 100644 --- a/rtengine/utils.h +++ b/rtengine/utils.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtengine/vng4_demosaic_RT.cc b/rtengine/vng4_demosaic_RT.cc index f9a4c5bc2..66413e4c7 100644 --- a/rtengine/vng4_demosaic_RT.cc +++ b/rtengine/vng4_demosaic_RT.cc @@ -16,7 +16,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// diff --git a/rtengine/xtrans_demosaic.cc b/rtengine/xtrans_demosaic.cc index cd925fc33..9a3b341cc 100644 --- a/rtengine/xtrans_demosaic.cc +++ b/rtengine/xtrans_demosaic.cc @@ -15,7 +15,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// @@ -39,9 +39,9 @@ const float d65_white[3] = { 0.950456, 1, 1.088754 }; void RawImageSource::cielab (const float (*rgb)[3], float* l, float* a, float *b, const int width, const int height, const int labWidth, const float xyz_cam[3][3]) { static LUTf cbrt(0x14000); - static bool cbrtinit = false; if (!rgb) { + static bool cbrtinit = false; if(!cbrtinit) { #pragma omp parallel for for (int i = 0; i < 0x14000; i++) { @@ -291,8 +291,6 @@ void RawImageSource::xtrans_interpolate (const int passes, const bool useCieLab, #endif { int progressCounter = 0; - int c; - float color[3][6]; float *buffer = (float *) malloc ((ts * ts * (ndir * 4 + 3) + 128) * sizeof(float)); float (*rgb)[ts][ts][3] = (float(*)[ts][ts][3]) buffer; @@ -521,6 +519,7 @@ void RawImageSource::xtrans_interpolate (const int passes, const bool useCieLab, /* Interpolate red and blue values for solitary green pixels: */ int sgstartcol = (left - sgcol + 4) / 3 * 3 + sgcol; + float color[3][6]; for (int row = (top - sgrow + 4) / 3 * 3 + sgrow; row < mrow - 2; row += 3) { for (int col = sgstartcol, h = fcol(row, col + 1); col < mcol - 2; col += 3, h ^= 2) { @@ -564,7 +563,7 @@ void RawImageSource::xtrans_interpolate (const int passes, const bool useCieLab, } int coloffset = (RightShift[row % 3] == 1 ? 3 : 1); - c = (row - sgrow) % 3 ? ts : 1; + int c = ((row - sgrow) % 3) ? ts : 1; int h = 3 * (c ^ ts ^ 1); if(coloffset == 3) { @@ -629,13 +628,13 @@ void RawImageSource::xtrans_interpolate (const int passes, const bool useCieLab, if (hex[d] + hex[d + 1]) { float g = 3 * rix[0][1] - 2 * rix[hex[d]][1] - rix[hex[d + 1]][1]; - for (c = 0; c < 4; c += 2) { + for (int c = 0; c < 4; c += 2) { rix[0][c] = CLIP((g + 2 * rix[hex[d]][c] + rix[hex[d + 1]][c]) * 0.33333333f); } } else { float g = 2 * rix[0][1] - rix[hex[d]][1] - rix[hex[d + 1]][1]; - for (c = 0; c < 4; c += 2) { + for (int c = 0; c < 4; c += 2) { rix[0][c] = CLIP((g + rix[hex[d]][c] + rix[hex[d + 1]][c]) * 0.5f); } } @@ -656,10 +655,7 @@ void RawImageSource::xtrans_interpolate (const int passes, const bool useCieLab, // (presumably coming from original AHD) and converts taking // camera matrix into account. We use this in RT. for (int d = 0; d < ndir; d++) { - float *l = &lab[0][0][0]; - float *a = &lab[1][0][0]; - float *b = &lab[2][0][0]; - cielab(&rgb[d][4][4], l, a, b, ts, mrow - 8, ts - 8, xyz_cam); + cielab(&rgb[d][4][4], &lab[0][0][0], &lab[1][0][0], &lab[2][0][0], ts, mrow - 8, ts - 8, xyz_cam); int f = dir[d & 3]; f = f == 1 ? 1 : f - 8; @@ -704,7 +700,7 @@ void RawImageSource::xtrans_interpolate (const int passes, const bool useCieLab, // which appears less good with specular highlights vfloat redv, greenv, bluev; vconvertrgbrgbrgbrgb2rrrrggggbbbb(rgb[d][row][col], redv, greenv, bluev); - vfloat yv = zd2627v * redv + zd6780v * bluev + zd0593v * greenv; + vfloat yv = zd2627v * redv + zd6780v * greenv + zd0593v * bluev; STVFU(yuv[0][row - 4][col - 4], yv); STVFU(yuv[1][row - 4][col - 4], (bluev - yv) * zd56433v); STVFU(yuv[2][row - 4][col - 4], (redv - yv) * zd67815v); @@ -963,7 +959,7 @@ void RawImageSource::xtrans_interpolate (const int passes, const bool useCieLab, free(buffer); } - xtransborder_interpolate(8, red, green, blue); + xtransborder_interpolate(passes > 1 ? 8 : 11, red, green, blue); } #undef CLIP void RawImageSource::fast_xtrans_interpolate (const array2D &rawData, array2D &red, array2D &green, array2D &blue) diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index ab58a73f9..67b127061 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -8,7 +8,7 @@ set(CLISOURCEFILES paramsedited.cc pathutils.cc threadutils.cc - ) +) set(NONCLISOURCEFILES adjuster.cc @@ -43,6 +43,7 @@ set(NONCLISOURCEFILES curveeditorgroup.cc darkframe.cc defringe.cc + dehaze.cc diagonalcurveeditorsubgroup.cc dirbrowser.cc dirpyrdenoise.cc @@ -55,15 +56,18 @@ set(NONCLISOURCEFILES editwidgets.cc editwindow.cc epd.cc + eventmapper.cc exiffiltersettings.cc exifpanel.cc exportpanel.cc extprog.cc + fattaltonemap.cc filebrowser.cc filebrowserentry.cc filecatalog.cc filepanel.cc filethumbnailbuttonset.cc + filmnegative.cc filmsimulation.cc filterpanel.cc flatcurveeditorsubgroup.cc @@ -83,12 +87,15 @@ set(NONCLISOURCEFILES inspector.cc iptcpanel.cc labcurve.cc + labgrid.cc lensgeom.cc lensprofile.cc + localcontrast.cc lockablecolorpicker.cc lwbutton.cc lwbuttonset.cc main.cc + metadatapanel.cc multilangmgr.cc mycurve.cc mydiagonalcurve.cc @@ -99,6 +106,7 @@ set(NONCLISOURCEFILES partialpastedlg.cc pathutils.cc pcvignette.cc + pdsharpening.cc perspective.cc placesbrowser.cc popupbutton.cc @@ -122,8 +130,8 @@ set(NONCLISOURCEFILES rgbcurves.cc rotate.cc rtimage.cc - rtsurface.cc rtscalable.cc + rtsurface.cc rtwindow.cc saveasdlg.cc saveformatpanel.cc @@ -134,6 +142,7 @@ set(NONCLISOURCEFILES sharpening.cc sharpenmicro.cc shcselector.cc + softlight.cc soundman.cc splash.cc threadutils.cc @@ -154,14 +163,7 @@ set(NONCLISOURCEFILES xtransprocess.cc xtransrawexposure.cc zoompanel.cc - fattaltonemap.cc - localcontrast.cc - eventmapper.cc - metadatapanel.cc - labgrid.cc - softlight.cc - dehaze.cc - ) +) include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}") @@ -284,6 +286,7 @@ target_link_libraries(rth rtengine ${ZLIB_LIBRARIES} ${LENSFUN_LIBRARIES} ${RSVG_LIBRARIES} + ${TCMALLOC_LIBRARIES} ) target_link_libraries(rth-cli rtengine @@ -305,6 +308,7 @@ target_link_libraries(rth-cli rtengine ${ZLIB_LIBRARIES} ${LENSFUN_LIBRARIES} ${RSVG_LIBRARIES} + ${TCMALLOC_LIBRARIES} ) # Install executables diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h index 163bc27ef..6a4ea83d3 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -142,6 +142,7 @@ enum { ADDSET_XTRANS_FALSE_COLOR_SUPPRESSION, ADDSET_SOFTLIGHT_STRENGTH, ADDSET_DEHAZE_STRENGTH, + ADDSET_SHARP_GAMMA, ADDSET_PARAM_NUM // THIS IS USED AS A DELIMITER!! }; diff --git a/rtgui/adjuster.cc b/rtgui/adjuster.cc index 0d2c2961f..5182cd825 100644 --- a/rtgui/adjuster.cc +++ b/rtgui/adjuster.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "adjuster.h" #include @@ -631,21 +631,21 @@ void Adjuster::setSliderValue(double val) if (val >= logPivot) { double range = vMax - logPivot; double x = (val - logPivot) / range; - val = (vMin + mid) + std::log(x * (logBase - 1.0) + 1.0) / std::log(logBase) * mid; + val = (vMin + mid) + std::log1p(x * (logBase - 1.0)) / std::log(logBase) * mid; } else { double range = logPivot - vMin; double x = (logPivot - val) / range; - val = (vMin + mid) - std::log(x * (logBase - 1.0) + 1.0) / std::log(logBase) * mid; + val = (vMin + mid) - std::log1p(x * (logBase - 1.0)) / std::log(logBase) * mid; } } else { if (val >= logPivot) { double range = vMax - logPivot; double x = (val - logPivot) / range; - val = logPivot + std::log(x * (logBase - 1.0) + 1.0) / std::log(logBase) * range; + val = logPivot + std::log1p(x * (logBase - 1.0)) / std::log(logBase) * range; } else { double range = logPivot - vMin; double x = (logPivot - val) / range; - val = logPivot - std::log(x * (logBase - 1.0) + 1.0) / std::log(logBase) * range; + val = logPivot - std::log1p(x * (logBase - 1.0)) / std::log(logBase) * range; } } } diff --git a/rtgui/adjuster.h b/rtgui/adjuster.h index f57129bf1..52857a3d2 100644 --- a/rtgui/adjuster.h +++ b/rtgui/adjuster.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _ADJUSTER_H_ #define _ADJUSTER_H_ @@ -30,7 +30,7 @@ class AdjusterListener public: virtual ~AdjusterListener() = default; virtual void adjusterChanged (Adjuster* a, double newval) = 0; - virtual void adjusterAutoToggled (Adjuster* a, bool newval) = 0; + virtual void adjusterAutoToggled (Adjuster* a, bool newval) {} }; typedef double(*double2double_fun)(double val); diff --git a/rtgui/alignedmalloc.cc b/rtgui/alignedmalloc.cc index 91fe15a85..85517e5c0 100644 --- a/rtgui/alignedmalloc.cc +++ b/rtgui/alignedmalloc.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "config.h" diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc index 7222be05d..abb37b24d 100644 --- a/rtgui/batchqueue.cc +++ b/rtgui/batchqueue.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -667,7 +667,7 @@ rtengine::ProcessingJob* BatchQueue::imageReady(rtengine::IImagefloat* img) Glib::ustring fname; SaveFormat saveFormat; - if (processing->outFileName == "") { // auto file name + if (processing->outFileName.empty()) { // auto file name Glib::ustring s = calcAutoFileNameBase (processing->filename, processing->sequence); saveFormat = options.saveFormatBatch; fname = autoCompleteFileName (s, saveFormat.format); @@ -686,7 +686,7 @@ rtengine::ProcessingJob* BatchQueue::imageReady(rtengine::IImagefloat* img) //printf ("fname=%s, %s\n", fname.c_str(), removeExtension(fname).c_str()); - if (img && fname != "") { + if (img && !fname.empty()) { int err = 0; if (saveFormat.format == "tif") { @@ -811,7 +811,7 @@ Glib::ustring BatchQueue::calcAutoFileNameBase (const Glib::ustring& origFileNam break; } - Glib::ustring tok = ""; + Glib::ustring tok; while ((i < origFileName.size()) && !(origFileName[i] == '\\' || origFileName[i] == '/')) { tok = tok + origFileName[i++]; @@ -857,7 +857,7 @@ Glib::ustring BatchQueue::calcAutoFileNameBase (const Glib::ustring& origFileNam // constructing full output path // printf ("path=|%s|\n", options.savePath.c_str()); - Glib::ustring path = ""; + Glib::ustring path; if (options.saveUsePathTemplate) { unsigned int ix = 0; diff --git a/rtgui/batchqueue.h b/rtgui/batchqueue.h index 95d92aef2..f61b7b5c4 100644 --- a/rtgui/batchqueue.h +++ b/rtgui/batchqueue.h @@ -13,7 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _BATCHQUEUE_ #define _BATCHQUEUE_ @@ -29,6 +29,7 @@ #include "options.h" #include "threadutils.h" #include "thumbbrowserbase.h" +#include "../rtengine/noncopyable.h" class BatchQueueListener { @@ -44,7 +45,8 @@ class FileCatalog; class BatchQueue final : public ThumbBrowserBase, public rtengine::BatchProcessingListener, - public LWButtonListener + public LWButtonListener, + public rtengine::NonCopyable { public: explicit BatchQueue (FileCatalog* aFileCatalog); diff --git a/rtgui/batchqueuebuttonset.cc b/rtgui/batchqueuebuttonset.cc index f5be480e8..a8be9eedf 100644 --- a/rtgui/batchqueuebuttonset.cc +++ b/rtgui/batchqueuebuttonset.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "batchqueuebuttonset.h" @@ -27,6 +27,10 @@ Cairo::RefPtr BatchQueueButtonSet::cancelIcon; Cairo::RefPtr BatchQueueButtonSet::headIcon; Cairo::RefPtr BatchQueueButtonSet::tailIcon; +Glib::ustring BatchQueueButtonSet::moveHeadToolTip; +Glib::ustring BatchQueueButtonSet::moveEndToolTip; +Glib::ustring BatchQueueButtonSet::cancelJobToolTip; + BatchQueueButtonSet::BatchQueueButtonSet (BatchQueueEntry* myEntry) { @@ -34,10 +38,13 @@ BatchQueueButtonSet::BatchQueueButtonSet (BatchQueueEntry* myEntry) cancelIcon = Cairo::RefPtr(new RTSurface("cancel-small.png")); headIcon = Cairo::RefPtr(new RTSurface("goto-start-small.png")); tailIcon = Cairo::RefPtr(new RTSurface("goto-end-small.png")); + moveHeadToolTip = M("FILEBROWSER_POPUPMOVEHEAD"); + moveEndToolTip = M("FILEBROWSER_POPUPMOVEEND"); + cancelJobToolTip = M("FILEBROWSER_POPUPCANCELJOB"); iconsLoaded = true; } - add (new LWButton (headIcon, 8, myEntry, LWButton::Left, LWButton::Center, M("FILEBROWSER_POPUPMOVEHEAD"))); - add (new LWButton (tailIcon, 9, myEntry, LWButton::Left, LWButton::Center, M("FILEBROWSER_POPUPMOVEEND"))); - add (new LWButton (cancelIcon, 10, myEntry, LWButton::Right, LWButton::Center, M("FILEBROWSER_POPUPCANCELJOB"))); + add(new LWButton(headIcon, 8, myEntry, LWButton::Left, LWButton::Center, &moveHeadToolTip)); + add(new LWButton(tailIcon, 9, myEntry, LWButton::Left, LWButton::Center, &moveEndToolTip)); + add(new LWButton(cancelIcon, 10, myEntry, LWButton::Right, LWButton::Center, &cancelJobToolTip)); } diff --git a/rtgui/batchqueuebuttonset.h b/rtgui/batchqueuebuttonset.h index 66dab91a1..19479ccc1 100644 --- a/rtgui/batchqueuebuttonset.h +++ b/rtgui/batchqueuebuttonset.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _BATCHQUEUEBUTTONSET_ #define _BATCHQUEUEBUTTONSET_ @@ -34,6 +34,10 @@ public: static Cairo::RefPtr headIcon; static Cairo::RefPtr tailIcon; + static Glib::ustring moveHeadToolTip; + static Glib::ustring moveEndToolTip; + static Glib::ustring cancelJobToolTip; + explicit BatchQueueButtonSet (BatchQueueEntry* myEntry); }; diff --git a/rtgui/batchqueueentry.cc b/rtgui/batchqueueentry.cc index d52fe4305..424c8e486 100644 --- a/rtgui/batchqueueentry.cc +++ b/rtgui/batchqueueentry.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "batchqueueentry.h" @@ -40,7 +40,6 @@ BatchQueueEntry::BatchQueueEntry (rtengine::ProcessingJob* pjob, const rtengine: job(pjob), params(new rtengine::procparams::ProcParams(pparams)), progress(0), - outFileName(""), sequence(0), forceFormatOpts(false), fast_pipeline(job->fastPipeline()), @@ -148,7 +147,7 @@ void BatchQueueEntry::removeButtonSet () buttonSet = nullptr; } -std::vector > BatchQueueEntry::getIconsOnImageArea () +std::vector> BatchQueueEntry::getIconsOnImageArea () { std::vector > ret; @@ -160,7 +159,7 @@ std::vector > BatchQueueEntry::getIconsOnImageArea () return ret; } -void BatchQueueEntry::getIconSize (int& w, int& h) +void BatchQueueEntry::getIconSize (int& w, int& h) const { w = savedAsIcon->get_width (); @@ -168,10 +167,12 @@ void BatchQueueEntry::getIconSize (int& w, int& h) } -Glib::ustring BatchQueueEntry::getToolTip (int x, int y) +std::tuple BatchQueueEntry::getToolTip (int x, int y) const { // get the parent class' tooltip first - Glib::ustring tooltip = ThumbBrowserEntryBase::getToolTip(x, y); + Glib::ustring tooltip; + bool useMarkup; + std::tie(tooltip, useMarkup) = ThumbBrowserEntryBase::getToolTip(x, y); // add the saving param options if (!outFileName.empty()) { @@ -198,7 +199,7 @@ Glib::ustring BatchQueueEntry::getToolTip (int x, int y) } } - return tooltip; + return std::make_tuple(std::move(tooltip), useMarkup); } diff --git a/rtgui/batchqueueentry.h b/rtgui/batchqueueentry.h index f3e8c1336..03097e55e 100644 --- a/rtgui/batchqueueentry.h +++ b/rtgui/batchqueueentry.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _BATCHQUEUEENTRY_ #define _BATCHQUEUEENTRY_ @@ -26,6 +26,7 @@ #include "thumbbrowserentrybase.h" #include "thumbnail.h" #include "bqentryupdater.h" +#include "../rtengine/noncopyable.h" class BatchQueueEntry; struct BatchQueueEntryIdleHelper { @@ -34,7 +35,7 @@ struct BatchQueueEntryIdleHelper { int pending; }; -class BatchQueueEntry : public ThumbBrowserEntryBase, public BQEntryUpdateListener +class BatchQueueEntry : public ThumbBrowserEntryBase, public BQEntryUpdateListener, public rtengine::NonCopyable { guint8* opreview; @@ -68,9 +69,9 @@ public: void removeButtonSet (); - std::vector > getIconsOnImageArea () override; - void getIconSize (int& w, int& h) override; - Glib::ustring getToolTip (int x, int y) override; + std::vector> getIconsOnImageArea () override; + void getIconSize (int& w, int& h) const override; + std::tuple getToolTip (int x, int y) const override; // bqentryupdatelistener interface void updateImage (guint8* img, int w, int h, int origw, int origh, guint8* newOPreview) override; diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index b800907e9..9107aaaa8 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "batchqueuepanel.h" #include "options.h" diff --git a/rtgui/batchqueuepanel.h b/rtgui/batchqueuepanel.h index a1ee7326f..2f8e27057 100644 --- a/rtgui/batchqueuepanel.h +++ b/rtgui/batchqueuepanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _BATCHQUEUEPANEL_ #define _BATCHQUEUEPANEL_ diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index 1a0eaeb28..87320892e 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "multilangmgr.h" #include "batchtoolpanelcoord.h" @@ -152,6 +152,7 @@ void BatchToolPanelCoordinator::initSession () cacorrection->setAdjusterBehavior (false); sharpening->setAdjusterBehavior (false, false, false, false, false, false, false); prsharpening->setAdjusterBehavior (false, false, false, false, false, false, false); + pdSharpening->setAdjusterBehavior (false, false, false, false); sharpenEdge->setAdjusterBehavior (false, false); sharpenMicro->setAdjusterBehavior (false, false, false); epd->setAdjusterBehavior (false, false, false, false, false); diff --git a/rtgui/batchtoolpanelcoord.h b/rtgui/batchtoolpanelcoord.h index f5889f967..f03d1d4b2 100644 --- a/rtgui/batchtoolpanelcoord.h +++ b/rtgui/batchtoolpanelcoord.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __BATCHTOOLPANELCCORD__ #define __BATCHTOOLPANELCCORD__ diff --git a/rtgui/bayerpreprocess.cc b/rtgui/bayerpreprocess.cc index 35f36e83e..0c01213e7 100644 --- a/rtgui/bayerpreprocess.cc +++ b/rtgui/bayerpreprocess.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -143,10 +143,6 @@ void BayerPreProcess::adjusterChanged(Adjuster* a, double newval) } } -void BayerPreProcess::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void BayerPreProcess::setBatchMode(bool batchMode) { ToolPanel::setBatchMode(batchMode); diff --git a/rtgui/bayerpreprocess.h b/rtgui/bayerpreprocess.h index e06a46d31..5d2b101d9 100644 --- a/rtgui/bayerpreprocess.h +++ b/rtgui/bayerpreprocess.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _BAYERPREPROCESS_H_ #define _BAYERPREPROCESS_H_ @@ -47,7 +47,6 @@ public: void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; void adjusterChanged(Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void hotDeadPixelChanged(); void setAdjusterBehavior (bool linedenoiseadd, bool greenequiladd); diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index 6f38f4c43..aa09067e4 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "bayerprocess.h" @@ -729,7 +729,7 @@ void BayerProcess::FrameCountChanged(int n, int frameNum) imageNumber->remove_all(); imageNumber->append("1"); - for (int i = 2; i <= std::min(n, 4); ++i) { + for (int i = 2; i <= std::min(n, 6); ++i) { std::ostringstream entry; entry << i; imageNumber->append(entry.str()); diff --git a/rtgui/bayerprocess.h b/rtgui/bayerprocess.h index df0c39d00..893010e65 100644 --- a/rtgui/bayerprocess.h +++ b/rtgui/bayerprocess.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _BAYERPROCESS_H_ #define _BAYERPROCESS_H_ diff --git a/rtgui/bayerrawexposure.cc b/rtgui/bayerrawexposure.cc index f9027c09f..9d8f9fff8 100644 --- a/rtgui/bayerrawexposure.cc +++ b/rtgui/bayerrawexposure.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "bayerrawexposure.h" @@ -152,10 +152,6 @@ void BayerRAWExposure::adjusterChanged(Adjuster* a, double newval) } } -void BayerRAWExposure::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void BayerRAWExposure::checkBoxToggled (CheckBox* c, CheckValue newval) { if (c == PextwoGreen) { diff --git a/rtgui/bayerrawexposure.h b/rtgui/bayerrawexposure.h index 08d415838..5825383be 100644 --- a/rtgui/bayerrawexposure.h +++ b/rtgui/bayerrawexposure.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _BAYERRAWEXPOSURE_H_ #define _BAYERRAWEXPOSURE_H_ @@ -43,7 +43,6 @@ public: void setBatchMode (bool batchMode) override; void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled (Adjuster* a, bool newval) override; void checkBoxToggled (CheckBox* c, CheckValue newval) override; void setAdjusterBehavior (bool pexblackadd); void trimValues (rtengine::procparams::ProcParams* pp) override; diff --git a/rtgui/blackwhite.cc b/rtgui/blackwhite.cc index 3d5deb8f2..b5ecb96bd 100644 --- a/rtgui/blackwhite.cc +++ b/rtgui/blackwhite.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -1150,10 +1150,6 @@ void BlackWhite::adjusterChanged(Adjuster* a, double newval) } } -void BlackWhite::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void BlackWhite::updateRGBLabel () { if (!batchMode) { diff --git a/rtgui/blackwhite.h b/rtgui/blackwhite.h index dd45a7729..36234cda5 100644 --- a/rtgui/blackwhite.h +++ b/rtgui/blackwhite.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _BLACKWHITE_H_ #define _BLACKWHITE_H_ @@ -55,7 +55,6 @@ public: void updateRGBLabel (); void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled (Adjuster* a, bool newval) override; void setAdjusterBehavior (bool bwadd, bool bwgadd); void trimValues (rtengine::procparams::ProcParams* pp) override; void enabledcc_toggled (); diff --git a/rtgui/bqentryupdater.cc b/rtgui/bqentryupdater.cc index f5adf56f9..21a0f5ad0 100644 --- a/rtgui/bqentryupdater.cc +++ b/rtgui/bqentryupdater.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "bqentryupdater.h" #include @@ -100,13 +100,12 @@ void BatchQueueEntryUpdater::processThread () break; } - rtengine::IImage8* img = nullptr; bool newBuffer = false; if (current.thumbnail && current.pparams) { // the thumbnail and the pparams are provided, it means that we have to build the original preview image double tmpscale; - img = current.thumbnail->processThumbImage (*current.pparams, current.oh, tmpscale); + rtengine::IImage8* img = current.thumbnail->processThumbImage (*current.pparams, current.oh, tmpscale); //current.thumbnail->decreaseRef (); // WARNING: decreasing refcount (and maybe deleting) thumbnail, with or without processed image if (img) { diff --git a/rtgui/bqentryupdater.h b/rtgui/bqentryupdater.h index e25f5aed4..efd63f9de 100644 --- a/rtgui/bqentryupdater.h +++ b/rtgui/bqentryupdater.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _BQENTRYUPDATER_ #define _BQENTRYUPDATER_ diff --git a/rtgui/browserfilter.cc b/rtgui/browserfilter.cc index ab4c843a4..c6a8ae46b 100644 --- a/rtgui/browserfilter.cc +++ b/rtgui/browserfilter.cc @@ -14,16 +14,16 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "browserfilter.h" BrowserFilter::BrowserFilter () : - showTrash (true), - showNotTrash (true), - showOriginal (false), - multiselect (false), - exifFilterEnabled (false) + showTrash(true), + showNotTrash(true), + showOriginal(false), + exifFilterEnabled(false), + matchEqual(true) { for (int i = 0; i < 6; i++) { showRanked[i] = true; diff --git a/rtgui/browserfilter.h b/rtgui/browserfilter.h index 8880a364d..f5dac180e 100644 --- a/rtgui/browserfilter.h +++ b/rtgui/browserfilter.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _BROWSERFILTER_ #define _BROWSERFILTER_ @@ -33,13 +33,11 @@ public: bool showOriginal; bool showEdited[2]; bool showRecentlySaved[2]; - bool multiselect; - - Glib::ustring queryString; - Glib::ustring queryFileName; bool exifFilterEnabled; + bool matchEqual; ExifFilterSettings exifFilter; + std::vector vFilterStrings; BrowserFilter (); }; diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 032a3a4f0..e98037040 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "cacheimagedata.h" #include @@ -24,12 +24,37 @@ #include "../rtengine/procparams.h" -CacheImageData::CacheImageData () - : md5(""), supported(false), format(FT_Invalid), rankOld(-1), inTrashOld(false), recentlySaved(false), - timeValid(false), year(0), month(0), day(0), hour(0), min(0), sec(0), exifValid(false), frameCount(1), - fnumber(0.0), shutter(0.0), focalLen(0.0), focalLen35mm(0.0), focusDist(0.f), iso(0), isHDR (false), - isPixelShift (false), sensortype(rtengine::ST_NONE), sampleFormat(rtengine::IIOSF_UNKNOWN), - redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), rotate(0), thumbImgType(0) +CacheImageData::CacheImageData() : + supported(false), + format(FT_Invalid), + rankOld(-1), + inTrashOld(false), + recentlySaved(false), + timeValid(false), + year(0), + month(0), + day(0), + hour(0), + min(0), + sec(0), + exifValid(false), + frameCount(1), + fnumber(0.0), + shutter(0.0), + focalLen(0.0), + focalLen35mm(0.0), + focusDist(0.f), + iso(0), + rating(0), + isHDR (false), + isPixelShift (false), + sensortype(rtengine::ST_NONE), + sampleFormat(rtengine::IIOSF_UNKNOWN), + redAWBMul(-1.0), + greenAWBMul(-1.0), + blueAWBMul(-1.0), + rotate(0), + thumbImgType(0) { } @@ -66,6 +91,10 @@ int CacheImageData::load (const Glib::ustring& fname) rankOld = keyFile.get_integer ("General", "Rank"); } + if (keyFile.has_key ("General", "Rating")) { + rating = keyFile.get_integer ("General", "Rating"); + } + if (keyFile.has_key ("General", "InTrash")) { inTrashOld = keyFile.get_boolean ("General", "InTrash"); } @@ -227,6 +256,7 @@ int CacheImageData::save (const Glib::ustring& fname) keyFile.set_boolean ("General", "Supported", supported); keyFile.set_integer ("General", "Format", format); keyFile.set_boolean ("General", "RecentlySaved", recentlySaved); + keyFile.set_integer ("General", "Rating", rating); // remove the old implementation of Rank and InTrash from cache if (keyFile.has_key ("General", "Rank")) { diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index 6fe55c460..ed11e5de1 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CACHEIMAGEDATA_ #define _CACHEIMAGEDATA_ @@ -54,6 +54,7 @@ public: double focalLen, focalLen35mm; float focusDist; unsigned iso; + int rating; bool isHDR; bool isPixelShift; int sensortype; @@ -103,6 +104,7 @@ public: std::string getLens() const override { return lens; } std::string getOrientation() const override { return ""; } // TODO Glib::ustring getFileName() const override { return ""; } + int getRating () const override { return rating; } // FIXME-piotr : missing rating bool getPixelShift () const override { return isPixelShift; } bool getHDR() const override { return isHDR; } std::string getImageType() const override { return isPixelShift ? "PS" : isHDR ? "HDR" : "STD"; } diff --git a/rtgui/cachemanager.cc b/rtgui/cachemanager.cc index b270c3795..419538656 100644 --- a/rtgui/cachemanager.cc +++ b/rtgui/cachemanager.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtgui/cachemanager.h b/rtgui/cachemanager.h index 99c732e88..3e987866d 100644 --- a/rtgui/cachemanager.h +++ b/rtgui/cachemanager.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CACHEMANAGER_ #define _CACHEMANAGER_ diff --git a/rtgui/cacorrection.cc b/rtgui/cacorrection.cc index c91eec145..971c0a284 100644 --- a/rtgui/cacorrection.cc +++ b/rtgui/cacorrection.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -101,10 +101,6 @@ void CACorrection::adjusterChanged (Adjuster* a, double newval) } } -void CACorrection::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void CACorrection::setAdjusterBehavior (bool badd) { diff --git a/rtgui/cacorrection.h b/rtgui/cacorrection.h index 198037060..f6e1f89e3 100644 --- a/rtgui/cacorrection.h +++ b/rtgui/cacorrection.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CACORRECTION_H_ #define _CACORRECTION_H_ @@ -40,7 +40,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void setAdjusterBehavior (bool badd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; diff --git a/rtgui/checkbox.cc b/rtgui/checkbox.cc index 1e3c2b61e..e05ba061a 100644 --- a/rtgui/checkbox.cc +++ b/rtgui/checkbox.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtgui/checkbox.h b/rtgui/checkbox.h index b5ab4945f..48324d4c8 100644 --- a/rtgui/checkbox.h +++ b/rtgui/checkbox.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CHECKBOX_H_ #define _CHECKBOX_H_ diff --git a/rtgui/chmixer.cc b/rtgui/chmixer.cc index 4a3411e8b..4b243f13c 100644 --- a/rtgui/chmixer.cc +++ b/rtgui/chmixer.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "chmixer.h" @@ -182,10 +182,6 @@ void ChMixer::adjusterChanged(Adjuster* a, double newval) } } -void ChMixer::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void ChMixer::enabledChanged() { if (listener) { diff --git a/rtgui/chmixer.h b/rtgui/chmixer.h index 7e372cbc2..94f54ed3d 100644 --- a/rtgui/chmixer.h +++ b/rtgui/chmixer.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CHMIXER_H_ #define _CHMIXER_H_ @@ -42,7 +42,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void setAdjusterBehavior (bool rgbadd); void trimValues (rtengine::procparams::ProcParams* pp) override; void enabledChanged() override; diff --git a/rtgui/clipboard.cc b/rtgui/clipboard.cc index c8eb94d7b..4cd50f574 100644 --- a/rtgui/clipboard.cc +++ b/rtgui/clipboard.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "clipboard.h" diff --git a/rtgui/clipboard.h b/rtgui/clipboard.h index 74c9f6770..4c0ec452f 100644 --- a/rtgui/clipboard.h +++ b/rtgui/clipboard.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CLIPBOARD_ #define _CLIPBOARD_ diff --git a/rtgui/coarsepanel.cc b/rtgui/coarsepanel.cc index 92c312554..c64d53017 100644 --- a/rtgui/coarsepanel.cc +++ b/rtgui/coarsepanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "coarsepanel.h" diff --git a/rtgui/coarsepanel.h b/rtgui/coarsepanel.h index bd4668eea..2da56b904 100644 --- a/rtgui/coarsepanel.h +++ b/rtgui/coarsepanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __COARSEPANEL__ #define __COARSEPANEL__ diff --git a/rtgui/colorappearance.cc b/rtgui/colorappearance.cc index f78a1f32b..f8eb736d4 100644 --- a/rtgui/colorappearance.cc +++ b/rtgui/colorappearance.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtgui/colorappearance.h b/rtgui/colorappearance.h index 3f95d9f74..da2e3c8b9 100644 --- a/rtgui/colorappearance.h +++ b/rtgui/colorappearance.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _COLORAPPEARANCE_H_ #define _COLORAPPEARANCE_H_ diff --git a/rtgui/coloredbar.cc b/rtgui/coloredbar.cc index 7d623949e..ca9a381cf 100644 --- a/rtgui/coloredbar.cc +++ b/rtgui/coloredbar.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "coloredbar.h" diff --git a/rtgui/coloredbar.h b/rtgui/coloredbar.h index 010d0dcb6..089dfa8cd 100644 --- a/rtgui/coloredbar.h +++ b/rtgui/coloredbar.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _COLOREDBAR_ #define _COLOREDBAR_ diff --git a/rtgui/colorprovider.h b/rtgui/colorprovider.h index ab6fb2865..feea792b6 100644 --- a/rtgui/colorprovider.h +++ b/rtgui/colorprovider.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _COLORPROVIDER_ #define _COLORPROVIDER_ diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index 7ca9a7305..e164739e5 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -1372,10 +1372,6 @@ void ColorToning::adjusterChanged(Adjuster* a, double newval) } } -void ColorToning::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void ColorToning::setBatchMode (bool batchMode) { ToolPanel::setBatchMode (batchMode); diff --git a/rtgui/colortoning.h b/rtgui/colortoning.h index abb44d09c..faba1e383 100644 --- a/rtgui/colortoning.h +++ b/rtgui/colortoning.h @@ -33,7 +33,6 @@ public: void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; void trimValues (rtengine::procparams::ProcParams* pp) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled (Adjuster* a, bool newval) override; void setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd); void neutral_pressed (); //void neutralCurves_pressed (); diff --git a/rtgui/config.h.in b/rtgui/config.h.in index 2d1f41dbc..95217b689 100644 --- a/rtgui/config.h.in +++ b/rtgui/config.h.in @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __CONFIG_H__ diff --git a/rtgui/coordinateadjuster.cc b/rtgui/coordinateadjuster.cc index 2525a07e5..ebf36b7e7 100644 --- a/rtgui/coordinateadjuster.cc +++ b/rtgui/coordinateadjuster.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "coordinateadjuster.h" @@ -23,7 +23,7 @@ #include "curveeditorgroup.h" Axis::Axis() - : label(""), decimal(5), increment(0.001), pageIncrement(0.01), rangeLowerBound(0.), rangeUpperBound(1.) + : decimal(5), increment(0.001), pageIncrement(0.01), rangeLowerBound(0.), rangeUpperBound(1.) {} Axis::Axis(Glib::ustring label, unsigned int decimal, double increment, double pageIncrement, double valMin = 0.0, double valMax = 1.0) diff --git a/rtgui/coordinateadjuster.h b/rtgui/coordinateadjuster.h index 33ea92bb2..d705915ab 100644 --- a/rtgui/coordinateadjuster.h +++ b/rtgui/coordinateadjuster.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _COORDINATEADJUSTER_ #define _COORDINATEADJUSTER_ diff --git a/rtgui/crop.cc b/rtgui/crop.cc index 781a916a1..b1780538e 100644 --- a/rtgui/crop.cc +++ b/rtgui/crop.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "crop.h" @@ -1400,24 +1400,19 @@ void Crop::cropResized (int &x, int &y, int& x2, int& y2) y2 = maxh - 1; } - int X, Y; int W; if (x < x2) { W = x2 - x + 1; - X = x; } else { W = x - x2 + 1; - X = x2; } - int H; + int Y; if (y < y2) { - H = y2 - y + 1; Y = y; } else { - H = y - y2 + 1; Y = y2; } @@ -1425,6 +1420,7 @@ void Crop::cropResized (int &x, int &y, int& x2, int& y2) W = maxw; } + int H; if (fixr->get_active()) { double r = getRatio (); @@ -1457,6 +1453,7 @@ void Crop::cropResized (int &x, int &y, int& x2, int& y2) } } + int X; if (x < x2) { W = x2 - x + 1; X = x; diff --git a/rtgui/crop.h b/rtgui/crop.h index ed0661598..1bbad548d 100644 --- a/rtgui/crop.h +++ b/rtgui/crop.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CROP_H_ #define _CROP_H_ diff --git a/rtgui/cropguilistener.h b/rtgui/cropguilistener.h index 7a791ef93..c20d6556a 100644 --- a/rtgui/cropguilistener.h +++ b/rtgui/cropguilistener.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __CROPGUILISTENER__ #define __CROPGUILISTENER__ diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc index ab2f3626c..c6ecde027 100644 --- a/rtgui/crophandler.cc +++ b/rtgui/crophandler.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "crophandler.h" #undef THREAD_PRIORITY_NORMAL diff --git a/rtgui/crophandler.h b/rtgui/crophandler.h index e90b96c25..77355b868 100644 --- a/rtgui/crophandler.h +++ b/rtgui/crophandler.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __CROPHANDLER__ #define __CROPHANDLER__ diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index 4b2c1a6cc..ef682cf1f 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -38,13 +38,20 @@ using namespace rtengine; +bool CropWindow::initialized = false; + +Glib::ustring CropWindow::zoomOuttt; +Glib::ustring CropWindow::zoomIntt; +Glib::ustring CropWindow::zoom100tt; +Glib::ustring CropWindow::closett; + CropWindow::CropWindow (ImageArea* parent, bool isLowUpdatePriority_, bool isDetailWindow) : ObjectMOBuffer(parent), state(SNormal), press_x(0), press_y(0), action_x(0), action_y(0), pickedObject(-1), pickModifierKey(0), rot_deg(0), onResizeArea(false), deleted(false), fitZoomEnabled(true), fitZoom(false), cursor_type(CSArrow), /*isLowUpdatePriority(isLowUpdatePriority_),*/ hoveredPicker(nullptr), cropLabel(Glib::ustring("100%")), backColor(options.bgcolor), decorated(true), isFlawnOver(false), titleHeight(30), sideBorderWidth(3), lowerBorderWidth(3), upperBorderWidth(1), sepWidth(2), xpos(30), ypos(30), width(0), height(0), imgAreaX(0), imgAreaY(0), imgAreaW(0), imgAreaH(0), imgX(-1), imgY(-1), imgW(1), imgH(1), iarea(parent), cropZoom(0), zoomVersion(0), exposeVersion(0), cropgl(nullptr), - pmlistener(nullptr), pmhlistener(nullptr), observedCropWin(nullptr), + pmlistener(nullptr), pmhlistener(nullptr), scrollAccum(0.0), observedCropWin(nullptr), crop_custom_ratio(0.f) { initZoomSteps(); @@ -61,11 +68,18 @@ CropWindow::CropWindow (ImageArea* parent, bool isLowUpdatePriority_, bool isDet titleHeight = ih; - bZoomOut = new LWButton (Cairo::RefPtr(new RTSurface("magnifier-minus-small.png")), 0, nullptr, LWButton::Left, LWButton::Center, "Zoom Out"); - bZoomIn = new LWButton (Cairo::RefPtr(new RTSurface("magnifier-plus-small.png")), 1, nullptr, LWButton::Left, LWButton::Center, "Zoom In"); - bZoom100 = new LWButton (Cairo::RefPtr(new RTSurface("magnifier-1to1-small.png")), 2, nullptr, LWButton::Left, LWButton::Center, "Zoom 100/%"); - //bZoomFit = new LWButton (Cairo::RefPtr(new RTSurface("magnifier-fit.png")), 3, NULL, LWButton::Left, LWButton::Center, "Zoom Fit"); - bClose = new LWButton (Cairo::RefPtr(new RTSurface("cancel-small.png")), 4, nullptr, LWButton::Right, LWButton::Center, "Close"); + if (!initialized) { + zoomOuttt = "Zoom Out"; + zoomIntt = "Zoom In"; + zoom100tt = "Zoom 100/%"; + closett = "Close"; + initialized = true; + } + bZoomOut = new LWButton(Cairo::RefPtr(new RTSurface("magnifier-minus-small.png")), 0, nullptr, LWButton::Left, LWButton::Center, &zoomOuttt); + bZoomIn = new LWButton(Cairo::RefPtr(new RTSurface("magnifier-plus-small.png")), 1, nullptr, LWButton::Left, LWButton::Center, &zoomIntt); + bZoom100 = new LWButton(Cairo::RefPtr(new RTSurface("magnifier-1to1-small.png")), 2, nullptr, LWButton::Left, LWButton::Center, &zoom100tt); + //bZoomFit = new LWButton (Cairo::RefPtr(new RTSurface("magnifier-fit.png")), 3, NULL, LWButton::Left, LWButton::Center, "Zoom Fit"); + bClose = new LWButton(Cairo::RefPtr(new RTSurface("cancel-small.png")), 4, nullptr, LWButton::Right, LWButton::Center, &closett); buttonSet.add (bZoomOut); buttonSet.add (bZoomIn); @@ -281,11 +295,16 @@ void CropWindow::scroll (int state, GdkScrollDirection direction, int x, int y, } else { delta = deltaY; } - if (delta == 0.0 && direction == GDK_SCROLL_SMOOTH) { - // sometimes this case happens. To avoid zooming into the wrong direction in this case, we just do nothing - return; + + if (direction == GDK_SCROLL_SMOOTH) { + scrollAccum += delta; + //Only change zoom level if we've accumulated +/- 1.0 of deltas. This conditional handles the previous delta=0.0 case + if (abs(scrollAccum) < 1.0) { + return; + } } - bool isUp = direction == GDK_SCROLL_UP || (direction == GDK_SCROLL_SMOOTH && delta < 0.0); + bool isUp = direction == GDK_SCROLL_UP || (direction == GDK_SCROLL_SMOOTH && scrollAccum < 0.0); + scrollAccum = 0.0; if ((state & GDK_CONTROL_MASK) && onArea(ColorPicker, x, y)) { // resizing a color picker if (isUp) { @@ -390,6 +409,26 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) action_y = 0; needRedraw = true; } + } else if (iarea->getToolMode () == TMHand + && editSubscriber + && cropgl + && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) + && editSubscriber->getEditingType() == ET_OBJECTS + && iarea->getObject() >= 0 + ) + { + needRedraw = editSubscriber->button1Pressed(bstate); + if (editSubscriber->isDragging()) { + state = SEditDrag1; + } else if (editSubscriber->isPicking()) { + state = SEditPick1; + pickedObject = iarea->getObject(); + pickModifierKey = bstate; + } + press_x = x; + press_y = y; + action_x = 0; + action_y = 0; } else if (onArea (CropTopLeft, x, y)) { state = SResizeTL; press_x = x; @@ -463,7 +502,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) cropgl->cropInit (cropHandler.cropParams->x, cropHandler.cropParams->y, cropHandler.cropParams->w, cropHandler.cropParams->h); } else if (iarea->getToolMode () == TMHand) { if (editSubscriber) { - if ((cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && (editSubscriber->getEditingType() == ET_PIPETTE && (bstate & GDK_CONTROL_MASK))) || editSubscriber->getEditingType() == ET_OBJECTS) { + if ((cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && editSubscriber->getEditingType() == ET_PIPETTE && (bstate & GDK_CONTROL_MASK))) { needRedraw = editSubscriber->button1Pressed(bstate); if (editSubscriber->isDragging()) { state = SEditDrag1; @@ -478,7 +517,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) action_y = 0; } } - if (state != SEditDrag1) { + if (state != SEditDrag1 && state != SEditPick1) { state = SCropImgMove; press_x = x; press_y = y; @@ -1242,6 +1281,8 @@ void CropWindow::updateCursor (int x, int y) newType = CSArrow; } else if (onArea (CropToolBar, x, y)) { newType = CSMove; + } else if (iarea->getObject() > -1 && editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) { + newType = editSubscriber->getCursor(iarea->getObject()); } else if (onArea (CropResize, x, y)) { newType = CSResizeDiagonal; } else if (tm == TMColorPicker && hoveredPicker) { @@ -1831,11 +1872,9 @@ void CropWindow::expose (Cairo::RefPtr cr) EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS && bufferCreated()) { - if (this != iarea->mainCropWindow) { - cr->set_line_width (0.); - cr->rectangle (x + imgAreaX, y + imgAreaY, imgAreaW, imgAreaH); - cr->clip(); - } + cr->set_line_width (0.); + cr->rectangle (x + imgAreaX, y + imgAreaY, imgAreaW, imgAreaH); + cr->clip(); // drawing Subscriber's visible geometry const std::vector visibleGeom = editSubscriber->getVisibleGeometry(); @@ -2184,8 +2223,6 @@ void CropWindow::updateHoveredPicker (rtengine::Coord *imgPos) } rtengine::Coord cropPos; - float r=0.f, g=0.f, b=0.f; - float rpreview=0.f, gpreview=0.f, bpreview=0.f; if (imgPos) { imageCoordToCropImage(imgPos->x, imgPos->y, cropPos.x, cropPos.y); hoveredPicker->setPosition (*imgPos); @@ -2201,6 +2238,8 @@ void CropWindow::updateHoveredPicker (rtengine::Coord *imgPos) MyMutex::MyLock lock(cropHandler.cimg); if (validity == LockableColorPicker::Validity::INSIDE) { + float r=0.f, g=0.f, b=0.f; + float rpreview=0.f, gpreview=0.f, bpreview=0.f; cropHandler.colorPick(cropPos, r, g, b, rpreview, gpreview, bpreview, hoveredPicker->getSize()); hoveredPicker->setRGB (r, g, b, rpreview, gpreview, bpreview); } diff --git a/rtgui/cropwindow.h b/rtgui/cropwindow.h index 287cbf1ef..99b0fd897 100644 --- a/rtgui/cropwindow.h +++ b/rtgui/cropwindow.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CROPWINDOW_ #define _CROPWINDOW_ @@ -31,6 +31,7 @@ #include "cursormanager.h" #include "editbuffer.h" #include "editcoordsys.h" +#include "../rtengine/noncopyable.h" class CropWindow; @@ -45,8 +46,14 @@ public: }; class ImageArea; -class CropWindow : public LWButtonListener, public CropDisplayHandler, public EditCoordSystem, public ObjectMOBuffer +class CropWindow : public LWButtonListener, public CropDisplayHandler, public EditCoordSystem, public ObjectMOBuffer, public rtengine::NonCopyable { + static bool initialized; + + static Glib::ustring zoomOuttt; + static Glib::ustring zoomIntt; + static Glib::ustring zoom100tt; + static Glib::ustring closett; // state management ImgEditState state; // current state of user (see enum State) @@ -95,6 +102,7 @@ class CropWindow : public LWButtonListener, public CropDisplayHandler, public Ed PointerMotionListener* pmlistener; PointerMotionListener* pmhlistener; std::list listeners; + double scrollAccum; CropWindow* observedCropWin; // Pointer to the currently active detail CropWindow diff --git a/rtgui/cursormanager.cc b/rtgui/cursormanager.cc index 3181d288e..76b4eabfb 100644 --- a/rtgui/cursormanager.cc +++ b/rtgui/cursormanager.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "cursormanager.h" diff --git a/rtgui/cursormanager.h b/rtgui/cursormanager.h index 111652726..aec5110d1 100644 --- a/rtgui/cursormanager.h +++ b/rtgui/cursormanager.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CURSORMANAGER_ #define _CURSORMANAGER_ diff --git a/rtgui/curveeditor.cc b/rtgui/curveeditor.cc index 528378423..2b3c100e0 100644 --- a/rtgui/curveeditor.cc +++ b/rtgui/curveeditor.cc @@ -13,7 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "curveeditor.h" #include "curveeditorgroup.h" diff --git a/rtgui/curveeditor.h b/rtgui/curveeditor.h index 1227edc0f..bdd6d6b48 100644 --- a/rtgui/curveeditor.h +++ b/rtgui/curveeditor.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CURVEEDITOR_ #define _CURVEEDITOR_ @@ -25,6 +25,7 @@ #include "editcallbacks.h" #include "mydiagonalcurve.h" #include "myflatcurve.h" +#include "../rtengine/noncopyable.h" class CurveEditorGroup; class CurveEditorSubGroup; @@ -38,7 +39,7 @@ class CurveEditorSubGroup; /** @brief This class is an interface between RT and the curve editor group * It handles the methods related to a specific curve. It is created by CurveEditorGroup::addCurve */ -class CurveEditor : public EditSubscriber +class CurveEditor : public EditSubscriber, public rtengine::NonCopyable { friend class CurveEditorGroup; diff --git a/rtgui/curveeditorgroup.cc b/rtgui/curveeditorgroup.cc index 10aff907c..0e7205518 100644 --- a/rtgui/curveeditorgroup.cc +++ b/rtgui/curveeditorgroup.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * Class created by Jean-Christophe FRISCH, aka 'Hombre' */ @@ -397,7 +397,7 @@ void CurveEditorGroup::setUnChanged (bool uc, CurveEditor* ce) } } -CurveEditorSubGroup::CurveEditorSubGroup(Glib::ustring& curveDir) : curveDir(curveDir), lastFilename(""), valLinear(0), valUnchanged(0), parent(nullptr) +CurveEditorSubGroup::CurveEditorSubGroup(Glib::ustring& curveDir) : curveDir(curveDir), valLinear(0), valUnchanged(0), parent(nullptr) { leftBar = nullptr; bottomBar = nullptr; diff --git a/rtgui/curveeditorgroup.h b/rtgui/curveeditorgroup.h index 80a1a95a4..6f7b98d9b 100644 --- a/rtgui/curveeditorgroup.h +++ b/rtgui/curveeditorgroup.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CURVEEDITORGROUP_ #define _CURVEEDITORGROUP_ @@ -70,7 +70,7 @@ public: * dialogs. */ - CurveEditorGroup(Glib::ustring& curveDir, Glib::ustring groupLabel = ""); + explicit CurveEditorGroup(Glib::ustring& curveDir, Glib::ustring groupLabel = ""); ~CurveEditorGroup() override; void newLine(); void curveListComplete(); diff --git a/rtgui/curvelistener.h b/rtgui/curvelistener.h index 3c85db712..05a9a4e99 100644 --- a/rtgui/curvelistener.h +++ b/rtgui/curvelistener.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _CURVELISTENER_ #define _CURVELISTENER_ diff --git a/rtgui/darkframe.cc b/rtgui/darkframe.cc index 77e9c53a6..af7ffeace 100644 --- a/rtgui/darkframe.cc +++ b/rtgui/darkframe.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -125,7 +125,7 @@ void DarkFrame::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi Glib::ustring fname = Glib::path_get_basename(dfp->GetCurrentImageFilePath()); Glib::ustring filetype; - if (fname != "") { + if (!fname.empty()) { // get image filetype, set filter to the same as current image's filetype std::string::size_type idx; idx = fname.rfind('.'); diff --git a/rtgui/darkframe.h b/rtgui/darkframe.h index c385a2153..c576712a8 100644 --- a/rtgui/darkframe.h +++ b/rtgui/darkframe.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _DARKFRAME_H_ #define _DARKFRAME_H_ diff --git a/rtgui/defringe.cc b/rtgui/defringe.cc index 7d29b8c8f..659d41960 100644 --- a/rtgui/defringe.cc +++ b/rtgui/defringe.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -164,10 +164,6 @@ void Defringe::adjusterChanged(Adjuster* a, double newval) } } -void Defringe::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void Defringe::enabledChanged () { diff --git a/rtgui/defringe.h b/rtgui/defringe.h index 1aa6cc303..8a6eb0753 100644 --- a/rtgui/defringe.h +++ b/rtgui/defringe.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _DEFRINGE_H_ #define _DEFRINGE_H_ @@ -50,7 +50,6 @@ public: void curveChanged () override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void enabledChanged () override; void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) override; diff --git a/rtgui/dehaze.cc b/rtgui/dehaze.cc index 8204210db..6b7fcd64f 100644 --- a/rtgui/dehaze.cc +++ b/rtgui/dehaze.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -36,6 +36,7 @@ Dehaze::Dehaze(): FoldableToolPanel(this, "dehaze", M("TP_DEHAZE_LABEL"), false, EvDehazeStrength = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_STRENGTH"); EvDehazeShowDepthMap = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP"); EvDehazeDepth = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_DEPTH"); + EvDehazeLuminance = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_LUMINANCE"); strength = Gtk::manage(new Adjuster(M("TP_DEHAZE_STRENGTH"), 0., 100., 1., 50.)); strength->setAdjusterListener(this); @@ -45,12 +46,17 @@ Dehaze::Dehaze(): FoldableToolPanel(this, "dehaze", M("TP_DEHAZE_LABEL"), false, depth->setAdjusterListener(this); depth->show(); + luminance = Gtk::manage(new Gtk::CheckButton(M("TP_DEHAZE_LUMINANCE"))); + luminance->signal_toggled().connect(sigc::mem_fun(*this, &Dehaze::luminanceChanged)); + luminance->show(); + showDepthMap = Gtk::manage(new Gtk::CheckButton(M("TP_DEHAZE_SHOW_DEPTH_MAP"))); showDepthMap->signal_toggled().connect(sigc::mem_fun(*this, &Dehaze::showDepthMapChanged)); showDepthMap->show(); pack_start(*strength); pack_start(*depth); + pack_start(*luminance); pack_start(*showDepthMap); } @@ -64,12 +70,14 @@ void Dehaze::read(const ProcParams *pp, const ParamsEdited *pedited) depth->setEditedState(pedited->dehaze.depth ? Edited : UnEdited); set_inconsistent(multiImage && !pedited->dehaze.enabled); showDepthMap->set_inconsistent(!pedited->dehaze.showDepthMap); + luminance->set_inconsistent(!pedited->dehaze.luminance); } setEnabled(pp->dehaze.enabled); strength->setValue(pp->dehaze.strength); depth->setValue(pp->dehaze.depth); showDepthMap->set_active(pp->dehaze.showDepthMap); + luminance->set_active(pp->dehaze.luminance); enableListener(); } @@ -81,12 +89,14 @@ void Dehaze::write(ProcParams *pp, ParamsEdited *pedited) pp->dehaze.depth = depth->getValue(); pp->dehaze.enabled = getEnabled(); pp->dehaze.showDepthMap = showDepthMap->get_active(); + pp->dehaze.luminance = luminance->get_active(); if (pedited) { pedited->dehaze.strength = strength->getEditedState(); pedited->dehaze.depth = depth->getEditedState(); pedited->dehaze.enabled = !get_inconsistent(); pedited->dehaze.showDepthMap = !showDepthMap->get_inconsistent(); + pedited->dehaze.luminance = !luminance->get_inconsistent(); } } @@ -138,6 +148,12 @@ void Dehaze::showDepthMapChanged() } } +void Dehaze::luminanceChanged() +{ + if (listener) { + listener->panelChanged(EvDehazeLuminance, luminance->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } +} void Dehaze::setBatchMode(bool batchMode) { diff --git a/rtgui/dehaze.h b/rtgui/dehaze.h index 322e0bf0c..6a9d31cd1 100644 --- a/rtgui/dehaze.h +++ b/rtgui/dehaze.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once @@ -28,12 +28,14 @@ class Dehaze: public ToolParamBlock, public AdjusterListener, public FoldableToo private: Adjuster *strength; Adjuster *depth; - Gtk::CheckButton *showDepthMap; + Gtk::CheckButton *showDepthMap; + Gtk::CheckButton *luminance; rtengine::ProcEvent EvDehazeEnabled; rtengine::ProcEvent EvDehazeStrength; rtengine::ProcEvent EvDehazeDepth; rtengine::ProcEvent EvDehazeShowDepthMap; + rtengine::ProcEvent EvDehazeLuminance; public: @@ -47,7 +49,7 @@ public: void adjusterChanged(Adjuster *a, double newval) override; void enabledChanged() override; void showDepthMapChanged(); + void luminanceChanged(); void setAdjusterBehavior(bool strengthAdd); - void adjusterAutoToggled(Adjuster* a, bool newval) override {} }; diff --git a/rtgui/diagonalcurveeditorsubgroup.cc b/rtgui/diagonalcurveeditorsubgroup.cc index 86ff26bb4..21b42a6ce 100644 --- a/rtgui/diagonalcurveeditorsubgroup.cc +++ b/rtgui/diagonalcurveeditorsubgroup.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "clipboard.h" @@ -1246,10 +1246,6 @@ void DiagonalCurveEditorSubGroup::adjusterChanged(Adjuster* a, double newval) parent->curveChanged (); } -void DiagonalCurveEditorSubGroup::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - /* * Listener called when the mouse is over a parametric curve's slider */ diff --git a/rtgui/diagonalcurveeditorsubgroup.h b/rtgui/diagonalcurveeditorsubgroup.h index 39cc86973..077ef590e 100644 --- a/rtgui/diagonalcurveeditorsubgroup.h +++ b/rtgui/diagonalcurveeditorsubgroup.h @@ -14,17 +14,18 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _DIAGONALCURVEEDITORSUBGROUP_ #define _DIAGONALCURVEEDITORSUBGROUP_ #include #include "curveeditorgroup.h" +#include "../rtengine/noncopyable.h" class DiagonalCurveEditor; -class DiagonalCurveEditorSubGroup : public CurveEditorSubGroup, public SHCListener, public AdjusterListener +class DiagonalCurveEditorSubGroup : public CurveEditorSubGroup, public SHCListener, public AdjusterListener, public rtengine::NonCopyable { friend class DiagonalCurveEditor; @@ -105,7 +106,6 @@ protected: const std::vector getCurveFromGUI (int type) override; void shcChanged () override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; bool adjusterEntered (GdkEventCrossing* ev, int ac); bool adjusterLeft (GdkEventCrossing* ev, int ac); void setSubGroupRangeLabels(Glib::ustring r1, Glib::ustring r2, Glib::ustring r3, Glib::ustring r4); diff --git a/rtgui/dirbrowser.cc b/rtgui/dirbrowser.cc index fcc40abc9..32361d5c5 100644 --- a/rtgui/dirbrowser.cc +++ b/rtgui/dirbrowser.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "dirbrowser.h" diff --git a/rtgui/dirbrowser.h b/rtgui/dirbrowser.h index 15b6dd201..68422f8be 100644 --- a/rtgui/dirbrowser.h +++ b/rtgui/dirbrowser.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _DIRBROWSER_ #define _DIRBROWSER_ diff --git a/rtgui/dirpyrdenoise.cc b/rtgui/dirpyrdenoise.cc index c60c06243..2a0bba596 100644 --- a/rtgui/dirpyrdenoise.cc +++ b/rtgui/dirpyrdenoise.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -988,10 +988,6 @@ void DirPyrDenoise::adjusterChanged(Adjuster* a, double newval) } } -void DirPyrDenoise::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void DirPyrDenoise::enabledChanged () { diff --git a/rtgui/dirpyrdenoise.h b/rtgui/dirpyrdenoise.h index de7dee800..a513eb262 100644 --- a/rtgui/dirpyrdenoise.h +++ b/rtgui/dirpyrdenoise.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _DIRPYRDENOISE_H_ #define _DIRPYRDENOISE_H_ @@ -51,7 +51,6 @@ public: void autoOpenCurve () override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void enabledChanged () override; void medianChanged (); void chromaChanged (double autchroma, double autred, double autblue) override; diff --git a/rtgui/dirpyrequalizer.cc b/rtgui/dirpyrequalizer.cc index 5f557c0f1..fc03c83ad 100644 --- a/rtgui/dirpyrequalizer.cc +++ b/rtgui/dirpyrequalizer.cc @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * (C) 2010 Emil Martinec */ @@ -373,10 +373,6 @@ void DirPyrEqualizer::adjusterChanged(Adjuster* a, double newval) } } -void DirPyrEqualizer::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void DirPyrEqualizer::enabledChanged () { diff --git a/rtgui/dirpyrequalizer.h b/rtgui/dirpyrequalizer.h index d7903116b..e236dc29b 100644 --- a/rtgui/dirpyrequalizer.h +++ b/rtgui/dirpyrequalizer.h @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * (C) 2010 Emil Martinec */ @@ -65,7 +65,6 @@ public: void trimValues (rtengine::procparams::ProcParams* pp) override; void cbdlMethodChanged(); void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void enabledChanged() override; void gamutlabToggled (); void lumaneutralPressed (); diff --git a/rtgui/distortion.cc b/rtgui/distortion.cc index 0ac067ba8..165ccee06 100644 --- a/rtgui/distortion.cc +++ b/rtgui/distortion.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -95,10 +95,6 @@ void Distortion::adjusterChanged(Adjuster* a, double newval) } } -void Distortion::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void Distortion::setBatchMode (bool batchMode) { diff --git a/rtgui/distortion.h b/rtgui/distortion.h index ce1e81046..5e1cf6a6b 100644 --- a/rtgui/distortion.h +++ b/rtgui/distortion.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _DISTORTION_H_ #define _DISTORTION_H_ @@ -43,7 +43,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled (Adjuster* a, bool newval) override; void setAdjusterBehavior (bool vadd); void trimValues (rtengine::procparams::ProcParams* pp) override; void idPressed (); diff --git a/rtgui/dynamicprofilepanel.cc b/rtgui/dynamicprofilepanel.cc index d83c70669..38029af71 100644 --- a/rtgui/dynamicprofilepanel.cc +++ b/rtgui/dynamicprofilepanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "dynamicprofilepanel.h" diff --git a/rtgui/dynamicprofilepanel.h b/rtgui/dynamicprofilepanel.h index e271edc5a..fd4a6e80e 100644 --- a/rtgui/dynamicprofilepanel.h +++ b/rtgui/dynamicprofilepanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _DYNAMICPROFILEPANEL_H_ #define _DYNAMICPROFILEPANEL_H_ diff --git a/rtgui/editbuffer.cc b/rtgui/editbuffer.cc index 882f3c084..80114ed11 100644 --- a/rtgui/editbuffer.cc +++ b/rtgui/editbuffer.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "editbuffer.h" diff --git a/rtgui/editbuffer.h b/rtgui/editbuffer.h index ffb80c48d..77afb6449 100644 --- a/rtgui/editbuffer.h +++ b/rtgui/editbuffer.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtgui/editcallbacks.cc b/rtgui/editcallbacks.cc index d51d672a5..1538ef7ba 100644 --- a/rtgui/editcallbacks.cc +++ b/rtgui/editcallbacks.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "editcallbacks.h" diff --git a/rtgui/editcallbacks.h b/rtgui/editcallbacks.h index c4003f9ca..c2efcf53e 100644 --- a/rtgui/editcallbacks.h +++ b/rtgui/editcallbacks.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtgui/editcoordsys.h b/rtgui/editcoordsys.h index 829225e3f..eff339ab9 100644 --- a/rtgui/editcoordsys.h +++ b/rtgui/editcoordsys.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ /** @file diff --git a/rtgui/editedstate.h b/rtgui/editedstate.h index db416c531..2cee07eb9 100644 --- a/rtgui/editedstate.h +++ b/rtgui/editedstate.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _EDITEDSTATE_ #define _EDITEDSTATE_ diff --git a/rtgui/editenums.h b/rtgui/editenums.h index 264576789..8fc28e922 100644 --- a/rtgui/editenums.h +++ b/rtgui/editenums.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _EDITENUMS_ #define _EDITENUMS_ diff --git a/rtgui/editid.h b/rtgui/editid.h index 5c1cf2389..88d77f859 100644 --- a/rtgui/editid.h +++ b/rtgui/editid.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _EDITID_H_ #define _EDITID_H_ diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index fd5284e74..1a37cb769 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "editorpanel.h" @@ -1090,7 +1090,7 @@ void EditorPanel::close () if (iareapanel) { iareapanel->imageArea->setPreviewHandler (nullptr); iareapanel->imageArea->setImProcCoordinator (nullptr); - iareapanel->imageArea->unsubscribe(); + tpc->editModeSwitchedOff(); } rtengine::StagedImageProcessor::destroy (ipc); @@ -1377,7 +1377,7 @@ void EditorPanel::info_toggled () infoString = M ("QINFO_NOEXIF"); } - iareapanel->imageArea->setInfoText (infoString); + iareapanel->imageArea->setInfoText (std::move(infoString)); iareapanel->imageArea->infoEnabled (info->get_active ()); } diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index de5360646..c4349f693 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _EDITORPANEL_ #define _EDITORPANEL_ @@ -34,6 +34,7 @@ #include "navigator.h" #include "progressconnector.h" #include "filepanel.h" +#include "../rtengine/noncopyable.h" class EditorPanel; class MyProgressBar; @@ -52,7 +53,8 @@ class EditorPanel final : public rtengine::ProgressListener, public ThumbnailListener, public HistoryBeforeLineListener, - public rtengine::HistogramListener + public rtengine::HistogramListener, + public rtengine::NonCopyable { public: explicit EditorPanel (FilePanel* filePanel = nullptr); diff --git a/rtgui/editwidgets.cc b/rtgui/editwidgets.cc index 16cd67cd4..a7996ee42 100644 --- a/rtgui/editwidgets.cc +++ b/rtgui/editwidgets.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "editwidgets.h" diff --git a/rtgui/editwidgets.h b/rtgui/editwidgets.h index 1ae185f7a..9154db31f 100644 --- a/rtgui/editwidgets.h +++ b/rtgui/editwidgets.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtgui/editwindow.cc b/rtgui/editwindow.cc index ec7201f84..50a1484cf 100644 --- a/rtgui/editwindow.cc +++ b/rtgui/editwindow.cc @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with RawTherapee. If not, see . +* along with RawTherapee. If not, see . */ #include "editwindow.h" diff --git a/rtgui/editwindow.h b/rtgui/editwindow.h index 42c8ec20e..8a2ade6ba 100644 --- a/rtgui/editwindow.h +++ b/rtgui/editwindow.h @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _EDITWINDOW_ #define _EDITWINDOW_ diff --git a/rtgui/epd.cc b/rtgui/epd.cc index 4b7cca10a..307790ff7 100644 --- a/rtgui/epd.cc +++ b/rtgui/epd.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -159,10 +159,6 @@ void EdgePreservingDecompositionUI::adjusterChanged(Adjuster* a, double newval) } } -void EdgePreservingDecompositionUI::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void EdgePreservingDecompositionUI::enabledChanged () { if (listener) { diff --git a/rtgui/epd.h b/rtgui/epd.h index f2073a976..d8781ef27 100644 --- a/rtgui/epd.h +++ b/rtgui/epd.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _EPD_H_ #define _EPD_H_ @@ -42,7 +42,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void enabledChanged () override; void setAdjusterBehavior (bool stAdd, bool gAdd, bool esAdd, bool scAdd, bool rAdd); }; diff --git a/rtgui/eventmapper.cc b/rtgui/eventmapper.cc index 81160c58e..b2e5067c7 100644 --- a/rtgui/eventmapper.cc +++ b/rtgui/eventmapper.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "eventmapper.h" diff --git a/rtgui/eventmapper.h b/rtgui/eventmapper.h index f977b0ff4..5cbb45388 100644 --- a/rtgui/eventmapper.h +++ b/rtgui/eventmapper.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtgui/exiffiltersettings.cc b/rtgui/exiffiltersettings.cc index 0218677d8..567a22868 100644 --- a/rtgui/exiffiltersettings.cc +++ b/rtgui/exiffiltersettings.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "exiffiltersettings.h" diff --git a/rtgui/exiffiltersettings.h b/rtgui/exiffiltersettings.h index d692eb510..e820a2cac 100644 --- a/rtgui/exiffiltersettings.h +++ b/rtgui/exiffiltersettings.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _EXIFFILTERSETTINGS_ #define _EXIFFILTERSETTINGS_ diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index f4da2d4b1..efa417c85 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -139,12 +139,10 @@ ExifPanel::ExifPanel() : show_all (); } - ExifPanel::~ExifPanel () { } - void ExifPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { disableListener (); @@ -162,21 +160,18 @@ void ExifPanel::write (ProcParams* pp, ParamsEdited* pedited) pp->exif = *changeList; } - void ExifPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { *defChangeList = defParams->exif; } - void ExifPanel::setImageData (const FramesMetaData* id) { idata = id; } - Gtk::TreeModel::Children ExifPanel::addTag(const std::string &key, const Glib::ustring &label, const Glib::ustring &value, bool editable, bool edited) { auto root = exifTreeModel->children(); @@ -201,7 +196,6 @@ Gtk::TreeModel::Children ExifPanel::addTag(const std::string &key, const Glib::u return row.children(); } - void ExifPanel::refreshTags() { Glib::RefPtr selection = exifTree->get_selection(); @@ -265,7 +259,6 @@ void ExifPanel::refreshTags() } } - void ExifPanel::exifSelectionChanged () { @@ -285,7 +278,6 @@ void ExifPanel::exifSelectionChanged () } } - void ExifPanel::resetIt(const Gtk::TreeModel::const_iterator& iter) { if (!iter) { @@ -296,7 +288,6 @@ void ExifPanel::resetIt(const Gtk::TreeModel::const_iterator& iter) changeList->erase(key); } - void ExifPanel::resetPressed () { @@ -310,7 +301,6 @@ void ExifPanel::resetPressed () notifyListener(); } - void ExifPanel::resetAllPressed () { setImageData(idata); @@ -319,7 +309,6 @@ void ExifPanel::resetAllPressed () notifyListener (); } - void ExifPanel::addPressed () { @@ -400,7 +389,6 @@ void ExifPanel::addPressed () delete hb2; } - void ExifPanel::notifyListener () { if (listener) { diff --git a/rtgui/exifpanel.h b/rtgui/exifpanel.h index de2174f6b..cb97e11bf 100644 --- a/rtgui/exifpanel.h +++ b/rtgui/exifpanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _EXIFPANEL_ #define _EXIFPANEL_ diff --git a/rtgui/exportpanel.cc b/rtgui/exportpanel.cc index 9a4c930d5..b4332f4a4 100644 --- a/rtgui/exportpanel.cc +++ b/rtgui/exportpanel.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "exportpanel.h" #include "multilangmgr.h" diff --git a/rtgui/exportpanel.h b/rtgui/exportpanel.h index dc9aa34a5..d13ca08ad 100644 --- a/rtgui/exportpanel.h +++ b/rtgui/exportpanel.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _EXPORTPANEL_ #define _EXPORTPANEL_ diff --git a/rtgui/extprog.cc b/rtgui/extprog.cc index 33424fac9..95c1c937d 100644 --- a/rtgui/extprog.cc +++ b/rtgui/extprog.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with RawTherapee. If not, see . +* along with RawTherapee. If not, see . */ #include "extprog.h" @@ -58,7 +58,7 @@ bool ExtProgAction::execute (const std::vector& fileNames) const } for (const auto& fileName : fileNames) { - cmdLine += " \"" + fileName + "\""; + cmdLine += " " + Glib::shell_quote(fileName); } return ExtProgStore::spawnCommandAsync (cmdLine); @@ -256,7 +256,7 @@ bool ExtProgStore::openInGimp (const Glib::ustring& fileName) #else - auto cmdLine = Glib::ustring("gimp \"") + fileName + Glib::ustring("\""); + auto cmdLine = Glib::ustring("gimp ") + Glib::shell_quote(fileName); auto success = spawnCommandAsync (cmdLine); #endif @@ -291,7 +291,7 @@ bool ExtProgStore::openInGimp (const Glib::ustring& fileName) #else - cmdLine = Glib::ustring("gimp-remote \"") + fileName + Glib::ustring("\""); + cmdLine = Glib::ustring("gimp-remote ") + Glib::shell_quote(fileName); success = ExtProgStore::spawnCommandAsync (cmdLine); #endif @@ -312,7 +312,7 @@ bool ExtProgStore::openInPhotoshop (const Glib::ustring& fileName) #else - const auto cmdLine = Glib::ustring("\"") + Glib::build_filename(options.psDir, "Photoshop.exe") + Glib::ustring("\" \"") + fileName + Glib::ustring("\""); + const auto cmdLine = Glib::ustring("\"") + Glib::build_filename(options.psDir, "Photoshop.exe") + "\" " + Glib::shell_quote(fileName); #endif @@ -334,7 +334,7 @@ bool ExtProgStore::openInCustomEditor (const Glib::ustring& fileName) #else - const auto cmdLine = Glib::ustring("\"") + options.customEditorProg + Glib::ustring("\" \"") + fileName + Glib::ustring("\""); + const auto cmdLine = Glib::ustring("\"") + options.customEditorProg + "\" " + Glib::shell_quote(fileName); return spawnCommandAsync (cmdLine); #endif diff --git a/rtgui/extprog.h b/rtgui/extprog.h index 154a825e1..ea2749a61 100644 --- a/rtgui/extprog.h +++ b/rtgui/extprog.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with RawTherapee. If not, see . +* along with RawTherapee. If not, see . */ #ifndef _EXTPROG_ diff --git a/rtgui/fattaltonemap.cc b/rtgui/fattaltonemap.cc index 85d835cc7..a0baf3531 100644 --- a/rtgui/fattaltonemap.cc +++ b/rtgui/fattaltonemap.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -119,10 +119,6 @@ void FattalToneMapping::adjusterChanged(Adjuster* a, double newval) } } -void FattalToneMapping::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void FattalToneMapping::enabledChanged () { if (listener) { diff --git a/rtgui/fattaltonemap.h b/rtgui/fattaltonemap.h index 76e850c4e..9f788351c 100644 --- a/rtgui/fattaltonemap.h +++ b/rtgui/fattaltonemap.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once @@ -42,7 +42,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void enabledChanged () override; void setAdjusterBehavior(bool amountAdd, bool thresholdAdd, bool anchorAdd); }; diff --git a/rtgui/favoritbrowser.cc b/rtgui/favoritbrowser.cc index 379ce26e6..2d49ab087 100644 --- a/rtgui/favoritbrowser.cc +++ b/rtgui/favoritbrowser.cc @@ -14,13 +14,13 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include "multilangmgr.h" #include "rtimage.h" -FavoritBrowser::FavoritBrowser () : listener (NULL), lastSelectedDir ("") +FavoritBrowser::FavoritBrowser () : listener (NULL) { scrollw = Gtk::manage (new Gtk::ScrolledWindow ()); @@ -97,7 +97,7 @@ void FavoritBrowser::dirSelected (const Glib::ustring& dirname, const Glib::ustr void FavoritBrowser::addPressed () { - if (lastSelectedDir == "") { + if (lastSelectedDir.empty()) { return; } diff --git a/rtgui/favoritbrowser.h b/rtgui/favoritbrowser.h index ed522c1c4..292f17de6 100644 --- a/rtgui/favoritbrowser.h +++ b/rtgui/favoritbrowser.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _FAVORITBROWSER_ #define _FAVORITBROWSER_ diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index a270e5af8..f9afcef48 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -16,8 +16,9 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ +#include #include #include @@ -592,15 +593,16 @@ void FileBrowser::addEntry_ (FileBrowserEntry* entry) { entry->selected = false; entry->drawable = false; - entry->framed = editedFiles.find (entry->filename) != editedFiles.end(); + entry->framed = editedFiles.find(entry->filename) != editedFiles.end(); // add button set to the thumbbrowserentry - entry->addButtonSet (new FileThumbnailButtonSet (entry)); - entry->getThumbButtonSet()->setRank (entry->thumbnail->getRank()); - entry->getThumbButtonSet()->setColorLabel (entry->thumbnail->getColorLabel()); - entry->getThumbButtonSet()->setInTrash (entry->thumbnail->getStage()); - entry->getThumbButtonSet()->setButtonListener (this); - entry->resize (getThumbnailHeight()); + entry->addButtonSet(new FileThumbnailButtonSet(entry)); + entry->getThumbButtonSet()->setRank(entry->thumbnail->getRank()); + entry->getThumbButtonSet()->setColorLabel(entry->thumbnail->getColorLabel()); + entry->getThumbButtonSet()->setInTrash(entry->thumbnail->getStage()); + entry->getThumbButtonSet()->setButtonListener(this); + entry->resize(getThumbnailHeight()); + entry->filtered = !checkFilter(entry); // find place in abc order { @@ -619,9 +621,9 @@ void FileBrowser::addEntry_ (FileBrowserEntry* entry) entry ); - initEntry (entry); + initEntry(entry); } - redraw (); + redraw(entry); } FileBrowserEntry* FileBrowser::delEntry (const Glib::ustring& fname) @@ -666,6 +668,7 @@ void FileBrowser::close () MYWRITERLOCK(l, entryRW); selected.clear (); + anchor = nullptr; MYWRITERLOCK_RELEASE(l); // notifySelectionListener will need read access! @@ -781,16 +784,20 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) { MYWRITERLOCK(l, entryRW); - selected.clear (); + selected.clear(); - for (size_t i = 0; i < fd.size(); i++) - if (checkFilter (fd[i])) { + for (size_t i = 0; i < fd.size(); ++i) { + if (checkFilter(fd[i])) { fd[i]->selected = true; - selected.push_back (fd[i]); + selected.push_back(fd[i]); } + } + if (!anchor && !selected.empty()) { + anchor = selected[0]; + } } queue_draw (); - notifySelectionListener (); + notifySelectionListener(); } else if( m == copyTo) { tbl->copyMoveRequested (mselected, false); } @@ -833,10 +840,10 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) } for (size_t i = 0; i < mselected.size(); i++) { - rtengine::procparams::ProcParams pp = mselected[i]->thumbnail->getProcParams(); - pp.raw.dark_frame = fc.get_filename(); - pp.raw.df_autoselect = false; - mselected[i]->thumbnail->setProcParams(pp, nullptr, FILEBROWSER, false); + rtengine::procparams::ProcParams lpp = mselected[i]->thumbnail->getProcParams(); + lpp.raw.dark_frame = fc.get_filename(); + lpp.raw.df_autoselect = false; + mselected[i]->thumbnail->setProcParams(lpp, nullptr, FILEBROWSER, false); } if (bppcl) { @@ -909,10 +916,10 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) } for (size_t i = 0; i < mselected.size(); i++) { - rtengine::procparams::ProcParams pp = mselected[i]->thumbnail->getProcParams(); - pp.raw.ff_file = fc.get_filename(); - pp.raw.ff_AutoSelect = false; - mselected[i]->thumbnail->setProcParams(pp, nullptr, FILEBROWSER, false); + rtengine::procparams::ProcParams lpp = mselected[i]->thumbnail->getProcParams(); + lpp.raw.ff_file = fc.get_filename(); + lpp.raw.ff_AutoSelect = false; + mselected[i]->thumbnail->setProcParams(lpp, nullptr, FILEBROWSER, false); } if (bppcl) { @@ -1072,17 +1079,17 @@ void FileBrowser::partPasteProfile () bppcl->beginBatchPParamsChange(mselected.size()); } - for (unsigned int i = 0; i < mselected.size(); i++) { + for (auto entry : mselected) { // copying read only clipboard PartialProfile to a temporary one, initialized to the thumb's ProcParams - mselected[i]->thumbnail->createProcParamsForUpdate(false, false); // this can execute customprofilebuilder to generate param file + entry->thumbnail->createProcParamsForUpdate(false, false); // this can execute customprofilebuilder to generate param file const rtengine::procparams::PartialProfile& cbPartProf = clipboard.getPartialProfile(); - rtengine::procparams::PartialProfile pastedPartProf(&mselected[i]->thumbnail->getProcParams (), nullptr); + rtengine::procparams::PartialProfile pastedPartProf(&entry->thumbnail->getProcParams (), nullptr); // pushing the selected values of the clipboard PartialProfile to the temporary PartialProfile partialPasteDlg.applyPaste (pastedPartProf.pparams, pastedPartProf.pedited, cbPartProf.pparams, cbPartProf.pedited); // applying the temporary PartialProfile to the thumb's ProcParams - mselected[i]->thumbnail->setProcParams (*pastedPartProf.pparams, pastedPartProf.pedited, FILEBROWSER); + entry->thumbnail->setProcParams (*pastedPartProf.pparams, pastedPartProf.pedited, FILEBROWSER); pastedPartProf.deleteInstance(); } @@ -1436,12 +1443,12 @@ void FileBrowser::applyFilter (const BrowserFilter& filter) } for (size_t i = 0; i < fd.size(); i++) { - if (checkFilter (fd[i])) { + if (checkFilter(fd[i])) { numFiltered++; - } else if (fd[i]->selected ) { + } else if (fd[i]->selected) { fd[i]->selected = false; - std::vector::iterator j = std::find (selected.begin(), selected.end(), fd[i]); - selected.erase (j); + std::vector::iterator j = std::find(selected.begin(), selected.end(), fd[i]); + selected.erase(j); if (lastClicked == fd[i]) { lastClicked = nullptr; @@ -1450,6 +1457,9 @@ void FileBrowser::applyFilter (const BrowserFilter& filter) selchanged = true; } } + if (selected.empty() || (anchor && std::find(selected.begin(), selected.end(), anchor) == selected.end())) { + anchor = nullptr; + } } if (selchanged) { @@ -1460,12 +1470,12 @@ void FileBrowser::applyFilter (const BrowserFilter& filter) redraw (); } -bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry complies filter +bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) const // true -> entry complies filter { FileBrowserEntry* entry = static_cast(entryb); - if (filter.showOriginal && entry->getOriginal() != nullptr) { + if (filter.showOriginal && entry->getOriginal()) { return false; } @@ -1484,44 +1494,22 @@ bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry return false; } - // return false is query is not satisfied - if (!filter.queryFileName.empty()) { + // return false if query is not satisfied + if (!filter.vFilterStrings.empty()) { // check if image's FileName contains queryFileName (case insensitive) // TODO should we provide case-sensitive search option via preferences? - Glib::ustring FileName; - FileName = Glib::path_get_basename (entry->thumbnail->getFileName()); - FileName = FileName.uppercase(); - //printf("FileBrowser::checkFilter FileName = '%s'; find() result= %i \n",FileName.c_str(), FileName.find(filter.queryFileName.uppercase())); - - Glib::ustring decodedQueryFileName; - bool MatchEqual; - - // Determine the match mode - check if the first 2 characters are equal to "!=" - if (filter.queryFileName.find("!=") == 0) { - decodedQueryFileName = filter.queryFileName.substr (2, filter.queryFileName.length() - 2); - MatchEqual = false; - } else { - decodedQueryFileName = filter.queryFileName; - MatchEqual = true; - } - - // Consider that queryFileName consist of comma separated values (FilterString) - // Evaluate if ANY of these FilterString are contained in the filename - // This will construct OR filter within the filter.queryFileName + std::string FileName = Glib::path_get_basename(entry->thumbnail->getFileName()); + std::transform(FileName.begin(), FileName.end(), FileName.begin(), ::toupper); int iFilenameMatch = 0; - std::vector vFilterStrings = Glib::Regex::split_simple(",", decodedQueryFileName.uppercase()); - for(size_t i = 0; i < vFilterStrings.size(); i++) { - // ignore empty vFilterStrings. Otherwise filter will always return true if - // e.g. filter.queryFileName ends on "," and will stop being a filter - if (!vFilterStrings.at(i).empty()) { - if (FileName.find(vFilterStrings.at(i)) != Glib::ustring::npos) { - iFilenameMatch++; - } + for (const auto& filterString : filter.vFilterStrings) { + if (FileName.find(filterString) != std::string::npos) { + ++iFilenameMatch; + break; } } - if (MatchEqual) { + if (filter.matchEqual) { if (iFilenameMatch == 0) { //none of the vFilterStrings found in FileName return false; } @@ -1530,10 +1518,10 @@ bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry return false; } } + } - /*experimental Regex support, this is unlikely to be useful to photographers*/ - //bool matchfound=Glib::Regex::match_simple(filter.queryFileName.uppercase(),FileName); - //if (!matchfound) return false; + if (!filter.exifFilterEnabled) { + return true; } // check exif filter @@ -1541,17 +1529,12 @@ bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry double tol = 0.01; double tol2 = 1e-8; - if (!filter.exifFilterEnabled) { - return true; - } - - Glib::ustring camera(cfs->getCamera()); - - if (!cfs->exifValid) - return (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(camera) > 0) + if (!cfs->exifValid) { + return (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(cfs->getCamera()) > 0) && (!filter.exifFilter.filterLens || filter.exifFilter.lenses.count(cfs->lens) > 0) && (!filter.exifFilter.filterFiletype || filter.exifFilter.filetypes.count(cfs->filetype) > 0) && (!filter.exifFilter.filterExpComp || filter.exifFilter.expcomp.count(cfs->expcomp) > 0); + } return (!filter.exifFilter.filterShutter || (rtengine::FramesMetaData::shutterFromString(rtengine::FramesMetaData::shutterToString(cfs->shutter)) >= filter.exifFilter.shutterFrom - tol2 && rtengine::FramesMetaData::shutterFromString(rtengine::FramesMetaData::shutterToString(cfs->shutter)) <= filter.exifFilter.shutterTo + tol2)) @@ -1559,7 +1542,7 @@ bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry && (!filter.exifFilter.filterFocalLen || (cfs->focalLen >= filter.exifFilter.focalFrom - tol && cfs->focalLen <= filter.exifFilter.focalTo + tol)) && (!filter.exifFilter.filterISO || (cfs->iso >= filter.exifFilter.isoFrom && cfs->iso <= filter.exifFilter.isoTo)) && (!filter.exifFilter.filterExpComp || filter.exifFilter.expcomp.count(cfs->expcomp) > 0) - && (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(camera) > 0) + && (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(cfs->getCamera()) > 0) && (!filter.exifFilter.filterLens || filter.exifFilter.lenses.count(cfs->lens) > 0) && (!filter.exifFilter.filterFiletype || filter.exifFilter.filetypes.count(cfs->filetype) > 0); } diff --git a/rtgui/filebrowser.h b/rtgui/filebrowser.h index b208a854d..6911a944f 100644 --- a/rtgui/filebrowser.h +++ b/rtgui/filebrowser.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _FILEBROWSER_ #define _FILEBROWSER_ @@ -30,6 +30,7 @@ #include "exportpanel.h" #include "extprog.h" #include "profilestorecombobox.h" +#include "../rtengine/noncopyable.h" class ProfileStoreLabel; class FileBrowser; @@ -56,7 +57,8 @@ public: class FileBrowser : public ThumbBrowserBase, public LWButtonListener, public ExportPanelListener, - public ProfileStoreListener + public ProfileStoreListener, + public rtengine::NonCopyable { private: typedef sigc::signal type_trash_changed; @@ -168,7 +170,7 @@ public: void buttonPressed (LWButton* button, int actionCode, void* actionData) override; void redrawNeeded (LWButton* button) override; - bool checkFilter (ThumbBrowserEntryBase* entry) override; + bool checkFilter (ThumbBrowserEntryBase* entry) const override; void rightClicked (ThumbBrowserEntryBase* entry) override; void doubleClicked (ThumbBrowserEntryBase* entry) override; bool keyPressed (GdkEventKey* event) override; diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc index 0fa5694de..44146b990 100644 --- a/rtgui/filebrowserentry.cc +++ b/rtgui/filebrowserentry.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "filebrowserentry.h" @@ -119,39 +119,37 @@ void FileBrowserEntry::calcThumbnailSize () } } -std::vector > FileBrowserEntry::getIconsOnImageArea () +std::vector> FileBrowserEntry::getIconsOnImageArea () { - - std::vector > ret; - if (!thumbnail) { - return ret; + return {}; } + std::vector> ret; + if (thumbnail->hasProcParams() && editedIcon) { - ret.push_back (editedIcon); + ret.push_back(editedIcon); } if (thumbnail->isRecentlySaved() && recentlySavedIcon) { - ret.push_back (recentlySavedIcon); + ret.push_back(recentlySavedIcon); } if (thumbnail->isEnqueued () && enqueuedIcon) { - ret.push_back (enqueuedIcon); + ret.push_back(enqueuedIcon); } return ret; } -std::vector > FileBrowserEntry::getSpecificityIconsOnImageArea () +std::vector> FileBrowserEntry::getSpecificityIconsOnImageArea () { - - std::vector > ret; - if (!thumbnail) { - return ret; + return {}; } + std::vector> ret; + if (thumbnail->isHDR() && hdr) { ret.push_back (hdr); } @@ -188,7 +186,7 @@ void FileBrowserEntry::customBackBufferUpdate (Cairo::RefPtr c) } } -void FileBrowserEntry::getIconSize (int& w, int& h) +void FileBrowserEntry::getIconSize (int& w, int& h) const { w = editedIcon->get_width (); @@ -253,32 +251,35 @@ void FileBrowserEntry::_updateImage(rtengine::IImage8* img, double s, const rten bool newLandscape = img->getWidth() > img->getHeight(); bool rotated = false; - if (preh == img->getHeight ()) { + if (preh == img->getHeight()) { + const bool resize = !preview || prew != img->getWidth(); prew = img->getWidth (); - GThreadLock lock; - // Check if image has been rotated since last time - rotated = preview != nullptr && newLandscape != landscape; + rotated = preview && newLandscape != landscape; - guint8* temp = preview; - preview = nullptr; - delete [] temp; - temp = new guint8 [prew * preh * 3]; - memcpy (temp, img->getData(), prew * preh * 3); - preview = temp; + if (resize) { + if (preview) { + delete [] preview; + } + preview = new guint8 [prew * preh * 3]; + } + memcpy(preview, img->getData(), prew * preh * 3); + { + GThreadLock lock; updateBackBuffer (); + } } landscape = newLandscape; - img->free (); + img->free(); - if (parent != nullptr) { + if (parent) { if (rotated) { parent->thumbRearrangementNeeded(); } else if (redrawRequests == 0) { - parent->redrawNeeded (this); + parent->redrawNeeded(this); } } } @@ -286,34 +287,29 @@ void FileBrowserEntry::_updateImage(rtengine::IImage8* img, double s, const rten bool FileBrowserEntry::motionNotify (int x, int y) { - bool b = ThumbBrowserEntryBase::motionNotify (x, y); + const bool b = ThumbBrowserEntryBase::motionNotify(x, y); - int ix = x - startx - ofsX; - int iy = y - starty - ofsY; + const int ix = x - startx - ofsX; + const int iy = y - starty - ofsY; Inspector* inspector = parent->getInspector(); if (inspector && inspector->isActive() && !parent->isInTabMode()) { - rtengine::Coord2D coord(-1., -1.); - getPosInImgSpace(x, y, coord); + const rtengine::Coord2D coord(getPosInImgSpace(x, y)); if (coord.x != -1.) { if (!wasInside) { inspector->switchImage(filename); + wasInside = true; } - - wasInside = true; inspector->mouseMove(coord, 0); } else { - if (wasInside) { - wasInside = false; - rtengine::Coord2D coord(-1, -1); - } + wasInside = false; } } - if (inside (x, y)) { - updateCursor (ix, iy); + if (inside(x, y)) { + updateCursor(ix, iy); } if (state == SRotateSelecting) { @@ -325,24 +321,36 @@ bool FileBrowserEntry::motionNotify (int x, int y) cropParams->y = action_y + (y - press_y) / scale; cropParams->h += oy - cropParams->y; cropgl->cropHeight1Resized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio); + { + MYREADERLOCK(l, lockRW); updateBackBuffer (); + } parent->redrawNeeded (this); } else if (state == SResizeH2 && cropgl) { cropParams->h = action_y + (y - press_y) / scale; cropgl->cropHeight2Resized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio); + { + MYREADERLOCK(l, lockRW); updateBackBuffer (); + } parent->redrawNeeded (this); } else if (state == SResizeW1 && cropgl) { int ox = cropParams->x; cropParams->x = action_x + (x - press_x) / scale; cropParams->w += ox - cropParams->x; cropgl->cropWidth1Resized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio); + { + MYREADERLOCK(l, lockRW); updateBackBuffer (); + } parent->redrawNeeded (this); } else if (state == SResizeW2 && cropgl) { cropParams->w = action_x + (x - press_x) / scale; cropgl->cropWidth2Resized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio); + { + MYREADERLOCK(l, lockRW); updateBackBuffer (); + } parent->redrawNeeded (this); } else if (state == SResizeTL && cropgl) { int ox = cropParams->x; @@ -352,7 +360,10 @@ bool FileBrowserEntry::motionNotify (int x, int y) cropParams->y = action_y + (y - press_y) / scale; cropParams->h += oy - cropParams->y; cropgl->cropTopLeftResized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio); + { + MYREADERLOCK(l, lockRW); updateBackBuffer (); + } parent->redrawNeeded (this); } else if (state == SResizeTR && cropgl) { cropParams->w = action_x + (x - press_x) / scale; @@ -360,7 +371,10 @@ bool FileBrowserEntry::motionNotify (int x, int y) cropParams->y = action_y + (y - press_y) / scale; cropParams->h += oy - cropParams->y; cropgl->cropTopRightResized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio); + { + MYREADERLOCK(l, lockRW); updateBackBuffer (); + } parent->redrawNeeded (this); } else if (state == SResizeBL && cropgl) { int ox = cropParams->x; @@ -368,19 +382,28 @@ bool FileBrowserEntry::motionNotify (int x, int y) cropParams->w += ox - cropParams->x; cropParams->h = action_y + (y - press_y) / scale; cropgl->cropBottomLeftResized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio); + { + MYREADERLOCK(l, lockRW); updateBackBuffer (); + } parent->redrawNeeded (this); } else if (state == SResizeBR && cropgl) { cropParams->w = action_x + (x - press_x) / scale; cropParams->h = action_y + (y - press_y) / scale; cropgl->cropBottomRightResized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio); + { + MYREADERLOCK(l, lockRW); updateBackBuffer (); + } parent->redrawNeeded (this); } else if (state == SCropMove && cropgl) { cropParams->x = action_x + (x - press_x) / scale; cropParams->y = action_y + (y - press_y) / scale; cropgl->cropMoved (cropParams->x, cropParams->y, cropParams->w, cropParams->h); + { + MYREADERLOCK(l, lockRW); updateBackBuffer (); + } parent->redrawNeeded (this); } else if (state == SCropSelecting && cropgl) { int cx1 = press_x, cy1 = press_y; @@ -403,7 +426,10 @@ bool FileBrowserEntry::motionNotify (int x, int y) cropParams->h = cy1 - cy2 + 1; } + { + MYREADERLOCK(l, lockRW); updateBackBuffer (); + } parent->redrawNeeded (this); } @@ -571,6 +597,7 @@ bool FileBrowserEntry::releaseNotify (int button, int type, int bstate, int x, i bool FileBrowserEntry::onArea (CursorArea a, int x, int y) { + MYREADERLOCK(l, lockRW); if (!drawable || !preview) { return false; } @@ -771,6 +798,8 @@ void FileBrowserEntry::drawStraightenGuide (Cairo::RefPtr cr) int y2 = action_y; int x2 = action_x; + { + MYREADERLOCK(l, lockRW); if (x2 < prex + ofsX + startx) { y2 = y1 - (double)(y1 - y2) * (x1 - (prex + ofsX + startx)) / (x1 - x2); x2 = prex + ofsX + startx; @@ -786,6 +815,7 @@ void FileBrowserEntry::drawStraightenGuide (Cairo::RefPtr cr) x2 = x1 - (double)(x1 - x2) * (y1 - (preh + prey + ofsY + starty - 1)) / (y1 - y2); y2 = preh + prey + ofsY + starty - 1; } + } cr->set_line_width (1.5); cr->set_source_rgb (1.0, 1.0, 1.0); diff --git a/rtgui/filebrowserentry.h b/rtgui/filebrowserentry.h index 3a3d32977..646e8e67e 100644 --- a/rtgui/filebrowserentry.h +++ b/rtgui/filebrowserentry.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _FILEBROWSERENTRY_ #define _FILEBROWSERENTRY_ @@ -34,6 +34,7 @@ #include "thumbimageupdater.h" #include "thumbnail.h" #include "thumbnaillistener.h" +#include "../rtengine/noncopyable.h" class FileBrowserEntry; @@ -46,7 +47,8 @@ struct FileBrowserEntryIdleHelper { class FileThumbnailButtonSet; class FileBrowserEntry : public ThumbBrowserEntryBase, public ThumbnailListener, - public ThumbImageUpdateListener + public ThumbImageUpdateListener, + public rtengine::NonCopyable { double scale; @@ -93,9 +95,9 @@ public: void refreshQuickThumbnailImage () override; void calcThumbnailSize () override; - std::vector > getIconsOnImageArea () override; - std::vector > getSpecificityIconsOnImageArea () override; - void getIconSize (int& w, int& h) override; + std::vector> getIconsOnImageArea () override; + std::vector> getSpecificityIconsOnImageArea () override; + void getIconSize (int& w, int& h) const override; // thumbnaillistener interface void procParamsChanged (Thumbnail* thm, int whoChangedIt) override; diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index fcccaac3a..674501322 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "filecatalog.h" @@ -457,8 +457,6 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : hScrollPos[i] = 0; vScrollPos[i] = 0; } - - selectedDirectory = ""; } FileCatalog::~FileCatalog() @@ -563,44 +561,49 @@ void FileCatalog::closeDir () redrawAll (); } -std::vector FileCatalog::getFileList () +std::vector FileCatalog::getFileList() { + std::vector names; - std::set extensions; - for (const auto& parsedExt : options.parsedExtensions) { - extensions.emplace (parsedExt.lowercase ()); - } + const std::set& extensions = options.parsedExtensionsSet; try { - auto dir = Gio::File::create_for_path (selectedDirectory); + const auto dir = Gio::File::create_for_path(selectedDirectory); - auto enumerator = dir->enumerate_children ("standard::name"); + auto enumerator = dir->enumerate_children("standard::name,standard::type,standard::is-hidden"); while (true) { try { - auto file = enumerator->next_file (); + const auto file = enumerator->next_file(); if (!file) { break; } - const Glib::ustring fname = file->get_name (); - - auto lastdot = fname.find_last_of ('.'); - if (lastdot >= fname.length () - 1) { + if (file->get_file_type() == Gio::FILE_TYPE_DIRECTORY) { continue; } - const auto fext = fname.substr (lastdot + 1).lowercase (); - if (extensions.count (fext) == 0) { + if (!options.fbShowHidden && file->is_hidden()) { continue; } - names.emplace_back (Glib::build_filename (selectedDirectory, fname)); + const Glib::ustring fname = file->get_name(); + const auto lastdot = fname.find_last_of('.'); + + if (lastdot >= fname.length() - 1) { + continue; + } + + if (extensions.find(fname.substr(lastdot + 1).lowercase()) == extensions.end()) { + continue; + } + + names.push_back(Glib::build_filename(selectedDirectory, fname)); } catch (Glib::Exception& exception) { if (options.rtSettings.verbose) { - std::cerr << exception.what () << std::endl; + std::cerr << exception.what() << std::endl; } } } @@ -620,13 +623,13 @@ void FileCatalog::dirSelected (const Glib::ustring& dirname, const Glib::ustring { try { - Glib::RefPtr dir = Gio::File::create_for_path (dirname); + const Glib::RefPtr dir = Gio::File::create_for_path(dirname); if (!dir) { return; } - closeDir (); + closeDir(); previewsToLoad = 0; previewsLoaded = 0; @@ -636,16 +639,14 @@ void FileCatalog::dirSelected (const Glib::ustring& dirname, const Glib::ustring } selectedDirectory = dir->get_parse_name(); - //printf("FileCatalog::dirSelected selectedDirectory = %s\n",selectedDirectory.c_str()); - BrowsePath->set_text (selectedDirectory); - buttonBrowsePath->set_image (*iRefreshWhite); - fileNameList = getFileList (); + + BrowsePath->set_text(selectedDirectory); + buttonBrowsePath->set_image(*iRefreshWhite); + fileNameList = getFileList(); for (unsigned int i = 0; i < fileNameList.size(); i++) { - Glib::RefPtr f = Gio::File::create_for_path(fileNameList[i]); - - if (f->get_parse_name() != openfile) { // if we opened a file at the beginning don't add it again - checkAndAddFile (f); + if (openfile.empty() || fileNameList[i] != openfile) { // if we opened a file at the beginning don't add it again + addFile(fileNameList[i]); } } @@ -696,34 +697,33 @@ void FileCatalog::_refreshProgressBar () // In tab mode, no progress bar at all // Also mention that this progress bar only measures the FIRST pass (quick thumbnails) // The second, usually longer pass is done multithreaded down in the single entries and is NOT measured by this - if (!inTabMode) { + if (!inTabMode && (!previewsToLoad || std::floor(100.f * previewsLoaded / previewsToLoad) != std::floor(100.f * (previewsLoaded - 1) / previewsToLoad))) { GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected - Gtk::Notebook *nb = (Gtk::Notebook *)(filepanel->get_parent()); - Gtk::Grid* grid = Gtk::manage (new Gtk::Grid ()); + Gtk::Grid* grid = Gtk::manage(new Gtk::Grid()); Gtk::Label *label = nullptr; - if (!previewsToLoad ) { - grid->attach_next_to(*Gtk::manage (new RTImage ("folder-closed.png")), options.mainNBVertical ? Gtk::POS_TOP : Gtk::POS_RIGHT, 1, 1); + if (!previewsToLoad) { + grid->attach_next_to(*Gtk::manage(new RTImage("folder-closed.png")), options.mainNBVertical ? Gtk::POS_TOP : Gtk::POS_RIGHT, 1, 1); int filteredCount = min(fileBrowser->getNumFiltered(), previewsLoaded); - label = Gtk::manage (new Gtk::Label (M("MAIN_FRAME_FILEBROWSER") + - (filteredCount != previewsLoaded ? " [" + Glib::ustring::format(filteredCount) + "/" : " (") - + Glib::ustring::format(previewsLoaded) + - (filteredCount != previewsLoaded ? "]" : ")"))); + label = Gtk::manage(new Gtk::Label(M("MAIN_FRAME_FILEBROWSER") + + (filteredCount != previewsLoaded ? " [" + Glib::ustring::format(filteredCount) + "/" : " (") + + Glib::ustring::format(previewsLoaded) + + (filteredCount != previewsLoaded ? "]" : ")"))); } else { - grid->attach_next_to(*Gtk::manage (new RTImage ("magnifier.png")), options.mainNBVertical ? Gtk::POS_TOP : Gtk::POS_RIGHT, 1, 1); - label = Gtk::manage (new Gtk::Label (M("MAIN_FRAME_FILEBROWSER") + " [" + Glib::ustring::format(std::fixed, std::setprecision(0), std::setw(3), (double)previewsLoaded / previewsToLoad * 100 ) + "%]" )); + grid->attach_next_to(*Gtk::manage(new RTImage("magnifier.png")), options.mainNBVertical ? Gtk::POS_TOP : Gtk::POS_RIGHT, 1, 1); + label = Gtk::manage(new Gtk::Label(M("MAIN_FRAME_FILEBROWSER") + " [" + Glib::ustring::format(std::fixed, std::setprecision(0), std::setw(3), (double)previewsLoaded / previewsToLoad * 100 ) + "%]" )); filepanel->loadingThumbs("", (double)previewsLoaded / previewsToLoad); } - if( options.mainNBVertical ) { + if (options.mainNBVertical) { label->set_angle(90); } grid->attach_next_to(*label, options.mainNBVertical ? Gtk::POS_TOP : Gtk::POS_RIGHT, 1, 1); - grid->set_tooltip_markup (M("MAIN_FRAME_FILEBROWSER_TOOLTIP")); - grid->show_all (); + grid->set_tooltip_markup(M("MAIN_FRAME_FILEBROWSER_TOOLTIP")); + grid->show_all(); if (nb) { nb->set_tab_label(*filepanel, *grid); @@ -802,28 +802,28 @@ void FileCatalog::previewsFinishedUI () { GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected - redrawAll (); + redrawAll(); previewsToLoad = 0; if (filterPanel) { - filterPanel->set_sensitive (true); + filterPanel->set_sensitive(true); - if ( !hasValidCurrentEFS ) { - MyMutex::MyLock lock(dirEFSMutex); + if (!hasValidCurrentEFS) { + MyMutex::MyLock myLock(dirEFSMutex); currentEFS = dirEFS; - filterPanel->setFilter ( dirEFS, true ); + filterPanel->setFilter(dirEFS, true); } else { - filterPanel->setFilter ( currentEFS, false ); + filterPanel->setFilter(currentEFS, false); } } if (exportPanel) { - exportPanel->set_sensitive (true); + exportPanel->set_sensitive(true); } // restart anything that might have been loaded low quality fileBrowser->refreshQuickThumbImages(); - fileBrowser->applyFilter (getFilter()); // refresh total image count + fileBrowser->applyFilter(getFilter()); // refresh total image count _refreshProgressBar(); } filepanel->loadingThumbs(M("PROGRESSBAR_READY"), 0); @@ -1005,12 +1005,16 @@ void FileCatalog::copyMoveRequested(const std::vector& tbe, b Gtk::FileChooserDialog fc (getToplevelWindow (this), fc_title, Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); fc.add_button( M("GENERAL_CANCEL"), Gtk::RESPONSE_CANCEL); fc.add_button( M("GENERAL_OK"), Gtk::RESPONSE_OK); - // open dialog at the 1-st file's path - fc.set_filename(tbe[0]->filename); + if (!options.lastCopyMovePath.empty() && Glib::file_test(options.lastCopyMovePath, Glib::FILE_TEST_IS_DIR)) { + fc.set_current_folder(options.lastCopyMovePath); + } else { + // open dialog at the 1-st file's path + fc.set_current_folder(Glib::path_get_dirname(tbe[0]->filename)); + } //!!! TODO prevent dialog closing on "enter" key press if( fc.run() == Gtk::RESPONSE_OK ) { - Glib::ustring dest_Dir = fc.get_current_folder(); + options.lastCopyMovePath = fc.get_current_folder(); // iterate through selected files for (unsigned int i = 0; i < tbe.size(); i++) { @@ -1027,10 +1031,10 @@ void FileCatalog::copyMoveRequested(const std::vector& tbe, b Glib::ustring fname_Ext = getExtension(fname); // construct destination File Paths - Glib::ustring dest_fPath = Glib::build_filename (dest_Dir, fname); + Glib::ustring dest_fPath = Glib::build_filename (options.lastCopyMovePath, fname); Glib::ustring dest_fPath_param = dest_fPath + paramFileExtension; - if (moveRequested && (src_Dir == dest_Dir)) { + if (moveRequested && (src_Dir == options.lastCopyMovePath)) { continue; } @@ -1085,7 +1089,7 @@ void FileCatalog::copyMoveRequested(const std::vector& tbe, b // adjust destination fname to avoid conflicts (append "_", preserve extension) Glib::ustring dest_fname = Glib::ustring::compose("%1%2%3%4%5", fname_noExt, "_", i_copyindex, ".", fname_Ext); // re-construct destination File Paths - dest_fPath = Glib::build_filename (dest_Dir, dest_fname); + dest_fPath = Glib::build_filename (options.lastCopyMovePath, dest_fname); dest_fPath_param = dest_fPath + paramFileExtension; i_copyindex++; } @@ -1597,7 +1601,6 @@ BrowserFilter FileCatalog::getFilter () anyRankFilterActive || anyCLabelFilterActive || anyEditedFilterActive; } - filter.multiselect = false; /* * Step 2 @@ -1613,7 +1616,6 @@ BrowserFilter FileCatalog::getFilter () (anyEditedFilterActive && anyRecentlySavedFilterActive) || (anySupplementaryActive && (anyRankFilterActive || anyCLabelFilterActive || anyEditedFilterActive || anyRecentlySavedFilterActive))) { - filter.multiselect = true; filter.showRanked[0] = anyRankFilterActive ? bUnRanked->get_active () : true; filter.showCLabeled[0] = anyCLabelFilterActive ? bUnCLabeled->get_active () : true; @@ -1650,14 +1652,28 @@ BrowserFilter FileCatalog::getFilter () //TODO could use date:;iso: etc // default will be filename - /* // this is for safe execution if getFilter is called before Query object is instantiated - Glib::ustring tempQuery; - tempQuery=""; - if (Query) tempQuery = Query->get_text(); - */ - filter.queryString = Query->get_text(); // full query string from Query Entry - filter.queryFileName = Query->get_text(); // for now Query is only by file name + Glib::ustring decodedQueryFileName = Query->get_text(); // for now Query is only by file name + // Determine the match mode - check if the first 2 characters are equal to "!=" + if (decodedQueryFileName.find("!=") == 0) { + decodedQueryFileName = decodedQueryFileName.substr(2); + filter.matchEqual = false; + } else { + filter.matchEqual = true; + } + + // Consider that queryFileName consist of comma separated values (FilterString) + // Evaluate if ANY of these FilterString are contained in the filename + // This will construct OR filter within the queryFileName + filter.vFilterStrings.clear(); + const std::vector filterStrings = Glib::Regex::split_simple(",", decodedQueryFileName.uppercase()); + for (const auto& entry : filterStrings) { + // ignore empty filterStrings. Otherwise filter will always return true if + // e.g. queryFileName ends on "," and will stop being a filter + if (!entry.empty()) { + filter.vFilterStrings.push_back(entry); + } + } return filter; } @@ -1677,49 +1693,46 @@ void FileCatalog::reparseDirectory () return; } - if (!Glib::file_test (selectedDirectory, Glib::FILE_TEST_IS_DIR)) { - closeDir (); + if (!Glib::file_test(selectedDirectory, Glib::FILE_TEST_IS_DIR)) { + closeDir(); return; } - std::vector nfileNameList = getFileList (); - // check if a thumbnailed file has been deleted - const std::vector& t = fileBrowser->getEntries (); + const std::vector& t = fileBrowser->getEntries(); std::vector fileNamesToDel; - for (size_t i = 0; i < t.size(); i++) - if (!Glib::file_test (t[i]->filename, Glib::FILE_TEST_EXISTS)) { - fileNamesToDel.push_back (t[i]->filename); + for (const auto& entry : t) { + if (!Glib::file_test(entry->filename, Glib::FILE_TEST_EXISTS)) { + fileNamesToDel.push_back(entry->filename); } - - for (size_t i = 0; i < fileNamesToDel.size(); i++) { - delete fileBrowser->delEntry (fileNamesToDel[i]); - cacheMgr->deleteEntry (fileNamesToDel[i]); - previewsLoaded--; } - if (!fileNamesToDel.empty ()) { + for (const auto& toDelete : fileNamesToDel) { + delete fileBrowser->delEntry(toDelete); + cacheMgr->deleteEntry(toDelete); + --previewsLoaded; + } + + if (!fileNamesToDel.empty()) { _refreshProgressBar(); } // check if a new file has been added - for (size_t i = 0; i < nfileNameList.size(); i++) { - bool found = false; + // build a set of collate-keys for faster search + std::set oldNames; + for (const auto& oldName : fileNameList) { + oldNames.insert(oldName.collate_key()); + } - for (size_t j = 0; j < fileNameList.size(); j++) - if (nfileNameList[i] == fileNameList[j]) { - found = true; - break; - } - - if (!found) { - checkAndAddFile (Gio::File::create_for_parse_name (nfileNameList[i])); - _refreshProgressBar (); + fileNameList = getFileList(); + for (const auto& newName : fileNameList) { + if (oldNames.find(newName.collate_key()) == oldNames.end()) { + addFile(newName); + _refreshProgressBar(); } } - fileNameList = nfileNameList; } void FileCatalog::on_dir_changed (const Glib::RefPtr& file, const Glib::RefPtr& other_file, Gio::FileMonitorEvent event_type, bool internal) @@ -1736,85 +1749,55 @@ void FileCatalog::on_dir_changed (const Glib::RefPtr& file, const Gli } } -void FileCatalog::checkAndAddFile (Glib::RefPtr file) +void FileCatalog::addFile (const Glib::ustring& fName) { - - if (!file) { - return; - } - - try { - - const auto info = file->query_info("standard::*"); - - if (!info || info->get_file_type() == Gio::FILE_TYPE_DIRECTORY) { - return; - } - - if (!options.fbShowHidden && info->is_hidden()) { - return; - } - - Glib::ustring ext; - - const auto lastdot = info->get_name().find_last_of('.'); - - if (lastdot != Glib::ustring::npos) { - ext = info->get_name().substr(lastdot + 1); - } - - if (!options.is_extention_enabled(ext)) { - return; - } - - previewLoader->add(selectedDirectoryId, file->get_parse_name(), this); + if (!fName.empty()) { + previewLoader->add(selectedDirectoryId, fName, this); previewsToLoad++; - - } catch(Gio::Error&) {} + } } void FileCatalog::addAndOpenFile (const Glib::ustring& fname) { - auto file = Gio::File::create_for_path (fname); + auto file = Gio::File::create_for_path(fname); if (!file ) { return; } - if (!file->query_exists ()) { + if (!file->query_exists()) { return; } try { - auto info = file->query_info (); + const auto info = file->query_info(); if (!info) { return; } - Glib::ustring ext; - - auto lastdot = info->get_name().find_last_of ('.'); + const auto lastdot = info->get_name().find_last_of('.'); if (lastdot != Glib::ustring::npos) { - ext = info->get_name ().substr (lastdot + 1); - } - - if (!options.is_extention_enabled(ext)) { + if (!options.is_extention_enabled(info->get_name().substr(lastdot + 1))) { + return; + } + } else { return; } + // if supported, load thumbnail first - const auto tmb = cacheMgr->getEntry (file->get_parse_name ()); + const auto tmb = cacheMgr->getEntry(file->get_parse_name()); if (!tmb) { return; } - FileBrowserEntry* entry = new FileBrowserEntry (tmb, file->get_parse_name ()); - previewReady (selectedDirectoryId, entry); + FileBrowserEntry* entry = new FileBrowserEntry(tmb, file->get_parse_name()); + previewReady(selectedDirectoryId, entry); // open the file - tmb->increaseRef (); + tmb->increaseRef(); idle_register.add( [this, tmb]() -> bool { @@ -1829,27 +1812,30 @@ void FileCatalog::addAndOpenFile (const Glib::ustring& fname) void FileCatalog::emptyTrash () { - const std::vector t = fileBrowser->getEntries (); + const auto& t = fileBrowser->getEntries(); std::vector toDel; - for (size_t i = 0; i < t.size(); i++) - if ((static_cast(t[i]))->thumbnail->getStage() == 1) { - toDel.push_back (static_cast(t[i])); + for (const auto entry : t) { + if ((static_cast(entry))->thumbnail->getStage() == 1) { + toDel.push_back(static_cast(entry)); } - - deleteRequested (toDel, false, false); - trashChanged(); + } + if (toDel.size() > 0) { + deleteRequested(toDel, false, false); + trashChanged(); + } } bool FileCatalog::trashIsEmpty () { - const std::vector t = fileBrowser->getEntries (); - for (size_t i = 0; i < t.size(); i++) - if ((static_cast(t[i]))->thumbnail->getStage() == 1) { + const auto& t = fileBrowser->getEntries(); + + for (const auto entry : t) { + if ((static_cast(entry))->thumbnail->getStage() == 1) { return false; } - + } return true; } diff --git a/rtgui/filecatalog.h b/rtgui/filecatalog.h index 4c0d13e51..09e2cc1ed 100644 --- a/rtgui/filecatalog.h +++ b/rtgui/filecatalog.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _FILECATALOG_ #define _FILECATALOG_ @@ -32,6 +32,7 @@ #include "previewloader.h" #include "multilangmgr.h" #include "threadutils.h" +#include "../rtengine/noncopyable.h" class FilePanel; /* @@ -44,7 +45,8 @@ class FileCatalog : public Gtk::VBox, public PreviewLoaderListener, public FilterPanelListener, public FileBrowserListener, - public ExportPanelListener + public ExportPanelListener, + public rtengine::NonCopyable { public: typedef sigc::slot DirSelectionSlot; @@ -141,7 +143,7 @@ private: IdleRegister idle_register; void addAndOpenFile (const Glib::ustring& fname); - void checkAndAddFile (Glib::RefPtr info); + void addFile (const Glib::ustring& fName); std::vector getFileList (); BrowserFilter getFilter (); void trashChanged (); diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index 5a344c8ba..3e23cbc5d 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "filepanel.h" @@ -358,7 +358,7 @@ void FilePanel::saveOptions () options.browserToolPanelWidth = winW - get_position(); options.browserToolPanelHeight = tpcPaned->get_position (); - if (options.startupDir == STARTUPDIR_LAST && fileCatalog->lastSelectedDir () != "") { + if (options.startupDir == STARTUPDIR_LAST && !fileCatalog->lastSelectedDir().empty()) { options.startupPath = fileCatalog->lastSelectedDir (); } diff --git a/rtgui/filepanel.h b/rtgui/filepanel.h index df61cb60d..bdeb266f4 100644 --- a/rtgui/filepanel.h +++ b/rtgui/filepanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _FILEPANEL_ #define _FILEPANEL_ @@ -31,12 +31,14 @@ #include "filterpanel.h" #include "exportpanel.h" #include "progressconnector.h" +#include "../rtengine/noncopyable.h" class RTWindow; class FilePanel final : public Gtk::HPaned, - public FileSelectionListener + public FileSelectionListener, + public rtengine::NonCopyable { public: FilePanel (); diff --git a/rtgui/fileselectionchangelistener.h b/rtgui/fileselectionchangelistener.h index 5f1b20fcc..1f3b8e612 100644 --- a/rtgui/fileselectionchangelistener.h +++ b/rtgui/fileselectionchangelistener.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _FILESELECTIONCHANGELISTENER_ #define _FILESELECTIONCHANGELISTENER_ diff --git a/rtgui/fileselectionlistener.h b/rtgui/fileselectionlistener.h index 0cac24d46..a7f7fb284 100644 --- a/rtgui/fileselectionlistener.h +++ b/rtgui/fileselectionlistener.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _FILESELECTIONLISTENER_ #define _FILESELECTIONLISTENER_ diff --git a/rtgui/filethumbnailbuttonset.cc b/rtgui/filethumbnailbuttonset.cc index 455ed8555..ef497a535 100644 --- a/rtgui/filethumbnailbuttonset.cc +++ b/rtgui/filethumbnailbuttonset.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "filethumbnailbuttonset.h" @@ -29,12 +29,14 @@ Cairo::RefPtr FileThumbnailButtonSet::unRankIcon; Cairo::RefPtr FileThumbnailButtonSet::trashIcon; Cairo::RefPtr FileThumbnailButtonSet::unTrashIcon; Cairo::RefPtr FileThumbnailButtonSet::processIcon; -Cairo::RefPtr FileThumbnailButtonSet::colorLabelIcon_0; -Cairo::RefPtr FileThumbnailButtonSet::colorLabelIcon_1; -Cairo::RefPtr FileThumbnailButtonSet::colorLabelIcon_2; -Cairo::RefPtr FileThumbnailButtonSet::colorLabelIcon_3; -Cairo::RefPtr FileThumbnailButtonSet::colorLabelIcon_4; -Cairo::RefPtr FileThumbnailButtonSet::colorLabelIcon_5; +std::array, 6> FileThumbnailButtonSet::colorLabelIcon; + +Glib::ustring FileThumbnailButtonSet::processToolTip; +Glib::ustring FileThumbnailButtonSet::unrankToolTip; +Glib::ustring FileThumbnailButtonSet::trashToolTip; +Glib::ustring FileThumbnailButtonSet::untrashToolTip; +Glib::ustring FileThumbnailButtonSet::colorLabelToolTip; +std::array FileThumbnailButtonSet::rankToolTip; FileThumbnailButtonSet::FileThumbnailButtonSet (FileBrowserEntry* myEntry) { @@ -46,73 +48,57 @@ FileThumbnailButtonSet::FileThumbnailButtonSet (FileBrowserEntry* myEntry) trashIcon = Cairo::RefPtr(new RTSurface("trash-small.png")); unTrashIcon = Cairo::RefPtr(new RTSurface("trash-remove-small.png")); processIcon = Cairo::RefPtr(new RTSurface("gears-small.png")); + colorLabelIcon[0] = Cairo::RefPtr(new RTSurface("circle-empty-gray-small.png")); + colorLabelIcon[1] = Cairo::RefPtr(new RTSurface("circle-red-small.png")); + colorLabelIcon[2] = Cairo::RefPtr(new RTSurface("circle-yellow-small.png")); + colorLabelIcon[3] = Cairo::RefPtr(new RTSurface("circle-green-small.png")); + colorLabelIcon[4] = Cairo::RefPtr(new RTSurface("circle-blue-small.png")); + colorLabelIcon[5] = Cairo::RefPtr(new RTSurface("circle-purple-small.png")); + + processToolTip = M("FILEBROWSER_POPUPPROCESS"); + unrankToolTip = M("FILEBROWSER_UNRANK_TOOLTIP"); + trashToolTip = M("FILEBROWSER_POPUPTRASH"); + untrashToolTip = M("FILEBROWSER_POPUPUNTRASH"); + colorLabelToolTip = M("FILEBROWSER_COLORLABEL_TOOLTIP"); + rankToolTip[0] = M("FILEBROWSER_RANK1_TOOLTIP"); + rankToolTip[1] = M("FILEBROWSER_RANK2_TOOLTIP"); + rankToolTip[2] = M("FILEBROWSER_RANK3_TOOLTIP"); + rankToolTip[3] = M("FILEBROWSER_RANK4_TOOLTIP"); + rankToolTip[4] = M("FILEBROWSER_RANK5_TOOLTIP"); - colorLabelIcon_0 = Cairo::RefPtr(new RTSurface("circle-empty-gray-small.png")); - colorLabelIcon_1 = Cairo::RefPtr(new RTSurface("circle-red-small.png")); - colorLabelIcon_2 = Cairo::RefPtr(new RTSurface("circle-yellow-small.png")); - colorLabelIcon_3 = Cairo::RefPtr(new RTSurface("circle-green-small.png")); - colorLabelIcon_4 = Cairo::RefPtr(new RTSurface("circle-blue-small.png")); - colorLabelIcon_5 = Cairo::RefPtr(new RTSurface("circle-purple-small.png"));; iconsLoaded = true; } - add (new LWButton (processIcon, 6, myEntry, LWButton::Left, LWButton::Center, M("FILEBROWSER_POPUPPROCESS"))); - add (new LWButton (unRankIcon, 0, myEntry, LWButton::Left, LWButton::Center, M("FILEBROWSER_UNRANK_TOOLTIP"))); + add(new LWButton(processIcon, 6, myEntry, LWButton::Left, LWButton::Center, &processToolTip)); + add(new LWButton(unRankIcon, 0, myEntry, LWButton::Left, LWButton::Center, &unrankToolTip)); for (int i = 0; i < 5; i++) { - add (new LWButton (rankIcon, i + 1, myEntry, LWButton::Left)); + add(new LWButton(rankIcon, i + 1, myEntry, LWButton::Left, LWButton::Center, &rankToolTip[i])); } - add (new LWButton (trashIcon, 7, myEntry, LWButton::Right, LWButton::Center, M("FILEBROWSER_POPUPTRASH"))); - - add (new LWButton (colorLabelIcon_0, 8, myEntry, LWButton::Right, LWButton::Center, M("FILEBROWSER_COLORLABEL_TOOLTIP"))); - - buttons[2]->setToolTip (M("FILEBROWSER_RANK1_TOOLTIP")); - buttons[3]->setToolTip (M("FILEBROWSER_RANK2_TOOLTIP")); - buttons[4]->setToolTip (M("FILEBROWSER_RANK3_TOOLTIP")); - buttons[5]->setToolTip (M("FILEBROWSER_RANK4_TOOLTIP")); - buttons[6]->setToolTip (M("FILEBROWSER_RANK5_TOOLTIP")); + add(new LWButton(trashIcon, 7, myEntry, LWButton::Right, LWButton::Center, &trashToolTip)); + add(new LWButton(colorLabelIcon[0], 8, myEntry, LWButton::Right, LWButton::Center, &colorLabelToolTip)); } void FileThumbnailButtonSet::setRank (int stars) { for (int i = 1; i <= 5; i++) { - buttons[i + 1]->setIcon (i <= stars ? rankIcon : gRankIcon); + buttons[i + 1]->setIcon(i <= stars ? rankIcon : gRankIcon); } } void FileThumbnailButtonSet::setColorLabel (int colorLabel) { - if (colorLabel == 0) { - buttons[8]->setIcon (colorLabelIcon_0); //transparent label - } - - if (colorLabel == 1) { - buttons[8]->setIcon (colorLabelIcon_1); - } - - if (colorLabel == 2) { - buttons[8]->setIcon (colorLabelIcon_2); - } - - if (colorLabel == 3) { - buttons[8]->setIcon (colorLabelIcon_3); - } - - if (colorLabel == 4) { - buttons[8]->setIcon (colorLabelIcon_4); - } - - if (colorLabel == 5) { - buttons[8]->setIcon (colorLabelIcon_5); + if (colorLabel >= 0 && colorLabel <= 5) { + buttons[8]->setIcon(colorLabelIcon[colorLabel]); } } void FileThumbnailButtonSet::setInTrash (bool inTrash) { - buttons[7]->setIcon (inTrash ? unTrashIcon : trashIcon); - buttons[7]->setToolTip (inTrash ? M("FILEBROWSER_POPUPUNTRASH") : M("FILEBROWSER_POPUPTRASH")); + buttons[7]->setIcon(inTrash ? unTrashIcon : trashIcon); + buttons[7]->setToolTip(inTrash ? &untrashToolTip : &trashToolTip); } diff --git a/rtgui/filethumbnailbuttonset.h b/rtgui/filethumbnailbuttonset.h index 57811addd..102b573c8 100644 --- a/rtgui/filethumbnailbuttonset.h +++ b/rtgui/filethumbnailbuttonset.h @@ -14,11 +14,13 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _FILETHUMBNAILBUTTONSET_ #define _FILETHUMBNAILBUTTONSET_ +#include + #include "lwbuttonset.h" #include #include "filebrowserentry.h" @@ -38,12 +40,14 @@ public: static Cairo::RefPtr unTrashIcon; static Cairo::RefPtr processIcon; - static Cairo::RefPtr colorLabelIcon_0; - static Cairo::RefPtr colorLabelIcon_1; - static Cairo::RefPtr colorLabelIcon_2; - static Cairo::RefPtr colorLabelIcon_3; - static Cairo::RefPtr colorLabelIcon_4; - static Cairo::RefPtr colorLabelIcon_5; + static std::array, 6> colorLabelIcon; + + static Glib::ustring processToolTip; + static Glib::ustring unrankToolTip; + static Glib::ustring trashToolTip; + static Glib::ustring untrashToolTip; + static Glib::ustring colorLabelToolTip; + static std::array rankToolTip; explicit FileThumbnailButtonSet (FileBrowserEntry* myEntry); void setRank (int stars); diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc new file mode 100644 index 000000000..90cedf148 --- /dev/null +++ b/rtgui/filmnegative.cc @@ -0,0 +1,313 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2019 Alberto Romei + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include + +#include "filmnegative.h" + +#include "editwidgets.h" +#include "eventmapper.h" +#include "options.h" +#include "rtimage.h" + +#include "../rtengine/procparams.h" + +namespace +{ + +Adjuster* createExponentAdjuster(AdjusterListener* listener, const Glib::ustring& label, double minV, double maxV, double defaultVal) +{ + Adjuster* const adj = Gtk::manage(new Adjuster(label, minV, maxV, 0.001, defaultVal)); + adj->setAdjusterListener(listener); + adj->setLogScale(6, 1, true); + + if (adj->delay < options.adjusterMaxDelay) { + adj->delay = options.adjusterMaxDelay; + } + + adj->show(); + return adj; +} + +} + +FilmNegative::FilmNegative() : + FoldableToolPanel(this, "filmnegative", M("TP_FILMNEGATIVE_LABEL"), false, true), + EditSubscriber(ET_OBJECTS), + evFilmNegativeExponents(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_VALUES")), + evFilmNegativeEnabled(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_ENABLED")), + fnp(nullptr), + greenExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_GREEN"), 0.3, 4, 1.5)), // master exponent (green channel) + redRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_RED"), 0.3, 3, (2.04 / 1.5))), // ratio of red exponent to master exponent + blueRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_BLUE"), 0.3, 3, (1.29 / 1.5))), // ratio of blue exponent to master exponent + spotgrid(Gtk::manage(new Gtk::Grid())), + spotbutton(Gtk::manage(new Gtk::ToggleButton(M("TP_FILMNEGATIVE_PICK")))) +{ + spotgrid->get_style_context()->add_class("grid-spacing"); + setExpandAlignProperties(spotgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + + setExpandAlignProperties(spotbutton, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + spotbutton->get_style_context()->add_class("independent"); + spotbutton->set_tooltip_text(M("TP_FILMNEGATIVE_GUESS_TOOLTIP")); + spotbutton->set_image (*Gtk::manage (new RTImage ("color-picker-small.png"))); + + // TODO make spot size configurable ? + + // Gtk::Label* slab = Gtk::manage (new Gtk::Label (M("TP_WBALANCE_SIZE"))); + // setExpandAlignProperties(slab, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + + // Gtk::Grid* wbsizehelper = Gtk::manage(new Gtk::Grid()); + // wbsizehelper->set_name("WB-Size-Helper"); + // setExpandAlignProperties(wbsizehelper, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + + // spotsize = Gtk::manage (new MyComboBoxText ()); + // setExpandAlignProperties(spotsize, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + // spotsize->append ("2"); + // spotsize->set_active(0); + // spotsize->append ("4"); + + spotgrid->attach (*spotbutton, 0, 1, 1, 1); + // spotgrid->attach (*slab, 1, 0, 1, 1); + // spotgrid->attach (*wbsizehelper, 2, 0, 1, 1); + + pack_start(*greenExp, Gtk::PACK_SHRINK, 0); + pack_start(*redRatio, Gtk::PACK_SHRINK, 0); + pack_start(*blueRatio, Gtk::PACK_SHRINK, 0); + pack_start(*spotgrid, Gtk::PACK_SHRINK, 0); + + spotbutton->signal_toggled().connect(sigc::mem_fun(*this, &FilmNegative::editToggled)); + // spotsize->signal_changed().connect( sigc::mem_fun(*this, &WhiteBalance::spotSizeChanged) ); + + // Editing geometry; create the spot rectangle + Rectangle* const spotRect = new Rectangle(); + spotRect->filled = false; + + visibleGeometry.push_back(spotRect); + + // Stick a dummy rectangle over the whole image in mouseOverGeometry. + // This is to make sure the getCursor() call is fired everywhere. + Rectangle* const imgRect = new Rectangle(); + imgRect->filled = true; + + mouseOverGeometry.push_back(imgRect); +} + +FilmNegative::~FilmNegative() +{ + for (auto geometry : visibleGeometry) { + delete geometry; + } + + for (auto geometry : mouseOverGeometry) { + delete geometry; + } +} + +void FilmNegative::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + disableListener(); + + if (pedited) { + redRatio->setEditedState(pedited->filmNegative.redRatio ? Edited : UnEdited); + greenExp->setEditedState(pedited->filmNegative.greenExp ? Edited : UnEdited); + blueRatio->setEditedState(pedited->filmNegative.blueRatio ? Edited : UnEdited); + set_inconsistent(multiImage && !pedited->filmNegative.enabled); + } + + setEnabled(pp->filmNegative.enabled); + redRatio->setValue(pp->filmNegative.redRatio); + greenExp->setValue(pp->filmNegative.greenExp); + blueRatio->setValue(pp->filmNegative.blueRatio); + + enableListener(); +} + +void FilmNegative::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + pp->filmNegative.redRatio = redRatio->getValue(); + pp->filmNegative.greenExp = greenExp->getValue(); + pp->filmNegative.blueRatio = blueRatio->getValue(); + pp->filmNegative.enabled = getEnabled(); + + if (pedited) { + pedited->filmNegative.redRatio = redRatio->getEditedState(); + pedited->filmNegative.greenExp = greenExp->getEditedState(); + pedited->filmNegative.blueRatio = blueRatio->getEditedState(); + pedited->filmNegative.enabled = !get_inconsistent(); + } +} + +void FilmNegative::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + redRatio->setValue(defParams->filmNegative.redRatio); + greenExp->setValue(defParams->filmNegative.greenExp); + blueRatio->setValue(defParams->filmNegative.blueRatio); + + if (pedited) { + redRatio->setDefaultEditedState(pedited->filmNegative.redRatio ? Edited : UnEdited); + greenExp->setDefaultEditedState(pedited->filmNegative.greenExp ? Edited : UnEdited); + blueRatio->setDefaultEditedState(pedited->filmNegative.blueRatio ? Edited : UnEdited); + } else { + redRatio->setDefaultEditedState(Irrelevant); + greenExp->setDefaultEditedState(Irrelevant); + blueRatio->setDefaultEditedState(Irrelevant); + } +} + +void FilmNegative::setBatchMode(bool batchMode) +{ + if (batchMode) { + spotConn.disconnect(); + removeIfThere(this, spotgrid, false); + ToolPanel::setBatchMode(batchMode); + redRatio->showEditedCB(); + greenExp->showEditedCB(); + blueRatio->showEditedCB(); + } +} + +void FilmNegative::adjusterChanged(Adjuster* a, double newval) +{ + if (listener) { + if (a == redRatio || a == greenExp || a == blueRatio) { + if (getEnabled()) { + listener->panelChanged( + evFilmNegativeExponents, + Glib::ustring::compose( + "Ref=%1\nR=%2\nB=%3", + greenExp->getValue(), + redRatio->getValue(), + blueRatio->getValue() + ) + ); + } + } + } +} + +void FilmNegative::enabledChanged() +{ + if (listener) { + if (get_inconsistent()) { + listener->panelChanged(evFilmNegativeEnabled, M("GENERAL_UNCHANGED")); + } + else if (getEnabled()) { + listener->panelChanged(evFilmNegativeEnabled, M("GENERAL_ENABLED")); + } + else { + listener->panelChanged(evFilmNegativeEnabled, M("GENERAL_DISABLED")); + } + } +} + +void FilmNegative::setFilmNegProvider(FilmNegProvider* provider) +{ + fnp = provider; +} + +void FilmNegative::setEditProvider(EditDataProvider* provider) +{ + EditSubscriber::setEditProvider(provider); +} + +CursorShape FilmNegative::getCursor(int objectID) const +{ + return CSSpotWB; +} + +bool FilmNegative::mouseOver(int modifierKey) +{ + EditDataProvider* const provider = getEditProvider(); + Rectangle* const spotRect = static_cast(visibleGeometry.at(0)); + spotRect->setXYWH(provider->posImage.x - 16, provider->posImage.y - 16, 32, 32); + + return true; +} + +bool FilmNegative::button1Pressed(int modifierKey) +{ + EditDataProvider* const provider = getEditProvider(); + + EditSubscriber::action = EditSubscriber::Action::NONE; + + if (listener) { + refSpotCoords.push_back(provider->posImage); + + if (refSpotCoords.size() == 2) { + // User has selected 2 reference gray spots. Calculating new exponents + // from channel values and updating parameters. + + std::array newExps; + if (fnp->getFilmNegativeExponents(refSpotCoords[0], refSpotCoords[1], newExps)) { + disableListener(); + // Leaving green exponent unchanged, setting red and blue exponents based on + // the ratios between newly calculated exponents. + redRatio->setValue(newExps[0] / newExps[1]); + blueRatio->setValue(newExps[2] / newExps[1]); + enableListener(); + + if (listener && getEnabled()) { + listener->panelChanged( + evFilmNegativeExponents, + Glib::ustring::compose( + "Ref=%1\nR=%2\nB=%3", + greenExp->getValue(), + redRatio->getValue(), + blueRatio->getValue() + ) + ); + } + } + + switchOffEditMode(); + } + } + + return true; +} + +bool FilmNegative::button1Released() +{ + EditSubscriber::action = EditSubscriber::Action::NONE; + return true; +} + +void FilmNegative::switchOffEditMode() +{ + refSpotCoords.clear(); + unsubscribe(); + spotbutton->set_active(false); +} + +void FilmNegative::editToggled() +{ + if (spotbutton->get_active()) { + subscribe(); + + int w, h; + getEditProvider()->getImageSize(w, h); + + // Stick a dummy rectangle over the whole image in mouseOverGeometry. + // This is to make sure the getCursor() call is fired everywhere. + Rectangle* const imgRect = static_cast(mouseOverGeometry.at(0)); + imgRect->setXYWH(0, 0, w, h); + } else { + refSpotCoords.clear(); + unsubscribe(); + } +} diff --git a/rtgui/filmnegative.h b/rtgui/filmnegative.h new file mode 100644 index 000000000..85919bef9 --- /dev/null +++ b/rtgui/filmnegative.h @@ -0,0 +1,85 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2019 Alberto Romei + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#pragma once + +#include + +#include + +#include "adjuster.h" +#include "editcallbacks.h" +#include "guiutils.h" +#include "toolpanel.h" +#include "wbprovider.h" + +class FilmNegProvider +{ +public: + virtual ~FilmNegProvider() = default; + + virtual bool getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, std::array& newExps) = 0; +}; + +class FilmNegative : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public EditSubscriber +{ +public: + FilmNegative(); + ~FilmNegative() override; + + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; + void setBatchMode(bool batchMode) override; + + void adjusterChanged(Adjuster* a, double newval) override; + void enabledChanged() override; + + void setFilmNegProvider(FilmNegProvider* provider); + + void setEditProvider(EditDataProvider* provider) override; + + // EditSubscriber interface + CursorShape getCursor(int objectID) const override; + bool mouseOver(int modifierKey) override; + bool button1Pressed(int modifierKey) override; + bool button1Released() override; + void switchOffEditMode() override; + +private: + void editToggled(); + + const rtengine::ProcEvent evFilmNegativeExponents; + const rtengine::ProcEvent evFilmNegativeEnabled; + + std::vector refSpotCoords; + + FilmNegProvider* fnp; + + Adjuster* const greenExp; + Adjuster* const redRatio; + Adjuster* const blueRatio; + + Gtk::Grid* const spotgrid; + Gtk::ToggleButton* const spotbutton; + sigc::connection spotConn; +}; diff --git a/rtgui/filmsimulation.cc b/rtgui/filmsimulation.cc index 734b46c34..6b40bb586 100644 --- a/rtgui/filmsimulation.cc +++ b/rtgui/filmsimulation.cc @@ -115,10 +115,6 @@ void FilmSimulation::adjusterChanged(Adjuster* a, double newval) } } -void FilmSimulation::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void FilmSimulation::setBatchMode( bool batchMode ) { ToolPanel::setBatchMode( batchMode ); diff --git a/rtgui/filmsimulation.h b/rtgui/filmsimulation.h index c55662757..b5c9ffa6b 100644 --- a/rtgui/filmsimulation.h +++ b/rtgui/filmsimulation.h @@ -56,7 +56,6 @@ public: FilmSimulation(); void adjusterChanged(Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void setBatchMode(bool batchMode) override; void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; diff --git a/rtgui/filterpanel.cc b/rtgui/filterpanel.cc index c140acfb0..301a7b188 100644 --- a/rtgui/filterpanel.cc +++ b/rtgui/filterpanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "filterpanel.h" #include "multilangmgr.h" diff --git a/rtgui/filterpanel.h b/rtgui/filterpanel.h index 7f32a88d9..e6e41a416 100644 --- a/rtgui/filterpanel.h +++ b/rtgui/filterpanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _FILTERPANEL_ #define _FILTERPANEL_ diff --git a/rtgui/flatcurveeditorsubgroup.cc b/rtgui/flatcurveeditorsubgroup.cc index 376bb55c2..6dc3a1f5b 100644 --- a/rtgui/flatcurveeditorsubgroup.cc +++ b/rtgui/flatcurveeditorsubgroup.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "clipboard.h" diff --git a/rtgui/flatcurveeditorsubgroup.h b/rtgui/flatcurveeditorsubgroup.h index ab2abedfb..e9253cd08 100644 --- a/rtgui/flatcurveeditorsubgroup.h +++ b/rtgui/flatcurveeditorsubgroup.h @@ -14,17 +14,18 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _FLATCURVEEDITORSUBGROUP_ #define _FLATCURVEEDITORSUBGROUP_ #include #include "curveeditorgroup.h" +#include "../rtengine/noncopyable.h" class FlatCurveEditor; -class FlatCurveEditorSubGroup: public CurveEditorSubGroup +class FlatCurveEditorSubGroup: public CurveEditorSubGroup, public rtengine::NonCopyable { friend class FlatCurveEditor; diff --git a/rtgui/flatfield.cc b/rtgui/flatfield.cc index 3cbd7acf1..03204c037 100644 --- a/rtgui/flatfield.cc +++ b/rtgui/flatfield.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -86,7 +86,6 @@ FlatField::FlatField () : FoldableToolPanel(this, "flatfield", M("TP_FLATFIELD_L flatFieldFileReset->signal_clicked().connect( sigc::mem_fun(*this, &FlatField::flatFieldFile_Reset), true ); flatFieldAutoSelectconn = flatFieldAutoSelect->signal_toggled().connect ( sigc::mem_fun(*this, &FlatField::flatFieldAutoSelectChanged), true); flatFieldBlurTypeconn = flatFieldBlurType->signal_changed().connect( sigc::mem_fun(*this, &FlatField::flatFieldBlurTypeChanged) ); - lastShortcutPath = ""; // Set filename filters b_filter_asCurrent = false; @@ -192,7 +191,7 @@ void FlatField::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi Glib::ustring fname = Glib::path_get_basename(ffp->GetCurrentImageFilePath()); Glib::ustring filetype; - if (fname != "") { + if (!fname.empty()) { // get image filetype, set filter to the same as current image's filetype std::string::size_type idx; idx = fname.rfind('.'); diff --git a/rtgui/flatfield.h b/rtgui/flatfield.h index 46e2f6ddd..b9997f65e 100644 --- a/rtgui/flatfield.h +++ b/rtgui/flatfield.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _FLATFIELD_H_ #define _FLATFIELD_H_ diff --git a/rtgui/gradient.cc b/rtgui/gradient.cc index 4961597bb..4f389e112 100644 --- a/rtgui/gradient.cc +++ b/rtgui/gradient.cc @@ -93,7 +93,7 @@ Gradient::Gradient () : FoldableToolPanel(this, "gradient", M("TP_GRADIENT_LABEL centerCircle = new Circle(); centerCircle->datum = Geometry::IMAGE; centerCircle->radiusInImageSpace = false; - centerCircle->radius = 30; + centerCircle->radius = 12; centerCircle->filled = true; EditSubscriber::mouseOverGeometry.push_back( hLine ); @@ -269,10 +269,6 @@ void Gradient::adjusterChanged(Adjuster* a, double newval) } } -void Gradient::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void Gradient::enabledChanged () { @@ -426,9 +422,7 @@ bool Gradient::button1Pressed(int modifierKey) double diagonal = sqrt(double(imW) * double(imW) + double(imH) * double(imH)); // trick to get the correct angle (clockwise/counter-clockwise) - int p = centerPos.y; - centerPos.y = currPos.y; - currPos.y = p; + std::swap(centerPos.y, currPos.y); draggedPoint = currPos - centerPos; // compute the projected value of the dragged point diff --git a/rtgui/gradient.h b/rtgui/gradient.h index 8aa4a5339..05a267a0d 100644 --- a/rtgui/gradient.h +++ b/rtgui/gradient.h @@ -43,7 +43,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void enabledChanged () override; void setAdjusterBehavior (bool degreeadd, bool featheradd, bool strengthadd, bool centeradd); void trimValues (rtengine::procparams::ProcParams* pp) override; diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index eb3704076..189cf6178 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -13,7 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include "../rtengine/rt_math.h" @@ -298,17 +298,14 @@ void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int cr->line_to (rectx1, recty1); cr->stroke (); cr->set_source_rgba (0.0, 0.0, 0.0, 0.618); - std::valarray ds (1); - ds[0] = 4; - cr->set_dash (ds, 0); + cr->set_dash (std::valarray({4}), 0); cr->move_to (rectx1, recty1); cr->line_to (rectx2, recty1); cr->line_to (rectx2, recty2); cr->line_to (rectx1, recty2); cr->line_to (rectx1, recty1); cr->stroke (); - ds.resize (0); - cr->set_dash (ds, 0); + cr->set_dash (std::valarray(), 0); if (cparams.guide != "Rule of diagonals" && cparams.guide != "Golden Triangle 1" && cparams.guide != "Golden Triangle 2") { // draw guide lines @@ -446,14 +443,11 @@ void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int cr->line_to (rectx2, recty2); cr->stroke (); cr->set_source_rgba (0.0, 0.0, 0.0, 0.618); - std::valarray ds (1); - ds[0] = 4; - cr->set_dash (ds, 0); + cr->set_dash (std::valarray({4}), 0); cr->move_to (rectx1, recty1); cr->line_to (rectx2, recty2); cr->stroke (); - ds.resize (0); - cr->set_dash (ds, 0); + cr->set_dash (std::valarray(), 0); double height = recty2 - recty1; double width = rectx2 - rectx1; @@ -470,14 +464,11 @@ void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int cr->line_to (rectx1 + x, recty1 + y); cr->stroke (); cr->set_source_rgba (0.0, 0.0, 0.0, 0.618); - ds.resize (1); - ds[0] = 4; - cr->set_dash (ds, 0); + cr->set_dash (std::valarray({4}), 0); cr->move_to (rectx1, recty2); cr->line_to (rectx1 + x, recty1 + y); cr->stroke (); - ds.resize (0); - cr->set_dash (ds, 0); + cr->set_dash (std::valarray(), 0); x = width - (a * b) / height; y = (b * (d - a)) / width; @@ -486,14 +477,11 @@ void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int cr->line_to (rectx1 + x, recty1 + y); cr->stroke (); cr->set_source_rgba (0.0, 0.0, 0.0, 0.618); - ds.resize (1); - ds[0] = 4; - cr->set_dash (ds, 0); + cr->set_dash (std::valarray({4}), 0); cr->move_to (rectx2, recty1); cr->line_to (rectx1 + x, recty1 + y); cr->stroke (); - ds.resize (0); - cr->set_dash (ds, 0); + cr->set_dash (std::valarray(), 0); } } @@ -675,12 +663,6 @@ MyExpander::MyExpander(bool useEnabled, Glib::ustring titleLabel) : statusImage->set_can_focus(false); - Glib::ustring str("-"); - - if (!titleLabel.empty()) { - str = titleLabel; - } - label = Gtk::manage(new Gtk::Label()); setExpandAlignProperties(label, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); label->set_markup(Glib::ustring("") + escapeHtmlChars(titleLabel) + Glib::ustring("")); @@ -970,39 +952,27 @@ bool MyScrolledWindow::on_scroll_event (GdkEventScroll* event) Gtk::Scrollbar *scroll = get_vscrollbar(); if (adjust && scroll) { - double upper = adjust->get_upper(); - double lower = adjust->get_lower(); + const double upperBound = adjust->get_upper(); + const double lowerBound = adjust->get_lower(); double value = adjust->get_value(); double step = adjust->get_step_increment(); double value2 = 0.; -// printf("MyScrolledwindow::on_scroll_event / delta_x=%.5f, delta_y=%.5f, direction=%d, type=%d, send_event=%d\n", -// event->delta_x, event->delta_y, (int)event->direction, (int)event->type, event->send_event); - if (event->direction == GDK_SCROLL_DOWN) { - value2 = value + step; - - if (value2 > upper) { - value2 = upper; - } + value2 = rtengine::min(value + step, upperBound); if (value2 != value) { scroll->set_value(value2); } } else if (event->direction == GDK_SCROLL_UP) { - value2 = value - step; - - if (value2 < lower) { - value2 = lower; - } + value2 = rtengine::max(value - step, lowerBound); if (value2 != value) { scroll->set_value(value2); } } else if (event->direction == GDK_SCROLL_SMOOTH) { - if (abs(event->delta_y) > 0.1) { - value2 = rtengine::LIM(value + (event->delta_y > 0 ? step : -step), lower, upper); - } + value2 = rtengine::LIM(value + event->delta_y * step, lowerBound, upperBound); + if (value2 != value) { scroll->set_value(value2); } @@ -1050,8 +1020,8 @@ bool MyScrolledToolbar::on_scroll_event (GdkEventScroll* event) Gtk::Scrollbar *scroll = get_hscrollbar(); if (adjust && scroll) { - double upper = adjust->get_upper(); - double lower = adjust->get_lower(); + const double upperBound = adjust->get_upper(); + const double lowerBound = adjust->get_lower(); double value = adjust->get_value(); double step = adjust->get_step_increment() * 2; double value2 = 0.; @@ -1060,20 +1030,20 @@ bool MyScrolledToolbar::on_scroll_event (GdkEventScroll* event) // event->delta_x, event->delta_y, (int)event->direction, (int)event->type, event->send_event); if (event->direction == GDK_SCROLL_DOWN) { - value2 = rtengine::min(value + step, upper); + value2 = rtengine::min(value + step, upperBound); if (value2 != value) { scroll->set_value(value2); } } else if (event->direction == GDK_SCROLL_UP) { - value2 = rtengine::max(value - step, lower); + value2 = rtengine::max(value - step, lowerBound); if (value2 != value) { scroll->set_value(value2); } } else if (event->direction == GDK_SCROLL_SMOOTH) { if (event->delta_x) { // if the user use a pad, it can scroll horizontally - value2 = rtengine::LIM(value + (event->delta_x > 0 ? 30 : -30), lower, upper); + value2 = rtengine::LIM(value + (event->delta_x > 0 ? 30 : -30), lowerBound, upperBound); } else if (event->delta_y) { - value2 = rtengine::LIM(value + (event->delta_y > 0 ? 30 : -30), lower, upper); + value2 = rtengine::LIM(value + (event->delta_y > 0 ? 30 : -30), lowerBound, upperBound); } if (value2 != value) { scroll->set_value(value2); @@ -1604,7 +1574,7 @@ bool BackBuffer::setDrawRectangle(Glib::RefPtr window, int newX, in x = newX; y = newY; - if (newH > 0) { + if (newW > 0) { w = newW; } if (newH > 0) { @@ -1637,7 +1607,7 @@ bool BackBuffer::setDrawRectangle(Cairo::Format format, int newX, int newY, int x = newX; y = newY; - if (newH > 0) { + if (newW > 0) { w = newW; } if (newH > 0) { diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index e4c38f347..b09e20abb 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __GUI_UTILS_ #define __GUI_UTILS_ @@ -400,7 +400,7 @@ protected: void set_none(); public: - MyFileChooserButton(const Glib::ustring &title, Gtk::FileChooserAction action=Gtk::FILE_CHOOSER_ACTION_OPEN); + explicit MyFileChooserButton(const Glib::ustring &title, Gtk::FileChooserAction action=Gtk::FILE_CHOOSER_ACTION_OPEN); sigc::signal &signal_selection_changed(); sigc::signal &signal_file_set(); diff --git a/rtgui/histogrampanel.cc b/rtgui/histogrampanel.cc index 49960b2db..36803ddf2 100644 --- a/rtgui/histogrampanel.cc +++ b/rtgui/histogrampanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "histogrampanel.h" #include "multilangmgr.h" @@ -142,7 +142,7 @@ HistogramPanel::HistogramPanel () showGreen->set_image (showGreen->get_active() ? *greenImage : *greenImage_g); showBlue->set_image (showBlue->get_active() ? *blueImage : *blueImage_g); showValue->set_image (showValue->get_active() ? *valueImage : *valueImage_g); - showChro->set_image (showChro->get_active() ? *chroImage : *chroImage_g); + showChro->set_image (showChro->get_active() ? *chroImage : *chroImage_g); showRAW->set_image (showRAW->get_active() ? *rawImage : *rawImage_g); if (options.histogramDrawMode == 0) showMode->set_image(*mode0Image); @@ -151,6 +151,8 @@ HistogramPanel::HistogramPanel () else showMode->set_image(*mode2Image); showBAR->set_image (showBAR->get_active() ? *barImage : *barImage_g); + + raw_toggled(); // Make sure the luma/chroma toggles are enabled or disabled setExpandAlignProperties(showRed , false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); setExpandAlignProperties(showGreen, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); @@ -464,7 +466,6 @@ void HistogramRGBArea::updateBackBuffer (int r, int g, int b, const Glib::ustrin if (surface) { Cairo::RefPtr cc = Cairo::Context::create(surface); - Glib::RefPtr style = get_style_context(); cc->set_source_rgba (0., 0., 0., 0.); cc->set_operator (Cairo::OPERATOR_CLEAR); @@ -503,7 +504,7 @@ void HistogramRGBArea::updateBackBuffer (int r, int g, int b, const Glib::ustrin if (needBlue) { // Blue - cc->set_source_rgb(0.0, 0.0, 1.0); + cc->set_source_rgb(0.0, 0.4, 1.0); if (options.histogramDrawMode < 2) { cc->move_to(b * (winw - 1.) / 255.0 + 0.5*s, 0); cc->line_to(b * (winw - 1.) / 255.0 + 0.5*s, winh - 0); @@ -616,7 +617,6 @@ void HistogramRGBArea::on_realize () { Gtk::DrawingArea::on_realize(); - Glib::RefPtr window = get_window(); add_events(Gdk::BUTTON_PRESS_MASK); } @@ -964,7 +964,7 @@ void HistogramArea::updateBackBuffer () if (needBlue) { drawCurve(cr, bhchanged, realhistheight, w, h); - cr->set_source_rgb (0.0, 0.0, 1.0); + cr->set_source_rgb (0.0, 0.4, 1.0); cr->stroke (); drawMarks(cr, bhchanged, realhistheight, w, ui, oi); } @@ -984,7 +984,6 @@ void HistogramArea::on_realize () { Gtk::DrawingArea::on_realize(); - Glib::RefPtr window = get_window(); add_events(Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK); } @@ -1037,8 +1036,6 @@ void HistogramArea::drawMarks(Cairo::RefPtr &cr, bool HistogramArea::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) { - Glib::RefPtr window = get_window(); - if (get_width() != oldwidth || get_height() != oldheight || isDirty ()) { updateBackBuffer (); } diff --git a/rtgui/histogrampanel.h b/rtgui/histogrampanel.h index f34b07c39..1515db97a 100644 --- a/rtgui/histogrampanel.h +++ b/rtgui/histogrampanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _HISTOGRAMPANEL_ #define _HISTOGRAMPANEL_ @@ -28,6 +28,7 @@ #include "guiutils.h" #include "pointermotionlistener.h" +#include "../rtengine/noncopyable.h" class HistogramArea; struct HistogramAreaIdleHelper { @@ -51,7 +52,7 @@ public: double log (double vsize, double val); }; -class HistogramRGBArea : public Gtk::DrawingArea, public BackBuffer, private HistogramScaling +class HistogramRGBArea : public Gtk::DrawingArea, public BackBuffer, private HistogramScaling, public rtengine::NonCopyable { private: typedef const double (*TMatrix)[3]; @@ -114,7 +115,7 @@ public: virtual void toggleButtonMode() = 0; }; -class HistogramArea : public Gtk::DrawingArea, public BackBuffer, private HistogramScaling +class HistogramArea : public Gtk::DrawingArea, public BackBuffer, private HistogramScaling, public rtengine::NonCopyable { public: typedef sigc::signal type_signal_factor_changed; @@ -172,7 +173,7 @@ private: void get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const override; }; -class HistogramPanel : public Gtk::Grid, public PointerMotionListener, public DrawModeListener +class HistogramPanel : public Gtk::Grid, public PointerMotionListener, public DrawModeListener, public rtengine::NonCopyable { protected: diff --git a/rtgui/history.cc b/rtgui/history.cc index ec5e006bc..5305c258b 100644 --- a/rtgui/history.cc +++ b/rtgui/history.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "history.h" diff --git a/rtgui/history.h b/rtgui/history.h index 196b29b67..abf0d1ba5 100644 --- a/rtgui/history.h +++ b/rtgui/history.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _HISTORY_ #define _HISTORY_ diff --git a/rtgui/hsvequalizer.cc b/rtgui/hsvequalizer.cc index f489696d2..b6b5b04f2 100644 --- a/rtgui/hsvequalizer.cc +++ b/rtgui/hsvequalizer.cc @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * 2010 Ilya Popov */ diff --git a/rtgui/hsvequalizer.h b/rtgui/hsvequalizer.h index 8d34b486b..2ffa9fa0f 100644 --- a/rtgui/hsvequalizer.h +++ b/rtgui/hsvequalizer.h @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * 2010 Ilya Popov */ diff --git a/rtgui/iccprofilecreator.cc b/rtgui/iccprofilecreator.cc index e5172c7e7..9efa4360b 100644 --- a/rtgui/iccprofilecreator.cc +++ b/rtgui/iccprofilecreator.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include "iccprofilecreator.h" @@ -389,10 +389,6 @@ void ICCProfileCreator::adjusterChanged(Adjuster* a, double newval) } } -void ICCProfileCreator::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void ICCProfileCreator::primariesChanged() { if (primaries->get_active_row_number() > 0) { @@ -678,8 +674,6 @@ void ICCProfileCreator::savePressed() //necessary for V2 profile if (!v2except) { - std::string is_RTv4 = ""; - //used partially for v4, and in case of if we want to back to old manner for v2 if (primariesPreset == "ACES-AP0" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.ACESp0)) { sNewProfile = options.rtSettings.ACESp0; @@ -691,11 +685,9 @@ void ICCProfileCreator::savePressed() sNewProfile = options.rtSettings.adobe; sPrimariesPreset = "Medium"; } else if (primariesPreset == "ProPhoto" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.prophoto)) { - is_RTv4 = options.rtSettings.prophoto.substr(0, 4); - - if (is_RTv4 == "RTv4") { + if (options.rtSettings.prophoto.substr(0, 4) == "RTv4") { options.rtSettings.prophoto = "RTv2_Large"; - }; + } sNewProfile = options.rtSettings.prophoto; @@ -707,32 +699,26 @@ void ICCProfileCreator::savePressed() sNewProfile = options.rtSettings.srgb; sPrimariesPreset = "sRGB"; } else if (primariesPreset == "Widegamut" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.widegamut)) { - is_RTv4 = options.rtSettings.widegamut.substr(0, 4); - - if (is_RTv4 == "RTv4") { + if (options.rtSettings.widegamut.substr(0, 4) == "RTv4") { options.rtSettings.widegamut = "RTv2_Wide"; - }; + } sNewProfile = options.rtSettings.widegamut; sPrimariesPreset = "Wide"; } else if (primariesPreset == "BestRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.best)) { - is_RTv4 = options.rtSettings.best.substr(0, 4); - - if (is_RTv4 == "RTv4") { + if (options.rtSettings.best.substr(0, 4) == "RTv4") { options.rtSettings.best = "RTv2_Best"; - }; + } sNewProfile = options.rtSettings.best; sPrimariesPreset = "Best"; } else if (primariesPreset == "BetaRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.beta)) { sNewProfile = options.rtSettings.beta; - is_RTv4 = options.rtSettings.beta.substr(0, 4); - - if (is_RTv4 == "RTv4") { + if (options.rtSettings.beta.substr(0, 4) == "RTv4") { options.rtSettings.widegamut = "RTv2_Beta"; - }; + } sPrimariesPreset = "Beta"; } else if (primariesPreset == "BruceRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.bruce)) { diff --git a/rtgui/iccprofilecreator.h b/rtgui/iccprofilecreator.h index 23e5b86c8..b28ac29f2 100644 --- a/rtgui/iccprofilecreator.h +++ b/rtgui/iccprofilecreator.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once @@ -92,7 +92,6 @@ private: void illuminantChanged(); void trcPresetsChanged(); void adjusterChanged(Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; static std::vector getGamma(); Glib::ustring getPrimariesPresetName(const Glib::ustring &preset); void getPrimaries(const Glib::ustring &preset, double *p, ColorTemp &temp); diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index ba8bf9cef..012aeca78 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -34,7 +34,7 @@ using namespace rtengine::procparams; extern Options options; -ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunchanged(nullptr), icmplistener(nullptr), lastRefFilename(""), camName("") +ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunchanged(nullptr), icmplistener(nullptr) { auto m = ProcEventMapper::getInstance(); EvICMprimariMethod = m->newEvent(GAMMA, "HISTORY_MSG_ICM_OUTPUT_PRIMARIES"); @@ -304,8 +304,6 @@ ICMPanel::ICMPanel() : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iuncha ipDialog->set_show_hidden(true); // ProgramData is hidden on Windows #endif - oldip = ""; - wprofnamesconn = wProfNames->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::wpChanged)); oprofnamesconn = oProfNames->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::opChanged)); orendintentconn = oRendIntent->signal_changed().connect(sigc::mem_fun(*this, &ICMPanel::oiChanged)); @@ -504,7 +502,7 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited) if (pp->icm.inputProfile == "(none)") { inone->set_active(true); updateDCP(pp->icm.dcpIlluminant, ""); - } else if (pp->icm.inputProfile == "(embedded)" || ((pp->icm.inputProfile == "(camera)" || pp->icm.inputProfile == "") && icamera->get_state() == Gtk::STATE_INSENSITIVE)) { + } else if (pp->icm.inputProfile == "(embedded)" || ((pp->icm.inputProfile == "(camera)" || pp->icm.inputProfile.empty()) && icamera->get_state() == Gtk::STATE_INSENSITIVE)) { iembedded->set_active(true); updateDCP(pp->icm.dcpIlluminant, ""); } else if ((pp->icm.inputProfile == "(cameraICC)") && icameraICC->get_state() != Gtk::STATE_INSENSITIVE) { @@ -519,7 +517,7 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited) // If neither (camera) nor (cameraICC) are available, as is the case when loading a non-raw, activate (embedded). iembedded->set_active(true); updateDCP(pp->icm.dcpIlluminant, "(cameraICC)"); - } else if ((pp->icm.inputProfile == "(camera)" || pp->icm.inputProfile == "") && icamera->get_state() != Gtk::STATE_INSENSITIVE) { + } else if ((pp->icm.inputProfile == "(camera)" || pp->icm.inputProfile.empty()) && icamera->get_state() != Gtk::STATE_INSENSITIVE) { icamera->set_active(true); updateDCP(pp->icm.dcpIlluminant, ""); } else { @@ -617,8 +615,6 @@ void ICMPanel::write(ProcParams* pp, ParamsEdited* pedited) } else { pp->icm.inputProfile = ""; // just a directory } - - Glib::ustring p = Glib::path_get_dirname(ipDialog->get_filename()); } pp->icm.workingProfile = wProfNames->get_active_text(); @@ -701,10 +697,6 @@ void ICMPanel::adjusterChanged(Adjuster* a, double newval) } } -void ICMPanel::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void ICMPanel::wpChanged() { if (listener) { @@ -953,7 +945,7 @@ void ICMPanel::setRawMeta(bool raw, const rtengine::FramesData* pMeta) void ICMPanel::ipSelectionChanged() { - if (ipDialog->get_filename() == "") { + if (ipDialog->get_filename().empty()) { return; } diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index b1106b6e1..9b4706ecd 100644 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _ICMPANEL_ #define _ICMPANEL_ @@ -126,7 +126,6 @@ public: void setBatchMode(bool batchMode) override; void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; void adjusterChanged(Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void wpChanged(); void wtrcinChanged(); diff --git a/rtgui/ilabel.cc b/rtgui/ilabel.cc index 65040b93b..9dfd50b89 100644 --- a/rtgui/ilabel.cc +++ b/rtgui/ilabel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "ilabel.h" diff --git a/rtgui/ilabel.h b/rtgui/ilabel.h index 1f5340fa2..06da470b1 100644 --- a/rtgui/ilabel.h +++ b/rtgui/ilabel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _ILABEL_ #define _ILABEL_ diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index dd891b351..b086f8baf 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "imagearea.h" #include @@ -29,7 +29,6 @@ ImageArea::ImageArea (ImageAreaPanel* p) : parent(p), fullImageWidth(0), fullImageHeight(0) { - infotext = ""; cropgl = nullptr; pmlistener = nullptr; pmhlistener = nullptr; @@ -148,7 +147,7 @@ void ImageArea::on_style_updated () void ImageArea::setInfoText (Glib::ustring text) { - infotext = text; + infotext = std::move(text); Glib::RefPtr context = get_pango_context () ; Pango::FontDescription fontd(get_style_context()->get_font()); @@ -160,7 +159,7 @@ void ImageArea::setInfoText (Glib::ustring text) // create text layout Glib::RefPtr ilayout = create_pango_layout(""); - ilayout->set_markup(text); + ilayout->set_markup(infotext); // get size of the text block int iw, ih; @@ -247,7 +246,7 @@ bool ImageArea::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) (*i)->expose (cr); } - if (options.showInfo && infotext != "") { + if (options.showInfo && !infotext.empty()) { iBackBuffer.copySurface(cr); } diff --git a/rtgui/imagearea.h b/rtgui/imagearea.h index 0e8794840..375e3a536 100644 --- a/rtgui/imagearea.h +++ b/rtgui/imagearea.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __IMAGEAREA_H__ #define __IMAGEAREA_H__ diff --git a/rtgui/imageareapanel.cc b/rtgui/imageareapanel.cc index b0e680ade..f693c3181 100644 --- a/rtgui/imageareapanel.cc +++ b/rtgui/imageareapanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "imageareapanel.h" diff --git a/rtgui/imageareapanel.h b/rtgui/imageareapanel.h index 13fd6650b..4ec3ffcf3 100644 --- a/rtgui/imageareapanel.h +++ b/rtgui/imageareapanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _IMAGEAREAPANEL_ #define _IMAGEAREAPANEL_ diff --git a/rtgui/imageareatoollistener.h b/rtgui/imageareatoollistener.h index 705888676..d387b595c 100644 --- a/rtgui/imageareatoollistener.h +++ b/rtgui/imageareatoollistener.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _IMAGEAREATOOLLISTENER_ #define _IMAGEAREATOOLLISTENER_ diff --git a/rtgui/impulsedenoise.cc b/rtgui/impulsedenoise.cc index 9203ce8a7..cc2e10899 100644 --- a/rtgui/impulsedenoise.cc +++ b/rtgui/impulsedenoise.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -88,10 +88,6 @@ void ImpulseDenoise::adjusterChanged(Adjuster* a, double newval) } } -void ImpulseDenoise::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void ImpulseDenoise::enabledChanged () { if (listener) { diff --git a/rtgui/impulsedenoise.h b/rtgui/impulsedenoise.h index 79484dc65..1ebdc430b 100644 --- a/rtgui/impulsedenoise.h +++ b/rtgui/impulsedenoise.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _IMPULSEDENOISE_H_ #define _IMPULSEDENOISE_H_ @@ -40,7 +40,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void enabledChanged () override; void setAdjusterBehavior (bool threshadd); diff --git a/rtgui/indclippedpanel.cc b/rtgui/indclippedpanel.cc index aff5035fe..df9f632ab 100644 --- a/rtgui/indclippedpanel.cc +++ b/rtgui/indclippedpanel.cc @@ -13,7 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "indclippedpanel.h" #include "options.h" diff --git a/rtgui/indclippedpanel.h b/rtgui/indclippedpanel.h index c026d4611..54476af10 100644 --- a/rtgui/indclippedpanel.h +++ b/rtgui/indclippedpanel.h @@ -13,7 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _INDCLIPPEDPANEL_ #define _INDCLIPPEDPANEL_ diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc index 06e2272e7..8bd9862a7 100644 --- a/rtgui/inspector.cc +++ b/rtgui/inspector.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "inspector.h" #include "guiutils.h" @@ -34,7 +34,7 @@ InspectorBuffer::InspectorBuffer(const Glib::ustring &imagePath) : currTransform // generate thumbnail image Glib::ustring ext = getExtension (imagePath); - if (ext == "") { + if (ext.empty()) { imgPath.clear(); return; } @@ -83,7 +83,6 @@ InspectorBuffer::~InspectorBuffer() { Inspector::Inspector () : currImage(nullptr), zoom(0.0), active(false) { - Glib::RefPtr style = get_style_context(); set_name("Inspector"); } @@ -115,7 +114,6 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) // compute the displayed area rtengine::Coord availableSize; rtengine::Coord topLeft; - rtengine::Coord displayedSize; rtengine::Coord dest(0, 0); availableSize.x = win->get_width(); availableSize.y = win->get_height(); @@ -125,7 +123,6 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) if (imW < availableSize.x) { // center the image in the available space along X topLeft.x = 0; - displayedSize.x = availableSize.x; dest.x = (availableSize.x - imW) / 2; } else { // partial image display @@ -139,7 +136,6 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) if (imH < availableSize.y) { // center the image in the available space along Y topLeft.y = 0; - displayedSize.y = availableSize.y; dest.y = (availableSize.y - imH) / 2; } else { // partial image display diff --git a/rtgui/inspector.h b/rtgui/inspector.h index d5ed327b8..681b90aa3 100644 --- a/rtgui/inspector.h +++ b/rtgui/inspector.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _INSPECTOR_ #define _INSPECTOR_ @@ -87,7 +87,7 @@ public: /** @brief Get the on/off state */ - bool isActive() + bool isActive() const { return active; }; diff --git a/rtgui/iptcpanel.cc b/rtgui/iptcpanel.cc index fcdd97101..2a4f7348c 100644 --- a/rtgui/iptcpanel.cc +++ b/rtgui/iptcpanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtgui/iptcpanel.h b/rtgui/iptcpanel.h index 25683ccec..0317314a1 100644 --- a/rtgui/iptcpanel.h +++ b/rtgui/iptcpanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _IPTCPANEL_ #define _IPTCPANEL_ diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc index f458fa717..237f9ea9b 100644 --- a/rtgui/labcurve.cc +++ b/rtgui/labcurve.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -29,9 +29,6 @@ using namespace rtengine::procparams; LCurve::LCurve () : FoldableToolPanel(this, "labcurves", M("TP_LABCURVE_LABEL"), false, true) { - - std::vector milestones; - brightness = Gtk::manage (new Adjuster (M("TP_LABCURVE_BRIGHTNESS"), -100., 100., 1., 0.)); contrast = Gtk::manage (new Adjuster (M("TP_LABCURVE_CONTRAST"), -100., 100., 1., 0.)); chromaticity = Gtk::manage (new Adjuster (M("TP_LABCURVE_CHROMATICITY"), -100., 100., 1., 0.)); @@ -98,12 +95,12 @@ LCurve::LCurve () : FoldableToolPanel(this, "labcurves", M("TP_LABCURVE_LABEL"), M("TP_LABCURVE_CURVEEDITOR_A_RANGE3"), M("TP_LABCURVE_CURVEEDITOR_A_RANGE4") ); //from green to magenta - milestones.clear(); - milestones.push_back( GradientMilestone(0., 0., 1., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 0., 1.) ); + std::vector milestones = { + GradientMilestone(0., 0., 1., 0.), + GradientMilestone(1., 1., 0., 1.) + }; ashape->setBottomBarBgGradient(milestones); ashape->setLeftBarBgGradient(milestones); - milestones.clear(); bshape = static_cast(curveEditorG->addCurve(CT_Diagonal, "b*")); bshape->setRangeLabels( @@ -113,12 +110,12 @@ LCurve::LCurve () : FoldableToolPanel(this, "labcurves", M("TP_LABCURVE_LABEL"), bshape->setEditID(EUID_Lab_bCurve, BT_SINGLEPLANE_FLOAT); //from blue to yellow - milestones.clear(); - milestones.push_back( GradientMilestone(0., 0., 0., 1.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 0.) ); + milestones = { + GradientMilestone(0., 0., 0., 1.), + GradientMilestone(1., 1., 1., 0.) + }; bshape->setBottomBarBgGradient(milestones); bshape->setLeftBarBgGradient(milestones); - milestones.clear(); curveEditorG->newLine(); // ------------------------------------------------ second line @@ -171,21 +168,23 @@ LCurve::LCurve () : FoldableToolPanel(this, "labcurves", M("TP_LABCURVE_LABEL"), clshape->setLeftBarColorProvider(this, 7); clshape->setRangeDefaultMilestones(0.25, 0.5, 0.75); - milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + milestones = { + GradientMilestone(0., 0., 0., 0.), + GradientMilestone(1., 1., 1., 1.) + }; clshape->setBottomBarBgGradient(milestones); // Setting the gradient milestones // from black to white - milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + milestones.emplace_back(0., 0., 0., 0.); + milestones.emplace_back(1., 1., 1., 1.); lshape->setBottomBarBgGradient(milestones); lshape->setLeftBarBgGradient(milestones); - milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + milestones.emplace_back(0., 0., 0., 0.); + milestones.emplace_back(1., 1., 1., 1.); lcshape->setRangeDefaultMilestones(0.05, 0.2, 0.58); lcshape->setBottomBarBgGradient(milestones); @@ -201,7 +200,7 @@ LCurve::LCurve () : FoldableToolPanel(this, "labcurves", M("TP_LABCURVE_LABEL"), float R, G, B; float x = float(i) * (1.0f / 6.0); Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); - milestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); + milestones.emplace_back(x, R, G, B); } chshape->setBottomBarBgGradient(milestones); @@ -567,10 +566,6 @@ void LCurve::adjusterChanged(Adjuster* a, double newval) } } -void LCurve::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void LCurve::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) { diff --git a/rtgui/labcurve.h b/rtgui/labcurve.h index b727cca84..51ba0fdd6 100644 --- a/rtgui/labcurve.h +++ b/rtgui/labcurve.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _LABCURVE_H_ #define _LABCURVE_H_ @@ -77,7 +77,6 @@ public: void curveChanged (CurveEditor* ce) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void avoidcolorshift_toggled (); void lcredsk_toggled(); diff --git a/rtgui/labgrid.cc b/rtgui/labgrid.cc index 4576885e8..b6393f6f5 100644 --- a/rtgui/labgrid.cc +++ b/rtgui/labgrid.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ // adapted from the "color correction" module of Darktable. Original copyright follows @@ -33,7 +33,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with darktable. If not, see . + along with darktable. If not, see . */ #include "labgrid.h" diff --git a/rtgui/labgrid.h b/rtgui/labgrid.h index dbb0cc427..227b4cacc 100644 --- a/rtgui/labgrid.h +++ b/rtgui/labgrid.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ // adapted from the "color correction" module of Darktable. Original copyright follows @@ -33,7 +33,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with darktable. If not, see . + along with darktable. If not, see . */ #pragma once diff --git a/rtgui/lensgeom.cc b/rtgui/lensgeom.cc index baf816c8b..76e0635eb 100644 --- a/rtgui/lensgeom.cc +++ b/rtgui/lensgeom.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "lensgeom.h" #include "guiutils.h" diff --git a/rtgui/lensgeom.h b/rtgui/lensgeom.h index 20bb4b7eb..06b8e5689 100644 --- a/rtgui/lensgeom.h +++ b/rtgui/lensgeom.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _LENSGEOM_H_ #define _LENSGEOM_H_ diff --git a/rtgui/lensgeomlistener.h b/rtgui/lensgeomlistener.h index c6ba966b1..dbe58f1fa 100644 --- a/rtgui/lensgeomlistener.h +++ b/rtgui/lensgeomlistener.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _LENSGEOMLISTENER_H_ #define _LENSGEOMLISTENER_H_ diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index 0dd3cb1b7..389f15461 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with RawTherapee. If not, see . +* along with RawTherapee. If not, see . */ #include #include diff --git a/rtgui/lensprofile.h b/rtgui/lensprofile.h index 76c15aa9a..7e740e26e 100644 --- a/rtgui/lensprofile.h +++ b/rtgui/lensprofile.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with RawTherapee. If not, see . +* along with RawTherapee. If not, see . */ #pragma once diff --git a/rtgui/localcontrast.cc b/rtgui/localcontrast.cc index 93b67657d..d91642b6c 100644 --- a/rtgui/localcontrast.cc +++ b/rtgui/localcontrast.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -134,10 +134,6 @@ void LocalContrast::adjusterChanged(Adjuster* a, double newval) } } -void LocalContrast::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void LocalContrast::enabledChanged () { if (listener) { diff --git a/rtgui/localcontrast.h b/rtgui/localcontrast.h index efe7a18f0..b23bac697 100644 --- a/rtgui/localcontrast.h +++ b/rtgui/localcontrast.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once @@ -47,7 +47,6 @@ public: void setBatchMode(bool batchMode) override; void adjusterChanged(Adjuster *a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void enabledChanged() override; void setAdjusterBehavior(bool radiusAdd, bool amountAdd, bool darknessAdd, bool lightnessAdd); }; diff --git a/rtgui/lockablecolorpicker.cc b/rtgui/lockablecolorpicker.cc index 859057e2c..ef16df6ec 100644 --- a/rtgui/lockablecolorpicker.cc +++ b/rtgui/lockablecolorpicker.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "lockablecolorpicker.h" diff --git a/rtgui/lockablecolorpicker.h b/rtgui/lockablecolorpicker.h index cafea26be..f1a63d533 100644 --- a/rtgui/lockablecolorpicker.h +++ b/rtgui/lockablecolorpicker.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __COLORPICKER__ diff --git a/rtgui/lwbutton.cc b/rtgui/lwbutton.cc index 48843a02e..b5c10c532 100644 --- a/rtgui/lwbutton.cc +++ b/rtgui/lwbutton.cc @@ -14,12 +14,12 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "lwbutton.h" #include "guiutils.h" -LWButton::LWButton (Cairo::RefPtr i, int aCode, void* aData, Alignment ha, Alignment va, Glib::ustring tooltip) +LWButton::LWButton (Cairo::RefPtr i, int aCode, void* aData, Alignment ha, Alignment va, Glib::ustring* tooltip) : xpos(0), ypos(0), halign(ha), valign(va), icon(i), bgr(0.0), bgg(0.0), bgb(0.0), fgr(0.0), fgg(0.0), fgb(0.0), state(Normal), listener(nullptr), actionCode(aCode), actionData(aData), toolTip(tooltip) { @@ -31,7 +31,7 @@ LWButton::LWButton (Cairo::RefPtr i, int aCode, void* aData, Alignmen } } -void LWButton::getSize (int& minw, int& minh) +void LWButton::getSize (int& minw, int& minh) const { minw = w; @@ -45,7 +45,13 @@ void LWButton::setPosition (int x, int y) ypos = y; } -void LWButton::getPosition (int& x, int& y) +void LWButton::addPosition (int x, int y) +{ + xpos += x; + ypos += y; +} + +void LWButton::getPosition (int& x, int& y) const { x = xpos; @@ -65,7 +71,7 @@ void LWButton::setIcon (Cairo::RefPtr i) } } -Cairo::RefPtr LWButton::getIcon () +Cairo::RefPtr LWButton::getIcon () const { return icon; @@ -82,7 +88,7 @@ void LWButton::setColors (const Gdk::RGBA& bg, const Gdk::RGBA& fg) fgb = fg.get_blue (); } -bool LWButton::inside (int x, int y) +bool LWButton::inside (int x, int y) const { return x > xpos && x < xpos + w && y > ypos && y < ypos + h; @@ -210,24 +216,23 @@ void LWButton::redraw (Cairo::RefPtr context) } } -void LWButton::getAlignment (Alignment& ha, Alignment& va) +void LWButton::getAlignment (Alignment& ha, Alignment& va) const { ha = halign; va = valign; } -Glib::ustring LWButton::getToolTip (int x, int y) +Glib::ustring LWButton::getToolTip (int x, int y) const { - - if (inside (x, y)) { - return toolTip; + if (inside(x, y) && toolTip) { + return *toolTip; } else { - return ""; + return {}; } } -void LWButton::setToolTip (const Glib::ustring& tooltip) +void LWButton::setToolTip (Glib::ustring* tooltip) { toolTip = tooltip; diff --git a/rtgui/lwbutton.h b/rtgui/lwbutton.h index 4ab34f265..16e53a875 100644 --- a/rtgui/lwbutton.h +++ b/rtgui/lwbutton.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _LWBUTTON_ #define _LWBUTTON_ @@ -49,26 +49,27 @@ private: LWButtonListener* listener; int actionCode; void* actionData; - Glib::ustring toolTip; + Glib::ustring* toolTip; public: - LWButton (Cairo::RefPtr i, int aCode, void* aData, Alignment ha = Left, Alignment va = Center, Glib::ustring tooltip = ""); + LWButton (Cairo::RefPtr i, int aCode, void* aData, Alignment ha = Left, Alignment va = Center, Glib::ustring* tooltip = nullptr); - void getSize (int& minw, int& minh); - void getAlignment (Alignment& ha, Alignment& va); + void getSize (int& minw, int& minh) const; + void getAlignment (Alignment& ha, Alignment& va) const; void setPosition (int x, int y); - void getPosition (int& x, int& y); - bool inside (int x, int y); + void addPosition (int x, int y); + void getPosition (int& x, int& y) const; + bool inside (int x, int y) const; void setIcon (Cairo::RefPtr i); - Cairo::RefPtr getIcon (); + Cairo::RefPtr getIcon () const; void setColors (const Gdk::RGBA& bg, const Gdk::RGBA& fg); - void setToolTip (const Glib::ustring& tooltip); + void setToolTip (Glib::ustring* tooltip); bool motionNotify (int x, int y); bool pressNotify (int x, int y); bool releaseNotify (int x, int y); - Glib::ustring getToolTip (int x, int y); + Glib::ustring getToolTip (int x, int y) const; void setButtonListener (LWButtonListener* bl) { diff --git a/rtgui/lwbuttonset.cc b/rtgui/lwbuttonset.cc index 6265c1039..a03b3064b 100644 --- a/rtgui/lwbuttonset.cc +++ b/rtgui/lwbuttonset.cc @@ -14,48 +14,46 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "lwbuttonset.h" -LWButtonSet::LWButtonSet () : aw(0), ah(0), ax(0), ay(0) +LWButtonSet::LWButtonSet () : aw(0), ah(0), ax(-1), ay(-1) { } LWButtonSet::~LWButtonSet () { - - for (size_t i = 0; i < buttons.size(); i++) { - delete buttons[i]; + for (const auto entry : buttons) { + delete entry; } } void LWButtonSet::add (LWButton* b) { - buttons.push_back (b); } -void LWButtonSet::getMinimalDimensions (int& w, int& h) +void LWButtonSet::getMinimalDimensions (int& w, int& h) const { - w = 0; h = 0; - for (size_t i = 0; i < buttons.size(); i++) { + for (const auto entry : buttons) { int bw, bh; - buttons[i]->getSize (bw, bh); + entry->getSize(bw, bh); w += bw; - - if (bh > h) { - h = bh; - } + h = std::max(bh, h); } } void LWButtonSet::arrangeButtons (int x, int y, int w, int h) { + if (x == ax && y == ay && w == aw && (h == -1 || h == ah )) { + return; + } + int mw, mh; getMinimalDimensions (mw, mh); @@ -103,108 +101,86 @@ void LWButtonSet::arrangeButtons (int x, int y, int w, int h) void LWButtonSet::move (int nx, int ny) { - - for (size_t i = 0; i < buttons.size(); i++) { - int x, y; - buttons[i]->getPosition (x, y); - buttons[i]->setPosition (x + nx - ax, y + ny - ay); + for (const auto entry : buttons) { + entry->addPosition(nx - ax, ny - ay); } - ax = nx; ay = ny; } void LWButtonSet::redraw (Cairo::RefPtr context) { - - for (size_t i = 0; i < buttons.size(); i++) { - buttons[i]->redraw (context); + for (const auto entry : buttons) { + entry->redraw(context); } } bool LWButtonSet::motionNotify (int x, int y) { - bool res = false; - - for (size_t i = 0; i < buttons.size(); i++) { - bool handled = buttons[i]->motionNotify (x, y); - res = res || handled; + for (const auto entry : buttons) { + res = entry->motionNotify(x, y) || res; } - return res; } bool LWButtonSet::pressNotify (int x, int y) { - bool res = false; - - for (size_t i = 0; i < buttons.size(); i++) { - bool handled = buttons[i]->pressNotify (x, y); - res = res || handled; + for (const auto entry : buttons) { + res = entry->pressNotify(x, y) || res; } - return res; } bool LWButtonSet::releaseNotify (int x, int y) { - bool res = false; - - for (size_t i = 0; i < buttons.size(); i++) { - bool handled = buttons[i]->releaseNotify (x, y); - res = res || handled; + for (const auto entry : buttons) { + res = entry->releaseNotify(x, y) || res; } - return res; } -bool LWButtonSet::inside (int x, int y) +bool LWButtonSet::inside (int x, int y) const { - for (size_t i = 0; i < buttons.size(); i++) - if (buttons[i]->inside (x, y)) { + for (const auto entry : buttons) { + if (entry->inside(x, y)) { return true; } - + } return false; } void LWButtonSet::setButtonListener (LWButtonListener* bl) { - - for (size_t i = 0; i < buttons.size(); i++) { - buttons[i]->setButtonListener (bl); + for (const auto entry : buttons) { + entry->setButtonListener(bl); } } -void LWButtonSet::getAllocatedDimensions (int& w, int& h) +void LWButtonSet::getAllocatedDimensions (int& w, int& h) const { - w = aw; h = ah; } void LWButtonSet::setColors (const Gdk::RGBA& bg, const Gdk::RGBA& fg) { - - for (size_t i = 0; i < buttons.size(); i++) { - buttons[i]->setColors (bg, fg); + for (const auto entry : buttons) { + entry->setColors(bg, fg); } } -Glib::ustring LWButtonSet::getToolTip (int x, int y) +Glib::ustring LWButtonSet::getToolTip (int x, int y) const { + for (const auto entry : buttons) { + const auto ttip = entry->getToolTip(x, y); - for (size_t i = 0; i < buttons.size(); i++) { - Glib::ustring ttip = buttons[i]->getToolTip (x, y); - - if (ttip != "") { + if (!ttip.empty()) { return ttip; } } - - return ""; + return {}; } diff --git a/rtgui/lwbuttonset.h b/rtgui/lwbuttonset.h index 5452fa434..07d17a135 100644 --- a/rtgui/lwbuttonset.h +++ b/rtgui/lwbuttonset.h @@ -14,10 +14,9 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ -#ifndef _LWBUTTONSET_ -#define _LWBUTTONSET_ +#pragma once #include #include "lwbutton.h" @@ -35,20 +34,18 @@ public: void add (LWButton* b); - void getMinimalDimensions (int& w, int& h); - void getAllocatedDimensions (int& w, int& h); + void getMinimalDimensions (int& w, int& h) const; + void getAllocatedDimensions (int& w, int& h) const; void arrangeButtons (int x, int y, int w, int h); void setColors (const Gdk::RGBA& bg, const Gdk::RGBA& fg); bool motionNotify (int x, int y); bool pressNotify (int x, int y); bool releaseNotify (int x, int y); void move (int nx, int ny); - bool inside (int x, int y); + bool inside (int x, int y) const; - Glib::ustring getToolTip (int x, int y); + Glib::ustring getToolTip (int x, int y) const; void setButtonListener (LWButtonListener* bl); void redraw (Cairo::RefPtr context); }; - -#endif diff --git a/rtgui/main-cli.cc b/rtgui/main-cli.cc index cbea1d477..09aab1cff 100644 --- a/rtgui/main-cli.cc +++ b/rtgui/main-cli.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifdef __GNUC__ @@ -256,7 +256,7 @@ int processLineParams ( int argc, char **argv ) { rtengine::procparams::PartialProfile *rawParams = nullptr, *imgParams = nullptr; std::vector inputFiles; - Glib::ustring outputPath = ""; + Glib::ustring outputPath; std::vector processingParams; bool outputDirectory = false; bool leaveUntouched = false; @@ -271,7 +271,7 @@ int processLineParams ( int argc, char **argv ) int subsampling = 3; int bits = -1; bool isFloat = false; - std::string outputType = ""; + std::string outputType; unsigned errors = 0; for ( int iArg = 1; iArg < argc; iArg++) { diff --git a/rtgui/main.cc b/rtgui/main.cc index 5cfe93718..098963e0e 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifdef __GNUC__ diff --git a/rtgui/metadatapanel.cc b/rtgui/metadatapanel.cc index ee97a7dfe..f92152763 100644 --- a/rtgui/metadatapanel.cc +++ b/rtgui/metadatapanel.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "metadatapanel.h" @@ -26,9 +26,8 @@ using namespace rtengine; using namespace rtengine::procparams; -MetaDataPanel::MetaDataPanel() +MetaDataPanel::MetaDataPanel() : EvMetaDataMode(ProcEventMapper::getInstance()->newEvent(M_VOID, "HISTORY_MSG_METADATA_MODE")) { - EvMetaDataMode = ProcEventMapper::getInstance()->newEvent(M_VOID, "HISTORY_MSG_METADATA_MODE"); Gtk::HBox *box = Gtk::manage(new Gtk::HBox()); box->pack_start(*Gtk::manage(new Gtk::Label(M("TP_METADATA_MODE") + ": ")), Gtk::PACK_SHRINK, 4); diff --git a/rtgui/metadatapanel.h b/rtgui/metadatapanel.h index d34a04585..b39ffd2c1 100644 --- a/rtgui/metadatapanel.h +++ b/rtgui/metadatapanel.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once diff --git a/rtgui/multilangmgr.cc b/rtgui/multilangmgr.cc index 298f5d2dd..ecf744519 100644 --- a/rtgui/multilangmgr.cc +++ b/rtgui/multilangmgr.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "multilangmgr.h" diff --git a/rtgui/multilangmgr.h b/rtgui/multilangmgr.h index 649865217..0c76b4c01 100644 --- a/rtgui/multilangmgr.h +++ b/rtgui/multilangmgr.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _MULTILANGMGR_ #define _MULTILANGMGR_ diff --git a/rtgui/mycurve.cc b/rtgui/mycurve.cc index 5684bec33..6c00e3f56 100644 --- a/rtgui/mycurve.cc +++ b/rtgui/mycurve.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "mycurve.h" #include "../rtengine/curves.h" diff --git a/rtgui/mycurve.h b/rtgui/mycurve.h index 82dd4a1a4..62d8d30f2 100644 --- a/rtgui/mycurve.h +++ b/rtgui/mycurve.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _MYCURVE_ #define _MYCURVE_ @@ -28,6 +28,7 @@ #include "../rtengine/LUT.h" #include "guiutils.h" #include "options.h" +#include "../rtengine/noncopyable.h" #define RADIUS 3.5 /** radius of the control points ; must be x.5 to target the center of a pixel */ #define CBAR_WIDTH 10 /** inner width of the colored bar (border excluded) */ @@ -55,7 +56,7 @@ enum SnapToType { class MyCurveIdleHelper; class CurveEditor; -class MyCurve : public Gtk::DrawingArea, public BackBuffer, public ColorCaller, public CoordinateProvider +class MyCurve : public Gtk::DrawingArea, public BackBuffer, public ColorCaller, public CoordinateProvider, public rtengine::NonCopyable { friend class MyCurveIdleHelper; diff --git a/rtgui/mydiagonalcurve.cc b/rtgui/mydiagonalcurve.cc index a3e7b9375..d393c7200 100644 --- a/rtgui/mydiagonalcurve.cc +++ b/rtgui/mydiagonalcurve.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -637,13 +637,8 @@ bool MyDiagonalCurve::handleEvents (GdkEvent* event) setDirty(true); draw (lit_point); new_type = CSArrow; - retval = true; } } - - if (buttonPressed) { - retval = true; - } } else { // if (edited_point > -1) if (event->button.button == 3) { // do we edit another point? @@ -679,7 +674,6 @@ bool MyDiagonalCurve::handleEvents (GdkEvent* event) newBoundaries.at(1).minVal = 0.; newBoundaries.at(1).maxVal = 1.; - retval = true; editedPos.at(0) = curve.x.at(edited_point); editedPos.at(1) = curve.y.at(edited_point); coordinateAdjuster->switchAdjustedPoint(editedPos, newBoundaries); @@ -691,12 +685,9 @@ bool MyDiagonalCurve::handleEvents (GdkEvent* event) stopNumericalAdjustment(); } } - - retval = true; } } } - retval = true; } diff --git a/rtgui/mydiagonalcurve.h b/rtgui/mydiagonalcurve.h index 5b0f6f01e..33fac6090 100644 --- a/rtgui/mydiagonalcurve.h +++ b/rtgui/mydiagonalcurve.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _MYDIAGONALCURVE_ #define _MYDIAGONALCURVE_ diff --git a/rtgui/myflatcurve.cc b/rtgui/myflatcurve.cc index 9796141d5..ec46908ce 100644 --- a/rtgui/myflatcurve.cc +++ b/rtgui/myflatcurve.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -556,7 +556,7 @@ bool MyFlatCurve::getHandles(int n) if (!n) { // first point, the left handle is then computed with the last point's right handle prevX = curve.x.at(N - 1) - 1.0; - nextX = curve.x.at(n + 1); + nextX = curve.x.at(1); } else if (n == N - 1) { // last point, the right handle is then computed with the first point's left handle prevX = curve.x.at(n - 1); @@ -745,7 +745,6 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) newBoundaries.at(2).maxVal = 1.; newBoundaries.at(3).minVal = 0.; newBoundaries.at(3).maxVal = 1.; - retval = true; editedPos.at(0) = curve.x.at(edited_point); editedPos.at(1) = curve.y.at(edited_point); editedPos.at(2) = curve.leftTangent.at(edited_point); diff --git a/rtgui/myflatcurve.h b/rtgui/myflatcurve.h index c0223bfcf..fa4466b8d 100644 --- a/rtgui/myflatcurve.h +++ b/rtgui/myflatcurve.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _MYFLATCURVE_ #define _MYFLATCURVE_ diff --git a/rtgui/navigator.cc b/rtgui/navigator.cc index 732b9f323..de07ffcd7 100644 --- a/rtgui/navigator.cc +++ b/rtgui/navigator.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include "navigator.h" diff --git a/rtgui/navigator.h b/rtgui/navigator.h index 1b898f895..eb4584f42 100644 --- a/rtgui/navigator.h +++ b/rtgui/navigator.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _NAVIGATOR_ #define _NAVIGATOR_ diff --git a/rtgui/options.cc b/rtgui/options.cc index 2437f5313..20e20620a 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "options.h" #include @@ -369,6 +369,7 @@ void Options::setDefaults() multiUser = true; profilePath = "profiles"; loadSaveProfilePath = ""; // will be corrected in load as otherwise construction fails + lastCopyMovePath = ""; version = "0.0.0.0"; // temporary value; will be correctly set in RTWindow::on_realize thumbSize = 160; thumbSizeTab = 160; @@ -412,6 +413,7 @@ void Options::setDefaults() favorites.clear(); parseExtensionsEnabled.clear(); parsedExtensions.clear(); + parsedExtensionsSet.clear(); renameUseTemplates = false; renameTemplates.clear(); thumbnailZoomRatios.clear(); @@ -648,10 +650,12 @@ Options* Options::copyFrom(Options* other) void Options::filterOutParsedExtensions() { parsedExtensions.clear(); + parsedExtensionsSet.clear(); for (unsigned int i = 0; i < parseExtensions.size(); i++) if (parseExtensionsEnabled[i]) { parsedExtensions.push_back(parseExtensions[i].lowercase()); + parsedExtensionsSet.emplace(parseExtensions[i].lowercase()); } } @@ -1836,6 +1840,7 @@ void Options::readFromFile(Glib::ustring fname) safeDirGet(keyFile, "Dialogs", "LastProfilingReferenceDir", lastProfilingReferenceDir); safeDirGet(keyFile, "Dialogs", "LastLensProfileDir", lastLensProfileDir); safeDirGet(keyFile, "Dialogs", "LastICCProfCreatorDir", lastICCProfCreatorDir); + safeDirGet(keyFile, "Dialogs", "LastCopyMovePath", lastCopyMovePath); if (keyFile.has_key("Dialogs", "GimpPluginShowInfoDialog")) { gimpPluginShowInfoDialog = keyFile.get_boolean("Dialogs", "GimpPluginShowInfoDialog"); @@ -2229,6 +2234,7 @@ void Options::saveToFile(Glib::ustring fname) keyFile.set_string("Dialogs", "LastProfilingReferenceDir", lastProfilingReferenceDir); keyFile.set_string("Dialogs", "LastLensProfileDir", lastLensProfileDir); keyFile.set_string("Dialogs", "LastICCProfCreatorDir", lastICCProfCreatorDir); + keyFile.set_string("Dialogs", "LastCopyMovePath", lastCopyMovePath); keyFile.set_boolean("Dialogs", "GimpPluginShowInfoDialog", gimpPluginShowInfoDialog); keyFile.set_string("Lensfun", "DBDirectory", rtSettings.lensfunDbDirectory); @@ -2464,36 +2470,29 @@ bool Options::is_parse_extention(Glib::ustring fname) /* * return true if fname ends with one of the retained image file extensions */ -bool Options::has_retained_extention(Glib::ustring fname) +bool Options::has_retained_extention(const Glib::ustring& fname) { + return parsedExtensionsSet.find(getExtension(fname).lowercase()) != parsedExtensionsSet.end(); +} - Glib::ustring ext = getExtension(fname).lowercase(); +// Pattern matches "5.1" from "5.1-23-g12345678", when comparing option.version to RTVERSION +bool Options::is_new_version() { + const std::string vs[] = {versionString, version}; + std::vector vMajor; - if (!ext.empty()) { - // there is an extension to the filename - - // look out if it has one of the retained extensions - for (unsigned int i = 0; i < parsedExtensions.size(); i++) { - if (ext == parsedExtensions[i]) { - return true; - } - } + for (const auto& v : vs) { + vMajor.emplace_back(v, 0, v.find_first_not_of("0123456789.")); } - return false; + return vMajor.size() == 2 && vMajor[0] != vMajor[1]; } /* * return true if ext is an enabled extension */ -bool Options::is_extention_enabled(Glib::ustring ext) +bool Options::is_extention_enabled(const Glib::ustring& ext) { - for (int j = 0; j < (int)parseExtensions.size(); j++) - if (parseExtensions[j].casefold() == ext.casefold()) { - return j >= (int)parseExtensionsEnabled.size() || parseExtensionsEnabled[j]; - } - - return false; + return parsedExtensionsSet.find(ext.lowercase()) != parsedExtensionsSet.end(); } Glib::ustring Options::getUserProfilePath() diff --git a/rtgui/options.h b/rtgui/options.h index 304a1e220..3bd83cd5b 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -14,11 +14,12 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _OPTIONS_ #define _OPTIONS_ +#include #include #include "../rtengine/rtengine.h" #include @@ -174,6 +175,7 @@ public: Glib::ustring startupPath; Glib::ustring profilePath; // can be an absolute or relative path; depending on this value, bundled profiles may not be found bool useBundledProfiles; // only used if multiUser == true + Glib::ustring lastCopyMovePath; Glib::ustring loadSaveProfilePath; Glib::ustring lastSaveAsPath; int saveAsDialogWidth; @@ -259,6 +261,7 @@ public: std::vector parseExtensions; // List containing all extensions type std::vector parseExtensionsEnabled; // List of bool to retain extension or not std::vector parsedExtensions; // List containing all retained extensions (lowercase) + std::set parsedExtensionsSet; // Set containing all retained extensions (lowercase) std::vector tpOpen; bool autoSaveTpOpen; //std::vector crvOpen; @@ -422,8 +425,9 @@ public: Glib::ustring getGlobalProfilePath(); Glib::ustring findProfilePath (Glib::ustring &profName); bool is_parse_extention (Glib::ustring fname); - bool has_retained_extention (Glib::ustring fname); - bool is_extention_enabled (Glib::ustring ext); + bool has_retained_extention (const Glib::ustring& fname); + bool is_new_version(); + bool is_extention_enabled (const Glib::ustring& ext); bool is_defProfRawMissing(); bool is_bundledDefProfRawMissing(); bool is_defProfImgMissing(); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 2c29b4f5b..74bf975de 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -152,6 +152,7 @@ void ParamsEdited::set(bool v) sharpening.contrast = v; sharpening.radius = v; sharpening.blurradius = v; + sharpening.gamma = v; sharpening.amount = v; sharpening.threshold = v; sharpening.edgesonly = v; @@ -164,6 +165,14 @@ void ParamsEdited::set(bool v) sharpening.deconvradius = v; sharpening.deconviter = v; sharpening.deconvdamping = v; + pdsharpening.enabled = v; + pdsharpening.contrast = v; + pdsharpening.autoContrast = v; + pdsharpening.autoRadius = v; + pdsharpening.gamma = v; + pdsharpening.deconvradius = v; + pdsharpening.deconvradiusOffset = v; + pdsharpening.deconviter = v; prsharpening.enabled = v; prsharpening.contrast = v; prsharpening.radius = v; @@ -579,7 +588,12 @@ void ParamsEdited::set(bool v) dehaze.strength = v; dehaze.showDepthMap = v; dehaze.depth = v; + dehaze.luminance = v; metadata.mode = v; + filmNegative.enabled = v; + filmNegative.redRatio = v; + filmNegative.greenExp = v; + filmNegative.blueRatio = v; exif = v; iptc = v; @@ -725,6 +739,7 @@ void ParamsEdited::initFrom(const std::vector& sharpening.contrast = sharpening.contrast && p.sharpening.contrast == other.sharpening.contrast; sharpening.radius = sharpening.radius && p.sharpening.radius == other.sharpening.radius; sharpening.blurradius = sharpening.blurradius && p.sharpening.blurradius == other.sharpening.blurradius; + sharpening.gamma = sharpening.gamma && p.sharpening.gamma == other.sharpening.gamma; sharpening.amount = sharpening.amount && p.sharpening.amount == other.sharpening.amount; sharpening.threshold = sharpening.threshold && p.sharpening.threshold == other.sharpening.threshold; sharpening.edgesonly = sharpening.edgesonly && p.sharpening.edgesonly == other.sharpening.edgesonly; @@ -737,6 +752,14 @@ void ParamsEdited::initFrom(const std::vector& sharpening.deconvradius = sharpening.deconvradius && p.sharpening.deconvradius == other.sharpening.deconvradius; sharpening.deconviter = sharpening.deconviter && p.sharpening.deconviter == other.sharpening.deconviter; sharpening.deconvdamping = sharpening.deconvdamping && p.sharpening.deconvdamping == other.sharpening.deconvdamping; + pdsharpening.enabled = pdsharpening.enabled && p.pdsharpening.enabled == other.pdsharpening.enabled; + pdsharpening.contrast = pdsharpening.contrast && p.pdsharpening.contrast == other.pdsharpening.contrast; + pdsharpening.autoContrast = pdsharpening.autoContrast && p.pdsharpening.autoContrast == other.pdsharpening.autoContrast; + pdsharpening.autoRadius = pdsharpening.autoRadius && p.pdsharpening.autoRadius == other.pdsharpening.autoRadius; + pdsharpening.gamma = pdsharpening.gamma && p.pdsharpening.gamma == other.pdsharpening.gamma; + pdsharpening.deconvradius = pdsharpening.deconvradius && p.pdsharpening.deconvradius == other.pdsharpening.deconvradius; + pdsharpening.deconvradiusOffset = pdsharpening.deconvradiusOffset && p.pdsharpening.deconvradiusOffset == other.pdsharpening.deconvradiusOffset; + pdsharpening.deconviter = pdsharpening.deconviter && p.pdsharpening.deconviter == other.pdsharpening.deconviter; prsharpening.enabled = prsharpening.enabled && p.prsharpening.enabled == other.prsharpening.enabled; prsharpening.contrast = prsharpening.contrast && p.prsharpening.contrast == other.prsharpening.contrast; prsharpening.radius = prsharpening.radius && p.prsharpening.radius == other.prsharpening.radius; @@ -1108,20 +1131,17 @@ void ParamsEdited::initFrom(const std::vector& wavelet.exptoning = wavelet.exptoning && p.wavelet.exptoning == other.wavelet.exptoning; wavelet.expnoise = wavelet.expnoise && p.wavelet.expnoise == other.wavelet.expnoise; - for (int i = 0; i < 9; i++) { - wavelet.c[i] = wavelet.c[i] && p.wavelet.c[i] == other.wavelet.c[i]; - } - - for (int i = 0; i < 9; i++) { - wavelet.ch[i] = wavelet.ch[i] && p.wavelet.ch[i] == other.wavelet.ch[i]; + for (int level = 0; level < 9; ++level) { + wavelet.c[level] = wavelet.c[level] && p.wavelet.c[level] == other.wavelet.c[level]; + wavelet.ch[level] = wavelet.ch[level] && p.wavelet.ch[level] == other.wavelet.ch[level]; } dirpyrequalizer.enabled = dirpyrequalizer.enabled && p.dirpyrequalizer.enabled == other.dirpyrequalizer.enabled; dirpyrequalizer.gamutlab = dirpyrequalizer.gamutlab && p.dirpyrequalizer.gamutlab == other.dirpyrequalizer.gamutlab; dirpyrequalizer.cbdlMethod = dirpyrequalizer.cbdlMethod && p.dirpyrequalizer.cbdlMethod == other.dirpyrequalizer.cbdlMethod; - for (int i = 0; i < 6; i++) { - dirpyrequalizer.mult[i] = dirpyrequalizer.mult[i] && p.dirpyrequalizer.mult[i] == other.dirpyrequalizer.mult[i]; + for (int level = 0; level < 6; ++level) { + dirpyrequalizer.mult[level] = dirpyrequalizer.mult[level] && p.dirpyrequalizer.mult[level] == other.dirpyrequalizer.mult[level]; } dirpyrequalizer.threshold = dirpyrequalizer.threshold && p.dirpyrequalizer.threshold == other.dirpyrequalizer.threshold; @@ -1141,7 +1161,12 @@ void ParamsEdited::initFrom(const std::vector& dehaze.strength = dehaze.strength && p.dehaze.strength == other.dehaze.strength; dehaze.showDepthMap = dehaze.showDepthMap && p.dehaze.showDepthMap == other.dehaze.showDepthMap; dehaze.depth = dehaze.depth && p.dehaze.depth == other.dehaze.depth; + dehaze.luminance = dehaze.luminance && p.dehaze.luminance == other.dehaze.luminance; metadata.mode = metadata.mode && p.metadata.mode == other.metadata.mode; + filmNegative.enabled = filmNegative.enabled && p.filmNegative.enabled == other.filmNegative.enabled; + filmNegative.redRatio = filmNegative.redRatio && p.filmNegative.redRatio == other.filmNegative.redRatio; + filmNegative.greenExp = filmNegative.greenExp && p.filmNegative.greenExp == other.filmNegative.greenExp; + filmNegative.blueRatio = filmNegative.blueRatio && p.filmNegative.blueRatio == other.filmNegative.blueRatio; // How the hell can we handle that??? // exif = exif && p.exif==other.exif @@ -1155,15 +1180,15 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng bool dontforceSet = !forceSet; if (toneCurve.curve) { - toEdit.toneCurve.curve = mods.toneCurve.curve; + toEdit.toneCurve.curve = mods.toneCurve.curve; } if (toneCurve.curve2) { - toEdit.toneCurve.curve2 = mods.toneCurve.curve2; + toEdit.toneCurve.curve2 = mods.toneCurve.curve2; } if (toneCurve.curveMode) { - toEdit.toneCurve.curveMode = mods.toneCurve.curveMode; + toEdit.toneCurve.curveMode = mods.toneCurve.curveMode; } if (toneCurve.curveMode2) { @@ -1175,11 +1200,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (toneCurve.black) { - toEdit.toneCurve.black = dontforceSet && options.baBehav[ADDSET_TC_BLACKLEVEL] ? toEdit.toneCurve.black + mods.toneCurve.black : mods.toneCurve.black; + toEdit.toneCurve.black = dontforceSet && options.baBehav[ADDSET_TC_BLACKLEVEL] ? toEdit.toneCurve.black + mods.toneCurve.black : mods.toneCurve.black; } if (toneCurve.contrast) { - toEdit.toneCurve.contrast = dontforceSet && options.baBehav[ADDSET_TC_CONTRAST] ? toEdit.toneCurve.contrast + mods.toneCurve.contrast : mods.toneCurve.contrast; + toEdit.toneCurve.contrast = dontforceSet && options.baBehav[ADDSET_TC_CONTRAST] ? toEdit.toneCurve.contrast + mods.toneCurve.contrast : mods.toneCurve.contrast; } if (toneCurve.saturation) { @@ -1187,43 +1212,43 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (toneCurve.shcompr) { - toEdit.toneCurve.shcompr = dontforceSet && options.baBehav[ADDSET_TC_SHCOMP] ? toEdit.toneCurve.shcompr + mods.toneCurve.shcompr : mods.toneCurve.shcompr; + toEdit.toneCurve.shcompr = dontforceSet && options.baBehav[ADDSET_TC_SHCOMP] ? toEdit.toneCurve.shcompr + mods.toneCurve.shcompr : mods.toneCurve.shcompr; } if (toneCurve.autoexp) { - toEdit.toneCurve.autoexp = mods.toneCurve.autoexp; + toEdit.toneCurve.autoexp = mods.toneCurve.autoexp; } if (toneCurve.clip) { - toEdit.toneCurve.clip = mods.toneCurve.clip; + toEdit.toneCurve.clip = mods.toneCurve.clip; } if (toneCurve.expcomp) { - toEdit.toneCurve.expcomp = dontforceSet && options.baBehav[ADDSET_TC_EXPCOMP] ? toEdit.toneCurve.expcomp + mods.toneCurve.expcomp : mods.toneCurve.expcomp; + toEdit.toneCurve.expcomp = dontforceSet && options.baBehav[ADDSET_TC_EXPCOMP] ? toEdit.toneCurve.expcomp + mods.toneCurve.expcomp : mods.toneCurve.expcomp; } if (toneCurve.hlcompr) { - toEdit.toneCurve.hlcompr = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPAMOUNT] ? toEdit.toneCurve.hlcompr + mods.toneCurve.hlcompr : mods.toneCurve.hlcompr; + toEdit.toneCurve.hlcompr = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPAMOUNT] ? toEdit.toneCurve.hlcompr + mods.toneCurve.hlcompr : mods.toneCurve.hlcompr; } if (toneCurve.hlcomprthresh) { - toEdit.toneCurve.hlcomprthresh = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPTHRESH] ? toEdit.toneCurve.hlcomprthresh + mods.toneCurve.hlcomprthresh : mods.toneCurve.hlcomprthresh; + toEdit.toneCurve.hlcomprthresh = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPTHRESH] ? toEdit.toneCurve.hlcomprthresh + mods.toneCurve.hlcomprthresh : mods.toneCurve.hlcomprthresh; } if (toneCurve.hrenabled) { - toEdit.toneCurve.hrenabled = mods.toneCurve.hrenabled; + toEdit.toneCurve.hrenabled = mods.toneCurve.hrenabled; } if (toneCurve.method) { - toEdit.toneCurve.method = mods.toneCurve.method; + toEdit.toneCurve.method = mods.toneCurve.method; } if (toneCurve.histmatching) { - toEdit.toneCurve.histmatching = mods.toneCurve.histmatching; + toEdit.toneCurve.histmatching = mods.toneCurve.histmatching; } if (toneCurve.fromHistMatching) { - toEdit.toneCurve.fromHistMatching = mods.toneCurve.fromHistMatching; + toEdit.toneCurve.fromHistMatching = mods.toneCurve.fromHistMatching; } if (toneCurve.clampOOG) { @@ -1231,132 +1256,132 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (retinex.enabled) { - toEdit.retinex.enabled = mods.retinex.enabled; + toEdit.retinex.enabled = mods.retinex.enabled; } if (retinex.cdcurve) { - toEdit.retinex.cdcurve = mods.retinex.cdcurve; + toEdit.retinex.cdcurve = mods.retinex.cdcurve; } if (retinex.mapcurve) { - toEdit.retinex.mapcurve = mods.retinex.mapcurve; + toEdit.retinex.mapcurve = mods.retinex.mapcurve; } if (retinex.cdHcurve) { - toEdit.retinex.cdHcurve = mods.retinex.cdHcurve; + toEdit.retinex.cdHcurve = mods.retinex.cdHcurve; } if (retinex.lhcurve) { - toEdit.retinex.lhcurve = mods.retinex.lhcurve; + toEdit.retinex.lhcurve = mods.retinex.lhcurve; } if (retinex.transmissionCurve) { - toEdit.retinex.transmissionCurve = mods.retinex.transmissionCurve; + toEdit.retinex.transmissionCurve = mods.retinex.transmissionCurve; } if (retinex.gaintransmissionCurve) { - toEdit.retinex.gaintransmissionCurve = mods.retinex.gaintransmissionCurve; + toEdit.retinex.gaintransmissionCurve = mods.retinex.gaintransmissionCurve; } if (retinex.retinexMethod) { - toEdit.retinex.retinexMethod = mods.retinex.retinexMethod; + toEdit.retinex.retinexMethod = mods.retinex.retinexMethod; } if (retinex.mapMethod) { - toEdit.retinex.mapMethod = mods.retinex.mapMethod; + toEdit.retinex.mapMethod = mods.retinex.mapMethod; } if (retinex.viewMethod) { - toEdit.retinex.viewMethod = mods.retinex.viewMethod; + toEdit.retinex.viewMethod = mods.retinex.viewMethod; } if (retinex.retinexcolorspace) { - toEdit.retinex.retinexcolorspace = mods.retinex.retinexcolorspace; + toEdit.retinex.retinexcolorspace = mods.retinex.retinexcolorspace; } if (retinex.gammaretinex) { - toEdit.retinex.gammaretinex = mods.retinex.gammaretinex; + toEdit.retinex.gammaretinex = mods.retinex.gammaretinex; } if (retinex.gam) { - toEdit.retinex.gam = dontforceSet && options.baBehav[ADDSET_RETI_GAM] ? toEdit.retinex.gam + mods.retinex.gam : mods.retinex.gam; + toEdit.retinex.gam = dontforceSet && options.baBehav[ADDSET_RETI_GAM] ? toEdit.retinex.gam + mods.retinex.gam : mods.retinex.gam; } if (retinex.slope) { - toEdit.retinex.slope = dontforceSet && options.baBehav[ADDSET_RETI_SLO] ? toEdit.retinex.slope + mods.retinex.slope : mods.retinex.slope; + toEdit.retinex.slope = dontforceSet && options.baBehav[ADDSET_RETI_SLO] ? toEdit.retinex.slope + mods.retinex.slope : mods.retinex.slope; } if (retinex.str) { - toEdit.retinex.str = dontforceSet && options.baBehav[ADDSET_RETI_STR] ? toEdit.retinex.str + mods.retinex.str : mods.retinex.str; + toEdit.retinex.str = dontforceSet && options.baBehav[ADDSET_RETI_STR] ? toEdit.retinex.str + mods.retinex.str : mods.retinex.str; } if (retinex.scal) { - toEdit.retinex.scal = mods.retinex.scal; + toEdit.retinex.scal = mods.retinex.scal; } if (retinex.iter) { - toEdit.retinex.iter = mods.retinex.iter; + toEdit.retinex.iter = mods.retinex.iter; } if (retinex.grad) { - toEdit.retinex.grad = mods.retinex.grad; + toEdit.retinex.grad = mods.retinex.grad; } if (retinex.grads) { - toEdit.retinex.grads = mods.retinex.grads; + toEdit.retinex.grads = mods.retinex.grads; } // if (retinex.scal) { -// toEdit.retinex.scal = dontforceSet && options.baBehav[ADDSET_RETI_SCAL] ? toEdit.retinex.scal + mods.retinex.scal : mods.retinex.scal; +// toEdit.retinex.scal = dontforceSet && options.baBehav[ADDSET_RETI_SCAL] ? toEdit.retinex.scal + mods.retinex.scal : mods.retinex.scal; // } if (retinex.medianmap) { - toEdit.retinex.medianmap = mods.retinex.medianmap; + toEdit.retinex.medianmap = mods.retinex.medianmap; } if (retinex.neigh) { - toEdit.retinex.neigh = dontforceSet && options.baBehav[ADDSET_RETI_NEIGH] ? toEdit.retinex.neigh + mods.retinex.neigh : mods.retinex.neigh; + toEdit.retinex.neigh = dontforceSet && options.baBehav[ADDSET_RETI_NEIGH] ? toEdit.retinex.neigh + mods.retinex.neigh : mods.retinex.neigh; } if (retinex.limd) { - toEdit.retinex.limd = dontforceSet && options.baBehav[ADDSET_RETI_LIMD] ? toEdit.retinex.limd + mods.retinex.limd : mods.retinex.limd; + toEdit.retinex.limd = dontforceSet && options.baBehav[ADDSET_RETI_LIMD] ? toEdit.retinex.limd + mods.retinex.limd : mods.retinex.limd; } if (retinex.highl) { - toEdit.retinex.highl = mods.retinex.highl; + toEdit.retinex.highl = mods.retinex.highl; } if (retinex.skal) { - toEdit.retinex.skal = mods.retinex.skal; + toEdit.retinex.skal = mods.retinex.skal; } if (retinex.offs) { - toEdit.retinex.offs = dontforceSet && options.baBehav[ADDSET_RETI_OFFS] ? toEdit.retinex.offs + mods.retinex.offs : mods.retinex.offs; + toEdit.retinex.offs = dontforceSet && options.baBehav[ADDSET_RETI_OFFS] ? toEdit.retinex.offs + mods.retinex.offs : mods.retinex.offs; } if (retinex.vart) { - toEdit.retinex.vart = dontforceSet && options.baBehav[ADDSET_RETI_VART] ? toEdit.retinex.vart + mods.retinex.vart : mods.retinex.vart; + toEdit.retinex.vart = dontforceSet && options.baBehav[ADDSET_RETI_VART] ? toEdit.retinex.vart + mods.retinex.vart : mods.retinex.vart; } if (retinex.highlights) { - toEdit.retinex.highlights = mods.retinex.highlights; + toEdit.retinex.highlights = mods.retinex.highlights; } if (retinex.htonalwidth) { - toEdit.retinex.htonalwidth = mods.retinex.htonalwidth; + toEdit.retinex.htonalwidth = mods.retinex.htonalwidth; } if (retinex.shadows) { - toEdit.retinex.shadows = mods.retinex.shadows; + toEdit.retinex.shadows = mods.retinex.shadows; } if (retinex.stonalwidth) { - toEdit.retinex.stonalwidth = mods.retinex.stonalwidth; + toEdit.retinex.stonalwidth = mods.retinex.stonalwidth; } if (retinex.radius) { - toEdit.retinex.radius = mods.retinex.radius; + toEdit.retinex.radius = mods.retinex.radius; } @@ -1365,47 +1390,47 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (labCurve.lcurve) { - toEdit.labCurve.lcurve = mods.labCurve.lcurve; + toEdit.labCurve.lcurve = mods.labCurve.lcurve; } if (labCurve.acurve) { - toEdit.labCurve.acurve = mods.labCurve.acurve; + toEdit.labCurve.acurve = mods.labCurve.acurve; } if (labCurve.bcurve) { - toEdit.labCurve.bcurve = mods.labCurve.bcurve; + toEdit.labCurve.bcurve = mods.labCurve.bcurve; } if (labCurve.cccurve) { - toEdit.labCurve.cccurve = mods.labCurve.cccurve; + toEdit.labCurve.cccurve = mods.labCurve.cccurve; } if (labCurve.chcurve) { - toEdit.labCurve.chcurve = mods.labCurve.chcurve; + toEdit.labCurve.chcurve = mods.labCurve.chcurve; } if (labCurve.lhcurve) { - toEdit.labCurve.lhcurve = mods.labCurve.lhcurve; + toEdit.labCurve.lhcurve = mods.labCurve.lhcurve; } if (labCurve.hhcurve) { - toEdit.labCurve.hhcurve = mods.labCurve.hhcurve; + toEdit.labCurve.hhcurve = mods.labCurve.hhcurve; } if (labCurve.lccurve) { - toEdit.labCurve.lccurve = mods.labCurve.lccurve; + toEdit.labCurve.lccurve = mods.labCurve.lccurve; } if (labCurve.clcurve) { - toEdit.labCurve.clcurve = mods.labCurve.clcurve; + toEdit.labCurve.clcurve = mods.labCurve.clcurve; } if (labCurve.brightness) { - toEdit.labCurve.brightness = dontforceSet && options.baBehav[ADDSET_LC_BRIGHTNESS] ? toEdit.labCurve.brightness + mods.labCurve.brightness : mods.labCurve.brightness; + toEdit.labCurve.brightness = dontforceSet && options.baBehav[ADDSET_LC_BRIGHTNESS] ? toEdit.labCurve.brightness + mods.labCurve.brightness : mods.labCurve.brightness; } if (labCurve.contrast) { - toEdit.labCurve.contrast = dontforceSet && options.baBehav[ADDSET_LC_CONTRAST] ? toEdit.labCurve.contrast + mods.labCurve.contrast : mods.labCurve.contrast; + toEdit.labCurve.contrast = dontforceSet && options.baBehav[ADDSET_LC_CONTRAST] ? toEdit.labCurve.contrast + mods.labCurve.contrast : mods.labCurve.contrast; } if (labCurve.chromaticity) { @@ -1421,7 +1446,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (labCurve.lcredsk) { - toEdit.labCurve.lcredsk = mods.labCurve.lcredsk; + toEdit.labCurve.lcredsk = mods.labCurve.lcredsk; } if (localContrast.enabled) { @@ -1446,23 +1471,23 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (rgbCurves.lumamode) { - toEdit.rgbCurves.lumamode = mods.rgbCurves.lumamode; + toEdit.rgbCurves.lumamode = mods.rgbCurves.lumamode; } if (rgbCurves.rcurve) { - toEdit.rgbCurves.rcurve = mods.rgbCurves.rcurve; + toEdit.rgbCurves.rcurve = mods.rgbCurves.rcurve; } if (rgbCurves.gcurve) { - toEdit.rgbCurves.gcurve = mods.rgbCurves.gcurve; + toEdit.rgbCurves.gcurve = mods.rgbCurves.gcurve; } if (rgbCurves.bcurve) { - toEdit.rgbCurves.bcurve = mods.rgbCurves.bcurve; + toEdit.rgbCurves.bcurve = mods.rgbCurves.bcurve; } if (colorToning.enabled) { - toEdit.colorToning.enabled = mods.colorToning.enabled; + toEdit.colorToning.enabled = mods.colorToning.enabled; } if (colorToning.twocolor) { @@ -1470,7 +1495,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.opacityCurve) { - toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; + toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; } if (colorToning.colorCurve) { @@ -1478,11 +1503,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.enabled) { - toEdit.colorToning.enabled = mods.colorToning.enabled; + toEdit.colorToning.enabled = mods.colorToning.enabled; } if (colorToning.opacityCurve) { - toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; + toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; } if (colorToning.satprotectionthreshold) { @@ -1490,7 +1515,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.autosat) { - toEdit.colorToning.autosat = mods.colorToning.autosat; + toEdit.colorToning.autosat = mods.colorToning.autosat; } if (colorToning.saturatedopacity) { @@ -1498,23 +1523,23 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.strength) { - toEdit.colorToning.strength = dontforceSet && options.baBehav[ADDSET_COLORTONING_STRENGTH] ? toEdit.colorToning.strength + mods.colorToning.strength : mods.colorToning.strength; + toEdit.colorToning.strength = dontforceSet && options.baBehav[ADDSET_COLORTONING_STRENGTH] ? toEdit.colorToning.strength + mods.colorToning.strength : mods.colorToning.strength; } if (colorToning.shadowsColSat) { - toEdit.colorToning.shadowsColSat = mods.colorToning.shadowsColSat; + toEdit.colorToning.shadowsColSat = mods.colorToning.shadowsColSat; } if (colorToning.hlColSat) { - toEdit.colorToning.hlColSat = mods.colorToning.hlColSat; + toEdit.colorToning.hlColSat = mods.colorToning.hlColSat; } if (colorToning.balance) { - toEdit.colorToning.balance = dontforceSet && options.baBehav[ADDSET_COLORTONING_BALANCE] ? toEdit.colorToning.balance + mods.colorToning.balance : mods.colorToning.balance; + toEdit.colorToning.balance = dontforceSet && options.baBehav[ADDSET_COLORTONING_BALANCE] ? toEdit.colorToning.balance + mods.colorToning.balance : mods.colorToning.balance; } if (colorToning.clcurve) { - toEdit.colorToning.clcurve = mods.colorToning.clcurve; + toEdit.colorToning.clcurve = mods.colorToning.clcurve; } if (colorToning.method) { @@ -1522,11 +1547,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.cl2curve) { - toEdit.colorToning.cl2curve = mods.colorToning.cl2curve; + toEdit.colorToning.cl2curve = mods.colorToning.cl2curve; } if (colorToning.lumamode) { - toEdit.colorToning.lumamode = mods.colorToning.lumamode; + toEdit.colorToning.lumamode = mods.colorToning.lumamode; } if (colorToning.satlow) { @@ -1534,7 +1559,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.sathigh) { - toEdit.colorToning.sathigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.sathigh + mods.colorToning.sathigh : mods.colorToning.sathigh; + toEdit.colorToning.sathigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.sathigh + mods.colorToning.sathigh : mods.colorToning.sathigh; } if (colorToning.redlow) { @@ -1542,11 +1567,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.greenlow) { - toEdit.colorToning.greenlow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenlow + mods.colorToning.greenlow : mods.colorToning.greenlow; + toEdit.colorToning.greenlow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenlow + mods.colorToning.greenlow : mods.colorToning.greenlow; } if (colorToning.bluelow) { - toEdit.colorToning.bluelow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluelow + mods.colorToning.bluelow : mods.colorToning.bluelow; + toEdit.colorToning.bluelow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluelow + mods.colorToning.bluelow : mods.colorToning.bluelow; } if (colorToning.redmed) { @@ -1554,15 +1579,15 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.greenmed) { - toEdit.colorToning.greenmed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenmed + mods.colorToning.greenmed : mods.colorToning.greenmed; + toEdit.colorToning.greenmed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenmed + mods.colorToning.greenmed : mods.colorToning.greenmed; } if (colorToning.bluemed) { - toEdit.colorToning.bluemed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluemed + mods.colorToning.bluemed : mods.colorToning.bluemed; + toEdit.colorToning.bluemed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluemed + mods.colorToning.bluemed : mods.colorToning.bluemed; } if (colorToning.redhigh) { - toEdit.colorToning.redhigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.redhigh + mods.colorToning.redhigh : mods.colorToning.redhigh; + toEdit.colorToning.redhigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.redhigh + mods.colorToning.redhigh : mods.colorToning.redhigh; } if (colorToning.greenhigh) { @@ -1570,7 +1595,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.bluehigh) { - toEdit.colorToning.bluehigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluehigh + mods.colorToning.bluehigh : mods.colorToning.bluehigh; + toEdit.colorToning.bluehigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluehigh + mods.colorToning.bluehigh : mods.colorToning.bluehigh; } if (colorToning.labgridALow) { @@ -1598,7 +1623,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (sharpenEdge.enabled) { - toEdit.sharpenEdge.enabled = mods.sharpenEdge.enabled; + toEdit.sharpenEdge.enabled = mods.sharpenEdge.enabled; } if (sharpenEdge.passes) { @@ -1610,47 +1635,51 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (sharpenEdge.threechannels) { - toEdit.sharpenEdge.threechannels = mods.sharpenEdge.threechannels; + toEdit.sharpenEdge.threechannels = mods.sharpenEdge.threechannels; } if (sharpenMicro.enabled) { - toEdit.sharpenMicro.enabled = mods.sharpenMicro.enabled; + toEdit.sharpenMicro.enabled = mods.sharpenMicro.enabled; } if (sharpenMicro.matrix) { - toEdit.sharpenMicro.matrix = mods.sharpenMicro.matrix; + toEdit.sharpenMicro.matrix = mods.sharpenMicro.matrix; } if (sharpenMicro.amount) { - toEdit.sharpenMicro.amount = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_AMOUNT] ? toEdit.sharpenMicro.amount + mods.sharpenMicro.amount : mods.sharpenMicro.amount; + toEdit.sharpenMicro.amount = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_AMOUNT] ? toEdit.sharpenMicro.amount + mods.sharpenMicro.amount : mods.sharpenMicro.amount; } if (sharpenMicro.contrast) { - toEdit.sharpenMicro.contrast = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_CONTRAST] ? toEdit.sharpenMicro.contrast + mods.sharpenMicro.contrast : mods.sharpenMicro.contrast; + toEdit.sharpenMicro.contrast = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_CONTRAST] ? toEdit.sharpenMicro.contrast + mods.sharpenMicro.contrast : mods.sharpenMicro.contrast; } if (sharpenMicro.uniformity) { - toEdit.sharpenMicro.uniformity = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY] ? toEdit.sharpenMicro.uniformity + mods.sharpenMicro.uniformity : mods.sharpenMicro.uniformity; + toEdit.sharpenMicro.uniformity = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY] ? toEdit.sharpenMicro.uniformity + mods.sharpenMicro.uniformity : mods.sharpenMicro.uniformity; } if (sharpening.enabled) { - toEdit.sharpening.enabled = mods.sharpening.enabled; + toEdit.sharpening.enabled = mods.sharpening.enabled; } if (sharpening.contrast) { - toEdit.sharpening.contrast = dontforceSet && options.baBehav[ADDSET_SHARP_CONTRAST] ? toEdit.sharpening.contrast + mods.sharpening.contrast : mods.sharpening.contrast; + toEdit.sharpening.contrast = dontforceSet && options.baBehav[ADDSET_SHARP_CONTRAST] ? toEdit.sharpening.contrast + mods.sharpening.contrast : mods.sharpening.contrast; } if (sharpening.radius) { - toEdit.sharpening.radius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.radius + mods.sharpening.radius : mods.sharpening.radius; + toEdit.sharpening.radius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.radius + mods.sharpening.radius : mods.sharpening.radius; } if (sharpening.blurradius) { - toEdit.sharpening.blurradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.blurradius + mods.sharpening.blurradius : mods.sharpening.blurradius; + toEdit.sharpening.blurradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.blurradius + mods.sharpening.blurradius : mods.sharpening.blurradius; + } + + if (sharpening.gamma) { + toEdit.sharpening.gamma = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.gamma + mods.sharpening.gamma : mods.sharpening.gamma; } if (sharpening.amount) { - toEdit.sharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.amount + mods.sharpening.amount : mods.sharpening.amount; + toEdit.sharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.amount + mods.sharpening.amount : mods.sharpening.amount; } if (sharpening.threshold) { @@ -1658,7 +1687,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (sharpening.edgesonly) { - toEdit.sharpening.edgesonly = mods.sharpening.edgesonly; + toEdit.sharpening.edgesonly = mods.sharpening.edgesonly; } if (sharpening.edges_radius) { @@ -1678,39 +1707,71 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (sharpening.method) { - toEdit.sharpening.method = mods.sharpening.method; + toEdit.sharpening.method = mods.sharpening.method; } if (sharpening.deconvamount) { - toEdit.sharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.deconvamount + mods.sharpening.deconvamount : mods.sharpening.deconvamount; + toEdit.sharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.deconvamount + mods.sharpening.deconvamount : mods.sharpening.deconvamount; } if (sharpening.deconvradius) { - toEdit.sharpening.deconvradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.deconvradius + mods.sharpening.deconvradius : mods.sharpening.deconvradius; + toEdit.sharpening.deconvradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.deconvradius + mods.sharpening.deconvradius : mods.sharpening.deconvradius; } if (sharpening.deconviter) { - toEdit.sharpening.deconviter = dontforceSet && options.baBehav[ADDSET_SHARP_ITER] ? toEdit.sharpening.deconviter + mods.sharpening.deconviter : mods.sharpening.deconviter; + toEdit.sharpening.deconviter = dontforceSet && options.baBehav[ADDSET_SHARP_ITER] ? toEdit.sharpening.deconviter + mods.sharpening.deconviter : mods.sharpening.deconviter; } if (sharpening.deconvdamping) { toEdit.sharpening.deconvdamping = dontforceSet && options.baBehav[ADDSET_SHARP_DAMPING] ? toEdit.sharpening.deconvdamping + mods.sharpening.deconvdamping : mods.sharpening.deconvdamping; } + if (pdsharpening.enabled) { + toEdit.pdsharpening.enabled = mods.pdsharpening.enabled; + } + + if (pdsharpening.contrast) { + toEdit.pdsharpening.contrast = dontforceSet && options.baBehav[ADDSET_SHARP_CONTRAST] ? toEdit.pdsharpening.contrast + mods.pdsharpening.contrast : mods.pdsharpening.contrast; + } + + if (pdsharpening.autoContrast) { + toEdit.pdsharpening.autoContrast = mods.pdsharpening.autoContrast; + } + + if (pdsharpening.autoRadius) { + toEdit.pdsharpening.autoRadius = mods.pdsharpening.autoRadius; + } + + if (pdsharpening.gamma) { + toEdit.pdsharpening.gamma = dontforceSet && options.baBehav[ADDSET_SHARP_GAMMA] ? toEdit.pdsharpening.gamma + mods.pdsharpening.gamma : mods.pdsharpening.gamma; + } + + if (pdsharpening.deconvradius) { + toEdit.pdsharpening.deconvradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.pdsharpening.deconvradius + mods.pdsharpening.deconvradius : mods.pdsharpening.deconvradius; + } + + if (pdsharpening.deconvradiusOffset) { + toEdit.pdsharpening.deconvradiusOffset = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.pdsharpening.deconvradiusOffset + mods.pdsharpening.deconvradiusOffset : mods.pdsharpening.deconvradiusOffset; + } + + if (pdsharpening.deconviter) { + toEdit.pdsharpening.deconviter = dontforceSet && options.baBehav[ADDSET_SHARP_ITER] ? toEdit.pdsharpening.deconviter + mods.pdsharpening.deconviter : mods.pdsharpening.deconviter; + } + if (prsharpening.enabled) { - toEdit.prsharpening.enabled = mods.prsharpening.enabled; + toEdit.prsharpening.enabled = mods.prsharpening.enabled; } if (prsharpening.contrast) { - toEdit.prsharpening.contrast = dontforceSet && options.baBehav[ADDSET_SHARP_CONTRAST] ? toEdit.prsharpening.contrast + mods.prsharpening.contrast : mods.prsharpening.contrast; + toEdit.prsharpening.contrast = dontforceSet && options.baBehav[ADDSET_SHARP_CONTRAST] ? toEdit.prsharpening.contrast + mods.prsharpening.contrast : mods.prsharpening.contrast; } if (prsharpening.radius) { - toEdit.prsharpening.radius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.prsharpening.radius + mods.prsharpening.radius : mods.prsharpening.radius; + toEdit.prsharpening.radius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.prsharpening.radius + mods.prsharpening.radius : mods.prsharpening.radius; } if (prsharpening.amount) { - toEdit.prsharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.prsharpening.amount + mods.prsharpening.amount : mods.prsharpening.amount; + toEdit.prsharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.prsharpening.amount + mods.prsharpening.amount : mods.prsharpening.amount; } if (prsharpening.threshold) { @@ -1718,11 +1779,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (prsharpening.edgesonly) { - toEdit.prsharpening.edgesonly = mods.prsharpening.edgesonly; + toEdit.prsharpening.edgesonly = mods.prsharpening.edgesonly; } if (prsharpening.edges_radius) { - toEdit.prsharpening.edges_radius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.prsharpening.edges_radius + mods.prsharpening.edges_radius : mods.prsharpening.edges_radius; + toEdit.prsharpening.edges_radius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.prsharpening.edges_radius + mods.prsharpening.edges_radius : mods.prsharpening.edges_radius; } if (prsharpening.edges_tolerance) { @@ -1730,7 +1791,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (prsharpening.halocontrol) { - toEdit.prsharpening.halocontrol = mods.prsharpening.halocontrol; + toEdit.prsharpening.halocontrol = mods.prsharpening.halocontrol; } if (prsharpening.halocontrol_amount) { @@ -1738,19 +1799,19 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (prsharpening.method) { - toEdit.prsharpening.method = mods.prsharpening.method; + toEdit.prsharpening.method = mods.prsharpening.method; } if (prsharpening.deconvamount) { - toEdit.prsharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.prsharpening.deconvamount + mods.prsharpening.deconvamount : mods.prsharpening.deconvamount; + toEdit.prsharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.prsharpening.deconvamount + mods.prsharpening.deconvamount : mods.prsharpening.deconvamount; } if (prsharpening.deconvradius) { - toEdit.prsharpening.deconvradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.prsharpening.deconvradius + mods.prsharpening.deconvradius : mods.prsharpening.deconvradius; + toEdit.prsharpening.deconvradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.prsharpening.deconvradius + mods.prsharpening.deconvradius : mods.prsharpening.deconvradius; } if (prsharpening.deconviter) { - toEdit.prsharpening.deconviter = dontforceSet && options.baBehav[ADDSET_SHARP_ITER] ? toEdit.prsharpening.deconviter + mods.prsharpening.deconviter : mods.prsharpening.deconviter; + toEdit.prsharpening.deconviter = dontforceSet && options.baBehav[ADDSET_SHARP_ITER] ? toEdit.prsharpening.deconviter + mods.prsharpening.deconviter : mods.prsharpening.deconviter; } if (prsharpening.deconvdamping) { @@ -1758,79 +1819,79 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (vibrance.enabled) { - toEdit.vibrance.enabled = mods.vibrance.enabled; + toEdit.vibrance.enabled = mods.vibrance.enabled; } if (vibrance.pastels) { - toEdit.vibrance.pastels = dontforceSet && options.baBehav[ADDSET_VIBRANCE_PASTELS] ? toEdit.vibrance.pastels + mods.vibrance.pastels : mods.vibrance.pastels; + toEdit.vibrance.pastels = dontforceSet && options.baBehav[ADDSET_VIBRANCE_PASTELS] ? toEdit.vibrance.pastels + mods.vibrance.pastels : mods.vibrance.pastels; } if (vibrance.saturated) { - toEdit.vibrance.saturated = dontforceSet && options.baBehav[ADDSET_VIBRANCE_SATURATED] ? toEdit.vibrance.saturated + mods.vibrance.saturated : mods.vibrance.saturated; + toEdit.vibrance.saturated = dontforceSet && options.baBehav[ADDSET_VIBRANCE_SATURATED] ? toEdit.vibrance.saturated + mods.vibrance.saturated : mods.vibrance.saturated; } if (vibrance.psthreshold) { - toEdit.vibrance.psthreshold = mods.vibrance.psthreshold; + toEdit.vibrance.psthreshold = mods.vibrance.psthreshold; } if (vibrance.protectskins) { - toEdit.vibrance.protectskins = mods.vibrance.protectskins; + toEdit.vibrance.protectskins = mods.vibrance.protectskins; } if (vibrance.avoidcolorshift) { - toEdit.vibrance.avoidcolorshift = mods.vibrance.avoidcolorshift; + toEdit.vibrance.avoidcolorshift = mods.vibrance.avoidcolorshift; } if (vibrance.pastsattog) { - toEdit.vibrance.pastsattog = mods.vibrance.pastsattog; + toEdit.vibrance.pastsattog = mods.vibrance.pastsattog; } if (vibrance.skintonescurve) { - toEdit.vibrance.skintonescurve = mods.vibrance.skintonescurve; + toEdit.vibrance.skintonescurve = mods.vibrance.skintonescurve; } - //if (colorBoost.amount) toEdit.colorBoost.amount = dontforceSet && options.baBehav[ADDSET_CBOOST_AMOUNT] ? toEdit.colorBoost.amount + mods.colorBoost.amount : mods.colorBoost.amount; - //if (colorBoost.avoidclip) toEdit.colorBoost.avoidclip = mods.colorBoost.avoidclip; - //if (colorBoost.enable_saturationlimiter)toEdit.colorBoost.enable_saturationlimiter = mods.colorBoost.enable_saturationlimiter; - //if (colorBoost.saturationlimit) toEdit.colorBoost.saturationlimit = mods.colorBoost.saturationlimit; + //if (colorBoost.amount) toEdit.colorBoost.amount = dontforceSet && options.baBehav[ADDSET_CBOOST_AMOUNT] ? toEdit.colorBoost.amount + mods.colorBoost.amount : mods.colorBoost.amount; + //if (colorBoost.avoidclip) toEdit.colorBoost.avoidclip = mods.colorBoost.avoidclip; + //if (colorBoost.enable_saturationlimiter)toEdit.colorBoost.enable_saturationlimiter = mods.colorBoost.enable_saturationlimiter; + //if (colorBoost.saturationlimit) toEdit.colorBoost.saturationlimit = mods.colorBoost.saturationlimit; if (wb.enabled) { toEdit.wb.enabled = mods.wb.enabled; } if (wb.method) { - toEdit.wb.method = mods.wb.method; + toEdit.wb.method = mods.wb.method; } if (wb.equal) { - toEdit.wb.equal = dontforceSet && options.baBehav[ADDSET_WB_EQUAL] ? toEdit.wb.equal + mods.wb.equal : mods.wb.equal; + toEdit.wb.equal = dontforceSet && options.baBehav[ADDSET_WB_EQUAL] ? toEdit.wb.equal + mods.wb.equal : mods.wb.equal; } if (wb.tempBias) { - toEdit.wb.tempBias = dontforceSet && options.baBehav[ADDSET_WB_TEMPBIAS] ? toEdit.wb.tempBias + mods.wb.tempBias : mods.wb.tempBias; + toEdit.wb.tempBias = dontforceSet && options.baBehav[ADDSET_WB_TEMPBIAS] ? toEdit.wb.tempBias + mods.wb.tempBias : mods.wb.tempBias; } if (wb.green) { - toEdit.wb.green = dontforceSet && options.baBehav[ADDSET_WB_GREEN] ? toEdit.wb.green + mods.wb.green : mods.wb.green; + toEdit.wb.green = dontforceSet && options.baBehav[ADDSET_WB_GREEN] ? toEdit.wb.green + mods.wb.green : mods.wb.green; } if (wb.temperature) { - toEdit.wb.temperature = dontforceSet && options.baBehav[ADDSET_WB_TEMPERATURE] ? toEdit.wb.temperature + mods.wb.temperature : mods.wb.temperature; + toEdit.wb.temperature = dontforceSet && options.baBehav[ADDSET_WB_TEMPERATURE] ? toEdit.wb.temperature + mods.wb.temperature : mods.wb.temperature; } - //if (colorShift.a) toEdit.colorShift.a = dontforceSet && options.baBehav[ADDSET_CS_BLUEYELLOW] ? toEdit.colorShift.a + mods.colorShift.a : mods.colorShift.a; - //if (colorShift.b) toEdit.colorShift.b = dontforceSet && options.baBehav[ADDSET_CS_GREENMAGENTA] ? toEdit.colorShift.b + mods.colorShift.b : mods.colorShift.b; - //if (lumaDenoise.enabled) toEdit.lumaDenoise.enabled = mods.lumaDenoise.enabled; - //if (lumaDenoise.radius) toEdit.lumaDenoise.radius = mods.lumaDenoise.radius; - //if (lumaDenoise.edgetolerance) toEdit.lumaDenoise.edgetolerance = dontforceSet && options.baBehav[ADDSET_LD_EDGETOLERANCE] ? toEdit.lumaDenoise.edgetolerance + mods.lumaDenoise.edgetolerance : mods.lumaDenoise.edgetolerance; - //if (colorDenoise.enabled) toEdit.colorDenoise.enabled = mods.colorDenoise.enabled; - //if (colorDenoise.amount) toEdit.colorDenoise.amount = mods.colorDenoise.amount; + //if (colorShift.a) toEdit.colorShift.a = dontforceSet && options.baBehav[ADDSET_CS_BLUEYELLOW] ? toEdit.colorShift.a + mods.colorShift.a : mods.colorShift.a; + //if (colorShift.b) toEdit.colorShift.b = dontforceSet && options.baBehav[ADDSET_CS_GREENMAGENTA] ? toEdit.colorShift.b + mods.colorShift.b : mods.colorShift.b; + //if (lumaDenoise.enabled) toEdit.lumaDenoise.enabled = mods.lumaDenoise.enabled; + //if (lumaDenoise.radius) toEdit.lumaDenoise.radius = mods.lumaDenoise.radius; + //if (lumaDenoise.edgetolerance) toEdit.lumaDenoise.edgetolerance = dontforceSet && options.baBehav[ADDSET_LD_EDGETOLERANCE] ? toEdit.lumaDenoise.edgetolerance + mods.lumaDenoise.edgetolerance : mods.lumaDenoise.edgetolerance; + //if (colorDenoise.enabled) toEdit.colorDenoise.enabled = mods.colorDenoise.enabled; + //if (colorDenoise.amount) toEdit.colorDenoise.amount = mods.colorDenoise.amount; if (defringe.enabled) { - toEdit.defringe.enabled = mods.defringe.enabled; + toEdit.defringe.enabled = mods.defringe.enabled; } if (defringe.radius) { - toEdit.defringe.radius = mods.defringe.radius; + toEdit.defringe.radius = mods.defringe.radius; } if (defringe.threshold) { @@ -1838,23 +1899,23 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (defringe.huecurve) { - toEdit.defringe.huecurve = mods.defringe.huecurve; + toEdit.defringe.huecurve = mods.defringe.huecurve; } if (colorappearance.curve) { - toEdit.colorappearance.curve = mods.colorappearance.curve; + toEdit.colorappearance.curve = mods.colorappearance.curve; } if (colorappearance.curve2) { - toEdit.colorappearance.curve2 = mods.colorappearance.curve2; + toEdit.colorappearance.curve2 = mods.colorappearance.curve2; } if (colorappearance.curve3) { - toEdit.colorappearance.curve3 = mods.colorappearance.curve3; + toEdit.colorappearance.curve3 = mods.colorappearance.curve3; } if (colorappearance.curveMode) { - toEdit.colorappearance.curveMode = mods.colorappearance.curveMode; + toEdit.colorappearance.curveMode = mods.colorappearance.curveMode; } if (colorappearance.curveMode2) { @@ -1866,11 +1927,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorappearance.enabled) { - toEdit.colorappearance.enabled = mods.colorappearance.enabled; + toEdit.colorappearance.enabled = mods.colorappearance.enabled; } if (colorappearance.degree) { - toEdit.colorappearance.degree = dontforceSet && options.baBehav[ADDSET_CAT_DEGREE] ? toEdit.colorappearance.degree + mods.colorappearance.degree : mods.colorappearance.degree; + toEdit.colorappearance.degree = dontforceSet && options.baBehav[ADDSET_CAT_DEGREE] ? toEdit.colorappearance.degree + mods.colorappearance.degree : mods.colorappearance.degree; } if (colorappearance.autodegree) { @@ -1878,7 +1939,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorappearance.degreeout) { - toEdit.colorappearance.degreeout = mods.colorappearance.degreeout; + toEdit.colorappearance.degreeout = mods.colorappearance.degreeout; } if (colorappearance.autodegreeout) { @@ -1886,95 +1947,95 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorappearance.surround) { - toEdit.colorappearance.surround = mods.colorappearance.surround; + toEdit.colorappearance.surround = mods.colorappearance.surround; } if (colorappearance.surrsrc) { - toEdit.colorappearance.surrsrc = mods.colorappearance.surrsrc; + toEdit.colorappearance.surrsrc = mods.colorappearance.surrsrc; } if (colorappearance.autoadapscen) { - toEdit.colorappearance.autoadapscen = mods.colorappearance.autoadapscen; + toEdit.colorappearance.autoadapscen = mods.colorappearance.autoadapscen; } if (colorappearance.adapscen) { - toEdit.colorappearance.adapscen = dontforceSet && options.baBehav[ADDSET_CAT_ADAPTSCENE] ? toEdit.colorappearance.adapscen + mods.colorappearance.adapscen : mods.colorappearance.adapscen; + toEdit.colorappearance.adapscen = dontforceSet && options.baBehav[ADDSET_CAT_ADAPTSCENE] ? toEdit.colorappearance.adapscen + mods.colorappearance.adapscen : mods.colorappearance.adapscen; } if (colorappearance.autoybscen) { - toEdit.colorappearance.autoybscen = mods.colorappearance.autoybscen; + toEdit.colorappearance.autoybscen = mods.colorappearance.autoybscen; } if (colorappearance.ybscen) { - toEdit.colorappearance.ybscen = mods.colorappearance.ybscen; + toEdit.colorappearance.ybscen = mods.colorappearance.ybscen; } if (colorappearance.adaplum) { - toEdit.colorappearance.adaplum = dontforceSet && options.baBehav[ADDSET_CAT_ADAPTVIEWING] ? toEdit.colorappearance.adaplum + mods.colorappearance.adaplum : mods.colorappearance.adaplum; + toEdit.colorappearance.adaplum = dontforceSet && options.baBehav[ADDSET_CAT_ADAPTVIEWING] ? toEdit.colorappearance.adaplum + mods.colorappearance.adaplum : mods.colorappearance.adaplum; } if (colorappearance.badpixsl) { - toEdit.colorappearance.badpixsl = dontforceSet && options.baBehav[ADDSET_CAT_BADPIX] ? toEdit.colorappearance.badpixsl + mods.colorappearance.badpixsl : mods.colorappearance.badpixsl; + toEdit.colorappearance.badpixsl = dontforceSet && options.baBehav[ADDSET_CAT_BADPIX] ? toEdit.colorappearance.badpixsl + mods.colorappearance.badpixsl : mods.colorappearance.badpixsl; } if (colorappearance.wbmodel) { - toEdit.colorappearance.wbmodel = mods.colorappearance.wbmodel; + toEdit.colorappearance.wbmodel = mods.colorappearance.wbmodel; } if (colorappearance.algo) { - toEdit.colorappearance.algo = mods.colorappearance.algo; + toEdit.colorappearance.algo = mods.colorappearance.algo; } if (colorappearance.tempout) { - toEdit.colorappearance.tempout = mods.colorappearance.tempout; + toEdit.colorappearance.tempout = mods.colorappearance.tempout; } if (colorappearance.greenout) { - toEdit.colorappearance.greenout = mods.colorappearance.greenout; + toEdit.colorappearance.greenout = mods.colorappearance.greenout; } if (colorappearance.tempsc) { - toEdit.colorappearance.tempsc = mods.colorappearance.tempsc; + toEdit.colorappearance.tempsc = mods.colorappearance.tempsc; } if (colorappearance.greensc) { - toEdit.colorappearance.greensc = mods.colorappearance.greensc; + toEdit.colorappearance.greensc = mods.colorappearance.greensc; } if (colorappearance.ybout) { - toEdit.colorappearance.ybout = mods.colorappearance.ybout; + toEdit.colorappearance.ybout = mods.colorappearance.ybout; } if (colorappearance.jlight) { - toEdit.colorappearance.jlight = dontforceSet && options.baBehav[ADDSET_CAT_LIGHT] ? toEdit.colorappearance.jlight + mods.colorappearance.jlight : mods.colorappearance.jlight; + toEdit.colorappearance.jlight = dontforceSet && options.baBehav[ADDSET_CAT_LIGHT] ? toEdit.colorappearance.jlight + mods.colorappearance.jlight : mods.colorappearance.jlight; } if (colorappearance.qbright) { - toEdit.colorappearance.qbright = dontforceSet && options.baBehav[ADDSET_CAT_BRIGHT] ? toEdit.colorappearance.qbright + mods.colorappearance.qbright : mods.colorappearance.qbright; + toEdit.colorappearance.qbright = dontforceSet && options.baBehav[ADDSET_CAT_BRIGHT] ? toEdit.colorappearance.qbright + mods.colorappearance.qbright : mods.colorappearance.qbright; } if (colorappearance.chroma) { - toEdit.colorappearance.chroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA] ? toEdit.colorappearance.chroma + mods.colorappearance.chroma : mods.colorappearance.chroma; + toEdit.colorappearance.chroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA] ? toEdit.colorappearance.chroma + mods.colorappearance.chroma : mods.colorappearance.chroma; } if (colorappearance.schroma) { - toEdit.colorappearance.schroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA_S] ? toEdit.colorappearance.schroma + mods.colorappearance.schroma : mods.colorappearance.schroma; + toEdit.colorappearance.schroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA_S] ? toEdit.colorappearance.schroma + mods.colorappearance.schroma : mods.colorappearance.schroma; } if (colorappearance.mchroma) { - toEdit.colorappearance.mchroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA_M] ? toEdit.colorappearance.mchroma + mods.colorappearance.mchroma : mods.colorappearance.mchroma; + toEdit.colorappearance.mchroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA_M] ? toEdit.colorappearance.mchroma + mods.colorappearance.mchroma : mods.colorappearance.mchroma; } if (colorappearance.contrast) { - toEdit.colorappearance.contrast = dontforceSet && options.baBehav[ADDSET_CAT_CONTRAST] ? toEdit.colorappearance.contrast + mods.colorappearance.contrast : mods.colorappearance.contrast; + toEdit.colorappearance.contrast = dontforceSet && options.baBehav[ADDSET_CAT_CONTRAST] ? toEdit.colorappearance.contrast + mods.colorappearance.contrast : mods.colorappearance.contrast; } if (colorappearance.qcontrast) { - toEdit.colorappearance.qcontrast = dontforceSet && options.baBehav[ADDSET_CAT_CONTRAST_Q] ? toEdit.colorappearance.qcontrast + mods.colorappearance.qcontrast : mods.colorappearance.qcontrast; + toEdit.colorappearance.qcontrast = dontforceSet && options.baBehav[ADDSET_CAT_CONTRAST_Q] ? toEdit.colorappearance.qcontrast + mods.colorappearance.qcontrast : mods.colorappearance.qcontrast; } if (colorappearance.colorh) { - toEdit.colorappearance.colorh = dontforceSet && options.baBehav[ADDSET_CAT_HUE] ? toEdit.colorappearance.colorh + mods.colorappearance.colorh : mods.colorappearance.colorh; + toEdit.colorappearance.colorh = dontforceSet && options.baBehav[ADDSET_CAT_HUE] ? toEdit.colorappearance.colorh + mods.colorappearance.colorh : mods.colorappearance.colorh; } if (colorappearance.rstprotection) { @@ -2000,47 +2061,47 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng // if (colorappearance.sharpcie) toEdit.colorappearance.sharpcie = mods.colorappearance.sharpcie; if (impulseDenoise.enabled) { - toEdit.impulseDenoise.enabled = mods.impulseDenoise.enabled; + toEdit.impulseDenoise.enabled = mods.impulseDenoise.enabled; } if (impulseDenoise.thresh) { - toEdit.impulseDenoise.thresh = mods.impulseDenoise.thresh; + toEdit.impulseDenoise.thresh = mods.impulseDenoise.thresh; } if (dirpyrDenoise.enabled) { - toEdit.dirpyrDenoise.enabled = mods.dirpyrDenoise.enabled; + toEdit.dirpyrDenoise.enabled = mods.dirpyrDenoise.enabled; } if (dirpyrDenoise.enhance) { - toEdit.dirpyrDenoise.enhance = mods.dirpyrDenoise.enhance; + toEdit.dirpyrDenoise.enhance = mods.dirpyrDenoise.enhance; } if (dirpyrDenoise.median) { - toEdit.dirpyrDenoise.median = mods.dirpyrDenoise.median; + toEdit.dirpyrDenoise.median = mods.dirpyrDenoise.median; } if (dirpyrDenoise.luma) { - toEdit.dirpyrDenoise.luma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMA] ? toEdit.dirpyrDenoise.luma + mods.dirpyrDenoise.luma : mods.dirpyrDenoise.luma; + toEdit.dirpyrDenoise.luma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMA] ? toEdit.dirpyrDenoise.luma + mods.dirpyrDenoise.luma : mods.dirpyrDenoise.luma; } if (dirpyrDenoise.lcurve) { - toEdit.dirpyrDenoise.lcurve = mods.dirpyrDenoise.lcurve; + toEdit.dirpyrDenoise.lcurve = mods.dirpyrDenoise.lcurve; } if (dirpyrDenoise.cccurve) { - toEdit.dirpyrDenoise.cccurve = mods.dirpyrDenoise.cccurve; + toEdit.dirpyrDenoise.cccurve = mods.dirpyrDenoise.cccurve; } if (dirpyrDenoise.Ldetail) { - toEdit.dirpyrDenoise.Ldetail = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMDET] ? toEdit.dirpyrDenoise.Ldetail + mods.dirpyrDenoise.Ldetail : mods.dirpyrDenoise.Ldetail; + toEdit.dirpyrDenoise.Ldetail = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMDET] ? toEdit.dirpyrDenoise.Ldetail + mods.dirpyrDenoise.Ldetail : mods.dirpyrDenoise.Ldetail; } if (dirpyrDenoise.chroma) { - toEdit.dirpyrDenoise.chroma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMA] ? toEdit.dirpyrDenoise.chroma + mods.dirpyrDenoise.chroma : mods.dirpyrDenoise.chroma; + toEdit.dirpyrDenoise.chroma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMA] ? toEdit.dirpyrDenoise.chroma + mods.dirpyrDenoise.chroma : mods.dirpyrDenoise.chroma; } if (dirpyrDenoise.redchro) { - toEdit.dirpyrDenoise.redchro = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMARED] ? toEdit.dirpyrDenoise.redchro + mods.dirpyrDenoise.redchro : mods.dirpyrDenoise.redchro; + toEdit.dirpyrDenoise.redchro = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMARED] ? toEdit.dirpyrDenoise.redchro + mods.dirpyrDenoise.redchro : mods.dirpyrDenoise.redchro; } if (dirpyrDenoise.bluechro) { @@ -2048,68 +2109,68 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (dirpyrDenoise.gamma) { - toEdit.dirpyrDenoise.gamma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_GAMMA] ? toEdit.dirpyrDenoise.gamma + mods.dirpyrDenoise.gamma : mods.dirpyrDenoise.gamma; + toEdit.dirpyrDenoise.gamma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_GAMMA] ? toEdit.dirpyrDenoise.gamma + mods.dirpyrDenoise.gamma : mods.dirpyrDenoise.gamma; } if (dirpyrDenoise.passes) { - toEdit.dirpyrDenoise.passes = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_PASSES] ? toEdit.dirpyrDenoise.passes + mods.dirpyrDenoise.passes : mods.dirpyrDenoise.passes; + toEdit.dirpyrDenoise.passes = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_PASSES] ? toEdit.dirpyrDenoise.passes + mods.dirpyrDenoise.passes : mods.dirpyrDenoise.passes; } -// if (dirpyrDenoise.perform) toEdit.dirpyrDenoise.perform = mods.dirpyrDenoise.perform; +// if (dirpyrDenoise.perform) toEdit.dirpyrDenoise.perform = mods.dirpyrDenoise.perform; if (dirpyrDenoise.dmethod) { - toEdit.dirpyrDenoise.dmethod = mods.dirpyrDenoise.dmethod; + toEdit.dirpyrDenoise.dmethod = mods.dirpyrDenoise.dmethod; } if (dirpyrDenoise.Lmethod) { - toEdit.dirpyrDenoise.Lmethod = mods.dirpyrDenoise.Lmethod; + toEdit.dirpyrDenoise.Lmethod = mods.dirpyrDenoise.Lmethod; } if (dirpyrDenoise.Cmethod) { - toEdit.dirpyrDenoise.Cmethod = mods.dirpyrDenoise.Cmethod; + toEdit.dirpyrDenoise.Cmethod = mods.dirpyrDenoise.Cmethod; } if (dirpyrDenoise.C2method) { - toEdit.dirpyrDenoise.C2method = mods.dirpyrDenoise.C2method; + toEdit.dirpyrDenoise.C2method = mods.dirpyrDenoise.C2method; } if (dirpyrDenoise.smethod) { - toEdit.dirpyrDenoise.smethod = mods.dirpyrDenoise.smethod; + toEdit.dirpyrDenoise.smethod = mods.dirpyrDenoise.smethod; } if (dirpyrDenoise.medmethod) { - toEdit.dirpyrDenoise.medmethod = mods.dirpyrDenoise.medmethod; + toEdit.dirpyrDenoise.medmethod = mods.dirpyrDenoise.medmethod; } if (dirpyrDenoise.methodmed) { - toEdit.dirpyrDenoise.methodmed = mods.dirpyrDenoise.methodmed; + toEdit.dirpyrDenoise.methodmed = mods.dirpyrDenoise.methodmed; } if (dirpyrDenoise.rgbmethod) { - toEdit.dirpyrDenoise.rgbmethod = mods.dirpyrDenoise.rgbmethod; + toEdit.dirpyrDenoise.rgbmethod = mods.dirpyrDenoise.rgbmethod; } if (epd.enabled) { - toEdit.epd.enabled = mods.epd.enabled; + toEdit.epd.enabled = mods.epd.enabled; } if (epd.strength) { - toEdit.epd.strength = mods.epd.strength; + toEdit.epd.strength = mods.epd.strength; } if (epd.gamma) { - toEdit.epd.gamma = mods.epd.gamma; + toEdit.epd.gamma = mods.epd.gamma; } if (epd.edgeStopping) { - toEdit.epd.edgeStopping = mods.epd.edgeStopping; + toEdit.epd.edgeStopping = mods.epd.edgeStopping; } if (epd.scale) { - toEdit.epd.scale = mods.epd.scale; + toEdit.epd.scale = mods.epd.scale; } if (epd.reweightingIterates) { - toEdit.epd.reweightingIterates = mods.epd.reweightingIterates; + toEdit.epd.reweightingIterates = mods.epd.reweightingIterates; } if (fattal.enabled) { @@ -2129,31 +2190,31 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (sh.enabled) { - toEdit.sh.enabled = mods.sh.enabled; + toEdit.sh.enabled = mods.sh.enabled; } if (sh.highlights) { - toEdit.sh.highlights = dontforceSet && options.baBehav[ADDSET_SH_HIGHLIGHTS] ? toEdit.sh.highlights + mods.sh.highlights : mods.sh.highlights; + toEdit.sh.highlights = dontforceSet && options.baBehav[ADDSET_SH_HIGHLIGHTS] ? toEdit.sh.highlights + mods.sh.highlights : mods.sh.highlights; } if (sh.htonalwidth) { - toEdit.sh.htonalwidth = mods.sh.htonalwidth; + toEdit.sh.htonalwidth = mods.sh.htonalwidth; } if (sh.shadows) { - toEdit.sh.shadows = dontforceSet && options.baBehav[ADDSET_SH_SHADOWS] ? toEdit.sh.shadows + mods.sh.shadows : mods.sh.shadows; + toEdit.sh.shadows = dontforceSet && options.baBehav[ADDSET_SH_SHADOWS] ? toEdit.sh.shadows + mods.sh.shadows : mods.sh.shadows; } if (sh.stonalwidth) { - toEdit.sh.stonalwidth = mods.sh.stonalwidth; + toEdit.sh.stonalwidth = mods.sh.stonalwidth; } if (sh.radius) { - toEdit.sh.radius = mods.sh.radius; + toEdit.sh.radius = mods.sh.radius; } if (sh.lab) { - toEdit.sh.lab = mods.sh.lab; + toEdit.sh.lab = mods.sh.lab; } if (crop.enabled) { @@ -2161,27 +2222,27 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (crop.x) { - toEdit.crop.x = mods.crop.x; + toEdit.crop.x = mods.crop.x; } if (crop.y) { - toEdit.crop.y = mods.crop.y; + toEdit.crop.y = mods.crop.y; } if (crop.w) { - toEdit.crop.w = mods.crop.w; + toEdit.crop.w = mods.crop.w; } if (crop.h) { - toEdit.crop.h = mods.crop.h; + toEdit.crop.h = mods.crop.h; } if (crop.fixratio) { - toEdit.crop.fixratio = mods.crop.fixratio; + toEdit.crop.fixratio = mods.crop.fixratio; } if (crop.ratio) { - toEdit.crop.ratio = mods.crop.ratio; + toEdit.crop.ratio = mods.crop.ratio; } if (crop.orientation) { @@ -2189,51 +2250,51 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (crop.guide) { - toEdit.crop.guide = mods.crop.guide; + toEdit.crop.guide = mods.crop.guide; } if (coarse.rotate) { - toEdit.coarse.rotate = mods.coarse.rotate; + toEdit.coarse.rotate = mods.coarse.rotate; } if (coarse.hflip) { - toEdit.coarse.hflip = mods.coarse.hflip; + toEdit.coarse.hflip = mods.coarse.hflip; } if (coarse.vflip) { - toEdit.coarse.vflip = mods.coarse.vflip; + toEdit.coarse.vflip = mods.coarse.vflip; } if (commonTrans.autofill) { - toEdit.commonTrans.autofill = mods.commonTrans.autofill; + toEdit.commonTrans.autofill = mods.commonTrans.autofill; } if (rotate.degree) { - toEdit.rotate.degree = dontforceSet && options.baBehav[ADDSET_ROTATE_DEGREE] ? toEdit.rotate.degree + mods.rotate.degree : mods.rotate.degree; + toEdit.rotate.degree = dontforceSet && options.baBehav[ADDSET_ROTATE_DEGREE] ? toEdit.rotate.degree + mods.rotate.degree : mods.rotate.degree; } if (distortion.amount) { - toEdit.distortion.amount = dontforceSet && options.baBehav[ADDSET_DIST_AMOUNT] ? toEdit.distortion.amount + mods.distortion.amount : mods.distortion.amount; + toEdit.distortion.amount = dontforceSet && options.baBehav[ADDSET_DIST_AMOUNT] ? toEdit.distortion.amount + mods.distortion.amount : mods.distortion.amount; } if (lensProf.lcMode) { - toEdit.lensProf.lcMode = mods.lensProf.lcMode; + toEdit.lensProf.lcMode = mods.lensProf.lcMode; } if (lensProf.lcpFile) { - toEdit.lensProf.lcpFile = mods.lensProf.lcpFile; + toEdit.lensProf.lcpFile = mods.lensProf.lcpFile; } if (lensProf.useDist) { - toEdit.lensProf.useDist = mods.lensProf.useDist; + toEdit.lensProf.useDist = mods.lensProf.useDist; } if (lensProf.useVign) { - toEdit.lensProf.useVign = mods.lensProf.useVign; + toEdit.lensProf.useVign = mods.lensProf.useVign; } if (lensProf.useCA) { - toEdit.lensProf.useCA = mods.lensProf.useCA; + toEdit.lensProf.useCA = mods.lensProf.useCA; } if (lensProf.lfCameraMake) { @@ -2249,47 +2310,47 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (perspective.horizontal) { - toEdit.perspective.horizontal = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.horizontal + mods.perspective.horizontal : mods.perspective.horizontal; + toEdit.perspective.horizontal = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.horizontal + mods.perspective.horizontal : mods.perspective.horizontal; } if (perspective.vertical) { - toEdit.perspective.vertical = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.vertical + mods.perspective.vertical : mods.perspective.vertical; + toEdit.perspective.vertical = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.vertical + mods.perspective.vertical : mods.perspective.vertical; } if (gradient.enabled) { - toEdit.gradient.enabled = mods.gradient.enabled; + toEdit.gradient.enabled = mods.gradient.enabled; } if (gradient.degree) { - toEdit.gradient.degree = dontforceSet && options.baBehav[ADDSET_GRADIENT_DEGREE] ? toEdit.gradient.degree + mods.gradient.degree : mods.gradient.degree; + toEdit.gradient.degree = dontforceSet && options.baBehav[ADDSET_GRADIENT_DEGREE] ? toEdit.gradient.degree + mods.gradient.degree : mods.gradient.degree; } if (gradient.feather) { - toEdit.gradient.feather = dontforceSet && options.baBehav[ADDSET_GRADIENT_FEATHER] ? toEdit.gradient.feather + mods.gradient.feather : mods.gradient.feather; + toEdit.gradient.feather = dontforceSet && options.baBehav[ADDSET_GRADIENT_FEATHER] ? toEdit.gradient.feather + mods.gradient.feather : mods.gradient.feather; } if (gradient.strength) { - toEdit.gradient.strength = dontforceSet && options.baBehav[ADDSET_GRADIENT_STRENGTH] ? toEdit.gradient.strength + mods.gradient.strength : mods.gradient.strength; + toEdit.gradient.strength = dontforceSet && options.baBehav[ADDSET_GRADIENT_STRENGTH] ? toEdit.gradient.strength + mods.gradient.strength : mods.gradient.strength; } if (gradient.centerX) { - toEdit.gradient.centerX = dontforceSet && options.baBehav[ADDSET_GRADIENT_CENTER] ? toEdit.gradient.centerX + mods.gradient.centerX : mods.gradient.centerX; + toEdit.gradient.centerX = dontforceSet && options.baBehav[ADDSET_GRADIENT_CENTER] ? toEdit.gradient.centerX + mods.gradient.centerX : mods.gradient.centerX; } if (gradient.centerY) { - toEdit.gradient.centerY = dontforceSet && options.baBehav[ADDSET_GRADIENT_CENTER] ? toEdit.gradient.centerY + mods.gradient.centerY : mods.gradient.centerY; + toEdit.gradient.centerY = dontforceSet && options.baBehav[ADDSET_GRADIENT_CENTER] ? toEdit.gradient.centerY + mods.gradient.centerY : mods.gradient.centerY; } if (pcvignette.enabled) { - toEdit.pcvignette.enabled = mods.pcvignette.enabled; + toEdit.pcvignette.enabled = mods.pcvignette.enabled; } if (pcvignette.strength) { - toEdit.pcvignette.strength = dontforceSet && options.baBehav[ADDSET_PCVIGNETTE_STRENGTH] ? toEdit.pcvignette.strength + mods.pcvignette.strength : mods.pcvignette.strength; + toEdit.pcvignette.strength = dontforceSet && options.baBehav[ADDSET_PCVIGNETTE_STRENGTH] ? toEdit.pcvignette.strength + mods.pcvignette.strength : mods.pcvignette.strength; } if (pcvignette.feather) { - toEdit.pcvignette.feather = dontforceSet && options.baBehav[ADDSET_PCVIGNETTE_FEATHER] ? toEdit.pcvignette.feather + mods.pcvignette.feather : mods.pcvignette.feather; + toEdit.pcvignette.feather = dontforceSet && options.baBehav[ADDSET_PCVIGNETTE_FEATHER] ? toEdit.pcvignette.feather + mods.pcvignette.feather : mods.pcvignette.feather; } if (pcvignette.roundness) { @@ -2297,19 +2358,19 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (cacorrection.red) { - toEdit.cacorrection.red = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.red + mods.cacorrection.red : mods.cacorrection.red; + toEdit.cacorrection.red = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.red + mods.cacorrection.red : mods.cacorrection.red; } if (cacorrection.blue) { - toEdit.cacorrection.blue = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.blue + mods.cacorrection.blue : mods.cacorrection.blue; + toEdit.cacorrection.blue = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.blue + mods.cacorrection.blue : mods.cacorrection.blue; } if (vignetting.amount) { - toEdit.vignetting.amount = dontforceSet && options.baBehav[ADDSET_VIGN_AMOUNT] ? toEdit.vignetting.amount + mods.vignetting.amount : mods.vignetting.amount; + toEdit.vignetting.amount = dontforceSet && options.baBehav[ADDSET_VIGN_AMOUNT] ? toEdit.vignetting.amount + mods.vignetting.amount : mods.vignetting.amount; } if (vignetting.radius) { - toEdit.vignetting.radius = dontforceSet && options.baBehav[ADDSET_VIGN_RADIUS] ? toEdit.vignetting.radius + mods.vignetting.radius : mods.vignetting.radius; + toEdit.vignetting.radius = dontforceSet && options.baBehav[ADDSET_VIGN_RADIUS] ? toEdit.vignetting.radius + mods.vignetting.radius : mods.vignetting.radius; } if (vignetting.strength) { @@ -2330,92 +2391,92 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng for (int i = 0; i < 3; i++) { if (chmixer.red[i]) { - toEdit.chmixer.red[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.red[i] + mods.chmixer.red[i] : mods.chmixer.red[i]; + toEdit.chmixer.red[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.red[i] + mods.chmixer.red[i] : mods.chmixer.red[i]; } if (chmixer.green[i]) { - toEdit.chmixer.green[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.green[i] + mods.chmixer.green[i] : mods.chmixer.green[i]; + toEdit.chmixer.green[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.green[i] + mods.chmixer.green[i] : mods.chmixer.green[i]; } if (chmixer.blue[i]) { - toEdit.chmixer.blue[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.blue[i] + mods.chmixer.blue[i] : mods.chmixer.blue[i]; + toEdit.chmixer.blue[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.blue[i] + mods.chmixer.blue[i] : mods.chmixer.blue[i]; } } if (blackwhite.enabled) { - toEdit.blackwhite.enabled = mods.blackwhite.enabled; + toEdit.blackwhite.enabled = mods.blackwhite.enabled; } if (blackwhite.method) { - toEdit.blackwhite.method = mods.blackwhite.method; + toEdit.blackwhite.method = mods.blackwhite.method; } if (blackwhite.luminanceCurve) { - toEdit.blackwhite.luminanceCurve = mods.blackwhite.luminanceCurve; + toEdit.blackwhite.luminanceCurve = mods.blackwhite.luminanceCurve; } if (blackwhite.autoc) { - toEdit.blackwhite.autoc = mods.blackwhite.autoc; + toEdit.blackwhite.autoc = mods.blackwhite.autoc; } if (blackwhite.setting) { - toEdit.blackwhite.setting = mods.blackwhite.setting; + toEdit.blackwhite.setting = mods.blackwhite.setting; } if (blackwhite.enabledcc) { - toEdit.blackwhite.enabledcc = mods.blackwhite.enabledcc; + toEdit.blackwhite.enabledcc = mods.blackwhite.enabledcc; } if (blackwhite.filter) { - toEdit.blackwhite.filter = mods.blackwhite.filter; + toEdit.blackwhite.filter = mods.blackwhite.filter; } if (blackwhite.mixerRed) { - toEdit.blackwhite.mixerRed = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerRed + mods.blackwhite.mixerRed : mods.blackwhite.mixerRed; + toEdit.blackwhite.mixerRed = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerRed + mods.blackwhite.mixerRed : mods.blackwhite.mixerRed; } if (blackwhite.mixerOrange) { - toEdit.blackwhite.mixerOrange = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerOrange + mods.blackwhite.mixerOrange : mods.blackwhite.mixerOrange; + toEdit.blackwhite.mixerOrange = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerOrange + mods.blackwhite.mixerOrange : mods.blackwhite.mixerOrange; } if (blackwhite.mixerYellow) { - toEdit.blackwhite.mixerYellow = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerYellow + mods.blackwhite.mixerYellow : mods.blackwhite.mixerYellow; + toEdit.blackwhite.mixerYellow = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerYellow + mods.blackwhite.mixerYellow : mods.blackwhite.mixerYellow; } if (blackwhite.mixerGreen) { - toEdit.blackwhite.mixerGreen = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerGreen + mods.blackwhite.mixerGreen : mods.blackwhite.mixerGreen; + toEdit.blackwhite.mixerGreen = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerGreen + mods.blackwhite.mixerGreen : mods.blackwhite.mixerGreen; } if (blackwhite.mixerCyan) { - toEdit.blackwhite.mixerCyan = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerCyan + mods.blackwhite.mixerCyan : mods.blackwhite.mixerCyan; + toEdit.blackwhite.mixerCyan = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerCyan + mods.blackwhite.mixerCyan : mods.blackwhite.mixerCyan; } if (blackwhite.mixerBlue) { - toEdit.blackwhite.mixerBlue = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerBlue + mods.blackwhite.mixerBlue : mods.blackwhite.mixerBlue; + toEdit.blackwhite.mixerBlue = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerBlue + mods.blackwhite.mixerBlue : mods.blackwhite.mixerBlue; } if (blackwhite.mixerMagenta) { - toEdit.blackwhite.mixerMagenta = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerMagenta + mods.blackwhite.mixerMagenta : mods.blackwhite.mixerMagenta; + toEdit.blackwhite.mixerMagenta = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerMagenta + mods.blackwhite.mixerMagenta : mods.blackwhite.mixerMagenta; } if (blackwhite.mixerPurple) { - toEdit.blackwhite.mixerPurple = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerPurple + mods.blackwhite.mixerPurple : mods.blackwhite.mixerPurple; + toEdit.blackwhite.mixerPurple = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerPurple + mods.blackwhite.mixerPurple : mods.blackwhite.mixerPurple; } if (blackwhite.gammaRed) { - toEdit.blackwhite.gammaRed = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaRed + mods.blackwhite.gammaRed : mods.blackwhite.gammaRed; + toEdit.blackwhite.gammaRed = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaRed + mods.blackwhite.gammaRed : mods.blackwhite.gammaRed; } if (blackwhite.gammaGreen) { - toEdit.blackwhite.gammaGreen = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaGreen + mods.blackwhite.gammaGreen : mods.blackwhite.gammaGreen; + toEdit.blackwhite.gammaGreen = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaGreen + mods.blackwhite.gammaGreen : mods.blackwhite.gammaGreen; } if (blackwhite.gammaBlue) { - toEdit.blackwhite.gammaBlue = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaBlue + mods.blackwhite.gammaBlue : mods.blackwhite.gammaBlue; + toEdit.blackwhite.gammaBlue = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaBlue + mods.blackwhite.gammaBlue : mods.blackwhite.gammaBlue; } if (blackwhite.beforeCurve) { - toEdit.blackwhite.beforeCurve = mods.blackwhite.beforeCurve; + toEdit.blackwhite.beforeCurve = mods.blackwhite.beforeCurve; } if (blackwhite.beforeCurveMode) { @@ -2423,19 +2484,19 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (blackwhite.afterCurve) { - toEdit.blackwhite.afterCurve = mods.blackwhite.afterCurve; + toEdit.blackwhite.afterCurve = mods.blackwhite.afterCurve; } if (blackwhite.afterCurveMode) { - toEdit.blackwhite.afterCurveMode = mods.blackwhite.afterCurveMode; + toEdit.blackwhite.afterCurveMode = mods.blackwhite.afterCurveMode; } if (blackwhite.algo) { - toEdit.blackwhite.algo = mods.blackwhite.algo; + toEdit.blackwhite.algo = mods.blackwhite.algo; } if (resize.scale) { - toEdit.resize.scale = dontforceSet && options.baBehav[ADDSET_RESIZE_SCALE] ? toEdit.resize.scale + mods.resize.scale : mods.resize.scale; + toEdit.resize.scale = dontforceSet && options.baBehav[ADDSET_RESIZE_SCALE] ? toEdit.resize.scale + mods.resize.scale : mods.resize.scale; } if (resize.appliesTo) { @@ -2443,23 +2504,23 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (resize.method) { - toEdit.resize.method = mods.resize.method; + toEdit.resize.method = mods.resize.method; } if (resize.dataspec) { - toEdit.resize.dataspec = mods.resize.dataspec; + toEdit.resize.dataspec = mods.resize.dataspec; } if (resize.width) { - toEdit.resize.width = mods.resize.width; + toEdit.resize.width = mods.resize.width; } if (resize.height) { - toEdit.resize.height = mods.resize.height; + toEdit.resize.height = mods.resize.height; } if (resize.enabled) { - toEdit.resize.enabled = mods.resize.enabled; + toEdit.resize.enabled = mods.resize.enabled; } if (resize.allowUpscaling) { @@ -2519,47 +2580,47 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (raw.bayersensor.method) { - toEdit.raw.bayersensor.method = mods.raw.bayersensor.method; + toEdit.raw.bayersensor.method = mods.raw.bayersensor.method; } if (raw.bayersensor.border) { - toEdit.raw.bayersensor.border = mods.raw.bayersensor.border; + toEdit.raw.bayersensor.border = mods.raw.bayersensor.border; } if (raw.bayersensor.imageNum) { - toEdit.raw.bayersensor.imageNum = mods.raw.bayersensor.imageNum; + toEdit.raw.bayersensor.imageNum = mods.raw.bayersensor.imageNum; } if (raw.bayersensor.ccSteps) { - toEdit.raw.bayersensor.ccSteps = mods.raw.bayersensor.ccSteps; + toEdit.raw.bayersensor.ccSteps = mods.raw.bayersensor.ccSteps; } if (raw.bayersensor.exBlack0) { - toEdit.raw.bayersensor.black0 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black0 + mods.raw.bayersensor.black0 : mods.raw.bayersensor.black0; + toEdit.raw.bayersensor.black0 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black0 + mods.raw.bayersensor.black0 : mods.raw.bayersensor.black0; } if (raw.bayersensor.exBlack1) { - toEdit.raw.bayersensor.black1 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black1 + mods.raw.bayersensor.black1 : mods.raw.bayersensor.black1; + toEdit.raw.bayersensor.black1 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black1 + mods.raw.bayersensor.black1 : mods.raw.bayersensor.black1; } if (raw.bayersensor.exBlack2) { - toEdit.raw.bayersensor.black2 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black2 + mods.raw.bayersensor.black2 : mods.raw.bayersensor.black2; + toEdit.raw.bayersensor.black2 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black2 + mods.raw.bayersensor.black2 : mods.raw.bayersensor.black2; } if (raw.bayersensor.exBlack3) { - toEdit.raw.bayersensor.black3 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black3 + mods.raw.bayersensor.black3 : mods.raw.bayersensor.black3; + toEdit.raw.bayersensor.black3 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black3 + mods.raw.bayersensor.black3 : mods.raw.bayersensor.black3; } if (raw.bayersensor.exTwoGreen) { - toEdit.raw.bayersensor.twogreen = mods.raw.bayersensor.twogreen; + toEdit.raw.bayersensor.twogreen = mods.raw.bayersensor.twogreen; } if (raw.bayersensor.dcbIterations) { - toEdit.raw.bayersensor.dcb_iterations = mods.raw.bayersensor.dcb_iterations; + toEdit.raw.bayersensor.dcb_iterations = mods.raw.bayersensor.dcb_iterations; } if (raw.bayersensor.dcbEnhance) { - toEdit.raw.bayersensor.dcb_enhance = mods.raw.bayersensor.dcb_enhance; + toEdit.raw.bayersensor.dcb_enhance = mods.raw.bayersensor.dcb_enhance; } if (raw.bayersensor.lmmseIterations) { @@ -2631,11 +2692,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (raw.bayersensor.greenEq) { - toEdit.raw.bayersensor.greenthresh = dontforceSet && options.baBehav[ADDSET_PREPROCESS_GREENEQUIL] ? toEdit.raw.bayersensor.greenthresh + mods.raw.bayersensor.greenthresh : mods.raw.bayersensor.greenthresh; + toEdit.raw.bayersensor.greenthresh = dontforceSet && options.baBehav[ADDSET_PREPROCESS_GREENEQUIL] ? toEdit.raw.bayersensor.greenthresh + mods.raw.bayersensor.greenthresh : mods.raw.bayersensor.greenthresh; } if (raw.bayersensor.linenoise) { - toEdit.raw.bayersensor.linenoise = dontforceSet && options.baBehav[ADDSET_PREPROCESS_LINEDENOISE] ? toEdit.raw.bayersensor.linenoise + mods.raw.bayersensor.linenoise : mods.raw.bayersensor.linenoise; + toEdit.raw.bayersensor.linenoise = dontforceSet && options.baBehav[ADDSET_PREPROCESS_LINEDENOISE] ? toEdit.raw.bayersensor.linenoise + mods.raw.bayersensor.linenoise : mods.raw.bayersensor.linenoise; } if (raw.bayersensor.linenoiseDirection) { @@ -2647,67 +2708,67 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (raw.xtranssensor.method) { - toEdit.raw.xtranssensor.method = mods.raw.xtranssensor.method; + toEdit.raw.xtranssensor.method = mods.raw.xtranssensor.method; } if (raw.xtranssensor.dualDemosaicAutoContrast) { - toEdit.raw.xtranssensor.dualDemosaicAutoContrast = mods.raw.xtranssensor.dualDemosaicAutoContrast; + toEdit.raw.xtranssensor.dualDemosaicAutoContrast = mods.raw.xtranssensor.dualDemosaicAutoContrast; } if (raw.xtranssensor.dualDemosaicContrast) { - toEdit.raw.xtranssensor.dualDemosaicContrast = mods.raw.xtranssensor.dualDemosaicContrast; + toEdit.raw.xtranssensor.dualDemosaicContrast = mods.raw.xtranssensor.dualDemosaicContrast; } if (raw.xtranssensor.ccSteps) { - toEdit.raw.xtranssensor.ccSteps = mods.raw.xtranssensor.ccSteps; + toEdit.raw.xtranssensor.ccSteps = mods.raw.xtranssensor.ccSteps; } if (raw.xtranssensor.border) { - toEdit.raw.xtranssensor.border = mods.raw.xtranssensor.border; + toEdit.raw.xtranssensor.border = mods.raw.xtranssensor.border; } if (raw.xtranssensor.exBlackRed) { - toEdit.raw.xtranssensor.blackred = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackred + mods.raw.xtranssensor.blackred : mods.raw.xtranssensor.blackred; + toEdit.raw.xtranssensor.blackred = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackred + mods.raw.xtranssensor.blackred : mods.raw.xtranssensor.blackred; } if (raw.xtranssensor.exBlackGreen) { - toEdit.raw.xtranssensor.blackgreen = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackgreen + mods.raw.xtranssensor.blackgreen : mods.raw.xtranssensor.blackgreen; + toEdit.raw.xtranssensor.blackgreen = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackgreen + mods.raw.xtranssensor.blackgreen : mods.raw.xtranssensor.blackgreen; } if (raw.xtranssensor.exBlackBlue) { - toEdit.raw.xtranssensor.blackblue = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackblue + mods.raw.xtranssensor.blackblue : mods.raw.xtranssensor.blackblue; + toEdit.raw.xtranssensor.blackblue = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackblue + mods.raw.xtranssensor.blackblue : mods.raw.xtranssensor.blackblue; } if (raw.ca_autocorrect) { - toEdit.raw.ca_autocorrect = mods.raw.ca_autocorrect; + toEdit.raw.ca_autocorrect = mods.raw.ca_autocorrect; } if (raw.ca_avoidcolourshift) { - toEdit.raw.ca_avoidcolourshift = mods.raw.ca_avoidcolourshift; + toEdit.raw.ca_avoidcolourshift = mods.raw.ca_avoidcolourshift; } if (raw.caautoiterations) { - toEdit.raw.caautoiterations = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.caautoiterations + mods.raw.caautoiterations : mods.raw.caautoiterations; + toEdit.raw.caautoiterations = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.caautoiterations + mods.raw.caautoiterations : mods.raw.caautoiterations; } if (raw.cared) { - toEdit.raw.cared = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cared + mods.raw.cared : mods.raw.cared; + toEdit.raw.cared = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cared + mods.raw.cared : mods.raw.cared; } if (raw.cablue) { - toEdit.raw.cablue = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cablue + mods.raw.cablue : mods.raw.cablue; + toEdit.raw.cablue = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cablue + mods.raw.cablue : mods.raw.cablue; } if (raw.exPos) { - toEdit.raw.expos = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_LINEAR] ? toEdit.raw.expos + mods.raw.expos : mods.raw.expos; + toEdit.raw.expos = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_LINEAR] ? toEdit.raw.expos + mods.raw.expos : mods.raw.expos; } if (raw.hotPixelFilter) { - toEdit.raw.hotPixelFilter = mods.raw.hotPixelFilter; + toEdit.raw.hotPixelFilter = mods.raw.hotPixelFilter; } if (raw.deadPixelFilter) { - toEdit.raw.deadPixelFilter = mods.raw.deadPixelFilter; + toEdit.raw.deadPixelFilter = mods.raw.deadPixelFilter; } if (raw.hotdeadpix_thresh) { @@ -2715,27 +2776,27 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (raw.darkFrame) { - toEdit.raw.dark_frame = mods.raw.dark_frame; + toEdit.raw.dark_frame = mods.raw.dark_frame; } if (raw.df_autoselect) { - toEdit.raw.df_autoselect = mods.raw.df_autoselect; + toEdit.raw.df_autoselect = mods.raw.df_autoselect; } if (raw.ff_file) { - toEdit.raw.ff_file = mods.raw.ff_file; + toEdit.raw.ff_file = mods.raw.ff_file; } if (raw.ff_AutoSelect) { - toEdit.raw.ff_AutoSelect = mods.raw.ff_AutoSelect; + toEdit.raw.ff_AutoSelect = mods.raw.ff_AutoSelect; } if (raw.ff_BlurRadius) { - toEdit.raw.ff_BlurRadius = mods.raw.ff_BlurRadius; + toEdit.raw.ff_BlurRadius = mods.raw.ff_BlurRadius; } if (raw.ff_BlurType) { - toEdit.raw.ff_BlurType = mods.raw.ff_BlurType; + toEdit.raw.ff_BlurType = mods.raw.ff_BlurType; } if (raw.ff_AutoClipControl) { @@ -2743,135 +2804,135 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (raw.ff_clipControl) { - toEdit.raw.ff_clipControl = dontforceSet && options.baBehav[ADDSET_RAWFFCLIPCONTROL] ? toEdit.raw.ff_clipControl + mods.raw.ff_clipControl : mods.raw.ff_clipControl; + toEdit.raw.ff_clipControl = dontforceSet && options.baBehav[ADDSET_RAWFFCLIPCONTROL] ? toEdit.raw.ff_clipControl + mods.raw.ff_clipControl : mods.raw.ff_clipControl; } if (wavelet.enabled) { - toEdit.wavelet.enabled = mods.wavelet.enabled; + toEdit.wavelet.enabled = mods.wavelet.enabled; } if (wavelet.strength) { - toEdit.wavelet.strength = mods.wavelet.strength; + toEdit.wavelet.strength = mods.wavelet.strength; } if (wavelet.balance) { - toEdit.wavelet.balance = mods.wavelet.balance; + toEdit.wavelet.balance = mods.wavelet.balance; } if (wavelet.iter) { - toEdit.wavelet.iter = mods.wavelet.iter; + toEdit.wavelet.iter = mods.wavelet.iter; } if (wavelet.median) { - toEdit.wavelet.median = mods.wavelet.median; + toEdit.wavelet.median = mods.wavelet.median; } if (wavelet.medianlev) { - toEdit.wavelet.medianlev = mods.wavelet.medianlev; + toEdit.wavelet.medianlev = mods.wavelet.medianlev; } if (wavelet.linkedg) { - toEdit.wavelet.linkedg = mods.wavelet.linkedg; + toEdit.wavelet.linkedg = mods.wavelet.linkedg; } if (wavelet.cbenab) { - toEdit.wavelet.cbenab = mods.wavelet.cbenab; + toEdit.wavelet.cbenab = mods.wavelet.cbenab; } if (wavelet.greenhigh) { - toEdit.wavelet.greenhigh = mods.wavelet.greenhigh; + toEdit.wavelet.greenhigh = mods.wavelet.greenhigh; } if (wavelet.bluehigh) { - toEdit.wavelet.bluehigh = mods.wavelet.bluehigh; + toEdit.wavelet.bluehigh = mods.wavelet.bluehigh; } if (wavelet.greenmed) { - toEdit.wavelet.greenmed = mods.wavelet.greenmed; + toEdit.wavelet.greenmed = mods.wavelet.greenmed; } if (wavelet.bluemed) { - toEdit.wavelet.bluemed = mods.wavelet.bluemed; + toEdit.wavelet.bluemed = mods.wavelet.bluemed; } if (wavelet.greenlow) { - toEdit.wavelet.greenlow = mods.wavelet.greenlow; + toEdit.wavelet.greenlow = mods.wavelet.greenlow; } if (wavelet.bluelow) { - toEdit.wavelet.bluelow = mods.wavelet.bluelow; + toEdit.wavelet.bluelow = mods.wavelet.bluelow; } if (wavelet.lipst) { - toEdit.wavelet.lipst = mods.wavelet.lipst; + toEdit.wavelet.lipst = mods.wavelet.lipst; } if (wavelet.Medgreinf) { - toEdit.wavelet.Medgreinf = mods.wavelet.Medgreinf; + toEdit.wavelet.Medgreinf = mods.wavelet.Medgreinf; } if (wavelet.avoid) { - toEdit.wavelet.avoid = mods.wavelet.avoid; + toEdit.wavelet.avoid = mods.wavelet.avoid; } if (wavelet.tmr) { - toEdit.wavelet.tmr = mods.wavelet.tmr; + toEdit.wavelet.tmr = mods.wavelet.tmr; } if (wavelet.Lmethod) { - toEdit.wavelet.Lmethod = mods.wavelet.Lmethod; + toEdit.wavelet.Lmethod = mods.wavelet.Lmethod; } if (wavelet.CLmethod) { - toEdit.wavelet.CLmethod = mods.wavelet.CLmethod; + toEdit.wavelet.CLmethod = mods.wavelet.CLmethod; } if (wavelet.Backmethod) { - toEdit.wavelet.Backmethod = mods.wavelet.Backmethod; + toEdit.wavelet.Backmethod = mods.wavelet.Backmethod; } if (wavelet.Tilesmethod) { - toEdit.wavelet.Tilesmethod = mods.wavelet.Tilesmethod; + toEdit.wavelet.Tilesmethod = mods.wavelet.Tilesmethod; } if (wavelet.daubcoeffmethod) { - toEdit.wavelet.daubcoeffmethod = mods.wavelet.daubcoeffmethod; + toEdit.wavelet.daubcoeffmethod = mods.wavelet.daubcoeffmethod; } if (wavelet.CHmethod) { - toEdit.wavelet.CHmethod = mods.wavelet.CHmethod; + toEdit.wavelet.CHmethod = mods.wavelet.CHmethod; } if (wavelet.CHSLmethod) { - toEdit.wavelet.CHSLmethod = mods.wavelet.CHSLmethod; + toEdit.wavelet.CHSLmethod = mods.wavelet.CHSLmethod; } if (wavelet.EDmethod) { - toEdit.wavelet.EDmethod = mods.wavelet.EDmethod; + toEdit.wavelet.EDmethod = mods.wavelet.EDmethod; } if (wavelet.NPmethod) { - toEdit.wavelet.NPmethod = mods.wavelet.NPmethod; + toEdit.wavelet.NPmethod = mods.wavelet.NPmethod; } if (wavelet.BAmethod) { - toEdit.wavelet.BAmethod = mods.wavelet.BAmethod; + toEdit.wavelet.BAmethod = mods.wavelet.BAmethod; } if (wavelet.TMmethod) { - toEdit.wavelet.TMmethod = mods.wavelet.TMmethod; + toEdit.wavelet.TMmethod = mods.wavelet.TMmethod; } if (wavelet.HSmethod) { - toEdit.wavelet.HSmethod = mods.wavelet.HSmethod; + toEdit.wavelet.HSmethod = mods.wavelet.HSmethod; } if (wavelet.Dirmethod) { - toEdit.wavelet.Dirmethod = mods.wavelet.Dirmethod; + toEdit.wavelet.Dirmethod = mods.wavelet.Dirmethod; } if (wavelet.edgthresh) { - toEdit.wavelet.edgthresh = mods.wavelet.edgthresh; + toEdit.wavelet.edgthresh = mods.wavelet.edgthresh; } if (wavelet.sky) { @@ -2887,39 +2948,39 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (wavelet.sup) { - toEdit.wavelet.sup = mods.wavelet.sup; + toEdit.wavelet.sup = mods.wavelet.sup; } if (wavelet.hllev) { - toEdit.wavelet.hllev = mods.wavelet.hllev; + toEdit.wavelet.hllev = mods.wavelet.hllev; } if (wavelet.bllev) { - toEdit.wavelet.bllev = mods.wavelet.bllev; + toEdit.wavelet.bllev = mods.wavelet.bllev; } if (wavelet.edgcont) { - toEdit.wavelet.edgcont = mods.wavelet.edgcont; + toEdit.wavelet.edgcont = mods.wavelet.edgcont; } if (wavelet.level0noise) { - toEdit.wavelet.level0noise = mods.wavelet.level0noise; + toEdit.wavelet.level0noise = mods.wavelet.level0noise; } if (wavelet.level1noise) { - toEdit.wavelet.level1noise = mods.wavelet.level1noise; + toEdit.wavelet.level1noise = mods.wavelet.level1noise; } if (wavelet.level2noise) { - toEdit.wavelet.level2noise = mods.wavelet.level2noise; + toEdit.wavelet.level2noise = mods.wavelet.level2noise; } if (wavelet.level3noise) { - toEdit.wavelet.level3noise = mods.wavelet.level3noise; + toEdit.wavelet.level3noise = mods.wavelet.level3noise; } if (wavelet.pastlev) { - toEdit.wavelet.pastlev = mods.wavelet.pastlev; + toEdit.wavelet.pastlev = mods.wavelet.pastlev; } if (wavelet.satlev) { @@ -2927,7 +2988,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (wavelet.ccwcurve) { - toEdit.wavelet.ccwcurve = mods.wavelet.ccwcurve; + toEdit.wavelet.ccwcurve = mods.wavelet.ccwcurve; } if (wavelet.opacityCurveRG) { @@ -2939,7 +3000,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (wavelet.opacityCurveW) { - toEdit.wavelet.opacityCurveW = mods.wavelet.opacityCurveW; + toEdit.wavelet.opacityCurveW = mods.wavelet.opacityCurveW; } if (wavelet.opacityCurveWL) { @@ -2947,44 +3008,44 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (wavelet.hhcurve) { - toEdit.wavelet.hhcurve = mods.wavelet.hhcurve; + toEdit.wavelet.hhcurve = mods.wavelet.hhcurve; } if (wavelet.Chcurve) { - toEdit.wavelet.Chcurve = mods.wavelet.Chcurve; + toEdit.wavelet.Chcurve = mods.wavelet.Chcurve; } if (wavelet.wavclCurve) { toEdit.wavelet.wavclCurve = mods.wavelet.wavclCurve; } - //if (wavelet.enacont) toEdit.wavelet.enacont = mods.wavelet.enacont; + //if (wavelet.enacont) toEdit.wavelet.enacont = mods.wavelet.enacont; if (wavelet.expcontrast) { - toEdit.wavelet.expcontrast = mods.wavelet.expcontrast; + toEdit.wavelet.expcontrast = mods.wavelet.expcontrast; } if (wavelet.expchroma) { - toEdit.wavelet.expchroma = mods.wavelet.expchroma; + toEdit.wavelet.expchroma = mods.wavelet.expchroma; } if (wavelet.expedge) { - toEdit.wavelet.expedge = mods.wavelet.expedge; + toEdit.wavelet.expedge = mods.wavelet.expedge; } if (wavelet.expresid) { - toEdit.wavelet.expresid = mods.wavelet.expresid; + toEdit.wavelet.expresid = mods.wavelet.expresid; } if (wavelet.expfinal) { - toEdit.wavelet.expfinal = mods.wavelet.expfinal; + toEdit.wavelet.expfinal = mods.wavelet.expfinal; } if (wavelet.exptoning) { - toEdit.wavelet.exptoning = mods.wavelet.exptoning; + toEdit.wavelet.exptoning = mods.wavelet.exptoning; } if (wavelet.expnoise) { - toEdit.wavelet.expnoise = mods.wavelet.expnoise; + toEdit.wavelet.expnoise = mods.wavelet.expnoise; } for (int i = 0; i < 9; i++) { @@ -3004,19 +3065,19 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (wavelet.hueskin) { - toEdit.wavelet.hueskin = mods.wavelet.hueskin; + toEdit.wavelet.hueskin = mods.wavelet.hueskin; } if (wavelet.hueskin2) { - toEdit.wavelet.hueskin2 = mods.wavelet.hueskin2; + toEdit.wavelet.hueskin2 = mods.wavelet.hueskin2; } if (wavelet.edgesensi) { - toEdit.wavelet.edgesensi = mods.wavelet.edgesensi; + toEdit.wavelet.edgesensi = mods.wavelet.edgesensi; } if (wavelet.edgeampli) { - toEdit.wavelet.edgeampli = mods.wavelet.edgeampli; + toEdit.wavelet.edgeampli = mods.wavelet.edgeampli; } if (wavelet.resconH) { @@ -3089,20 +3150,20 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng if (dirpyrequalizer.enabled) { - toEdit.dirpyrequalizer.enabled = mods.dirpyrequalizer.enabled; + toEdit.dirpyrequalizer.enabled = mods.dirpyrequalizer.enabled; } if (dirpyrequalizer.gamutlab) { - toEdit.dirpyrequalizer.gamutlab = mods.dirpyrequalizer.gamutlab; + toEdit.dirpyrequalizer.gamutlab = mods.dirpyrequalizer.gamutlab; } if (dirpyrequalizer.cbdlMethod) { - toEdit.dirpyrequalizer.cbdlMethod = mods.dirpyrequalizer.cbdlMethod; + toEdit.dirpyrequalizer.cbdlMethod = mods.dirpyrequalizer.cbdlMethod; } for (int i = 0; i < 6; i++) { if (dirpyrequalizer.mult[i]) { - toEdit.dirpyrequalizer.mult[i] = dontforceSet && options.baBehav[ADDSET_DIRPYREQ] ? toEdit.dirpyrequalizer.mult[i] + mods.dirpyrequalizer.mult[i] : mods.dirpyrequalizer.mult[i]; + toEdit.dirpyrequalizer.mult[i] = dontforceSet && options.baBehav[ADDSET_DIRPYREQ] ? toEdit.dirpyrequalizer.mult[i] + mods.dirpyrequalizer.mult[i] : mods.dirpyrequalizer.mult[i]; } } @@ -3115,77 +3176,99 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (dirpyrequalizer.hueskin) { - toEdit.dirpyrequalizer.hueskin = mods.dirpyrequalizer.hueskin; + toEdit.dirpyrequalizer.hueskin = mods.dirpyrequalizer.hueskin; } -// if (dirpyrequalizer.algo) toEdit.dirpyrequalizer.algo = mods.dirpyrequalizer.algo; +// if (dirpyrequalizer.algo) toEdit.dirpyrequalizer.algo = mods.dirpyrequalizer.algo; if (hsvequalizer.enabled) { toEdit.hsvequalizer.enabled = mods.hsvequalizer.enabled; } if (hsvequalizer.hcurve) { - toEdit.hsvequalizer.hcurve = mods.hsvequalizer.hcurve; + toEdit.hsvequalizer.hcurve = mods.hsvequalizer.hcurve; } if (hsvequalizer.scurve) { - toEdit.hsvequalizer.scurve = mods.hsvequalizer.scurve; + toEdit.hsvequalizer.scurve = mods.hsvequalizer.scurve; } if (hsvequalizer.vcurve) { - toEdit.hsvequalizer.vcurve = mods.hsvequalizer.vcurve; + toEdit.hsvequalizer.vcurve = mods.hsvequalizer.vcurve; } if (filmSimulation.enabled) { - toEdit.filmSimulation.enabled = mods.filmSimulation.enabled; + toEdit.filmSimulation.enabled = mods.filmSimulation.enabled; } if (filmSimulation.clutFilename) { - toEdit.filmSimulation.clutFilename = mods.filmSimulation.clutFilename; + toEdit.filmSimulation.clutFilename = mods.filmSimulation.clutFilename; } if (filmSimulation.strength) { - toEdit.filmSimulation.strength = dontforceSet && options.baBehav[ADDSET_FILMSIMULATION_STRENGTH] ? toEdit.filmSimulation.strength + mods.filmSimulation.strength : mods.filmSimulation.strength; + toEdit.filmSimulation.strength = dontforceSet && options.baBehav[ADDSET_FILMSIMULATION_STRENGTH] ? toEdit.filmSimulation.strength + mods.filmSimulation.strength : mods.filmSimulation.strength; } if (softlight.enabled) { - toEdit.softlight.enabled = mods.softlight.enabled; + toEdit.softlight.enabled = mods.softlight.enabled; } if (softlight.strength) { - toEdit.softlight.strength = dontforceSet && options.baBehav[ADDSET_SOFTLIGHT_STRENGTH] ? toEdit.softlight.strength + mods.softlight.strength : mods.softlight.strength; + toEdit.softlight.strength = dontforceSet && options.baBehav[ADDSET_SOFTLIGHT_STRENGTH] ? toEdit.softlight.strength + mods.softlight.strength : mods.softlight.strength; } if (dehaze.enabled) { - toEdit.dehaze.enabled = mods.dehaze.enabled; + toEdit.dehaze.enabled = mods.dehaze.enabled; } if (dehaze.strength) { - toEdit.dehaze.strength = dontforceSet && options.baBehav[ADDSET_DEHAZE_STRENGTH] ? toEdit.dehaze.strength + mods.dehaze.strength : mods.dehaze.strength; + toEdit.dehaze.strength = dontforceSet && options.baBehav[ADDSET_DEHAZE_STRENGTH] ? toEdit.dehaze.strength + mods.dehaze.strength : mods.dehaze.strength; } if (dehaze.depth) { - toEdit.dehaze.depth = mods.dehaze.depth; + toEdit.dehaze.depth = mods.dehaze.depth; } if (dehaze.showDepthMap) { - toEdit.dehaze.showDepthMap = mods.dehaze.showDepthMap; + toEdit.dehaze.showDepthMap = mods.dehaze.showDepthMap; + } + + if (dehaze.luminance) { + toEdit.dehaze.luminance = mods.dehaze.luminance; } if (metadata.mode) { - toEdit.metadata.mode = mods.metadata.mode; + toEdit.metadata.mode = mods.metadata.mode; + } + + if (filmNegative.enabled) { + toEdit.filmNegative.enabled = mods.filmNegative.enabled; + } + + if (filmNegative.redRatio) { + toEdit.filmNegative.redRatio = mods.filmNegative.redRatio; + } + + if (filmNegative.greenExp) { + toEdit.filmNegative.greenExp = mods.filmNegative.greenExp; + } + + if (filmNegative.blueRatio) { + toEdit.filmNegative.blueRatio = mods.filmNegative.blueRatio; } // Exif changes are added to the existing ones - if (exif) + if (exif) { for (procparams::ExifPairs::const_iterator i = mods.exif.begin(); i != mods.exif.end(); ++i) { toEdit.exif[i->first] = i->second; } + } // IPTC changes are added to the existing ones - if (iptc) + if (iptc) { for (procparams::IPTCPairs::const_iterator i = mods.iptc.begin(); i != mods.iptc.end(); ++i) { toEdit.iptc[i->first] = i->second; } + } } bool RAWParamsEdited::BayerSensor::isUnchanged() const @@ -3216,3 +3299,13 @@ bool RetinexParamsEdited::isUnchanged() const { return enabled && retinexcolorspace && gammaretinex && gam && slope; } + +bool FilmNegativeParamsEdited::isUnchanged() const +{ + return enabled && redRatio && greenExp && blueRatio; +} + +bool CaptureSharpeningParamsEdited::isUnchanged() const +{ + return enabled && contrast && autoContrast && autoRadius && gamma && deconvradius && deconvradiusOffset && deconviter; +} \ No newline at end of file diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 95701e01a..e435e2291 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once @@ -179,7 +179,9 @@ struct SharpenMicroParamsEdited { struct SharpeningParamsEdited { bool enabled; bool contrast; + bool autoContrast; bool blurradius; + bool gamma; bool radius; bool amount; bool threshold; @@ -196,6 +198,18 @@ struct SharpeningParamsEdited { bool deconvdamping; }; +struct CaptureSharpeningParamsEdited { + bool enabled; + bool contrast; + bool autoContrast; + bool autoRadius; + bool gamma; + bool deconvradius; + bool deconvradiusOffset; + bool deconviter; + bool isUnchanged() const; +}; + struct VibranceParamsEdited { bool enabled; bool pastels; @@ -583,6 +597,7 @@ struct DehazeParamsEdited { bool strength; bool showDepthMap; bool depth; + bool luminance; }; struct RAWParamsEdited { @@ -666,6 +681,15 @@ struct MetaDataParamsEdited { bool mode; }; +struct FilmNegativeParamsEdited { + bool enabled; + bool redRatio; + bool greenExp; + bool blueRatio; + + bool isUnchanged() const; +}; + struct ParamsEdited { GeneralParamsEdited general; ToneCurveParamsEdited toneCurve; @@ -675,6 +699,7 @@ struct ParamsEdited { ColorToningEdited colorToning; RetinexParamsEdited retinex; SharpeningParamsEdited sharpening; + CaptureSharpeningParamsEdited pdsharpening; SharpeningParamsEdited prsharpening; SharpenEdgeParamsEdited sharpenEdge; SharpenMicroParamsEdited sharpenMicro; @@ -710,6 +735,7 @@ struct ParamsEdited { SoftLightParamsEdited softlight; DehazeParamsEdited dehaze; MetaDataParamsEdited metadata; + FilmNegativeParamsEdited filmNegative; bool exif; bool iptc; diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index 734f7c29b..a7d2bd0d1 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "partialpastedlg.h" #include "multilangmgr.h" @@ -134,6 +134,8 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren raw_ca_autocorrect = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAWCACORR_AUTO"))); raw_caredblue = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAWCACORR_CAREDBLUE"))); raw_ca_avoid_colourshift = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAWCACORR_AVOIDCOLORSHIFT"))); + //--- + filmNegative = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_FILMNEGATIVE")) ); Gtk::VBox* vboxes[8]; Gtk::HSeparator* hseps[8]; @@ -249,6 +251,8 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren vboxes[7]->pack_start (*raw_ca_autocorrect, Gtk::PACK_SHRINK, 2); vboxes[7]->pack_start (*raw_caredblue, Gtk::PACK_SHRINK, 2); vboxes[7]->pack_start (*raw_ca_avoid_colourshift, Gtk::PACK_SHRINK, 2); + vboxes[7]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); + vboxes[7]->pack_start (*filmNegative, Gtk::PACK_SHRINK, 2); Gtk::VBox* vbCol1 = Gtk::manage (new Gtk::VBox ()); Gtk::VBox* vbCol2 = Gtk::manage (new Gtk::VBox ()); @@ -396,6 +400,8 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren raw_ca_autocorrectConn = raw_ca_autocorrect->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); raw_caredblueConn = raw_caredblue->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); raw_ca_avoid_colourshiftconn = raw_ca_avoid_colourshift->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); + //--- + filmNegativeConn = filmNegative->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); add_button (M("GENERAL_OK"), Gtk::RESPONSE_OK); add_button (M("GENERAL_CANCEL"), Gtk::RESPONSE_CANCEL); @@ -467,6 +473,7 @@ void PartialPasteDlg::rawToggled () ConnectionBlocker raw_ca_autocorrectBlocker(raw_ca_autocorrectConn); ConnectionBlocker raw_caredblueBlocker(raw_caredblueConn); ConnectionBlocker raw_ca_avoid_colourshiftBlocker(raw_ca_avoid_colourshiftconn); + ConnectionBlocker filmNegativeBlocker(filmNegativeConn); raw->set_inconsistent (false); @@ -495,6 +502,7 @@ void PartialPasteDlg::rawToggled () raw_ca_autocorrect->set_active (raw->get_active ()); raw_caredblue->set_active (raw->get_active ()); raw_ca_avoid_colourshift->set_active (raw->get_active ()); + filmNegative->set_active (raw->get_active()); } void PartialPasteDlg::basicToggled () @@ -966,6 +974,13 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param filterPE.raw.ff_AutoClipControl = falsePE.raw.ff_AutoClipControl; } + if (!filmNegative->get_active ()) { + filterPE.filmNegative.enabled = falsePE.filmNegative.enabled; + filterPE.filmNegative.redRatio = falsePE.filmNegative.redRatio; + filterPE.filmNegative.greenExp = falsePE.filmNegative.greenExp; + filterPE.filmNegative.blueRatio = falsePE.filmNegative.blueRatio; + } + if (dstPE) { *dstPE = filterPE; } @@ -973,4 +988,3 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param // Apply the filter! filterPE.combine(*dstPP, *srcPP, true); } - diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h index 0325fa063..eebb08705 100644 --- a/rtgui/partialpastedlg.h +++ b/rtgui/partialpastedlg.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PARTIALPASTEDLG_ #define _PARTIALPASTEDLG_ @@ -130,6 +130,8 @@ public: Gtk::CheckButton* ff_BlurType; Gtk::CheckButton* ff_ClipControl; + Gtk::CheckButton* filmNegative; + sigc::connection everythingConn, basicConn, detailConn, colorConn, lensConn, compositionConn, metaConn, rawConn, advancedConn; sigc::connection wbConn, exposureConn, localcontrastConn, shConn, pcvignetteConn, gradientConn, labcurveConn, colorappearanceConn; @@ -140,6 +142,7 @@ public: sigc::connection metadataConn, exifchConn, iptcConn, icmConn; sigc::connection df_fileConn, df_AutoSelectConn, ff_fileConn, ff_AutoSelectConn, ff_BlurRadiusConn, ff_BlurTypeConn, ff_ClipControlConn; sigc::connection raw_caredblueConn, raw_ca_autocorrectConn, raw_ca_avoid_colourshiftconn, raw_hotpix_filtConn, raw_deadpix_filtConn, raw_pdaf_lines_filterConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_methodConn, raw_borderConn, raw_imagenumConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_pixelshiftConn, raw_dcb_enhanceConn, raw_exposConn, raw_blackConn; + sigc::connection filmNegativeConn; public: PartialPasteDlg (const Glib::ustring &title, Gtk::Window* parent); diff --git a/rtgui/pathutils.cc b/rtgui/pathutils.cc index 21c452d4c..71ff8b0b2 100644 --- a/rtgui/pathutils.cc +++ b/rtgui/pathutils.cc @@ -13,7 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "pathutils.h" diff --git a/rtgui/pathutils.h b/rtgui/pathutils.h index ce58103b9..ed7d21984 100644 --- a/rtgui/pathutils.h +++ b/rtgui/pathutils.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __PATH_UTILS_ #define __PATH_UTILS_ diff --git a/rtgui/pcvignette.cc b/rtgui/pcvignette.cc index 303ae5cfb..9c141d618 100644 --- a/rtgui/pcvignette.cc +++ b/rtgui/pcvignette.cc @@ -93,10 +93,6 @@ void PCVignette::adjusterChanged(Adjuster* a, double newval) } } -void PCVignette::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void PCVignette::enabledChanged () { diff --git a/rtgui/pcvignette.h b/rtgui/pcvignette.h index 98d42a477..ce41ab75f 100644 --- a/rtgui/pcvignette.h +++ b/rtgui/pcvignette.h @@ -26,7 +26,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void enabledChanged () override; void setAdjusterBehavior (bool strengthadd, bool featheradd, bool roundnessadd); void trimValues (rtengine::procparams::ProcParams* pp) override; diff --git a/rtgui/pdsharpening.cc b/rtgui/pdsharpening.cc new file mode 100644 index 000000000..5b38f0256 --- /dev/null +++ b/rtgui/pdsharpening.cc @@ -0,0 +1,312 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2019 Ingo Weyrich (heckflosse67@gmx.de) + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . +*/ + +#include +#include +#include "eventmapper.h" +#include "pdsharpening.h" +#include "options.h" +#include "../rtengine/procparams.h" + +using namespace rtengine; +using namespace rtengine::procparams; + +PdSharpening::PdSharpening() : FoldableToolPanel(this, "capturesharpening", M("TP_PDSHARPENING_LABEL"), false, true) +{ + + auto m = ProcEventMapper::getInstance(); + EvPdShrContrast = m->newEvent(CAPTURESHARPEN, "HISTORY_MSG_PDSHARPEN_CONTRAST"); + EvPdSharpenGamma = m->newEvent(CAPTURESHARPEN, "HISTORY_MSG_PDSHARPEN_GAMMA"); + EvPdShrDRadius = m->newEvent(CAPTURESHARPEN, "HISTORY_MSG_PDSHARPEN_RADIUS"); + EvPdShrDRadiusOffset = m->newEvent(CAPTURESHARPEN, "HISTORY_MSG_PDSHARPEN_RADIUS_BOOST"); + EvPdShrDIterations = m->newEvent(CAPTURESHARPEN, "HISTORY_MSG_PDSHARPEN_ITERATIONS"); + EvPdShrAutoContrast = m->newEvent(CAPTURESHARPEN, "HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST"); + EvPdShrAutoRadius = m->newEvent(CAPTURESHARPEN, "HISTORY_MSG_PDSHARPEN_AUTO_RADIUS"); + + Gtk::HBox* hb = Gtk::manage(new Gtk::HBox()); + hb->show(); + contrast = Gtk::manage(new Adjuster(M("TP_SHARPENING_CONTRAST"), 0, 200, 1, 10)); + contrast->setAdjusterListener(this); + contrast->addAutoButton(); + contrast->setAutoValue(true); + + pack_start(*contrast); + contrast->show(); + + pack_start(*hb); + + Gtk::VBox* rld = Gtk::manage(new Gtk::VBox()); + gamma = Gtk::manage(new Adjuster(M("TP_SHARPENING_GAMMA"), 0.5, 6.0, 0.05, 1.00)); + dradius = Gtk::manage(new Adjuster(M("TP_SHARPENING_RADIUS"), 0.4, 1.15, 0.01, 0.75)); + dradius->addAutoButton(); + dradius->setAutoValue(true); + dradiusOffset = Gtk::manage(new Adjuster(M("TP_SHARPENING_RADIUS_BOOST"), 0.0, 0.5, 0.01, 0.0)); + diter = Gtk::manage(new Adjuster(M("TP_SHARPENING_RLD_ITERATIONS"), 1, 100, 1, 20)); + rld->pack_start(*gamma); + rld->pack_start(*dradius); + rld->pack_start(*dradiusOffset); + rld->pack_start(*diter); + gamma->show(); + dradius->show(); + dradiusOffset->show(); + diter->show(); + rld->show(); + pack_start(*rld); + + dradius->setAdjusterListener(this); + dradiusOffset->setAdjusterListener(this); + gamma->setAdjusterListener(this); + diter->setAdjusterListener(this); + + contrast->delay = std::max(contrast->delay, options.adjusterMaxDelay); + dradius->delay = std::max(dradius->delay, options.adjusterMaxDelay); + dradiusOffset->delay = std::max(dradiusOffset->delay, options.adjusterMaxDelay); + gamma->delay = std::max(gamma->delay, options.adjusterMaxDelay); + diter->delay = std::max(diter->delay, options.adjusterMaxDelay); +} + +PdSharpening::~PdSharpening() +{ + idle_register.destroy(); +} + + +void PdSharpening::read(const ProcParams* pp, const ParamsEdited* pedited) +{ + + disableListener(); + + if (pedited) { + contrast->setEditedState(pedited->pdsharpening.contrast ? Edited : UnEdited); + contrast->setAutoInconsistent(multiImage && !pedited->pdsharpening.autoContrast); + dradius->setAutoInconsistent(multiImage && !pedited->pdsharpening.autoRadius); + gamma->setEditedState(pedited->pdsharpening.gamma ? Edited : UnEdited); + dradius->setEditedState(pedited->pdsharpening.deconvradius ? Edited : UnEdited); + dradiusOffset->setEditedState(pedited->pdsharpening.deconvradiusOffset ? Edited : UnEdited); + diter->setEditedState(pedited->pdsharpening.deconviter ? Edited : UnEdited); + + set_inconsistent(multiImage && !pedited->pdsharpening.enabled); + } + + setEnabled(pp->pdsharpening.enabled); + + contrast->setValue(pp->pdsharpening.contrast); + contrast->setAutoValue(pp->pdsharpening.autoContrast); + gamma->setValue(pp->pdsharpening.gamma); + dradius->setValue(pp->pdsharpening.deconvradius); + dradius->setAutoValue(pp->pdsharpening.autoRadius); + dradiusOffset->setValue(pp->pdsharpening.deconvradiusOffset); + diter->setValue(pp->pdsharpening.deconviter); + lastAutoContrast = pp->pdsharpening.autoContrast; + lastAutoRadius = pp->pdsharpening.autoRadius; + + enableListener(); +} + +void PdSharpening::write(ProcParams* pp, ParamsEdited* pedited) +{ + + pp->pdsharpening.contrast = contrast->getValue(); + pp->pdsharpening.autoContrast = contrast->getAutoValue(); + pp->pdsharpening.enabled = getEnabled(); + pp->pdsharpening.gamma = gamma->getValue(); + pp->pdsharpening.deconvradius = dradius->getValue(); + pp->pdsharpening.autoRadius = dradius->getAutoValue(); + pp->pdsharpening.deconvradiusOffset = dradiusOffset->getValue(); + pp->pdsharpening.deconviter =(int)diter->getValue(); + + if (pedited) { + pedited->pdsharpening.contrast = contrast->getEditedState(); + pedited->pdsharpening.autoContrast = !contrast->getAutoInconsistent(); + pedited->pdsharpening.gamma = gamma->getEditedState(); + pedited->pdsharpening.deconvradius = dradius->getEditedState(); + pedited->pdsharpening.autoRadius = !dradius->getAutoInconsistent(); + pedited->pdsharpening.deconvradiusOffset = dradiusOffset->getEditedState(); + pedited->pdsharpening.deconviter = diter->getEditedState(); + pedited->pdsharpening.enabled = !get_inconsistent(); + } +} + +void PdSharpening::setDefaults(const ProcParams* defParams, const ParamsEdited* pedited) +{ + + contrast->setDefault(defParams->pdsharpening.contrast); + gamma->setDefault(defParams->pdsharpening.gamma); + dradius->setDefault(defParams->pdsharpening.deconvradius); + dradiusOffset->setDefault(defParams->pdsharpening.deconvradiusOffset); + diter->setDefault(defParams->pdsharpening.deconviter); + + if (pedited) { + contrast->setDefaultEditedState(pedited->pdsharpening.contrast ? Edited : UnEdited); + gamma->setDefaultEditedState(pedited->pdsharpening.gamma ? Edited : UnEdited); + dradius->setDefaultEditedState(pedited->pdsharpening.deconvradius ? Edited : UnEdited); + dradiusOffset->setDefaultEditedState(pedited->pdsharpening.deconvradiusOffset ? Edited : UnEdited); + diter->setDefaultEditedState(pedited->pdsharpening.deconviter ? Edited : UnEdited); + } else { + contrast->setDefaultEditedState(Irrelevant); + gamma->setDefaultEditedState(Irrelevant); + dradius->setDefaultEditedState(Irrelevant); + dradiusOffset->setDefaultEditedState(Irrelevant); + diter->setDefaultEditedState(Irrelevant); + } +} + +void PdSharpening::adjusterChanged(Adjuster* a, double newval) +{ + if (listener && (multiImage || getEnabled())) { + + Glib::ustring costr; + + if (a == gamma || a == dradius || a == dradiusOffset) { + costr = Glib::ustring::format(std::setw(3), std::fixed, std::setprecision(2), a->getValue()); + } else { + costr = Glib::ustring::format((int)a->getValue()); + } + + if (a == contrast) { + listener->panelChanged(EvPdShrContrast, costr); + } else if (a == gamma) { + listener->panelChanged(EvPdSharpenGamma, costr); + } else if (a == dradius) { + listener->panelChanged(EvPdShrDRadius, costr); + } else if (a == dradiusOffset) { + listener->panelChanged(EvPdShrDRadiusOffset, costr); + } else if (a == diter) { + listener->panelChanged(EvPdShrDIterations, costr); + } + } +} + +void PdSharpening::enabledChanged() +{ + if (listener) { + if (get_inconsistent()) { + listener->panelChanged(EvPdShrEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged(EvPdShrEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(EvPdShrEnabled, M("GENERAL_DISABLED")); + } + } +} + +void PdSharpening::setBatchMode(bool batchMode) +{ + + ToolPanel::setBatchMode(batchMode); + + contrast->showEditedCB(); + gamma->showEditedCB(); + dradius->showEditedCB(); + dradiusOffset->showEditedCB(); + diter->showEditedCB(); +} + +void PdSharpening::setAdjusterBehavior(bool contrastadd, bool gammaadd, bool radiusadd, bool iteradd) +{ + + contrast->setAddMode(contrastadd); + gamma->setAddMode(gammaadd); + dradius->setAddMode(radiusadd); + dradiusOffset->setAddMode(radiusadd); + diter->setAddMode(iteradd); +} + +void PdSharpening::trimValues(rtengine::procparams::ProcParams* pp) +{ + + contrast->trimValue(pp->pdsharpening.contrast); + gamma->trimValue(pp->pdsharpening.gamma); + dradius->trimValue(pp->pdsharpening.deconvradius); + dradiusOffset->trimValue(pp->pdsharpening.deconvradiusOffset); + diter->trimValue(pp->pdsharpening.deconviter); +} + +void PdSharpening::autoContrastChanged(double autoContrast) +{ + idle_register.add( + [this, autoContrast]() -> bool + { + disableListener(); + contrast->setValue(autoContrast); + enableListener(); + return false; + } + ); +} + +void PdSharpening::autoRadiusChanged(double autoRadius) +{ + idle_register.add( + [this, autoRadius]() -> bool + { + disableListener(); + dradius->setValue(autoRadius); + enableListener(); + return false; + } + ); +} + +void PdSharpening::adjusterAutoToggled(Adjuster* a, bool newval) +{ + if (a == contrast) { + if (multiImage) { + if (contrast->getAutoInconsistent()) { + contrast->setAutoInconsistent(false); + contrast->setAutoValue(false); + } else if (lastAutoContrast) { + contrast->setAutoInconsistent(true); + } + + lastAutoContrast = contrast->getAutoValue(); + } + + if (listener) { + if (contrast->getAutoInconsistent()) { + listener->panelChanged(EvPdShrAutoContrast, M("GENERAL_UNCHANGED")); + } else if (contrast->getAutoValue()) { + listener->panelChanged(EvPdShrAutoContrast, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(EvPdShrAutoContrast, M("GENERAL_DISABLED")); + } + } + } else { // must be dradius + if (multiImage) { + if (dradius->getAutoInconsistent()) { + dradius->setAutoInconsistent(false); + dradius->setAutoValue(false); + } else if (lastAutoRadius) { + dradius->setAutoInconsistent(true); + } + + lastAutoRadius = dradius->getAutoValue(); + } + + if (listener) { + if (dradius->getAutoInconsistent()) { + listener->panelChanged(EvPdShrAutoRadius, M("GENERAL_UNCHANGED")); + } else if (dradius->getAutoValue()) { + listener->panelChanged(EvPdShrAutoRadius, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(EvPdShrAutoRadius, M("GENERAL_DISABLED")); + } + } + } +} diff --git a/rtgui/pdsharpening.h b/rtgui/pdsharpening.h new file mode 100644 index 000000000..f621fd0a5 --- /dev/null +++ b/rtgui/pdsharpening.h @@ -0,0 +1,64 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2019 Ingo Weyrich (heckflosse67@gmx.de) + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . +*/ +#pragma once + +#include "adjuster.h" +#include "toolpanel.h" + +class PdSharpening final : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoContrastListener, public rtengine::AutoRadiusListener +{ + +protected: + Adjuster* contrast; + Adjuster* gamma; + Adjuster* dradius; + Adjuster* dradiusOffset; + Adjuster* diter; + + bool lastAutoContrast; + bool lastAutoRadius; + rtengine::ProcEvent EvPdShrContrast; + rtengine::ProcEvent EvPdShrDRadius; + rtengine::ProcEvent EvPdShrDRadiusOffset; + rtengine::ProcEvent EvPdSharpenGamma; + rtengine::ProcEvent EvPdShrDIterations; + rtengine::ProcEvent EvPdShrAutoContrast; + rtengine::ProcEvent EvPdShrAutoRadius; + IdleRegister idle_register; + +public: + + PdSharpening (); + ~PdSharpening () override; + + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; + void setBatchMode (bool batchMode) override; + + void adjusterAutoToggled (Adjuster* a, bool newval) override; + void adjusterChanged (Adjuster* a, double newval) override; + void enabledChanged () override; + + void autoContrastChanged (double autoContrast) override; + void autoRadiusChanged (double autoRadius) override; + + void setAdjusterBehavior (bool contrastadd, bool gammaadd, bool radiusadd, bool iteradds); + void trimValues (rtengine::procparams::ProcParams* pp) override; +}; diff --git a/rtgui/perspective.cc b/rtgui/perspective.cc index db2f32248..b86da6a52 100644 --- a/rtgui/perspective.cc +++ b/rtgui/perspective.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "perspective.h" @@ -98,10 +98,6 @@ void PerspCorrection::adjusterChanged(Adjuster* a, double newval) } } -void PerspCorrection::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void PerspCorrection::setAdjusterBehavior (bool badd) { diff --git a/rtgui/perspective.h b/rtgui/perspective.h index 8038120fa..9b36ed24d 100644 --- a/rtgui/perspective.h +++ b/rtgui/perspective.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PERSPECTIVE_PANEL_H_ #define _PERSPECTIVE_PANEL_H_ @@ -40,7 +40,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void setAdjusterBehavior (bool badd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; diff --git a/rtgui/placesbrowser.cc b/rtgui/placesbrowser.cc index 0d20e9bad..f1450cea2 100644 --- a/rtgui/placesbrowser.cc +++ b/rtgui/placesbrowser.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "placesbrowser.h" @@ -230,15 +230,15 @@ void PlacesBrowser::refreshPlacesList () } for (size_t i = 0; i < options.favoriteDirs.size(); i++) { - Glib::RefPtr hfile = Gio::File::create_for_path (options.favoriteDirs[i]); + Glib::RefPtr fav = Gio::File::create_for_path (options.favoriteDirs[i]); - if (hfile && hfile->query_exists()) { + if (fav && fav->query_exists()) { try { - if (auto info = hfile->query_info ()) { + if (auto info = fav->query_info ()) { Gtk::TreeModel::Row newrow = *(placesModel->append()); newrow[placesColumns.label] = info->get_display_name (); newrow[placesColumns.icon] = info->get_icon (); - newrow[placesColumns.root] = hfile->get_parse_name (); + newrow[placesColumns.root] = fav->get_parse_name (); newrow[placesColumns.type] = 5; newrow[placesColumns.rowSeparator] = false; } @@ -309,7 +309,7 @@ void PlacesBrowser::dirSelected (const Glib::ustring& dirname, const Glib::ustri void PlacesBrowser::addPressed () { - if (lastSelectedDir == "") { + if (lastSelectedDir.empty()) { return; } diff --git a/rtgui/placesbrowser.h b/rtgui/placesbrowser.h index b3bed867c..6325bdb45 100644 --- a/rtgui/placesbrowser.h +++ b/rtgui/placesbrowser.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PLACESBROWSER_ #define _PLACESBROWSER_ diff --git a/rtgui/pointermotionlistener.h b/rtgui/pointermotionlistener.h index 88a4b2279..0a2931262 100644 --- a/rtgui/pointermotionlistener.h +++ b/rtgui/pointermotionlistener.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _POINTERMOTIONLISTENER_ #define _POINTERMOTIONLISTENER_ diff --git a/rtgui/popupbutton.cc b/rtgui/popupbutton.cc index 2aa43ddcb..7c15255c6 100644 --- a/rtgui/popupbutton.cc +++ b/rtgui/popupbutton.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * Class created by Jean-Christophe FRISCH, aka 'Hombre' */ diff --git a/rtgui/popupbutton.h b/rtgui/popupbutton.h index be08cd1ba..fb0b66e0d 100644 --- a/rtgui/popupbutton.h +++ b/rtgui/popupbutton.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * Class created by Jean-Christophe FRISCH, aka 'Hombre' */ diff --git a/rtgui/popupcommon.cc b/rtgui/popupcommon.cc index c5a5a03e3..8c4c9dda1 100644 --- a/rtgui/popupcommon.cc +++ b/rtgui/popupcommon.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * Class created by Jean-Christophe FRISCH, aka 'Hombre' */ diff --git a/rtgui/popupcommon.h b/rtgui/popupcommon.h index f939dbe96..44ad0886a 100644 --- a/rtgui/popupcommon.h +++ b/rtgui/popupcommon.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * Class created by Jean-Christophe FRISCH, aka 'Hombre' */ @@ -47,7 +47,7 @@ public: type_signal_item_selected signal_item_selected(); Gtk::Grid* buttonGroup; // this is the widget to be packed - PopUpCommon (Gtk::Button* button, const Glib::ustring& label = ""); + explicit PopUpCommon (Gtk::Button* button, const Glib::ustring& label = ""); virtual ~PopUpCommon (); bool addEntry (const Glib::ustring& fileName, const Glib::ustring& label); int getEntryCount () const; diff --git a/rtgui/popuptogglebutton.cc b/rtgui/popuptogglebutton.cc index 9676a2bea..47c3e4088 100644 --- a/rtgui/popuptogglebutton.cc +++ b/rtgui/popuptogglebutton.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * Class created by Jean-Christophe FRISCH, aka 'Hombre' */ diff --git a/rtgui/popuptogglebutton.h b/rtgui/popuptogglebutton.h index 58a7ff82a..b2949a0b8 100644 --- a/rtgui/popuptogglebutton.h +++ b/rtgui/popuptogglebutton.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * Class created by Jean-Christophe FRISCH, aka 'Hombre' */ diff --git a/rtgui/pparamschangelistener.h b/rtgui/pparamschangelistener.h index c8338745e..2c73ea3f6 100644 --- a/rtgui/pparamschangelistener.h +++ b/rtgui/pparamschangelistener.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PPARAMSCHANGELISTENER_ #define _PPARAMSCHANGELISTENER_ diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index b7d10c8de..b4447fd44 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include "preferences.h" @@ -56,6 +56,7 @@ Glib::RefPtr fontcss; Preferences::Preferences (RTWindow *rtwindow) : Gtk::Dialog (M ("MAIN_BUTTON_PREFERENCES"), *rtwindow, true) + , regex(Glib::Regex::create (THEMEREGEXSTR, Glib::RegexCompileFlags::REGEX_CASELESS)) , splash (nullptr) , rprofiles (nullptr) , iprofiles (nullptr) @@ -63,7 +64,6 @@ Preferences::Preferences (RTWindow *rtwindow) , newFont (false) , newCPFont (false) { - regex = Glib::Regex::create (THEMEREGEXSTR, Glib::RegexCompileFlags::REGEX_CASELESS); moptions.copyFrom (&options); diff --git a/rtgui/preferences.h b/rtgui/preferences.h index 4f92e9e22..6ca302fe8 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __PREFERENCES_H__ #define __PREFERENCES_H__ diff --git a/rtgui/preprocess.cc b/rtgui/preprocess.cc index 92cd06bc1..4a663ad07 100644 --- a/rtgui/preprocess.cc +++ b/rtgui/preprocess.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -101,10 +101,6 @@ void PreProcess::adjusterChanged(Adjuster* a, double newval) } } -void PreProcess::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void PreProcess::hotPixelChanged () { if (batchMode) { diff --git a/rtgui/preprocess.h b/rtgui/preprocess.h index 58cc2c2de..015fa3650 100644 --- a/rtgui/preprocess.h +++ b/rtgui/preprocess.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PREPROCESS_H_ #define _PREPROCESS_H_ @@ -48,7 +48,6 @@ public: void hotPixelChanged(); void deadPixelChanged(); void adjusterChanged(Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; //void adjusterChanged (Adjuster* a, double newval); diff --git a/rtgui/previewhandler.cc b/rtgui/previewhandler.cc index a1640b39c..1dad0676e 100644 --- a/rtgui/previewhandler.cc +++ b/rtgui/previewhandler.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "previewhandler.h" #include diff --git a/rtgui/previewhandler.h b/rtgui/previewhandler.h index fcd0a0c5f..7fe7b96f4 100644 --- a/rtgui/previewhandler.h +++ b/rtgui/previewhandler.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PREVIEWHANDLER_ #define _PREVIEWHANDLER_ @@ -28,6 +28,7 @@ #include "guiutils.h" #include "../rtengine/rtengine.h" +#include "../rtengine/noncopyable.h" class PreviewListener { @@ -44,7 +45,7 @@ struct PreviewHandlerIdleHelper { int pending; }; -class PreviewHandler : public rtengine::PreviewImageListener +class PreviewHandler : public rtengine::PreviewImageListener, public rtengine::NonCopyable { private: friend int setImageUI (void* data); diff --git a/rtgui/previewloader.cc b/rtgui/previewloader.cc index 34b42dcb7..67de50113 100644 --- a/rtgui/previewloader.cc +++ b/rtgui/previewloader.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtgui/previewloader.h b/rtgui/previewloader.h index 311d9d5ce..52dbee43c 100644 --- a/rtgui/previewloader.h +++ b/rtgui/previewloader.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PREVIEWLOADER_ #define _PREVIEWLOADER_ diff --git a/rtgui/previewmodepanel.cc b/rtgui/previewmodepanel.cc index 086f6ab17..37b3f6468 100644 --- a/rtgui/previewmodepanel.cc +++ b/rtgui/previewmodepanel.cc @@ -13,7 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "previewmodepanel.h" #include "options.h" diff --git a/rtgui/previewmodepanel.h b/rtgui/previewmodepanel.h index 4924b77af..b43e8484c 100644 --- a/rtgui/previewmodepanel.h +++ b/rtgui/previewmodepanel.h @@ -13,7 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PREVIEWMODEPANEL_ #define _PREVIEWMODEPANEL_ diff --git a/rtgui/previewwindow.cc b/rtgui/previewwindow.cc index 7688c0470..54d785313 100644 --- a/rtgui/previewwindow.cc +++ b/rtgui/previewwindow.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "previewwindow.h" #include "guiutils.h" diff --git a/rtgui/previewwindow.h b/rtgui/previewwindow.h index c89c89d4e..64aa84afd 100644 --- a/rtgui/previewwindow.h +++ b/rtgui/previewwindow.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PREVIEWWINDOW_ #define _PREVIEWWINDOW_ diff --git a/rtgui/procparamchangers.h b/rtgui/procparamchangers.h index aeebae4fb..8dd3769c6 100644 --- a/rtgui/procparamchangers.h +++ b/rtgui/procparamchangers.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #define UNKNOWN -1 #define FILEBROWSER 1 diff --git a/rtgui/profilechangelistener.h b/rtgui/profilechangelistener.h index e333933ea..fa7e1b877 100644 --- a/rtgui/profilechangelistener.h +++ b/rtgui/profilechangelistener.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PROFILECHANGELISTENER_ #define _PROFILECHANGELISTENER_ diff --git a/rtgui/profilepanel.cc b/rtgui/profilepanel.cc index af39695fa..b4b85dfd0 100644 --- a/rtgui/profilepanel.cc +++ b/rtgui/profilepanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "profilepanel.h" @@ -42,7 +42,7 @@ void ProfilePanel::cleanup () delete partialProfileDlg; } -ProfilePanel::ProfilePanel () : storedPProfile(nullptr), lastFilename(""), imagePath(""), lastSavedPSE(nullptr), customPSE(nullptr) +ProfilePanel::ProfilePanel () : storedPProfile(nullptr), lastSavedPSE(nullptr), customPSE(nullptr) { tpc = nullptr; diff --git a/rtgui/profilepanel.h b/rtgui/profilepanel.h index b0fb42ab7..c5717d523 100644 --- a/rtgui/profilepanel.h +++ b/rtgui/profilepanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PROFILEPANEL_ #define _PROFILEPANEL_ @@ -28,8 +28,9 @@ #include "guiutils.h" #include "profilestorecombobox.h" #include "rtimage.h" +#include "../rtengine/noncopyable.h" -class ProfilePanel : public Gtk::Grid, public PParamsChangeListener, public ProfileStoreListener +class ProfilePanel : public Gtk::Grid, public PParamsChangeListener, public ProfileStoreListener, public rtengine::NonCopyable { private: diff --git a/rtgui/profilestorecombobox.cc b/rtgui/profilestorecombobox.cc index 96bbc32fa..bb294189f 100644 --- a/rtgui/profilestorecombobox.cc +++ b/rtgui/profilestorecombobox.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "../rtengine/profilestore.h" #include "profilestorecombobox.h" @@ -37,23 +37,22 @@ ProfileStoreComboBox::ProfileStoreComboBox () setPreferredWidth (50, 120); } -Glib::ustring ProfileStoreComboBox::getCurrentLabel() +Glib::ustring ProfileStoreComboBox::getCurrentLabel() const { - Glib::ustring currLabel; - Gtk::TreeModel::iterator currRow = get_active(); + const Gtk::TreeModel::const_iterator currRow = get_active(); if (currRow) { const ProfileStoreEntry *currEntry = (*currRow)[methodColumns.profileStoreEntry]; return currEntry->label; } - return currLabel; + return {}; } -const ProfileStoreEntry* ProfileStoreComboBox::getSelectedEntry() +const ProfileStoreEntry* ProfileStoreComboBox::getSelectedEntry() const { - Gtk::TreeModel::iterator currRow_ = get_active(); - Gtk::TreeModel::Row currRow = *currRow_; + const Gtk::TreeModel::const_iterator currRow_ = get_active(); + const Gtk::TreeModel::Row currRow = *currRow_; if (currRow) { return currRow[methodColumns.profileStoreEntry]; @@ -145,18 +144,16 @@ void ProfileStoreComboBox::updateProfileList () cellRenderer->property_ellipsize_set() = true; } -Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry_ (Gtk::TreeModel::Children childs, const ProfileStoreEntry *pse) +Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry_ (Gtk::TreeModel::Children childs, const ProfileStoreEntry *pse) const { - Gtk::TreeModel::Row row; - Gtk::TreeIter rowInSubLevel; - for (Gtk::TreeModel::Children::iterator iter = childs.begin(); iter != childs.end(); ++iter) { - row = *iter; + for (const auto& iter : childs) { + const Gtk::TreeModel::Row row = *iter; // Hombre: is there a smarter way of knowing if this row has childs? const ProfileStoreEntry *pse_ = row[methodColumns.profileStoreEntry]; if (pse_->type == PSET_FOLDER) { - rowInSubLevel = findRowFromEntry_ (iter->children(), pse); + const Gtk::TreeIter rowInSubLevel = findRowFromEntry_ (iter->children(), pse); if (rowInSubLevel) { // entry found @@ -171,30 +168,27 @@ Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry_ (Gtk::TreeModel::Children return childs.end(); } -Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry (const ProfileStoreEntry *pse) +Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry (const ProfileStoreEntry *pse) const { Gtk::TreeModel::Children childs = refTreeModel->children(); if (pse) { - Gtk::TreeIter row = findRowFromEntry_ (childs, pse); - return row; + return findRowFromEntry_ (childs, pse); } return childs.end(); } -Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath_ (Gtk::TreeModel::Children childs, int parentFolderId, Glib::ustring &name) +Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath_ (Gtk::TreeModel::Children childs, int parentFolderId, const Glib::ustring &name) const { - Gtk::TreeModel::Row row; - Gtk::TreeIter rowInSubLevel; - for (Gtk::TreeModel::Children::iterator iter = childs.begin(); iter != childs.end(); ++iter) { - row = *iter; + for (const auto iter : childs) { + const Gtk::TreeModel::Row row = *iter; // Hombre: is there a smarter way of knowing if this row has childs? const ProfileStoreEntry *pse = row[methodColumns.profileStoreEntry]; if (pse->type == PSET_FOLDER) { - rowInSubLevel = findRowFromFullPath_ (iter->children(), parentFolderId, name); + const Gtk::TreeIter rowInSubLevel = findRowFromFullPath_ (iter->children(), parentFolderId, name); if (rowInSubLevel) { // entry found @@ -209,88 +203,77 @@ Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath_ (Gtk::TreeModel::Childr return childs.end(); } -Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath (Glib::ustring path) +Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath (const Glib::ustring &path) const { - Gtk::TreeIter row; - ProfileStore *profileStore = ProfileStore::getInstance(); if (path.empty()) { - return row; + return {}; } + const ProfileStore *profileStore = ProfileStore::getInstance(); + if (path == DEFPROFILE_INTERNAL) { - row = findRowFromEntry (profileStore->getInternalDefaultPSE()); - return row; + return findRowFromEntry (profileStore->getInternalDefaultPSE()); } if (path == DEFPROFILE_DYNAMIC) { - row = findRowFromEntry (profileStore->getInternalDynamicPSE()); - return row; + return findRowFromEntry (profileStore->getInternalDynamicPSE()); } // removing the filename - Glib::ustring fName = Glib::path_get_basename (path); + const Glib::ustring fName = Glib::path_get_basename(path); if (!fName.empty()) { - path = path.substr (0, path.length() - fName.length()); - } else { - // path is malformed; - return row; + int parentFolderId = profileStore->findFolderId (Glib::path_get_dirname (path.substr (0, path.length() - fName.length()))); + // 1. find the path in the folder list + if (parentFolderId != -1) { + return findRowFromFullPath_ (refTreeModel->children(), parentFolderId, fName); + } } - path = Glib::path_get_dirname (path); - int parentFolderId = profileStore->findFolderId (path); - - // 1. find the path in the folder list - if (parentFolderId != -1) { - row = findRowFromFullPath_ (refTreeModel->children(), parentFolderId, fName); - } - - return row; + return {}; } /** @brief Get the absolute full path of the active row entry. * @return The absolute full path of the active row entry, or the "Internal" keyword, * or an empty string if the ComboBox is in an invalid state */ -Glib::ustring ProfileStoreComboBox::getFullPathFromActiveRow() +Glib::ustring ProfileStoreComboBox::getFullPathFromActiveRow() const { - Glib::ustring path; - Gtk::TreeModel::iterator currRowI = get_active(); - ProfileStore *profileStore = ProfileStore::getInstance(); + const Gtk::TreeModel::const_iterator currRowI = get_active(); if (!currRowI) { - return path; + return {}; } Gtk::TreeModel::Row currRow = *currRowI; if (currRow) { - const ProfileStoreEntry *currEntry = currRow[methodColumns.profileStoreEntry]; if (!currEntry) { - return path; + return {}; } + const ProfileStore *profileStore = ProfileStore::getInstance(); if (currEntry == profileStore->getInternalDefaultPSE()) { - return Glib::ustring (DEFPROFILE_INTERNAL); + return DEFPROFILE_INTERNAL; } if (currEntry == profileStore->getInternalDynamicPSE()) { - return Glib::ustring (DEFPROFILE_DYNAMIC); + return DEFPROFILE_DYNAMIC; } - path = Glib::build_filename (profileStore->getPathFromId (currEntry->parentFolderId), currEntry->label); + return Glib::build_filename (profileStore->getPathFromId (currEntry->parentFolderId), currEntry->label); } - return path; + return {}; } -bool ProfileStoreComboBox::setActiveRowFromFullPath (Glib::ustring path) +bool ProfileStoreComboBox::setActiveRowFromFullPath (const Glib::ustring &path) { if (!path.empty()) { - Gtk::TreeIter row = findRowFromFullPath (path); + const Gtk::TreeIter row = findRowFromFullPath (path); if (row) { set_active (row); @@ -304,7 +287,7 @@ bool ProfileStoreComboBox::setActiveRowFromFullPath (Glib::ustring path) bool ProfileStoreComboBox::setActiveRowFromEntry (const ProfileStoreEntry *pse) { if (pse) { - Gtk::TreeIter row = findRowFromEntry (pse); + const Gtk::TreeIter row = findRowFromEntry (pse); if (row) { set_active (row); @@ -321,16 +304,13 @@ bool ProfileStoreComboBox::setInternalEntry () } /** @brief Get the row from the first level of the tree that match the provided name */ -Gtk::TreeIter ProfileStoreComboBox::getRowFromLabel (Glib::ustring name) +Gtk::TreeIter ProfileStoreComboBox::getRowFromLabel (const Glib::ustring &name) const { - Gtk::TreeIter row; - Gtk::TreeModel::Children childs = refTreeModel->children(); + const Gtk::TreeModel::Children childs = refTreeModel->children(); if (!name.empty()) { - Gtk::TreeModel::Row currRow; - - for (Gtk::TreeModel::Children::iterator iter = childs.begin(); iter != childs.end(); ++iter) { - currRow = *iter; + for (const auto iter : childs) { + const Gtk::TreeModel::Row currRow = *iter; const ProfileStoreEntry *pse = currRow[methodColumns.profileStoreEntry]; if (pse->label == name) { diff --git a/rtgui/profilestorecombobox.h b/rtgui/profilestorecombobox.h index 9c31ad60a..5d04813d6 100644 --- a/rtgui/profilestorecombobox.h +++ b/rtgui/profilestorecombobox.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PROFILESTORECOMBOBOX_ #define _PROFILESTORECOMBOBOX_ @@ -24,7 +24,6 @@ #include #include "../rtengine/rtengine.h" -#include "../rtengine/noncopyable.h" #include "../rtengine/profilestore.h" #include "threadutils.h" @@ -35,7 +34,7 @@ /** * @brief subclass of Gtk::Label with extra fields for Combobox and Menu, to link with a ProfileStoreEntry */ -class ProfileStoreLabel : public Gtk::Label +class ProfileStoreLabel final : public Gtk::Label { public: @@ -44,7 +43,7 @@ public: #ifndef NDEBUG ProfileStoreLabel() : Gtk::Label ("*** error ***"), entry (nullptr) {} #else - ProfileStoreLabel() : Gtk::Label (""), entry (NULL) {} + ProfileStoreLabel() : Gtk::Label (""), entry (nullptr) {} #endif /** @brief Create a new ProfileStoreLabel @@ -55,11 +54,11 @@ public: ProfileStoreLabel (const ProfileStoreLabel &other); }; -class ProfileStoreComboBox : public MyComboBox +class ProfileStoreComboBox final : public MyComboBox { -protected: - class MethodColumns : public Gtk::TreeModel::ColumnRecord +private: + class MethodColumns final : public Gtk::TreeModel::ColumnRecord { public: Gtk::TreeModelColumn label; @@ -74,21 +73,22 @@ protected: Glib::RefPtr refTreeModel; MethodColumns methodColumns; void refreshProfileList_ (Gtk::TreeModel::Row *parentRow, int parentFolderId, bool initial, const std::vector *entryList); - Gtk::TreeIter findRowFromEntry_ (Gtk::TreeModel::Children childs, const ProfileStoreEntry *pse); - Gtk::TreeIter findRowFromFullPath_ (Gtk::TreeModel::Children childs, int parentFolderId, Glib::ustring &name); + Gtk::TreeIter findRowFromEntry_ (Gtk::TreeModel::Children childs, const ProfileStoreEntry *pse) const; + Gtk::TreeIter findRowFromFullPath_ (Gtk::TreeModel::Children childs, int parentFolderId, const Glib::ustring &name) const; + Gtk::TreeIter findRowFromEntry (const ProfileStoreEntry *pse) const; + Gtk::TreeIter findRowFromFullPath (const Glib::ustring &path) const; + public: ProfileStoreComboBox(); void updateProfileList(); - Glib::ustring getCurrentLabel(); - const ProfileStoreEntry* getSelectedEntry(); - Gtk::TreeIter findRowFromEntry (const ProfileStoreEntry *pse); - Gtk::TreeIter findRowFromFullPath (Glib::ustring path); - Glib::ustring getFullPathFromActiveRow (); - bool setActiveRowFromFullPath (Glib::ustring oldPath); + Glib::ustring getCurrentLabel() const; + const ProfileStoreEntry* getSelectedEntry() const; + Glib::ustring getFullPathFromActiveRow () const; + bool setActiveRowFromFullPath (const Glib::ustring &oldPath); bool setActiveRowFromEntry (const ProfileStoreEntry *pse); bool setInternalEntry (); - Gtk::TreeIter getRowFromLabel (Glib::ustring name); + Gtk::TreeIter getRowFromLabel (const Glib::ustring &name) const; Gtk::TreeIter addRow (const ProfileStoreEntry *profileStoreEntry); void deleteRow (const ProfileStoreEntry *profileStoreEntry); }; diff --git a/rtgui/progressconnector.h b/rtgui/progressconnector.h index 394ad3909..012039ba6 100644 --- a/rtgui/progressconnector.h +++ b/rtgui/progressconnector.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PROGRESSCONNECTOR_ #define _PROGRESSCONNECTOR_ diff --git a/rtgui/prsharpening.cc b/rtgui/prsharpening.cc index c7c2ddf9f..d065dbc07 100644 --- a/rtgui/prsharpening.cc +++ b/rtgui/prsharpening.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include "eventmapper.h" @@ -350,10 +350,6 @@ void PrSharpening::adjusterChanged (Adjuster* a, double newval) } } -void PrSharpening::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void PrSharpening::enabledChanged () { if (listener) { diff --git a/rtgui/prsharpening.h b/rtgui/prsharpening.h index 0bceca856..9d37fa8ba 100644 --- a/rtgui/prsharpening.h +++ b/rtgui/prsharpening.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _PRSHARPENING_H_ #define _PRSHARPENING_H_ @@ -65,7 +65,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void enabledChanged () override; void edgesonly_toggled (); void halocontrol_toggled (); diff --git a/rtgui/rawcacorrection.cc b/rtgui/rawcacorrection.cc index a6b624562..9e5c592ef 100644 --- a/rtgui/rawcacorrection.cc +++ b/rtgui/rawcacorrection.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "rawcacorrection.h" @@ -144,10 +144,6 @@ void RAWCACorr::adjusterChanged(Adjuster* a, double newval) } } -void RAWCACorr::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void RAWCACorr::checkBoxToggled (CheckBox* c, CheckValue newval) { if (c == caAutocorrect) { diff --git a/rtgui/rawcacorrection.h b/rtgui/rawcacorrection.h index 13db1d1e3..d3874d9f9 100644 --- a/rtgui/rawcacorrection.h +++ b/rtgui/rawcacorrection.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _RAWCACORRECTION_H_ #define _RAWCACORRECTION_H_ @@ -50,7 +50,6 @@ public: void trimValues (rtengine::procparams::ProcParams* pp) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled (Adjuster* a, bool newval) override; void checkBoxToggled (CheckBox* c, CheckValue newval) override; }; diff --git a/rtgui/rawexposure.cc b/rtgui/rawexposure.cc index 599c8fd12..7548bf4be 100644 --- a/rtgui/rawexposure.cc +++ b/rtgui/rawexposure.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -76,10 +76,6 @@ void RAWExposure::adjusterChanged(Adjuster* a, double newval) } } -void RAWExposure::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void RAWExposure::setBatchMode(bool batchMode) { ToolPanel::setBatchMode (batchMode); diff --git a/rtgui/rawexposure.h b/rtgui/rawexposure.h index f34776d19..1dafd4d64 100644 --- a/rtgui/rawexposure.h +++ b/rtgui/rawexposure.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _RAWEXPOSURE_H_ #define _RAWEXPOSURE_H_ @@ -41,7 +41,6 @@ public: void setBatchMode (bool batchMode) override; void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled (Adjuster* a, bool newval) override; void setAdjusterBehavior (bool pexposadd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; diff --git a/rtgui/recentbrowser.cc b/rtgui/recentbrowser.cc index ec97f6ded..fca97cafa 100644 --- a/rtgui/recentbrowser.cc +++ b/rtgui/recentbrowser.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "recentbrowser.h" #include "multilangmgr.h" diff --git a/rtgui/recentbrowser.h b/rtgui/recentbrowser.h index 2d1e210f4..1ba2c17f4 100644 --- a/rtgui/recentbrowser.h +++ b/rtgui/recentbrowser.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _RECENTBROWSER_ #define _RECENTBROWSER_ diff --git a/rtgui/renamedlg.cc b/rtgui/renamedlg.cc index f03df455f..8f55b3653 100644 --- a/rtgui/renamedlg.cc +++ b/rtgui/renamedlg.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "renamedlg.h" #include "multilangmgr.h" @@ -88,159 +88,3 @@ Glib::ustring RenameDialog::getNewName () return newName->get_text (); } -//void RenameDialog::fillTemplateList () -//{ -// -// templateModel->clear (); -// -// for (size_t i = 0; i < options.renameTemplates.size(); i++) { -// Gtk::TreeModel::iterator iter = templateModel->append (); -// iter->set_value (templateColumns.tmplName, options.renameTemplates[i]); -// iter->set_value (templateColumns.rowSeparator, false); -// } -// -// // append separator and the manage... item -// Gtk::TreeModel::iterator iter = templateModel->append (); -// iter->set_value (templateColumns.tmplName, Glib::ustring("")); -// iter->set_value (templateColumns.rowSeparator, true); -// iter = templateModel->append (); -// iter->set_value (templateColumns.tmplName, Glib::ustring(M("FILEBROWSER_ADDDELTEMPLATE"))); -// iter->set_value (templateColumns.rowSeparator, false); -//} - -//bool RenameDialog::rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter) -//{ -// -// return iter->get_value (templateColumns.rowSeparator); -//} - -//void RenameDialog::useTemplToggled () -//{ -// -// templates->set_sensitive (useTmpl->get_active ()); -// -// if (useTmpl->get_active () && isTemplSelected ()) { -// all->set_sensitive (true); -// newName->set_text (applyTemplate (oldName->get_text(), imageData, getActiveTemplate())); -// } else { -// all->set_sensitive (false); -// } -// -// newName->select_region (0, newName->get_text().size()); -//} - -//bool RenameDialog::isTemplSelected () -//{ -// -// Gtk::TreeModel::iterator iter = templates->get_active(); -// return iter && iter->get_value (templateColumns.tmplName) != M("FILEBROWSER_ADDDELTEMPLATE"); -//} - -//Glib::ustring RenameDialog::getActiveTemplate () -//{ -// -// Gtk::TreeModel::iterator iter = templates->get_active(); -// -// if (iter && iter->get_value (templateColumns.tmplName) != M("FILEBROWSER_ADDDELTEMPLATE")) { -// return iter->get_value (templateColumns.tmplName); -// } else { -// return ""; -// } -//} - -//void RenameDialog::tmplSelectionChanged () -//{ -// -// Gtk::TreeModel::iterator iter = templates->get_active(); -// -// if (iter && iter->get_value (templateColumns.tmplName) == M("FILEBROWSER_ADDDELTEMPLATE")) { -// RenameTemplateEditor* rte = new RenameTemplateEditor (p); -// -// if (rte->run() == Gtk::RESPONSE_OK) { -// fillTemplateList (); -// } -// -// delete rte; -// // show add/del template dialog -// } else { -// useTemplToggled (); -// } -//} - -//RenameTemplateEditor::RenameTemplateEditor (Gtk::Window* parent) -// : Gtk::Dialog ("Edit rename templates", *parent, true) -//{ -// -// list = Gtk::manage (new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE)); -// list->set_headers_visible (false); -// get_content_area ()->pack_start (*list); -// -// Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); -// templ = Gtk::manage (new Gtk::Entry ()); -// Gtk::Button* add = Gtk::manage (new Gtk::Button ()); -// Gtk::Button* del = Gtk::manage (new Gtk::Button ()); -// add->add (*Gtk::manage (new RTImage ("add-small.png"))); -// del->add (*Gtk::manage (new RTImage ("remove-small.png"))); -// hb->pack_start (*templ); -// hb->pack_start (*add, Gtk::PACK_SHRINK, 2); -// hb->pack_start (*del, Gtk::PACK_SHRINK, 2); -// -// get_content_area ()->pack_start (*hb, Gtk::PACK_SHRINK, 4); -// -// add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); -// -// refreshTemplateList (); -// -// add->signal_pressed().connect( sigc::mem_fun(*this, &RenameTemplateEditor::addPressed) ); -// del->signal_pressed().connect( sigc::mem_fun(*this, &RenameTemplateEditor::delPressed) ); -// -// show_all_children (); -// -// set_size_request (-1, 250); -//} -// -//void RenameTemplateEditor::refreshTemplateList () -//{ -// -// list->remove_all_columns(); -// -// for (size_t i = 0; i < options.renameTemplates.size(); i++) { -// list->append (options.renameTemplates[i]); -// } -//} -// -//void RenameTemplateEditor::addPressed () -//{ -// -// if (templ->get_text() != "") { -// options.renameTemplates.push_back (templ->get_text ()); -// refreshTemplateList (); -// templ->set_text(""); -// } -//} -// -//void RenameTemplateEditor::delPressed () -//{ -// -// std::vector sel = list->get_selected (); -// -// for (size_t i = 0; i < sel.size(); i++) { -// Glib::ustring toDel = list->get_text (sel[i]); -// std::vector::iterator f = std::find (options.renameTemplates.begin(), options.renameTemplates.end(), toDel); -// -// if (f != options.renameTemplates.end()) { -// options.renameTemplates.erase (f); -// } -// } -// -// refreshTemplateList (); -//} - -//Glib::ustring RenameDialog::applyTemplate (const Glib::ustring& oName, const CacheImageData* cid, const Glib::ustring& templ) -//{ -// -// return Glib::ustring ("szeva"); -// -//} - - diff --git a/rtgui/renamedlg.h b/rtgui/renamedlg.h index 94972d575..a3e16ad0a 100644 --- a/rtgui/renamedlg.h +++ b/rtgui/renamedlg.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _RENAMEDLG_ #define _RENAMEDLG_ @@ -30,62 +30,19 @@ class RenameDialog : public Gtk::Dialog protected: -// class TemplateColumns : public Gtk::TreeModel::ColumnRecord -// { -// public: -// Gtk::TreeModelColumn tmplName; -// Gtk::TreeModelColumn rowSeparator; -// TemplateColumns() -// { -// add(tmplName); -// add(rowSeparator); -// } -// }; -// TemplateColumns templateColumns; -// Glib::RefPtr templateModel; Gtk::Window* p; Gtk::Label* oldName; Gtk::Entry* newName; -// Gtk::CheckButton* useTmpl; -// MyComboBox* templates; -// Gtk::Button* all; const CacheImageData* imageData; -// void fillTemplateList (); - public: explicit RenameDialog (Gtk::Window* parent); void initName (const Glib::ustring& iname, const CacheImageData* cid); Glib::ustring getNewName (); -// bool rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter); -// void tmplSelectionChanged (); -// void useTemplToggled (); - -// bool isTemplSelected (); -// Glib::ustring getActiveTemplate (); - -// static Glib::ustring applyTemplate (const Glib::ustring& oName, const CacheImageData* cid, const Glib::ustring& templ); }; -//class RenameTemplateEditor : public Gtk::Dialog -//{ -// -//protected: -// Gtk::ListViewText* list; -// Gtk::Entry* templ; -// -// void refreshTemplateList (); -//public: -// explicit RenameTemplateEditor (Gtk::Window* parent); -// -// Glib::ustring getSelectedTemplate (); -// -// void addPressed (); -// void delPressed (); -//}; - #endif diff --git a/rtgui/resize.cc b/rtgui/resize.cc index 40d7ace56..641cffd7c 100644 --- a/rtgui/resize.cc +++ b/rtgui/resize.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -93,14 +93,13 @@ Resize::Resize () : FoldableToolPanel(this, "resize", M("TP_RESIZE_LABEL"), fals sbox->pack_start (*hbox); sizeBox->pack_start (*sbox, Gtk::PACK_SHRINK, 0); - - allowUpscaling = Gtk::manage(new Gtk::CheckButton(M("TP_RESIZE_ALLOW_UPSCALING"))); - sizeBox->pack_start(*allowUpscaling); - allowUpscaling->signal_toggled().connect(sigc::mem_fun(*this, &Resize::allowUpscalingChanged)); - sizeBox->show_all (); sizeBox->reference (); + allowUpscaling = Gtk::manage(new Gtk::CheckButton(M("TP_RESIZE_ALLOW_UPSCALING"))); + pack_start(*allowUpscaling); + allowUpscaling->signal_toggled().connect(sigc::mem_fun(*this, &Resize::allowUpscalingChanged)); + w->set_digits (0); w->set_increments (1, 100); w->set_value (800); @@ -275,10 +274,6 @@ void Resize::adjusterChanged(Adjuster* a, double newval) } } -void Resize::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - int Resize::getComputedWidth() { @@ -578,11 +573,13 @@ void Resize::updateGUI () case (0): // Scale mode pack_start (*scale, Gtk::PACK_SHRINK, 4); + reorder_child(*allowUpscaling, 4); break; case (1): // Width mode pack_start (*sizeBox, Gtk::PACK_SHRINK, 4); + reorder_child(*allowUpscaling, 4); w->set_sensitive (true); h->set_sensitive (false); break; @@ -590,6 +587,7 @@ void Resize::updateGUI () case (2): // Height mode pack_start (*sizeBox, Gtk::PACK_SHRINK, 4); + reorder_child(*allowUpscaling, 4); w->set_sensitive (false); h->set_sensitive (true); break; @@ -597,6 +595,7 @@ void Resize::updateGUI () case (3): // Bounding box mode pack_start (*sizeBox, Gtk::PACK_SHRINK, 4); + reorder_child(*allowUpscaling, 4); w->set_sensitive (true); h->set_sensitive (true); break; diff --git a/rtgui/resize.h b/rtgui/resize.h index 3c599808d..1d38ae674 100644 --- a/rtgui/resize.h +++ b/rtgui/resize.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _RESIZE_H_ #define _RESIZE_H_ @@ -46,7 +46,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void entryWChanged (); void entryHChanged (); void appliesToChanged (); diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc index 544ace535..e074d7e9c 100644 --- a/rtgui/retinex.cc +++ b/rtgui/retinex.cc @@ -1362,10 +1362,6 @@ void Retinex::adjusterChanged(Adjuster* a, double newval) } } -void Retinex::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void Retinex::autoOpenCurve () { cdshape->openIfNonlinear(); diff --git a/rtgui/retinex.h b/rtgui/retinex.h index 8703ec607..1be511cb3 100644 --- a/rtgui/retinex.h +++ b/rtgui/retinex.h @@ -104,7 +104,6 @@ public: void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; void trimValues (rtengine::procparams::ProcParams* pp) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled (Adjuster* a, bool newval) override; void autoOpenCurve () override; void medianmapChanged (); void minmaxChanged (double cdma, double cdmin, double mini, double maxi, double Tmean, double Tsigma, double Tmin, double Tmax) override; diff --git a/rtgui/rgbcurves.cc b/rtgui/rgbcurves.cc index 560ee7e57..2350783e0 100644 --- a/rtgui/rgbcurves.cc +++ b/rtgui/rgbcurves.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "rgbcurves.h" @@ -23,7 +23,7 @@ using namespace rtengine; using namespace rtengine::procparams; -RGBCurves::RGBCurves () : FoldableToolPanel(this, "rgbcurves", M("TP_RGBCURVES_LABEL"), false, true) +RGBCurves::RGBCurves () : FoldableToolPanel(this, "rgbcurves", M("TP_RGBCURVES_LABEL"), false, true), lastLumamode(false) { lumamode = Gtk::manage (new Gtk::CheckButton (M("TP_RGBCURVES_LUMAMODE"))); diff --git a/rtgui/rgbcurves.h b/rtgui/rgbcurves.h index a7846f9ab..e62fdd7c7 100644 --- a/rtgui/rgbcurves.h +++ b/rtgui/rgbcurves.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _RGBCURVES_H_ #define _RGBCURVES_H_ diff --git a/rtgui/rotate.cc b/rtgui/rotate.cc index 9f5d665d5..7436186c3 100644 --- a/rtgui/rotate.cc +++ b/rtgui/rotate.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -96,10 +96,6 @@ void Rotate::adjusterChanged(Adjuster* a, double newval) } } -void Rotate::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void Rotate::straighten (double deg) { diff --git a/rtgui/rotate.h b/rtgui/rotate.h index c23807361..bd0613609 100644 --- a/rtgui/rotate.h +++ b/rtgui/rotate.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _ROTATE_H_ #define _ROTATE_H_ @@ -44,7 +44,6 @@ public: void straighten (double deg); void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled (Adjuster* a, bool newval) override; void setAdjusterBehavior (bool rotadd); void trimValues (rtengine::procparams::ProcParams* pp) override; void selectStraightPressed (); diff --git a/rtgui/rtimage.cc b/rtgui/rtimage.cc index 6a289ead6..e35a6d164 100644 --- a/rtgui/rtimage.cc +++ b/rtgui/rtimage.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "rtimage.h" @@ -37,12 +37,8 @@ int RTImage::scaleBack = 0; RTImage::RTImage () {} -RTImage::RTImage (RTImage &other) +RTImage::RTImage (RTImage &other) : surface(other.surface), pixbuf(other.pixbuf) { - dpiBack = other.dpiBack; - scaleBack = other.scaleBack; - pixbuf = other.pixbuf; - surface = other.surface; if (pixbuf) { set(pixbuf); } else if (surface) { @@ -173,7 +169,7 @@ void RTImage::init() scaleBack = RTScalable::getScale(); } -void RTImage::cleanup() +void RTImage::cleanup(bool all) { for (auto& entry : pixbufCache) { entry.second.reset(); @@ -181,7 +177,7 @@ void RTImage::cleanup() for (auto& entry : surfaceCache) { entry.second.clear(); } - RTScalable::cleanup(); + RTScalable::cleanup(all); } void RTImage::updateImages() @@ -197,8 +193,7 @@ void RTImage::updateImages() Glib::RefPtr RTImage::createPixbufFromFile (const Glib::ustring& fileName) { Cairo::RefPtr imgSurf = createImgSurfFromFile(fileName); - Glib::RefPtr pixbuf = Gdk::Pixbuf::create(imgSurf, 0, 0, imgSurf->get_width(), imgSurf->get_height()); - return pixbuf; + return Gdk::Pixbuf::create(imgSurf, 0, 0, imgSurf->get_width(), imgSurf->get_height()); } Cairo::RefPtr RTImage::createImgSurfFromFile (const Glib::ustring& fileName) diff --git a/rtgui/rtimage.h b/rtgui/rtimage.h index 5679f6edc..b68becd82 100644 --- a/rtgui/rtimage.h +++ b/rtgui/rtimage.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once @@ -38,11 +38,11 @@ protected: public: RTImage (); RTImage (RTImage &other); - RTImage (Glib::RefPtr &pixbuf); - RTImage (Cairo::RefPtr &surf); - RTImage(Cairo::RefPtr other); - RTImage (Glib::RefPtr &other); - RTImage (const Glib::ustring& fileName, const Glib::ustring& rtlFileName = Glib::ustring()); + explicit RTImage (Glib::RefPtr &pixbuf); + explicit RTImage (Cairo::RefPtr &surf); + explicit RTImage(Cairo::RefPtr other); + explicit RTImage (Glib::RefPtr &other); + explicit RTImage (const Glib::ustring& fileName, const Glib::ustring& rtlFileName = Glib::ustring()); void setImage (const Glib::ustring& fileName, const Glib::ustring& rtlFileName = Glib::ustring()); void changeImage (const Glib::ustring& imageName); @@ -52,7 +52,7 @@ public: static void init(); - static void cleanup(); + static void cleanup(bool all = false); static void updateImages (); static void setDPInScale (const double newDPI, const int newScale); static void setScale (const int newScale); diff --git a/rtgui/rtscalable.cc b/rtgui/rtscalable.cc index aaa10bd21..15211a7ee 100644 --- a/rtgui/rtscalable.cc +++ b/rtgui/rtscalable.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "rtscalable.h" @@ -119,7 +119,7 @@ void RTScalable::deleteDir(const Glib::ustring& path) } } -void RTScalable::cleanup() +void RTScalable::cleanup(bool all) { Glib::ustring imagesCacheFolder = Glib::build_filename (options.cacheBaseDir, "svg2png"); Glib::ustring sDPI = Glib::ustring::compose("%1", (int)getTweakedDPI()); @@ -134,7 +134,7 @@ void RTScalable::cleanup() continue; } - if (fileName != sDPI) { + if (all || fileName != sDPI) { deleteDir(filePath); } } @@ -220,7 +220,7 @@ Cairo::RefPtr RTScalable::loadImage(const Glib::ustring &fn GError **error = nullptr; RsvgHandle *handle = rsvg_handle_new_from_data((unsigned const char*)updatedSVG.c_str(), updatedSVG.length(), error); - if (handle == nullptr) { + if (error && !handle) { std::cerr << "ERROR: Can't use the provided data for \"" << fname << "\" to create a RsvgHandle:" << std::endl << Glib::ustring((*error)->message) << std::endl; Cairo::RefPtr surf = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, 10, 10); diff --git a/rtgui/rtscalable.h b/rtgui/rtscalable.h index e6180eaa1..28ebf7be8 100644 --- a/rtgui/rtscalable.h +++ b/rtgui/rtscalable.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once @@ -50,7 +50,7 @@ public: #endif static void init(Gtk::Window *window); - static void cleanup(); + static void cleanup(bool all = false); static double getDPI (); static double getTweakedDPI (); // The returned value is tweaked DPI to adapt to main the font size. Maybe not an ideal solution. static int getScale (); diff --git a/rtgui/rtsurface.cc b/rtgui/rtsurface.cc index 230c3ff4f..62dfe36d5 100644 --- a/rtgui/rtsurface.cc +++ b/rtgui/rtsurface.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtgui/rtsurface.h b/rtgui/rtsurface.h index c314ab1c1..1944cc2dc 100644 --- a/rtgui/rtsurface.h +++ b/rtgui/rtsurface.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once @@ -30,7 +30,7 @@ class RTSurface : { public: RTSurface(); - RTSurface(const Glib::ustring& fileName, const Glib::ustring& rtlFileName = {}); + explicit RTSurface(const Glib::ustring& fileName, const Glib::ustring& rtlFileName = {}); void setImage(const Glib::ustring& fileName, const Glib::ustring& rtlFileName = {}); diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index 6158cb76a..3983f93b1 100644 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -95,6 +95,9 @@ RTWindow::RTWindow () , fpanel (nullptr) { + if (options.is_new_version()) { + RTImage::cleanup(true); + } cacheMgr->init (); ProfilePanel::init (this); @@ -173,8 +176,8 @@ RTWindow::RTWindow () } else { Glib::RefPtr style = Gtk::StyleContext::create(); Pango::FontDescription pfd = style->get_font(Gtk::STATE_FLAG_NORMAL); - int pt; if (pfd.get_set_fields() & Pango::FONT_MASK_SIZE) { + int pt; int fontSize = pfd.get_size(); bool isPix = pfd.get_size_is_absolute(); int resolution = (int)style->get_screen()->get_resolution(); @@ -254,8 +257,6 @@ RTWindow::RTWindow () #if defined(__APPLE__) { osxApp = (GtkosxApplication *)g_object_new (GTKOSX_TYPE_APPLICATION, NULL); - gboolean falseval = FALSE; - gboolean trueval = TRUE; RTWindow *rtWin = this; g_signal_connect (osxApp, "NSApplicationBlockTermination", G_CALLBACK (osx_should_quit_cb), rtWin); g_signal_connect (osxApp, "NSApplicationWillTerminate", G_CALLBACK (osx_will_quit_cb), rtWin); @@ -477,16 +478,8 @@ void RTWindow::on_realize () mainWindowCursorManager.init (get_window()); // Display release notes only if new major version. - // Pattern matches "5.1" from "5.1-23-g12345678" - const std::string vs[] = {versionString, options.version}; - std::vector vMajor; - - for (const auto& v : vs) { - vMajor.emplace_back(v, 0, v.find_first_not_of("0123456789.")); - } - bool waitForSplash = false; - if (vMajor.size() == 2 && vMajor[0] != vMajor[1]) { + if (options.is_new_version()) { // Update the version parameter with the right value options.version = versionString; diff --git a/rtgui/rtwindow.h b/rtgui/rtwindow.h index 5b58ab0eb..93e1c31b9 100644 --- a/rtgui/rtwindow.h +++ b/rtgui/rtwindow.h @@ -13,7 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _RTWINDOW_ #define _RTWINDOW_ @@ -29,8 +29,9 @@ #if defined(__APPLE__) #include #endif +#include "../rtengine/noncopyable.h" -class RTWindow : public Gtk::Window, public rtengine::ProgressListener +class RTWindow : public Gtk::Window, public rtengine::ProgressListener, public rtengine::NonCopyable { private: @@ -52,7 +53,6 @@ private: { return !options.tabbedUI && ! (options.multiDisplayMode > 0); }; - void findVerNumbers (int* numbers, Glib::ustring versionStr); bool on_expose_event_epanel (GdkEventExpose* event); bool on_expose_event_fpanel (GdkEventExpose* event); diff --git a/rtgui/saveasdlg.cc b/rtgui/saveasdlg.cc index f2a7206b9..1b61d7d3d 100644 --- a/rtgui/saveasdlg.cc +++ b/rtgui/saveasdlg.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtgui/saveasdlg.h b/rtgui/saveasdlg.h index e02be340f..dd120337d 100644 --- a/rtgui/saveasdlg.h +++ b/rtgui/saveasdlg.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _SAVEASDLG_ #define _SAVEASDLG_ diff --git a/rtgui/saveformatpanel.cc b/rtgui/saveformatpanel.cc index de2240fc6..00f6e7b2b 100644 --- a/rtgui/saveformatpanel.cc +++ b/rtgui/saveformatpanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -218,7 +218,3 @@ void SaveFormatPanel::adjusterChanged(Adjuster* a, double newval) listener->formatChanged(sf_templates[act].second.format); } } - -void SaveFormatPanel::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} diff --git a/rtgui/saveformatpanel.h b/rtgui/saveformatpanel.h index 48fa97e13..ab5ffef3e 100644 --- a/rtgui/saveformatpanel.h +++ b/rtgui/saveformatpanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __SAVEFORMATPANEL_H__ #define __SAVEFORMATPANEL_H__ @@ -23,6 +23,7 @@ #include "adjuster.h" #include "guiutils.h" #include "options.h" +#include "../rtengine/noncopyable.h" class FormatChangeListener { @@ -31,7 +32,7 @@ public: virtual void formatChanged(const Glib::ustring& format) = 0; }; -class SaveFormatPanel : public Gtk::Grid, public AdjusterListener +class SaveFormatPanel : public Gtk::Grid, public AdjusterListener, public rtengine::NonCopyable { protected: @@ -60,7 +61,6 @@ public: void formatChanged (); void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; }; #endif diff --git a/rtgui/sensorbayer.cc b/rtgui/sensorbayer.cc index 44afdd2e8..39ed5cb91 100644 --- a/rtgui/sensorbayer.cc +++ b/rtgui/sensorbayer.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "sensorbayer.h" #include "guiutils.h" diff --git a/rtgui/sensorbayer.h b/rtgui/sensorbayer.h index f3c620d88..2d68411ce 100644 --- a/rtgui/sensorbayer.h +++ b/rtgui/sensorbayer.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _SENSORBAYER_H_ #define _SENSORBAYER_H_ diff --git a/rtgui/sensorxtrans.cc b/rtgui/sensorxtrans.cc index c0a704ebf..f13e6607f 100644 --- a/rtgui/sensorxtrans.cc +++ b/rtgui/sensorxtrans.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "sensorxtrans.h" #include "guiutils.h" diff --git a/rtgui/sensorxtrans.h b/rtgui/sensorxtrans.h index d723d29f7..fbf71b401 100644 --- a/rtgui/sensorxtrans.h +++ b/rtgui/sensorxtrans.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _SENSORXTRANS_H_ #define _SENSORXTRANS_H_ diff --git a/rtgui/shadowshighlights.cc b/rtgui/shadowshighlights.cc index 6fdf6f2f3..3e3c277c7 100644 --- a/rtgui/shadowshighlights.cc +++ b/rtgui/shadowshighlights.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "shadowshighlights.h" @@ -172,10 +172,6 @@ void ShadowsHighlights::adjusterChanged (Adjuster* a, double newval) } } -void ShadowsHighlights::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void ShadowsHighlights::enabledChanged () { diff --git a/rtgui/shadowshighlights.h b/rtgui/shadowshighlights.h index e04e2000a..d675f40d6 100644 --- a/rtgui/shadowshighlights.h +++ b/rtgui/shadowshighlights.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _SHADOWSHIGHLIGHTS_H_ #define _SHADOWSHIGHLIGHTS_H_ @@ -46,7 +46,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void enabledChanged () override; void setAdjusterBehavior (bool hadd, bool sadd); diff --git a/rtgui/sharpenedge.cc b/rtgui/sharpenedge.cc index 968cb75ad..f4415bb15 100644 --- a/rtgui/sharpenedge.cc +++ b/rtgui/sharpenedge.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -147,10 +147,6 @@ void SharpenEdge::adjusterChanged(Adjuster* a, double newval) } } -void SharpenEdge::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void SharpenEdge::setBatchMode(bool batchMode) { passes->showEditedCB (); diff --git a/rtgui/sharpenedge.h b/rtgui/sharpenedge.h index 8bf5647ed..b136d8e5e 100644 --- a/rtgui/sharpenedge.h +++ b/rtgui/sharpenedge.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * * Manuel Llorens' algorithm of edge sharpening @@ -51,7 +51,6 @@ public: void trimValues (rtengine::procparams::ProcParams* pp) override; void setAdjusterBehavior (bool amountadd, bool passadd); void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled (Adjuster* a, bool newval) override; void enabledChanged () override; void chanthree_toggled (); diff --git a/rtgui/sharpening.cc b/rtgui/sharpening.cc index 8a7b8e591..e16511279 100644 --- a/rtgui/sharpening.cc +++ b/rtgui/sharpening.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include "eventmapper.h" @@ -356,10 +356,6 @@ void Sharpening::adjusterChanged(Adjuster* a, double newval) } } -void Sharpening::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void Sharpening::adjusterChanged(ThresholdAdjuster* a, double newBottom, double newTop) { } diff --git a/rtgui/sharpening.h b/rtgui/sharpening.h index 75ea083c9..ac846a2b6 100644 --- a/rtgui/sharpening.h +++ b/rtgui/sharpening.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _SHARPENING_H_ #define _SHARPENING_H_ @@ -68,7 +68,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged(Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void enabledChanged () override; void edgesonly_toggled (); void halocontrol_toggled (); diff --git a/rtgui/sharpenmicro.cc b/rtgui/sharpenmicro.cc index 0b4142677..78228d27c 100644 --- a/rtgui/sharpenmicro.cc +++ b/rtgui/sharpenmicro.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -156,10 +156,6 @@ void SharpenMicro::adjusterChanged(Adjuster* a, double newval) } } -void SharpenMicro::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void SharpenMicro::setBatchMode(bool batchMode) { amount->showEditedCB (); diff --git a/rtgui/sharpenmicro.h b/rtgui/sharpenmicro.h index 6dfccea85..7c292413b 100644 --- a/rtgui/sharpenmicro.h +++ b/rtgui/sharpenmicro.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * * Manuel Llorens' algorithm of micro-contrast sharpening @@ -54,7 +54,6 @@ public: void trimValues (rtengine::procparams::ProcParams* pp) override; void setAdjusterBehavior (bool amountadd, bool contrastadd, bool uniformityadd); void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled (Adjuster* a, bool newval) override; void enabledChanged () override; void matrix_toggled (); diff --git a/rtgui/shcselector.cc b/rtgui/shcselector.cc index 55a2ad9dd..20b7e5e0a 100644 --- a/rtgui/shcselector.cc +++ b/rtgui/shcselector.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtgui/shcselector.h b/rtgui/shcselector.h index ac6c8afed..d3ef2adb8 100644 --- a/rtgui/shcselector.h +++ b/rtgui/shcselector.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _SHCSELECTOR_ #define _SHCSELECTOR_ diff --git a/rtgui/softlight.cc b/rtgui/softlight.cc index 0054f8f6d..84461f169 100644 --- a/rtgui/softlight.cc +++ b/rtgui/softlight.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -89,12 +89,6 @@ void SoftLight::adjusterChanged(Adjuster* a, double newval) } } - -void SoftLight::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - - void SoftLight::enabledChanged () { if (listener) { diff --git a/rtgui/softlight.h b/rtgui/softlight.h index a036592e4..a584d3a73 100644 --- a/rtgui/softlight.h +++ b/rtgui/softlight.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #pragma once @@ -41,7 +41,6 @@ public: void setBatchMode(bool batchMode) override; void adjusterChanged(Adjuster *a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void enabledChanged() override; void setAdjusterBehavior(bool strengthAdd); }; diff --git a/rtgui/soundman.cc b/rtgui/soundman.cc index 62c7d59b6..a4cf5337b 100644 --- a/rtgui/soundman.cc +++ b/rtgui/soundman.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with RawTherapee. If not, see . +* along with RawTherapee. If not, see . * */ diff --git a/rtgui/soundman.h b/rtgui/soundman.h index dd8e515fc..6d065c87a 100644 --- a/rtgui/soundman.h +++ b/rtgui/soundman.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with RawTherapee. If not, see . +* along with RawTherapee. If not, see . * */ diff --git a/rtgui/splash.cc b/rtgui/splash.cc index d608ccd97..7ae5bf4d7 100644 --- a/rtgui/splash.cc +++ b/rtgui/splash.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "splash.h" @@ -27,15 +27,13 @@ extern Glib::ustring creditsPath; extern Glib::ustring licensePath; extern Glib::ustring versionString; -SplashImage::SplashImage () +SplashImage::SplashImage () : surface(RTImage::createImgSurfFromFile("splash.png")) { - surface = RTImage::createImgSurfFromFile ("splash.png"); } bool SplashImage::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) { - Glib::RefPtr window = get_window(); cr->set_source(surface, 0., 0.); cr->rectangle(0, 0, surface->get_width(), surface->get_height()); cr->fill(); diff --git a/rtgui/splash.h b/rtgui/splash.h index 00e9f556e..29dbb62cf 100644 --- a/rtgui/splash.h +++ b/rtgui/splash.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __SPLASH__ #define __SPLASH__ diff --git a/rtgui/threadutils.cc b/rtgui/threadutils.cc index 7ba296081..025abf300 100644 --- a/rtgui/threadutils.cc +++ b/rtgui/threadutils.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "threadutils.h" diff --git a/rtgui/threadutils.h b/rtgui/threadutils.h index 1215d53a1..f8107d74c 100644 --- a/rtgui/threadutils.h +++ b/rtgui/threadutils.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _THREADUTILS_ #define _THREADUTILS_ diff --git a/rtgui/thresholdadjuster.cc b/rtgui/thresholdadjuster.cc index 210f63333..c6ba96111 100644 --- a/rtgui/thresholdadjuster.cc +++ b/rtgui/thresholdadjuster.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "thresholdadjuster.h" #include diff --git a/rtgui/thresholdadjuster.h b/rtgui/thresholdadjuster.h index 54026a183..ea3822875 100644 --- a/rtgui/thresholdadjuster.h +++ b/rtgui/thresholdadjuster.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _THRESHOLDADJUSTER_H_ #define _THRESHOLDADJUSTER_H_ diff --git a/rtgui/thresholdselector.cc b/rtgui/thresholdselector.cc index e1e6fc36f..b44425be4 100644 --- a/rtgui/thresholdselector.cc +++ b/rtgui/thresholdselector.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -30,7 +30,7 @@ ThresholdSelector::ThresholdSelector(double minValueBottom, double maxValueBottom, double defBottom, Glib::ustring labelBottom, unsigned int precisionBottom, double minValueTop, double maxValueTop, double defTop, Glib::ustring labelTop, unsigned int precisionTop, ThresholdCurveProvider* curveProvider) - : coloredBar(RTO_Left2Right) + : separatedLabelBottom(std::move(labelBottom)), separatedLabelTop(std::move(labelTop)), coloredBar(RTO_Left2Right) { positions[TS_BOTTOMLEFT] = defPos[TS_BOTTOMLEFT] = defBottom; positions[TS_TOPLEFT] = defPos[TS_TOPLEFT] = defTop; @@ -40,8 +40,6 @@ ThresholdSelector::ThresholdSelector(double minValueBottom, double maxValueBotto this->precisionBottom = precisionBottom; doubleThresh = false; - separatedLabelBottom = labelBottom; - separatedLabelTop = labelTop; bgCurveProvider = curveProvider; separatedSliders = true; @@ -66,9 +64,6 @@ ThresholdSelector::ThresholdSelector(double minValue, double maxValue, double de this->precisionBottom = precision; doubleThresh = false; - separatedLabelBottom = ""; - separatedLabelTop = ""; - #ifndef NDEBUG if (startAtOne) { @@ -106,9 +101,6 @@ ThresholdSelector::ThresholdSelector(double minValue, double maxValue, double de this->precisionBottom = precision; doubleThresh = true; - separatedLabelBottom = ""; - separatedLabelTop = ""; - #ifndef NDEBUG if (startAtOne) { @@ -329,14 +321,13 @@ void ThresholdSelector::updateBackBuffer() if (pts.size() >= 4) { std::vector::iterator i = pts.begin(); - double x = *i; ++i; double y = *i; ++i; cr->move_to (xStart, ih*y + yStart); for (; i < pts.end(); ) { - x = *i; + double x = *i; ++i; y = *i; ++i; @@ -638,13 +629,8 @@ void ThresholdSelector::findBoundaries(double &min, double &max) switch (movedCursor) { case (TS_BOTTOMLEFT): if (separatedSliders) { - if (movedCursor == TS_BOTTOMLEFT) { - min = minValBottom; - max = maxValBottom; - } else if (movedCursor == TS_TOPLEFT) { - min = minValTop; - max = maxValTop; - } + min = minValBottom; + max = maxValBottom; } else if (initalEq1) { min = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_TOPLEFT] : minValTop + (positions[TS_BOTTOMLEFT] - positions[TS_TOPLEFT]); max = positions[TS_BOTTOMRIGHT]; @@ -657,13 +643,8 @@ void ThresholdSelector::findBoundaries(double &min, double &max) case (TS_TOPLEFT): if (separatedSliders) { - if (movedCursor == TS_BOTTOMLEFT) { - min = minValBottom; - max = maxValBottom; - } else if (movedCursor == TS_TOPLEFT) { - min = minValTop; - max = maxValTop; - } + min = minValTop; + max = maxValTop; } else if (initalEq1) { min = minValTop; max = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_BOTTOMLEFT] : positions[TS_BOTTOMRIGHT] - (positions[TS_BOTTOMLEFT] - positions[TS_TOPLEFT]); diff --git a/rtgui/thresholdselector.h b/rtgui/thresholdselector.h index fff707959..6b9dda3d0 100644 --- a/rtgui/thresholdselector.h +++ b/rtgui/thresholdselector.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _THRESHOLDSELECTOR_ #define _THRESHOLDSELECTOR_ diff --git a/rtgui/thumbbrowserbase.cc b/rtgui/thumbbrowserbase.cc index 334f00e51..adf451f05 100644 --- a/rtgui/thumbbrowserbase.cc +++ b/rtgui/thumbbrowserbase.cc @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -28,7 +28,7 @@ using namespace std; ThumbBrowserBase::ThumbBrowserBase () - : location(THLOC_FILEBROWSER), inspector(nullptr), isInspectorActive(false), eventTime(0), lastClicked(nullptr), previewHeight(options.thumbSize), numOfCols(1), arrangement(TB_Horizontal) + : location(THLOC_FILEBROWSER), inspector(nullptr), isInspectorActive(false), eventTime(0), lastClicked(nullptr), anchor(nullptr), previewHeight(options.thumbSize), numOfCols(1), lastRowHeight(0), arrangement(TB_Horizontal) { inW = -1; inH = -1; @@ -44,6 +44,8 @@ ThumbBrowserBase::ThumbBrowserBase () show_all (); + vscroll.get_adjustment()->set_lower(0); + hscroll.get_adjustment()->set_lower(0); vscroll.signal_value_changed().connect( sigc::mem_fun(*this, &ThumbBrowserBase::scrollChanged) ); hscroll.signal_value_changed().connect( sigc::mem_fun(*this, &ThumbBrowserBase::scrollChanged) ); @@ -77,10 +79,19 @@ void ThumbBrowserBase::scroll (int direction, double deltaX, double deltaY) delta = deltaY; } if (direction == GDK_SCROLL_SMOOTH && delta == 0.0) { - // sometimes this case happens. To avoid scrolling the wrong direction in this case, we just do nothing + // sometimes this case happens. To avoid scrolling the wrong direction in this case, we just do nothing + // This is probably no longer necessary now that coef is no longer quantized to +/-1.0 but why waste CPU cycles? return; } - double coef = direction == GDK_SCROLL_DOWN || (direction == GDK_SCROLL_SMOOTH && delta > 0.0) ? +1.0 : -1.0; + //GDK_SCROLL_SMOOTH can come in as many events with small deltas, don't quantize these to +/-1.0 so trackpads work well + double coef; + if(direction == GDK_SCROLL_SMOOTH) { + coef = delta; + } else if (direction == GDK_SCROLL_DOWN) { + coef = +1.0; + } else { + coef = -1.0; + } // GUI already acquired when here if (direction == GDK_SCROLL_UP || direction == GDK_SCROLL_DOWN || direction == GDK_SCROLL_SMOOTH) { @@ -162,37 +173,42 @@ inline void removeFromSelection (const ThumbIterator& iterator, ThumbVector& sel void ThumbBrowserBase::selectSingle (ThumbBrowserEntryBase* clicked) { - clearSelection (selected); + clearSelection(selected); + anchor = clicked; - if (clicked) - addToSelection (clicked, selected); + if (clicked) { + addToSelection(clicked, selected); + } } void ThumbBrowserBase::selectRange (ThumbBrowserEntryBase* clicked, bool additional) { - if (selected.empty()) { - addToSelection(clicked, selected); - return; + if (!anchor) { + anchor = clicked; + if (selected.empty()) { + addToSelection(clicked, selected); + return; + } } if (!additional || !lastClicked) { // Extend the current range w.r.t to first selected entry. - ThumbIterator front = std::find(fd.begin(), fd.end(), selected.front()); - ThumbIterator current = std::find(fd.begin(), fd.end(), clicked); + ThumbIterator back = std::find(fd.begin(), fd.end(), clicked); + ThumbIterator front = anchor == clicked ? back : std::find(fd.begin(), fd.end(), anchor); - if (front > current) { - std::swap(front, current); + if (front > back) { + std::swap(front, back); } clearSelection(selected); - for (; front <= current && front != fd.end(); ++front) { + for (; front <= back && front != fd.end(); ++front) { addToSelection(*front, selected); } } else { // Add an additional range w.r.t. the last clicked entry. ThumbIterator last = std::find(fd.begin(), fd.end(), lastClicked); - ThumbIterator current = std::find (fd.begin(), fd.end(), clicked); + ThumbIterator current = std::find(fd.begin(), fd.end(), clicked); if (last > current) { std::swap(last, current); @@ -206,32 +222,33 @@ void ThumbBrowserBase::selectRange (ThumbBrowserEntryBase* clicked, bool additio void ThumbBrowserBase::selectSet (ThumbBrowserEntryBase* clicked) { - const ThumbIterator iterator = std::find (selected.begin (), selected.end (), clicked); + const ThumbIterator iterator = std::find(selected.begin(), selected.end(), clicked); - if (iterator != selected.end ()) { - removeFromSelection (iterator, selected); + if (iterator != selected.end()) { + removeFromSelection(iterator, selected); } else { - addToSelection (clicked, selected); + addToSelection(clicked, selected); } + anchor = clicked; } static void scrollToEntry (double& h, double& v, int iw, int ih, ThumbBrowserEntryBase* entry) { - const int hmin = entry->getX (); - const int hmax = hmin + entry->getEffectiveWidth () - iw; - const int vmin = entry->getY (); - const int vmax = vmin + entry->getEffectiveHeight () - ih; + const int hMin = entry->getX(); + const int hMax = hMin + entry->getEffectiveWidth() - iw; + const int vMin = entry->getY(); + const int vMax = vMin + entry->getEffectiveHeight() - ih; - if (hmin < 0) { - h += hmin; - } else if (hmax > 0) { - h += hmax; + if (hMin < 0) { + h += hMin; + } else if (hMax > 0) { + h += hMax; } - if(vmin < 0) { - v += vmin; - } else if (vmax > 0) { - v += vmax; + if (vMin < 0) { + v += vMin; + } else if (vMax > 0) { + v += vMax; } } @@ -534,28 +551,31 @@ void ThumbBrowserBase::configScrollBars () GThreadLock tLock; // Acquire the GUI if (inW > 0 && inH > 0) { - - int iw = internal.get_width (); - int ih = internal.get_height (); - - hscroll.get_adjustment()->set_upper (inW); - vscroll.get_adjustment()->set_upper (inH); - hscroll.get_adjustment()->set_lower (0); - vscroll.get_adjustment()->set_lower (0); - hscroll.get_adjustment()->set_step_increment (!fd.empty() ? fd[0]->getEffectiveHeight() : 0); - vscroll.get_adjustment()->set_step_increment (!fd.empty() ? fd[0]->getEffectiveHeight() : 0); - hscroll.get_adjustment()->set_page_increment (iw); - vscroll.get_adjustment()->set_page_increment (ih); - hscroll.get_adjustment()->set_page_size (iw); - vscroll.get_adjustment()->set_page_size (ih); - - if(iw >= inW) { - hscroll.hide(); + int ih = internal.get_height(); + if (arrangement == TB_Horizontal) { + auto ha = hscroll.get_adjustment(); + int iw = internal.get_width(); + ha->set_upper(inW); + ha->set_step_increment(!fd.empty() ? fd[0]->getEffectiveWidth() : 0); + ha->set_page_increment(iw); + ha->set_page_size(iw); + if (iw >= inW) { + hscroll.hide(); + } else { + hscroll.show(); + } } else { - hscroll.show(); + hscroll.hide(); } - if(ih >= inH) { + auto va = vscroll.get_adjustment(); + va->set_upper(inH); + const auto height = !fd.empty() ? fd[0]->getEffectiveHeight() : 0; + va->set_step_increment(height); + va->set_page_increment(height == 0 ? ih : (ih / height) * height); + va->set_page_size(ih); + + if (ih >= inH) { vscroll.hide(); } else { vscroll.show(); @@ -563,8 +583,22 @@ void ThumbBrowserBase::configScrollBars () } } -void ThumbBrowserBase::arrangeFiles() +void ThumbBrowserBase::arrangeFiles(ThumbBrowserEntryBase* entry) { + + if (fd.empty()) { + // nothing to arrange + resizeThumbnailArea(0, 0); + return; + } + if(entry && entry->filtered) { + // a filtered entry was added, nothing to arrange, but has to be marked not drawable + MYREADERLOCK(l, entryRW); + entry->drawable = false; + MYREADERLOCK_RELEASE(l); + return; + } + MYREADERLOCK(l, entryRW); // GUI already locked by ::redraw, the only caller of this method for now. @@ -572,14 +606,19 @@ void ThumbBrowserBase::arrangeFiles() //GThreadLock lock; int rowHeight = 0; + if (entry) { + // we got the reference to the added entry, makes calculation of rowHeight O(1) + lastRowHeight = rowHeight = std::max(lastRowHeight, entry->getMinimalHeight()); + } else { - for (unsigned int i = 0; i < fd.size(); i++) { - // apply filter - fd[i]->filtered = !checkFilter (fd[i]); - - // compute size of the items - if (!fd[i]->filtered && fd[i]->getMinimalHeight() > rowHeight) { - rowHeight = fd[i]->getMinimalHeight (); + lastRowHeight = 0; + for (const auto thumb : fd) { + // apply filter + thumb->filtered = !checkFilter(thumb); + // compute max rowHeight + if (!thumb->filtered) { + rowHeight = std::max(thumb->getMinimalHeight(), rowHeight); + } } } @@ -590,7 +629,6 @@ void ThumbBrowserBase::arrangeFiles() for (unsigned int ct = 0; ct < fd.size(); ++ct) { // arrange items in the column - int curry = 0; for (; ct < fd.size() && fd[ct]->filtered; ++ct) { fd[ct]->drawable = false; @@ -599,10 +637,9 @@ void ThumbBrowserBase::arrangeFiles() if (ct < fd.size()) { const int maxw = fd[ct]->getMinimalWidth(); - fd[ct]->setPosition(currx, curry, maxw, rowHeight); + fd[ct]->setPosition(currx, 0, maxw, rowHeight); fd[ct]->drawable = true; currx += maxw; - curry += rowHeight; } } @@ -613,14 +650,16 @@ void ThumbBrowserBase::arrangeFiles() const int availWidth = internal.get_width(); // initial number of columns + int oldNumOfCols = numOfCols; numOfCols = 0; int colsWidth = 0; for (unsigned int i = 0; i < fd.size(); ++i) { if (!fd[i]->filtered && colsWidth + fd[i]->getMinimalWidth() <= availWidth) { - colsWidth += fd[numOfCols]->getMinimalWidth(); + colsWidth += fd[i]->getMinimalWidth(); ++numOfCols; if(colsWidth > availWidth) { + --numOfCols; break; } } @@ -656,8 +695,73 @@ void ThumbBrowserBase::arrangeFiles() // arrange files int curry = 0; + size_t ct = 0; + if (entry) { + std::vector oldColWidths; + if (oldNumOfCols == numOfCols) { + for (; oldNumOfCols > 0; --oldNumOfCols) { + // compute old column widths + oldColWidths.assign(oldNumOfCols, 0); + + for (unsigned int i = 0, j = 0; i < fd.size(); ++i) { + if (fd[i] != entry && !fd[i]->filtered && fd[i]->getMinimalWidth() > oldColWidths[j % oldNumOfCols]) { + oldColWidths[j % oldNumOfCols] = fd[i]->getMinimalWidth(); + } + + if (fd[i] != entry && !fd[i]->filtered) { + ++j; + } + } + if (oldNumOfCols == 1 || std::accumulate(oldColWidths.begin(), oldColWidths.end(), 0) < availWidth) { + break; + } + } + } + + bool arrangeAll = true; + if (oldNumOfCols == numOfCols) { + arrangeAll = false; + for (int i = 0; i < numOfCols; ++i) { + if(colWidths[i] != oldColWidths[i]) { + arrangeAll = true; + break; + } + } + } + if (!arrangeAll) { + int j = 0; + // Find currently added entry + for (; ct < fd.size() && fd[ct] != entry; j += !fd[ct]->filtered, ++ct) { + } + //Calculate the position of currently added entry + const int row = j / numOfCols; + const int col = j % numOfCols; + curry = row * rowHeight; + int currx = 0; + for (int c = 0; c < col; ++c) { + currx += colWidths[c]; + } + // arrange all entries in the row beginning with the currently added one + for (int i = col; ct < fd.size() && i < numOfCols; ++i, ++ct) { + for (; ct < fd.size() && fd[ct]->filtered; ++ct) { + fd[ct]->drawable = false; + } + if (ct < fd.size()) { + fd[ct]->setPosition(currx, curry, colWidths[i], rowHeight); + fd[ct]->drawable = true; + currx += colWidths[i]; + } + } + + if (currx > 0) { // there were thumbnails placed in the row + curry += rowHeight; + } + } + } + + // arrange remaining entries, if any, that's the most expensive part + for (; ct < fd.size();) { - for (unsigned int ct = 0; ct < fd.size();) { // arrange items in the row int currx = 0; @@ -667,9 +771,9 @@ void ThumbBrowserBase::arrangeFiles() } if (ct < fd.size()) { - fd[ct]->setPosition(currx, curry, colWidths[i % numOfCols], rowHeight); + fd[ct]->setPosition(currx, curry, colWidths[i], rowHeight); fd[ct]->drawable = true; - currx += colWidths[i % numOfCols]; + currx += colWidths[i]; } } @@ -680,7 +784,7 @@ void ThumbBrowserBase::arrangeFiles() MYREADERLOCK_RELEASE(l); // This will require a Writer access - resizeThumbnailArea (colsWidth, curry); + resizeThumbnailArea(colsWidth, curry); } } @@ -736,20 +840,24 @@ void ThumbBrowserBase::Internal::on_realize() bool ThumbBrowserBase::Internal::on_query_tooltip (int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) { // Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave) - Glib::ustring ttip = ""; - + Glib::ustring ttip; + bool useMarkup = false; { MYREADERLOCK(l, parent->entryRW); for (size_t i = 0; i < parent->fd.size(); i++) if (parent->fd[i]->drawable && parent->fd[i]->inside (x, y)) { - ttip = parent->fd[i]->getToolTip (x, y); + std::tie(ttip, useMarkup) = parent->fd[i]->getToolTip (x, y); break; } } - if (ttip != "") { - tooltip->set_markup (ttip); + if (!ttip.empty()) { + if (useMarkup) { + tooltip->set_markup(ttip); + } else { + tooltip->set_text(ttip); + } return true; } else { return false; @@ -764,7 +872,6 @@ void ThumbBrowserBase::on_style_updated () ThumbBrowserBase::Internal::Internal () : ofsX(0), ofsY(0), parent(nullptr), dirty(true) { - Glib::RefPtr style = get_style_context(); set_name("FileCatalog"); } @@ -970,12 +1077,12 @@ bool ThumbBrowserBase::Internal::on_scroll_event (GdkEventScroll* event) } -void ThumbBrowserBase::redraw () +void ThumbBrowserBase::redraw (ThumbBrowserEntryBase* entry) { GThreadLock lock; - arrangeFiles (); - queue_draw (); + arrangeFiles(entry); + queue_draw(); } void ThumbBrowserBase::zoomChanged (bool zoomIn) diff --git a/rtgui/thumbbrowserbase.h b/rtgui/thumbbrowserbase.h index dcda30f92..890c37c87 100644 --- a/rtgui/thumbbrowserbase.h +++ b/rtgui/thumbbrowserbase.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _THUMBNAILBROWSERBASE_ #define _THUMBNAILBROWSERBASE_ @@ -171,15 +171,17 @@ protected: std::vector fd; std::vector selected; ThumbBrowserEntryBase* lastClicked; + ThumbBrowserEntryBase* anchor; int previewHeight; int numOfCols; + int lastRowHeight; Arrangement arrangement; std::set editedFiles; - void arrangeFiles (); + void arrangeFiles (ThumbBrowserEntryBase* entry = nullptr); void zoomChanged (bool zoomIn); public: @@ -201,7 +203,7 @@ public: return fd; } void on_style_updated () override; - void redraw (); // arrange files and draw area + void redraw (ThumbBrowserEntryBase* entry = nullptr); // arrange files and draw area void refreshThumbImages (); // refresh thumbnail sizes, re-generate thumbnail images, arrange and draw void refreshQuickThumbImages (); // refresh thumbnail sizes, re-generate thumbnail images, arrange and draw void refreshEditedState (const std::set& efiles); @@ -214,7 +216,7 @@ public: void setArrangement (Arrangement a); void enableTabMode(bool enable); // set both thumb sizes and arrangements - virtual bool checkFilter (ThumbBrowserEntryBase* entry) + virtual bool checkFilter (ThumbBrowserEntryBase* entry) const { return true; } diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index ed34c65c7..9d74fbd79 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "thumbbrowserentrybase.h" @@ -157,9 +157,6 @@ ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname) : collate_name(getPaddedName(dispname).casefold_collate_key()), thumbnail(nullptr), filename(fname), - shortname(dispname), - exifline(""), - datetimeline(""), selected(false), drawable(false), filtered(false), @@ -404,7 +401,7 @@ void ThumbBrowserEntryBase::updateBackBuffer () // draw date/time label int tpos = fnlabh; - if (options.fbShowDateTime && datetimeline != "") { + if (options.fbShowDateTime && !datetimeline.empty()) { fn = w->create_pango_layout (datetimeline); fn->set_width (textw * Pango::SCALE); fn->set_ellipsize (Pango::ELLIPSIZE_MIDDLE); @@ -415,7 +412,7 @@ void ThumbBrowserEntryBase::updateBackBuffer () } // draw basic exif info - if (options.fbShowBasicExif && exifline != "") { + if (options.fbShowBasicExif && !exifline.empty()) { fn = w->create_pango_layout (exifline); fn->set_width (textw * Pango::SCALE); fn->set_ellipsize (Pango::ELLIPSIZE_MIDDLE); @@ -439,7 +436,6 @@ void ThumbBrowserEntryBase::getTextSizes (int& infow, int& infoh) Gtk::Widget* w = parent->getDrawingArea (); // calculate dimensions of the text based fields - dispname = shortname; Glib::RefPtr context = w->get_pango_context () ; context->set_font_description (w->get_style_context()->get_font()); @@ -449,7 +445,7 @@ void ThumbBrowserEntryBase::getTextSizes (int& infow, int& infoh) Pango::FontDescription fontd = context->get_font_description (); fontd.set_weight (Pango::WEIGHT_BOLD); context->set_font_description (fontd); - Glib::RefPtr fn = w->create_pango_layout(shortname); + Glib::RefPtr fn = w->create_pango_layout(dispname); fn->get_pixel_size (fnlabw, fnlabh); // calculate cummulated height of all info fields @@ -498,6 +494,7 @@ void ThumbBrowserEntryBase::resize (int h) height = h; int old_preh = preh; + int old_prew = prew; // dimensions of the button set int bsw = 0, bsh = 0; @@ -559,9 +556,11 @@ void ThumbBrowserEntryBase::resize (int h) width = bsw + 2 * sideMargin + 2 * borderWidth; } - if (preh != old_preh) { - delete [] preview; - preview = nullptr; + if (preh != old_preh || prew != old_prew) { // if new thumbnail height or new orientation + if (preview) { + delete [] preview; + preview = nullptr; + } refreshThumbnailImage (); } else if (backBuffer) { backBuffer->setDirty(true); // This will force a backBuffer update on queue_draw @@ -672,16 +671,15 @@ void ThumbBrowserEntryBase::setOffset (int x, int y) } } -bool ThumbBrowserEntryBase::inside (int x, int y) +bool ThumbBrowserEntryBase::inside (int x, int y) const { return x > ofsX + startx && x < ofsX + startx + exp_width && y > ofsY + starty && y < ofsY + starty + exp_height; } -void ThumbBrowserEntryBase::getPosInImgSpace (int x, int y, rtengine::Coord2D &coord) +rtengine::Coord2D ThumbBrowserEntryBase::getPosInImgSpace (int x, int y) const { - - coord.x = coord.y = -1.; + rtengine::Coord2D coord(-1., -1.); if (preview) { x -= ofsX + startx; @@ -692,15 +690,16 @@ void ThumbBrowserEntryBase::getPosInImgSpace (int x, int y, rtengine::Coord2D &c coord.y = double(y - prey) / double(preh); } } + return coord; } -bool ThumbBrowserEntryBase::insideWindow (int x, int y, int w, int h) +bool ThumbBrowserEntryBase::insideWindow (int x, int y, int w, int h) const { return !(ofsX + startx > x + w || ofsX + startx + exp_width < x || ofsY + starty > y + h || ofsY + starty + exp_height < y); } -std::vector > ThumbBrowserEntryBase::getIconsOnImageArea() +std::vector> ThumbBrowserEntryBase::getIconsOnImageArea() { return std::vector >(); } @@ -710,12 +709,6 @@ std::vector > ThumbBrowserEntryBase::getSpecificityIco return std::vector >(); } -void ThumbBrowserEntryBase::getIconSize(int& w, int& h) -{ - w = 0; - h = 0; -} - bool ThumbBrowserEntryBase::motionNotify (int x, int y) { @@ -734,31 +727,32 @@ bool ThumbBrowserEntryBase::releaseNotify (int button, int type, int bstate, int return buttonSet ? buttonSet->releaseNotify (x, y) : false; } -Glib::ustring ThumbBrowserEntryBase::getToolTip (int x, int y) +std::tuple ThumbBrowserEntryBase::getToolTip (int x, int y) const { - Glib::ustring tooltip = ""; + Glib::ustring tooltip; if (buttonSet) { - tooltip = buttonSet->getToolTip (x, y); + tooltip = buttonSet->getToolTip(x, y); } // Always show the filename in the tooltip since the filename in the thumbnail could be truncated. // If "Show Exif info" is disabled, also show Exif info in the tooltip. + bool useMarkup = !tooltip.empty(); if (inside(x, y) && tooltip.empty()) { tooltip = dispname; if (withFilename < WFNAME_FULL) { - if (options.fbShowDateTime && datetimeline != "") { + if (options.fbShowDateTime && !datetimeline.empty()) { tooltip += Glib::ustring("\n") + datetimeline; } - if (options.fbShowBasicExif && exifline != "") { + if (options.fbShowBasicExif && !exifline.empty()) { tooltip += Glib::ustring("\n") + exifline; } } } - return tooltip; + return std::make_tuple(std::move(tooltip), useMarkup); } diff --git a/rtgui/thumbbrowserentrybase.h b/rtgui/thumbbrowserentrybase.h index 8237b7c6b..5f018eefd 100644 --- a/rtgui/thumbbrowserentrybase.h +++ b/rtgui/thumbbrowserentrybase.h @@ -14,13 +14,12 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ -#ifndef _THUMBNAILBROWSERENTRYBASE_ -#define _THUMBNAILBROWSERENTRYBASE_ +#pragma once #include - +#include #include #include "cursormanager.h" @@ -82,8 +81,8 @@ protected: Glib::RefPtr backBuffer; bool bbSelected, bbFramed; guint8* bbPreview; - std::vector > bbIcons; - std::vector > bbSpecificityIcons; + std::vector> bbIcons; + std::vector> bbSpecificityIcons; CursorShape cursor_type; void drawFrame (Cairo::RefPtr cr, const Gdk::RGBA& bg, const Gdk::RGBA& fg); @@ -101,7 +100,6 @@ public: // thumbnail preview properties: Glib::ustring filename; - Glib::ustring shortname; Glib::ustring exifline; Glib::ustring datetimeline; @@ -117,61 +115,61 @@ public: bool updatepriority; eWithFilename withFilename; - explicit ThumbBrowserEntryBase (const Glib::ustring& fname); - virtual ~ThumbBrowserEntryBase (); + explicit ThumbBrowserEntryBase (const Glib::ustring& fname); + virtual ~ThumbBrowserEntryBase (); void setParent (ThumbBrowserBase* l) { parent = l; } - void updateBackBuffer (); - void resize (int h); - virtual void draw (Cairo::RefPtr cc); + void updateBackBuffer (); + void resize (int h); + virtual void draw (Cairo::RefPtr cc); - void addButtonSet (LWButtonSet* bs); - int getMinimalHeight () + void addButtonSet (LWButtonSet* bs); + int getMinimalHeight () const { return height; } - int getMinimalWidth () + int getMinimalWidth () const { return width; } - int getEffectiveWidth () const + int getEffectiveWidth () const { return exp_width; } - int getEffectiveHeight () const + int getEffectiveHeight () const { return exp_height; } - int getPreviewHeight () const + int getPreviewHeight () const { return preh; } - int getStartX () const + int getStartX () const { return startx; } - int getStartY () const + int getStartY () const { return starty; } - int getX () const + int getX () const { return ofsX + startx; } - int getY () const + int getY () const { return ofsY + starty; } - bool inside (int x, int y); - void getPosInImgSpace (int x, int y, rtengine::Coord2D &coord); - bool insideWindow (int x, int y, int w, int h); - void setPosition (int x, int y, int w, int h); + bool inside (int x, int y) const; + rtengine::Coord2D getPosInImgSpace (int x, int y) const; + bool insideWindow (int x, int y, int w, int h) const; + void setPosition (int x, int y, int w, int h); void setOffset (int x, int y); bool operator <(const ThumbBrowserEntryBase& other) const @@ -179,33 +177,29 @@ public: return collate_name < other.collate_name; } - ThumbBrowserEntryBase* getOriginal () const; - void setOriginal (ThumbBrowserEntryBase* original); - - virtual void refreshThumbnailImage () {} + virtual void refreshThumbnailImage () = 0; virtual void refreshQuickThumbnailImage () {} - virtual void calcThumbnailSize () {} + virtual void calcThumbnailSize () = 0; virtual void drawProgressBar (Glib::RefPtr win, const Gdk::RGBA& foregr, const Gdk::RGBA& backgr, int x, int w, int y, int h) {} - virtual std::vector > getIconsOnImageArea (); - virtual std::vector > getSpecificityIconsOnImageArea (); - virtual void getIconSize (int& w, int& h); + virtual std::vector> getIconsOnImageArea (); + virtual std::vector> getSpecificityIconsOnImageArea (); + virtual void getIconSize (int& w, int& h) const = 0; + + virtual bool motionNotify (int x, int y); + virtual bool pressNotify (int button, int type, int bstate, int x, int y); + virtual bool releaseNotify (int button, int type, int bstate, int x, int y); + virtual std::tuple getToolTip (int x, int y) const; + + inline ThumbBrowserEntryBase* getOriginal() const + { + return original; + } + + inline void setOriginal(ThumbBrowserEntryBase* original) + { + this->original = original; + } - virtual bool motionNotify (int x, int y); - virtual bool pressNotify (int button, int type, int bstate, int x, int y); - virtual bool releaseNotify (int button, int type, int bstate, int x, int y); - virtual Glib::ustring getToolTip (int x, int y); }; - -inline ThumbBrowserEntryBase* ThumbBrowserEntryBase::getOriginal() const -{ - return original; -} - -inline void ThumbBrowserEntryBase::setOriginal(ThumbBrowserEntryBase* original) -{ - this->original = original; -} - -#endif diff --git a/rtgui/thumbimageupdater.cc b/rtgui/thumbimageupdater.cc index c0df751a5..182eba704 100644 --- a/rtgui/thumbimageupdater.cc +++ b/rtgui/thumbimageupdater.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include diff --git a/rtgui/thumbimageupdater.h b/rtgui/thumbimageupdater.h index a3be44d7c..0e46b11d7 100644 --- a/rtgui/thumbimageupdater.h +++ b/rtgui/thumbimageupdater.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _THUMBIMAGEUPDATER_ #define _THUMBIMAGEUPDATER_ diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index ba335d215..e62fccea4 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -13,7 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -182,9 +182,9 @@ void Thumbnail::_generateThumbnailImage () imgRatio = -1.; // generate thumbnail image - Glib::ustring ext = getExtension (fname); + const std::string ext = getExtension(fname).lowercase(); - if (ext == "") { + if (ext.empty()) { return; } @@ -192,20 +192,20 @@ void Thumbnail::_generateThumbnailImage () cfs.exifValid = false; cfs.timeValid = false; - if (ext.lowercase() == "jpg" || ext.lowercase() == "jpeg") { + if (ext == "jpg" || ext == "jpeg") { infoFromImage (fname); tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams->wb.equal); if (tpp) { cfs.format = FT_Jpeg; } - } else if (ext.lowercase() == "png") { + } else if (ext == "png") { tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams->wb.equal); if (tpp) { cfs.format = FT_Png; } - } else if (ext.lowercase() == "tif" || ext.lowercase() == "tiff") { + } else if (ext == "tif" || ext == "tiff") { infoFromImage (fname); tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams->wb.equal); @@ -295,9 +295,6 @@ const ProcParams& Thumbnail::getProcParamsU () */ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool returnParams, bool force, bool flaggingMode) { - - static int index = 0; // Will act as unique identifier during the session - // try to load the last saved parameters from the cache or from the paramfile file ProcParams* ldprof = nullptr; @@ -306,7 +303,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu const CacheImageData* cfs = getCacheImageData(); Glib::ustring defaultPparamsPath = options.findProfilePath(defProf); const bool create = (!hasProcParams() || force); - const bool run_cpb = false; + const bool run_cpb = !options.CPBPath.empty() && !defaultPparamsPath.empty() && cfs && cfs->exifValid && create; const Glib::ustring outFName = (options.paramsLoadLocation == PLL_Input && options.saveParamsFile) ? @@ -315,12 +312,12 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu if (!run_cpb) { if (defProf == DEFPROFILE_DYNAMIC && create && cfs && cfs->exifValid) { - const auto pp_deleter = - [](PartialProfile* pp) - { - pp->deleteInstance(); - delete pp; - }; + const auto pp_deleter = + [](PartialProfile* pp) + { + pp->deleteInstance(); + delete pp; + }; const std::unique_ptr imageMetaData(rtengine::FramesMetaData::fromFile(fname)); const std::unique_ptr pp( imageMetaData @@ -339,6 +336,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu } } else { // First generate the communication file, with general values and EXIF metadata + static int index = 0; // Will act as unique identifier during the session Glib::ustring tmpFileName( Glib::build_filename(options.cacheBaseDir, Glib::ustring::compose("CPB_temp_%1.txt", index++)) ); CPBDump(tmpFileName, fname, outFName, @@ -446,6 +444,7 @@ void Thumbnail::clearProcParams (int whoClearedIt) // and restore rank and inTrash setRank(rank); + pparamsValid = cfs.rating != rank; setColorLabel(colorlabel); setStage(inTrash); @@ -520,6 +519,7 @@ void Thumbnail::setProcParams (const ProcParams& pp, ParamsEdited* pe, int whoCh || pparams->filmSimulation != pp.filmSimulation || pparams->softlight != pp.softlight || pparams->dehaze != pp.dehaze + || pparams->filmNegative != pp.filmNegative || whoChangedIt == FILEBROWSER || whoChangedIt == BATCHEDITOR; @@ -763,7 +763,7 @@ void Thumbnail::generateExifDateTimeStrings () exifString = Glib::ustring::compose ("f/%1 %2s %3%4 %5mm", Glib::ustring(rtengine::FramesData::apertureToString(cfs.fnumber)), Glib::ustring(rtengine::FramesData::shutterToString(cfs.shutter)), M("QINFO_ISO"), cfs.iso, Glib::ustring::format(std::setw(3), std::fixed, std::setprecision(2), cfs.focalLen)); - if (options.fbShowExpComp && cfs.expcomp != "0.00" && cfs.expcomp != "") { // don't show exposure compensation if it is 0.00EV;old cache iles do not have ExpComp, so value will not be displayed. + if (options.fbShowExpComp && cfs.expcomp != "0.00" && !cfs.expcomp.empty()) { // don't show exposure compensation if it is 0.00EV;old cache files do not have ExpComp, so value will not be displayed. exifString = Glib::ustring::compose ("%1 %2EV", exifString, cfs.expcomp); // append exposure compensation to exifString } @@ -860,6 +860,7 @@ int Thumbnail::infoFromImage (const Glib::ustring& fname) cfs.lens = idata->getLens(); cfs.camMake = idata->getMake(); cfs.camModel = idata->getModel(); + cfs.rating = idata->getRating(); if (idata->getOrientation() == "Rotate 90 CW") { deg = 90; @@ -1052,15 +1053,20 @@ void Thumbnail::setFileName (const Glib::ustring &fn) int Thumbnail::getRank () const { - return pparams->rank; + // prefer the user-set rank over the embedded Rating + // pparams->rank == -1 means that there is no saved rank yet, so we should + // next look for the embedded Rating metadata. + if (pparams->rank != -1) { + return pparams->rank; + } else { + return cfs.rating; + } } void Thumbnail::setRank (int rank) { - if (pparams->rank != rank) { - pparams->rank = rank; - pparamsValid = true; - } + pparams->rank = rank; + pparamsValid = true; } int Thumbnail::getColorLabel () const diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index 33bccbf81..db7266468 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _THUMBNAIL_ #define _THUMBNAIL_ @@ -49,17 +49,17 @@ class Thumbnail rtengine::Thumbnail* tpp; int tw, th; // dimensions of timgdata (it stores tpp->width and tpp->height in processed mode for simplicity) float imgRatio; // hack to avoid rounding error -// double scale; // portion of the sizes of the processed thumbnail image and the full scale image +// double scale; // portion of the sizes of the processed thumbnail image and the full scale image const std::unique_ptr pparams; bool pparamsValid; bool imageLoading; // these are the data of the result image of the last getthumbnailimage call (for caching purposes) - unsigned char* lastImg; - int lastW; - int lastH; - double lastScale; + unsigned char* lastImg; // pointer to the processed and scaled base ImageIO image + int lastW; // non rotated width of the cached ImageIO image + int lastH; // non rotated height of the cached ImageIO image + double lastScale; // scale of the cached ImageIO image // exif & date/time strings Glib::ustring exifString; diff --git a/rtgui/thumbnailbrowser.h b/rtgui/thumbnailbrowser.h index 0c2d6ebab..9d40d1f7d 100644 --- a/rtgui/thumbnailbrowser.h +++ b/rtgui/thumbnailbrowser.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _THUMBNAILBROWSER_ #define _THUMBNAILBROWSER_ diff --git a/rtgui/thumbnaillistener.h b/rtgui/thumbnaillistener.h index 99a9a9286..97503c420 100644 --- a/rtgui/thumbnaillistener.h +++ b/rtgui/thumbnaillistener.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _THUMBNAILLISTENER_ #define _THUMBNAILLISTENER_ diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc index 91b268e9c..fa1c80ed8 100644 --- a/rtgui/tonecurve.cc +++ b/rtgui/tonecurve.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -645,10 +645,6 @@ void ToneCurve::adjusterChanged(Adjuster* a, double newval) } } -void ToneCurve::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void ToneCurve::neutral_pressed () { // This method deselects auto levels and HL reconstruction auto diff --git a/rtgui/tonecurve.h b/rtgui/tonecurve.h index 29b484137..fb08c02c2 100644 --- a/rtgui/tonecurve.h +++ b/rtgui/tonecurve.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _TONECURVE_H_ #define _TONECURVE_H_ @@ -104,7 +104,6 @@ public: float blendPipetteValues (CurveEditor *ce, float chan1, float chan2, float chan3) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void neutral_pressed (); void autolevels_toggled (); void clip_changed (); diff --git a/rtgui/toolbar.cc b/rtgui/toolbar.cc index 9bed78768..b8e0d64dc 100644 --- a/rtgui/toolbar.cc +++ b/rtgui/toolbar.cc @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "toolbar.h" #include "multilangmgr.h" diff --git a/rtgui/toolbar.h b/rtgui/toolbar.h index 2d859eac7..52f4dcbd4 100644 --- a/rtgui/toolbar.h +++ b/rtgui/toolbar.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __TOOLBAR_H__ #define __TOOLBAR_H__ diff --git a/rtgui/toolenum.h b/rtgui/toolenum.h index 85a7b954a..e90a0f685 100644 --- a/rtgui/toolenum.h +++ b/rtgui/toolenum.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _TOOLENUM_ #define _TOOLENUM_ diff --git a/rtgui/toolpanel.cc b/rtgui/toolpanel.cc index 1fe9808cd..27f68767e 100644 --- a/rtgui/toolpanel.cc +++ b/rtgui/toolpanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "toolpanel.h" #include "toolpanelcoord.h" diff --git a/rtgui/toolpanel.h b/rtgui/toolpanel.h index 2da5f1bba..8d4a55eab 100644 --- a/rtgui/toolpanel.h +++ b/rtgui/toolpanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __TOOLPANEL__ #define __TOOLPANEL__ @@ -26,6 +26,7 @@ #include "guiutils.h" #include "multilangmgr.h" #include "paramsedited.h" +#include "../rtengine/noncopyable.h" class ToolPanel; class FoldableToolPanel; @@ -51,7 +52,7 @@ public: ToolParamBlock(); }; -class ToolPanel +class ToolPanel : public rtengine::NonCopyable { protected: diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 41e25387e..4fec4a18a 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "multilangmgr.h" #include "toolpanelcoord.h" @@ -92,7 +92,8 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit bayerrawexposure = Gtk::manage (new BayerRAWExposure ()); xtransrawexposure = Gtk::manage (new XTransRAWExposure ()); fattal = Gtk::manage (new FattalToneMapping ()); - + filmNegative = Gtk::manage (new FilmNegative ()); + pdSharpening = Gtk::manage (new PdSharpening()); // So Demosaic, Line noise filter, Green Equilibration, Ca-Correction (garder le nom de section identique!) and Black-Level will be moved in a "Bayer sensor" tool, // and a separate Demosaic and Black Level tool will be created in an "X-Trans sensor" tool @@ -154,6 +155,8 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit addfavoritePanel (rawPanel, preprocess); addfavoritePanel (rawPanel, darkframe); addfavoritePanel (rawPanel, flatfield); + addfavoritePanel (rawPanel, filmNegative); + addfavoritePanel (rawPanel, pdSharpening); int favoriteCount = 0; for(auto it = favorites.begin(); it != favorites.end(); ++it) { @@ -255,6 +258,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit distortion->setLensGeomListener (this); crop->setCropPanelListener (this); icm->setICMPanelListener (this); + filmNegative->setFilmNegProvider (this); toolBar = new ToolBar (); toolBar->setToolBarListener (this); @@ -305,6 +309,8 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt sensorbayer->FoldableToolPanel::show(); preprocess->FoldableToolPanel::show(); flatfield->FoldableToolPanel::show(); + filmNegative->FoldableToolPanel::show(); + pdSharpening->FoldableToolPanel::show(); retinex->FoldableToolPanel::setGrayedOut(false); return false; @@ -320,6 +326,8 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt sensorbayer->FoldableToolPanel::hide(); preprocess->FoldableToolPanel::show(); flatfield->FoldableToolPanel::show(); + filmNegative->FoldableToolPanel::show(); + pdSharpening->FoldableToolPanel::show(); retinex->FoldableToolPanel::setGrayedOut(false); return false; @@ -335,6 +343,8 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt sensorxtrans->FoldableToolPanel::hide(); preprocess->FoldableToolPanel::hide(); flatfield->FoldableToolPanel::show(); + filmNegative->FoldableToolPanel::hide(); + pdSharpening->FoldableToolPanel::show(); retinex->FoldableToolPanel::setGrayedOut(false); return false; @@ -349,6 +359,8 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt sensorxtrans->FoldableToolPanel::hide(); preprocess->FoldableToolPanel::hide(); flatfield->FoldableToolPanel::hide(); + filmNegative->FoldableToolPanel::hide(); + pdSharpening->FoldableToolPanel::hide(); retinex->FoldableToolPanel::setGrayedOut(false); return false; @@ -360,6 +372,8 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt [this]() -> bool { rawPanelSW->set_sensitive(false); + filmNegative->FoldableToolPanel::hide(); + pdSharpening->FoldableToolPanel::hide(); retinex->FoldableToolPanel::setGrayedOut(true); return false; @@ -476,7 +490,7 @@ void ToolPanelCoordinator::profileChange( lParams[1] = *mergedParams; pe.initFrom (lParams); - filterRawRefresh = pe.raw.isUnchanged() && pe.lensProf.isUnchanged() && pe.retinex.isUnchanged(); + filterRawRefresh = pe.raw.isUnchanged() && pe.lensProf.isUnchanged() && pe.retinex.isUnchanged() && pe.filmNegative.isUnchanged() && pe.pdsharpening.isUnchanged(); } *params = *mergedParams; @@ -558,6 +572,8 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool ipc->setFlatFieldAutoClipListener (flatfield); ipc->setBayerAutoContrastListener (bayerprocess); ipc->setXtransAutoContrastListener (xtransprocess); + ipc->setpdSharpenAutoContrastListener (pdSharpening); + ipc->setpdSharpenAutoRadiusListener (pdSharpening); ipc->setAutoWBListener (whitebalance); ipc->setAutoColorTonListener (colortoning); ipc->setAutoChromaListener (dirpyrdenoise); @@ -681,8 +697,7 @@ void ToolPanelCoordinator::sharpMaskSelected(bool sharpMask) return; } ipc->beginUpdateParams (); - ipc->setSharpMask(sharpMask); - ipc->endUpdateParams (rtengine::EvShrEnabled); + ipc->endUpdateParams (ipc->setSharpMask(sharpMask)); } int ToolPanelCoordinator::getSpotWBRectSize() const @@ -914,7 +929,7 @@ bool ToolPanelCoordinator::handleShortcutKey (GdkEventKey* event) toolPanelNotebook->set_current_page (toolPanelNotebook->page_num (*rawPanelSW)); return true; - case GDK_KEY_w: + case GDK_KEY_a: toolPanelNotebook->set_current_page (toolPanelNotebook->page_num (*advancedPanelSW)); return true; @@ -1014,3 +1029,8 @@ void ToolPanelCoordinator::setEditProvider (EditDataProvider *provider) toolPanels.at (i)->setEditProvider (provider); } } + +bool ToolPanelCoordinator::getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, std::array& newExps) +{ + return ipc && ipc->getFilmNegativeExponents(spotA.x, spotA.y, spotB.x, spotB.y, newExps); +} diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 1ac74871a..3a4ddc05f 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef __TOOLPANELCCORD__ #define __TOOLPANELCCORD__ @@ -77,11 +77,14 @@ #include "colortoning.h" #include "filmsimulation.h" #include "prsharpening.h" +#include "pdsharpening.h" #include "fattaltonemap.h" #include "localcontrast.h" #include "softlight.h" #include "dehaze.h" #include "guiutils.h" +#include "filmnegative.h" +#include "../rtengine/noncopyable.h" class ImageEditorCoordinator; @@ -97,7 +100,9 @@ class ToolPanelCoordinator : public CropPanelListener, public ICMPanelListener, public ImageAreaToolListener, - public rtengine::ImageTypeListener + public rtengine::ImageTypeListener, + public FilmNegProvider, + public rtengine::NonCopyable { protected: WhiteBalance* whitebalance; @@ -152,7 +157,8 @@ protected: XTransRAWExposure* xtransrawexposure; FattalToneMapping *fattal; MetaDataPanel* metadata; - + FilmNegative* filmNegative; + PdSharpening* pdSharpening; std::vector paramcListeners; rtengine::StagedImageProcessor* ipc; @@ -236,7 +242,6 @@ public: void imageTypeChanged (bool isRaw, bool isBayer, bool isXtrans, bool isMono = false) override; -// void autoContrastChanged (double autoContrast); // profilechangelistener interface void profileChange( const rtengine::procparams::PartialProfile* nparams, @@ -288,6 +293,9 @@ public: rtengine::RawImage* getFF() override; Glib::ustring GetCurrentImageFilePath() override; + // FilmNegProvider interface + bool getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, std::array& newExps) override; + // rotatelistener interface void straightenRequested () override; void autoCropRequested () override; diff --git a/rtgui/vibrance.cc b/rtgui/vibrance.cc index 0069576e0..461c4a79f 100644 --- a/rtgui/vibrance.cc +++ b/rtgui/vibrance.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "vibrance.h" @@ -290,10 +290,6 @@ void Vibrance::adjusterChanged(Adjuster* a, double newval) } } -void Vibrance::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void Vibrance::adjusterChanged(ThresholdAdjuster* a, double newBottom, double newTop) { } diff --git a/rtgui/vibrance.h b/rtgui/vibrance.h index ed3e10059..606bfa80a 100644 --- a/rtgui/vibrance.h +++ b/rtgui/vibrance.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _VIBRANCE_ #define _VIBRANCE_ @@ -61,7 +61,6 @@ public: void trimValues (rtengine::procparams::ProcParams* pp) override; void setAdjusterBehavior (bool pastelsadd, bool saturatedadd); void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled (Adjuster* a, bool newval) override; void curveChanged () override; void autoOpenCurve () override; diff --git a/rtgui/vignetting.cc b/rtgui/vignetting.cc index 799a4cff7..04a350b99 100644 --- a/rtgui/vignetting.cc +++ b/rtgui/vignetting.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "vignetting.h" @@ -129,10 +129,6 @@ void Vignetting::adjusterChanged(Adjuster* a, double newval) } } -void Vignetting::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void Vignetting::setAdjusterBehavior (bool amountadd, bool radiusadd, bool strengthadd, bool centeradd) { diff --git a/rtgui/vignetting.h b/rtgui/vignetting.h index 5432b6178..094869f67 100644 --- a/rtgui/vignetting.h +++ b/rtgui/vignetting.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _VIGNETTING_H_ #define _VIGNETTING_H_ @@ -43,7 +43,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged(Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void setAdjusterBehavior (bool amountadd, bool radiusadd, bool strengthadd, bool centeradd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 942608414..94f96e0cc 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * 2014 Jacques Desmis */ @@ -2513,10 +2513,6 @@ void Wavelet::adjusterChanged(Adjuster* a, double newval) } } -void Wavelet::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void Wavelet::enabledUpdateUI () { if (!batchMode) { diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h index 90a72f623..feec85fc9 100644 --- a/rtgui/wavelet.h +++ b/rtgui/wavelet.h @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . * * 2014 Jacques Desmis */ @@ -46,7 +46,6 @@ public: bool wavComputed_ (); void adjusterChanged(Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; void autoOpenCurve () override; void curveChanged (CurveEditor* ce) override; void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; diff --git a/rtgui/wbprovider.h b/rtgui/wbprovider.h index df1329c84..31ba8331a 100644 --- a/rtgui/wbprovider.h +++ b/rtgui/wbprovider.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _WBPROVIDER_ #define _WBPROVIDER_ diff --git a/rtgui/whitebalance.cc b/rtgui/whitebalance.cc index 3c3382bc3..109fb7502 100644 --- a/rtgui/whitebalance.cc +++ b/rtgui/whitebalance.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "whitebalance.h" @@ -382,7 +382,6 @@ void WhiteBalance::adjusterChanged(Adjuster* a, double newval) return; } - Glib::ustring colLabel = row[methodColumns.colLabel]; const std::pair ppMethod = findWBEntry (row[methodColumns.colLabel], WBLT_GUI); const std::pair wbCustom = findWBEntry ("Custom", WBLT_PP); @@ -434,10 +433,6 @@ void WhiteBalance::adjusterChanged(Adjuster* a, double newval) } } -void WhiteBalance::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void WhiteBalance::optChanged () { Gtk::TreeModel::Row row = getActiveMethod(); diff --git a/rtgui/whitebalance.h b/rtgui/whitebalance.h index 2db46b7af..fd7efe7ce 100644 --- a/rtgui/whitebalance.h +++ b/rtgui/whitebalance.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _WB_H_ #define _WB_H_ @@ -107,7 +107,6 @@ public: void spotPressed (); void spotSizeChanged (); void adjusterChanged(Adjuster* a, double newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; int getSize (); void setWBProvider (WBProvider* p) { diff --git a/rtgui/xtransprocess.cc b/rtgui/xtransprocess.cc index 115fa3868..52c46be65 100644 --- a/rtgui/xtransprocess.cc +++ b/rtgui/xtransprocess.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "xtransprocess.h" diff --git a/rtgui/xtransprocess.h b/rtgui/xtransprocess.h index e5389b566..dae93822f 100644 --- a/rtgui/xtransprocess.h +++ b/rtgui/xtransprocess.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _XTRANSPROCESS_H_ #define _XTRANSPROCESS_H_ diff --git a/rtgui/xtransrawexposure.cc b/rtgui/xtransrawexposure.cc index 93f6ee202..28059e69c 100644 --- a/rtgui/xtransrawexposure.cc +++ b/rtgui/xtransrawexposure.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include @@ -110,10 +110,6 @@ void XTransRAWExposure::adjusterChanged(Adjuster* a, double newval) } } -void XTransRAWExposure::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - void XTransRAWExposure::setBatchMode(bool batchMode) { ToolPanel::setBatchMode (batchMode); diff --git a/rtgui/xtransrawexposure.h b/rtgui/xtransrawexposure.h index 75bdbd0e2..08cdcc8bf 100644 --- a/rtgui/xtransrawexposure.h +++ b/rtgui/xtransrawexposure.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _XTRANSRAWEXPOSURE_H_ #define _XTRANSRAWEXPOSURE_H_ @@ -43,7 +43,6 @@ public: void setBatchMode (bool batchMode) override; void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; void adjusterChanged (Adjuster* a, double newval) override; - void adjusterAutoToggled (Adjuster* a, bool newval) override; void setAdjusterBehavior (bool pexblackadd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; diff --git a/rtgui/zoompanel.cc b/rtgui/zoompanel.cc index ea57b7fdc..c10ec97b9 100644 --- a/rtgui/zoompanel.cc +++ b/rtgui/zoompanel.cc @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include "zoompanel.h" #include "multilangmgr.h" diff --git a/rtgui/zoompanel.h b/rtgui/zoompanel.h index 69fe418d4..e1cb651e3 100644 --- a/rtgui/zoompanel.h +++ b/rtgui/zoompanel.h @@ -14,7 +14,7 @@ * GNU General Public License for more details. *l * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #ifndef _ZOOMPANEL_ #define _ZOOMPANEL_ diff --git a/tools/camconst_creator.ods b/tools/camconst_creator.ods new file mode 100644 index 000000000..954abe6ac Binary files /dev/null and b/tools/camconst_creator.ods differ diff --git a/tools/gimp-plugin/file-formats.h b/tools/gimp-plugin/file-formats.h index fc6697ec7..ac8c2fa54 100644 --- a/tools/gimp-plugin/file-formats.h +++ b/tools/gimp-plugin/file-formats.h @@ -16,7 +16,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . */ /* These are the raw formats that file-rawtherapee will register */ diff --git a/tools/gimp-plugin/file-rawtherapee.c b/tools/gimp-plugin/file-rawtherapee.c index d78c30a10..2848e74fa 100644 --- a/tools/gimp-plugin/file-rawtherapee.c +++ b/tools/gimp-plugin/file-rawtherapee.c @@ -17,7 +17,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . */ #include "config.h"