diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 000000000..bab7397a6 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,69 @@ +name: macOS build + +on: + push + +jobs: + build: + + runs-on: macos-latest + + steps: + - uses: actions/checkout@v1 + - name: Install dependencies + run: brew install gtk+3 gtkmm3 gtk-mac-integration adwaita-icon-theme libsigc++ little-cms2 libiptcdata fftw lensfun llvm expat pkgconfig libomp shared-mime-info + - name: patch libiconv + run: | + mkdir libiconv && cd libiconv + wget https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.16.tar.gz + tar xf libiconv-1.16.tar.gz + cd libiconv-1.16 + patch -p1 < "${GITHUB_WORKSPACE}/tools/osx/libiconv_1.16_rt.patch" + mkdir build && cd build + destDir="$(pwd)" + ../configure --prefix=/opt/local --disable-static 'CFLAGS=-arch x86_64 -mmacosx-version-min=10.9' 'LDFLAGS=-arch x86_64 -mmacosx-version-min=10.9' CXXFLAGS="-arch x86_64 -mmacosx-version-min=10.9" + make --jobs + make DESTDIR="${destDir}" install + sudo mv opt/local /usr/local/opt/libiconv + - name: cmake + env: + CMAKE_CXX_STANDARD: 11 + PKG_CONFIG_PATH: /usr/local/opt/libffi/lib/pkgconfig:/usr/local/opt/expat/lib/pkgconfig + RAW_THERAPEE_MAJOR: '5' + RAW_THERAPEE_MINOR: '7' + C_FLAGS: -Xpreprocessor -fopenmp /usr/local/lib/libomp.dylib -I/usr/local/include -I/usr/local/opt/gdk-pixbuf/include -I/usr/local/opt/libiconv/include -I/usr/local/opt/libxml2/include -I/usr/local/opt/expat/include -I/usr/local/opt/llvm/include + run: | + # GITHUB_REF is the ref that triggered the build, like refs/heads/new-feature - the next line parses that to REF: the branch name only (new-feature) + REF=${GITHUB_REF##*/} + mkdir build && cd build + cmake \ + -DCMAKE_BUILD_TYPE="release" \ + -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ + -DCMAKE_EXE_LINKER_FLAGS="-L/usr/local/lib -L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib -L/usr/local/opt/gdk-pixbuf/lib -L/usr/local/opt/libiconv/lib -L/usr/local/opt/libffi/lib -L/usr/local/opt/libffi/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/expat/lib" \ + -DCACHE_NAME_SUFFIX="${RAW_THERAPEE_MAJOR}.${RAW_THERAPEE_MINOR}-${REF}" \ + -DPROC_TARGET_NUMBER="2" \ + -DPROC_LABEL="generic processor" \ + -DWITH_LTO="OFF" \ + -DLENSFUNDBDIR="./share/lensfun" \ + -DOpenMP_C_FLAGS=-fopenmp=libomp \ + -DOpenMP_CXX_FLAGS=-fopenmp=libomp \ + -DOpenMP_C_LIB_NAMES="libomp" \ + -DOpenMP_CXX_LIB_NAMES="libomp" \ + -DOpenMP_libomp_LIBRARY="/usr/local/lib/libomp.dylib" \ + -DOpenMP_C_FLAGS="${C_FLAGS}" \ + -DOpenMP_CXX_FLAGS="${C_FLAGS}" \ + -DCMAKE_AR="/usr/local/opt/llvm/bin/llvm-ar" \ + -DCMAKE_RANLIB="/usr/local/opt/llvm/bin/llvm-ranlib" \ + .. + make --jobs + make install + sudo make macosx_bundle + ARTIFACT=(RawTherapee*.zip) + echo "=== artifact: ${ARTIFACT}" + # defining environment variables for next step as per https://github.com/actions/starter-workflows/issues/68 + echo "::set-env name=ARTIFACT_PATH::${GITHUB_WORKSPACE}/build/${ARTIFACT}" + echo "::set-env name=ARTIFACT_FILE::${ARTIFACT}" + - uses: actions/upload-artifact@v1 + with: + name: ${{env.ARTIFACT_FILE}} + path: ${{env.ARTIFACT_PATH}} diff --git a/.travis.yml.fixme b/.travis.yml.fixme deleted file mode 100644 index 0aa85f3b4..000000000 --- a/.travis.yml.fixme +++ /dev/null @@ -1,44 +0,0 @@ -sudo: required -dist: trusty - -language: cpp - -compiler: - - gcc - -os: - - linux - -#branches: -# only: -# - master - -notifications: - irc: - channels: - - "chat.freenode.net#rawtherapee" - skip_join: true - template: - - "%{repository}/%{branch} (%{commit} - %{author}): %{build_url}: %{message}" - email: - on_success: change - on_failure: always - -env: - global: - - OMP_NUM_THREADS=4 - -before_install: - - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - - sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ xenial main" - - sudo apt-get -qq update - - sudo apt-get install gcc-6 g++-6 - - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 60 --slave /usr/bin/g++ g++ /usr/bin/g++-6 - - sudo apt-get install build-essential cmake curl git libbz2-dev libcanberra-gtk3-dev libexiv2-dev libexpat-dev libfftw3-dev libglibmm-2.4-dev libgtk-3-dev libgtkmm-3.0-dev libiptcdata0-dev libjpeg8-dev liblcms2-dev libpng12-dev libsigc++-2.0-dev libtiff5-dev zlib1g-dev - -before_script: - - mkdir build - - cd build - - cmake -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" -DWITH_LTO="OFF" -DPROC_TARGET_NUMBER="2" .. - -script: make diff --git a/AUTHORS.txt b/AUTHORS.txt index 160869776..227390faa 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -39,6 +39,7 @@ Development contributors, in last name alphabetical order: Other contributors (profiles, ideas, mockups, testing, forum activity, translations, etc.), in last name alphabetical order: Marcin Bajor + Javier Bartol Thorsten Bartolomäus Patrik Brunner Fernando Carello diff --git a/CMakeLists.txt b/CMakeLists.txt index 637cc1b9f..13c648de0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,6 +89,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PROC_FLAGS}") # Stop compilation on typos such as std:swap (missing colon will be detected as unused label): set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=unused-label") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=delete-incomplete") # Special treatment for x87 and x86-32 SSE (see GitHub issue #4324) include(FindX87Math) @@ -136,6 +137,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) @@ -248,8 +252,10 @@ if(NOT DEFINED APPDATADIR) endif() endif() -if(DEFINED LENSFUNDBDIR AND NOT IS_ABSOLUTE "${LENSFUNDBDIR}") - set(LENSFUNDBDIR "${DATADIR}/${LENSFUNDBDIR}") +if (NOT APPLE) + if(DEFINED LENSFUNDBDIR AND NOT IS_ABSOLUTE "${LENSFUNDBDIR}") + set(LENSFUNDBDIR "${DATADIR}/${LENSFUNDBDIR}") + endif() endif() if(APPLE) @@ -259,7 +265,11 @@ if(APPLE) if("${NOTARY}") set(NOTARY "${NOTARY}" CACHE STRING "Notarization Identity") endif() - + if("${LOCAL_PREFIX}") + set(LOCAL_PREFIX "${LOCAL_PREFIX}" CACHE STRING "macos/gtk parent directory ie /usr or /opt") + elseif(NOT DEFINED LOCAL_PREFIX) + set(LOCAL_PREFIX "/usr") + endif() endif() # Enforce absolute paths for non-bundle builds: @@ -392,7 +402,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 -Wunused-macros") if(OPTION_OMP) find_package(OpenMP) if(OPENMP_FOUND) @@ -564,6 +574,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(rtexif) add_subdirectory(rtengine) diff --git a/LICENSE.txt b/LICENSE.txt index 0aa0df7c8..2ba8256ab 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ RawTherapee - A powerful, cross-platform raw image processing program. Copyright (C) 2004-2012 Gabor Horvath - Copyright (C) 2010-2019 RawTherapee development team. + Copyright (C) 2010-2020 RawTherapee development team. RawTherapee is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -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..eb8d96379 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,14 +1,14 @@ -RAWTHERAPEE 5.6-dev RELEASE NOTES +RAWTHERAPEE 5.8-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. - You should report these bugs so that they get fixed for the next stable release. See - www.rawpedia.rawtherapee.com/How_to_write_useful_bug_reports + https://rawpedia.rawtherapee.com/How_to_write_useful_bug_reports - The way new tools work in the development versions is likely to change as we tweak and tune them, so your processing profiles may produce different results when used in a future stable version. - Bugs present in the stable versions get fixed in the development versions, and make it into the next stable version when we make a new official release. That means that in some ways the development versions can be "more stable" than the latest stable release. At the same time, new features may introduce new bugs. This is a trade-off you should be aware of. @@ -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.8: +- TODO NEWS RELEVANT TO PACKAGE MAINTAINERS +New since 5.8: +- 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..f7d588684 100644 --- a/com.rawtherapee.RawTherapee.appdata.xml +++ b/com.rawtherapee.RawTherapee.appdata.xml @@ -8,37 +8,23 @@ 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://discuss.pixls.us/t/localization-how-to-translate-rawtherapee-and-rawpedia/2594 + https://rawpedia.rawtherapee.com + https://www.rawtherapee.com + https://rawpedia.rawtherapee.com/Main_Page#Localization rawtherapee.desktop + + - - @@ -47,16 +33,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..a98fbbac1 100644 --- a/header +++ b/header @@ -7,12 +7,12 @@ * 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 . + * along with RawTherapee. If not, see . */ diff --git a/rtdata/dcpprofiles/Canon EOS RP.dcp b/rtdata/dcpprofiles/Canon EOS RP.dcp new file mode 100644 index 000000000..8379d9703 Binary files /dev/null and b/rtdata/dcpprofiles/Canon EOS RP.dcp differ diff --git a/rtdata/dcpprofiles/FUJIFILM X-T10.dcp b/rtdata/dcpprofiles/FUJIFILM X-T10.dcp new file mode 100644 index 000000000..e77837f3e Binary files /dev/null and b/rtdata/dcpprofiles/FUJIFILM X-T10.dcp differ diff --git a/rtdata/dcpprofiles/FUJIFILM X-T2.dcp b/rtdata/dcpprofiles/FUJIFILM X-T2.dcp new file mode 100644 index 000000000..5a4e11688 Binary files /dev/null and b/rtdata/dcpprofiles/FUJIFILM X-T2.dcp differ diff --git a/rtdata/dcpprofiles/FUJIFILM X-T30.dcp b/rtdata/dcpprofiles/FUJIFILM X-T30.dcp new file mode 100644 index 000000000..97917b810 Binary files /dev/null and b/rtdata/dcpprofiles/FUJIFILM X-T30.dcp differ diff --git a/rtdata/dcpprofiles/Panasonic DMC-GX7.dcp b/rtdata/dcpprofiles/Panasonic DMC-GX7.dcp new file mode 100644 index 000000000..25f4e6eab Binary files /dev/null and b/rtdata/dcpprofiles/Panasonic DMC-GX7.dcp differ diff --git a/rtdata/dcpprofiles/RICOH GR III.dcp b/rtdata/dcpprofiles/RICOH GR III.dcp new file mode 100644 index 000000000..f226e62b4 Binary files /dev/null and b/rtdata/dcpprofiles/RICOH GR III.dcp differ diff --git a/rtdata/dcpprofiles/SONY ILCE-6300.dcp b/rtdata/dcpprofiles/SONY ILCE-6300.dcp new file mode 100644 index 000000000..53194d35d Binary files /dev/null and b/rtdata/dcpprofiles/SONY ILCE-6300.dcp differ diff --git a/rtdata/dcpprofiles/SONY ILCE-6500.dcp b/rtdata/dcpprofiles/SONY ILCE-6500.dcp new file mode 100644 index 000000000..66be8b1de Binary files /dev/null and b/rtdata/dcpprofiles/SONY ILCE-6500.dcp differ 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/questionmark.svg b/rtdata/images/svg/questionmark.svg new file mode 100644 index 000000000..4c4b59590 --- /dev/null +++ b/rtdata/images/svg/questionmark.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + image/svg+xml + + + + + Maciej Dworak + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + ? + + + + diff --git a/rtdata/images/svg/splash.svg b/rtdata/images/svg/splash.svg index 2e46f0e6d..5609a45c1 100644 --- a/rtdata/images/svg/splash.svg +++ b/rtdata/images/svg/splash.svg @@ -1,6 +1,4 @@ - - + inkscape:export-xdpi="96" + inkscape:export-filename="/tmp/splash.png" + sodipodi:docname="splash.svg" + inkscape:version="1.1-dev (4cd8f7c, 2020-02-06)" + id="svg783" + version="1.1" + viewBox="0 0 146.05 91.545836" + height="346" + width="552"> RawTherapee splash screen + id="stop3964-8" /> + id="stop3966-8" /> + id="stop3956-7" /> + id="stop3958-6" /> + inkscape:collect="always" + id="linearGradient4002-3"> + id="stop4004-0" /> + id="stop4006-3" /> + id="stop4026-2" /> + id="stop4028-5" /> + inkscape:collect="always" + id="linearGradient4018-0"> + id="stop4020-5" /> + id="stop4022-9" /> + style="stop-color:#f18e01;stop-opacity:1;" /> + id="stop3982-2" /> + inkscape:collect="always" + id="linearGradient3994-4"> + id="stop3996-7" /> + id="stop3998-7" /> + id="stop3972-8" /> + id="stop3974-1" /> + id="stop3948-9" /> + id="stop3950-3" /> + id="stop3988-0" /> + id="stop3990-2" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + inkscape:window-maximized="1" + inkscape:window-y="0" + inkscape:window-x="0" + inkscape:window-height="1021" + inkscape:window-width="1920" + inkscape:snap-global="false" + inkscape:snap-nodes="true" + inkscape:object-nodes="false" + inkscape:snap-others="true" + inkscape:guide-bbox="true" + showguides="true" + inkscape:bbox-paths="false" + inkscape:snap-bbox-edge-midpoints="false" + inkscape:snap-bbox-midpoints="true" + inkscape:object-paths="false" + inkscape:snap-intersection-paths="false" + inkscape:snap-smooth-nodes="false" + inkscape:snap-midpoints="false" + inkscape:snap-object-midpoints="true" + inkscape:snap-center="false" + inkscape:snap-text-baseline="false" + inkscape:snap-page="false" + inkscape:bbox-nodes="true" + inkscape:snap-bbox="true" + units="px" + showgrid="false" + inkscape:current-layer="layer1" + inkscape:document-units="px" + inkscape:cy="209.17983" + inkscape:cx="275.82889" + inkscape:zoom="0.95596044" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base"> - + + orientation="0,1" + position="27.648959,71.437501" /> - + + orientation="1,0" + position="138.12828,76.425406" /> - + - + - - + position="123.92422,11.509375" /> + + + orientation="1,0" + position="73.162242,39.921138" /> @@ -574,7 +542,7 @@ RawTherapee splash screen - 2019-02-27 + Maciej Dworak @@ -602,518 +570,374 @@ - - - Each logo element has a filter effect (ring*). Additionally, the logo as a whole (all elements grouped) also has a filter effect (logo glow)."Raw": font Eras Ultra ITC, 60pt, -3px spacing between characters."Therapee": font Eras Medium ITC, 60pt, +1px spacing between characters.Version: font Eras Bold ITC, 64pt, skewed -3°. RawTherapee splash screen design version 1.2 from 2019-02-27 | www.rawtherapee.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + inkscape:groupmode="layer" + inkscape:label="Layer 1"> - + GNU GPLv3 - - Development + d="m 9.4489751,288.85927 q 0.3352508,0.002 0.5154724,0.002 0.1918485,0 0.4321445,-0.002 -0.04263,0.57942 -0.06201,1.39914 -0.5871735,0.12596 -1.0038148,0.12596 -0.3081207,0 -0.5910491,-0.0795 -0.2809906,-0.0795 -0.4747773,-0.24224 -0.1937866,-0.16278 -0.2926178,-0.41858 -0.096893,-0.25579 -0.096893,-0.54066 0,-0.32362 0.1220856,-0.60849 0.1240234,-0.2868 0.346878,-0.48059 0.2228547,-0.19379 0.5019074,-0.27712 0.2790527,-0.0833 0.6181793,-0.0833 0.3720703,0 0.829407,0.0988 0.0039,0.14534 0.01938,0.31393 -0.271301,-0.0891 -0.4689632,-0.12208 -0.1976624,-0.0349 -0.3643189,-0.0349 -0.2616119,0 -0.4980316,0.0795 -0.2364196,0.0775 -0.405014,0.24029 -0.1685944,0.16084 -0.2557983,0.3992 -0.087204,0.23836 -0.087204,0.49222 0,0.22673 0.069763,0.42633 0.071701,0.19766 0.2151031,0.32362 0.1434021,0.12597 0.3488159,0.19379 0.2073517,0.0659 0.449585,0.0659 0.1317749,0 0.3139343,-0.0233 0.1821594,-0.0252 0.3681946,-0.0833 l 0.038757,-0.91661 H 9.855927 q -0.1821594,0 -0.4185791,0.01 0.011627,-0.13952 0.011627,-0.25773 z" /> + + + + + + + - Release Candidate 1 + style="filter:url(#filter173)" + id="g171"> + + + + + + + + + + + + + + + + + + + + + + + + + + - 5 - . 6 - Therapee - Raw - Therapee - Raw + transform="matrix(0.24127119,0,0.01264448,0.24127122,-4.8837849,265.42414)" + aria-label="5" /> + id="text3659" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Eras Medium ITC';-inkscape-font-specification:'Eras Medium ITC';letter-spacing:1px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.07075834px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4749);enable-background:new" + transform="matrix(0.24732122,0,0,0.24687704,-5.5339446,264.55152)" + aria-label="Therapee"> + id="path670" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:79.99999237px;line-height:1.25;font-family:'Eras Medium ITC';-inkscape-font-specification:'Eras Medium ITC';letter-spacing:0.99999994px;stroke-width:1.07075834px" + d="m 256.12553,-157.9659 0.78125,-11.95312 1.05469,-24.76562 0.35156,-11.44531 q -9.57031,0.0391 -16.75781,0.35156 0.23438,-3.125 0.27344,-5.50781 9.92187,0.0391 21.40625,0.0391 l 12.5,-0.0391 h 6.64062 q -0.27344,3.4375 -0.27344,5.46875 -6.05468,-0.35157 -13.39843,-0.35157 h -3.20313 l -0.82031,17.30469 -0.82031,24.375 v 6.52343 l -3.75,-0.0781 q -0.50782,0 -3.98438,0.0781 z" /> + id="path672" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:79.99999237px;line-height:1.25;font-family:'Eras Medium ITC';-inkscape-font-specification:'Eras Medium ITC';letter-spacing:0.99999994px;stroke-width:1.07075834px" + d="m 287.32084,-157.9659 0.97656,-16.99218 0.89844,-23.16406 0.23438,-13.16406 3.55468,0.0391 q 1.32813,0 3.47657,-0.0391 l -0.85938,13.55468 -0.3125,8.08594 q 0.9375,-1.67969 1.60156,-2.65625 0.70313,-1.01563 1.75782,-1.99219 1.09375,-1.01562 2.26562,-1.71875 1.17188,-0.70312 2.61719,-1.21094 1.44531,-0.54687 3.47656,-0.89843 2.03125,-0.35157 4.25781,-0.35157 3.32031,0 6.32813,0.74219 3.04687,0.74219 5.19531,2.46094 2.1875,1.71875 2.96875,4.10156 0.82031,2.38281 0.82031,4.84375 0,0.97656 -0.0391,2.57813 -0.11719,2.42187 -0.3125,5.66406 l -0.66406,14.375 q -0.11719,2.34375 -0.15625,5.74218 -2.26563,-0.0781 -3.47657,-0.0781 -1.32812,0 -3.71093,0.0781 0.42968,-4.21875 0.97656,-13.28125 0.58594,-9.06249 0.58594,-12.57812 0,-3.125 -1.13282,-5.15625 -1.13281,-2.07031 -3.75,-3.16406 -2.61718,-1.09375 -5.82031,-1.09375 -2.92968,0 -5.46875,0.89844 -2.30468,0.82031 -3.94531,2.30468 -1.60156,1.48438 -2.57812,3.63282 -1.05469,2.30468 -1.48438,4.64843 -0.66406,3.71094 -0.9375,10.3125 -0.15625,3.94531 -0.42969,13.47656 -2.1875,-0.0781 -3.28125,-0.0781 -1.01562,0 -3.63281,0.0781 z" /> + + + + + + + + + + + + + + + + + + + + + + id="g3926"> + id="text3924" + style="font-style:normal;font-weight:normal;font-size:12.8px;line-height:0%;font-family:sans-serif;text-align:end;letter-spacing:-1.06667px;word-spacing:0px;text-anchor:end;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.06667px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"> + inkscape:connector-curvature="0" + d="m 491.97872,49.720543 q 0.18333,-1.900004 0.25,-3.041673 0.1,-1.700003 0.2,-4.400008 0.075,-2.066671 0.075,-2.958339 v -0.975002 q 0.975,0.025 1.68334,0.025 0.68333,0 1.79167,-0.03333 1.10833,-0.04167 2.08333,-0.04167 1.11667,0 1.95834,0.133333 0.84167,0.133334 1.56667,0.550001 0.73334,0.416668 1.225,1.091669 0.49167,0.675001 0.75,1.583336 0.25834,0.900002 0.25834,1.858337 0,0.941669 -0.2,1.816671 -0.2,0.866668 -0.55834,1.566669 -0.35833,0.700002 -0.84166,1.208336 -0.47501,0.500001 -1.09167,0.858335 -0.45834,0.266667 -0.92501,0.416668 -0.46666,0.15 -1.275,0.241667 -0.9,0.1 -2.04167,0.1 l -3.36667,-0.025 q -0.475,0 -1.54167,0.025 z m 3.60001,-2.508338 q 0.45833,0.04167 0.95833,0.04167 0.85,0 1.51667,-0.15 0.66667,-0.15 1.16667,-0.641668 0.50833,-0.491667 0.75,-1.258336 0.24167,-0.775001 0.24167,-1.583336 0,-0.991669 -0.35834,-1.66667 -0.35833,-0.683335 -0.95833,-0.950002 -0.59167,-0.266667 -1.61667,-0.266667 -0.6,0 -1.41667,0.05 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.0667px;line-height:110%;font-family:'Eras Bold ITC';-inkscape-font-specification:'Eras Bold ITC Bold';text-align:end;letter-spacing:-1.06667px;text-anchor:end;fill:#ffffff;stroke-width:1.06667px" + id="path3928" /> + inkscape:connector-curvature="0" + d="m 512.24542,47.203871 q -0.10833,0.500001 -0.41666,2.416672 -0.96667,0.191667 -1.62501,0.25 -0.65833,0.06667 -1.33333,0.06667 -0.99167,0 -1.82501,-0.141667 -0.83333,-0.133334 -1.44167,-0.483334 -0.6,-0.350001 -1.00833,-0.866669 -0.40834,-0.525001 -0.625,-1.241669 -0.20834,-0.716668 -0.20834,-1.475003 0,-1.066668 0.425,-2.083337 0.42501,-1.025002 1.09167,-1.600003 0.675,-0.575001 1.55001,-0.816668 0.875,-0.241667 1.79167,-0.241667 0.95,0 1.80833,0.225 0.86667,0.216667 1.46667,0.766668 0.6,0.550001 0.85,1.241669 0.25834,0.691668 0.25834,1.49167 0,0.475001 -0.10833,1.058335 l -5.84168,0.0083 q -0.008,0.133333 -0.008,0.241667 0,0.900001 0.64167,1.325002 0.64167,0.425001 1.56667,0.425001 0.55,0 1.25,-0.125 0.70834,-0.133334 1.74167,-0.441668 z m -5.12501,-2.700005 h 2.75001 q 0.008,-0.141667 0.008,-0.241667 0,-0.433334 -0.15833,-0.741668 -0.15,-0.308334 -0.44167,-0.450001 -0.28333,-0.141667 -0.64167,-0.141667 -0.25,0 -0.48333,0.08333 -0.23333,0.075 -0.425,0.233334 -0.18334,0.150001 -0.30834,0.350001 -0.125,0.2 -0.18333,0.391667 -0.0583,0.183334 -0.11667,0.516668 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.0667px;line-height:110%;font-family:'Eras Bold ITC';-inkscape-font-specification:'Eras Bold ITC Bold';text-align:end;letter-spacing:-1.06667px;text-anchor:end;fill:#ffffff;stroke-width:1.06667px" + id="path3930" /> + inkscape:connector-curvature="0" + d="m 515.32043,49.720543 -0.88334,-2.733339 -1.99167,-5.775011 q 0.95001,0.01667 1.76667,0.01667 0.85,0 1.60001,-0.01667 0.14166,0.575001 0.55833,2.016671 0.41667,1.433336 0.91667,3.416673 l 0.21667,-0.691668 q 0.05,-0.125 0.39166,-1.066669 l 1.32501,-3.675007 q 0.9,0.01667 1.7,0.01667 0.825,0 1.71667,-0.01667 l -1.15,2.475005 -2.14167,4.916676 -0.45834,1.116669 q -0.98333,-0.01667 -1.73333,-0.01667 -0.81667,0 -1.83334,0.01667 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.0667px;line-height:110%;font-family:'Eras Bold ITC';-inkscape-font-specification:'Eras Bold ITC Bold';text-align:end;letter-spacing:-1.06667px;text-anchor:end;fill:#ffffff;stroke-width:1.06667px" + id="path3932" /> + inkscape:connector-curvature="0" + d="m 530.27879,47.203871 q -0.10833,0.500001 -0.41667,2.416672 -0.96667,0.191667 -1.625,0.25 -0.65834,0.06667 -1.33334,0.06667 -0.99167,0 -1.825,-0.141667 -0.83334,-0.133334 -1.44167,-0.483334 -0.6,-0.350001 -1.00834,-0.866669 -0.40833,-0.525001 -0.625,-1.241669 -0.20833,-0.716668 -0.20833,-1.475003 0,-1.066668 0.425,-2.083337 0.425,-1.025002 1.09167,-1.600003 0.675,-0.575001 1.55,-0.816668 0.875,-0.241667 1.79167,-0.241667 0.95,0 1.80834,0.225 0.86667,0.216667 1.46667,0.766668 0.6,0.550001 0.85,1.241669 0.25833,0.691668 0.25833,1.49167 0,0.475001 -0.10833,1.058335 l -5.84168,0.0083 q -0.008,0.133333 -0.008,0.241667 0,0.900001 0.64167,1.325002 0.64166,0.425001 1.56667,0.425001 0.55,0 1.25,-0.125 0.70833,-0.133334 1.74167,-0.441668 z m -5.12501,-2.700005 h 2.75 q 0.008,-0.141667 0.008,-0.241667 0,-0.433334 -0.15834,-0.741668 -0.15,-0.308334 -0.44166,-0.450001 -0.28334,-0.141667 -0.64167,-0.141667 -0.25,0 -0.48334,0.08333 -0.23333,0.075 -0.425,0.233334 -0.18333,0.150001 -0.30833,0.350001 -0.125,0.2 -0.18333,0.391667 -0.0583,0.183334 -0.11667,0.516668 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.0667px;line-height:110%;font-family:'Eras Bold ITC';-inkscape-font-specification:'Eras Bold ITC Bold';text-align:end;letter-spacing:-1.06667px;text-anchor:end;fill:#ffffff;stroke-width:1.06667px" + id="path3934" /> + inkscape:connector-curvature="0" + d="m 531.04546,49.71221 0.15,-1.791671 0.325,-6.225012 0.0917,-3.350006 q 1.15833,0.01667 1.74167,0.01667 0.75833,0 1.675,-0.01667 l -0.19167,2.558338 -0.30833,6.300012 -0.0667,2.516672 q -0.89167,-0.01667 -1.60834,-0.01667 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.0667px;line-height:110%;font-family:'Eras Bold ITC';-inkscape-font-specification:'Eras Bold ITC Bold';text-align:end;letter-spacing:-1.06667px;text-anchor:end;fill:#ffffff;stroke-width:1.06667px" + id="path3936" /> + inkscape:connector-curvature="0" + d="m 540.25381,40.995526 q 1.03333,0 1.98333,0.316667 0.95834,0.316667 1.61667,0.916669 0.65834,0.591667 0.96667,1.391669 0.31667,0.791668 0.31667,1.708337 0,0.891668 -0.28334,1.700003 -0.275,0.800002 -0.94166,1.508336 -0.66667,0.700002 -1.70001,1.050002 -1.025,0.350001 -2.175,0.350001 -1.05834,0 -2.03334,-0.308334 -0.975,-0.308334 -1.63334,-0.900002 -0.65,-0.591668 -0.98333,-1.416669 -0.325,-0.825002 -0.325,-1.733337 0,-0.908335 0.31667,-1.733337 0.325,-0.825001 1.01666,-1.483336 0.70001,-0.658334 1.72501,-1.008335 1.025,-0.358334 2.13334,-0.358334 z m -0.0583,2.450005 q -0.53333,0 -0.95,0.275 -0.41667,0.275001 -0.63333,0.808335 -0.20834,0.525001 -0.20834,1.150002 0,0.916669 0.45834,1.408336 0.45833,0.483335 1.15,0.483335 0.525,0 0.94167,-0.275001 0.41666,-0.283334 0.625,-0.825001 0.21666,-0.550002 0.21666,-1.175003 0,-0.516667 -0.16666,-0.933335 -0.16667,-0.416667 -0.55,-0.666668 -0.375,-0.25 -0.88334,-0.25 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.0667px;line-height:110%;font-family:'Eras Bold ITC';-inkscape-font-specification:'Eras Bold ITC Bold';text-align:end;letter-spacing:-1.06667px;text-anchor:end;fill:#ffffff;stroke-width:1.06667px" + id="path3938" /> + inkscape:connector-curvature="0" + d="m 545.04548,53.620551 q 0.15833,-1.708337 0.26667,-3.40834 0.19167,-2.908339 0.25833,-4.87501 0.075,-1.975004 0.075,-3.908341 1.69167,-0.258334 2.65001,-0.341667 0.95833,-0.09167 1.91667,-0.09167 1.2,0 2.20834,0.25 1.00833,0.250001 1.61667,0.883335 0.61666,0.633335 0.925,1.508337 0.30833,0.875001 0.30833,1.833337 0,0.875001 -0.25,1.700003 -0.25,0.816668 -0.76667,1.475003 -0.51667,0.658334 -1.19167,0.975002 -0.66666,0.316667 -1.49167,0.316667 -0.40833,0 -0.85,-0.08333 -0.43333,-0.075 -0.825,-0.225001 -0.39167,-0.15 -0.65833,-0.300001 -0.25834,-0.158333 -0.65001,-0.45 l -0.0917,2.325004 q -0.0583,1.600003 -0.0583,2.416672 -0.96666,-0.01667 -1.65833,-0.01667 -0.6,0 -1.73334,0.01667 z m 3.84167,-10.066687 q -0.0667,0.375001 -0.0917,0.616668 -0.025,0.233334 -0.05,0.641668 -0.025,0.400001 -0.025,0.641668 0,0.683335 0.20833,1.150002 0.21667,0.458334 0.59167,0.716668 0.38333,0.250001 0.81667,0.250001 0.45833,0 0.84167,-0.258334 0.38333,-0.266667 0.60833,-0.791668 0.225,-0.525001 0.225,-1.183336 0,-0.891668 -0.475,-1.433336 -0.46667,-0.541668 -1.36667,-0.541668 -0.56667,0 -1.28334,0.191667 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.0667px;line-height:110%;font-family:'Eras Bold ITC';-inkscape-font-specification:'Eras Bold ITC Bold';text-align:end;letter-spacing:-1.06667px;text-anchor:end;fill:#ffffff;stroke-width:1.06667px" + id="path3940" /> + inkscape:connector-curvature="0" + d="m 555.45383,49.720543 0.23334,-4.016675 0.13333,-3.141672 0.0167,-1.350003 q 0.91666,0.01667 1.61667,0.01667 0.79166,0 1.54167,-0.01667 l -0.0583,1.108335 q 0.25834,-0.333334 0.43334,-0.508334 0.18333,-0.183334 0.44166,-0.341667 0.25834,-0.166667 0.53334,-0.258334 0.275,-0.1 0.61667,-0.158334 0.34166,-0.05833 0.71666,-0.05833 0.425,0 0.78334,0.075 0.35833,0.06667 0.61667,0.175 0.25833,0.108334 0.45,0.250001 0.19166,0.141667 0.33333,0.325 0.15,0.175001 0.34167,0.516668 0.36667,-0.533334 0.775,-0.808335 0.40833,-0.275 0.925,-0.400001 0.525,-0.133333 1.075,-0.133333 0.72501,0 1.36667,0.208334 0.64167,0.208333 1.05001,0.725001 0.41666,0.508334 0.41666,1.325003 0,0.383334 -0.0583,1.158335 -0.05,0.775002 -0.15,2.666672 -0.0917,1.883337 -0.1,2.641672 -0.76667,-0.01667 -1.48334,-0.01667 -0.875,0 -1.83333,0.01667 0.0833,-1.058335 0.16666,-2.650005 0.0917,-1.600003 0.0917,-2.216671 0,-0.533335 -0.125,-0.791668 -0.125,-0.266668 -0.325,-0.358335 -0.19167,-0.1 -0.425,-0.1 -0.25,0 -0.43334,0.09167 -0.2,0.1 -0.35,0.308334 -0.2,0.275001 -0.325,0.691668 -0.1,0.325001 -0.15833,0.991669 -0.0583,0.683334 -0.0917,1.800003 l -0.0667,2.233338 q -0.89167,-0.01667 -1.60834,-0.01667 -0.73334,0 -1.725,0.01667 0.075,-0.741668 0.175,-2.491672 0.1,-1.750003 0.1,-2.341671 0,-0.500001 -0.1,-0.750001 -0.1,-0.250001 -0.28334,-0.400001 -0.175,-0.15 -0.475,-0.15 -0.325,0 -0.56667,0.191667 -0.24166,0.191667 -0.41666,0.550001 -0.16667,0.358334 -0.24167,0.991668 -0.0667,0.625002 -0.125,1.916671 -0.0583,1.291669 -0.075,2.483338 -1.00834,-0.01667 -1.63334,-0.01667 -0.69167,0 -1.71667,0.01667 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.0667px;line-height:110%;font-family:'Eras Bold ITC';-inkscape-font-specification:'Eras Bold ITC Bold';text-align:end;letter-spacing:-1.06667px;text-anchor:end;fill:#ffffff;stroke-width:1.06667px" + id="path3942" /> + inkscape:connector-curvature="0" + d="m 578.51221,47.203871 q -0.10833,0.500001 -0.41666,2.416672 -0.96667,0.191667 -1.62501,0.25 -0.65833,0.06667 -1.33333,0.06667 -0.99167,0 -1.82501,-0.141667 -0.83333,-0.133334 -1.44167,-0.483334 -0.6,-0.350001 -1.00833,-0.866669 -0.40833,-0.525001 -0.625,-1.241669 -0.20834,-0.716668 -0.20834,-1.475003 0,-1.066668 0.42501,-2.083337 0.425,-1.025002 1.09166,-1.600003 0.67501,-0.575001 1.55001,-0.816668 0.875,-0.241667 1.79167,-0.241667 0.95,0 1.80833,0.225 0.86667,0.216667 1.46667,0.766668 0.6,0.550001 0.85001,1.241669 0.25833,0.691668 0.25833,1.49167 0,0.475001 -0.10833,1.058335 l -5.84168,0.0083 q -0.008,0.133333 -0.008,0.241667 0,0.900001 0.64167,1.325002 0.64167,0.425001 1.56667,0.425001 0.55,0 1.25,-0.125 0.70834,-0.133334 1.74167,-0.441668 z m -5.12501,-2.700005 h 2.75001 q 0.008,-0.141667 0.008,-0.241667 0,-0.433334 -0.15833,-0.741668 -0.15,-0.308334 -0.44167,-0.450001 -0.28333,-0.141667 -0.64167,-0.141667 -0.25,0 -0.48333,0.08333 -0.23333,0.075 -0.425,0.233334 -0.18334,0.150001 -0.30834,0.350001 -0.125,0.2 -0.18333,0.391667 -0.0583,0.183334 -0.11667,0.516668 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.0667px;line-height:110%;font-family:'Eras Bold ITC';-inkscape-font-specification:'Eras Bold ITC Bold';text-align:end;letter-spacing:-1.06667px;text-anchor:end;fill:#ffffff;stroke-width:1.06667px" + id="path3944" /> + inkscape:connector-curvature="0" + d="m 579.21221,49.720543 q 0.24167,-1.89167 0.36667,-4.175008 0.13333,-2.291671 0.15833,-4.333342 1.00001,0.01667 1.72501,0.01667 0.84167,0 1.61667,-0.01667 l -0.0833,1.133336 q 0.275,-0.308334 0.475,-0.483335 0.2,-0.183333 0.49167,-0.35 0.3,-0.175001 0.63334,-0.283334 0.33333,-0.108334 0.725,-0.166667 0.4,-0.06667 0.83333,-0.06667 0.6,0 1.16667,0.133333 0.575,0.125001 0.95834,0.366668 0.38333,0.233334 0.64166,0.591668 0.25834,0.35 0.34167,0.758334 0.0833,0.408335 0.0833,0.841669 0,0.316667 -0.0667,1.366669 l -0.14167,3.016673 q -0.0417,0.891668 -0.0417,1.650003 -0.84167,-0.01667 -1.57501,-0.01667 -0.99167,0 -1.80833,0.01667 0.075,-0.758335 0.15833,-2.250004 0.0833,-1.500003 0.0833,-2.108338 0,-0.941668 -0.36666,-1.308336 -0.35834,-0.375001 -0.90834,-0.375001 -0.48333,0 -0.91667,0.316668 -0.425,0.316667 -0.65833,0.925002 -0.23334,0.600001 -0.33334,1.983337 -0.0917,1.383336 -0.125,2.816672 -0.83333,-0.01667 -1.625,-0.01667 -0.83334,0 -1.80834,0.01667 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.0667px;line-height:110%;font-family:'Eras Bold ITC';-inkscape-font-specification:'Eras Bold ITC Bold';text-align:end;letter-spacing:-1.06667px;text-anchor:end;fill:#ffffff;stroke-width:1.06667px" + id="path3946" /> + inkscape:connector-curvature="0" + d="m 596.02891,47.270538 q -0.15,0.700001 -0.25834,1.366669 l -0.18333,1.016669 q -0.825,0.183334 -1.29167,0.233334 -0.45833,0.05 -0.89167,0.05 -0.70833,0 -1.25833,-0.125 -0.55001,-0.116667 -0.91667,-0.433334 -0.36667,-0.325001 -0.5,-0.741669 -0.13334,-0.416667 -0.13334,-0.883335 0,-0.08333 0.008,-0.291667 0.008,-0.216667 0.0583,-0.950002 l 0.18333,-2.883339 h -1.3 q 0.0417,-0.575001 0.075,-1.516669 l 0.025,-0.775002 h 1.38334 q 0.05,-0.383334 0.125,-1.675003 l 1.425,-0.291667 q 0.39167,-0.075 1.66667,-0.383334 -0.0583,1.091668 -0.0833,2.350004 h 1.9 q -0.0667,1.733337 -0.0667,2.291671 h -1.91667 l -0.1,2.083338 q -0.0167,0.466667 -0.0167,0.600001 0,0.400001 0.0833,0.666668 0.0917,0.266667 0.30833,0.383334 0.225,0.116667 0.49167,0.116667 0.2,0 0.41667,-0.025 0.21667,-0.03333 0.76667,-0.183334 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.0667px;line-height:110%;font-family:'Eras Bold ITC';-inkscape-font-specification:'Eras Bold ITC Bold';text-align:end;letter-spacing:-1.06667px;text-anchor:end;fill:#ffffff;stroke-width:1.06667px" + id="path3948" /> diff --git a/rtdata/images/svg/splash_template.svg b/rtdata/images/svg/splash_template.svg new file mode 100644 index 000000000..8044343c0 --- /dev/null +++ b/rtdata/images/svg/splash_template.svg @@ -0,0 +1,1078 @@ + + + + + RawTherapee splash screen + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + RawTherapee splash screen + + + + Maciej Dworak + + + www.rawtherapee.com + + + + + + + + + + + + + + + + Each logo element has a filter effect (ring*). Additionally, the logo as a whole (all elements grouped) also has a filter effect (logo glow)."Raw": font Eras Ultra ITC, 60pt, -3px spacing between characters."Therapee": font Eras Medium ITC, 60pt, +1px spacing between characters.Version: font Eras Bold ITC, 64pt, skewed -3°. RawTherapee splash screen design version 1.2 from 2019-02-27 | www.rawtherapee.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GNU GPLv3 + + Development + + + Release Candidate 1 + + 5 + . 9 + Therapee + Raw + Therapee + Raw + + + + + + + + + + + + diff --git a/rtdata/languages/Catala b/rtdata/languages/Catala index 8b2bc5992..ac4c9565b 100644 --- a/rtdata/languages/Catala +++ b/rtdata/languages/Catala @@ -977,6 +977,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !GENERAL_AUTO;Automatic !GENERAL_CLOSE;Close !GENERAL_CURRENT;Current +!GENERAL_HELP;Help !GENERAL_OPEN;Open !GENERAL_RESET;Reset !GENERAL_SAVE_AS;Save as... @@ -1293,6 +1294,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !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 @@ -1310,6 +1312,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !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 @@ -1330,6 +1333,13 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - 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 @@ -1344,6 +1354,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light !HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength !HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor +!HISTORY_MSG_TRANS_Method;Geometry - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !ICCPROFCREATOR_COPYRIGHT;Copyright: !ICCPROFCREATOR_COPYRIGHT_RESET_TOOLTIP;Reset to the default copyright, granted to "RawTherapee, CC0" @@ -1423,7 +1434,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 @@ -1786,6 +1797,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !TP_CROP_SELECTCROP;Select !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 @@ -1856,16 +1868,16 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral 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 !TP_FILMSIMULATION_ZEROCLUTSFOUND;Set HaldCLUT directory in Preferences !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_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, value 0 is used. !TP_GENERAL_11SCALE_TOOLTIP;The effects of this tool are only visible or only accurate at a preview scale of 1:1. !TP_GRADIENT_CENTER;Center !TP_GRADIENT_CENTER_X;Center X @@ -1909,6 +1921,8 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !TP_LABCURVE_CURVEEDITOR_LH;LH !TP_LABCURVE_CURVEEDITOR_LH_TOOLTIP;Luminance according to hue L=f(H) !TP_LABCURVE_CURVEEDITOR_LL_TOOLTIP;Luminance according to luminance L=f(L) +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected @@ -1935,6 +1949,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !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_PFCURVE_CURVEEDITOR_CH;Hue !TP_PFCURVE_CURVEEDITOR_CH_TOOLTIP;Controls defringe strength by color.\nHigher = more,\nLower = less. !TP_PREPROCESS_DEADPIXFILT;Dead pixel filter @@ -2110,6 +2125,8 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !TP_SAVEDIALOG_OK_TIP;Shortcut: Ctrl-Enter !TP_SHARPENING_BLUR;Blur radius !TP_SHARPENING_CONTRAST;Contrast threshold +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost !TP_SHARPENMICRO_CONTRAST;Contrast threshold !TP_SOFTLIGHT_LABEL;Soft Light !TP_SOFTLIGHT_STRENGTH;Strength diff --git a/rtdata/languages/Chinese (Simplified) b/rtdata/languages/Chinese (Simplified) index b01c39d84..61cbd58ac 100644 --- a/rtdata/languages/Chinese (Simplified) +++ b/rtdata/languages/Chinese (Simplified) @@ -973,6 +973,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !FILEBROWSER_SHOWUNCOLORHINT;Show images without a color label.\nShortcut: Alt-0 !FILEBROWSER_UNRANK_TOOLTIP;Unrank.\nShortcut: Shift-0 !GENERAL_CURRENT;Current +!GENERAL_HELP;Help !GENERAL_RESET;Reset !GENERAL_SAVE_AS;Save as... !GENERAL_SLIDER;Slider @@ -1340,6 +1341,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !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 @@ -1357,6 +1359,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !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 @@ -1377,6 +1380,13 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - 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 @@ -1391,6 +1401,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light !HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength !HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor +!HISTORY_MSG_TRANS_Method;Geometry - Method !ICCPROFCREATOR_COPYRIGHT;Copyright: !ICCPROFCREATOR_COPYRIGHT_RESET_TOOLTIP;Reset to the default copyright, granted to "RawTherapee, CC0" !ICCPROFCREATOR_CUSTOM;Custom @@ -1468,7 +1479,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 @@ -1732,6 +1743,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !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 @@ -1803,16 +1815,16 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral 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 !TP_FILMSIMULATION_ZEROCLUTSFOUND;Set HaldCLUT directory in Preferences !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_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, value 0 is used. !TP_GENERAL_11SCALE_TOOLTIP;The effects of this tool are only visible or only accurate at a preview scale of 1:1. !TP_GRADIENT_CENTER_X_TOOLTIP;Shift gradient to the left (negative values) or right (positive values). !TP_GRADIENT_CENTER_Y_TOOLTIP;Shift gradient up (negative values) or down (positive values). @@ -1874,6 +1886,8 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !TP_LABCURVE_LCREDSK_TIP;If enabled, the LC Curve affects only red and skin-tones.\nIf disabled, it applies to all tones. !TP_LABCURVE_RSTPROTECTION;Red and skin-tones protection !TP_LABCURVE_RSTPRO_TOOLTIP;Works on the Chromaticity slider and the CC curve. +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected @@ -1896,6 +1910,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !TP_NEUTRAL_TIP;Resets exposure sliders to neutral values.\nApplies to the same controls that Auto Levels applies to, regardless of whether you used Auto Levels or not. !TP_PCVIGNETTE_FEATHER_TOOLTIP;Feathering:\n0 = corners only,\n50 = halfway to center,\n100 = to center. !TP_PCVIGNETTE_ROUNDNESS_TOOLTIP;Roundness:\n0 = rectangle,\n50 = fitted ellipse,\n100 = circle. +!TP_PDSHARPENING_LABEL;Capture Sharpening !TP_PFCURVE_CURVEEDITOR_CH;Hue !TP_PFCURVE_CURVEEDITOR_CH_TOOLTIP;Controls defringe strength by color.\nHigher = more,\nLower = less. !TP_PREPROCESS_DEADPIXFILT;Dead pixel filter @@ -2078,6 +2093,8 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !TP_RETINEX_VIEW_UNSHARP;Unsharp mask !TP_SHARPENING_BLUR;Blur radius !TP_SHARPENING_CONTRAST;Contrast threshold +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost !TP_SHARPENMICRO_CONTRAST;Contrast threshold !TP_SHARPENMICRO_LABEL;Microcontrast !TP_SHARPENMICRO_MATRIX;3×3 matrix instead of 5×5 diff --git a/rtdata/languages/Czech b/rtdata/languages/Czech index ce16e057f..19182a1e5 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 @@ -961,8 +961,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Barva pozadí náhledu: bílá\nZkratka: 9 MAIN_TOOLTIP_BACKCOLOR3;Barva pozadí náhledu: středně šedá\nZkratka: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Zamknout / Odemknout pohled Před\n\nZamknout: ponechá pohled Před nezměněn.\nUžitečné pro posouzení výsledného efektu po použití více nástrojů.\nNavíc může být porovnání provedeno proti kterémukoli stavu v historii.\n\nOdemknout: pohled Před bude následovat pohled Poté, vždy jen o jeden krok zpět, představí vliv právě použitého nástroje. MAIN_TOOLTIP_HIDEHP;Zobrazit či schovat levý panel (obsahující historii).\nZkratka: l -MAIN_TOOLTIP_INDCLIPPEDH;Zvýraznit oříznutá světla.\nZkratka: < -MAIN_TOOLTIP_INDCLIPPEDS;Zvýraznit oříznuté stíny.\nZkratka: > +MAIN_TOOLTIP_INDCLIPPEDH;Zvýraznit oříznutá světla.\nZkratka: > +MAIN_TOOLTIP_INDCLIPPEDS;Zvýraznit oříznuté stíny.\nZkratka: < MAIN_TOOLTIP_PREVIEWB;Náhled modrého kanálu.\nZkratka: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Náhled masky zaostření.\nZkratka: Shift-f\n\nVíce přesné u snímků s nízkou hloubkou ostrosti, nízkým šumem a na vyšších úrovních zvětšení.\n\nPoužijte přiblížení v rozsahu 10 až 30% pro zlepšení přesnosti detekce u zašuměných snímků. MAIN_TOOLTIP_PREVIEWG;Náhled zeleného kanálu.\nZkratka: g @@ -2323,13 +2323,30 @@ 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. +!GENERAL_HELP;Help +!HISTORY_MSG_494;Capture Sharpening +!HISTORY_MSG_DEHAZE_LUMINANCE;Dehaze - Luminance only !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative !HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - Corner radius boost +!HISTORY_MSG_TRANS_Method;Geometry - Method !PARTIALPASTE_FILMNEGATIVE;Film Negative !PREFERENCES_APPEARANCE_PSEUDOHIDPI;Pseudo-HiDPI mode +!TP_DEHAZE_LUMINANCE;Luminance only !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral spots !TP_FILMNEGATIVE_RED;Red ratio +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic +!TP_PDSHARPENING_LABEL;Capture Sharpening +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 7967786dd..99835591a 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 06.10.2019 Erweiterung (TooWaBoo) RT 5.7 #84 18.07.2019 Erweiterung (TooWaBoo) RT 5.6 ABOUT_TAB_BUILD;Version @@ -808,6 +809,7 @@ HISTORY_MSG_490;(Dynamikkompression)\nIntensität HISTORY_MSG_491;(Weißabgleich) HISTORY_MSG_492;(RGB-Kurven) HISTORY_MSG_493;(L*a*b*) +HISTORY_MSG_494;(Eingangsschärfung) HISTORY_MSG_CLAMPOOG;(Belichtung) - Farben\nauf Farbraum beschränken HISTORY_MSG_COLORTONING_LABGRID_VALUE;(Farbanpassungen)\nL*a*b*-Farbkorrektur HISTORY_MSG_COLORTONING_LABREGION_AB;(Farbanpassungen)\nL*a*b*-Farbkorrektur\nBereich @@ -825,6 +827,7 @@ HISTORY_MSG_COLORTONING_LABREGION_SHOWMASK;(Farbanpassungen)\nL*a*b*-Farbkorrekt HISTORY_MSG_COLORTONING_LABREGION_SLOPE;(Farbanpassungen)\nL*a*b*-Farbkorrektur\nBereich - Steigung HISTORY_MSG_DEHAZE_DEPTH;(Bildschleier entfernen)\nTiefe HISTORY_MSG_DEHAZE_ENABLED;(Bildschleier entfernen) +HISTORY_MSG_DEHAZE_LUMINANCE;(Bildschleier entfernen)\nNur Luminanz 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 @@ -845,6 +848,13 @@ HISTORY_MSG_LOCALCONTRAST_LIGHTNESS;(Lokaler Kontrast)\nHelle Bereiche HISTORY_MSG_LOCALCONTRAST_RADIUS;(Lokaler Kontrast)\nRadius HISTORY_MSG_METADATA_MODE;(Metadaten)\nKopiermodus HISTORY_MSG_MICROCONTRAST_CONTRAST;(Mikrokontrast)\nKontrastschwelle +HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;(Eingangsschärfung)\nAuto-Schwelle +HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;(Eingangsschärfung)\nAuto-Radius +HISTORY_MSG_PDSHARPEN_CONTRAST;(Eingangsschärfung)\nKontrastschwelle +HISTORY_MSG_PDSHARPEN_GAMMA;(Eingangsschärfung)\nGamma +HISTORY_MSG_PDSHARPEN_ITERATIONS;(Eingangsschärfung)\nIterationen +HISTORY_MSG_PDSHARPEN_RADIUS;(Eingangsschärfung)\nRadius +HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;(Eingangsschärfung)\nRandschärfe erhöhen HISTORY_MSG_PIXELSHIFT_DEMOSAIC;(Sensor-Matrix)\nFarbinterpolation - PS\nBewegungsmethode HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;(Sensor-Matrix)\nVorverarbeitung\nRichtung HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;(Sensor-Matrix)\nVorverarbeitung\nPDAF-Zeilenfilter @@ -855,6 +865,7 @@ HISTORY_MSG_RAW_BORDER;(Sensor-Matrix)\nFarbinterpolation\nBildrand HISTORY_MSG_RESIZE_ALLOWUPSCALING;(Skalieren)\nHochskalieren zulassen HISTORY_MSG_SHARPENING_BLUR;(Schärfung)\nWeichzeichnerradius HISTORY_MSG_SHARPENING_CONTRAST;(Schärfung)\nKontrastschwelle +HISTORY_MSG_SHARPENING_GAMMA;(Schärfung) - Gamma HISTORY_MSG_SH_COLORSPACE;Farbraum HISTORY_MSG_SOFTLIGHT_ENABLED;(Weiches Licht) HISTORY_MSG_SOFTLIGHT_STRENGTH;(Weiches Licht)\nIntensität @@ -984,7 +995,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 @@ -1011,8 +1022,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Hintergrundfarbe der Vorschau: Weiß\nTaste: 9 MAIN_TOOLTIP_BACKCOLOR3;Hintergrundfarbe der Vorschau: Mittleres Grau\nTaste: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Vorher-Ansicht: Sperren / Entsperren\n\nGesperrt: Friert die Vorher-Ansicht ein, so\ndass sich die Gesamtwirkung mehrerer\nBearbeitungsschritte beurteilen lässt.\n\nEntsperrt: Die Vorher-Ansicht hinkt dem\naktuellen Bild immer einen Bearbeitungs-\nschritt hinterher. MAIN_TOOLTIP_HIDEHP;Linkes Bedienfeld ein-/ausblenden.\nTaste: l -MAIN_TOOLTIP_INDCLIPPEDH;Anzeige zu heller Bereiche ein-/ausschalten.\nTaste: < -MAIN_TOOLTIP_INDCLIPPEDS;Anzeige zu dunkler Bereiche ein-/ausschalten.\nTaste: > +MAIN_TOOLTIP_INDCLIPPEDH;Anzeige zu heller Bereiche ein-/ausschalten.\nTaste: > +MAIN_TOOLTIP_INDCLIPPEDS;Anzeige zu dunkler Bereiche ein-/ausschalten.\nTaste: < MAIN_TOOLTIP_PREVIEWB;Vorschau Blau-Kanal\nTaste: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Vorschau Fokusmaske\nTaste: Umschalt + f\n\nPräziser bei Bildern mit geringer Tiefenschärfe,\nniedrigem Rauschen und bei hoher Vergrößerung. MAIN_TOOLTIP_PREVIEWG;Vorschau Grün-Kanal\nTaste: g @@ -1613,6 +1624,7 @@ TP_DEFRINGE_RADIUS;Radius TP_DEFRINGE_THRESHOLD;Schwelle TP_DEHAZE_DEPTH;Tiefe TP_DEHAZE_LABEL;Bildschleier entfernen +TP_DEHAZE_LUMINANCE;Nur Luminanz TP_DEHAZE_SHOW_DEPTH_MAP;Maske anzeigen TP_DEHAZE_STRENGTH;Intensität TP_DIRPYRDENOISE_CHROMINANCE_AMZ;Auto-Multizonen @@ -1723,9 +1735,9 @@ 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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. TP_FILMNEGATIVE_LABEL;Filmnegativ -TP_FILMNEGATIVE_PICK;Weißen und schwarzen Bereich auswählen +TP_FILMNEGATIVE_PICK;Pick neutral spots 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? @@ -1875,6 +1887,7 @@ TP_PCVIGNETTE_ROUNDNESS;Form TP_PCVIGNETTE_ROUNDNESS_TOOLTIP;Form:\n0 = Rechteck\n50 = Ellipse\n100 = Kreis TP_PCVIGNETTE_STRENGTH;Intensität TP_PCVIGNETTE_STRENGTH_TOOLTIP;Filterstärke in Blendenstufen (bezogen auf die Bildecken). +TP_PDSHARPENING_LABEL;Eingangsschärfung TP_PERSPECTIVE_HORIZONTAL;Horizontal TP_PERSPECTIVE_LABEL;Perspektive TP_PERSPECTIVE_VERTICAL;Vertikal @@ -2104,12 +2117,14 @@ TP_SHARPENING_BLUR;Weichzeichnerradius TP_SHARPENING_CONTRAST;Kontrastschwelle TP_SHARPENING_EDRADIUS;Radius TP_SHARPENING_EDTOLERANCE;Kantentoleranz +TP_SHARPENING_GAMMA;Gamma TP_SHARPENING_HALOCONTROL;Halokontrolle TP_SHARPENING_HCAMOUNT;Intensität TP_SHARPENING_LABEL;Schärfung TP_SHARPENING_METHOD;Methode TP_SHARPENING_ONLYEDGES;Nur Kanten schärfen TP_SHARPENING_RADIUS;Radius +TP_SHARPENING_RADIUS_BOOST;Randschärfe erhöhen TP_SHARPENING_RLD;RL-Dekonvolution TP_SHARPENING_RLD_AMOUNT;Intensität TP_SHARPENING_RLD_DAMPING;Dämpfung @@ -2371,3 +2386,13 @@ 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. +!!!!!!!!!!!!!!!!!!!!!!!!! + +!GENERAL_HELP;Help +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_TRANS_Method;Geometry - Method +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic +!TP_SHARPENING_ITERCHECK;Auto limit iterations diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index 503e63860..2cb1d526d 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -88,7 +88,7 @@ TP_DIRPYREQUALIZER_ALGO;Skin Colour Range TP_DIRPYREQUALIZER_ALGO_TOOLTIP;Fine: closer to the colours of the skin, minimizing the action on other colours\nLarge: avoid more artifacts. TP_DIRPYREQUALIZER_TOOLTIP;Attempts to reduce artifacts in the transitions between skin colours (hue, chroma, luma) and the rest of the image. TP_EXPOSURE_CLAMPOOG;Clip out-of-gamut colours -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 colour cast. +TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no colour) in the original scene. The patches should differ in brightness. Set the white balance afterwards. TP_GRADIENT_CENTER;Centre TP_GRADIENT_CENTER_X;Centre X TP_GRADIENT_CENTER_Y;Centre Y @@ -340,6 +340,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !GENERAL_ENABLE;Enable !GENERAL_ENABLED;Enabled !GENERAL_FILE;File +!GENERAL_HELP;Help !GENERAL_LANDSCAPE;Landscape !GENERAL_NA;n/a !GENERAL_NO;No @@ -820,6 +821,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !HISTORY_MSG_491;White Balance !HISTORY_MSG_492;RGB Curves !HISTORY_MSG_493;L*a*b* Adjustments +!HISTORY_MSG_494;Capture Sharpening !HISTORY_MSG_COLORTONING_LABREGION_CHANNEL;CT - Channel !HISTORY_MSG_COLORTONING_LABREGION_CHROMATICITYMASK;CT - region C mask !HISTORY_MSG_COLORTONING_LABREGION_HUEMASK;CT - H mask @@ -834,6 +836,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !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 @@ -854,6 +857,13 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - 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 @@ -866,6 +876,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light !HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength !HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor +!HISTORY_MSG_TRANS_Method;Geometry - Method !HISTORY_NEWSNAPSHOT;Add !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !HISTORY_SNAPSHOT;Snapshot @@ -990,7 +1001,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 @@ -1012,8 +1023,8 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !MAIN_TAB_TRANSFORM_TOOLTIP;Shortcut: Alt-t !MAIN_TOOLTIP_BEFOREAFTERLOCK;Lock / Unlock the Before view\n\nLock: keep the Before view unchanged.\nUseful to evaluate the cumulative effect of multiple tools.\nAdditionally, comparisons can be made to any state in the History.\n\nUnlock: the Before view will follow the After view one step behind, showing the image before the effect of the currently used tool. !MAIN_TOOLTIP_HIDEHP;Show/Hide the left panel (including the history).\nShortcut: l -!MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: < -!MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: > +!MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: > +!MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: < !MAIN_TOOLTIP_PREVIEWB;Preview the blue channel.\nShortcut: b !MAIN_TOOLTIP_PREVIEWFOCUSMASK;Preview the focus mask.\nShortcut: Shift-f\n\nMore accurate on images with shallow depth of field, low noise and at higher zoom levels.\nZoom out to 10-30% to improve detection accuracy on noisy images. !MAIN_TOOLTIP_PREVIEWG;Preview the green channel.\nShortcut: g @@ -1568,6 +1579,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !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 @@ -1670,9 +1682,8 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !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_PICK;Pick neutral 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? @@ -1686,6 +1697,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !TP_FLATFIELD_BT_VERTHORIZ;Vertical + Horizontal !TP_FLATFIELD_BT_VERTICAL;Vertical !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, value 0 is used. !TP_FLATFIELD_LABEL;Flat-Field !TP_GENERAL_11SCALE_TOOLTIP;The effects of this tool are only visible or only accurate at a preview scale of 1:1. !TP_GRADIENT_CENTER_X_TOOLTIP;Shift gradient to the left (negative values) or right (positive values). @@ -1781,6 +1793,8 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !TP_LENSGEOM_AUTOCROP;Auto-Crop !TP_LENSGEOM_FILL;Auto-fill !TP_LENSGEOM_LABEL;Lens / Geometry +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected @@ -1808,6 +1822,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !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 @@ -2033,10 +2048,12 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !TP_SHARPENING_EDTOLERANCE;Edge tolerance !TP_SHARPENING_HALOCONTROL;Halo control !TP_SHARPENING_HCAMOUNT;Amount +!TP_SHARPENING_ITERCHECK;Auto limit iterations !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/languages/English (US) b/rtdata/languages/English (US) index 52caa23e4..d8c497f16 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -226,6 +226,7 @@ !GENERAL_ENABLE;Enable !GENERAL_ENABLED;Enabled !GENERAL_FILE;File +!GENERAL_HELP;Help !GENERAL_LANDSCAPE;Landscape !GENERAL_NA;n/a !GENERAL_NO;No @@ -727,6 +728,7 @@ !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 @@ -744,6 +746,7 @@ !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 @@ -764,6 +767,13 @@ !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - 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 @@ -778,6 +788,7 @@ !HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light !HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength !HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor +!HISTORY_MSG_TRANS_Method;Geometry - Method !HISTORY_NEWSNAPSHOT;Add !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !HISTORY_SNAPSHOT;Snapshot @@ -902,7 +913,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 @@ -929,8 +940,8 @@ !MAIN_TOOLTIP_BACKCOLOR3;Background color of the preview: middle grey\nShortcut: 9 !MAIN_TOOLTIP_BEFOREAFTERLOCK;Lock / Unlock the Before view\n\nLock: keep the Before view unchanged.\nUseful to evaluate the cumulative effect of multiple tools.\nAdditionally, comparisons can be made to any state in the History.\n\nUnlock: the Before view will follow the After view one step behind, showing the image before the effect of the currently used tool. !MAIN_TOOLTIP_HIDEHP;Show/Hide the left panel (including the history).\nShortcut: l -!MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: < -!MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: > +!MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: > +!MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: < !MAIN_TOOLTIP_PREVIEWB;Preview the blue channel.\nShortcut: b !MAIN_TOOLTIP_PREVIEWFOCUSMASK;Preview the focus mask.\nShortcut: Shift-f\n\nMore accurate on images with shallow depth of field, low noise and at higher zoom levels.\nZoom out to 10-30% to improve detection accuracy on noisy images. !MAIN_TOOLTIP_PREVIEWG;Preview the green channel.\nShortcut: g @@ -1531,6 +1542,7 @@ !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 @@ -1641,9 +1653,9 @@ !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral 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? @@ -1657,7 +1669,7 @@ !TP_FLATFIELD_BT_VERTHORIZ;Vertical + Horizontal !TP_FLATFIELD_BT_VERTICAL;Vertical !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_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, value 0 is used. !TP_FLATFIELD_LABEL;Flat-Field !TP_GENERAL_11SCALE_TOOLTIP;The effects of this tool are only visible or only accurate at a preview scale of 1:1. !TP_GRADIENT_CENTER;Center @@ -1765,6 +1777,8 @@ !TP_LENSGEOM_AUTOCROP;Auto-Crop !TP_LENSGEOM_FILL;Auto-fill !TP_LENSGEOM_LABEL;Lens / Geometry +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected @@ -1793,6 +1807,7 @@ !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 @@ -2023,10 +2038,12 @@ !TP_SHARPENING_EDTOLERANCE;Edge tolerance !TP_SHARPENING_HALOCONTROL;Halo control !TP_SHARPENING_HCAMOUNT;Amount +!TP_SHARPENING_ITERCHECK;Auto limit iterations !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/languages/Espanol b/rtdata/languages/Espanol index c91bd4a6b..c1468a6d9 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 @@ -979,8 +979,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Color de fondo de la previsualización: Blanco\nT MAIN_TOOLTIP_BACKCOLOR3;Color de fondo de la vista previa: Medio gris \nMétodo rápido: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Bloquear / Desbloquear la vista Antes\n\nBloquear: la vista Antes permanece inalterada - \nútil para evaluar el efecto acumulativo de varias herramientas.\nAdemás, se puede hacer una comparación con cualquier estado en el Historial\n\nDesbloquear: la vista Antes seguirá a la vista Después un paso por detrás, mostrando la imagen antes del efecto de la herramienta que se está usando MAIN_TOOLTIP_HIDEHP;Mostrar/Ocultar panel izquierdo (incluyendo historial).\nTecla de Atajo: i -MAIN_TOOLTIP_INDCLIPPEDH;Indicación de luces altas recortadas.\nTecla de Atajo: < -MAIN_TOOLTIP_INDCLIPPEDS;Indicación de sombras recortadas.\nTecla de Atajo: > +MAIN_TOOLTIP_INDCLIPPEDH;Indicación de luces altas recortadas.\nTecla de Atajo: > +MAIN_TOOLTIP_INDCLIPPEDS;Indicación de sombras recortadas.\nTecla de Atajo: < MAIN_TOOLTIP_PREVIEWB;Previsualización Canal azul.\nTecla de Atajo: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Previsualización Máscara de Foco.\nTecla de Atajo: Shift-F\n\nMás preciso en imágenes con poca profundidad de campo, bajo ruido y a mayores niveles de aumento\n\nPara mejorar la precisión en imágenes con ruido evalúe usando menor aumento (10%-30%)\n\nLa vista previa es realizada más lentamente cuando la Máscara de Foco esta activa. MAIN_TOOLTIP_PREVIEWG;Previsualización Canal verde.\nTecla de Atajo: g @@ -2321,9 +2321,20 @@ 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. +!GENERAL_HELP;Help +!HISTORY_MSG_494;Capture Sharpening +!HISTORY_MSG_DEHAZE_LUMINANCE;Dehaze - Luminance only !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative !HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - Corner radius boost !HISTORY_MSG_SHARPENING_BLUR;Sharpening - Blur radius +!HISTORY_MSG_TRANS_Method;Geometry - Method !MAIN_FRAME_PLACES_DEL;Remove !MAIN_TAB_FAVORITES;Favorites !MAIN_TAB_FAVORITES_TOOLTIP;Shortcut: Alt-u @@ -2345,18 +2356,24 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nTecla de Atajo: - !PROGRESSBAR_RAWCACORR;Raw CA correction... !QUEUE_LOCATION_TITLE;Output Location !TP_CROP_PPI;PPI +!TP_DEHAZE_LUMINANCE;Luminance only !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral spots !TP_FILMNEGATIVE_RED;Red ratio +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected !TP_LENSPROFILE_MODE_HEADER;Lens Profile !TP_LENSPROFILE_USE_GEOMETRIC;Geometric distortion !TP_LENSPROFILE_USE_HEADER;Correct +!TP_PDSHARPENING_LABEL;Capture Sharpening !TP_RAW_IMAGENUM_SN;SN mode !TP_RAW_XTRANS;X-Trans !TP_RAW_XTRANSFAST;Fast X-Trans !TP_SHARPENING_BLUR;Blur radius +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 2c5017a6e..a98b6eded 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 @@ -916,8 +916,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Couleur de fond de l'aperçu: Blanc\nRaccourci: < MAIN_TOOLTIP_BACKCOLOR3;Couleur de fond de l'aperçu: Gris moyen\nRaccourci : 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Vérouille / déverouille la vue Avant\n\nVérouille: garde la vue Avant inchangée - \nutile pour évaluer l'effet cumulatif de plusieurs outils.\nDe plus, une comparaison peut être faite à partir de n'importe quelle étape de l'historique\n\nDéverouille: la vue Avant représentera l'étape précédant la vue Après, montrant l'effet qui vient d'être modifié MAIN_TOOLTIP_HIDEHP;Montrer/cacher le panneau gauche (incluant l'historique)\nRaccourci: l -MAIN_TOOLTIP_INDCLIPPEDH;Indication hautes lumières hors domaine\nRaccourci: < -MAIN_TOOLTIP_INDCLIPPEDS;Indication ombres hors domaine\nRaccourci: > +MAIN_TOOLTIP_INDCLIPPEDH;Indication hautes lumières hors domaine\nRaccourci: > +MAIN_TOOLTIP_INDCLIPPEDS;Indication ombres hors domaine\nRaccourci: < MAIN_TOOLTIP_PREVIEWB;Affichage du canal Bleu\nRaccourci: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Affichage du Masque du focus\nRaccourci: Shift-f\n\nPlus précis sur les images avec une faible profondeur de champ, à faible bruit et à des niveaux de zoom élevé\n\nPour améliorer la précision de détection des images bruitées, évaluez les à un facteur de zoom de 10-30%\n\nLa prévisualisation met plus de temps à se calculer lorsque cet outil est actif. MAIN_TOOLTIP_PREVIEWG;Affichage du canal Vert\nRaccourci: g @@ -2266,8 +2266,19 @@ 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. +!GENERAL_HELP;Help +!HISTORY_MSG_494;Capture Sharpening +!HISTORY_MSG_DEHAZE_LUMINANCE;Dehaze - Luminance only !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative !HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - Corner radius boost +!HISTORY_MSG_TRANS_Method;Geometry - Method !MAIN_FRAME_PLACES_DEL;Remove !PARTIALPASTE_FILMNEGATIVE;Film Negative !PROGRESSBAR_DECODING;Decoding... @@ -2278,16 +2289,22 @@ ZOOMPANEL_ZOOMOUT;Zoom Arrière\nRaccourci: - !PROGRESSBAR_RAWCACORR;Raw CA correction... !QUEUE_LOCATION_TITLE;Output Location !TP_CROP_PPI;PPI +!TP_DEHAZE_LUMINANCE;Luminance only !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral spots !TP_FILMNEGATIVE_RED;Red ratio +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected !TP_LENSPROFILE_MODE_HEADER;Lens Profile !TP_LENSPROFILE_USE_GEOMETRIC;Geometric distortion !TP_LENSPROFILE_USE_HEADER;Correct +!TP_PDSHARPENING_LABEL;Capture Sharpening !TP_RAW_XTRANS;X-Trans !TP_RAW_XTRANSFAST;Fast X-Trans +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost diff --git a/rtdata/languages/Italiano b/rtdata/languages/Italiano index 977277a73..340309b9f 100644 --- a/rtdata/languages/Italiano +++ b/rtdata/languages/Italiano @@ -519,8 +519,8 @@ MAIN_TOOLTIP_BACKCOLOR1;Colore di sfondo dell'anteprima: Nero\nScorciatoi MAIN_TOOLTIP_BACKCOLOR2;Colore di sfondo dell'anteprima: Bianco\nScorciatoia: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Blocca/Sblocca la vista Prima\n\nBlocca: Conserva la vista Prima.\nUtile per valutare l'effetto cumulativo di diversi strumenti.\nIn più, possono essere confrontati diversi passi della cronologia.\n\nSblocca: la vista Prima segue di un passo la vista Dopo, mostrando l'immagine prima dell'effetto dello strumento corrente. MAIN_TOOLTIP_HIDEHP;Mostra/Nascondi il pannello sinistro (inclusa la cronologia)\nScorciatoia: l -MAIN_TOOLTIP_INDCLIPPEDH;Indicazione delle alteluci tosate.\nScorciatoia: < -MAIN_TOOLTIP_INDCLIPPEDS;Indicazione delle ombre tosate.\nScorciatoia: > +MAIN_TOOLTIP_INDCLIPPEDH;Indicazione delle alteluci tosate.\nScorciatoia: > +MAIN_TOOLTIP_INDCLIPPEDS;Indicazione delle ombre tosate.\nScorciatoia: < MAIN_TOOLTIP_PREVIEWB;Anteprima del Canale Blu.\nScorciatoia: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Anteprima della Focus Mask.\nScorciatoia: Maiuscolo-F\n\nPiù accurato su immagini con bassa profondità di campo, poco rumore e ad elevati livelli di zoom.\n\nPer aumentare l'accuratezza della rilevazione su immagini con molto rumore, riduci le dimensioni del 10-30%. MAIN_TOOLTIP_PREVIEWG;Anteprima del Canale Verde.\nScorciatoia: g @@ -1285,6 +1285,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !GENERAL_APPLY;Apply !GENERAL_ASIMAGE;As Image !GENERAL_CURRENT;Current +!GENERAL_HELP;Help !GENERAL_OPEN;Open !GENERAL_RESET;Reset !GENERAL_SAVE_AS;Save as... @@ -1518,6 +1519,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !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 @@ -1535,6 +1537,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !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 @@ -1555,6 +1558,13 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - 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 @@ -1569,6 +1579,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light !HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength !HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor +!HISTORY_MSG_TRANS_Method;Geometry - Method !ICCPROFCREATOR_COPYRIGHT;Copyright: !ICCPROFCREATOR_COPYRIGHT_RESET_TOOLTIP;Reset to the default copyright, granted to "RawTherapee, CC0" !ICCPROFCREATOR_CUSTOM;Custom @@ -1640,7 +1651,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 @@ -1852,6 +1863,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !TP_CROP_SELECTCROP;Select !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 @@ -1908,16 +1920,16 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral 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 !TP_FILMSIMULATION_ZEROCLUTSFOUND;Set HaldCLUT directory in Preferences !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_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, value 0 is used. !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. !TP_ICM_APPLYHUESATMAP;Base table @@ -1935,6 +1947,8 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !TP_ICM_WORKING_TRC_NONE;None !TP_ICM_WORKING_TRC_SLOPE;Slope !TP_ICM_WORKING_TRC_TOOLTIP;Only for built-in profiles. +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected @@ -1954,6 +1968,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !TP_METADATA_STRIP;Strip all metadata !TP_METADATA_TUNNEL;Copy unchanged !TP_NEUTRAL;Reset +!TP_PDSHARPENING_LABEL;Capture Sharpening !TP_PREPROCESS_DEADPIXFILT;Dead pixel filter !TP_PREPROCESS_DEADPIXFILT_TOOLTIP;Tries to suppress dead pixels. !TP_PREPROCESS_HOTPIXFILT;Hot pixel filter @@ -2119,6 +2134,8 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !TP_RETINEX_VIEW_UNSHARP;Unsharp mask !TP_SHARPENING_BLUR;Blur radius !TP_SHARPENING_CONTRAST;Contrast threshold +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost !TP_SHARPENMICRO_CONTRAST;Contrast threshold !TP_SOFTLIGHT_LABEL;Soft Light !TP_SOFTLIGHT_STRENGTH;Strength diff --git a/rtdata/languages/Japanese b/rtdata/languages/Japanese index 96ffea174..b7c0b7e22 100644 --- a/rtdata/languages/Japanese +++ b/rtdata/languages/Japanese @@ -8,30 +8,6 @@ #08 2012-12-22 a3novy #09 2013-04-01 a3novy #10 2013-04-19 a3novy -#11 2013-09-10 firefly -#12 2013-10-28 firefly -#13 2014-01-07 firefly -#14 2014-01-15 firefly -#15 2014-02-25 firefly -#16 2014-04-07 firefly -#17 2014-04-08 firefly -#18 2014-05-16 firefly -#19 2014-07-13 firefly -#20 2014-07-24 firefly -#21 2014-09-11 firefly -#22 2014-10-21 firefly -#23 2014-11-07 firefly -#24 2014-11-18 firefly -#25 2015-01-05 firefly -#26 2015-02-17 firefly -#27 2015-02-21 firefly -#28 2015-03-03 firefly -#29 2015-04-20 firefly -#30 2015-05-01 firefly -#31 2015-05-31 firefly -#32 2015-06-13 firefly -#33 2015-07-20 firefly -#34 2015-08-12 firefly ABOUT_TAB_BUILD;バージョン ABOUT_TAB_CREDITS;クレジット @@ -49,7 +25,7 @@ CURVEEDITOR_CURVE;カーブ CURVEEDITOR_CURVES;カーブ CURVEEDITOR_CUSTOM;カスタム CURVEEDITOR_DARKS;ダーク -CURVEEDITOR_EDITPOINT_HINT;ボタンを押すと数値で入出力を編集出来ます\n\n編集したいカーブ上のポイントを右クリックします\n編集を無効にする場合はポイント以外の部分んで右クリックします +CURVEEDITOR_EDITPOINT_HINT;ボタンを押すと数値で入出力を編集出来ます\n\n編集したいカーブ上のポイントを右クリックします\n編集を無効にする場合はポイント以外の部分で右クリックします CURVEEDITOR_HIGHLIGHTS;ハイライト CURVEEDITOR_LIGHTS;ライト CURVEEDITOR_LINEAR;リニア @@ -489,8 +465,8 @@ HISTORY_MSG_205;CAM02 ホット/バッドピクセル HISTORY_MSG_206;CAT02 - 自動で順応 HISTORY_MSG_207;フリンジ低減 - 色相カーブ HISTORY_MSG_208;ブルー/レッド イコライザ -HISTORY_MSG_210;グラデーションフィルター - 角度 -HISTORY_MSG_211;グラデーションフィルター +HISTORY_MSG_210;減光フィルター - 角度 +HISTORY_MSG_211;減光フィルター HISTORY_MSG_212;ビネットフィルター - 強さ HISTORY_MSG_213;ビネットフィルター HISTORY_MSG_214;白黒 @@ -517,10 +493,10 @@ HISTORY_MSG_234;白黒 ‘後の‘カーブのタイプ HISTORY_MSG_235;白黒 チャンネルミキサー 自動 HISTORY_MSG_236;--未使用-- HISTORY_MSG_237;白黒 チャンネルミキサー -HISTORY_MSG_238;グラデーションフィルター フェザー処理 -HISTORY_MSG_239;グラデーションフィルター 強さ -HISTORY_MSG_240;グラデーションフィルター 中央 -HISTORY_MSG_241;ビネットフィルター フェザー処理 +HISTORY_MSG_238;減光フィルター フェザー +HISTORY_MSG_239;減光フィルター 強さ +HISTORY_MSG_240;減光フィルター 中央 +HISTORY_MSG_241;ビネットフィルター フェザー HISTORY_MSG_242;ビネットフィルター 形状 HISTORY_MSG_243;半径 HISTORY_MSG_244;ビネットフィルター 強さ @@ -757,6 +733,7 @@ HISTORY_MSG_490;DRC - 量 HISTORY_MSG_491;ホワイトバランス HISTORY_MSG_492;RGBカーブ HISTORY_MSG_493;L*a*b*調整 +HISTORY_MSG_494;キャプチャーシャープニング HISTORY_MSG_CLAMPOOG;色域外の色を切り取る HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - カラー補正 HISTORY_MSG_COLORTONING_LABREGION_AB;CT - 色の補正 @@ -774,6 +751,7 @@ HISTORY_MSG_COLORTONING_LABREGION_SHOWMASK;CT - マスクの表示 HISTORY_MSG_COLORTONING_LABREGION_SLOPE;CT - スロープ HISTORY_MSG_DEHAZE_DEPTH;霞除去 - 深度 HISTORY_MSG_DEHAZE_ENABLED;霞除去 +HISTORY_MSG_DEHAZE_LUMINANCE;霞除去 - 輝度のみ HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;霞除去 - 深度マップの表示 HISTORY_MSG_DEHAZE_STRENGTH;霞除去 - 強さ HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;デュアルデモザイク - 自動しきい値 @@ -794,6 +772,13 @@ HISTORY_MSG_LOCALCONTRAST_LIGHTNESS;ローカルコントラスト - 明るい HISTORY_MSG_LOCALCONTRAST_RADIUS;ローカルコントラスト - 半径 HISTORY_MSG_METADATA_MODE;メタデータ コピーモード HISTORY_MSG_MICROCONTRAST_CONTRAST;マイクロコントラスト - コントラストのしきい値 +HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - しきい値の自動設定 +HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - シグマの自動設定 +HISTORY_MSG_PDSHARPEN_CHECKITER;CS - 繰り返しの自動制限 +HISTORY_MSG_PDSHARPEN_CONTRAST;CS - コントラストのしきい値 +HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - 繰り返し +HISTORY_MSG_PDSHARPEN_RADIUS;CS - シグマ +HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - 周辺のシグマを増やす HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - 振れに対するデモザイクの方式 HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;ラインノイズフィルタの方向 HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAFラインフィルタ @@ -933,7 +918,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 @@ -1023,7 +1008,7 @@ PARTIALPASTE_FLATFIELDBLURRADIUS;フラットフィールド ぼかし半径 PARTIALPASTE_FLATFIELDBLURTYPE;フラットフィールド ぼかしタイプ PARTIALPASTE_FLATFIELDCLIPCONTROL;フラットフィールド クリップコントロール PARTIALPASTE_FLATFIELDFILE;フラットフィールド ファイル -PARTIALPASTE_GRADIENT;グラデーションフィルター +PARTIALPASTE_GRADIENT;減光フィルター PARTIALPASTE_HSVEQUALIZER;HSV イコライザ PARTIALPASTE_ICMSETTINGS;ICM 設定 PARTIALPASTE_IMPULSEDENOISE;インパルス・ノイズ低減 @@ -1562,6 +1547,7 @@ TP_DEFRINGE_RADIUS;半径 TP_DEFRINGE_THRESHOLD;しきい値 TP_DEHAZE_DEPTH;深度 TP_DEHAZE_LABEL;霞除去 +TP_DEHAZE_LUMINANCE;輝度のみ TP_DEHAZE_SHOW_DEPTH_MAP;深度マップの表示 TP_DEHAZE_STRENGTH;強さ TP_DIRPYRDENOISE_CHROMINANCE_AMZ;自動(多分割方式) @@ -1672,9 +1658,9 @@ 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_GUESS_TOOLTIP;原画像の中で色相がニュートラルな部分2か所をピックすることでレッドとブルーの比率を自動で設定します。明るさが異なる2か所をピックします。その後、ホワイトバランスを設定します。 TP_FILMNEGATIVE_LABEL;ネガフィルム -TP_FILMNEGATIVE_PICK;白と黒のポイントをピックアップする +TP_FILMNEGATIVE_PICK;ニュートラルなポイントをピック TP_FILMNEGATIVE_RED;レッドの比率 TP_FILMSIMULATION_LABEL;フィルムシミュレーション TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapeeはフィルムシミュレーション機能に使う画像をHald CLUTフォルダーの中から探すよう設計されています(プログラムに組み込むにはフォルダーが大き過ぎるため)。\n変更するには、環境設定 > 画像処理 > フィルムシミュレーションと進み\nどのフォルダーが使われているか確認します。機能を利用する場合は、Hald CLUTだけが入っているフォルダーを指定するか、 この機能を使わない場合はそのフォルダーを空にしておきます。\n\n詳しくはRawPediaを参照して下さい。\n\nフィルム画像のスキャンを止めますか? @@ -1698,9 +1684,9 @@ TP_GRADIENT_CENTER_Y;中央 Y軸 TP_GRADIENT_CENTER_Y_TOOLTIP;アンカーポイントの位置 y軸: -100=上端, 0=中央, +100=下端 TP_GRADIENT_DEGREE;角度 TP_GRADIENT_DEGREE_TOOLTIP;回転角度の度数 -TP_GRADIENT_FEATHER;フェザー処理 -TP_GRADIENT_FEATHER_TOOLTIP;対角線に対するグラデーションの幅の割合 -TP_GRADIENT_LABEL;グラデーションフィルター +TP_GRADIENT_FEATHER;フェザー +TP_GRADIENT_FEATHER_TOOLTIP;対角線に対する減光の幅の割合 +TP_GRADIENT_LABEL;減光フィルター TP_GRADIENT_STRENGTH;強さ TP_GRADIENT_STRENGTH_TOOLTIP;終点位置でのフィルターの強さ TP_HLREC_BLEND;ブレンド @@ -1817,13 +1803,14 @@ TP_METADATA_STRIP;メタデータを全て取り除く TP_METADATA_TUNNEL;変更なしでコピー TP_NEUTRAL;リセット TP_NEUTRAL_TIP;露光量補正のスライダー値をニュートラルにリセットします。\n自動露光補正の調整値ついても同様にリセットされます -TP_PCVIGNETTE_FEATHER;フェザー処理 -TP_PCVIGNETTE_FEATHER_TOOLTIP;フェザー処理: 0=四隅だけ、50=中央までの半分、100=中央まで +TP_PCVIGNETTE_FEATHER;フェザー +TP_PCVIGNETTE_FEATHER_TOOLTIP;フェザー: 0=四隅だけ、50=中央までの半分、100=中央まで TP_PCVIGNETTE_LABEL;ビネットフィルター TP_PCVIGNETTE_ROUNDNESS;フィルター形状 TP_PCVIGNETTE_ROUNDNESS_TOOLTIP;形状: 0=長方形、50=楕円形、100=円形 TP_PCVIGNETTE_STRENGTH;強さ TP_PCVIGNETTE_STRENGTH_TOOLTIP;終点位置でのフィルターの強さ(四隅) +TP_PDSHARPENING_LABEL;キャプチャーシャープニング TP_PERSPECTIVE_HORIZONTAL;水平 TP_PERSPECTIVE_LABEL;パースペクティブ TP_PERSPECTIVE_VERTICAL;垂直 @@ -2054,10 +2041,12 @@ TP_SHARPENING_EDRADIUS;半径 TP_SHARPENING_EDTOLERANCE;エッジ許容 TP_SHARPENING_HALOCONTROL;ハロ抑制 TP_SHARPENING_HCAMOUNT;適用量 +TP_SHARPENING_ITERCHECK;繰り返しの自動制限 TP_SHARPENING_LABEL;シャープニング TP_SHARPENING_METHOD;方式 TP_SHARPENING_ONLYEDGES;エッジのみシャープニング TP_SHARPENING_RADIUS;半径 +TP_SHARPENING_RADIUS_BOOST;周辺のシグマを増やす TP_SHARPENING_RLD;RL デコンボリューション TP_SHARPENING_RLD_AMOUNT;適用量 TP_SHARPENING_RLD_DAMPING;減衰 @@ -2311,6 +2300,7 @@ TP_WBALANCE_TUNGSTEN;タングステン TP_WBALANCE_WATER1;水中 1 TP_WBALANCE_WATER2;水中 2 TP_WBALANCE_WATER_HEADER;水中 +The last update by firefly 2019-12-21 ZOOMPANEL_100;(100%) ZOOMPANEL_NEWCROPWINDOW;新規ディテール ウィンドウを開く ZOOMPANEL_ZOOM100;100%にズーム\nショートカット: z @@ -2319,3 +2309,11 @@ ZOOMPANEL_ZOOMFITSCREEN;画像全体を画面に合わせる\nショートカッ ZOOMPANEL_ZOOMIN;ズームイン\nショートカット: + ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - +!!!!!!!!!!!!!!!!!!!!!!!!! +! Untranslated keys follow; remove the ! prefix after an entry is translated. +!!!!!!!!!!!!!!!!!!!!!!!!! + +!GENERAL_HELP;Help +!HISTORY_MSG_TRANS_Method;Geometry - Method +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic 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 26f1b1aa0..7ecdc6f3b 100644 --- a/rtdata/languages/Magyar +++ b/rtdata/languages/Magyar @@ -908,6 +908,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !GENERAL_AUTO;Automatic !GENERAL_CLOSE;Close !GENERAL_CURRENT;Current +!GENERAL_HELP;Help !GENERAL_OPEN;Open !GENERAL_RESET;Reset !GENERAL_SAVE_AS;Save as... @@ -1227,6 +1228,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !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 @@ -1244,6 +1246,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !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 @@ -1264,6 +1267,13 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - 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 @@ -1278,6 +1288,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light !HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength !HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor +!HISTORY_MSG_TRANS_Method;Geometry - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !ICCPROFCREATOR_COPYRIGHT;Copyright: !ICCPROFCREATOR_COPYRIGHT_RESET_TOOLTIP;Reset to the default copyright, granted to "RawTherapee, CC0" @@ -1357,7 +1368,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 @@ -1741,6 +1752,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !TP_CROP_SELECTCROP;Select !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 @@ -1821,16 +1833,16 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral 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 !TP_FILMSIMULATION_ZEROCLUTSFOUND;Set HaldCLUT directory in Preferences !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_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, value 0 is used. !TP_GENERAL_11SCALE_TOOLTIP;The effects of this tool are only visible or only accurate at a preview scale of 1:1. !TP_GRADIENT_CENTER;Center !TP_GRADIENT_CENTER_X;Center X @@ -1901,6 +1913,8 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !TP_LABCURVE_LCREDSK_TIP;If enabled, the LC Curve affects only red and skin-tones.\nIf disabled, it applies to all tones. !TP_LABCURVE_RSTPROTECTION;Red and skin-tones protection !TP_LABCURVE_RSTPRO_TOOLTIP;Works on the Chromaticity slider and the CC curve. +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected @@ -1928,6 +1942,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !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_PFCURVE_CURVEEDITOR_CH;Hue !TP_PFCURVE_CURVEEDITOR_CH_TOOLTIP;Controls defringe strength by color.\nHigher = more,\nLower = less. !TP_PREPROCESS_DEADPIXFILT;Dead pixel filter @@ -2103,6 +2118,8 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !TP_SAVEDIALOG_OK_TIP;Shortcut: Ctrl-Enter !TP_SHARPENING_BLUR;Blur radius !TP_SHARPENING_CONTRAST;Contrast threshold +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost !TP_SHARPENMICRO_CONTRAST;Contrast threshold !TP_SOFTLIGHT_LABEL;Soft Light !TP_SOFTLIGHT_STRENGTH;Strength diff --git a/rtdata/languages/Nederlands b/rtdata/languages/Nederlands index 43afc8efa..c43f6314e 100644 --- a/rtdata/languages/Nederlands +++ b/rtdata/languages/Nederlands @@ -788,8 +788,8 @@ MAIN_TOOLTIP_BACKCOLOR1;Achtergrond kleur van het voorbeeld: Zwart\nSnelt MAIN_TOOLTIP_BACKCOLOR2;Achtergrond kleur van het voorbeeld: Wit\nSneltoets: 0 MAIN_TOOLTIP_BEFOREAFTERLOCK;Vergrendel / Ontgrendel de Voorafbeelding.\n\nVergrendel: hou de Voorafbeelding ongewijzigd.\nDit is handig om het cumulatieve effect van meerdere gereedschappen te beoordelen.\nBovendien kan er worden vergeleken met elke stap in de geschiedenislijst.\n\nOntgrendel: de Voorafbeelding volgt een stap achter de Naafbeelding en laat de afbeelding zien zonder het effect van het huidige gereedschap. MAIN_TOOLTIP_HIDEHP;Toon/verberg linkerpaneel (geschiedenis).\nSneltoets: H -MAIN_TOOLTIP_INDCLIPPEDH;Overbelichtingsindicatie.\nSneltoets: < -MAIN_TOOLTIP_INDCLIPPEDS;Onderbelichtingsindicatie.\nSneltoets: > +MAIN_TOOLTIP_INDCLIPPEDH;Overbelichtingsindicatie.\nSneltoets: > +MAIN_TOOLTIP_INDCLIPPEDS;Onderbelichtingsindicatie.\nSneltoets: < MAIN_TOOLTIP_PREVIEWB;Bekijk het Blauwe kanaal.\nSneltoets: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Bekijk het Focus Masker.\nSneltoets: Shift-F\n\nAccurater bij afbeeldingen met geringe scherptediepte, weinig ruis en hogere zoomniveaus.\n\nBekijk de afbeelding op lagere zoomniveaus (10-30%) om de accuratesse te vergroten bij afbeeldingen met veel ruis.\n\nHet voorbeeld wordt langzamer aangemaakt als Focus Masker aanstaat. MAIN_TOOLTIP_PREVIEWG;Bekijk het Groene kanaal.\nSneltoets: g @@ -1982,6 +1982,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !FILEBROWSER_POPUPREMOVEINCLPROC;Delete permanently, including queue-processed version !FILEBROWSER_SHOWNOTTRASHHINT;Show only images not in trash. !GENERAL_CURRENT;Current +!GENERAL_HELP;Help !GENERAL_RESET;Reset !GENERAL_SAVE_AS;Save as... !GENERAL_SLIDER;Slider @@ -2015,6 +2016,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !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 @@ -2032,6 +2034,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !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 @@ -2052,6 +2055,13 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - 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 @@ -2066,6 +2076,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light !HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength !HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor +!HISTORY_MSG_TRANS_Method;Geometry - Method !ICCPROFCREATOR_COPYRIGHT;Copyright: !ICCPROFCREATOR_COPYRIGHT_RESET_TOOLTIP;Reset to the default copyright, granted to "RawTherapee, CC0" !ICCPROFCREATOR_CUSTOM;Custom @@ -2111,7 +2122,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 @@ -2226,6 +2237,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !TP_CROP_SELECTCROP;Select !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_CURVE_TOOLTIP;Increase (multiply) the value of all chrominance sliders.\nThis curve lets you adjust the strength of chromatic noise reduction as a function of chromaticity, for instance to increase the action in areas of low saturation and to decrease it in those of high saturation. @@ -2235,9 +2247,9 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral spots !TP_FILMNEGATIVE_RED;Red ratio !TP_ICM_WORKING_TRC;Tone response curve: !TP_ICM_WORKING_TRC_CUSTOM;Custom @@ -2245,6 +2257,8 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !TP_ICM_WORKING_TRC_NONE;None !TP_ICM_WORKING_TRC_SLOPE;Slope !TP_ICM_WORKING_TRC_TOOLTIP;Only for built-in profiles. +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected @@ -2263,6 +2277,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !TP_METADATA_MODE;Metadata copy mode !TP_METADATA_STRIP;Strip all metadata !TP_METADATA_TUNNEL;Copy unchanged +!TP_PDSHARPENING_LABEL;Capture Sharpening !TP_PREPROCESS_LINEDENOISE_DIRECTION;Direction !TP_PREPROCESS_LINEDENOISE_DIRECTION_BOTH;Both !TP_PREPROCESS_LINEDENOISE_DIRECTION_HORIZONTAL;Horizontal @@ -2300,6 +2315,8 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !TP_RETINEX_MAP;Method !TP_SHARPENING_BLUR;Blur radius !TP_SHARPENING_CONTRAST;Contrast threshold +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost !TP_SHARPENMICRO_CONTRAST;Contrast threshold !TP_SOFTLIGHT_LABEL;Soft Light !TP_SOFTLIGHT_STRENGTH;Strength diff --git a/rtdata/languages/Polish b/rtdata/languages/Polish index 528b6a198..b4e1a2281 100644 --- a/rtdata/languages/Polish +++ b/rtdata/languages/Polish @@ -7,6 +7,8 @@ #07 2012-04-02 DrSlony #08 2013-05-21 DrSlony #09 2014-10-16 DrSlony +#10 2020-02-02 Bartłomiej Wiśniowski +#11 2020-02-02 Bartłomiej Wiśniowski ABOUT_TAB_BUILD;Wersja ABOUT_TAB_CREDITS;Zasługi @@ -14,6 +16,7 @@ ABOUT_TAB_LICENSE;Licencja ABOUT_TAB_RELEASENOTES;Notatki eksploatacyjne ABOUT_TAB_SPLASH;Ekran powitalny BATCH_PROCESSING;Przetwarzanie wsadowe +CURVEEDITOR_CATMULLROM;Elastyczny CURVEEDITOR_CURVE;Krzywa CURVEEDITOR_CURVES;Krzywe CURVEEDITOR_CUSTOM;Własna @@ -34,6 +37,14 @@ CURVEEDITOR_TOOLTIPPASTE;Wstaw krzywą ze schowka CURVEEDITOR_TOOLTIPSAVE;Zapisz krzywą CURVEEDITOR_TYPE;Typ: DIRBROWSER_FOLDERS;Katalogi +DYNPROFILEEDITOR_DELETE;Usuń +DYNPROFILEEDITOR_EDIT;Edytuj +DYNPROFILEEDITOR_IMGTYPE_ANY;Każdy +DYNPROFILEEDITOR_IMGTYPE_STD;Standardowy +DYNPROFILEEDITOR_MOVE_DOWN;Przesuń w dół +DYNPROFILEEDITOR_MOVE_UP;Przesuń w górę +DYNPROFILEEDITOR_NEW;Nowy +DYNPROFILEEDITOR_PROFILE;Profil przetwarzania EDITWINDOW_TITLE;Edytor obrazu EDIT_OBJECT_TOOLTIP;Wyświetla widżet na podglądzie który ułatwia ustawienie narzędzia. EDIT_PIPETTE_TOOLTIP;Aby dodać punkt do krzywej należy trzymac wciśnięty klawisz Ctrl podczas kliknięcia lewym guzikiem myszki na danym obszarze głównego podglądu.\nAby zmienic ustawienie już istniejącego punktu, należy trzymać wduszony klawisz Ctrl podczas kliknięcia lewym guzikiem myszki na danym obszarze głównego podglądu, następnie należy puścić klawisz Ctrl (chyba że chodzi nam o bardzo precyzyjne ustawienie dzieki spowolnieniu jakie trzymanie klawisza Ctrl nam daje) i podczas trzymania lewego guzika myszki należy myszką ruszać w pionie aby odpowiednio manipulować punktem w pionie. @@ -42,6 +53,7 @@ EXIFFILTER_CAMERA;Aparat EXIFFILTER_EXPOSURECOMPENSATION;Korekcja ekspozycji (EV) EXIFFILTER_FILETYPE;Typ pliku EXIFFILTER_FOCALLEN;Wartość ogniskowej +EXIFFILTER_IMAGETYPE;Typ obrazu EXIFFILTER_ISO;ISO EXIFFILTER_LENS;Obiektyw EXIFFILTER_METADATAFILTER;Włącz filtry metadanych @@ -59,6 +71,7 @@ EXIFPANEL_RESET;Przywróć EXIFPANEL_RESETALL;Przywróć wszystkie EXIFPANEL_RESETALLHINT;Przywraca orginalne wartości etykiet EXIFPANEL_RESETHINT;Przywraca orginalne wartości wybranych etykiet +EXIFPANEL_SHOWALL;Pokaż wszystkie EXIFPANEL_SUBDIRECTORY;Podkatalog EXPORT_BYPASS_ALL;Zaznacz / Odznacz wszystkie EXPORT_BYPASS_DEFRINGE;Pomiń usuwanie widma @@ -90,6 +103,8 @@ FILEBROWSER_AUTODARKFRAME;Automatyczne użycie czarnej klatki FILEBROWSER_AUTOFLATFIELD;Automatyczne użycie klatki typu puste pole FILEBROWSER_BROWSEPATHHINT;Umożliwia przeglądanie wprowadzonej ścieżki\nCtrl-o zaznaczenie\nEnter, Ctrl-Enter (w menedżerze plików) przeglądanie\nSkróty:\n ~ - katalog domowy użytkownika\n ! - katalog z obrazami użytkownia FILEBROWSER_CACHE;Pamięć podręczna +FILEBROWSER_CACHECLEARFROMFULL;Wyczyść wszystkie profile +FILEBROWSER_CACHECLEARFROMPARTIAL;Wyczyść wszystkie, oprócz znajdujących się w pamięci podręcznej FILEBROWSER_CLEARPROFILE;Wyczyść profil FILEBROWSER_COLORLABEL_TOOLTIP;Kolorowe etykiety\n\nUżyj za pomocą rozwijanej listy lub skrótów:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Czerwona\nShift-Ctrl-2 Żółta\nShift-Ctrl-3 Zielona\nShift-Ctrl-4 Niebieska\nShift-Ctrl-5 Purpurowa FILEBROWSER_COPYPROFILE;Kopiuj profil @@ -97,6 +112,7 @@ FILEBROWSER_CURRENT_NAME;Obecna nazwa: FILEBROWSER_DARKFRAME;Czarna klatka FILEBROWSER_DELETEDIALOG_HEADER;Potwierdzenie usunięcia pliku FILEBROWSER_EMPTYTRASH;Wyczyść kosz +FILEBROWSER_EMPTYTRASHHINT;Usuwa na zawsze pliki znajdujące się w koszu. FILEBROWSER_EXTPROGMENU;Otwórz za pomocą FILEBROWSER_FLATFIELD;Puste pole FILEBROWSER_MOVETODARKFDIR;Przenieś do katalogu zawierającego czarne klatki @@ -144,6 +160,7 @@ FILEBROWSER_RANK3_TOOLTIP;Oceń 3 *\nSkrót: Shift-3 FILEBROWSER_RANK4_TOOLTIP;Oceń 4 *\nSkrót: Shift-4 FILEBROWSER_RANK5_TOOLTIP;Oceń 5 *\nSkrót: Shift-5 FILEBROWSER_RENAMEDLGLABEL;Zmień nazwę pliku +FILEBROWSER_RESETDEFAULTPROFILE;Przywróć domyślne FILEBROWSER_SELECTDARKFRAME;Wybierz czarną klatkę... FILEBROWSER_SELECTFLATFIELD;Wybierz puste pole... FILEBROWSER_SHOWCOLORLABEL1HINT;Pokazuje zdjęcia z czerwoną etykietą.\nSkrót: Alt-1 @@ -169,24 +186,38 @@ FILEBROWSER_THUMBSIZE;Rozmiar minaturek FILEBROWSER_UNRANK_TOOLTIP;Usuń ocenę.\nSkrót: Shift-0 FILEBROWSER_ZOOMINHINT;Zwiększa rozmiar miniaturek.\n\nSkróty:\n+ - Tryb wielu zakładek,\nAlt-+ - Tryb pojedyńczej zakładki. FILEBROWSER_ZOOMOUTHINT;Zmniejsza rozmiar miniaturek.\n\nSkróty:\n- - Tryb wielu zakładek,\nAlt-- - Tryb pojedyńczej zakładki. +FILECHOOSER_FILTER_ANY;Wszystkie pliki +FILECHOOSER_FILTER_COLPROF;Profile kolorów (*.icc) +FILECHOOSER_FILTER_CURVE;Pliki krzywych +FILECHOOSER_FILTER_LCP;Profile korekcyjne obiektywów +FILECHOOSER_FILTER_PP;Profile przetwarzania +FILECHOOSER_FILTER_SAME;Taki sam format jak aktualnego zdjęcia +FILECHOOSER_FILTER_TIFF;Pliki TIFF GENERAL_ABOUT;O programie GENERAL_AFTER;Po +GENERAL_APPLY;Zastosuj +GENERAL_ASIMAGE;Jako obraz GENERAL_AUTO;Automatyczne GENERAL_BEFORE;Przed GENERAL_CANCEL;Anuluj GENERAL_CLOSE;Zamknij +GENERAL_CURRENT;Obecny GENERAL_DISABLE;Wyłącz GENERAL_DISABLED;Wyłączone GENERAL_ENABLE;Włącz GENERAL_ENABLED;Włączone GENERAL_FILE;Plik +GENERAL_HELP;Pomoc GENERAL_LANDSCAPE;Poziomo GENERAL_NA;nd. GENERAL_NO;Nie GENERAL_NONE;Żaden GENERAL_OK;OK +GENERAL_OPEN;Otwórz GENERAL_PORTRAIT;Pionowo +GENERAL_RESET;Resetuj GENERAL_SAVE;Zapisz +GENERAL_SAVE_AS;Zapisz jako... GENERAL_UNCHANGED;(Niezmienione) GENERAL_WARNING;Uwaga HISTOGRAM_TOOLTIP_B;Pokaż/Ukryj histogram błękitów. @@ -364,12 +395,14 @@ HISTORY_MSG_162;Tone Mapping HISTORY_MSG_163;Krzywe RGB - Czerwona HISTORY_MSG_164;Krzywe RGB - Zielona HISTORY_MSG_165;Krzywe RGB - Niebieska +HISTORY_MSG_166;Ekspozycja - Reset HISTORY_MSG_167;Algorytm demozaikowania HISTORY_MSG_168;L*a*b* - Krzywa CC HISTORY_MSG_169;L*a*b* - Krzywa CH HISTORY_MSG_170;Jaskrawość - Krzywa HH HISTORY_MSG_171;L*a*b* - Krzywa LC HISTORY_MSG_172;L*a*b* - Ogranicz LC +HISTORY_MSG_173;NR - Odzyskiwanie detali HISTORY_MSG_174;CIECAM02 HISTORY_MSG_175;CAM02 - Adaptacja CAT02 HISTORY_MSG_176;CAM02 - Otoczenie @@ -399,6 +432,7 @@ HISTORY_MSG_199;CAM02 - Histogramy wyjściowe HISTORY_MSG_200;CAMO2 - Tone mapping HISTORY_MSG_201;RS - Chrominancja - R&G HISTORY_MSG_202;RS - Chrominancja - B&Y +HISTORY_MSG_203;NR - Przestrzeń kolorów HISTORY_MSG_204;Kroki poprawy LMMSE HISTORY_MSG_205;CAM02 - Gorące/uszkodzone px HISTORY_MSG_206;CAT02 - Auto luminancja sceny @@ -448,6 +482,7 @@ HISTORY_MSG_252;KwgPS - Odcienie skóry HISTORY_MSG_253;KwgPS - Redukcja błędów HISTORY_MSG_254;KwgPS - Odcienie skóry HISTORY_MSG_255;RS - Filtr mediana +HISTORY_MSG_256;NR - Mediana - Typ HISTORY_MSG_257;Koloryzacja HISTORY_MSG_258;Koloryzacja - Kolor HISTORY_MSG_259;Koloryzacja - Przezroczystość @@ -487,35 +522,175 @@ HISTORY_MSG_293;Symulacja Kliszy HISTORY_MSG_294;Symulacja Kliszy - Siła HISTORY_MSG_295;Symulacja Kliszy - Klisza HISTORY_MSG_296;RS - Modulacja luminancji +HISTORY_MSG_297;NR - Tryb HISTORY_MSG_298;Filtrowanie martwych pikseli +HISTORY_MSG_299;NR - Krzywa chrominancji +HISTORY_MSG_300;- +HISTORY_MSG_301;NR - Kontrola luminancji +HISTORY_MSG_302;NR - Metoda chrominancji +HISTORY_MSG_303;NR - Metoda chrominancji +HISTORY_MSG_304;W - Poziomy kontrastu +HISTORY_MSG_306;W - Proces +HISTORY_MSG_307;W - Proces +HISTORY_MSG_308;W - Kierunek procesu +HISTORY_MSG_309;W - ES - Detale +HISTORY_MSG_312;W - Residual - Próg cieni +HISTORY_MSG_315;W - Residual - Kontrast +HISTORY_MSG_317;W - Gamut - Odcień skóry +HISTORY_MSG_318;W - Kontrast - Poziom podświetleń +HISTORY_MSG_319;W - Kontrast - Zakres podświetleń +HISTORY_MSG_320;W - Kontrast - Zakres cieni +HISTORY_MSG_321;W - Kontrast - Poziom cieni +HISTORY_MSG_322;W - Gamut - Unikaj przesunięcia kolorów +HISTORY_MSG_323;W - ES - Kontrast lokalny +HISTORY_MSG_324;W - Chroma - Pastelowe +HISTORY_MSG_325;W - Chroma - Nasycone +HISTORY_MSG_326;W - Chroma - Metoda +HISTORY_MSG_333;W - Residual - Cienie +HISTORY_MSG_334;W - Residual - Chrominancja +HISTORY_MSG_335;W - Residual - Podświetlenia +HISTORY_MSG_336;W - Residual - Próg podświetleń +HISTORY_MSG_337;W - Residual - Odcień nieba +HISTORY_MSG_338;W - ES - Promień +HISTORY_MSG_339;W - ES - Siła +HISTORY_MSG_340;W - Siła +HISTORY_MSG_343;W - Poziomy chrominancji +HISTORY_MSG_345;W - ES - Kontrast lokalny +HISTORY_MSG_346;W - ES - Tryb kontrastu lokalnego +HISTORY_MSG_347;W - Odszumianie - Poziom 1 +HISTORY_MSG_348;W - Odszumianie - Poziom 2 +HISTORY_MSG_349;W - Odszumianie - Poziom 3 +HISTORY_MSG_352;W - Tło +HISTORY_MSG_355;W - ES - Niski próg +HISTORY_MSG_356;W - ES - Wysoki próg +HISTORY_MSG_359;Hot/Dead - Próg +HISTORY_MSG_362;W - Residual - Metoda kompresji +HISTORY_MSG_363;W - Residual - Siła kompersji +HISTORY_MSG_364;W - Final - Balans kontrastu +HISTORY_MSG_368;W - Final - Balans kontrastu +HISTORY_MSG_369;W - Final - Metoda balansu +HISTORY_MSG_370;W - Final - Krzywa lokalnego kontrastu +HISTORY_MSG_372;PRS USM - Promień +HISTORY_MSG_373;PRS USM - Ilość +HISTORY_MSG_374;PRS USM - Próg +HISTORY_MSG_376;PRS USM - Promień wykrywania krawędzi +HISTORY_MSG_377;PRS USM - Tolerancja krawędzi +HISTORY_MSG_380;PRS - Metoda +HISTORY_MSG_381;PRS RLD - Promień +HISTORY_MSG_382;PRS RLD - Ilość +HISTORY_MSG_384;PRS RLD - Iteracje +HISTORY_MSG_385;W - Residual - Balans kolorów +HISTORY_MSG_392;W - Residual - Balans kolorów +HISTORY_MSG_405;W - Odszumianie - Poziom 4 +HISTORY_MSG_407;Retinex - Metoda +HISTORY_MSG_408;Retinex - Promień +HISTORY_MSG_409;Retinex - Contrast +HISTORY_MSG_410;Retinex - Przesunięcie +HISTORY_MSG_411;Retinex - Siła +HISTORY_MSG_413;Retinex - Kontrast +HISTORY_MSG_418;Retinex - Próg +HISTORY_MSG_419;Retinex - Przestrzeń kolorów +HISTORY_MSG_426;Retinex - Wyrównywanie odcieni +HISTORY_MSG_429;Retinex - Iteracje +HISTORY_MSG_432;Retinex - M - Podświetlenia +HISTORY_MSG_434;Retinex - M - Cienie +HISTORY_MSG_436;Retinex - M - Promień +HISTORY_MSG_437;Retinex - M - Metoda +HISTORY_MSG_438;Retinex - M - Wyrównywanie +HISTORY_MSG_439;Retinex - Proces +HISTORY_MSG_440;CbDL - Metoda +HISTORY_MSG_442;Retinex - Skala +HISTORY_MSG_449;PS - Adaptacja ISO +HISTORY_MSG_452;PS - Pokaż ruch +HISTORY_MSG_471;PS - Korekcja ruchu +HISTORY_MSG_474;PS - Wyrównaj +HISTORY_MSG_475;PS - Wyrównaj kanał +HISTORY_MSG_485;Korekcja obiektywu +HISTORY_MSG_486;Korekcja obiektywu - Aparat +HISTORY_MSG_487;Korekcja obiektywu - Obiektyw +HISTORY_MSG_489;DRC - Detal +HISTORY_MSG_490;DRC - Ilość +HISTORY_MSG_491;Balans bieli +HISTORY_MSG_492;Krzywe RGB +HISTORY_MSG_CLAMPOOG;Ucinaj kolory spoza zakresu +HISTORY_MSG_DEHAZE_DEPTH;Usuwanie mgły - Głębia +HISTORY_MSG_DEHAZE_ENABLED;Usuwanie mgły +HISTORY_MSG_DEHAZE_LUMINANCE;Usuwanie mgły - Tylko luminancja +HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;Usuwanie mgły - Pokaż mapę głębokości +HISTORY_MSG_DEHAZE_STRENGTH;Usuwanie mgły - Siła +HISTORY_MSG_LOCALCONTRAST_AMOUNT;Kontrast lokalny - Ilość +HISTORY_MSG_LOCALCONTRAST_DARKNESS;Kontrast lokalny - Ciemne miejsca +HISTORY_MSG_LOCALCONTRAST_ENABLED;Kontrast lokalny +HISTORY_MSG_LOCALCONTRAST_LIGHTNESS;Kontrast lokalny - Jasne miejsca +HISTORY_MSG_LOCALCONTRAST_RADIUS;Kontrast lokalny - Promień +HISTORY_MSG_MICROCONTRAST_CONTRAST;Mikrokontrast - Próg kontrastu +HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Automatyczny próg +HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Automatyczny promień +HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Automatycznie limituj iteracje +HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Próg kontrastu +HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iteracje +HISTORY_MSG_PDSHARPEN_RADIUS;CS - Promień +HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Próg kontrastu HISTORY_NEWSNAPSHOT;Nowa migawka HISTORY_NEWSNAPSHOT_TOOLTIP;Skrót: Alt-s HISTORY_SNAPSHOT;Migawka HISTORY_SNAPSHOTS;Migawki +ICCPROFCREATOR_COPYRIGHT;Prawa autorskie: +ICCPROFCREATOR_COPYRIGHT_RESET_TOOLTIP;Przywróć prawa autorskie do domyślnych, przyznanych dla "RawTherapee, CC0" +ICCPROFCREATOR_CUSTOM;Własny +ICCPROFCREATOR_DESCRIPTION;Opis: +ICCPROFCREATOR_GAMMA;Gamma +ICCPROFCREATOR_ICCVERSION;Wersja ICC: +ICCPROFCREATOR_ILL_41;D41 +ICCPROFCREATOR_ILL_50;D50 +ICCPROFCREATOR_ILL_55;D55 +ICCPROFCREATOR_ILL_60;D60 +ICCPROFCREATOR_ILL_65;D65 +ICCPROFCREATOR_ILL_80;D80 +ICCPROFCREATOR_ILL_DEF;Domyślne +ICCPROFCREATOR_ILL_INC;StdA 2856K +ICCPROFCREATOR_PRIM_ADOBE;Adobe RGB (1998) +ICCPROFCREATOR_PRIM_BEST;BestRGB +ICCPROFCREATOR_PRIM_BETA;BetaRGB +ICCPROFCREATOR_PRIM_BRUCE;BruceRGB +ICCPROFCREATOR_PRIM_PROPH;Prophoto +ICCPROFCREATOR_PRIM_REC2020;Rec2020 +ICCPROFCREATOR_PRIM_SRGB;sRGB +ICCPROFCREATOR_PROF_V2;ICC v2 +ICCPROFCREATOR_PROF_V4;ICC v4 +ICCPROFCREATOR_SAVEDIALOG_TITLE;Zapisz profil ICC jako... IPTCPANEL_CATEGORY;Kategoria IPTCPANEL_CITY;Miasto +IPTCPANEL_CITYHINT;Wprowadź nazwę miasta uwiecznionego na zdjęciu. IPTCPANEL_COPYHINT;Kopiuje ustawienia IPTC do schowka IPTCPANEL_COUNTRY;Kraj +IPTCPANEL_CREATOR;Twórca IPTCPANEL_CREDIT;Zasługa IPTCPANEL_CREDITHINT;Identyfikuje dostawcę zdjęcia, niekoniecznie właściciela lub autora (Credit). IPTCPANEL_DATECREATED;Data utworzenia +IPTCPANEL_DATECREATEDHINT;Wprowadź datę zrobienia zdjęcia. +IPTCPANEL_DESCRIPTION;Opis IPTCPANEL_EMBEDDED;Osadzony IPTCPANEL_EMBEDDEDHINT;Resetuje dane IPTC do domyślnych ustawień osadzonych w orginalnym zdjęciu IPTCPANEL_HEADLINE;Nagłówek IPTCPANEL_INSTRUCTIONS;Instrukcje IPTCPANEL_KEYWORDS;Słowa kluczowe IPTCPANEL_PASTEHINT;Wstawia ustawienia IPTC ze schowka +IPTCPANEL_PROVINCE;Województwo lub stan IPTCPANEL_RESET;Reset IPTCPANEL_RESETHINT;Resetuje do domyślnych ustawień profilu IPTCPANEL_SOURCE;Źródło +IPTCPANEL_SUPPCATEGORIES;Dodatkowe kategorie IPTCPANEL_TITLE;Tytuł MAIN_BUTTON_FULLSCREEN;Pełen ekran +MAIN_BUTTON_ICCPROFCREATOR;Kreator profili ICC MAIN_BUTTON_NAVNEXT_TOOLTIP;Przejdź do następnego zdjęcia względem zdjęcia otwartego w Edytorze.\nSkrót: Shift-F4\n\nAby przejść do następnego zdjęcia względem miniaturki wybranej w Nawigatorze Zdjęć:\nSkrót: F4 MAIN_BUTTON_NAVPREV_TOOLTIP;Przejdź do poprzedniego zdjęcia wzgledem zdjęcia otwartego w Edytorze.\nSkrót: Shift-F3 \n\nAby przejść do poprzedniego zdjęcia względem miniaturki wybranej w Nawigatorze Zdjęć:\nSkrót: F3 MAIN_BUTTON_NAVSYNC_TOOLTIP;Synchronizuj Nawigator Zdjęć z Edytorem aby ukazać miniaturkę obecnie otwartego zdjęcia, oraz usuń filtry w Nawigatorze Zdjęć.\nSkrót: x\n\nJak wyżej, ale bez usuwania filtrów:\nSkrót: y\n(Miniaturka otwartego zdjęcia nie zostanie wyświetlona jesli filtr ją ukrywa). MAIN_BUTTON_PREFERENCES;Ustawienia MAIN_BUTTON_PUTTOQUEUE_TOOLTIP;Dodaj bieżące zdjęcie do kolejki przetwarzania Ctrl+B MAIN_BUTTON_SAVE_TOOLTIP;Zapisz bieżące zdjęcieCtrl+S +MAIN_BUTTON_SENDTOEDITOR;Edytuj obraz w zewnętrznym edytorze MAIN_BUTTON_SENDTOEDITOR_TOOLTIP;Otwórz bieżące zdjęcie w zewnętrznym edytorze.\nSkrót: Ctrl+e MAIN_BUTTON_SHOWHIDESIDEPANELS_TOOLTIP;Pokaż/Ukryj wszystkie panele boczne.\nSkrót: m MAIN_BUTTON_UNFULLSCREEN;Zwolnij ekran @@ -525,6 +700,7 @@ MAIN_FRAME_FILEBROWSER;Przeglądarka plików MAIN_FRAME_FILEBROWSER_TOOLTIP; Przeglądarka plików.\nSkrót: Ctrl-F2 MAIN_FRAME_PLACES;Miejsca MAIN_FRAME_PLACES_ADD;Dodaj +MAIN_FRAME_PLACES_DEL;Usuń MAIN_FRAME_QUEUE;Kolejka MAIN_FRAME_QUEUE_TOOLTIP;Przetwarzanie wsadowe\nSkrót: Ctrl-F3 MAIN_FRAME_RECENT;Ostatnio używane foldery @@ -541,6 +717,8 @@ MAIN_MSG_PATHDOESNTEXIST;Ścieżka\n\n%1\n\nnie istnieje. Wybierz przawid MAIN_MSG_QOVERWRITE;Zastąpić? MAIN_MSG_SETPATHFIRST;Aby użyć tej funkcji należy wpierw wybrać odpowiednią ścieżkę docelową w Ustawieniach! MAIN_MSG_WRITEFAILED;Zapis nie powiódł się:\n\n"%1"\n\nUpewnij się, że folder istnieje oraz że można do niego zapisywać. +MAIN_TAB_ADVANCED;Zaawansowane +MAIN_TAB_ADVANCED_TOOLTIP;Skrót: Alt-a MAIN_TAB_COLOR;Kolor MAIN_TAB_COLOR_TOOLTIP;Skrót: Alt-c MAIN_TAB_DETAIL;Szczegóły @@ -550,7 +728,10 @@ MAIN_TAB_EXIF;Exif MAIN_TAB_EXPORT; Szybki eksport MAIN_TAB_EXPOSURE;Ekspozycja MAIN_TAB_EXPOSURE_TOOLTIP;Skrót: Alt-e +MAIN_TAB_FAVORITES;Ulubione +MAIN_TAB_FAVORITES_TOOLTIP;Skrót: Alt-u MAIN_TAB_FILTER; Filtr +MAIN_TAB_INSPECT; Inspekcja MAIN_TAB_IPTC;IPTC MAIN_TAB_METADATA;Metadane MAIN_TAB_METADATA_TOOLTIP;Skrót: Alt-m @@ -563,8 +744,8 @@ MAIN_TOOLTIP_BACKCOLOR1;Kolor tła podglądu: Czarny\nSkrót: 9 MAIN_TOOLTIP_BACKCOLOR2;Kolor tła podglądu: Biały\nSkrót: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Zablokuj / Odblokuj widok Przed\n\nZablokuj: nie zmieniaj widoku Przed - \nPrzydatne w porównywaniu zablokowanego obrazu z obrazem na ktorym wykonano wiele zmian.\n\nOdblokuj: widok Przed będzie śledził widok Po o jeden krok do tyłu, pokazując obraz przed efektem aktualnie użytego narzędzia. MAIN_TOOLTIP_HIDEHP;Pokaż/ukryj lewy panel (razem z historią).\nSkrót: l -MAIN_TOOLTIP_INDCLIPPEDH;Pokaż obcięte prześwietlenia.\nSkrót: < -MAIN_TOOLTIP_INDCLIPPEDS;Pokaż obcięte niedoświetlenia.\nSkrót: > +MAIN_TOOLTIP_INDCLIPPEDH;Pokaż obcięte prześwietlenia.\nSkrót: > +MAIN_TOOLTIP_INDCLIPPEDS;Pokaż obcięte niedoświetlenia.\nSkrót: < MAIN_TOOLTIP_PREVIEWB;Podgląd kanału niebieskiego.\nSkrót: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Podgląd maski ostrości.\nSkrót: Shift-f\n\nDokładniejsze w przypadku zdjęc o płytkiej głębi ostrości, niskim pozimie szumów i o większym przybliżeniu. W przypadku zdjęć o wyższym poziomie szumów maska ostrości będzie dokładniejsza przy mniejszym zoomie (10-30%). MAIN_TOOLTIP_PREVIEWG;Podgląd kanału zielonego.\nSkrót: g @@ -576,6 +757,7 @@ MAIN_TOOLTIP_SHOWHIDERP1;Pokaż/Ukryj prawy panel.\nSkrót: Alt-l MAIN_TOOLTIP_SHOWHIDETP1;Pokaż/Ukryj górny panel.\nSkrót: Shift-l MAIN_TOOLTIP_THRESHOLD;Próg MAIN_TOOLTIP_TOGGLE;Przełącz widok Przed/Po.\nSkrót: Shift-b +MONITOR_PROFILE_SYSTEM;Ustawienia domyślne NAVIGATOR_B;B: NAVIGATOR_G;G: NAVIGATOR_H;H: @@ -588,6 +770,7 @@ NAVIGATOR_S;S: NAVIGATOR_V;V: NAVIGATOR_XY_FULL;Szerokość: %1, Wysokość: %2 NAVIGATOR_XY_NA;x: --, y: -- +PARTIALPASTE_ADVANCEDGROUP;Ustawienia zaawansowane PARTIALPASTE_BASICGROUP;Podstawowe ustawienia PARTIALPASTE_CACORRECTION;Korekcja aberacji chr. PARTIALPASTE_CHANNELMIXER;Mieszacz kanałów @@ -602,6 +785,7 @@ PARTIALPASTE_CROP;Kadrowanie PARTIALPASTE_DARKFRAMEAUTOSELECT;Auto-wybór czarnej klatki PARTIALPASTE_DARKFRAMEFILE;Wybór czarnej klatki PARTIALPASTE_DEFRINGE;Usuwanie widma +PARTIALPASTE_DEHAZE;Usuwanie mgły PARTIALPASTE_DETAILGROUP;Ustawienia szczegółowe PARTIALPASTE_DIALOGLABEL;Częściowe wklejenie profilu przetwarzania PARTIALPASTE_DIRPYRDENOISE;Redukcja szumu @@ -625,6 +809,7 @@ PARTIALPASTE_IPTCINFO;IPTC PARTIALPASTE_LABCURVE;Regulacje L*a*b* PARTIALPASTE_LENSGROUP;Ustawienia związane z obiektywem PARTIALPASTE_LENSPROFILE;Profil korekcji obiektywu LCP +PARTIALPASTE_LOCALCONTRAST;Kontrast lokalny PARTIALPASTE_METAGROUP;Metadane PARTIALPASTE_PCVIGNETTE;Winietowanie PARTIALPASTE_PERSPECTIVE;Perspektywa @@ -642,6 +827,7 @@ PARTIALPASTE_RAW_DMETHOD;Algorytm demozaikowania PARTIALPASTE_RAW_FALSECOLOR;Tłumienie fałszowania koloru PARTIALPASTE_RAW_LMMSEITERATIONS;Kroki poprawy LMMSE PARTIALPASTE_RESIZE;Zmiana rozmiaru +PARTIALPASTE_RETINEX;Retinex PARTIALPASTE_RGBCURVES;Krzywe RGB PARTIALPASTE_ROTATION;Obrót PARTIALPASTE_SHADOWSHIGHLIGHTS;Cienie/Podświetlenia @@ -652,7 +838,9 @@ PARTIALPASTE_VIBRANCE;Jaskrawość PARTIALPASTE_VIGNETTING;Korekcja winietowania PARTIALPASTE_WHITEBALANCE;Balans bieli PREFERENCES_ADD;Dodaj +PREFERENCES_APPEARANCE;Wygląd PREFERENCES_APPEARANCE_NAVGUIDECOLOR;Kolor ramki Nawigatora +PREFERENCES_APPEARANCE_THEME;Motyw graficzny PREFERENCES_APPLNEXTSTARTUP;wymaga ponownego uruchomienia PREFERENCES_AUTOMONPROFILE;Automatycznie użyj systemowego profilu monitora PREFERENCES_BATCH_PROCESSING;Przetwarzanie wsadowe @@ -661,11 +849,26 @@ PREFERENCES_BEHADDALLHINT;Ustaw wszystkie narzędzia w tryb Dodaj.\nZmian PREFERENCES_BEHAVIOR;Zachowanie PREFERENCES_BEHSETALL;'Ustaw' wszystkie PREFERENCES_BEHSETALLHINT;Ustaw wszystkie narzędzia w tryb Ustaw.\nZmiany parametrów w panelu edycji zbiorczej zostaną traktowane jako absolutne, nie biorąc pod uwagę poprzednich wartości. +PREFERENCES_CACHECLEAR;Wyczyść +PREFERENCES_CACHECLEAR_ALL;Usuń wszystkie pliki z pamięci podręcznej: +PREFERENCES_CACHECLEAR_ONLYPROFILES;Usuń wszystkie profile przetwarzania z pamięci podręcznej: PREFERENCES_CACHEMAXENTRIES;Maksymalna liczba wpisów w pamięci podręcznej PREFERENCES_CACHEOPTS;Opcje pamięci podręcznej PREFERENCES_CACHETHUMBHEIGHT;Maksymalna wysokość miniatury +PREFERENCES_CHUNKSIZE_RAW_AMAZE;Demozaikowanie AMaZE +PREFERENCES_CHUNKSIZE_RAW_RCD;Demozaikowanie RCD +PREFERENCES_CHUNKSIZE_RAW_XT;Demozaikowanie Xtrans +PREFERENCES_CHUNKSIZE_RGB;Przetwarzanie RGB PREFERENCES_CLIPPINGIND;Pokazywanie obciętych prześwietleń/cieni PREFERENCES_CLUTSDIR;Folder obrazów HaldCLUT +PREFERENCES_CMMBPC;Kompensacja punktu czerni +PREFERENCES_CROP_GUIDES_FRAME;Ramka +PREFERENCES_CROP_GUIDES_FULL;Oryginał +PREFERENCES_CROP_GUIDES_NONE;Brak +PREFERENCES_CURVEBBOXPOS_ABOVE;Powyżej +PREFERENCES_CURVEBBOXPOS_BELOW;Poniżej +PREFERENCES_CURVEBBOXPOS_LEFT;Z lewej +PREFERENCES_CURVEBBOXPOS_RIGHT;Z prawej PREFERENCES_CUSTPROFBUILD;Zewnętrzny kreator profilów przetwarzania PREFERENCES_CUSTPROFBUILDHINT;Plik wykonywalny (lub skrypt) uruchamiany kiedy trzeba wygenerować profil przetwarzania dla zdjęcia.\n\nScieżka pliku nośnego (w stylu *.ini czyli sekcje i klucze/parametry) występuje jako parametr wiersza poleceń. Plik ten zawiera przeróżne parametry oraz dane Exif dzięki którym odpowiedni program bądź skrypt może wygenerować plik PP3 według reguł.\n\nUWAGA: Twoją odpowiedzialnością jest prawidłowe użycie cudzysłowiów w przypadku ścieżek zawierających spacje i znaki specjalne. PREFERENCES_CUSTPROFBUILDKEYFORMAT;Rodzaj kluczy @@ -678,6 +881,7 @@ PREFERENCES_DARKFRAMETEMPLATES;szablonów(ny) PREFERENCES_DATEFORMAT;Format daty PREFERENCES_DATEFORMATHINT;Dozwolone są następujące kody formatujące:\n%y - rok\n%m - miesiąc\n%d - dzień\n\nNa przykład według standardu ISO 8601 format daty wygląda następująco:\n%y-%m-%d PREFERENCES_DIRDARKFRAMES;Katalog z czarnymi klatkami +PREFERENCES_DIRECTORIES;Katalogi PREFERENCES_DIRHOME;Katalog domowy PREFERENCES_DIRLAST;Ostatnio odwiedzony katalog PREFERENCES_DIROTHER;Inny @@ -698,11 +902,14 @@ PREFERENCES_HISTOGRAM_TOOLTIP;Jeśli opcja jest włączona profil roboczy jest u PREFERENCES_HLTHRESHOLD;Próg dla prześwietleń PREFERENCES_ICCDIR;Katalog z profilami koloru ICC PREFERENCES_IMPROCPARAMS;Domyślne parametry przetwarzania obrazu +PREFERENCES_INSPECT_LABEL;Inspekcja +PREFERENCES_INSPECT_MAXBUFFERS_LABEL;Maksymalna liczba obrazów w pamięci podręcznej PREFERENCES_INTENT_ABSOLUTE;Absolutnie kolorymetryczny PREFERENCES_INTENT_PERCEPTUAL;Percepcyjny PREFERENCES_INTENT_RELATIVE;Względnie kolorymetryczny PREFERENCES_INTENT_SATURATION;Nasyceniowy PREFERENCES_INTERNALTHUMBIFUNTOUCHED;Pokaż osadzoną miniaturę JPEG jeśli plik raw jest nieedytowany +PREFERENCES_LANG;Język PREFERENCES_LANGAUTODETECT;Użyj języka systemowego PREFERENCES_MENUGROUPEXTPROGS;Grupuj "Otwórz za pomocą" PREFERENCES_MENUGROUPFILEOPERATIONS;Grupuj operacje plików @@ -710,8 +917,11 @@ PREFERENCES_MENUGROUPLABEL;Grupuj operacje etykiet PREFERENCES_MENUGROUPPROFILEOPERATIONS;Grupuj operacje profili przetwarzania PREFERENCES_MENUGROUPRANK;Grupuj operacje oceny PREFERENCES_MENUOPTIONS;Opcje menu +PREFERENCES_MONITOR;Monitor +PREFERENCES_MONPROFILE;Domyślny profil kolorów PREFERENCES_MULTITAB;Tryb wielu zakładek PREFERENCES_MULTITABDUALMON;Tryb wielu zakładek (na drugim monitorze jeśli dostępny) +PREFERENCES_NAVIGATIONFRAME;Nawigacja PREFERENCES_OVERLAY_FILENAMES;Nakładaj nazwy pliku na miniatury PREFERENCES_OVERWRITEOUTPUTFILE;Nadpisuj istniejące pliki PREFERENCES_PANFACTORLABEL;Współczynnik @@ -719,13 +929,18 @@ PREFERENCES_PARSEDEXT;Przetwarzane rozszerzenia PREFERENCES_PARSEDEXTADD;Dodaj rozszerzenie PREFERENCES_PARSEDEXTADDHINT;Proszę wprowadzić rozszerzenie i zatwierdzić przyciskiem, by dodać do listy PREFERENCES_PARSEDEXTDELHINT;Skasuje wybrane rozszerzenie z listy +PREFERENCES_PERFORMANCE_THREADS;Wątki +PREFERENCES_PREVDEMO;Metoda demozaikowania podglądu +PREFERENCES_PREVDEMO_FAST;Szybka PREFERENCES_PROFILEHANDLING;Obsługa profili PREFERENCES_PROFILELOADPR;Priorytet wczytywania profilu PREFERENCES_PROFILEPRCACHE;Profil w pamięci podręcznej PREFERENCES_PROFILEPRFILE;Profil przy pliku wejściowym PREFERENCES_PROFILESAVECACHE;Zapisz parametry przetwarzania w pamięci podręcznej PREFERENCES_PROFILESAVEINPUT;Zapisz parametry przetwarzania obok pliku wejściowego +PREFERENCES_PROFILE_NONE;Żaden PREFERENCES_PROPERTY;Własność +PREFERENCES_PRTPROFILE;Profil kolorów PREFERENCES_PSPATH;Katalog w którym zainstalowany jest Adobe Photoshop PREFERENCES_SELECTLANG;Wybierz język PREFERENCES_SET;Ustaw @@ -744,6 +959,7 @@ PREFERENCES_TAB_BROWSER;Przeglądarka plików PREFERENCES_TAB_COLORMGR;Zarządzanie kolorami PREFERENCES_TAB_GENERAL;Ogólne PREFERENCES_TAB_IMPROC;Przetwarzanie obrazu +PREFERENCES_TAB_PERFORMANCE;Wydajność PREFERENCES_TAB_SOUND;Dźwięki PREFERENCES_TP_LABEL;Panel narzędzi: PREFERENCES_TP_VSCROLLBAR;Ukry pionowy pasek przesuwania @@ -767,6 +983,8 @@ PROFILEPANEL_TOOLTIPCOPY;Skopiuj aktualny profil do schowka PROFILEPANEL_TOOLTIPLOAD;Ładuj profil z pliku.\nCtrl+klik aby wybrać parametry do ładowania. PROFILEPANEL_TOOLTIPPASTE;Wklej profil ze schowka.\nCtrl+klik aby wybrać parametry do wklejenia. PROFILEPANEL_TOOLTIPSAVE;Zapisz aktualny profil.\nCtrl+klik aby wybrać parametry do zapisania. +PROGRESSBAR_DECODING;Dekodowanie... +PROGRESSBAR_HLREC;Rekonstrukcja podświetleń... PROGRESSBAR_LOADING;Wczytywanie obrazu... PROGRESSBAR_LOADINGTHUMBS;Wczytywanie miniatur... PROGRESSBAR_LOADJPEG;Ładowanie pliku JPEG... @@ -781,8 +999,11 @@ PROGRESSBAR_SAVEPNG;Zapisywanie pliku PNG... PROGRESSBAR_SAVETIFF;Zapisywanie pliku TIFF... PROGRESSBAR_SNAPSHOT_ADDED;Dodano migawkę PROGRESSDLG_PROFILECHANGEDINBROWSER;Profil zmieniony w przeglądarce +QINFO_FRAMECOUNT;%2 klatki +QINFO_HDR;HDR / %2 klatka/i QINFO_ISO;ISO QINFO_NOEXIF;Dane Exif niedostępne. +QINFO_PIXELSHIFT;Pixel Shift / %2 klatka/i QUEUE_AUTOSTART;Autostart QUEUE_AUTOSTART_TOOLTIP;Rozpocznij przetwarzanie automatycznie gdy pojawi się nowe zadanie. QUEUE_DESTFILENAME;Ścieżka i nazwa pliku @@ -848,6 +1069,8 @@ TP_BWMIX_MET;Metoda TP_BWMIX_MET_CHANMIX;Mieszacz kanałów TP_BWMIX_MET_DESAT;Desaturacja TP_BWMIX_MET_LUMEQUAL;Ekwalizator luminancji +TP_BWMIX_MIXC;Mieszacz kanałów +TP_BWMIX_NEUTRAL;Reset TP_BWMIX_RGBLABEL;R: %1%% G: %2%% B: %3%% Total: %4%% TP_BWMIX_RGBLABEL_HINT;Ostateczne wartości RGB które uwzględniają wszystkie opcje mieszacza.\n"Total" wyświetla sumę wartości RGB:\n- zawsze 100% w trybie relatywnym,\n- ponad (jaśniej) lub poniżej (ciemniej) 100% w trybie absolutnym. TP_BWMIX_RGB_TOOLTIP;Miesza kanały RGB. Kieruj się gotowymi ustawieniami.\nNależy zwrócić uwagę na ujemne wartości ponieważ mogą pojawić się zniekształcenia sygnału w obrazie lub działać w sposób nieprzewidywalny. @@ -884,6 +1107,7 @@ TP_COARSETRAF_TOOLTIP_HFLIP;Odbij w poziomie TP_COARSETRAF_TOOLTIP_ROTLEFT;Obróć w lewo.\n\nSkróty:\n[ - Tryb wielu zakładek,\nAlt-[ - Tryb jednej zakładki. TP_COARSETRAF_TOOLTIP_ROTRIGHT;Obróć w prawo.\n\nSkróty:\n] - Tryb wielu zakładek,\nAlt-] - Tryb jednej zakładki. TP_COARSETRAF_TOOLTIP_VFLIP;Odbij w pionie +TP_COLORAPP_ABSOLUTELUMINANCE;Luminancja absolutna TP_COLORAPP_ALGO;Algorytm TP_COLORAPP_ALGO_ALL;Wszystkie TP_COLORAPP_ALGO_JC;Światłość + Chroma (JC) @@ -925,6 +1149,8 @@ TP_COLORAPP_LIGHT;Światłość (J) TP_COLORAPP_LIGHT_TOOLTIP;Światłość w CIECAM02 różni się od światłości CIELab oraz RGB TP_COLORAPP_MODEL;Model PB TP_COLORAPP_MODEL_TOOLTIP;Model punktu bieli.\n\nBB [RT] + [wyjściowy]:\nBalans bieli RawTherapee jest użyty dla sceny, CIECAM02 jest ustawione na D50, i balans bieli urządzenia wyjściowego ustawiony jest w Ustawieniach > Zarządzanie Kolorami\n\nBB [RT+CAT02] + [wyjściowe]:\nUstawienia balansu bieli RawTherapee są używane przez CAT02, i balans bieli urządzenia wyjściowego jest ustawione w Ustawieniach > Zarządzanie Kolorami. +TP_COLORAPP_NEUTRAL;Reset +TP_COLORAPP_NEUTRAL_TIP;Przywróć wszystkie suwaki oraz krzywe do wartości domyślnych TP_COLORAPP_RSTPRO;Ochrona odcieni skóry i czerwieni TP_COLORAPP_RSTPRO_TOOLTIP;Ochrona odcieni skóry i czerwieni (suwaki i krzywe) TP_COLORAPP_SURROUND;Otoczenie @@ -957,6 +1183,16 @@ TP_COLORTONING_HIGHLIGHT;Podświetlenia TP_COLORTONING_HUE;Odcień (hue) TP_COLORTONING_LAB;Mieszanie L*a*b* TP_COLORTONING_LABEL;Koloryzacja +TP_COLORTONING_LABREGION_CHANNEL;Kanał +TP_COLORTONING_LABREGION_CHANNEL_ALL;Wszystkie +TP_COLORTONING_LABREGION_CHANNEL_B;Niebieski +TP_COLORTONING_LABREGION_CHANNEL_G;Zielony +TP_COLORTONING_LABREGION_CHANNEL_R;Czerwony +TP_COLORTONING_LABREGION_LIST_TITLE;Korekcja +TP_COLORTONING_LABREGION_MASK;Maska +TP_COLORTONING_LABREGION_OFFSET;Przesunięcie +TP_COLORTONING_LABREGION_SATURATION;Saturacja +TP_COLORTONING_LABREGION_SHOWMASK;Pokaż maskę TP_COLORTONING_LUMA;Luminancja TP_COLORTONING_LUMAMODE;Zachowaj luminancję TP_COLORTONING_LUMAMODE_TOOLTIP;Luminancja zostanie zachowana przy zmianie kolorów. @@ -992,6 +1228,9 @@ TP_CROP_GTRULETHIRDS;Trójpodział TP_CROP_GUIDETYPE;Typ pomocy: TP_CROP_H;Wysokość TP_CROP_LABEL;Kadrowanie +TP_CROP_PPI;PPI +TP_CROP_RESETCROP;Reset +TP_CROP_SELECTCROP;Wybierz TP_CROP_W;Szerokość TP_CROP_X;X TP_CROP_Y;Y @@ -1000,13 +1239,27 @@ TP_DARKFRAME_LABEL;Czarna klatka TP_DEFRINGE_LABEL;Usuwanie widma TP_DEFRINGE_RADIUS;Promień TP_DEFRINGE_THRESHOLD;Próg +TP_DEHAZE_DEPTH;Głębia +TP_DEHAZE_LABEL;Usuwanie mgły +TP_DEHAZE_LUMINANCE;Tylko luminancja +TP_DEHAZE_SHOW_DEPTH_MAP;Pokaż mapę głębokości +TP_DEHAZE_STRENGTH;Siła TP_DIRPYRDENOISE_CHROMINANCE_BLUEYELLOW;Chrominancja - Błękit-żółć +TP_DIRPYRDENOISE_CHROMINANCE_CURVE;Krzywa chrominancji +TP_DIRPYRDENOISE_CHROMINANCE_FRAME;Chrominancja +TP_DIRPYRDENOISE_CHROMINANCE_MANUAL;Ręcznie TP_DIRPYRDENOISE_CHROMINANCE_MASTER;Chrominancja - Główna +TP_DIRPYRDENOISE_CHROMINANCE_METHOD;Metoda +TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW;Podgląd TP_DIRPYRDENOISE_CHROMINANCE_REDGREEN;Chrominancja - Czerwień-zieleń +TP_DIRPYRDENOISE_LABEL;Redukcja szumu +TP_DIRPYRDENOISE_LUMINANCE_CONTROL;Kontrola luminancji TP_DIRPYRDENOISE_LUMINANCE_CURVE;Krzywa luminancji TP_DIRPYRDENOISE_LUMINANCE_DETAIL;Szczegółowość luminancji +TP_DIRPYRDENOISE_LUMINANCE_FRAME;Luminancja TP_DIRPYRDENOISE_LUMINANCE_SMOOTHING;Luminacja TP_DIRPYRDENOISE_MAIN_COLORSPACE;Metoda +TP_DIRPYRDENOISE_MAIN_COLORSPACE_LAB;L*a*b* TP_DIRPYRDENOISE_MAIN_COLORSPACE_RGB;RGB TP_DIRPYRDENOISE_MAIN_COLORSPACE_TOOLTIP;Dla obrazów raw można używać metody RGB oraz L*a*b*.\n\nDla obrazów nie-raw metoda L*a*b* zostanie użyta niezależnie od wyboru. TP_DIRPYRDENOISE_MAIN_GAMMA;Gamma @@ -1016,6 +1269,7 @@ TP_DIRPYRDENOISE_MAIN_MODE_AGGRESSIVE;Wysoka TP_DIRPYRDENOISE_MAIN_MODE_CONSERVATIVE;Standardowa TP_DIRPYRDENOISE_MAIN_MODE_TOOLTIP;Jakość może zostać dopasowana do wzoru szumów. Ustawienie "wysoka" ulepsza odszumianie około 20% wzrostu czasu przetwarzania. TP_DIRPYRDENOISE_MEDIAN_METHOD;Metoda mediana +TP_DIRPYRDENOISE_MEDIAN_METHOD_CHROMINANCE;Tylko Chroma TP_DIRPYRDENOISE_MEDIAN_METHOD_LAB;L*a*b* TP_DIRPYRDENOISE_MEDIAN_METHOD_LABEL;Filtr Mediana TP_DIRPYRDENOISE_MEDIAN_METHOD_LUMINANCE;Tylko luminancja @@ -1025,6 +1279,7 @@ TP_DIRPYRDENOISE_MEDIAN_PASSES;Liczba powtórzeń mediana TP_DIRPYRDENOISE_MEDIAN_TYPE;Rodzaj mediana TP_DIRPYREQUALIZER_ALGO;Zakres odcieni skóry TP_DIRPYREQUALIZER_ALGO_TOOLTIP;- +TP_DIRPYREQUALIZER_ARTIF;Usuń artefakty TP_DIRPYREQUALIZER_HUESKIN;Odcień skóry TP_DIRPYREQUALIZER_HUESKIN_TOOLTIP;Piramida wyznacza zakres kolorów uważany jako zakres odcieni skóry. Większość odcieni skóry - białej, czarnej, i pomiędzy - ma tę samą odcień. Małe poprawki są dopuszczalne, jednak jeśli potrzebna jest większa zmiana w lewo lub prawo, lub jeśli są widoczne artefakty, to najprawdopobniej balans bieli jest niepoprawny. TP_DIRPYREQUALIZER_LABEL;Kontrast wg. precyzji detali @@ -1040,6 +1295,7 @@ TP_DIRPYREQUALIZER_TOOLTIP;Zapobiega artefaktom w strefach przejścia pomiędzy TP_DISTORTION_AMOUNT;Siła TP_DISTORTION_LABEL;Dystorsja TP_EPD_EDGESTOPPING;Wyszukiwanie krawędzi +TP_EPD_GAMMA;Gamma TP_EPD_LABEL;Tone Mapping TP_EPD_REWEIGHTINGITERATES;Powtarzanie rozważania TP_EPD_SCALE;Skala @@ -1048,6 +1304,7 @@ TP_EXPOSURE_AUTOLEVELS;Wyrównaj poziomy TP_EXPOSURE_AUTOLEVELS_TIP;Dokonaj automatycznego ustawienia parametrów ekspozycji na podstawie analizy obrazu TP_EXPOSURE_BLACKLEVEL;Czerń TP_EXPOSURE_BRIGHTNESS;Jasność +TP_EXPOSURE_CLAMPOOG;Przytnij kolory spoza gamy kolorów TP_EXPOSURE_CLIP;Przytnij % TP_EXPOSURE_CLIP_TIP;Ułamek pikseli ktore mają zostać rozjaśnione do punktu prześwietlenia podczas automatycznego wyrównania poziomów. TP_EXPOSURE_COMPRHIGHLIGHTS;Kompresja podświetleń @@ -1064,6 +1321,7 @@ TP_EXPOSURE_SATURATION;Nasycenie TP_EXPOSURE_TCMODE_FILMLIKE;Klisza TP_EXPOSURE_TCMODE_LABEL1;Tryb krzywej 1 TP_EXPOSURE_TCMODE_LABEL2;Tryb krzywej 2 +TP_EXPOSURE_TCMODE_LUMINANCE;Luminancja TP_EXPOSURE_TCMODE_SATANDVALBLENDING;Mieszanie nasycenia i mocy światła białego TP_EXPOSURE_TCMODE_STANDARD;Standardowa TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Ważona standardowa @@ -1107,6 +1365,7 @@ TP_HSVEQUALIZER_HUE;H TP_HSVEQUALIZER_LABEL;Ekwalizator HSV TP_HSVEQUALIZER_SAT;S TP_HSVEQUALIZER_VAL;V +TP_ICM_BPC;Kompensacja punktu czerni TP_ICM_DCPILLUMINANT;Iluminant TP_ICM_DCPILLUMINANT_INTERPOLATED;Interpolowany TP_ICM_DCPILLUMINANT_TOOLTIP;Wybierz który osadzony iluminant DCP należy użyć. Domyślną opcją jest "interpolowany", czyli wartość jest mieszaniną pomiędzy dwoma osadzonymi wartościami iluminantu zależnie od balansu bieli. Ten wybór jest możliwy jedynie kiedy DCP zawiera dwa iluminanty z możliwościa interpolacji. @@ -1125,10 +1384,13 @@ TP_ICM_INPUTPROFILE;Profil wejściowy TP_ICM_LABEL;ICM TP_ICM_NOICM;Brak ICM: Wyjście sRGB TP_ICM_OUTPUTPROFILE;Profil wyjściowy +TP_ICM_SAVEREFERENCE_APPLYWB;Zastosuj balans bieli TP_ICM_SAVEREFERENCE_TOOLTIP;Zapisz liniowy obraz TIFF zanim profil wejściowy zostanie zastosowany. Obraz ten można użyć do kalibracji oraz do wytworzenia profilu aparatu. TP_ICM_TONECURVE;Użyj krzywą tonalną z DCP TP_ICM_TONECURVE_TOOLTIP;Włącz aby użyć krzywą tonalną znajdującą się w profilu DCP. Opcja ta jest tylko aktywna jeśli profil DCP zawiera krzywą tonalną. TP_ICM_WORKINGPROFILE;Profil roboczy +TP_ICM_WORKING_TRC_CUSTOM;Własna +TP_ICM_WORKING_TRC_NONE;Żadna TP_IMPULSEDENOISE_LABEL;Redukcja Szumów Impulsowych TP_IMPULSEDENOISE_THRESH;Próg TP_LABCURVE_AVOIDCOLORSHIFT;Zapobiegaj zmianom koloru @@ -1171,7 +1433,22 @@ TP_LABCURVE_RSTPRO_TOOLTIP;Ma wpływ na suwak Chromatyczności oraz na krzywą C TP_LENSGEOM_AUTOCROP;Auto-kadrowanie TP_LENSGEOM_FILL;Auto-wypełnienie TP_LENSGEOM_LABEL;Obiektyw / Geometria +TP_LENSGEOM_LIN;Liniowo +TP_LENSGEOM_LOG;Logarytmicznie +TP_LENSPROFILE_CORRECTION_LCPFILE;Plik LCP TP_LENSPROFILE_LABEL;Profil korekcji obiektywu LCP +TP_LENSPROFILE_MODE_HEADER;Profil obiektywu +TP_LENSPROFILE_USE_CA;Aberracja chromatyczna +TP_LENSPROFILE_USE_GEOMETRIC;Zniekształcenia geometryczne +TP_LENSPROFILE_USE_VIGNETTING;Winietowanie +TP_LOCALCONTRAST_AMOUNT;Ilość +TP_LOCALCONTRAST_LABEL;Kontrast lokalny +TP_LOCALCONTRAST_RADIUS;Promień +TP_METADATA_EDIT;Zastosuj modyfikacje +TP_METADATA_MODE;Tryb kopiowania metadanych +TP_METADATA_STRIP;Usuń wszystkie metadane +TP_METADATA_TUNNEL;Kopiuj niezmienione +TP_NEUTRAL;Reset TP_NEUTRAL_TIP;Zresetuj ustawienia do wartości neutralnych.\nDziała na tych samych suwakach na których funkcja "Wyrównaj poziomy" działa, niezależnie od tego czy funkcja ta była użyta czy nie. TP_PCVIGNETTE_FEATHER;Wtapianie TP_PCVIGNETTE_FEATHER_TOOLTIP;Wtapianie:\n0 = tylko brzegi,\n50 = w pół drogi do środka,\n100 = aż do środka. @@ -1192,8 +1469,13 @@ TP_PREPROCESS_HOTPIXFILT;Filtr gorących pikseli TP_PREPROCESS_HOTPIXFILT_TOOLTIP;Łata gorące piksele (pojedyńcze świecące, przesycone piksele). TP_PREPROCESS_LABEL;Przetwarzanie początkowe TP_PREPROCESS_LINEDENOISE;Filtr zakłóceń liniowych +TP_PREPROCESS_LINEDENOISE_DIRECTION;Kierunek +TP_PREPROCESS_LINEDENOISE_DIRECTION_HORIZONTAL;Poziomo +TP_PREPROCESS_LINEDENOISE_DIRECTION_VERTICAL;Pionowo TP_PREPROCESS_NO_FOUND;Nic nie znaleziono TP_RAWCACORR_AUTO;Autokorekcja +TP_RAWCACORR_AUTOIT;Iteracje +TP_RAWCACORR_AVOIDCOLORSHIFT;Unikaj przesunięcia kolorów TP_RAWCACORR_CABLUE;Niebieski TP_RAWCACORR_CARED;Czerwony TP_RAWCACORR_LABEL;Korekcja aberracji chromatycznej @@ -1207,19 +1489,47 @@ TP_RAWEXPOS_BLACK_RED;Czerwony TP_RAWEXPOS_LINEAR;Liniowy współczynnik korekcji TP_RAWEXPOS_RGB;Czerwony, Zielony, Niebieski TP_RAWEXPOS_TWOGREEN;Połącz obie zielenie +TP_RAW_1PASSMEDIUM;1-pass (Markesteijn) +TP_RAW_2PASS;1-pass+fast +TP_RAW_3PASSBEST;3-pass (Markesteijn) +TP_RAW_4PASS;3-pass+fast +TP_RAW_AHD;AHD +TP_RAW_AMAZE;AMaZE +TP_RAW_AMAZEVNG4;AMaZE+VNG4 +TP_RAW_DCB;DCB TP_RAW_DCBENHANCE;Zastosuj poprawę DCB TP_RAW_DCBITERATIONS;Liczba powtórzeń DCB +TP_RAW_DCBVNG4;DCB+VNG4 TP_RAW_DMETHOD;Metoda TP_RAW_DMETHOD_PROGRESSBAR;Demozaikowanie %1... TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Udoskonalanie demozaikowania... TP_RAW_DMETHOD_TOOLTIP;IGV oraz LMMSE są przeznaczone dla zdjęć raw o wysokim poziomie szumów (wysokie ISO) aby zapobiec utworzeniu się wzorków w kształcie małych labiryntów, posteryzacji oraz mydlanego wyglądu. +TP_RAW_DUALDEMOSAICAUTOCONTRAST;Próg automatyczny +TP_RAW_DUALDEMOSAICCONTRAST;Próg kontrastu +TP_RAW_EAHD;EAHD TP_RAW_FALSECOLOR;Kroki zapobiegające fałszowaniu kolorów +TP_RAW_FAST;Szybki +TP_RAW_HD;Próg +TP_RAW_HPHD;HPHD +TP_RAW_IGV;IGV TP_RAW_LABEL;Demozaikowanie +TP_RAW_LMMSE;LMMSE TP_RAW_LMMSEITERATIONS;Ilość kroków udoskonalenia LMMSE TP_RAW_LMMSE_TOOLTIP;Aby zmniejszyć ilość artefaktów i poprawić stosunek sygnału do szumów, można wykorzystać następujące ustawienia:\n1: Gamma\n2-4: Średnia mediana\n5-6: Rafinowanie +TP_RAW_MONO;Mono +TP_RAW_PIXELSHIFTEPERISO;Czułość +TP_RAW_PIXELSHIFTMM_AUTO;Automatyczny +TP_RAW_PIXELSHIFTMM_CUSTOM;Własny +TP_RAW_PIXELSHIFTMM_OFF;Wyłączony +TP_RAW_PIXELSHIFTSIGMA;Promień rozmycia +TP_RAW_RCD;RCD +TP_RAW_RCDVNG4;RCD+VNG4 TP_RAW_SENSOR_BAYER_LABEL;Matryca z filtrem Bayera TP_RAW_SENSOR_XTRANS_DMETHOD_TOOLTIP;Trzy powtórzenia prowadzą do najlepszych rezultatów (zalecane dla zdjęć o niskim ISO).\nJedno powtórzenie jest prawie nie do odróżnienia od trzech dla zdjęć o wysokim ISO a jest znacznie szybsze. TP_RAW_SENSOR_XTRANS_LABEL;Matryca z filtrem X-Trans +TP_RAW_VNG4;VNG4 +TP_RAW_XTRANS;X-Trans +TP_RAW_XTRANSFAST;Szybki X-Trans TP_RESIZE_APPLIESTO;Dotyczy: TP_RESIZE_CROPPEDAREA;Obszaru kadrowanego TP_RESIZE_FITBOX;Wymiary obwodu @@ -1234,6 +1544,35 @@ TP_RESIZE_SCALE;Skalę TP_RESIZE_SPECIFY;Określ: TP_RESIZE_W;Szerokość TP_RESIZE_WIDTH;Szerokość +TP_RETINEX_CONTEDIT_HSL;Histogram HSL +TP_RETINEX_CONTEDIT_LAB;Histogram L*a*b* +TP_RETINEX_CONTEDIT_LH;Odcień +TP_RETINEX_CONTEDIT_MAP;Wyrównywanie +TP_RETINEX_EQUAL;Wyrównywanie +TP_RETINEX_GAIN;Wzmocnienie +TP_RETINEX_HIGH;Wysoki +TP_RETINEX_HIGHLIGHT;Próg podświetleń +TP_RETINEX_LABEL;Retinex +TP_RETINEX_LABEL_MASK;Maska +TP_RETINEX_LABSPACE;L*a*b* +TP_RETINEX_LOW;Niski +TP_RETINEX_MAP;Metoda +TP_RETINEX_MAP_GAUS;Maska Gaussa +TP_RETINEX_MAP_NONE;Żaden +TP_RETINEX_METHOD;Metoda +TP_RETINEX_NEIGHBOR;Promień +TP_RETINEX_NEUTRAL;Reset +TP_RETINEX_OFFSET;Przesunięcie (jasność) +TP_RETINEX_SETTINGS;Ustawienia +TP_RETINEX_SKAL;Skala +TP_RETINEX_STRENGTH;Siła +TP_RETINEX_THRESHOLD;Próg +TP_RETINEX_UNIFORM;Jednolity +TP_RETINEX_VARIANCE;Kontrast +TP_RETINEX_VIEW;Proces +TP_RETINEX_VIEW_MASK;Maska +TP_RETINEX_VIEW_NONE;Standardowy +TP_RETINEX_VIEW_UNSHARP;Maska wyostrzająca TP_RGBCURVES_BLUE;B TP_RGBCURVES_CHANNEL;Kanał TP_RGBCURVES_GREEN;G @@ -1256,6 +1595,7 @@ TP_SHARPENEDGE_LABEL;Krawędzie TP_SHARPENEDGE_PASSES;Powtórzenia TP_SHARPENEDGE_THREE;Tylko luminancja TP_SHARPENING_AMOUNT;Siła +TP_SHARPENING_CONTRAST;Próg kontrastu TP_SHARPENING_EDRADIUS;Promień TP_SHARPENING_EDTOLERANCE;Tolerancja krawędzi TP_SHARPENING_HALOCONTROL;Kontrola poświaty @@ -1271,9 +1611,13 @@ TP_SHARPENING_RLD_ITERATIONS;Powtórzenia TP_SHARPENING_THRESHOLD;Próg TP_SHARPENING_USM;Maska wyostrzająca TP_SHARPENMICRO_AMOUNT;Siła +TP_SHARPENMICRO_CONTRAST;Próg kontrastu TP_SHARPENMICRO_LABEL;Mikrokontrast TP_SHARPENMICRO_MATRIX;Matryca 3×3 zamiast 5×5 TP_SHARPENMICRO_UNIFORMITY;Jednolitość +TP_SOFTLIGHT_STRENGTH;Siła +TP_TM_FATTAL_AMOUNT;Ilość +TP_TM_FATTAL_THRESHOLD;Detale TP_VIBRANCE_AVOIDCOLORSHIFT;Zapobiegaj przesunięcia kolorów TP_VIBRANCE_CURVEEDITOR_SKINTONES;HH TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL;Odcienie skóry @@ -1298,6 +1642,79 @@ TP_VIGNETTING_CENTER_Y;Środek Y TP_VIGNETTING_LABEL;Korekcja winietowania TP_VIGNETTING_RADIUS;Promień TP_VIGNETTING_STRENGTH;Siła +TP_WAVELET_1;Poziom 1 +TP_WAVELET_2;Poziom 2 +TP_WAVELET_3;Poziom 3 +TP_WAVELET_4;Poziom 4 +TP_WAVELET_5;Poziom 5 +TP_WAVELET_6;Poziom 6 +TP_WAVELET_7;Poziom 7 +TP_WAVELET_8;Poziom 8 +TP_WAVELET_9;Poziom 9 +TP_WAVELET_APPLYTO;Zastosuj do +TP_WAVELET_AVOID;Unikaj przesunięcia kolorów +TP_WAVELET_B0;Czarny +TP_WAVELET_B1;Szary +TP_WAVELET_BACKGROUND;Tło +TP_WAVELET_BACUR;Krzywa +TP_WAVELET_BALCHRO;Balans chrominancji +TP_WAVELET_BANONE;Żaden +TP_WAVELET_CCURVE;Kontrast lokalny +TP_WAVELET_CHCU;Krzywa +TP_WAVELET_COMPCONT;Kontrast +TP_WAVELET_CONTR;Gamut +TP_WAVELET_CONTRA;Kontrast +TP_WAVELET_CONTRAST_MINUS;Kontrast - +TP_WAVELET_CONTRAST_PLUS;Kontrast + +TP_WAVELET_CTYPE;Kontrola chrominancji +TP_WAVELET_DALL;We wszystkich kierunkach +TP_WAVELET_DAUB2;D2 - niski +TP_WAVELET_DAUB4;D4 - standard +TP_WAVELET_DAUB6;D6 - standard plus +TP_WAVELET_DAUB10;D10 - średni +TP_WAVELET_DAUB14;D14 - wysoki +TP_WAVELET_DONE;Pionowo +TP_WAVELET_DTHR;Po przekątnej +TP_WAVELET_DTWO;Poziomo +TP_WAVELET_EDCU;Krzywa +TP_WAVELET_EDGCONT;Kontrast lokalny +TP_WAVELET_EDGE;Ostrość krawędzi +TP_WAVELET_EDGEDETECTTHR;Niski próg (szum) +TP_WAVELET_EDGEDETECTTHR2;Wysoki próg (wykrywanie) +TP_WAVELET_EDRAD;Promień +TP_WAVELET_EDSL;Suwaki progów +TP_WAVELET_EDVAL;Siła +TP_WAVELET_HS2;Cienie/Podświetlenia +TP_WAVELET_HUESKIN;Odcień skóry +TP_WAVELET_HUESKY;Odcień nieba +TP_WAVELET_LEVF;Kontrast +TP_WAVELET_LEVONE;Poziom 2 +TP_WAVELET_LEVTHRE;Poziom 4 +TP_WAVELET_LEVTWO;Poziom 3 +TP_WAVELET_LEVZERO;Poziom 1 +TP_WAVELET_LIPST;Usprawniony algorytm +TP_WAVELET_MEDI;Usuwaj artefakty niebieskiego nieba +TP_WAVELET_MEDILEV;Wykrywanie krawędzi +TP_WAVELET_NEUTRAL;Neutralny +TP_WAVELET_NOIS;Odszumianie +TP_WAVELET_NPHIGH;Wysoki +TP_WAVELET_NPLOW;Niski +TP_WAVELET_NPNONE;Brak +TP_WAVELET_NPTYPE;Piksele sąsiadujące +TP_WAVELET_PROC;Proces +TP_WAVELET_RE1;Wzmocniony +TP_WAVELET_RE2;Niezmieniony +TP_WAVELET_RE3;Zmniejszony +TP_WAVELET_RESCON;Cienie +TP_WAVELET_RESCONH;Podświetlenia +TP_WAVELET_STREN;Siła +TP_WAVELET_STRENGTH;Siła +TP_WAVELET_SUPE;Ekstra +TP_WAVELET_THR;Próg cieni +TP_WAVELET_THRESHOLD;Poziom podświetleń +TP_WAVELET_THRESHOLD2;Poziom cieni +TP_WAVELET_THRH;Próg podświetleń +TP_WAVELET_TMTYPE;Metoda kompresji TP_WBALANCE_AUTO;Auto TP_WBALANCE_CAMERA;Z aparatu TP_WBALANCE_CLOUDY;Pochmurnie @@ -1332,6 +1749,7 @@ TP_WBALANCE_LED_CRS;CRS SP12 WWMR16 TP_WBALANCE_LED_HEADER;LED TP_WBALANCE_LED_LSI;LSI Lumelex 2040 TP_WBALANCE_METHOD;Metoda +TP_WBALANCE_PICKER;Wybierz TP_WBALANCE_SHADE;Ćień TP_WBALANCE_SIZE;Wielkość: TP_WBALANCE_SOLUX35;Solux 3500K @@ -1361,24 +1779,13 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !CURVEEDITOR_AXIS_LEFT_TAN;LT: !CURVEEDITOR_AXIS_OUT;O: !CURVEEDITOR_AXIS_RIGHT_TAN;RT: -!CURVEEDITOR_CATMULLROM;Flexible !CURVEEDITOR_EDITPOINT_HINT;Enable edition of node in/out values.\n\nRight-click on a node to select it.\nRight-click on empty space to de-select the node. !DONT_SHOW_AGAIN;Don't show this message again. -!DYNPROFILEEDITOR_DELETE;Delete -!DYNPROFILEEDITOR_EDIT;Edit !DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule !DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. -!DYNPROFILEEDITOR_IMGTYPE_ANY;Any !DYNPROFILEEDITOR_IMGTYPE_HDR;HDR !DYNPROFILEEDITOR_IMGTYPE_PS;Pixel Shift -!DYNPROFILEEDITOR_IMGTYPE_STD;Standard -!DYNPROFILEEDITOR_MOVE_DOWN;Move Down -!DYNPROFILEEDITOR_MOVE_UP;Move Up -!DYNPROFILEEDITOR_NEW;New !DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule -!DYNPROFILEEDITOR_PROFILE;Processing Profile -!EXIFFILTER_IMAGETYPE;Image type -!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1386,135 +1793,56 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !EXPORT_USE_FAST_PIPELINE_TIP;Use a dedicated processing pipeline for images in Fast Export mode, that trades speed for quality. Resizing of the image is done as early as possible, instead of doing it at the end like in the normal pipeline. The speedup can be significant, but be prepared to see artifacts and a general degradation of output quality. !EXPORT_USE_NORMAL_PIPELINE;Standard (bypass some steps, resize at the end) !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to open specified path, reload folder and apply "find" keywords. -!FILEBROWSER_CACHECLEARFROMFULL;Clear all including cached profiles -!FILEBROWSER_CACHECLEARFROMPARTIAL;Clear all except cached profiles !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_RESETDEFAULTPROFILE;Reset to default !FILEBROWSER_SHOWNOTTRASHHINT;Show only images not in trash. !FILEBROWSER_SHOWORIGINALHINT;Show only original images.\n\nWhen several images exist with the same filename but different extensions, the one considered original is the one whose extension is nearest the top of the parsed extensions list in Preferences > File Browser > Parsed Extensions. -!FILECHOOSER_FILTER_ANY;All files -!FILECHOOSER_FILTER_COLPROF;Color profiles (*.icc) -!FILECHOOSER_FILTER_CURVE;Curve files -!FILECHOOSER_FILTER_LCP;Lens correction profiles -!FILECHOOSER_FILTER_PP;Processing profiles -!FILECHOOSER_FILTER_SAME;Same format as current photo -!FILECHOOSER_FILTER_TIFF;TIFF files -!GENERAL_APPLY;Apply -!GENERAL_ASIMAGE;As Image -!GENERAL_CURRENT;Current -!GENERAL_OPEN;Open -!GENERAL_RESET;Reset -!GENERAL_SAVE_AS;Save as... !GENERAL_SLIDER;Slider !GIMP_PLUGIN_INFO;Welcome to the RawTherapee GIMP plugin!\nOnce you are done editing, simply close the main RawTherapee window and the image will be automatically imported in GIMP. !HISTOGRAM_TOOLTIP_MODE;Toggle between linear, log-linear and log-log scaling of the histogram. -!HISTORY_MSG_166;Exposure - Reset -!HISTORY_MSG_173;NR - Detail recovery -!HISTORY_MSG_203;NR - Color space !HISTORY_MSG_235;B&W - CM - Auto !HISTORY_MSG_237;B&W - CM -!HISTORY_MSG_256;NR - Median - Type !HISTORY_MSG_273;CT - Color Balance SMH -!HISTORY_MSG_297;NR - Mode -!HISTORY_MSG_299;NR - Chrominance curve -!HISTORY_MSG_300;- -!HISTORY_MSG_301;NR - Luma control -!HISTORY_MSG_302;NR - Chroma method -!HISTORY_MSG_303;NR - Chroma method -!HISTORY_MSG_304;W - Contrast levels !HISTORY_MSG_305;Wavelet Levels -!HISTORY_MSG_306;W - Process -!HISTORY_MSG_307;W - Process -!HISTORY_MSG_308;W - Process direction -!HISTORY_MSG_309;W - ES - Detail !HISTORY_MSG_310;W - Residual - Sky tar/prot !HISTORY_MSG_311;W - Wavelet levels -!HISTORY_MSG_312;W - Residual - Shadows threshold !HISTORY_MSG_313;W - Chroma - Sat/past !HISTORY_MSG_314;W - Gamut - Reduce artifacts -!HISTORY_MSG_315;W - Residual - Contrast !HISTORY_MSG_316;W - Gamut - Skin tar/prot -!HISTORY_MSG_317;W - Gamut - Skin hue -!HISTORY_MSG_318;W - Contrast - Highlight levels -!HISTORY_MSG_319;W - Contrast - Highlight range -!HISTORY_MSG_320;W - Contrast - Shadow range -!HISTORY_MSG_321;W - Contrast - Shadow levels -!HISTORY_MSG_322;W - Gamut - Avoid color shift -!HISTORY_MSG_323;W - ES - Local contrast -!HISTORY_MSG_324;W - Chroma - Pastel -!HISTORY_MSG_325;W - Chroma - Saturated -!HISTORY_MSG_326;W - Chroma - Method !HISTORY_MSG_327;W - Contrast - Apply to !HISTORY_MSG_328;W - Chroma - Link strength !HISTORY_MSG_329;W - Toning - Opacity RG !HISTORY_MSG_330;W - Toning - Opacity BY !HISTORY_MSG_331;W - Contrast levels - Extra !HISTORY_MSG_332;W - Tiling method -!HISTORY_MSG_333;W - Residual - Shadows -!HISTORY_MSG_334;W - Residual - Chroma -!HISTORY_MSG_335;W - Residual - Highlights -!HISTORY_MSG_336;W - Residual - Highlights threshold -!HISTORY_MSG_337;W - Residual - Sky hue -!HISTORY_MSG_338;W - ES - Radius -!HISTORY_MSG_339;W - ES - Strength -!HISTORY_MSG_340;W - Strength !HISTORY_MSG_341;W - Edge performance !HISTORY_MSG_342;W - ES - First level -!HISTORY_MSG_343;W - Chroma levels !HISTORY_MSG_344;W - Meth chroma sl/cur -!HISTORY_MSG_345;W - ES - Local contrast -!HISTORY_MSG_346;W - ES - Local contrast method -!HISTORY_MSG_347;W - Denoise - Level 1 -!HISTORY_MSG_348;W - Denoise - Level 2 -!HISTORY_MSG_349;W - Denoise - Level 3 !HISTORY_MSG_350;W - ES - Edge detection !HISTORY_MSG_351;W - Residual - HH curve -!HISTORY_MSG_352;W - Background !HISTORY_MSG_353;W - ES - Gradient sensitivity !HISTORY_MSG_354;W - ES - Enhanced -!HISTORY_MSG_355;W - ES - Threshold low -!HISTORY_MSG_356;W - ES - Threshold high !HISTORY_MSG_357;W - Denoise - Link with ES !HISTORY_MSG_358;W - Gamut - CH -!HISTORY_MSG_359;Hot/Dead - Threshold !HISTORY_MSG_360;TM - Gamma !HISTORY_MSG_361;W - Final - Chroma balance -!HISTORY_MSG_362;W - Residual - Compression method -!HISTORY_MSG_363;W - Residual - Compression strength -!HISTORY_MSG_364;W - Final - Contrast balance !HISTORY_MSG_365;W - Final - Delta balance !HISTORY_MSG_366;W - Residual - Compression gamma !HISTORY_MSG_367;W - Final - 'After' contrast curve -!HISTORY_MSG_368;W - Final - Contrast balance -!HISTORY_MSG_369;W - Final - Balance method -!HISTORY_MSG_370;W - Final - Local contrast curve !HISTORY_MSG_371;Post-Resize Sharpening -!HISTORY_MSG_372;PRS USM - Radius -!HISTORY_MSG_373;PRS USM - Amount -!HISTORY_MSG_374;PRS USM - Threshold !HISTORY_MSG_375;PRS USM - Sharpen only edges -!HISTORY_MSG_376;PRS USM - Edge detection radius -!HISTORY_MSG_377;PRS USM - Edge tolerance !HISTORY_MSG_378;PRS USM - Halo control !HISTORY_MSG_379;PRS USM - Halo control amount -!HISTORY_MSG_380;PRS - Method -!HISTORY_MSG_381;PRS RLD - Radius -!HISTORY_MSG_382;PRS RLD - Amount !HISTORY_MSG_383;PRS RLD - Damping -!HISTORY_MSG_384;PRS RLD - Iterations -!HISTORY_MSG_385;W - Residual - Color Balance !HISTORY_MSG_386;W - Residual - CB green high !HISTORY_MSG_387;W - Residual - CB blue high !HISTORY_MSG_388;W - Residual - CB green mid !HISTORY_MSG_389;W - Residual - CB blue mid !HISTORY_MSG_390;W - Residual - CB green low !HISTORY_MSG_391;W - Residual - CB blue low -!HISTORY_MSG_392;W - Residual - Color Balance !HISTORY_MSG_393;DCP - Look table !HISTORY_MSG_394;DCP - Baseline exposure !HISTORY_MSG_395;DCP - Base table @@ -1527,49 +1855,28 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !HISTORY_MSG_402;W - Denoise sub-tool !HISTORY_MSG_403;W - ES - Edge sensitivity !HISTORY_MSG_404;W - ES - Base amplification -!HISTORY_MSG_405;W - Denoise - Level 4 !HISTORY_MSG_406;W - ES - Neighboring pixels -!HISTORY_MSG_407;Retinex - Method -!HISTORY_MSG_408;Retinex - Radius -!HISTORY_MSG_409;Retinex - Contrast -!HISTORY_MSG_410;Retinex - Offset -!HISTORY_MSG_411;Retinex - Strength !HISTORY_MSG_412;Retinex - Gaussian gradient -!HISTORY_MSG_413;Retinex - Contrast !HISTORY_MSG_414;Retinex - Histogram - Lab !HISTORY_MSG_415;Retinex - Transmission !HISTORY_MSG_416;Retinex !HISTORY_MSG_417;Retinex - Transmission median -!HISTORY_MSG_418;Retinex - Threshold -!HISTORY_MSG_419;Retinex - Color space !HISTORY_MSG_420;Retinex - Histogram - HSL !HISTORY_MSG_421;Retinex - Gamma !HISTORY_MSG_422;Retinex - Gamma !HISTORY_MSG_423;Retinex - Gamma slope !HISTORY_MSG_424;Retinex - HL threshold !HISTORY_MSG_425;Retinex - Log base -!HISTORY_MSG_426;Retinex - Hue equalizer !HISTORY_MSG_427;Output rendering intent !HISTORY_MSG_428;Monitor rendering intent -!HISTORY_MSG_429;Retinex - Iterations !HISTORY_MSG_430;Retinex - Transmission gradient !HISTORY_MSG_431;Retinex - Strength gradient -!HISTORY_MSG_432;Retinex - M - Highlights !HISTORY_MSG_433;Retinex - M - Highlights TW -!HISTORY_MSG_434;Retinex - M - Shadows !HISTORY_MSG_435;Retinex - M - Shadows TW -!HISTORY_MSG_436;Retinex - M - Radius -!HISTORY_MSG_437;Retinex - M - Method -!HISTORY_MSG_438;Retinex - M - Equalizer -!HISTORY_MSG_439;Retinex - Process -!HISTORY_MSG_440;CbDL - Method !HISTORY_MSG_441;Retinex - Gain transmission -!HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output black point compensation !HISTORY_MSG_444;WB - Temp bias !HISTORY_MSG_445;Raw sub-image -!HISTORY_MSG_449;PS - ISO adaption -!HISTORY_MSG_452;PS - Show motion !HISTORY_MSG_453;PS - Show mask only !HISTORY_MSG_457;PS - Check red/blue !HISTORY_MSG_462;PS - Check green @@ -1577,11 +1884,8 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !HISTORY_MSG_465;PS - Blur radius !HISTORY_MSG_468;PS - Fill holes !HISTORY_MSG_469;PS - Median -!HISTORY_MSG_471;PS - Motion correction !HISTORY_MSG_472;PS - Smooth transitions !HISTORY_MSG_473;PS - Use LMMSE -!HISTORY_MSG_474;PS - Equalize -!HISTORY_MSG_475;PS - Equalize channel !HISTORY_MSG_476;CAM02 - Temp out !HISTORY_MSG_477;CAM02 - Green out !HISTORY_MSG_478;CAM02 - Yb out @@ -1591,16 +1895,9 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !HISTORY_MSG_482;CAM02 - Green scene !HISTORY_MSG_483;CAM02 - Yb scene !HISTORY_MSG_484;CAM02 - Auto Yb scene -!HISTORY_MSG_485;Lens Correction -!HISTORY_MSG_486;Lens Correction - Camera -!HISTORY_MSG_487;Lens Correction - Lens !HISTORY_MSG_488;Dynamic Range Compression -!HISTORY_MSG_489;DRC - Detail -!HISTORY_MSG_490;DRC - Amount -!HISTORY_MSG_491;White Balance -!HISTORY_MSG_492;RGB Curves !HISTORY_MSG_493;L*a*b* Adjustments -!HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors +!HISTORY_MSG_494;Capture Sharpening !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction !HISTORY_MSG_COLORTONING_LABREGION_AB;CT - Color correction !HISTORY_MSG_COLORTONING_LABREGION_CHANNEL;CT - Channel @@ -1615,10 +1912,6 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !HISTORY_MSG_COLORTONING_LABREGION_SATURATION;CT - Saturation !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_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 @@ -1630,17 +1923,11 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !HISTORY_MSG_ICM_WORKING_GAMMA;Working - Gamma !HISTORY_MSG_ICM_WORKING_SLOPE;Working - Slope !HISTORY_MSG_ICM_WORKING_TRC_METHOD;Working - TRC method -!HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount -!HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness -!HISTORY_MSG_LOCALCONTRAST_ENABLED;Local Contrast -!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_RADIUS_BOOST;CS - 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 -!HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold !HISTORY_MSG_RAWCACORR_AUTOIT;Raw CA Correction - Iterations !HISTORY_MSG_RAWCACORR_COLORSHIFT;Raw CA Correction - Avoid color shift !HISTORY_MSG_RAW_BORDER;Raw border @@ -1651,92 +1938,51 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light !HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength !HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor -!ICCPROFCREATOR_COPYRIGHT;Copyright: -!ICCPROFCREATOR_COPYRIGHT_RESET_TOOLTIP;Reset to the default copyright, granted to "RawTherapee, CC0" -!ICCPROFCREATOR_CUSTOM;Custom -!ICCPROFCREATOR_DESCRIPTION;Description: +!HISTORY_MSG_TRANS_Method;Geometry - Method !ICCPROFCREATOR_DESCRIPTION_ADDPARAM;Append gamma and slope values to the description !ICCPROFCREATOR_DESCRIPTION_TOOLTIP;Leave empty to set the default description. -!ICCPROFCREATOR_GAMMA;Gamma -!ICCPROFCREATOR_ICCVERSION;ICC version: !ICCPROFCREATOR_ILL;Illuminant: -!ICCPROFCREATOR_ILL_41;D41 -!ICCPROFCREATOR_ILL_50;D50 -!ICCPROFCREATOR_ILL_55;D55 -!ICCPROFCREATOR_ILL_60;D60 -!ICCPROFCREATOR_ILL_65;D65 -!ICCPROFCREATOR_ILL_80;D80 -!ICCPROFCREATOR_ILL_DEF;Default -!ICCPROFCREATOR_ILL_INC;StdA 2856K !ICCPROFCREATOR_ILL_TOOLTIP;You can only set the illuminant for ICC v4 profiles. !ICCPROFCREATOR_PRIMARIES;Primaries: !ICCPROFCREATOR_PRIM_ACESP0;ACES AP0 !ICCPROFCREATOR_PRIM_ACESP1;ACES AP1 -!ICCPROFCREATOR_PRIM_ADOBE;Adobe RGB (1998) -!ICCPROFCREATOR_PRIM_BEST;BestRGB -!ICCPROFCREATOR_PRIM_BETA;BetaRGB !ICCPROFCREATOR_PRIM_BLUX;Blue X !ICCPROFCREATOR_PRIM_BLUY;Blue Y -!ICCPROFCREATOR_PRIM_BRUCE;BruceRGB !ICCPROFCREATOR_PRIM_GREX;Green X !ICCPROFCREATOR_PRIM_GREY;Green Y -!ICCPROFCREATOR_PRIM_PROPH;Prophoto -!ICCPROFCREATOR_PRIM_REC2020;Rec2020 !ICCPROFCREATOR_PRIM_REDX;Red X !ICCPROFCREATOR_PRIM_REDY;Red Y -!ICCPROFCREATOR_PRIM_SRGB;sRGB !ICCPROFCREATOR_PRIM_TOOLTIP;You can only set custom primaries for ICC v4 profiles. !ICCPROFCREATOR_PRIM_WIDEG;Widegamut -!ICCPROFCREATOR_PROF_V2;ICC v2 -!ICCPROFCREATOR_PROF_V4;ICC v4 -!ICCPROFCREATOR_SAVEDIALOG_TITLE;Save ICC profile as... !ICCPROFCREATOR_SLOPE;Slope !ICCPROFCREATOR_TRC_PRESET;Tone response curve: !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. -!IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. !IPTCPANEL_COPYRIGHT;Copyright notice !IPTCPANEL_COPYRIGHTHINT;Enter a Notice on the current owner of the Copyright for this image, such as ©2008 Jane Doe. !IPTCPANEL_COUNTRYHINT;Enter the name of the country pictured in this image. -!IPTCPANEL_CREATOR;Creator !IPTCPANEL_CREATORHINT;Enter the name of the person that created this image. !IPTCPANEL_CREATORJOBTITLE;Creator's job title !IPTCPANEL_CREATORJOBTITLEHINT;Enter the Job Title of the person listed in the Creator field. -!IPTCPANEL_DATECREATEDHINT;Enter the Date the image was taken. -!IPTCPANEL_DESCRIPTION;Description !IPTCPANEL_DESCRIPTIONHINT;Enter a "caption" describing the who, what, and why of what is happening in this image, this might include names of people, and/or their role in the action that is taking place within the image. !IPTCPANEL_DESCRIPTIONWRITER;Description writer !IPTCPANEL_DESCRIPTIONWRITERHINT;Enter the name of the person involved in writing, editing or correcting the description of the image. !IPTCPANEL_HEADLINEHINT;Enter a brief publishable synopsis or summary of the contents of the image. !IPTCPANEL_INSTRUCTIONSHINT;Enter information about embargoes, or other restrictions not covered by the Copyright field. !IPTCPANEL_KEYWORDSHINT;Enter any number of keywords, terms or phrases used to express the subject matter in the image. -!IPTCPANEL_PROVINCE;Province or state !IPTCPANEL_PROVINCEHINT;Enter the name of the province or state pictured in this image. !IPTCPANEL_SOURCEHINT;Enter or edit the name of a person or party who has a role in the content supply chain, such as a person or entity from whom you received this image from. -!IPTCPANEL_SUPPCATEGORIES;Supplemental categories !IPTCPANEL_SUPPCATEGORIESHINT;Further refines the subject of the image. !IPTCPANEL_TITLEHINT;Enter a short verbal and human readable name for the image, this may be the file name. !IPTCPANEL_TRANSREFERENCE;Job ID !IPTCPANEL_TRANSREFERENCEHINT;Enter a number or identifier needed for workflow control or tracking. -!MAIN_BUTTON_ICCPROFCREATOR;ICC Profile Creator -!MAIN_BUTTON_SENDTOEDITOR;Edit image in external editor -!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_FAVORITES;Favorites -!MAIN_TAB_FAVORITES_TOOLTIP;Shortcut: Alt-u -!MAIN_TAB_INSPECT; Inspect !MAIN_TOOLTIP_BACKCOLOR3;Background color of the preview: middle grey\nShortcut: 9 !MAIN_TOOLTIP_PREVIEWSHARPMASK;Preview the sharpening contrast mask.\nShortcut: p\n\nOnly works when sharpening is enabled and zoom >= 100%. -!MONITOR_PROFILE_SYSTEM;System default !OPTIONS_BUNDLED_MISSING;The bundled profile "%1" could not be found!\n\nYour installation could be damaged.\n\nDefault internal values will be used instead. !OPTIONS_DEFIMG_MISSING;The default profile for non-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. !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_EQUALIZER;Wavelet levels !PARTIALPASTE_FILMNEGATIVE;Film Negative -!PARTIALPASTE_LOCALCONTRAST;Local contrast !PARTIALPASTE_METADATA;Metadata mode !PARTIALPASTE_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !PARTIALPASTE_PRSHARPENING;Post-resize sharpening @@ -1745,73 +1991,43 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !PARTIALPASTE_RAW_BORDER;Raw border !PARTIALPASTE_RAW_IMAGENUM;Sub-image !PARTIALPASTE_RAW_PIXELSHIFT;Pixel Shift -!PARTIALPASTE_RETINEX;Retinex !PARTIALPASTE_SOFTLIGHT;Soft light !PARTIALPASTE_TM_FATTAL;Dynamic range compression -!PREFERENCES_APPEARANCE;Appearance !PREFERENCES_APPEARANCE_COLORPICKERFONT;Color picker font !PREFERENCES_APPEARANCE_CROPMASKCOLOR;Crop mask color !PREFERENCES_APPEARANCE_MAINFONT;Main font !PREFERENCES_APPEARANCE_PSEUDOHIDPI;Pseudo-HiDPI mode -!PREFERENCES_APPEARANCE_THEME;Theme !PREFERENCES_AUTOSAVE_TP_OPEN;Save tool collapsed/expanded state on exit -!PREFERENCES_CACHECLEAR;Clear -!PREFERENCES_CACHECLEAR_ALL;Clear all cached files: !PREFERENCES_CACHECLEAR_ALLBUTPROFILES;Clear all cached files except for cached processing profiles: -!PREFERENCES_CACHECLEAR_ONLYPROFILES;Clear only cached processing profiles: !PREFERENCES_CACHECLEAR_SAFETY;Only files in the cache are cleared. Processing profiles stored alongside the source images are not touched. !PREFERENCES_CHUNKSIZES;Tiles per thread -!PREFERENCES_CHUNKSIZE_RAW_AMAZE;AMaZE demosaic !PREFERENCES_CHUNKSIZE_RAW_CA;Raw CA correction -!PREFERENCES_CHUNKSIZE_RAW_RCD;RCD demosaic -!PREFERENCES_CHUNKSIZE_RAW_XT;Xtrans demosaic -!PREFERENCES_CHUNKSIZE_RGB;RGB processing !PREFERENCES_CLUTSCACHE;HaldCLUT Cache !PREFERENCES_CLUTSCACHE_LABEL;Maximum number of cached CLUTs -!PREFERENCES_CMMBPC;Black point compensation !PREFERENCES_CROP;Crop Editing !PREFERENCES_CROP_AUTO_FIT;Automatically zoom to fit the crop !PREFERENCES_CROP_GUIDES;Guides shown when not editing the crop -!PREFERENCES_CROP_GUIDES_FRAME;Frame -!PREFERENCES_CROP_GUIDES_FULL;Original -!PREFERENCES_CROP_GUIDES_NONE;None !PREFERENCES_CURVEBBOXPOS;Position of curve copy & paste buttons -!PREFERENCES_CURVEBBOXPOS_ABOVE;Above -!PREFERENCES_CURVEBBOXPOS_BELOW;Below -!PREFERENCES_CURVEBBOXPOS_LEFT;Left -!PREFERENCES_CURVEBBOXPOS_RIGHT;Right -!PREFERENCES_DIRECTORIES;Directories !PREFERENCES_EDITORCMDLINE;Custom command line !PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Compact toolbars in File Browser !PREFERENCES_FSTRIP_SAME_THUMB_HEIGHT;Same thumbnail height between the Filmstrip and the File Browser !PREFERENCES_FSTRIP_SAME_THUMB_HEIGHT_HINT;Having separate thumbnail size will require more processing time each time you'll switch between the single Editor tab and the File Browser. -!PREFERENCES_INSPECT_LABEL;Inspect -!PREFERENCES_INSPECT_MAXBUFFERS_LABEL;Maximum number of cached images !PREFERENCES_INSPECT_MAXBUFFERS_TOOLTIP;Set the maximum number of images stored in cache when hovering over them in the File Browser; systems with little RAM (2GB) should keep this value set to 1 or 2. -!PREFERENCES_LANG;Language !PREFERENCES_MAXRECENTFOLDERS;Maximum number of recent folders !PREFERENCES_MONINTENT;Default rendering intent -!PREFERENCES_MONITOR;Monitor -!PREFERENCES_MONPROFILE;Default color profile !PREFERENCES_MONPROFILE_WARNOSX;Due to MacOS limitations, only sRGB is supported. -!PREFERENCES_NAVIGATIONFRAME;Navigation !PREFERENCES_OVERLAY_FILENAMES_FILMSTRIP;Overlay filenames on thumbnails in the editor pannel !PREFERENCES_PARSEDEXTDOWNHINT;Move selected extension down in the list. !PREFERENCES_PARSEDEXTUPHINT;Move selected extension up in the list. !PREFERENCES_PERFORMANCE_MEASURE;Measure !PREFERENCES_PERFORMANCE_MEASURE_HINT;Logs processing times in console -!PREFERENCES_PERFORMANCE_THREADS;Threads !PREFERENCES_PERFORMANCE_THREADS_LABEL;Maximum number of threads for Noise Reduction and Wavelet Levels (0 = Automatic) -!PREFERENCES_PREVDEMO;Preview Demosaic Method -!PREFERENCES_PREVDEMO_FAST;Fast !PREFERENCES_PREVDEMO_LABEL;Demosaicing method used for the preview at <100% zoom: !PREFERENCES_PREVDEMO_SIDECAR;As in PP3 !PREFERENCES_PRINTER;Printer (Soft-Proofing) !PREFERENCES_PROFILESAVEBOTH;Save processing profile both to the cache and next to the input file !PREFERENCES_PROFILESAVELOCATION;Processing profile saving location -!PREFERENCES_PROFILE_NONE;None !PREFERENCES_PRTINTENT;Rendering intent -!PREFERENCES_PRTPROFILE;Color profile !PREFERENCES_REMEMBERZOOMPAN;Remember zoom % and pan offset !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_SAVE_TP_OPEN_NOW;Save tool collapsed/expanded state now @@ -1820,21 +2036,15 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !PREFERENCES_SERIALIZE_TIFF_READ_TOOLTIP;Enabling this option when working with folders containing uncompressed TIFF files can increase performance of thumbnail generation. !PREFERENCES_SHOWFILMSTRIPTOOLBAR;Show Filmstrip toolbar !PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules -!PREFERENCES_TAB_PERFORMANCE;Performance !PREFERENCES_THUMBNAIL_INSPECTOR_JPEG;Embedded JPEG preview !PREFERENCES_THUMBNAIL_INSPECTOR_MODE;Image to show !PREFERENCES_THUMBNAIL_INSPECTOR_RAW;Neutral raw rendering !PREFERENCES_THUMBNAIL_INSPECTOR_RAW_IF_NO_JPEG_FULLSIZE;Embedded JPEG if fullsize, neutral raw otherwise !PROFILEPANEL_PDYNAMIC;Dynamic -!PROGRESSBAR_DECODING;Decoding... !PROGRESSBAR_GREENEQUIL;Green equilibration... -!PROGRESSBAR_HLREC;Highlight reconstruction... !PROGRESSBAR_HOTDEADPIXELFILTER;Hot/dead pixel filter... !PROGRESSBAR_LINEDENOISE;Line noise filter... !PROGRESSBAR_RAWCACORR;Raw CA correction... -!QINFO_FRAMECOUNT;%2 frames -!QINFO_HDR;HDR / %2 frame(s) -!QINFO_PIXELSHIFT;Pixel Shift / %2 frame(s) !QUEUE_LOCATION_TITLE;Output Location !QUEUE_STARTSTOP_TOOLTIP;Start or stop processing the images in the queue.\n\nShortcut: Ctrl+s !SAMPLEFORMAT_0;Unknown data format @@ -1850,71 +2060,39 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !SOFTPROOF_GAMUTCHECK_TOOLTIP;Highlight pixels with out-of-gamut colors with respect to:\n- the printer profile, if one is set and soft-proofing is enabled,\n- the output profile, if a printer profile is not set and soft-proofing is enabled,\n- the monitor profile, if soft-proofing is disabled. !SOFTPROOF_TOOLTIP;Soft-proofing simulates the appearance of the image:\n- when printed, if a printer profile is set in Preferences > Color Management,\n- when viewed on a display that uses the current output profile, if a printer profile is not set. !TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen the tool is active:\n- Add a picker: left-click.\n- Drag a picker: left-click and drag.\n- Delete a picker: right-click.\n- Delete all pickers: Ctrl+Shift+right-click.\n- Revert to hand tool: right-click outside any picker. -!TP_BWMIX_MIXC;Channel Mixer -!TP_BWMIX_NEUTRAL;Reset !TP_CBDL_AFT;After Black-and-White !TP_CBDL_BEF;Before Black-and-White !TP_CBDL_METHOD;Process located !TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. -!TP_COLORAPP_ABSOLUTELUMINANCE;Absolute luminance !TP_COLORAPP_CAT02ADAPTATION_TOOLTIP;When setting manually, values above 65 are recommended. !TP_COLORAPP_FREE;Free temp+green + CAT02 + [output] !TP_COLORAPP_MEANLUMINANCE;Mean luminance (Yb%) -!TP_COLORAPP_NEUTRAL;Reset -!TP_COLORAPP_NEUTRAL_TIP;Reset all sliders checkbox and curves to their default values !TP_COLORAPP_TEMP_TOOLTIP;To select an illuminant, always set Tint=1.\n\nA temp=2856\nD50 temp=5003\nD55 temp=5503\nD65 temp=6504\nD75 temp=7504 !TP_COLORTONING_LABGRID;L*a*b* color correction grid !TP_COLORTONING_LABGRID_VALUES;HL: a=%1 b=%2\nS: a=%3 b=%4 !TP_COLORTONING_LABREGIONS;Color correction regions !TP_COLORTONING_LABREGION_ABVALUES;a=%1 b=%2 -!TP_COLORTONING_LABREGION_CHANNEL;Channel -!TP_COLORTONING_LABREGION_CHANNEL_ALL;All -!TP_COLORTONING_LABREGION_CHANNEL_B;Blue -!TP_COLORTONING_LABREGION_CHANNEL_G;Green -!TP_COLORTONING_LABREGION_CHANNEL_R;Red !TP_COLORTONING_LABREGION_CHROMATICITYMASK;C !TP_COLORTONING_LABREGION_HUEMASK;H !TP_COLORTONING_LABREGION_LIGHTNESS;Lightness !TP_COLORTONING_LABREGION_LIGHTNESSMASK;L -!TP_COLORTONING_LABREGION_LIST_TITLE;Correction -!TP_COLORTONING_LABREGION_MASK;Mask !TP_COLORTONING_LABREGION_MASKBLUR;Mask Blur -!TP_COLORTONING_LABREGION_OFFSET;Offset !TP_COLORTONING_LABREGION_POWER;Power -!TP_COLORTONING_LABREGION_SATURATION;Saturation -!TP_COLORTONING_LABREGION_SHOWMASK;Show mask !TP_COLORTONING_LABREGION_SLOPE;Slope !TP_CROP_GTHARMMEANS;Harmonic Means !TP_CROP_GTTRIANGLE1;Golden Triangles 1 !TP_CROP_GTTRIANGLE2;Golden Triangles 2 -!TP_CROP_PPI;PPI -!TP_CROP_RESETCROP;Reset -!TP_CROP_SELECTCROP;Select -!TP_DEHAZE_DEPTH;Depth -!TP_DEHAZE_LABEL;Haze Removal -!TP_DEHAZE_SHOW_DEPTH_MAP;Show depth map -!TP_DEHAZE_STRENGTH;Strength !TP_DIRPYRDENOISE_CHROMINANCE_AMZ;Auto multi-zones !TP_DIRPYRDENOISE_CHROMINANCE_AUTOGLOBAL;Automatic global -!TP_DIRPYRDENOISE_CHROMINANCE_CURVE;Chrominance curve !TP_DIRPYRDENOISE_CHROMINANCE_CURVE_TOOLTIP;Increase (multiply) the value of all chrominance sliders.\nThis curve lets you adjust the strength of chromatic noise reduction as a function of chromaticity, for instance to increase the action in areas of low saturation and to decrease it in those of high saturation. -!TP_DIRPYRDENOISE_CHROMINANCE_FRAME;Chrominance -!TP_DIRPYRDENOISE_CHROMINANCE_MANUAL;Manual -!TP_DIRPYRDENOISE_CHROMINANCE_METHOD;Method !TP_DIRPYRDENOISE_CHROMINANCE_METHODADVANCED_TOOLTIP;Manual\nActs on the full image.\nYou control the noise reduction settings manually.\n\nAutomatic global\nActs on the full image.\n9 zones are used to calculate a global chrominance noise reduction setting.\n\nPreview\nActs on the whole image.\nThe part of the image visible in the preview is used to calculate global chrominance noise reduction settings. !TP_DIRPYRDENOISE_CHROMINANCE_METHOD_TOOLTIP;Manual\nActs on the full image.\nYou control the noise reduction settings manually.\n\nAutomatic global\nActs on the full image.\n9 zones are used to calculate a global chrominance noise reduction setting.\n\nAutomatic multi-zones\nNo preview - works only during saving, but using the "Preview" method by matching the tile size and center to the preview size and center you can get an idea of the expected results.\nThe image is divided into tiles (about 10 to 70 depending on image size) and each tile receives its own chrominance noise reduction settings.\n\nPreview\nActs on the whole image.\nThe part of the image visible in the preview is used to calculate global chrominance noise reduction settings. !TP_DIRPYRDENOISE_CHROMINANCE_PMZ;Preview multi-zones -!TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW;Preview !TP_DIRPYRDENOISE_CHROMINANCE_PREVIEWRESIDUAL_INFO_TOOLTIP;Displays the remaining noise levels of the part of the image visible in the preview after wavelet.\n\n>300 Very noisy\n100-300 Noisy\n50-100 A little noisy\n<50 Very low noise\n\nBeware, the values will differ between RGB and L*a*b* mode. The RGB values are less accurate because the RGB mode does not completely separate luminance and chrominance. !TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_INFO;Preview size=%1, Center: Px=%2 Py=%3 !TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_NOISEINFO;Preview noise: Mean=%1 High=%2 !TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_NOISEINFO_EMPTY;Preview noise: Mean= - High= - !TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_TILEINFO;Tile size=%1, Center: Tx=%2 Ty=%3 -!TP_DIRPYRDENOISE_LABEL;Noise Reduction -!TP_DIRPYRDENOISE_LUMINANCE_CONTROL;Luminance control -!TP_DIRPYRDENOISE_LUMINANCE_FRAME;Luminance -!TP_DIRPYRDENOISE_MAIN_COLORSPACE_LAB;L*a*b* -!TP_DIRPYRDENOISE_MEDIAN_METHOD_CHROMINANCE;Chroma only !TP_DIRPYRDENOISE_MEDIAN_METHOD_WEIGHTED;Weighted L* (little) + a*b* (normal) !TP_DIRPYRDENOISE_MEDIAN_PASSES_TOOLTIP;Applying three median filter iterations with a 3×3 window size often leads to better results than using one median filter iteration with a 7×7 window size. !TP_DIRPYRDENOISE_MEDIAN_TYPE_TOOLTIP;Apply a median filter of the desired window size. The larger the window's size, the longer it takes.\n\n3×3 soft: treats 5 pixels in a 3×3 pixel window.\n3×3: treats 9 pixels in a 3×3 pixel window.\n5×5 soft: treats 13 pixels in a 5×5 pixel window.\n5×5: treats 25 pixels in a 5×5 pixel window.\n7×7: treats 49 pixels in a 7×7 pixel window.\n9×9: treats 81 pixels in a 9×9 pixel window.\n\nSometimes it is possible to achieve higher quality running several iterations with a smaller window size than one iteration with a larger one. @@ -1924,19 +2102,15 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_DIRPYRDENOISE_TYPE_5X5SOFT;5×5 soft !TP_DIRPYRDENOISE_TYPE_7X7;7×7 !TP_DIRPYRDENOISE_TYPE_9X9;9×9 -!TP_DIRPYREQUALIZER_ARTIF;Reduce artifacts !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_EPD_GAMMA;Gamma -!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_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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral 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 @@ -1945,76 +2119,36 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_ICM_APPLYHUESATMAP_TOOLTIP;Employ the embedded DCP base table (HueSatMap). The setting is only available if the selected DCP has one. !TP_ICM_APPLYLOOKTABLE;Look table !TP_ICM_APPLYLOOKTABLE_TOOLTIP;Employ the embedded DCP look table. The setting is only available if the selected DCP has one. -!TP_ICM_BPC;Black Point Compensation !TP_ICM_PROFILEINTENT;Rendering Intent !TP_ICM_SAVEREFERENCE;Save Reference Image -!TP_ICM_SAVEREFERENCE_APPLYWB;Apply white balance !TP_ICM_SAVEREFERENCE_APPLYWB_TOOLTIP;Generally, apply the white balance when saving images to create ICC profiles, and do not apply the white balance to create DCP profiles. !TP_ICM_WORKING_TRC;Tone response curve: -!TP_ICM_WORKING_TRC_CUSTOM;Custom !TP_ICM_WORKING_TRC_GAMMA;Gamma -!TP_ICM_WORKING_TRC_NONE;None !TP_ICM_WORKING_TRC_SLOPE;Slope !TP_ICM_WORKING_TRC_TOOLTIP;Only for built-in profiles. !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected -!TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file !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. -!TP_LENSPROFILE_MODE_HEADER;Lens Profile -!TP_LENSPROFILE_USE_CA;Chromatic aberration -!TP_LENSPROFILE_USE_GEOMETRIC;Geometric distortion !TP_LENSPROFILE_USE_HEADER;Correct -!TP_LENSPROFILE_USE_VIGNETTING;Vignetting -!TP_LOCALCONTRAST_AMOUNT;Amount !TP_LOCALCONTRAST_DARKNESS;Darkness level -!TP_LOCALCONTRAST_LABEL;Local Contrast !TP_LOCALCONTRAST_LIGHTNESS;Lightness level -!TP_LOCALCONTRAST_RADIUS;Radius -!TP_METADATA_EDIT;Apply modifications -!TP_METADATA_MODE;Metadata copy mode -!TP_METADATA_STRIP;Strip all metadata -!TP_METADATA_TUNNEL;Copy unchanged -!TP_NEUTRAL;Reset -!TP_PREPROCESS_LINEDENOISE_DIRECTION;Direction +!TP_PDSHARPENING_LABEL;Capture Sharpening !TP_PREPROCESS_LINEDENOISE_DIRECTION_BOTH;Both -!TP_PREPROCESS_LINEDENOISE_DIRECTION_HORIZONTAL;Horizontal !TP_PREPROCESS_LINEDENOISE_DIRECTION_PDAF_LINES;Horizontal only on PDAF rows -!TP_PREPROCESS_LINEDENOISE_DIRECTION_VERTICAL;Vertical !TP_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !TP_PRSHARPENING_LABEL;Post-Resize Sharpening !TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. -!TP_RAWCACORR_AUTOIT;Iterations !TP_RAWCACORR_AUTOIT_TOOLTIP;This setting is available if "Auto-correction" is checked.\nAuto-correction is conservative, meaning that it often does not correct all chromatic aberration.\nTo correct the remaining chromatic aberration, you can use up to five iterations of automatic chromatic aberration correction.\nEach iteration will reduce the remaining chromatic aberration from the last iteration at the cost of additional processing time. -!TP_RAWCACORR_AVOIDCOLORSHIFT;Avoid color shift -!TP_RAW_1PASSMEDIUM;1-pass (Markesteijn) -!TP_RAW_2PASS;1-pass+fast -!TP_RAW_3PASSBEST;3-pass (Markesteijn) -!TP_RAW_4PASS;3-pass+fast -!TP_RAW_AHD;AHD -!TP_RAW_AMAZE;AMaZE -!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_BORDER;Border -!TP_RAW_DCB;DCB -!TP_RAW_DCBVNG4;DCB+VNG4 -!TP_RAW_DUALDEMOSAICAUTOCONTRAST;Auto threshold !TP_RAW_DUALDEMOSAICAUTOCONTRAST_TOOLTIP;If the checkbox is checked (recommended), RawTherapee calculates an optimum value based on flat regions in the image.\nIf there is no flat region in the image or the image is too noisy, the value will be set to 0.\nTo set the value manually, uncheck the checkbox first (reasonable values depend on the image). -!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold -!TP_RAW_EAHD;EAHD -!TP_RAW_FAST;Fast -!TP_RAW_HD;Threshold !TP_RAW_HD_TOOLTIP;Lower values make hot/dead pixel detection more aggressive, but false positives may lead to artifacts. If you notice any artifacts appearing when enabling the Hot/Dead Pixel Filters, gradually increase the threshold value until they disappear. -!TP_RAW_HPHD;HPHD -!TP_RAW_IGV;IGV !TP_RAW_IMAGENUM;Sub-image !TP_RAW_IMAGENUM_SN;SN mode !TP_RAW_IMAGENUM_TOOLTIP;Some raw files consist of several sub-images (Pentax/Sony Pixel Shift, Pentax 3-in-1 HDR, Canon Dual Pixel, Fuji EXR).\n\nWhen using any demosaicing method other than Pixel Shift, this selects which sub-image is used.\n\nWhen using the Pixel Shift demosaicing method on a Pixel Shift raw, all sub-images are used, and this selects which sub-image should be used for moving parts. -!TP_RAW_LMMSE;LMMSE -!TP_RAW_MONO;Mono !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask !TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion -!TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames !TP_RAW_PIXELSHIFTEQUALBRIGHTCHANNEL;Equalize per channel @@ -2025,38 +2159,23 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_RAW_PIXELSHIFTHOLEFILL_TOOLTIP;Fill holes in motion mask !TP_RAW_PIXELSHIFTMEDIAN;Use median for moving parts !TP_RAW_PIXELSHIFTMEDIAN_TOOLTIP;Use median of all frames instead of selected frame for regions with motion.\nRemoves objects which are at different places in all frames.\nGives motion effect on slow moving (overlapping) objects. -!TP_RAW_PIXELSHIFTMM_AUTO;Automatic -!TP_RAW_PIXELSHIFTMM_CUSTOM;Custom -!TP_RAW_PIXELSHIFTMM_OFF;Off !TP_RAW_PIXELSHIFTMOTIONMETHOD;Motion Correction !TP_RAW_PIXELSHIFTNONGREENCROSS;Check red/blue channels for motion !TP_RAW_PIXELSHIFTSHOWMOTION;Show motion mask !TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY;Show only motion mask !TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY_TOOLTIP;Shows the motion mask without the image. !TP_RAW_PIXELSHIFTSHOWMOTION_TOOLTIP;Overlays the image with a green mask showing the regions with motion. -!TP_RAW_PIXELSHIFTSIGMA;Blur radius !TP_RAW_PIXELSHIFTSIGMA_TOOLTIP;The default radius of 1.0 usually fits well for base ISO.\nIncrease the value for high ISO shots, 5.0 is a good starting point.\nWatch the motion mask while changing the value. !TP_RAW_PIXELSHIFTSMOOTH;Smooth transitions !TP_RAW_PIXELSHIFTSMOOTH_TOOLTIP;Smooth transitions between areas with motion and areas without.\nSet to 0 to disable transition smoothing.\nSet to 1 to either get the AMaZE/LMMSE result of the selected frame (depending on whether "Use LMMSE" is selected), or the median of all four frames if "Use median" is selected. -!TP_RAW_RCD;RCD -!TP_RAW_RCDVNG4;RCD+VNG4 -!TP_RAW_VNG4;VNG4 -!TP_RAW_XTRANS;X-Trans -!TP_RAW_XTRANSFAST;Fast X-Trans !TP_RESIZE_ALLOW_UPSCALING;Allow Upscaling -!TP_RETINEX_CONTEDIT_HSL;HSL histogram -!TP_RETINEX_CONTEDIT_LAB;L*a*b* histogram -!TP_RETINEX_CONTEDIT_LH;Hue -!TP_RETINEX_CONTEDIT_MAP;Equalizer !TP_RETINEX_CURVEEDITOR_CD;L=f(L) !TP_RETINEX_CURVEEDITOR_CD_TOOLTIP;Luminance according to luminance L=f(L)\nCorrect raw data to reduce halos and artifacts. !TP_RETINEX_CURVEEDITOR_LH;Strength=f(H) !TP_RETINEX_CURVEEDITOR_LH_TOOLTIP;Strength according to hue Strength=f(H)\nThis curve also acts on chroma when using the "Highlight" retinex method. !TP_RETINEX_CURVEEDITOR_MAP;L=f(L) !TP_RETINEX_CURVEEDITOR_MAP_TOOLTIP;This curve can be applied alone or with a Gaussian mask or wavelet mask.\nBeware of artifacts! -!TP_RETINEX_EQUAL;Equalizer !TP_RETINEX_FREEGAMMA;Free gamma -!TP_RETINEX_GAIN;Gain !TP_RETINEX_GAINOFFS;Gain and Offset (brightness) !TP_RETINEX_GAINTRANSMISSION;Gain transmission !TP_RETINEX_GAINTRANSMISSION_TOOLTIP;Amplify or reduce the transmission map to achieve the desired luminance.\nThe x-axis is the transmission.\nThe y-axis is the gain. @@ -2071,41 +2190,24 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_RETINEX_GRADS;Strength gradient !TP_RETINEX_GRADS_TOOLTIP;If slider at 0, all iterations are identical.\nIf > 0 Strength is reduced when iterations increase, and conversely. !TP_RETINEX_GRAD_TOOLTIP;If slider at 0, all iterations are identical.\nIf > 0 Variance and Threshold are reduced when iterations increase, and conversely. -!TP_RETINEX_HIGH;High !TP_RETINEX_HIGHLIG;Highlight -!TP_RETINEX_HIGHLIGHT;Highlight threshold !TP_RETINEX_HIGHLIGHT_TOOLTIP;Increase action of High algorithm.\nMay require you to re-adjust "Neighboring pixels" and to increase the "White-point correction" in the Raw tab -> Raw White Points tool. !TP_RETINEX_HSLSPACE_LIN;HSL-Linear !TP_RETINEX_HSLSPACE_LOG;HSL-Logarithmic !TP_RETINEX_ITER;Iterations (Tone-mapping) !TP_RETINEX_ITERF;Tone mapping !TP_RETINEX_ITER_TOOLTIP;Simulate a tone-mapping operator.\nHigh values increase the processing time. -!TP_RETINEX_LABEL;Retinex -!TP_RETINEX_LABEL_MASK;Mask -!TP_RETINEX_LABSPACE;L*a*b* -!TP_RETINEX_LOW;Low -!TP_RETINEX_MAP;Method -!TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) !TP_RETINEX_MAP_METHOD_TOOLTIP;Use the mask generated by the Gaussian function above (Radius, Method) to reduce halos and artifacts.\n\nCurve only: apply a diagonal contrast curve on the mask.\nBeware of artifacts!\n\nGaussian mask: generate and use a Gaussian blur of the original mask.\nQuick.\n\nSharp mask: generate and use a wavelet on the original mask.\nSlow. -!TP_RETINEX_MAP_NONE;None !TP_RETINEX_MEDIAN;Transmission median filter -!TP_RETINEX_METHOD;Method !TP_RETINEX_METHOD_TOOLTIP;Low = Reinforce low light.\nUniform = Equalize action.\nHigh = Reinforce high light.\nHighlights = Remove magenta in highlights. !TP_RETINEX_MLABEL;Restored haze-free Min=%1 Max=%2 !TP_RETINEX_MLABEL_TOOLTIP;Should be near min=0 max=32768\nRestored image with no mixture. -!TP_RETINEX_NEIGHBOR;Radius -!TP_RETINEX_NEUTRAL;Reset !TP_RETINEX_NEUTRAL_TIP;Reset all sliders and curves to their default values. -!TP_RETINEX_OFFSET;Offset (brightness) !TP_RETINEX_SCALES;Gaussian gradient !TP_RETINEX_SCALES_TOOLTIP;If slider at 0, all iterations are identical.\nIf > 0 Scale and radius are reduced when iterations increase, and conversely. -!TP_RETINEX_SETTINGS;Settings -!TP_RETINEX_SKAL;Scale !TP_RETINEX_SLOPE;Free gamma slope -!TP_RETINEX_STRENGTH;Strength -!TP_RETINEX_THRESHOLD;Threshold !TP_RETINEX_THRESHOLD_TOOLTIP;Limits in/out.\nIn = image source,\nOut = image gauss. !TP_RETINEX_TLABEL;TM Min=%1 Max=%2 Mean=%3 Sigma=%4 !TP_RETINEX_TLABEL2;TM Tm=%1 TM=%2 @@ -2113,55 +2215,27 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_RETINEX_TRANF;Transmission !TP_RETINEX_TRANSMISSION;Transmission map !TP_RETINEX_TRANSMISSION_TOOLTIP;Transmission according to transmission.\nAbscissa: transmission from negative values (min), mean, and positives values (max).\nOrdinate: amplification or reduction. -!TP_RETINEX_UNIFORM;Uniform -!TP_RETINEX_VARIANCE;Contrast !TP_RETINEX_VARIANCE_TOOLTIP;Low variance increase local contrast and saturation, but can lead to artifacts. -!TP_RETINEX_VIEW;Process -!TP_RETINEX_VIEW_MASK;Mask !TP_RETINEX_VIEW_METHOD_TOOLTIP;Standard - Normal display.\nMask - Displays the mask.\nUnsharp mask - Displays the image with a high radius unsharp mask.\nTransmission - Auto/Fixed - Displays the file transmission-map, before any action on contrast and brightness.\n\nAttention: the mask does not correspond to reality, but is amplified to make it more visible. -!TP_RETINEX_VIEW_NONE;Standard !TP_RETINEX_VIEW_TRAN;Transmission - Auto !TP_RETINEX_VIEW_TRAN2;Transmission - Fixed -!TP_RETINEX_VIEW_UNSHARP;Unsharp mask !TP_SHARPENING_BLUR;Blur radius -!TP_SHARPENING_CONTRAST;Contrast threshold -!TP_SHARPENMICRO_CONTRAST;Contrast threshold +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost !TP_SOFTLIGHT_LABEL;Soft Light -!TP_SOFTLIGHT_STRENGTH;Strength -!TP_TM_FATTAL_AMOUNT;Amount !TP_TM_FATTAL_ANCHOR;Anchor !TP_TM_FATTAL_LABEL;Dynamic Range Compression -!TP_TM_FATTAL_THRESHOLD;Detail -!TP_WAVELET_1;Level 1 -!TP_WAVELET_2;Level 2 -!TP_WAVELET_3;Level 3 -!TP_WAVELET_4;Level 4 -!TP_WAVELET_5;Level 5 -!TP_WAVELET_6;Level 6 -!TP_WAVELET_7;Level 7 -!TP_WAVELET_8;Level 8 -!TP_WAVELET_9;Level 9 -!TP_WAVELET_APPLYTO;Apply To -!TP_WAVELET_AVOID;Avoid color shift -!TP_WAVELET_B0;Black -!TP_WAVELET_B1;Grey !TP_WAVELET_B2;Residual -!TP_WAVELET_BACKGROUND;Background -!TP_WAVELET_BACUR;Curve !TP_WAVELET_BALANCE;Contrast balance d/v-h !TP_WAVELET_BALANCE_TOOLTIP;Alters the balance between the wavelet directions: vertical-horizontal and diagonal.\nIf contrast, chroma or residual tone mapping are activated, the effect due to balance is amplified. -!TP_WAVELET_BALCHRO;Chroma balance !TP_WAVELET_BALCHRO_TOOLTIP;If enabled, the 'Contrast balance' curve or slider also modifies chroma balance. -!TP_WAVELET_BANONE;None !TP_WAVELET_BASLI;Slider !TP_WAVELET_BATYPE;Contrast balance method !TP_WAVELET_CBENAB;Toning and Color Balance !TP_WAVELET_CB_TOOLTIP;For strong values product color-toning by combining it or not with levels decomposition 'toning'\nFor low values you can change the white balance of the background (sky, ...) without changing that of the front plane, generally more contrasted -!TP_WAVELET_CCURVE;Local contrast !TP_WAVELET_CH1;Whole chroma range !TP_WAVELET_CH2;Saturated/pastel !TP_WAVELET_CH3;Link contrast levels -!TP_WAVELET_CHCU;Curve !TP_WAVELET_CHR;Chroma-contrast link strength !TP_WAVELET_CHRO;Saturated/pastel threshold !TP_WAVELET_CHRO_TOOLTIP;Sets the wavelet level which will be the threshold between saturated and pastel colors.\n1-x: saturated\nx-9: pastel\n\nIf the value exceeds the amount of wavelet levels you are using then it will be ignored. @@ -2169,17 +2243,11 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_WAVELET_CHSL;Sliders !TP_WAVELET_CHTYPE;Chrominance method !TP_WAVELET_COLORT;Opacity Red-Green -!TP_WAVELET_COMPCONT;Contrast !TP_WAVELET_COMPGAMMA;Compression gamma !TP_WAVELET_COMPGAMMA_TOOLTIP;Adjusting the gamma of the residual image allows you to equilibrate the data and histogram. !TP_WAVELET_COMPTM;Tone mapping !TP_WAVELET_CONTEDIT;'After' contrast curve -!TP_WAVELET_CONTR;Gamut -!TP_WAVELET_CONTRA;Contrast -!TP_WAVELET_CONTRAST_MINUS;Contrast - -!TP_WAVELET_CONTRAST_PLUS;Contrast + !TP_WAVELET_CONTRA_TOOLTIP;Changes contrast of the residual image. -!TP_WAVELET_CTYPE;Chrominance control !TP_WAVELET_CURVEEDITOR_CC_TOOLTIP;Modifies local contrast as a function of the original local contrast (abscissa).\nLow abscissa values represent small local contrast (real values about 10..20).\n50% abscissa represents average local contrast (real value about 100..300).\n66% abscissa represents standard deviation of local contrast (real value about 300..800).\n100% abscissa represents maximum local contrast (real value about 3000..8000). !TP_WAVELET_CURVEEDITOR_CH;Contrast levels=f(Hue) !TP_WAVELET_CURVEEDITOR_CH_TOOLTIP;Modifies each level's contrast as a function of hue.\nTake care not to overwrite changes made with the Gamut sub-tool's hue controls.\nThe curve will only have an effect when wavelet contrast level sliders are non-zero. @@ -2187,44 +2255,24 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_WAVELET_CURVEEDITOR_CL_TOOLTIP;Applies a final contrast luminance curve at the end of the wavelet treatment. !TP_WAVELET_CURVEEDITOR_HH;HH !TP_WAVELET_CURVEEDITOR_HH_TOOLTIP;Modifies the residual image's hue as a function of hue. -!TP_WAVELET_DALL;All directions !TP_WAVELET_DAUB;Edge performance -!TP_WAVELET_DAUB2;D2 - low -!TP_WAVELET_DAUB4;D4 - standard -!TP_WAVELET_DAUB6;D6 - standard plus -!TP_WAVELET_DAUB10;D10 - medium -!TP_WAVELET_DAUB14;D14 - high !TP_WAVELET_DAUB_TOOLTIP;Changes Daubechies coefficients:\nD4 = Standard,\nD14 = Often best performance, 10% more time-intensive.\n\nAffects edge detection as well as the general quality of the firsts levels. However the quality is not strictly related to this coefficient and can vary with images and uses. -!TP_WAVELET_DONE;Vertical -!TP_WAVELET_DTHR;Diagonal -!TP_WAVELET_DTWO;Horizontal -!TP_WAVELET_EDCU;Curve -!TP_WAVELET_EDGCONT;Local contrast !TP_WAVELET_EDGCONT_TOOLTIP;Adjusting the points to the left decreases contrast, and to the right increases it.\nBottom-left, top-left, top-right and bottom-right represent respectively local contrast for low values, mean, mean+stdev and maxima. -!TP_WAVELET_EDGE;Edge Sharpness !TP_WAVELET_EDGEAMPLI;Base amplification !TP_WAVELET_EDGEDETECT;Gradient sensitivity -!TP_WAVELET_EDGEDETECTTHR;Threshold low (noise) -!TP_WAVELET_EDGEDETECTTHR2;Threshold high (detection) !TP_WAVELET_EDGEDETECTTHR_TOOLTIP;This adjuster lets you target edge detection for example to avoid applying edge sharpness to fine details, such as noise in the sky. !TP_WAVELET_EDGEDETECT_TOOLTIP;Moving the slider to the right increases edge sensitivity. This affects local contrast, edge settings and noise. !TP_WAVELET_EDGESENSI;Edge sensitivity !TP_WAVELET_EDGREINF_TOOLTIP;Reinforce or reduce the action of the first level, do the opposite to the second level, and leave the rest unchanged. !TP_WAVELET_EDGTHRESH;Detail !TP_WAVELET_EDGTHRESH_TOOLTIP;Change the repartition between the first levels and the others. The higher the threshold the more the action is centered on the first levels. Be careful with negative values, they increase the action of high levels and can introduce artifacts. -!TP_WAVELET_EDRAD;Radius !TP_WAVELET_EDRAD_TOOLTIP;This radius adjustment is very different from those in other sharpening tools. Its value is compared to each level through a complex function. In this sense, a value of zero still has an effect. -!TP_WAVELET_EDSL;Threshold Sliders !TP_WAVELET_EDTYPE;Local contrast method -!TP_WAVELET_EDVAL;Strength !TP_WAVELET_FINAL;Final Touchup !TP_WAVELET_FINEST;Finest !TP_WAVELET_HIGHLIGHT;Highlight luminance range !TP_WAVELET_HS1;Whole luminance range -!TP_WAVELET_HS2;Shadows/Highlights -!TP_WAVELET_HUESKIN;Skin hue !TP_WAVELET_HUESKIN_TOOLTIP;The bottom points set the beginning of the transition zone, and the upper points the end of it, where the effect is at its maximum.\n\nIf you need to move the area significantly, or if there are artifacts, then the white balance is incorrect. -!TP_WAVELET_HUESKY;Sky hue !TP_WAVELET_HUESKY_TOOLTIP;The bottom points set the beginning of the transition zone, and the upper points the end of it, where the effect is at its maximum.\n\nIf you need to move the area significantly, or if there are artifacts, then the white balance is incorrect. !TP_WAVELET_ITER;Delta balance levels !TP_WAVELET_ITER_TOOLTIP;Left: increase low levels and reduce high levels,\nRight: reduce low levels and increase high levels. @@ -2237,39 +2285,19 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_WAVELET_LEVDIR_SUP;Above the level !TP_WAVELET_LEVELS;Wavelet levels !TP_WAVELET_LEVELS_TOOLTIP;Choose the number of detail levels the image is to be decomposed into. More levels require more RAM and require a longer processing time. -!TP_WAVELET_LEVF;Contrast !TP_WAVELET_LEVLABEL;Preview maximum possible levels = %1 -!TP_WAVELET_LEVONE;Level 2 -!TP_WAVELET_LEVTHRE;Level 4 -!TP_WAVELET_LEVTWO;Level 3 -!TP_WAVELET_LEVZERO;Level 1 !TP_WAVELET_LINKEDG;Link with Edge Sharpness' Strength -!TP_WAVELET_LIPST;Enhanced algoritm !TP_WAVELET_LOWLIGHT;Shadow luminance range !TP_WAVELET_MEDGREINF;First level -!TP_WAVELET_MEDI;Reduce artifacts in blue sky -!TP_WAVELET_MEDILEV;Edge detection !TP_WAVELET_MEDILEV_TOOLTIP;When you enable Edge Detection, it is recommanded:\n- to disabled low contrast levels to avoid artifacts,\n- to use high values of gradient sensitivity.\n\nYou can modulate the strength with 'refine' from Denoise and Refine. -!TP_WAVELET_NEUTRAL;Neutral -!TP_WAVELET_NOIS;Denoise !TP_WAVELET_NOISE;Denoise and Refine -!TP_WAVELET_NPHIGH;High -!TP_WAVELET_NPLOW;Low -!TP_WAVELET_NPNONE;None -!TP_WAVELET_NPTYPE;Neighboring pixels !TP_WAVELET_NPTYPE_TOOLTIP;This algorithm uses the proximity of a pixel and eight of its neighbors. If less difference, edges are reinforced. !TP_WAVELET_OPACITY;Opacity Blue-Yellow !TP_WAVELET_OPACITYW;Contrast balance d/v-h curve !TP_WAVELET_OPACITYWL;Final local contrast !TP_WAVELET_OPACITYWL_TOOLTIP;Modify the final local contrast at the end of the wavelet treatment.\n\nThe left side represents the smallest local contrast, progressing to the largest local contrast on the right. !TP_WAVELET_PASTEL;Pastel chroma -!TP_WAVELET_PROC;Process -!TP_WAVELET_RE1;Reinforced -!TP_WAVELET_RE2;Unchanged -!TP_WAVELET_RE3;Reduced !TP_WAVELET_RESCHRO;Chroma -!TP_WAVELET_RESCON;Shadows -!TP_WAVELET_RESCONH;Highlights !TP_WAVELET_RESID;Residual Image !TP_WAVELET_SAT;Saturated chroma !TP_WAVELET_SETTINGS;Wavelet Settings @@ -2277,15 +2305,8 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_WAVELET_SKIN_TOOLTIP;At -100 skin-tones are targetted.\nAt 0 all tones are treated equally.\nAt +100 skin-tones are protected while all other tones are affected. !TP_WAVELET_SKY;Sky targetting/protection !TP_WAVELET_SKY_TOOLTIP;At -100 sky-tones are targetted.\nAt 0 all tones are treated equally.\nAt +100 sky-tones are protected while all other tones are affected. -!TP_WAVELET_STREN;Strength -!TP_WAVELET_STRENGTH;Strength -!TP_WAVELET_SUPE;Extra -!TP_WAVELET_THR;Shadows threshold -!TP_WAVELET_THRESHOLD;Highlight levels -!TP_WAVELET_THRESHOLD2;Shadow levels !TP_WAVELET_THRESHOLD2_TOOLTIP;Only levels between 9 and 9 minus the value will be affected by the shadow luminance range. Other levels will be fully treated. The highest level possible is limited by the highlight level value (9 minus highlight level value). !TP_WAVELET_THRESHOLD_TOOLTIP;Only levels beyond the chosen value will be affected by the highlight luminance range. Other levels will be fully treated. The chosen value here limits the highest possible value of the shadow levels. -!TP_WAVELET_THRH;Highlights threshold !TP_WAVELET_TILESBIG;Big tiles !TP_WAVELET_TILESFULL;Full image !TP_WAVELET_TILESIZE;Tiling method @@ -2293,8 +2314,6 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_WAVELET_TILES_TOOLTIP;Processing the full image leads to better quality and is the recommended option, while using tiles is a fall-back solution for users with little RAM. Refer to RawPedia for memory requirements. !TP_WAVELET_TMSTRENGTH;Compression strength !TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image. When the value is different from 0, the Strength and Gamma sliders of the Tone Mapping tool in the Exposure tab will become grayed out. -!TP_WAVELET_TMTYPE;Compression method !TP_WAVELET_TON;Toning -!TP_WBALANCE_PICKER;Pick !TP_WBALANCE_TEMPBIAS;AWB temperature bias !TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". diff --git a/rtdata/languages/Portugues b/rtdata/languages/Portugues index e68f93e56..0896214a0 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 @@ -916,8 +916,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Cor de fundo da pré-visualização: branco\nAtal MAIN_TOOLTIP_BACKCOLOR3;Cor de fundo da pré-visualização: cinza médio\nAtalho: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Bloquear / desbloquear a visualização antes\n\nBloquear: manter a visualização antes inalterada.\nÚtil para avaliar o efeito cumulativo de várias ferramentas.\nAlém disso, podem ser feitas comparações a qualquer momento no histórico.\n\nDesbloquear: a visualização antes seguirá a visualização depois um passo antes, mostrando a imagem antes do efeito da ferramenta atualmente utilizada. MAIN_TOOLTIP_HIDEHP;Mostrar o painel esquerdo (incluindo o histórico).\nAtalho: l -MAIN_TOOLTIP_INDCLIPPEDH;Ver altas luzes cortadas.\nAtalho: < -MAIN_TOOLTIP_INDCLIPPEDS;Ver sombras cortadas.\nAtalho: > +MAIN_TOOLTIP_INDCLIPPEDH;Ver altas luzes cortadas.\nAtalho: > +MAIN_TOOLTIP_INDCLIPPEDS;Ver sombras cortadas.\nAtalho: < MAIN_TOOLTIP_PREVIEWB;Pré-visualizar o canal azul.\nAtalho: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Pré-visualizar a máscara de foco.\nAtalho: Shift-f\n\nMais preciso em imagens com pouca profundidade de campo, baixo ruído e níveis de zoom mais altos.\n\nUtilize um zoom menor entre 10-30% para melhorar a precisão da deteção de imagens com muito ruído. MAIN_TOOLTIP_PREVIEWG;Pré-visualizar o canal verde.\nAtalho: g @@ -2264,8 +2264,19 @@ ZOOMPANEL_ZOOMOUT;Afastar\nAtalho: - !FILEBROWSER_POPUPREMOVE;Delete permanently !FILEBROWSER_POPUPREMOVEINCLPROC;Delete permanently, including queue-processed version !FILEBROWSER_SHOWNOTTRASHHINT;Show only images not in trash. +!GENERAL_HELP;Help +!HISTORY_MSG_494;Capture Sharpening +!HISTORY_MSG_DEHAZE_LUMINANCE;Dehaze - Luminance only !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative !HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - Corner radius boost +!HISTORY_MSG_TRANS_Method;Geometry - Method !MAIN_FRAME_PLACES_DEL;Remove !PARTIALPASTE_FILMNEGATIVE;Film Negative !PREFERENCES_APPEARANCE_PSEUDOHIDPI;Pseudo-HiDPI mode @@ -2277,16 +2288,22 @@ ZOOMPANEL_ZOOMOUT;Afastar\nAtalho: - !PROGRESSBAR_RAWCACORR;Raw CA correction... !QUEUE_LOCATION_TITLE;Output Location !TP_CROP_PPI;PPI +!TP_DEHAZE_LUMINANCE;Luminance only !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral spots !TP_FILMNEGATIVE_RED;Red ratio +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected !TP_LENSPROFILE_MODE_HEADER;Lens Profile !TP_LENSPROFILE_USE_GEOMETRIC;Geometric distortion !TP_LENSPROFILE_USE_HEADER;Correct +!TP_PDSHARPENING_LABEL;Capture Sharpening !TP_RAW_XTRANS;X-Trans !TP_RAW_XTRANSFAST;Fast X-Trans +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost diff --git a/rtdata/languages/Portugues (Brasil) b/rtdata/languages/Portugues (Brasil) index c7cc2dfe7..85dbf377f 100644 --- a/rtdata/languages/Portugues (Brasil) +++ b/rtdata/languages/Portugues (Brasil) @@ -119,8 +119,12 @@ FILEBROWSER_COLORLABEL_TOOLTIP;Etiqueta de cor.\n\nUse o menu suspenso ou atalho FILEBROWSER_COPYPROFILE;Copiar perfil FILEBROWSER_CURRENT_NAME;Nome atual: FILEBROWSER_DARKFRAME;Quadro escuro +FILEBROWSER_DELETEDIALOG_ALL;Você tem certeza que quer deletas permanentemente todos os %1 arquivos na lixeira? FILEBROWSER_DELETEDIALOG_HEADER;Confirmação de exclusão de arquivo +FILEBROWSER_DELETEDIALOG_SELECTED;Você tem certeza que quer deletar permanentemente os %1 arquivos selecionados? +FILEBROWSER_DELETEDIALOG_SELECTEDINCLPROC;Você tem certeza que quer deletar permanentemente os %1 arquivos selecionados, incluindo a versão processada em fila? FILEBROWSER_EMPTYTRASH;Esvaziar lixeira +FILEBROWSER_EMPTYTRASHHINT;Deletar permanentemente todos os arquivos na lixeira. FILEBROWSER_EXTPROGMENU;Abrir com FILEBROWSER_FLATFIELD;Flat-Field FILEBROWSER_MOVETODARKFDIR;Mover para o diretório de quadros escuros @@ -154,6 +158,8 @@ FILEBROWSER_POPUPRANK2;Classificação 2 ** FILEBROWSER_POPUPRANK3;Classificação 3 *** FILEBROWSER_POPUPRANK4;Classificação 4 **** FILEBROWSER_POPUPRANK5;Classificação 5 ***** +FILEBROWSER_POPUPREMOVE;Deletar permanentemente +FILEBROWSER_POPUPREMOVEINCLPROC;Excluir permanentemente, incluindo a versão processada em fila FILEBROWSER_POPUPRENAME;Renomear FILEBROWSER_POPUPSELECTALL;Selecionar tudo FILEBROWSER_POPUPTRASH;Mover para a lixeira @@ -180,6 +186,7 @@ FILEBROWSER_SHOWDIRHINT;Limpar todos os filtros.\nAtalho: d FILEBROWSER_SHOWEDITEDHINT;Mostrar imagens editadas.\nAtalho: 7 FILEBROWSER_SHOWEDITEDNOTHINT;Mostrar imagens não editadas.\nAtalho: 6 FILEBROWSER_SHOWEXIFINFO;Mostrar informações Exif.\n\nAtalhos:\ni - Modo de Guias de Editores Múltiplos,\nAlt-i - Modo de Guia de Editor Único. +FILEBROWSER_SHOWNOTTRASHHINT;Mostrar apenas imagens que não estão no lixo. FILEBROWSER_SHOWORIGINALHINT;Mostre somente imagens originais.\n\nQuando existem várias imagens com o mesmo nome de arquivo, mas extensões diferentes, a única considerada original é aquela cuja extensão está mais próxima da parte superior da lista de extensões analisadas em Preferências > Navegador de Arquivos > Extensões Analisadas. FILEBROWSER_SHOWRANK1HINT;Mostrar imagens classificadas com 1 estrela.\nAtalho: 1 FILEBROWSER_SHOWRANK2HINT;Mostrar imagens classificadas com 2 estrelas.\nAtalho: 2 @@ -870,6 +877,7 @@ MAIN_FRAME_FILEBROWSER;Navegador de Arquivos MAIN_FRAME_FILEBROWSER_TOOLTIP;Navegador de arquivos.\nAtalho: Ctrl-F2 MAIN_FRAME_PLACES;Locais MAIN_FRAME_PLACES_ADD;Adicionar +MAIN_FRAME_PLACES_DEL;Remover MAIN_FRAME_QUEUE;Fila MAIN_FRAME_QUEUE_TOOLTIP;Processando fila.\nAtalho: Ctrl-F3 MAIN_FRAME_RECENT;Pastas Recentes @@ -888,7 +896,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 @@ -915,8 +923,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Cor de fundo da pré-visualização: Branco\nAtal MAIN_TOOLTIP_BACKCOLOR3;Cor de fundo da pré-visualização: Cinza médio\nAtalho: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Travar / Destravar a Antes visualização\n\nTravar: mantenha o Antes visualização inalterada.\nÚtil para avaliar o efeito cumulativo de várias ferramentas.\nAlém disso, comparações podem ser feitas a qualquer momento.\n\nDestravar: o Antes visualização seguinte Depois visualização anterior, mostrando a imagem antes do efeito da ferramenta atualmente utilizada. MAIN_TOOLTIP_HIDEHP;Mostrar/Ocultar o painel esquerdo (incluindo o histórico).\nAtalho: l -MAIN_TOOLTIP_INDCLIPPEDH;Indicação de realce recortado.\nAtalho: < -MAIN_TOOLTIP_INDCLIPPEDS;Indicação de sombra recortada.\nAtalho: > +MAIN_TOOLTIP_INDCLIPPEDH;Indicação de realce recortado.\nAtalho: > +MAIN_TOOLTIP_INDCLIPPEDS;Indicação de sombra recortada.\nAtalho: < MAIN_TOOLTIP_PREVIEWB;Pré-visualize o Canal Azul.\nAtalho: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Pré-visualize a Máscara de Foco.\nAtalho: Shift-f\n\nMais preciso em imagens com pouca profundidade de campo, baixo ruído e níveis de zoom mais altos.\n\nPara melhorar a precisão da detecção de imagens ruidosas, avalie com zoom menor, cerca de 10-30%. MAIN_TOOLTIP_PREVIEWG;Pré-visualize o Canal verde.\nAtalho: g @@ -1029,6 +1037,7 @@ PREFERENCES_APPEARANCE_COLORPICKERFONT;Fonte do seletor de cor PREFERENCES_APPEARANCE_CROPMASKCOLOR;Cor da máscara de corte PREFERENCES_APPEARANCE_MAINFONT;Fonte principal PREFERENCES_APPEARANCE_NAVGUIDECOLOR;Cor do guia do navegador +PREFERENCES_APPEARANCE_PSEUDOHIDPI;Modo pseudo-HiDPI PREFERENCES_APPEARANCE_THEME;Tema PREFERENCES_APPLNEXTSTARTUP;é necessário reiniciar PREFERENCES_AUTOMONPROFILE;Usar o perfil de cores do monitor principal do sistema operacional @@ -1215,6 +1224,9 @@ PROFILEPANEL_TOOLTIPCOPY;Copie o perfil de processamento atual para a área de t PROFILEPANEL_TOOLTIPLOAD;Carregue um perfil do arquivo.\nCtrl-click para selecionar os parâmetros a serem carregados. PROFILEPANEL_TOOLTIPPASTE;Cole o perfil da área de transferência.\nCtrl-click para selecionar os parâmetros a serem colados. PROFILEPANEL_TOOLTIPSAVE;Salvar o perfil atual.\nCtrl-click para selecionar os parâmetros a serem salvos. +PROGRESSBAR_GREENEQUIL;Equilíbrio de verde... +PROGRESSBAR_HLREC;Reconstrução de realces... +PROGRESSBAR_LINEDENOISE;Filtro de ruído de linha... PROGRESSBAR_LOADING;Carregando imagem... PROGRESSBAR_LOADINGTHUMBS;Carregando miniaturas... PROGRESSBAR_LOADJPEG;Carregando arquivo JPEG... @@ -1241,6 +1253,7 @@ QUEUE_FORMAT_TITLE;Formato de arquivo QUEUE_LOCATION_FOLDER;Salvar na pasta QUEUE_LOCATION_TEMPLATE;Use modelo QUEUE_LOCATION_TEMPLATE_TOOLTIP;Podes usar as seguintes sequências de formatação:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r, %s1, %s2, ...\n\nEssas cadeias de formatação referem-se às diferentes partes do endereço do nome da foto, alguns atributos da foto ou um índice de sequência arbitrário no processamento em lote.\n\nPor exemplo, se a foto que está sendo processada tiver o seguinte endereço do nome:\n/inicio/rodrigo/fotos/2010-10-31/dsc0042.nef\no significado das cadeias de formatação são:\n%d4 = inicio\n%d3 = rodrigo\n%d2 = fotos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /inicio/rodrigo/fotos/2010-10-31/\n%p2 = /inicio/rodrigo/fotos/\n%p3 = /inicio/rodrigo/\n%p4 = /inicio/\n\n%r será substituído pela classificação da foto. Se a foto não tiver classificação, %r será substituído por '0'. Se a foto estiver na lixeira, %r será substituído por 'x'.\n\n%s1, %s2, etc. será substituído por um índice de sequência que é preenchido entre 1 e 9 dígitos. O índice de sequência iniciará em 1 sempre que o processamento da fila for iniciado e será incrementado em 1 para cada imagem processada.\n\nSe quiseres salvar a imagem de saída no local onde se encontra a original, escreva:\n%p1/%f\n\nSe quiseres salvar a imagem de saída num diretório chamado "convertido" localizado no diretório da imagem aberta, escreva:\n%p1/convertido/%f\n\nSe quiseres salvar a imagem de saída num diretório chamado\n"/inicio/rodrigo/fotos/convertido/2010-10-31", escreva:\n%p2/convertido/%d1/%f +QUEUE_LOCATION_TITLE;Local da Saída QUEUE_STARTSTOP_TOOLTIP;Inicia ou para o processamento das imagens na fila.\n\nAtalho: Ctrl+s SAMPLEFORMAT_0;Formato de dados desconhecido SAMPLEFORMAT_1;8 bits sem assinatura @@ -1612,6 +1625,9 @@ TP_EXPOSURE_TCMODE_STANDARD;Padrão TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Padrão Ponderado TP_EXPOS_BLACKPOINT_LABEL;Pontos Pretos Raw TP_EXPOS_WHITEPOINT_LABEL;Pontos Brancos Raw +TP_FILMNEGATIVE_BLUE;Relação de azul +TP_FILMNEGATIVE_PICK;Pick neutral spots +TP_FILMNEGATIVE_RED;Relação de vermelho TP_FILMSIMULATION_LABEL;Simulação de Filme TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee está configurado para procurar por imagens Hald CLUT, que são usadas para a ferramenta Simulação de Filme, numa pasta que está demorando para carregar.\nVá para Preferências > Processamento de Imagem > Simulação de Filme\npara ver qual pasta está sendo usada. Deves apontar RawTherapee para uma pasta que contenha apenas imagens Hald CLUT e nada mais, ou para uma pasta vazia, se não quiseres usar a ferramenta Simulação de Filme.\n\nLeia o artigo sobre Simulação de Filme na RawPedia para mais informações.\n\nDesejas cancelar a verificação agora? TP_FILMSIMULATION_STRENGTH;Intensidade @@ -1732,9 +1748,13 @@ TP_LABCURVE_RSTPRO_TOOLTIP;Funciona no controle deslizante de cromaticidade e na TP_LENSGEOM_AUTOCROP;Corte automático TP_LENSGEOM_FILL;Preenchimento automático TP_LENSGEOM_LABEL;Lente / Geometria +TP_LENSPROFILE_CORRECTION_AUTOMATCH;Selecionado automaticamente TP_LENSPROFILE_CORRECTION_LCPFILE;Ficheiro LCP +TP_LENSPROFILE_CORRECTION_MANUAL;Selecionado manualmente TP_LENSPROFILE_LABEL;Correção de lente perfilada +TP_LENSPROFILE_MODE_HEADER;Perfil da Lente TP_LENSPROFILE_USE_CA;Aberração cromática +TP_LENSPROFILE_USE_GEOMETRIC;Distorção geométrica TP_LENSPROFILE_USE_VIGNETTING;Vinhetagem TP_LOCALCONTRAST_AMOUNT;Montante TP_LOCALCONTRAST_DARKNESS;Nível de escuridão @@ -2249,45 +2269,42 @@ ZOOMPANEL_ZOOMOUT;Menos Zoom\nAtalho: - !!!!!!!!!!!!!!!!!!!!!!!!! !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to open specified path, reload folder and apply "find" keywords. -!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. +!GENERAL_HELP;Help +!HISTORY_MSG_494;Capture Sharpening !HISTORY_MSG_COLORTONING_LABREGION_OFFSET;CT - region offset !HISTORY_MSG_COLORTONING_LABREGION_POWER;CT - region power +!HISTORY_MSG_DEHAZE_LUMINANCE;Dehaze - Luminance only !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative !HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values -!MAIN_FRAME_PLACES_DEL;Remove +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - Corner radius boost +!HISTORY_MSG_TRANS_Method;Geometry - Method !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... -!PROGRESSBAR_GREENEQUIL;Green equilibration... -!PROGRESSBAR_HLREC;Highlight reconstruction... !PROGRESSBAR_HOTDEADPIXELFILTER;Hot/dead pixel filter... -!PROGRESSBAR_LINEDENOISE;Line noise filter... !PROGRESSBAR_RAWCACORR;Raw CA correction... -!QUEUE_LOCATION_TITLE;Output Location !TP_COLORTONING_LABREGION_OFFSET;Offset !TP_COLORTONING_LABREGION_POWER;Power !TP_CROP_PPI;PPI -!TP_FILMNEGATIVE_BLUE;Blue ratio +!TP_DEHAZE_LUMINANCE;Luminance only !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !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_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !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. -!TP_LENSPROFILE_MODE_HEADER;Lens Profile -!TP_LENSPROFILE_USE_GEOMETRIC;Geometric distortion !TP_LENSPROFILE_USE_HEADER;Correct +!TP_PDSHARPENING_LABEL;Capture Sharpening !TP_RAWCACORR_AUTOIT_TOOLTIP;This setting is available if "Auto-correction" is checked.\nAuto-correction is conservative, meaning that it often does not correct all chromatic aberration.\nTo correct the remaining chromatic aberration, you can use up to five iterations of automatic chromatic aberration correction.\nEach iteration will reduce the remaining chromatic aberration from the last iteration at the cost of additional processing time. !TP_RAW_DUALDEMOSAICAUTOCONTRAST_TOOLTIP;If the checkbox is checked (recommended), RawTherapee calculates an optimum value based on flat regions in the image.\nIf there is no flat region in the image or the image is too noisy, the value will be set to 0.\nTo set the value manually, uncheck the checkbox first (reasonable values depend on the image). !TP_RAW_XTRANS;X-Trans !TP_RAW_XTRANSFAST;Fast X-Trans !TP_RETINEX_GAINTRANSMISSION_TOOLTIP;Amplify or reduce the transmission map to achieve the desired luminance.\nThe x-axis is the transmission.\nThe y-axis is the gain. +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost diff --git a/rtdata/languages/Russian b/rtdata/languages/Russian index a33458ef6..27f4cff0c 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;Детализация @@ -613,8 +613,8 @@ MAIN_TOOLTIP_BACKCOLOR1;Фоновый цвет предпросмотра: MAIN_TOOLTIP_BACKCOLOR2;Фоновый цвет предпросмотра: Белый\nГорячая клавиша: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Заблокировать / Разблокировать предыдущий вид\n\nЗаблокировать: сохраняет предыдущий вид неизменным.\nПолезно для оценки общего эффекта от применения нескольких инструментов.\nК тому же, сравнения могут быть произведены на любом состоянии истории\n\nРазблокировать: предыдущий вид будет следовать сразу за следующим, показывая состояние изображения до применения текущего инструмента. MAIN_TOOLTIP_HIDEHP;Показать/скрыть левую панель (включая историю).\nГорячая клавиша l -MAIN_TOOLTIP_INDCLIPPEDH;Индикатор пересветов.\nГорячая клавиша: < -MAIN_TOOLTIP_INDCLIPPEDS;Индикатор затемнений.\nГорячая клавиша: > +MAIN_TOOLTIP_INDCLIPPEDH;Индикатор пересветов.\nГорячая клавиша: > +MAIN_TOOLTIP_INDCLIPPEDS;Индикатор затемнений.\nГорячая клавиша: < MAIN_TOOLTIP_PREVIEWB;Просмотреть канал синего.\nГорячая клавиша: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Просмотреть Маску резкости.\nГорячая клавиша: Shift-F\n\nБолее точна на изображениях с небольшой глубиной резкости, малым шумом и при большем приближении изображения\n\nДля улучшения определения на шумных изображениях используйте на маленьком зуме 10-30% MAIN_TOOLTIP_PREVIEWG;Просмотреть канал зеленого.\nГорячая клавиша: g @@ -1475,6 +1475,7 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !FILEBROWSER_SHOWORIGINALHINT;Show only original images.\n\nWhen several images exist with the same filename but different extensions, the one considered original is the one whose extension is nearest the top of the parsed extensions list in Preferences > File Browser > Parsed Extensions. !FILECHOOSER_FILTER_PP;Processing profiles !FILECHOOSER_FILTER_SAME;Same format as current photo +!GENERAL_HELP;Help !GIMP_PLUGIN_INFO;Welcome to the RawTherapee GIMP plugin!\nOnce you are done editing, simply close the main RawTherapee window and the image will be automatically imported in GIMP. !HISTOGRAM_TOOLTIP_MODE;Toggle between linear, log-linear and log-log scaling of the histogram. !HISTORY_MSG_235;B&W - CM - Auto @@ -1690,6 +1691,7 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !HISTORY_MSG_483;CAM02 - Yb scene !HISTORY_MSG_484;CAM02 - Auto Yb scene !HISTORY_MSG_489;DRC - Detail +!HISTORY_MSG_494;Capture Sharpening !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction !HISTORY_MSG_COLORTONING_LABREGION_AB;CT - Color correction !HISTORY_MSG_COLORTONING_LABREGION_CHANNEL;CT - Channel @@ -1704,6 +1706,7 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !HISTORY_MSG_COLORTONING_LABREGION_SATURATION;CT - Saturation !HISTORY_MSG_COLORTONING_LABREGION_SHOWMASK;CT - region show mask !HISTORY_MSG_COLORTONING_LABREGION_SLOPE;CT - region slope +!HISTORY_MSG_DEHAZE_LUMINANCE;Dehaze - Luminance only !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative @@ -1715,6 +1718,13 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !HISTORY_MSG_ICM_WORKING_SLOPE;Working - Slope !HISTORY_MSG_ICM_WORKING_TRC_METHOD;Working - TRC method !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - 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 @@ -1726,6 +1736,7 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !HISTORY_MSG_SHARPENING_BLUR;Sharpening - Blur radius !HISTORY_MSG_SHARPENING_CONTRAST;Sharpening - Contrast threshold !HISTORY_MSG_SH_COLORSPACE;S/H - Colorspace +!HISTORY_MSG_TRANS_Method;Geometry - Method !ICCPROFCREATOR_COPYRIGHT;Copyright: !ICCPROFCREATOR_COPYRIGHT_RESET_TOOLTIP;Reset to the default copyright, granted to "RawTherapee, CC0" !ICCPROFCREATOR_CUSTOM;Custom @@ -1947,6 +1958,7 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !TP_COLORTONING_TWOCOLOR_TOOLTIP;Standard chroma:\nLinear response, a* = b*.\n\nSpecial chroma:\nLinear response, a* = b*, but unbound - try under the diagonal.\n\nSpecial a* and b*:\nLinear response unbound with separate curves for a* and b*. Intended for special effects.\n\nSpecial chroma 2 colors:\nMore predictable. !TP_COLORTONING_TWOSTD;Standard chroma !TP_CROP_PPI;PPI +!TP_DEHAZE_LUMINANCE;Luminance only !TP_DIRPYRDENOISE_CHROMINANCE_AMZ;Auto multi-zones !TP_DIRPYRDENOISE_CHROMINANCE_CURVE_TOOLTIP;Increase (multiply) the value of all chrominance sliders.\nThis curve lets you adjust the strength of chromatic noise reduction as a function of chromaticity, for instance to increase the action in areas of low saturation and to decrease it in those of high saturation. !TP_DIRPYRDENOISE_CHROMINANCE_METHODADVANCED_TOOLTIP;Manual\nActs on the full image.\nYou control the noise reduction settings manually.\n\nAutomatic global\nActs on the full image.\n9 zones are used to calculate a global chrominance noise reduction setting.\n\nPreview\nActs on the whole image.\nThe part of the image visible in the preview is used to calculate global chrominance noise reduction settings. @@ -1979,13 +1991,13 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral 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. +!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, value 0 is used. !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. !TP_ICM_APPLYHUESATMAP;Base table @@ -2003,11 +2015,14 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !TP_ICM_WORKING_TRC_NONE;None !TP_ICM_WORKING_TRC_SLOPE;Slope !TP_ICM_WORKING_TRC_TOOLTIP;Only for built-in profiles. +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected !TP_LENSPROFILE_MODE_HEADER;Lens Profile !TP_LENSPROFILE_USE_GEOMETRIC;Geometric distortion !TP_LENSPROFILE_USE_HEADER;Correct +!TP_PDSHARPENING_LABEL;Capture Sharpening !TP_PREPROCESS_LINEDENOISE_DIRECTION;Direction !TP_PREPROCESS_LINEDENOISE_DIRECTION_BOTH;Both !TP_PREPROCESS_LINEDENOISE_DIRECTION_HORIZONTAL;Horizontal @@ -2135,6 +2150,8 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !TP_RETINEX_VIEW_TRAN2;Transmission - Fixed !TP_RETINEX_VIEW_UNSHARP;Unsharp mask !TP_SHARPENING_BLUR;Blur radius +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost !TP_WAVELET_1;Level 1 !TP_WAVELET_2;Level 2 !TP_WAVELET_3;Level 3 diff --git a/rtdata/languages/Serbian (Cyrilic Characters) b/rtdata/languages/Serbian (Cyrilic Characters) index 98d74a5dd..27da76acc 100644 --- a/rtdata/languages/Serbian (Cyrilic Characters) +++ b/rtdata/languages/Serbian (Cyrilic Characters) @@ -1257,6 +1257,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !GENERAL_APPLY;Apply !GENERAL_ASIMAGE;As Image !GENERAL_CURRENT;Current +!GENERAL_HELP;Help !GENERAL_OPEN;Open !GENERAL_RESET;Reset !GENERAL_SAVE_AS;Save as... @@ -1493,6 +1494,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !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 @@ -1510,6 +1512,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !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 @@ -1530,6 +1533,13 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - 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 @@ -1544,6 +1554,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light !HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength !HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor +!HISTORY_MSG_TRANS_Method;Geometry - Method !ICCPROFCREATOR_COPYRIGHT;Copyright: !ICCPROFCREATOR_COPYRIGHT_RESET_TOOLTIP;Reset to the default copyright, granted to "RawTherapee, CC0" !ICCPROFCREATOR_CUSTOM;Custom @@ -1614,7 +1625,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 @@ -1843,6 +1854,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !TP_CROP_SELECTCROP;Select !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 @@ -1907,16 +1919,16 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral 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 !TP_FILMSIMULATION_ZEROCLUTSFOUND;Set HaldCLUT directory in Preferences !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_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, value 0 is used. !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. !TP_ICM_APPLYHUESATMAP;Base table @@ -1936,6 +1948,8 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !TP_ICM_WORKING_TRC_NONE;None !TP_ICM_WORKING_TRC_SLOPE;Slope !TP_ICM_WORKING_TRC_TOOLTIP;Only for built-in profiles. +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected @@ -1954,6 +1968,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !TP_METADATA_MODE;Metadata copy mode !TP_METADATA_STRIP;Strip all metadata !TP_METADATA_TUNNEL;Copy unchanged +!TP_PDSHARPENING_LABEL;Capture Sharpening !TP_PREPROCESS_DEADPIXFILT;Dead pixel filter !TP_PREPROCESS_DEADPIXFILT_TOOLTIP;Tries to suppress dead pixels. !TP_PREPROCESS_HOTPIXFILT;Hot pixel filter @@ -2119,6 +2134,8 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !TP_RETINEX_VIEW_UNSHARP;Unsharp mask !TP_SHARPENING_BLUR;Blur radius !TP_SHARPENING_CONTRAST;Contrast threshold +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost !TP_SHARPENMICRO_CONTRAST;Contrast threshold !TP_SOFTLIGHT_LABEL;Soft Light !TP_SOFTLIGHT_STRENGTH;Strength diff --git a/rtdata/languages/Slovenian b/rtdata/languages/Slovenian new file mode 100644 index 000000000..73c1bd2d1 --- /dev/null +++ b/rtdata/languages/Slovenian @@ -0,0 +1,2314 @@ +#01 2019-10-05 Matjaž Jeran + +ABOUT_TAB_BUILD;Verzija +ABOUT_TAB_CREDITS;Zasluge +ABOUT_TAB_LICENSE;Licenca +ABOUT_TAB_RELEASENOTES;Opombe ob izdaji +ABOUT_TAB_SPLASH;Uvodni zaslon +ADJUSTER_RESET_TO_DEFAULT;Klik - nastavi na privzeto vrednost.\nCtrl+klik - nastavi na začetno vrednost. +BATCH_PROCESSING;Paketna obdelava +CURVEEDITOR_AXIS_IN;I: +CURVEEDITOR_AXIS_LEFT_TAN;LT: +CURVEEDITOR_AXIS_OUT;O: +CURVEEDITOR_AXIS_RIGHT_TAN;RT: +CURVEEDITOR_CATMULLROM;Fleksibilno +CURVEEDITOR_CURVE;Krivulja +CURVEEDITOR_CURVES;Krivulje +CURVEEDITOR_CUSTOM;Standard +CURVEEDITOR_DARKS;Temine +CURVEEDITOR_EDITPOINT_HINT;Omogoči urejanje vhodno/izhodnih vrednosti v vozlišču.\n\nDesni klik v vozlišču za njgovo izbiro.\nDesni klik v prazno za izbris izbire vozlišča. +CURVEEDITOR_HIGHLIGHTS;Bleščave +CURVEEDITOR_LIGHTS;Osvetljenosti +CURVEEDITOR_LINEAR;Linearno +CURVEEDITOR_LOADDLGLABEL;naloži krivuljo ... +CURVEEDITOR_MINMAXCPOINTS;Ekvalizator +CURVEEDITOR_NURBS;Kontrolna kletka +CURVEEDITOR_PARAMETRIC;Parametrična +CURVEEDITOR_SAVEDLGLABEL;Shrani krivuljo... +CURVEEDITOR_SHADOWS;Sence +CURVEEDITOR_TOOLTIPCOPY;Kopiraj trenutno krivuljo na odložišče. +CURVEEDITOR_TOOLTIPLINEAR;Poravnaj krivuljo v daljico.. +CURVEEDITOR_TOOLTIPLOAD;Naloži krivuljo iz datoteke. +CURVEEDITOR_TOOLTIPPASTE;Prilepi krivuljo iz odlagališča. +CURVEEDITOR_TOOLTIPSAVE;Shrani tenutno krivuljo. +CURVEEDITOR_TYPE;Tip: +DIRBROWSER_FOLDERS;Mape +DONT_SHOW_AGAIN;Ne kaži več tega sporočila. +DYNPROFILEEDITOR_DELETE;Briši +DYNPROFILEEDITOR_EDIT;Uredi +DYNPROFILEEDITOR_EDIT_RULE;Uredi pravilo dinamičnega profila +DYNPROFILEEDITOR_ENTRY_TOOLTIP;Iskanje je neobčutljivo na velike/male črke.\nUporabite "re:" prefiks za\nregularni izraz. +DYNPROFILEEDITOR_IMGTYPE_ANY;Katerikoli +DYNPROFILEEDITOR_IMGTYPE_HDR;HDR +DYNPROFILEEDITOR_IMGTYPE_PS;Pomik pikslov +DYNPROFILEEDITOR_IMGTYPE_STD;Standardni +DYNPROFILEEDITOR_MOVE_DOWN;Pomakni dol +DYNPROFILEEDITOR_MOVE_UP;Pomakni gor +DYNPROFILEEDITOR_NEW;Novo +DYNPROFILEEDITOR_NEW_RULE;Novo pravilo dinamičnega profila +DYNPROFILEEDITOR_PROFILE;Profilo obdelovanja +EDITWINDOW_TITLE;Uredi sliko +EDIT_OBJECT_TOOLTIP;Prikaže gradnik v predoglednem oknu in vam omogoča prilagoditev tega orodja. +EDIT_PIPETTE_TOOLTIP;Če želite krivulji dodati prilagoditveno točko, pridržite tipko Ctrl, medtem ko levo kliknete želeno mesto v predogledu slike.\nČe želite prilagoditi točko, pridržite tipko Ctrl, medtem ko levo kliknete ustrezno območje v predogledu, nato pa jo pustite Ctrl (razen če želite natančen nadzor) in medtem ko držite levi gumb miške, miško premikate navzgor ali navzdol, da to točko v krivulji premaknete navzgor ali navzdol. +EXIFFILTER_APERTURE;Zaslonka +EXIFFILTER_CAMERA;Fotoaparat +EXIFFILTER_EXPOSURECOMPENSATION;Prilagajanje osvetlitve (EV) +EXIFFILTER_FILETYPE;Tip datoteke +EXIFFILTER_FOCALLEN;Goriščna razdalja +EXIFFILTER_IMAGETYPE;Tip slike +EXIFFILTER_ISO;ISO +EXIFFILTER_LENS;Objektiv +EXIFFILTER_METADATAFILTER;Omogoči filtriranje metapodatkov +EXIFFILTER_SHUTTER;Čas +EXIFPANEL_ADDEDIT;Dodaj/Uredi +EXIFPANEL_ADDEDITHINT;Dodaj novo značko ali uredi značko. +EXIFPANEL_ADDTAGDLG_ENTERVALUE;Vnesi vrednost +EXIFPANEL_ADDTAGDLG_SELECTTAG;Izberi značko +EXIFPANEL_ADDTAGDLG_TITLE;Dodaj/Uredi značko +EXIFPANEL_KEEP;Ohrani +EXIFPANEL_KEEPHINT;Ohrani izbrane značke ob pisanju izhodne datoteke. +EXIFPANEL_REMOVE;Odstrani +EXIFPANEL_REMOVEHINT;Odstrani izbrane značke ob pisanju izhodne datoteke. +EXIFPANEL_RESET;Ponastavi +EXIFPANEL_RESETALL;Ponastavi vse +EXIFPANEL_RESETALLHINT;Ponastavi vse značke na njihove izvirne vrednosti. +EXIFPANEL_RESETHINT;Ponastavi izbrane značke na njihove izvirne vrednosti. +EXIFPANEL_SHOWALL;Prikaži vse +EXIFPANEL_SUBDIRECTORY;Podmapa +EXPORT_BYPASS;Koraki obdelave za obvoz +EXPORT_BYPASS_ALL;Izberi / Odizberi vse +EXPORT_BYPASS_DEFRINGE;Izpusti odstranjevanje napak robov +EXPORT_BYPASS_DIRPYRDENOISE;Izpusti zmanjšanje šuma +EXPORT_BYPASS_DIRPYREQUALIZER;xxIzpusti kontrast by Detail Levels +EXPORT_BYPASS_EQUALIZER;Izpusti Podrobnosti valovčkov +EXPORT_BYPASS_RAW_CA;Izpusti [surovo] Popravek kromatske aberacije +EXPORT_BYPASS_RAW_CCSTEPS;Izpusti [surovo] Zatiranje napačnih barv +EXPORT_BYPASS_RAW_DCB_ENHANCE;Izpusti [surovo] DCB koraki izboljšav +EXPORT_BYPASS_RAW_DCB_ITERATIONS;Izpusti [surovo] DCB iteracije +EXPORT_BYPASS_RAW_DF;Izpusti [surovo] Dark-frame +EXPORT_BYPASS_RAW_FF;Izpusti [surovo] Flat-field +EXPORT_BYPASS_RAW_GREENTHRESH;Izpusti [surovo] Uravnoteženje zelene +EXPORT_BYPASS_RAW_LINENOISE;Izpusti [surovo] Filtriranje šuma na liniji +EXPORT_BYPASS_RAW_LMMSE_ITERATIONS;Izpusti [surovo] LMMSE Korake izboljšav +EXPORT_BYPASS_SHARPENEDGE;Izpusti ostrenje robov +EXPORT_BYPASS_SHARPENING;Izpusti ostrenje +EXPORT_BYPASS_SHARPENMICRO;Izpusti mikrokontrast +EXPORT_FASTEXPORTOPTIONS;Nastavitve hitrega izvoza +EXPORT_INSTRUCTIONS;Nastavite hitrega izvoza nudijo možnost izogiba zahtevnih nastavitev gleda časa in virov za obdelavo slik namesto hitrih nastavitev v čakalnih vrstah za obdelavo. Ta način priporočam za hitro izdelavo slik manjše natančnosti kadar se mudi in je izhod zgolj drugačne velikosti od izvirnika brez siceršnjih sprememb vsebine. +EXPORT_MAXHEIGHT;Maksimalna višina: +EXPORT_MAXWIDTH;Maksimalna širina: +EXPORT_PIPELINE;Vrstni red obdelav +EXPORT_PUTTOQUEUEFAST; Vstavi v čakalno vrsto za hiter izvoz +EXPORT_RAW_DMETHOD;Demosaic method +EXPORT_USE_FAST_PIPELINE;Namenska (polna obdelava na sliki spremenjene velikosti) +EXPORT_USE_FAST_PIPELINE_TIP;Uporabite namenski tok obdelav za hitri izvoz za primer, kjer je hitrost pomembnejša od kakovosti. Sprememba velikosti slike se izvede čimprej namesto na koncu kot pri običajnem toku obdelav. Delovanje je bistveno hitrejše a bodite pripravljeni na pojav artefaktov in splošno znužanje kakovosti izdelanih slik. +EXPORT_USE_NORMAL_PIPELINE;Standardno (preskoči nekatere korake, spremeni velikost na koncu) +EXTPROGTARGET_1;surovo +EXTPROGTARGET_2;čakalna vrsta-obdelano +FILEBROWSER_APPLYPROFILE;Izvedi +FILEBROWSER_APPLYPROFILE_PARTIAL;Delno - izvedi +FILEBROWSER_AUTODARKFRAME;Avto dark-frame +FILEBROWSER_AUTOFLATFIELD;Avto flat-field +FILEBROWSER_BROWSEPATHBUTTONHINT;Klik, da odprem določeno pot, naložim mapo in uporabim ključne besede iskanja. +FILEBROWSER_BROWSEPATHHINT;Vnesite pot kamor nameravate.\n\nBližnjice:\nCtrl-o osredotočenje na polje iskanja.\nEnter / Ctrl-Enter da bi brskali tam\nEsc za brisanje sprememb.\nShift-Esc prekinitev osredotočenosti.\n\nBližnjice poti:\n~ - uporabnikova domača mapa.\n! - uporabnikova mapa s slikami +FILEBROWSER_CACHE;Predpomnilnik +FILEBROWSER_CACHECLEARFROMFULL;Počistite vse vključno s predpomnjenimi profili +FILEBROWSER_CACHECLEARFROMPARTIAL;Počistite vse razen predpomnjenih profilov +FILEBROWSER_CLEARPROFILE;Očisti +FILEBROWSER_COLORLABEL_TOOLTIP;Barvna oznaka.\n\nUporabi roletni menu ali funkcionalne tipke:\nShift-Ctrl-0 Brez barve\nShift-Ctrl-1 Rdeča\nShift-Ctrl-2 Rumena\nShift-Ctrl-3 Zelena\nShift-Ctrl-4 Modra\nShift-Ctrl-5 Škrlatna +FILEBROWSER_COPYPROFILE;Kopiraj +FILEBROWSER_CURRENT_NAME;Trenutno ime: +FILEBROWSER_DARKFRAME;Dark-frame +FILEBROWSER_DELETEDIALOG_ALL;Ali ste prepričani, da želite trajno izbrisati vse datoteke %1 v smetnjaku? +FILEBROWSER_DELETEDIALOG_HEADER;Potrditev izbrisa datoteke: +FILEBROWSER_DELETEDIALOG_SELECTED;Ali ste prepričani, da želite trajno izbrisati izbrane datoteke %1? +FILEBROWSER_DELETEDIALOG_SELECTEDINCLPROC;Ali ste prepričani, da želite trajno izbrisati izbrane datoteke %1, vključno z obdelano različico iz čakalne vrste? +FILEBROWSER_DELETEDLGLABEL;Potrditev brisanja datoteke +FILEBROWSER_DELETEDLGMSG;Ali ste prepričani, da želite brisati izbrane %1 datoteke? +FILEBROWSER_DELETEDLGMSGINCLPROC;Ali ste prepričani, da želite brisati izbrane %1 datoteke vključno z verzijo v čakalni vrsti za obdelavo? +FILEBROWSER_EMPTYTRASH;Izprazni smetnjak +FILEBROWSER_EMPTYTRASHHINT;Nepreklicno briši datoteke v smetnjaku. +FILEBROWSER_EXTPROGMENU;Odpri z +FILEBROWSER_FLATFIELD;Flat-field +FILEBROWSER_MOVETODARKFDIR;Prestavi v mapo za dark-frame +FILEBROWSER_MOVETOFLATFIELDDIR;Premakni se v mapo za flat-field +FILEBROWSER_NEW_NAME;Novo ime: +FILEBROWSER_OPENDEFAULTVIEWER;Privzeti pregledovalnik v oknu (obdeluje čakalne vrste) +FILEBROWSER_PARTIALPASTEPROFILE;Delno - prilepi +FILEBROWSER_PASTEPROFILE;Prilepi +FILEBROWSER_POPUPCANCELJOB;Prekliči ukaz +FILEBROWSER_POPUPCOLORLABEL;Barvna oznaka +FILEBROWSER_POPUPCOLORLABEL0;Label: Brez +FILEBROWSER_POPUPCOLORLABEL1;Label: Rdeča +FILEBROWSER_POPUPCOLORLABEL2;Label: Rumena +FILEBROWSER_POPUPCOLORLABEL3;Label: Zelena +FILEBROWSER_POPUPCOLORLABEL4;Label: Modra +FILEBROWSER_POPUPCOLORLABEL5;Label: Škrlatna +FILEBROWSER_POPUPCOPYTO;Kopiraj na... +FILEBROWSER_POPUPFILEOPERATIONS;Delo z datotekami +FILEBROWSER_POPUPMOVEEND;Prestavi na konec čakalne vrste +FILEBROWSER_POPUPMOVEHEAD;Prestavi na začetek čakalne vrste +FILEBROWSER_POPUPMOVETO;Prestavi na... +FILEBROWSER_POPUPOPEN;Odpri +FILEBROWSER_POPUPOPENINEDITOR;Odpri v urejevalniku +FILEBROWSER_POPUPPROCESS;Postavi v čakalno vrsto +FILEBROWSER_POPUPPROCESSFAST;Postavi v čakalno vrsto (Hiter izvoz) +FILEBROWSER_POPUPPROFILEOPERATIONS;Obdelujem profile +FILEBROWSER_POPUPRANK;Rangiraj +FILEBROWSER_POPUPRANK0;Unrank +FILEBROWSER_POPUPRANK1;Rang 1 * +FILEBROWSER_POPUPRANK2;Rang 2 ** +FILEBROWSER_POPUPRANK3;Rang 3 *** +FILEBROWSER_POPUPRANK4;Rang 4 **** +FILEBROWSER_POPUPRANK5;Rang 5 ***** +FILEBROWSER_POPUPREMOVE;Briši +FILEBROWSER_POPUPREMOVEINCLPROC;Briši vključno z izhodom iz čakalne vrste +FILEBROWSER_POPUPRENAME;Preimenuj +FILEBROWSER_POPUPSELECTALL;Izberi vse +FILEBROWSER_POPUPTRASH;Prestavi v smetnjak +FILEBROWSER_POPUPUNRANK;Odstrani rang +FILEBROWSER_POPUPUNTRASH;Odstrani iz smetnjaka +FILEBROWSER_QUERYBUTTONHINT;Očisti poizvedbo iskanja +FILEBROWSER_QUERYHINT;Vnesi imena iskanih datotek. Dovolj je že del imena. Loči iskalne termine z vejicami, npr.\n1001,1004,1199\n\nIzloči termine iskanje s predpono !=\nnpr.\n!=1001,1004,1199\n\nBližnjice:\nCtrl-f - fokusiraj rubriko iskanja,\nEnter - išči,\nEsc - očisti rubriko iskanja,\nShift-Esc - sprosti fokus na rubriki iskanja. +FILEBROWSER_QUERYLABEL; Išči: +FILEBROWSER_RANK1_TOOLTIP;Rank 1 *\nBližnjica: Shift-1 +FILEBROWSER_RANK2_TOOLTIP;Rank 2 *\nBližnjica: Shift-2 +FILEBROWSER_RANK3_TOOLTIP;Rank 3 *\nBližnjica: Shift-3 +FILEBROWSER_RANK4_TOOLTIP;Rank 4 *\nBližnjica: Shift-4 +FILEBROWSER_RANK5_TOOLTIP;Rank 5 *\nBližnjica: Shift-5 +FILEBROWSER_RENAMEDLGLABEL;Preimenuj datoteko +FILEBROWSER_RESETDEFAULTPROFILE;Nastavi na privzeto vrednost +FILEBROWSER_SELECTDARKFRAME;Izberi dark-frame... +FILEBROWSER_SELECTFLATFIELD;Izberite flat-field... +FILEBROWSER_SHOWCOLORLABEL1HINT;Prikaži slike označene z rdečo.\nBližnjica: Alt-1 +FILEBROWSER_SHOWCOLORLABEL2HINT;Prikaži slike označene z rumeno.\nBližnjica: Alt-2 +FILEBROWSER_SHOWCOLORLABEL3HINT;Prikaži slike označene z zeleno.\nBližnjica: Alt-3 +FILEBROWSER_SHOWCOLORLABEL4HINT;Prikaži slike označene z modro.\nBližnjica: Alt-4 +FILEBROWSER_SHOWCOLORLABEL5HINT;Prikaži slike označene s škrlatno.\nBližnjica: Alt-5 +FILEBROWSER_SHOWDIRHINT;Odstrani vse filtre.\nBližnjica: d +FILEBROWSER_SHOWEDITEDHINT;Prikaži spremenjene slike.\nBližnjica: 7 +FILEBROWSER_SHOWEDITEDNOTHINT;Prikaži nespremenjene slike.\nBližnjica: 6 +FILEBROWSER_SHOWEXIFINFO;Prikaži Exif informacije.\n\nBližnjice:\ni - Način zavihkov več urejevalnikov,\nAlt-i - Način enega zavihka urejevalnika. +FILEBROWSER_SHOWNOTTRASHHINT;Prikaži samo nezbrisane slike. +FILEBROWSER_SHOWORIGINALHINT;Prikaži samo izvirne slike.\n\nKadar obstaja več slik z enakim imenom a različnimi podaljški imena, smatram za izvirnik tisto, katere podaljšek je najvišje v seznamu podaljškov v nastavitvah > File Browser > Parsed Extensions. +FILEBROWSER_SHOWRANK1HINT;Prikaži slike označene z 1 zvezdico.\nBližnjica: 1 +FILEBROWSER_SHOWRANK2HINT;Prikaži slike označene z 2 zvezdicama.\nBližnjica: 2 +FILEBROWSER_SHOWRANK3HINT;Prikaži slike označene z 3 zvezdicami.\nBližnjica: 3 +FILEBROWSER_SHOWRANK4HINT;Prikaži slike označene z 4 zvezdicami.\nBližnjica: 4 +FILEBROWSER_SHOWRANK5HINT;Prikaži slike označene z 5 zvezdicami.\nBližnjica: 5 +FILEBROWSER_SHOWRECENTLYSAVEDHINT;Pokaži shranjene slike.\nBližnjica: Alt-7 +FILEBROWSER_SHOWRECENTLYSAVEDNOTHINT;Pokaži neshranjene slike.\nBližnjica: Alt-6 +FILEBROWSER_SHOWTRASHHINT;Pokaži vsebino smetnjaka.\nBližnjica: Ctrl-t +FILEBROWSER_SHOWUNCOLORHINT;Pokaži slike brez barvne oznake.\nShortcut: Alt-0 +FILEBROWSER_SHOWUNRANKHINT;Prikaži nerangirane slike.\nShortcut: 0 +FILEBROWSER_THUMBSIZE;Velikost predogledne sličice +FILEBROWSER_UNRANK_TOOLTIP;Odstrani rang.\nShortcut: Shift-0 +FILEBROWSER_ZOOMINHINT;Povečaj velikost predogledne sličice.\n\nBližnjice:\n+ - Način z več zavihki urejevalnika,\nAlt-+ - Način z enim zavihkom in urejevalnikom. +FILEBROWSER_ZOOMOUTHINT;Pomanjšaj velikost predogledne sličice.\n\nBližnjice:\n- - Način z več zavihki urejevalnika,\nAlt-- - Način z enim zavihkom in urejevalnikom. +FILECHOOSER_FILTER_ANY;Vse datoteke +FILECHOOSER_FILTER_COLPROF;Barvni profili (*.icc) +FILECHOOSER_FILTER_CURVE;Profili krivulj +FILECHOOSER_FILTER_LCP;Profili popravkov lečij +FILECHOOSER_FILTER_PP;Profili obdelovanja +FILECHOOSER_FILTER_SAME;Enak format kot trenutna slika +FILECHOOSER_FILTER_TIFF;Datoteke TIFF +GENERAL_ABOUT;O programu +GENERAL_AFTER;Po +GENERAL_APPLY;Uveljavi +GENERAL_ASIMAGE;Kot slika +GENERAL_AUTO;Avtomatsko +GENERAL_BEFORE;Pred +GENERAL_CANCEL;Prekliči +GENERAL_CLOSE;Zapri +GENERAL_CURRENT;Trenutno +GENERAL_DISABLE;Onemogoči +GENERAL_DISABLED;Onemogočeno +GENERAL_ENABLE;Omogoči +GENERAL_ENABLED;Omogočeno +GENERAL_FILE;Datoteka +GENERAL_LANDSCAPE;Ležeči format +GENERAL_NA;n/a +GENERAL_NO;Ne +GENERAL_NONE;Nič +GENERAL_OK;OK +GENERAL_OPEN;Odpri +GENERAL_PORTRAIT;Pokončni format +GENERAL_RESET;Reset +GENERAL_SAVE;Shrani +GENERAL_SAVE_AS;Shrani kot... +GENERAL_SLIDER;Drsnik +GENERAL_UNCHANGED;(Nespremenjeno) +GENERAL_WARNING;Opozorilo +GIMP_PLUGIN_INFO;Dobrodošli v RawTherapee vtičniku za GIMP!\nKo boste končali z urejanjem enostavno zaprite glavno okno in slika se bo avtomatično uvozila v GIMP. +HISTOGRAM_TOOLTIP_B;Prikaži/Skrij histogram za modro. +HISTOGRAM_TOOLTIP_BAR;Prikaži/Skrij stolpce RGB indikatorjev. +HISTOGRAM_TOOLTIP_CHRO;Prikaži/Skrij histogram barvitosti. +HISTOGRAM_TOOLTIP_G;Prikaži/Skrij histogram za zeleno. +HISTOGRAM_TOOLTIP_L;Prikaži/Skrij histogram CIELab svetlosti. +HISTOGRAM_TOOLTIP_MODE;Preklopi med linearno, log-linearno in log-log merilom histograma. +HISTOGRAM_TOOLTIP_R;Prikaži/Skrij histogram za rdečo. +HISTOGRAM_TOOLTIP_RAW;Prikaži/Skrij surovi histogram. +HISTORY_CHANGED;Spremenjeno +HISTORY_CUSTOMCURVE;Prilagojena krivulja +HISTORY_FROMCLIPBOARD;Iz odložišča +HISTORY_LABEL;Zgodovina +HISTORY_MSG_1;Slika naložena +HISTORY_MSG_2;PP3 naložena +HISTORY_MSG_3;PP3 spremenjena +HISTORY_MSG_4;Brskanje po zgodovini +HISTORY_MSG_5;Ekspozicija - Osvetljenost +HISTORY_MSG_6;Ekspozicija - Kontrast +HISTORY_MSG_7;Ekspozicija - Črnina +HISTORY_MSG_8;Ekspozicija - Prilagoditev +HISTORY_MSG_9;Ekspozicija - Stiskanje bleščav +HISTORY_MSG_10;Ekspozicija - Stiskanje senc +HISTORY_MSG_11;Ekspozicija - Krivulja tonov 1 +HISTORY_MSG_12;Ekspozicija - Avtomatski nivoji +HISTORY_MSG_13;Ekspozicija - Klip +HISTORY_MSG_14;L*a*b* - Osvetljenost +HISTORY_MSG_15;L*a*b* - Kontrast +HISTORY_MSG_16;- +HISTORY_MSG_17;- +HISTORY_MSG_18;- +HISTORY_MSG_19;L*a*b* - krivulja L* +HISTORY_MSG_20;Ostrenje +HISTORY_MSG_21;USM - Radij +HISTORY_MSG_22;USM - Količina +HISTORY_MSG_23;USM - Prag +HISTORY_MSG_24;USM - Naostri samo robove +HISTORY_MSG_25;USM - Radij detekcije roba +HISTORY_MSG_26;USM - Toleranca roba +HISTORY_MSG_27;USM - Kontrola haloja +HISTORY_MSG_28;USM - Kontrolna velikost haloja +HISTORY_MSG_29;Methoda - ostrenja +HISTORY_MSG_30;RLD - Radiij +HISTORY_MSG_31;RLD - Količina +HISTORY_MSG_32;RLD - Blaženje +HISTORY_MSG_33;RLD - Iteracije +HISTORY_MSG_34;Popravki lečja - Popačenje +HISTORY_MSG_35;Popravki lečja - Vinjetiranje +HISTORY_MSG_36;Popravki lečja - - CA +HISTORY_MSG_37;Ekspozicija - Avtomatski nivoji +HISTORY_MSG_38;Ravnotežje beline - Metoda +HISTORY_MSG_39;WB - Temperatura +HISTORY_MSG_40;WB - Odtenek +HISTORY_MSG_41;Ekspozicija - način krivulje odtenkov 1 +HISTORY_MSG_42;Ekspozicija - krivulja odtenkov 2 +HISTORY_MSG_43;Ekspozicija - način krivulje odtenkov 2 +HISTORY_MSG_44;Lum. radij odstranjevanja šuma +HISTORY_MSG_45;Lum. toleranca roba odstranjevanja šuma +HISTORY_MSG_46;Odstranjevanje barvnega šuma +HISTORY_MSG_47;Zmešaj ICC bleščave z matriko +HISTORY_MSG_48;DCP - Krivulja tonov +HISTORY_MSG_49;DCP osvetljava +HISTORY_MSG_50;Sence/bleščave +HISTORY_MSG_51;S/H - Bleščave +HISTORY_MSG_52;S/H - Sence +HISTORY_MSG_53;S/H - Tonska širina bleščav +HISTORY_MSG_54;S/H - Tonska širina senc +HISTORY_MSG_55;S/H - Lokalni kontrast +HISTORY_MSG_56;S/H - Radij +HISTORY_MSG_57;Groba rotacija +HISTORY_MSG_58;Horizontalni preobrat +HISTORY_MSG_59;Vertikalni preobrat +HISTORY_MSG_60;Rotacija +HISTORY_MSG_61;Avtomatsko polnenje +HISTORY_MSG_62;Popravki popačenja +HISTORY_MSG_63;Izbran posnetek stanja +HISTORY_MSG_64;Izrez +HISTORY_MSG_65;CA popravki +HISTORY_MSG_66;Ekspozicija - Rekonstrukcija bleščav +HISTORY_MSG_67;Ekspozicija - HLR količina +HISTORY_MSG_68;Ekspozicija - HLR metoda +HISTORY_MSG_69;Delovni barvni prostor +HISTORY_MSG_70;Izhodni barvni prostor +HISTORY_MSG_71;Vhodni barvni prostor +HISTORY_MSG_72;VC - Količina +HISTORY_MSG_73;Mešalnik kanalov +HISTORY_MSG_74;Sprememba velikosti - Merilo +HISTORY_MSG_75;Spremeba velikosti - Metoda +HISTORY_MSG_76;Exif metapodatki +HISTORY_MSG_77;IPTC metapodatki +HISTORY_MSG_78;- +HISTORY_MSG_79;Sprememba velikosti - Širina +HISTORY_MSG_80;Sprememba velikosti - Višina +HISTORY_MSG_81;Spremeni velikost +HISTORY_MSG_82;Profil spremenjen +HISTORY_MSG_83;S/H - maska ostrenja +HISTORY_MSG_84;Popravek perspektive +HISTORY_MSG_85;Popravek objektiva - datoteka LCP +HISTORY_MSG_86;RGB krivulje - Način svetilnosti +HISTORY_MSG_87;Impulzno zmanjšanje šuma +HISTORY_MSG_88;Prag impulznega zmanjšanja šuma +HISTORY_MSG_89;Zmanjšanje šuma +HISTORY_MSG_90;Zmanjšanje šuma - Svetlost +HISTORY_MSG_91;Zmanjšanje šuma - glavna barvitost +HISTORY_MSG_92;Zmanjšanje šuma - Gama +HISTORY_MSG_93;CbDL - Vrednost +HISTORY_MSG_94;Kontrast po nivojih podrobnosti +HISTORY_MSG_95;L*a*b* - Barvitost +HISTORY_MSG_96;L*a*b* - a* krivulja +HISTORY_MSG_97;L*a*b* - b* krivulja +HISTORY_MSG_98;Metoda odstranjevanja mozaičnosti +HISTORY_MSG_99;Filtriranje vročih pikslov +HISTORY_MSG_100;Ekspozicija - Nasičenje +HISTORY_MSG_101;HSV - Odtenek +HISTORY_MSG_102;HSV - Nasičenost +HISTORY_MSG_103;HSV - Vrednost +HISTORY_MSG_104;HSV Ekvalizator +HISTORY_MSG_105;Odstranjevanje napak robov +HISTORY_MSG_106;Odstranjevanje napak robov - Radij +HISTORY_MSG_107;Odstranjevanje napak robov - Prag +HISTORY_MSG_108;Ekspozicija - prag HLC +HISTORY_MSG_109;Sprememba velikosti - Velikostni okvir +HISTORY_MSG_110;Sprememba velikosti - Uporabi na +HISTORY_MSG_111;L*a*b* - Izogibanje barvnega premika +HISTORY_MSG_112;--neuporabljeno-- +HISTORY_MSG_113;L*a*b* - Zaščita rdeče kože +HISTORY_MSG_114;DCB iteracije +HISTORY_MSG_115;Zatiranje napačne barve +HISTORY_MSG_116;DCB izboljšave +HISTORY_MSG_117;Surovi CA popravek - Rdeča +HISTORY_MSG_118;Surovi CA popravek - Modra +HISTORY_MSG_119;Filtriranje šuma na črti +HISTORY_MSG_120;Uravnoteženje zelene +HISTORY_MSG_121;Surovi CA popravek - Avtomatski +HISTORY_MSG_122;Dark-frame - Avtomatski izbor +HISTORY_MSG_123;Dark-frame - Datoteka +HISTORY_MSG_124;Popravek točke beline +HISTORY_MSG_126;Flat-field - Datoteka +HISTORY_MSG_127;Flat-field - Avto-selekcija +HISTORY_MSG_128;Flat-field - Radij zameglevanja +HISTORY_MSG_129;Flat-field - Tip zameglevanja +HISTORY_MSG_130;Avtomatski popravek popačenja +HISTORY_MSG_131;Zmanjšanje šuma - Luma +HISTORY_MSG_132;Zmanjšanje šuma - Barvitost +HISTORY_MSG_133;Gama izhoda +HISTORY_MSG_134;Svobodni gama +HISTORY_MSG_135;Svobodni gama +HISTORY_MSG_136;Strmina proste game +HISTORY_MSG_137;Nivo črnine - Zelena 1 +HISTORY_MSG_138;Nivo črnine - Rdeča +HISTORY_MSG_139;Nivo črnine - Modra +HISTORY_MSG_140;Nivo črnine - Zelena 2 +HISTORY_MSG_141;Nivo črnine - Poveži zelene +HISTORY_MSG_142;ES - Iteracije +HISTORY_MSG_143;ES - Količina +HISTORY_MSG_144;Mikrokontrast - Količina +HISTORY_MSG_145;Mikrokontrast - Enotnost +HISTORY_MSG_146;Ostrenje robov +HISTORY_MSG_147;ES - Samo svetlost +HISTORY_MSG_148;Mikrokontrast +HISTORY_MSG_149;Mikrokontrast - matrika 3×3 +HISTORY_MSG_150;Zmanjševanje šuma in artefaktov po odstr. mozaičnosti +HISTORY_MSG_151;Vibranca +HISTORY_MSG_152;Vib - Pastelni toni +HISTORY_MSG_153;Vib - Nasičeni toni +HISTORY_MSG_154;Vib - Zavaruj tone kože +HISTORY_MSG_155;Vib - Izogibaj se pomiku barv +HISTORY_MSG_156;Vib - Poveži pastelne/nasičene +HISTORY_MSG_157;Vib - Prag pastelnih/nasičenih +HISTORY_MSG_158;TM - Moč +HISTORY_MSG_159;TM - Zaustavljanje roba +HISTORY_MSG_160;TM - Merilo +HISTORY_MSG_161;TM - Ponovno uteževanje iteracij +HISTORY_MSG_162;Preslikava tonov +HISTORY_MSG_163;RGB Krivulje - Rdeča +HISTORY_MSG_164;RGB Krivulje - Zelena +HISTORY_MSG_165;RGB Krivulje - Modra +HISTORY_MSG_166;Ekspozicija - Ponastavitev +HISTORY_MSG_167;Metoda odstranjevanja mozaičnosti +HISTORY_MSG_168;L*a*b* - CC krivulja +HISTORY_MSG_169;L*a*b* - CH krivulja +HISTORY_MSG_170;Vibrance - HH krivulja +HISTORY_MSG_171;L*a*b* - LC krivulja +HISTORY_MSG_172;L*a*b* - Omeji LC +HISTORY_MSG_173;NR - Obnova podrobnosti +HISTORY_MSG_174;CIECAM02 +HISTORY_MSG_175;CAM02 - CAT02 adaptacija +HISTORY_MSG_176;CAM02 - Pogled okolice +HISTORY_MSG_177;CAM02 - Svetlost scene +HISTORY_MSG_178;CAM02 - Ogled svetlosti +HISTORY_MSG_179;CAM02 - Model bele točke +HISTORY_MSG_180;CAM02 - Lightness (J) +HISTORY_MSG_181;CAM02 - Barvitost (C) +HISTORY_MSG_182;CAM02 - Avtomatski CAT02 +HISTORY_MSG_183;CAM02 - Kontrast (J) +HISTORY_MSG_184;CAM02 - Obkroži sceno +HISTORY_MSG_185;CAM02 - Kontrola barvnega obsega +HISTORY_MSG_186;CAM02 - Algoritem +HISTORY_MSG_187;CAM02 - Zaščita rdeče/kožne +HISTORY_MSG_188;CAM02 - Svetlost (Q) +HISTORY_MSG_189;CAM02 - Kontrast (Q) +HISTORY_MSG_190;CAM02 - Nasičenost (S) +HISTORY_MSG_191;CAM02 - Polnost barv (M) +HISTORY_MSG_192;CAM02 - Odtenek (h) +HISTORY_MSG_193;CAM02 - Krivulja tona 1 +HISTORY_MSG_194;CAM02 - Krivulja tona 2 +HISTORY_MSG_195;CAM02 - Krivulja tona 1 +HISTORY_MSG_196;CAM02 - Krivulja tona 2 +HISTORY_MSG_197;CAM02 - Barvna krivulja +HISTORY_MSG_198;CAM02 - Barvna krivulja +HISTORY_MSG_199;CAM02 - Izhodni histogrami +HISTORY_MSG_200;CAM02 - Preslikava tonov +HISTORY_MSG_201;NR - Barvitost - R&G +HISTORY_MSG_202;NR - Barvitost - B&Y +HISTORY_MSG_203;NR - Barvni prostor +HISTORY_MSG_204;LMMSE koraki izboljšav +HISTORY_MSG_205;CAM02 - Filtriranje vročih/slabih pikslov +HISTORY_MSG_206;CAT02 - Avtomatska svetilnost scene +HISTORY_MSG_207;Odstranjevanje napak robov - Krivulja odtenkov +HISTORY_MSG_208;WB - B/R ekvalizator +HISTORY_MSG_210;GF - Kot +HISTORY_MSG_211;Postopno Filtriranje +HISTORY_MSG_212;VF - Moč +HISTORY_MSG_213;Filter vinjete +HISTORY_MSG_214;Črno-belo +HISTORY_MSG_215;B&W - CM - Rdeče +HISTORY_MSG_216;B&W - CM - Zeleno +HISTORY_MSG_217;B&W - CM - Modro +HISTORY_MSG_218;B&W - Gama - Rdeče +HISTORY_MSG_219;B&W - Gama - Zeleno +HISTORY_MSG_220;B&W - Gama - Modro +HISTORY_MSG_221;B&W - barvni filter +HISTORY_MSG_222;B&W - Prednastavitve +HISTORY_MSG_223;B&W - CM - Oranžno +HISTORY_MSG_224;B&W - CM - Rumeno +HISTORY_MSG_225;B&W - CM - Cian +HISTORY_MSG_226;B&W - CM - Magenta +HISTORY_MSG_227;B&W - CM - Vijolična +HISTORY_MSG_228;B&W - Ekvalizator svetlosti +HISTORY_MSG_229;B&W - Ekvalizator svetlosti +HISTORY_MSG_230;B&W - Način +HISTORY_MSG_231;B&W - Krivulja 'pred' +HISTORY_MSG_232;B&W - Tip krivulje 'pred' +HISTORY_MSG_233;B&W - Krivulja 'po' +HISTORY_MSG_234;B&W - Tip krivulje 'po' +HISTORY_MSG_235;B&W - CM - Avto +HISTORY_MSG_236;--neuporabljeno-- +HISTORY_MSG_237;B&W - CM +HISTORY_MSG_238;GF - Pero +HISTORY_MSG_239;GF - Moč +HISTORY_MSG_240;GF - Center +HISTORY_MSG_241;VF - Pero +HISTORY_MSG_242;VF - Okroglost +HISTORY_MSG_243;VC - Radij +HISTORY_MSG_244;VC - Moč +HISTORY_MSG_245;VC - Center +HISTORY_MSG_246;L*a*b* - CL krivulja +HISTORY_MSG_247;L*a*b* - LH krivulja +HISTORY_MSG_248;L*a*b* - HH krivulja +HISTORY_MSG_249;CbDL - Prag +HISTORY_MSG_250;NR - Izboljšano +HISTORY_MSG_251;B&W - Algoritem +HISTORY_MSG_252;CbDL - Skin tar/prot +HISTORY_MSG_253;CbDL - Reduciraj artefakte +HISTORY_MSG_254;CbDL - Odtenek kože +HISTORY_MSG_255;NR - Filter mediane +HISTORY_MSG_256;NR - Mediana - Tip +HISTORY_MSG_257;Toniranje barve +HISTORY_MSG_258;CT - Barvna krivulja +HISTORY_MSG_259;CT - Krivulja neprosojnosti +HISTORY_MSG_260;CT - a*[b*] neprosojnost +HISTORY_MSG_261;CT - Metoda +HISTORY_MSG_262;CT - b* neprosojnost +HISTORY_MSG_263;CT - Sence - Rdeča +HISTORY_MSG_264;CT - Sence - Zelena +HISTORY_MSG_265;CT - Sence - Modra +HISTORY_MSG_266;CT - srednje - Rdeča +HISTORY_MSG_267;CT - Srednje - Zelena +HISTORY_MSG_268;CT - Srednje - Modra +HISTORY_MSG_269;CT - Svetle - Rdeča +HISTORY_MSG_270;CT - Svetle - Zelena +HISTORY_MSG_271;CT - Svetle - Modra +HISTORY_MSG_272;CT - Uravnoteži +HISTORY_MSG_273;CT - Uravnoteženost barv SMH +HISTORY_MSG_274;CT - Nasičenost senc +HISTORY_MSG_275;CT - Nasičenost svetlih delov +HISTORY_MSG_276;CT - Neprosojnost +HISTORY_MSG_277;--neuporabljeno-- +HISTORY_MSG_278;CT - Ohrani svetlost +HISTORY_MSG_279;CT - Sence +HISTORY_MSG_280;CT - Bleščave +HISTORY_MSG_281;CT - Moč nasičenosti +HISTORY_MSG_282;CT - Prag nasičenosti +HISTORY_MSG_283;CT - Moč +HISTORY_MSG_284;CT - Avtomatsko varovanje nasičenosti +HISTORY_MSG_285;NR - Mediana - Metoda +HISTORY_MSG_286;NR - Mediana - Tip +HISTORY_MSG_287;NR - Mediana - Iteracije +HISTORY_MSG_288;Flat-Field - Kontrola obrezave +HISTORY_MSG_289;Flat-Field - Kontrola obrezave - Avto +HISTORY_MSG_290;Nivo črnine - Rdeča +HISTORY_MSG_291;Nivo črnine - Zelena +HISTORY_MSG_292;Nivo črnine - Modra +HISTORY_MSG_293;Simulacija filma +HISTORY_MSG_294;Simulacija filma - Moč +HISTORY_MSG_295;Simulacija filma - Film +HISTORY_MSG_296;NR - Krivulja svetlosti +HISTORY_MSG_297;NR - Način +HISTORY_MSG_298;Filter mrtvih pikslov +HISTORY_MSG_299;NR - Krivulja svetlosti +HISTORY_MSG_300;- +HISTORY_MSG_301;NR - Kontrola lume +HISTORY_MSG_302;NR - Metoda barvitosti +HISTORY_MSG_303;NR - Metoda barvitosti +HISTORY_MSG_304;W - Nivoji kontrastov +HISTORY_MSG_305;Nivoji valovčkov +HISTORY_MSG_306;W - Obdelava +HISTORY_MSG_307;W - Obdelava +HISTORY_MSG_308;W - Smer obdelave +HISTORY_MSG_309;W - ES - Podrobnost +HISTORY_MSG_310;W - Residual - Nebo tar/prot +HISTORY_MSG_311;W - Nivoji valovčkov +HISTORY_MSG_312;W - Residual - Prag senc +HISTORY_MSG_313;W - Barvitost - Sat/past +HISTORY_MSG_314;W - Barvni obseg - Reduciraj artefakte +HISTORY_MSG_315;W - Residual - Kontrast +HISTORY_MSG_316;W - Barvni obseg - Koža tar/prot +HISTORY_MSG_317;W - Barvni obseg - Koža hue +HISTORY_MSG_318;W - Kontrast - Nivoji bleščav +HISTORY_MSG_319;W - Kontrast - Obseg bleščav +HISTORY_MSG_320;W - Kontrast - Obseg senc +HISTORY_MSG_321;W - Kontrast - Nivoji senc +HISTORY_MSG_322;W - Barvni obseg - Izogibanje barvnega pomika +HISTORY_MSG_323;W - ES - Lokalni kontrast +HISTORY_MSG_324;W - Barvitost - Pastel +HISTORY_MSG_325;W - Barvitost - Nasičenje +HISTORY_MSG_326;W - Barvitost - Metoda +HISTORY_MSG_327;W - Kontrast - Uporabi za +HISTORY_MSG_328;W - Barvitost - Moč povezave +HISTORY_MSG_329;W - Toniranje - Neprosojnost RG +HISTORY_MSG_330;W - Toniranje - Neprosojnost BY +HISTORY_MSG_331;W - Nivoji kontrastov - Ekstra +HISTORY_MSG_332;W - Metoda prekrivanja +HISTORY_MSG_333;W - Residual - Sence +HISTORY_MSG_334;W - Residual - Barvitost +HISTORY_MSG_335;W - Residual - Bleščave +HISTORY_MSG_336;W - Residual - Prag bleščav +HISTORY_MSG_337;W - Residual - Odtenek neba +HISTORY_MSG_338;W - ES - Radij +HISTORY_MSG_339;W - ES - Moč +HISTORY_MSG_340;W - Moč +HISTORY_MSG_341;W - Izvedba robov +HISTORY_MSG_342;W - ES - Prvi nivo +HISTORY_MSG_343;W - Nivoji barvitosti +HISTORY_MSG_344;W - Metoda barvitost sl/cur +HISTORY_MSG_345;W - ES - Lokalni kontrast +HISTORY_MSG_346;W - ES - Metoda lokalnega kontrasta +HISTORY_MSG_347;W - Odstranjevanje šuma - Nivo 1 +HISTORY_MSG_348;W - Odstranjevanje šuma - Nivo 2 +HISTORY_MSG_349;W - Odstranjevanje šuma - Nivo 3 +HISTORY_MSG_350;W - ES - Detekcija roba +HISTORY_MSG_351;W - Residual - HH krivulja +HISTORY_MSG_352;W - Ozadje +HISTORY_MSG_353;W - ES - Občutljivost gradienta +HISTORY_MSG_354;W - ES - Izboljšan +HISTORY_MSG_355;W - ES - Nizki prag +HISTORY_MSG_356;W - ES - Visoki prag +HISTORY_MSG_357;W - Odstrani šum - Povezava z ES +HISTORY_MSG_358;W - Barvni obseg - CH +HISTORY_MSG_359;Vroč/Mrtev - Prag +HISTORY_MSG_360;TM - Gama +HISTORY_MSG_361;W - Končno - uravnoteženje barvitosti +HISTORY_MSG_362;W - Residual - Metoda stiskanja +HISTORY_MSG_363;W - Residual - Moč stiskanja +HISTORY_MSG_364;W - Končno - Uravnoteženost kontrasta +HISTORY_MSG_365;W - Končno - Delta uravnoteženje +HISTORY_MSG_366;W - Residual - Stiskanje game +HISTORY_MSG_367;W - Končno - Krivulja kontrastov 'Po' +HISTORY_MSG_368;W - Končno - Uravnoteženje kontrastov +HISTORY_MSG_369;W - Končno - Metoda uravnoteženja +HISTORY_MSG_370;W - Končno - Krivulja lokalnega kontrasta +HISTORY_MSG_371;Post-Resize Ostrenje +HISTORY_MSG_372;PRS USM - Radij +HISTORY_MSG_373;PRS USM - Količina +HISTORY_MSG_374;PRS USM - Prag +HISTORY_MSG_375;PRS USM - Naostri samo robove +HISTORY_MSG_376;PRS USM - Radij detekcije roba +HISTORY_MSG_377;PRS USM - Toleranca roba +HISTORY_MSG_378;PRS USM - Kontrola haloja +HISTORY_MSG_379;PRS USM - Količina kontrole haloja +HISTORY_MSG_380;PRS - Metoda +HISTORY_MSG_381;PRS RLD - Radij +HISTORY_MSG_382;PRS RLD - Količina +HISTORY_MSG_383;PRS RLD - Dušenje +HISTORY_MSG_384;PRS RLD - Iteracij +HISTORY_MSG_385;W - Residual - Uravnoteženost barv +HISTORY_MSG_386;W - Residual - CB močne zelene +HISTORY_MSG_387;W - Residual - CB močne modre +HISTORY_MSG_388;W - Residual - CB srednje zelene +HISTORY_MSG_389;W - Residual - CB srednje modre +HISTORY_MSG_390;W - Residual - CB šibke zelene +HISTORY_MSG_391;W - Residual - CB šibke modre +HISTORY_MSG_392;W - Residual - Uravnoteženost barv +HISTORY_MSG_393;DCP - Iskalna tabela +HISTORY_MSG_394;DCP - Osnovna ekspozicija +HISTORY_MSG_395;DCP - Osnovna tabela +HISTORY_MSG_396;W - pod-orodje kontrasta +HISTORY_MSG_397;W - Pod-orodje barvitosti +HISTORY_MSG_398;W - ES sub-tool +HISTORY_MSG_399;W - Residual sub-tool +HISTORY_MSG_400;W - Končno sub-tool +HISTORY_MSG_401;W - Pod-orodje toniranja +HISTORY_MSG_402;W - Pod-orodje odstranjevanja šuma +HISTORY_MSG_403;W - ES - Občutljivost na robove +HISTORY_MSG_404;W - ES - Ojačevanje osnove +HISTORY_MSG_405;W - Odstranjevanje šuma - Nivo 4 +HISTORY_MSG_406;W - ES - Sosednji piksli +HISTORY_MSG_407;Retinex - Metoda +HISTORY_MSG_408;Retinex - Radij +HISTORY_MSG_409;Retinex - Kontrast +HISTORY_MSG_410;Retinex - Odmik +HISTORY_MSG_411;Retinex - Moč +HISTORY_MSG_412;Retinex - Gaussov gradient +HISTORY_MSG_413;Retinex - Kontrast +HISTORY_MSG_414;Retinex - Histogram - Lab +HISTORY_MSG_415;Retinex - Prenos +HISTORY_MSG_416;Retinex +HISTORY_MSG_417;Retinex - Mediana prenosa +HISTORY_MSG_418;Retinex - Prag +HISTORY_MSG_419;Retinex - Barvni prostor +HISTORY_MSG_420;Retinex - Histogram - HSL +HISTORY_MSG_421;Retinex - Gama +HISTORY_MSG_422;Retinex - Gama +HISTORY_MSG_423;Retinex - Gama strmina +HISTORY_MSG_424;Retinex - HL prag +HISTORY_MSG_425;Retinex - Log base +HISTORY_MSG_426;Retinex - Ekvalizator odtenkov +HISTORY_MSG_427;Namen izrisovanja izhoda +HISTORY_MSG_428;Namen izrisovanja zaslona +HISTORY_MSG_429;Retinex - Iteracij +HISTORY_MSG_430;Retinex - Gradient prenosa +HISTORY_MSG_431;Retinex - Moč gradienta +HISTORY_MSG_432;Retinex - M - Bleščave +HISTORY_MSG_433;Retinex - M - Bleščave TW +HISTORY_MSG_434;Retinex - M - Sence +HISTORY_MSG_435;Retinex - M - Sence TW +HISTORY_MSG_436;Retinex - M - Radij +HISTORY_MSG_437;Retinex - M - Metoda +HISTORY_MSG_438;Retinex - M - Ekvalizator +HISTORY_MSG_439;Retinex - Obdelava +HISTORY_MSG_440;CbDL - Metoda +HISTORY_MSG_441;Retinex - Prenos povečanja +HISTORY_MSG_442;Retinex - Merilo +HISTORY_MSG_443;Prilagoditev črne točke izhoda +HISTORY_MSG_444;WB - Začasna pristranost +HISTORY_MSG_445;Raw sub-image +HISTORY_MSG_449;PS - prilagoditev ISO +HISTORY_MSG_452;PS - Prikaži gibanje +HISTORY_MSG_453;PS - Prikaži samo masko +HISTORY_MSG_457;PS - Preveri redečo/modro +HISTORY_MSG_462;PS - Preveri zeleno +HISTORY_MSG_464;PS - Zamegli masko gibanja +HISTORY_MSG_465;PS - Zamegli radij +HISTORY_MSG_468;PS - Zapolni luknje +HISTORY_MSG_469;PS - Mediana +HISTORY_MSG_471;PS - Popravek gibanja +HISTORY_MSG_472;PS - Gladki prehodi +HISTORY_MSG_473;PS - Uporabi LMMSE +HISTORY_MSG_474;PS - Izenači +HISTORY_MSG_475;PS - Izenači kanal +HISTORY_MSG_476;CAM02 - Začasno ven +HISTORY_MSG_477;CAM02 - Zeleno ven +HISTORY_MSG_478;CAM02 - Yb ven +HISTORY_MSG_479;CAM02 - CAT02 prilagoditev ven +HISTORY_MSG_480;CAM02 - Avtomatska CAT02 ven +HISTORY_MSG_481;CAM02 - Začasna scena +HISTORY_MSG_482;CAM02 - Zelena scena +HISTORY_MSG_483;CAM02 - Yb scena +HISTORY_MSG_484;CAM02 - Avto Yb scena +HISTORY_MSG_485;Popravek objektiva +HISTORY_MSG_486;Popravek objektiva - Fotoaparat +HISTORY_MSG_487;Popravek objektiva - Objektiv +HISTORY_MSG_488;Zmanjšanje dinamičnega obsega +HISTORY_MSG_489;DRC - Podrobnost +HISTORY_MSG_490;DRC - Količina +HISTORY_MSG_491;Ravnotežje beline +HISTORY_MSG_492;RGB krivulje +HISTORY_MSG_493;L*a*b* prilagoditve +HISTORY_MSG_494;Ujemite ostrenje +HISTORY_MSG_CLAMPOOG;Izrežite barve izven obsega +HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Popravek barv +HISTORY_MSG_COLORTONING_LABREGION_AB;CT - Popravek barv +HISTORY_MSG_COLORTONING_LABREGION_CHANNEL;CT - Kanal +HISTORY_MSG_COLORTONING_LABREGION_CHROMATICITYMASK;CT - maska regije C +HISTORY_MSG_COLORTONING_LABREGION_HUEMASK;CT - H maska +HISTORY_MSG_COLORTONING_LABREGION_LIGHTNESS;CT - Svetlost +HISTORY_MSG_COLORTONING_LABREGION_LIGHTNESSMASK;CT - L maska +HISTORY_MSG_COLORTONING_LABREGION_LIST;CT - Seznam +HISTORY_MSG_COLORTONING_LABREGION_MASKBLUR;CT - zamegljevanje regijske maske +HISTORY_MSG_COLORTONING_LABREGION_OFFSET;CT - odmik regije +HISTORY_MSG_COLORTONING_LABREGION_POWER;CT - moč regije +HISTORY_MSG_COLORTONING_LABREGION_SATURATION;CT - Nasičenost +HISTORY_MSG_COLORTONING_LABREGION_SHOWMASK;CT - prikaz maske regije +HISTORY_MSG_COLORTONING_LABREGION_SLOPE;CT - strmina regije +HISTORY_MSG_DEHAZE_DEPTH;Odstranjevanje zamegljenosti - Globina +HISTORY_MSG_DEHAZE_ENABLED;Odstranjevanje zamegljenosti +HISTORY_MSG_DEHAZE_LUMINANCE;Odstranjevanje zamegljenosti - samo svetlost +HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;Odstranjevanje zamegljenosti - Prikaži globino mape +HISTORY_MSG_DEHAZE_STRENGTH;Odstranjevanje zamegljenosti - Moč +HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dualno odstranjevanje mozaičnosti - Avtomatski prag +HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dualno odstranjevanje mozaičnosti - Prag kontrasta +HISTORY_MSG_FILMNEGATIVE_ENABLED;Filmski negativ +HISTORY_MSG_FILMNEGATIVE_VALUES;Film negativne vrednosti +HISTORY_MSG_HISTMATCHING;Avto-usklajena krivulja tonov +HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries +HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 osvetljevalnik D +HISTORY_MSG_ICM_OUTPUT_TYPE;Output - Tip +HISTORY_MSG_ICM_WORKING_GAMMA;Delovanje - Gama +HISTORY_MSG_ICM_WORKING_SLOPE;Delovanje - Strmina +HISTORY_MSG_ICM_WORKING_TRC_METHOD;Delovanje - Metoda TRC +HISTORY_MSG_LOCALCONTRAST_AMOUNT;Lokalni kontrast - Količina +HISTORY_MSG_LOCALCONTRAST_DARKNESS;Lokalni kontrast - Temina +HISTORY_MSG_LOCALCONTRAST_ENABLED;Lokalni kontrast +HISTORY_MSG_LOCALCONTRAST_LIGHTNESS;Lokalni kontrast - Svetlost +HISTORY_MSG_LOCALCONTRAST_RADIUS;Lokalni kontrast - Radij +HISTORY_MSG_METADATA_MODE;Način kopiranja metapodatkov +HISTORY_MSG_MICROCONTRAST_CONTRAST;Mikrokontrast - Prag kontrasta +HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Avtomatski prag +HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Avtomatski radij +HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Prag kontrasta +HISTORY_MSG_PDSHARPEN_GAMMA;CS - Gama +HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iteracije +HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radij +HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - Povečanje polmera vogala +HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - metoda odstranjevanje mozaičnosti za gibanje +HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Smer linijskega filtra šuma +HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF linijski filter +HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Prag kontrasta +HISTORY_MSG_RAWCACORR_AUTOIT;Surovi CA popravek - Iteracije +HISTORY_MSG_RAWCACORR_COLORSHIFT;Surovi CA popravek - Izogibanje pomika barv +HISTORY_MSG_RAW_BORDER;Surova meja +HISTORY_MSG_RESIZE_ALLOWUPSCALING;Resize - Dovoli povečevanje +HISTORY_MSG_SHARPENING_BLUR;Ostrenje - Zamegli radij +HISTORY_MSG_SHARPENING_CONTRAST;Ostrenje - Prag kontrasta +HISTORY_MSG_SHARPENING_GAMMA;Ostrenje - Gama +HISTORY_MSG_SH_COLORSPACE;S/H - Barvni prostor +HISTORY_MSG_SOFTLIGHT_ENABLED;Mehka svetloba +HISTORY_MSG_SOFTLIGHT_STRENGTH;Mehka svetloba - Moč +HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Sidro +HISTORY_NEWSNAPSHOT;Dodaj +HISTORY_NEWSNAPSHOT_TOOLTIP;Bližnjica: Alt-s +HISTORY_SNAPSHOT;Posnetek +HISTORY_SNAPSHOTS;Posnetek +ICCPROFCREATOR_COPYRIGHT;Copyright: +ICCPROFCREATOR_COPYRIGHT_RESET_TOOLTIP;Ponastavi na privzeti copyright, dodeljen "RawTherapee, CC0" +ICCPROFCREATOR_CUSTOM;Po meri +ICCPROFCREATOR_DESCRIPTION;Opis: +ICCPROFCREATOR_DESCRIPTION_ADDPARAM;Dodaj vrednosti game and strmine k opisu +ICCPROFCREATOR_DESCRIPTION_TOOLTIP;Pusti prazno in nastavi privzeti opis. +ICCPROFCREATOR_GAMMA;Gama +ICCPROFCREATOR_ICCVERSION;ICC verzija: +ICCPROFCREATOR_ILL;Illuminant: +ICCPROFCREATOR_ILL_41;D41 +ICCPROFCREATOR_ILL_50;D50 +ICCPROFCREATOR_ILL_55;D55 +ICCPROFCREATOR_ILL_60;D60 +ICCPROFCREATOR_ILL_65;D65 +ICCPROFCREATOR_ILL_80;D80 +ICCPROFCREATOR_ILL_DEF;Privzeto +ICCPROFCREATOR_ILL_INC;StdA 2856K +ICCPROFCREATOR_ILL_TOOLTIP;Nastaviš lahko samo svetlobe iz profilov ICC v4. +ICCPROFCREATOR_PRIMARIES;Primaries: +ICCPROFCREATOR_PRIM_ACESP0;ACES AP0 +ICCPROFCREATOR_PRIM_ACESP1;ACES AP1 +ICCPROFCREATOR_PRIM_ADOBE;Adobe RGB (1998) +ICCPROFCREATOR_PRIM_BEST;BestRGB +ICCPROFCREATOR_PRIM_BETA;BetaRGB +ICCPROFCREATOR_PRIM_BLUX;Blue X +ICCPROFCREATOR_PRIM_BLUY;Blue Y +ICCPROFCREATOR_PRIM_BRUCE;BruceRGB +ICCPROFCREATOR_PRIM_GREX;Green X +ICCPROFCREATOR_PRIM_GREY;Green Y +ICCPROFCREATOR_PRIM_PROPH;Prophoto +ICCPROFCREATOR_PRIM_REC2020;Rec2020 +ICCPROFCREATOR_PRIM_REDX;Red X +ICCPROFCREATOR_PRIM_REDY;Red Y +ICCPROFCREATOR_PRIM_SRGB;sRGB +ICCPROFCREATOR_PRIM_TOOLTIP;Primarne prilagojene vrednosti lahko nastavite samo za profile ICC v4. +ICCPROFCREATOR_PRIM_WIDEG;Široki barvni prostor +ICCPROFCREATOR_PROF_V2;ICC v2 +ICCPROFCREATOR_PROF_V4;ICC v4 +ICCPROFCREATOR_SAVEDIALOG_TITLE;Shrani ICC profil kot... +ICCPROFCREATOR_SLOPE;Strmina +ICCPROFCREATOR_TRC_PRESET;Krivulja odzivnosti tonov: +IPTCPANEL_CATEGORY;Kategorija +IPTCPANEL_CATEGORYHINT;Določa temo slike po mnenju punudnika. +IPTCPANEL_CITY;Mesto +IPTCPANEL_CITYHINT;Vnesi ime mesta na tej sliki. +IPTCPANEL_COPYHINT;Kopiraj nastavitve IPTC na odložišče. +IPTCPANEL_COPYRIGHT;Obvestilo copyrighta +IPTCPANEL_COPYRIGHTHINT;Vnesi določilo trenutnega nosilca Copyrighta te slike kot npr. ©2019 Janez Novak. +IPTCPANEL_COUNTRY;Država +IPTCPANEL_COUNTRYHINT;Vnesi ime države na tej sliki. +IPTCPANEL_CREATOR;Avtor +IPTCPANEL_CREATORHINT;Vnesi ime avtorja te slike. +IPTCPANEL_CREATORJOBTITLE;Uradni naziv avtorja +IPTCPANEL_CREATORJOBTITLEHINT;Vnesi službeni naziv avtorja te slike, ki je zabeležen v polju avtorja. +IPTCPANEL_CREDIT;Zasluge +IPTCPANEL_CREDITHINT;Vnesi osebo zaslužno za objavo te slike. +IPTCPANEL_DATECREATED;Datum nastanka +IPTCPANEL_DATECREATEDHINT;Vnesi datum, ko je bila slika posneta. +IPTCPANEL_DESCRIPTION;Opis +IPTCPANEL_DESCRIPTIONHINT;Vnesi naslov, ki opisuje kdo, kaj in zakaj to dogaja na tej sliki, kar vključuje imena oseb in njihove vloge pri tem, kar se dogaja na sliki. +IPTCPANEL_DESCRIPTIONWRITER;Zapisnikar opisa +IPTCPANEL_DESCRIPTIONWRITERHINT;Vnesi ime osebe, ki je napisala, uredila ali popravila opis slike. +IPTCPANEL_EMBEDDED;Vdelano +IPTCPANEL_EMBEDDEDHINT;Nastavi nazaj na podatke IPTC, ki so vdelani v datoteki slike. +IPTCPANEL_HEADLINE;Naslov +IPTCPANEL_HEADLINEHINT;Vnesi kratek objavljiv opis vsebine te slike. +IPTCPANEL_INSTRUCTIONS;Navodila +IPTCPANEL_INSTRUCTIONSHINT;Vnesi informacije o morebitnem embargu ali drugih omejitvah, ki niso omenjene v polju Copyright. +IPTCPANEL_KEYWORDS;Ključne besede +IPTCPANEL_KEYWORDSHINT;Vstavi poljubno število terminov ali fraz, ki opisujejo vsebino slike. +IPTCPANEL_PASTEHINT;Prilepi nastavitve IPTC iz odložišča. +IPTCPANEL_PROVINCE;Provinca ali država +IPTCPANEL_PROVINCEHINT;Vnesi ime province ali države v povezavi s to sliko. +IPTCPANEL_RESET;Ponastavi +IPTCPANEL_RESETHINT;Ponastavi na privzeti profil +IPTCPANEL_SOURCE;Vir +IPTCPANEL_SOURCEHINT;Vnesi ali uredi ime osebe ali skupine, ki je imela vlogo pri dobavi slike kot npr. oseba od katere si dobil sliko. +IPTCPANEL_SUPPCATEGORIES;Dodatki kategorije +IPTCPANEL_SUPPCATEGORIESHINT;Podrobneje določa vsebino slike. +IPTCPANEL_TITLE;Naslov +IPTCPANEL_TITLEHINT;Vnesi kratko človeku prijazno ime slike, lahko je tudi ime datoteke. +IPTCPANEL_TRANSREFERENCE;ID delovnega mesta +IPTCPANEL_TRANSREFERENCEHINT;Vnesite številko ali identifikator za delovnega toka ali omogočanje sledenja. +MAIN_BUTTON_FULLSCREEN;Celotni zaslon +MAIN_BUTTON_ICCPROFCREATOR;Ustvarjalec ICC profila +MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigacija do naslednje slike odprte v urejevalniku.\nBližnjica: Shift-F4\n\nNavigacija do naslednje slike glede na trenutno izbrano predogledno sličico v brskalniku datotek:\nBližnjica: F4 +MAIN_BUTTON_NAVPREV_TOOLTIP;Navigacija do prejšnje slike odprte v urejevalniku.\nBližnjica: Shift-F3\n\nNavigacija do prejšnje slike glede na trenutno izbrano predogledno sličico v brskalniku datotek:\nBližnjica: F3 +MAIN_BUTTON_NAVSYNC_TOOLTIP;Sinhroniziraj pregledovalnik datotek z urejevalnikom, tako da se vidi predogledna sličica trenutno odprte slike in deaktivira aktivne filtre.\nBližnjica: x\n\nKot zgoraj, a brez deaktivranja filtrov:\nBližnjica: y\n(Zavedajte se predogledna sličica odprte slike ne bo pokazana, če je sfiltrirana). +MAIN_BUTTON_PREFERENCES;Preference +MAIN_BUTTON_PUTTOQUEUE_TOOLTIP;Postavi trenutno sliko v čakalno vrsto za obdelavo.\nBližnjica: Ctrl+b +MAIN_BUTTON_SAVE_TOOLTIP;Shrani trenutno sliko.\nBližnjica: Ctrl+s\nShrani trenutni profil (.pp3).\nBližnjica: Ctrl+Shift+s +MAIN_BUTTON_SENDTOEDITOR;Uredi sliko v zunanjem urejevalniku +MAIN_BUTTON_SENDTOEDITOR_TOOLTIP;Uredi sliko v zunanjem urejevalniku.\nBližnjica: Ctrl+e +MAIN_BUTTON_SHOWHIDESIDEPANELS_TOOLTIP;Prikaži/skrij stranske panele.\nBližnjica: m +MAIN_BUTTON_UNFULLSCREEN;Izhod iz celotnega zaslona +MAIN_FRAME_EDITOR;Urejevalnik +MAIN_FRAME_EDITOR_TOOLTIP;Urejevalnik.\nBližnjica: Ctrl-F4 +MAIN_FRAME_FILEBROWSER;Prikazovalnik datotek +MAIN_FRAME_FILEBROWSER_TOOLTIP;Prikazovalnik datotek.\nBližnjica: Ctrl-F2 +MAIN_FRAME_PLACES;Lokacije slik +MAIN_FRAME_PLACES_ADD;Dodaj +MAIN_FRAME_PLACES_DEL;Odstrani +MAIN_FRAME_QUEUE;Čakalna vrsta +MAIN_FRAME_QUEUE_TOOLTIP;Čakalna vrsta obdelav.\nBližnjica: Ctrl-F3 +MAIN_FRAME_RECENT;Zadnje uporabljene mape +MAIN_MSG_ALREADYEXISTS;Datoteka že obstaja. +MAIN_MSG_CANNOTLOAD;Ne morem naložiti slike +MAIN_MSG_CANNOTSAVE;Napaka pri shranjevanju datoteke +MAIN_MSG_CANNOTSTARTEDITOR;Ne morem zagnati urejevalnika. +MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY;Prosim nastavi ustrezno pot v preferencah. +MAIN_MSG_EMPTYFILENAME;Datoteka ni določena! +MAIN_MSG_IMAGEUNPROCESSED;Ta ukaz zahteva, da so vse slike najprej obdelane v čakalni vrsti. +MAIN_MSG_NAVIGATOR;Navigator +MAIN_MSG_OPERATIONCANCELLED;Operacija preklicana +MAIN_MSG_PATHDOESNTEXIST;Pot\n\n%1\n\nne obstaja. Prosim postavi pravilno pot v preferencah. +MAIN_MSG_QOVERWRITE;Ali jo želiš prepisati? +MAIN_MSG_SETPATHFIRST;Najprej moraš nastaviti pot v preferencah za uporabo te funkcije! +MAIN_MSG_TOOMANYOPENEDITORS;Preveč odprtih urejevalnikov.\nZa nadaljevanje dela prosim zapri urejevalnik. +MAIN_MSG_WRITEFAILED;Izpad pri pisanju\n"%1"\n\nPreveri, da mapa obstaja in da imaš pravico pisanja v njej. +MAIN_TAB_ADVANCED;Napredno +MAIN_TAB_ADVANCED_TOOLTIP;Bližnjica: Alt-w +MAIN_TAB_COLOR;Barva +MAIN_TAB_COLOR_TOOLTIP;Bližnjica: Alt-c +MAIN_TAB_DETAIL;Podrobnost +MAIN_TAB_DETAIL_TOOLTIP;Bližnjica: Alt-d +MAIN_TAB_DEVELOP; Paketno urejanje +MAIN_TAB_EXIF;Exif +MAIN_TAB_EXPORT; Hitri izvoz +MAIN_TAB_EXPOSURE;Ekspozicija +MAIN_TAB_EXPOSURE_TOOLTIP;Bližnjica: Alt-e +MAIN_TAB_FAVORITES;Priljubljene +MAIN_TAB_FAVORITES_TOOLTIP;Bližnjica: Alt-u +MAIN_TAB_FILTER; Filter +MAIN_TAB_INSPECT; Pregled +MAIN_TAB_IPTC;IPTC +MAIN_TAB_METADATA;Metapodatki +MAIN_TAB_METADATA_TOOLTIP;Bližnjica: Alt-m +MAIN_TAB_RAW;Surove +MAIN_TAB_RAW_TOOLTIP;Bližnjica: Alt-r +MAIN_TAB_TRANSFORM;Transformiraj +MAIN_TAB_TRANSFORM_TOOLTIP;Bližnjica: Alt-t +MAIN_TOOLTIP_BACKCOLOR0;Barva ozadja predpregleda: theme-based\nBližnjica: 9 +MAIN_TOOLTIP_BACKCOLOR1;Barva ozadja predpregleda: črna\nBližnjica: 9 +MAIN_TOOLTIP_BACKCOLOR2;Barva ozadja predpregleda: bela\nBližnjica: 9 +MAIN_TOOLTIP_BACKCOLOR3;Barva ozadja predpregleda: srednje siva\nBližnjica: 9 +MAIN_TOOLTIP_BEFOREAFTERLOCK;Zakleni / Odkleni the Pred pogled\n\nZakleni: ohranjaj pogled Pred nespremenjen.\nUporabno za oceno skupnega učinka več orodij.\nPoleg tega je mogoče opraviti primerjave s katerim koli stanjem v zgodovini.\n\nOdkleni: Pred prikaz bo sledil pogledu Po z enim korakom zamude, prikazuje sliko pred učinkom zadnje uporabljenega orodja. +MAIN_TOOLTIP_HIDEHP;Prikaži/skrij levo ploščo (vključno z zgodovino).\nBližnjica: l +MAIN_TOOLTIP_INDCLIPPEDH;Obrezana oznaka osvetlitve.\nBližnjica: < +MAIN_TOOLTIP_INDCLIPPEDS;Obrezana oznaka senc.\nBližnjica: > +MAIN_TOOLTIP_PREVIEWB;Predogled modrega kanala.\nBližnjica: b +MAIN_TOOLTIP_PREVIEWFOCUSMASK;Predogled maske ostrenja.\nBližnjica: Shift-f \n\nBolj natančne pri slikah z majhno globinsko ostrino, nizkim šumom in višjo stopnjo povečave.\nZa povečavo 10-30% za izboljšanje natančnosti odkrivanja šumnih slik. +MAIN_TOOLTIP_PREVIEWG;Predogled zelenega kanala.\nBližnjica: g +MAIN_TOOLTIP_PREVIEWL;Predogled osvetljenosti.\nBližnjica: v\n\n0.299*R + 0.587*G + 0.114*B +MAIN_TOOLTIP_PREVIEWR;Predogled rdečega kanala.\nBližnjica: r +MAIN_TOOLTIP_PREVIEWSHARPMASK;Predogled maske ostrinskega kontrasta.\nBližnjica: p\n\nDeluje samo, kadar je omogočeno ostrenje in zoom >= 100%. +MAIN_TOOLTIP_QINFO;Hitre informacije o sliki.\nBližnjica: i +MAIN_TOOLTIP_SHOWHIDELP1;Prikaži/skrij levi panel.\nBližnjica: l +MAIN_TOOLTIP_SHOWHIDERP1;Prikaži/skrij desni panel.\nBližnjica: Alt-l +MAIN_TOOLTIP_SHOWHIDETP1;Prikaži/skrij vrhnji panel.\nBližnjica: Shift-l +MAIN_TOOLTIP_THRESHOLD;Prag +MAIN_TOOLTIP_TOGGLE;Preklopi pogled Pred/Po.\nBližnjica: Shift-b +MONITOR_PROFILE_SYSTEM;Sistemska privzeta vrednost +NAVIGATOR_B;B: +NAVIGATOR_G;G: +NAVIGATOR_H;H: +NAVIGATOR_LAB_A;a*: +NAVIGATOR_LAB_B;b*: +NAVIGATOR_LAB_L;L*: +NAVIGATOR_NA; -- +NAVIGATOR_R;R: +NAVIGATOR_S;S: +NAVIGATOR_V;V: +NAVIGATOR_XY_FULL;Širina: %1, Višina: %2 +NAVIGATOR_XY_NA;x: --, y: -- +OPTIONS_BUNDLED_MISSING;Že pripravljenih profilov "%1" ne morem najti!\n\nVaša namestitev je morda poškodovana.\n\nUporabljene bodo privzete programske vrednosti. +OPTIONS_DEFIMG_MISSING;Privzetega profila za ne-surove fotografije ne morem najti ali ni nastavljen.\n\nProsim preverite vašo mapo profilov, morda manjka ali je poškodovan.\n\n"%1" bo uporabljena kot nadomestek. +OPTIONS_DEFRAW_MISSING;Privzetega profila za surove fotografije ne morem najti ali ni nastavljen.\n\nProsim preverite vašo mapo profilov, morda manjka ali je poškodovan.\n\n"%1" bo uporabljena kot nadomestek. +PARTIALPASTE_ADVANCEDGROUP;Napredne nastavitve +PARTIALPASTE_BASICGROUP;Osnovne nastavitve +PARTIALPASTE_CACORRECTION;Popravek barvne aberacije +PARTIALPASTE_CHANNELMIXER;Mešalnik kanalov +PARTIALPASTE_CHANNELMIXERBW;Črno-belo +PARTIALPASTE_COARSETRANS;Groba rotacija/preklop +PARTIALPASTE_COLORAPP;CIECAM02 +PARTIALPASTE_COLORGROUP;Nastavitev barv +PARTIALPASTE_COLORTONING;Toniranje barv +PARTIALPASTE_COMMONTRANSFORMPARAMS;Avto-polnjenje +PARTIALPASTE_COMPOSITIONGROUP;Nastavitev kompozicije +PARTIALPASTE_CROP;Obreži +PARTIALPASTE_DARKFRAMEAUTOSELECT;Avtomatska izbira dark-frame +PARTIALPASTE_DARKFRAMEFILE;Datoteke dark-frame +PARTIALPASTE_DEFRINGE;Odstranjevanje barvnih napak robov +PARTIALPASTE_DEHAZE;Odstranjevanje motnosti +PARTIALPASTE_DETAILGROUP;Nastavitve podrobnosti +PARTIALPASTE_DIALOGLABEL;Profil obdelovanja delnega lepljenja +PARTIALPASTE_DIRPYRDENOISE;Zmanjšanje šumov +PARTIALPASTE_DIRPYREQUALIZER;Kontrast po nivojih podrobnosti +PARTIALPASTE_DISTORTION;Popravljanje popačenosti +PARTIALPASTE_EPD;Preslikava odtenkov +PARTIALPASTE_EQUALIZER;Nivoji valovčkov +PARTIALPASTE_EVERYTHING;Vse +PARTIALPASTE_EXIFCHANGES;Exif +PARTIALPASTE_EXPOSURE;Ekspozicija +PARTIALPASTE_FILMNEGATIVE;Filmski negativ +PARTIALPASTE_FILMSIMULATION;Simulacija filma +PARTIALPASTE_FLATFIELDAUTOSELECT;Flat-field avtomatski izbor +PARTIALPASTE_FLATFIELDBLURRADIUS;Flat-field radij zamegljenosti +PARTIALPASTE_FLATFIELDBLURTYPE;Flat-field vrsta zameglitve +PARTIALPASTE_FLATFIELDCLIPCONTROL;Flat-field nadzor obrezave +PARTIALPASTE_FLATFIELDFILE;Datoteka flat-field +PARTIALPASTE_GRADIENT;Postopni filter +PARTIALPASTE_HSVEQUALIZER;HSV ekvalizator +PARTIALPASTE_ICMSETTINGS;Nastavitve upravljanja barv +PARTIALPASTE_IMPULSEDENOISE;Impuzno zmanjšanje šuma +PARTIALPASTE_IPTCINFO;IPTC +PARTIALPASTE_LABCURVE;L*a*b* prilagoditve +PARTIALPASTE_LENSGROUP;Nastavitve objektiva +PARTIALPASTE_LENSPROFILE;Popravki objektiva iz njegovega profila +PARTIALPASTE_LOCALCONTRAST;Lokalni kontrast +PARTIALPASTE_METADATA;Način metapodatkov +PARTIALPASTE_METAGROUP;Nastavitve metapodatkov +PARTIALPASTE_PCVIGNETTE;Filter vinjetiranja +PARTIALPASTE_PERSPECTIVE;Perspektiva +PARTIALPASTE_PREPROCESS_DEADPIXFILT;Filter mrtvih pikslov +PARTIALPASTE_PREPROCESS_GREENEQUIL;Uravnoteženje zelene +PARTIALPASTE_PREPROCESS_HOTPIXFILT;Filter vročih pikslov +PARTIALPASTE_PREPROCESS_LINEDENOISE;Filter šuma na črti +PARTIALPASTE_PREPROCESS_PDAFLINESFILTER;Filter linij PDAF +PARTIALPASTE_PRSHARPENING;Ostrenje po spremembi velikosti +PARTIALPASTE_RAWCACORR_AUTO;CA avtomatski popravek +PARTIALPASTE_RAWCACORR_AVOIDCOLORSHIFT;CA izogibaj se pomiku barve +PARTIALPASTE_RAWCACORR_CAREDBLUE;CA rdeča & modra +PARTIALPASTE_RAWEXPOS_BLACK;Nivoji črne +PARTIALPASTE_RAWEXPOS_LINEAR;Popravek bele točke +PARTIALPASTE_RAWGROUP;Nastavitve za surove +PARTIALPASTE_RAW_BORDER;Surova meja +PARTIALPASTE_RAW_DCBENHANCE;DCB izboljšava +PARTIALPASTE_RAW_DCBITERATIONS;DCB iteracije +PARTIALPASTE_RAW_DMETHOD;Metoda odstranjevanja mozaičnosti +PARTIALPASTE_RAW_FALSECOLOR;Zatiranje napačne barve +PARTIALPASTE_RAW_IMAGENUM;Sub-image +PARTIALPASTE_RAW_LMMSEITERATIONS;LMMSE koraki izboljšave +PARTIALPASTE_RAW_PIXELSHIFT;Pomik pikslov +PARTIALPASTE_RESIZE;Sprememba velikosti +PARTIALPASTE_RETINEX;Retinex +PARTIALPASTE_RGBCURVES;Krivulje RGB +PARTIALPASTE_ROTATION;Rotacija +PARTIALPASTE_SHADOWSHIGHLIGHTS;Sence/bleščave +PARTIALPASTE_SHARPENEDGE;Robovi +PARTIALPASTE_SHARPENING;Ostrenje (USM/RL) +PARTIALPASTE_SHARPENMICRO;Mikrokontrast +PARTIALPASTE_SOFTLIGHT;Mehka svetloba +PARTIALPASTE_TM_FATTAL;Stiskanje dinamičnega obsega +PARTIALPASTE_VIBRANCE;Vibrance +PARTIALPASTE_VIGNETTING;Popravi vinjetiranja +PARTIALPASTE_WHITEBALANCE;Uravnoteženje beline +PREFERENCES_ADD;Dodaj +PREFERENCES_APPEARANCE;Izgled +PREFERENCES_APPEARANCE_COLORPICKERFONT;Pisava izbire barv +PREFERENCES_APPEARANCE_CROPMASKCOLOR;Barve maske obrezovanja +PREFERENCES_APPEARANCE_MAINFONT;Glavna pisava +PREFERENCES_APPEARANCE_NAVGUIDECOLOR;Glavna barva navigacije +PREFERENCES_APPEARANCE_PSEUDOHIDPI;Psevdo način HiDPI +PREFERENCES_APPEARANCE_THEME;Tema +PREFERENCES_APPLNEXTSTARTUP;potreben ponovni zagon +PREFERENCES_AUTOMONPROFILE;Uporabi profil glavnega monitorja iz operacijskega sistema +PREFERENCES_AUTOSAVE_TP_OPEN;Ob ihodu shrani orodje zloženo/razširjeno +PREFERENCES_BATCH_PROCESSING;Paketna obdelava +PREFERENCES_BEHADDALL;Vse na 'Dodaj' +PREFERENCES_BEHADDALLHINT;Nastavi vse pramaetre na način dodajanja.\nPrilagoditve prametrov v kontrolni plošči paketa bodo spremembe glede na shranjene vrednosti. +PREFERENCES_BEHAVIOR;Obnašanje +PREFERENCES_BEHSETALL;Vse na 'Nastavi' +PREFERENCES_BEHSETALLHINT;Postavi vse parametre v način Nastavi.\nPrilagoditve parametrov v kontrolni plošči paketnega orodja bo absolutno, prikazane bodo dejanske vrednosti. +PREFERENCES_CACHECLEAR;Počisti +PREFERENCES_CACHECLEAR_ALL;Počisti vse datoteke v vmesnem pomnilniku: +PREFERENCES_CACHECLEAR_ALLBUTPROFILES;Očisti vse datoteke iz vmesnega pomnilnika razen profilov obdelav: +PREFERENCES_CACHECLEAR_ONLYPROFILES;Očisti datoteke profilov obdelav iz vmesnega ponilnika: +PREFERENCES_CACHECLEAR_SAFETY;Očiščene samo datoteke v vmesnem pomnilniku. Profili obdelav, ki sodijo k slikam, so nedotaknjeni. +PREFERENCES_CACHEMAXENTRIES;Največje število datotek v vmesnem pomnilniku +PREFERENCES_CACHEOPTS;Nastavitve predpomnilnika +PREFERENCES_CACHETHUMBHEIGHT;Največja višina predogledne slikice +PREFERENCES_CHUNKSIZES;Ploskev na nit +PREFERENCES_CHUNKSIZE_RAW_AMAZE;AMaZE odstranjevanje mozaičnosti +PREFERENCES_CHUNKSIZE_RAW_CA;Surovi CA popravki +PREFERENCES_CHUNKSIZE_RAW_RCD;RCD odstranjevanje mozaičnosti +PREFERENCES_CHUNKSIZE_RAW_XT;Xtrans odstranjevanje mozaičnosti +PREFERENCES_CHUNKSIZE_RGB;RGB obdelava +PREFERENCES_CLIPPINGIND;Indikator obrezave +PREFERENCES_CLUTSCACHE;HaldCLUT predpomnilnik +PREFERENCES_CLUTSCACHE_LABEL;Maksimalno število predpomnjenih CLUTsev +PREFERENCES_CLUTSDIR;HaldCLUT mapa +PREFERENCES_CMMBPC;Prilagoditev črne točke +PREFERENCES_CROP;Obrezovanje +PREFERENCES_CROP_AUTO_FIT;Avtomatically prilagodi obrezavi +PREFERENCES_CROP_GUIDES;Prikaz vodil, kadar ne urejamo obrezave +PREFERENCES_CROP_GUIDES_FRAME;Okvir +PREFERENCES_CROP_GUIDES_FULL;Izvirnik +PREFERENCES_CROP_GUIDES_NONE;Noben +PREFERENCES_CURVEBBOXPOS;Pozicija gumbov za kopiranje in lepljenje krivulj +PREFERENCES_CURVEBBOXPOS_ABOVE;Nad +PREFERENCES_CURVEBBOXPOS_BELOW;Pod +PREFERENCES_CURVEBBOXPOS_LEFT;Levo +PREFERENCES_CURVEBBOXPOS_RIGHT;Desno +PREFERENCES_CUSTPROFBUILD;Orodje za izdelavo profila obdelav po meri +PREFERENCES_CUSTPROFBUILDHINT;Datoteka s programom (ali skriptom), ki se izvede kadar je treba idelati profil obdelave za sliko.\n\nPot za komunikacijsko datoteko (*.ini imenovana kudi "ključna datoteka") je dodana kot parameter ob klicu te datoteke. Vsebuje različne parametre za skripte in dele slik Exif, tako da omogoča generiranje profila obdelave glede na pravila.\n\nWARNING: Če pot vsebuje presledke, je vaša naloga, da jo omejite z dvojnimi apostrofi. +PREFERENCES_CUSTPROFBUILDKEYFORMAT;Format ključnih besed +PREFERENCES_CUSTPROFBUILDKEYFORMAT_NAME;Ime +PREFERENCES_CUSTPROFBUILDKEYFORMAT_TID;ID značke +PREFERENCES_CUSTPROFBUILDPATH;Pot izvajanja +PREFERENCES_DARKFRAMEFOUND;Najdeno +PREFERENCES_DARKFRAMESHOTS;posnetkov +PREFERENCES_DARKFRAMETEMPLATES;Šablone +PREFERENCES_DATEFORMAT;Format datuma +PREFERENCES_DATEFORMATHINT;Možna je raba naslednjih formatnih določil:\n%y - leto\n%m - mesec\n%d - dan\n\nNa primer standard ISO 8601 določa datum takole:\n%y-%m-%d +PREFERENCES_DIRDARKFRAMES;Mapa dark-frame +PREFERENCES_DIRECTORIES;Mape +PREFERENCES_DIRHOME;Domača mapa +PREFERENCES_DIRLAST;Zadnje obiskana mapa +PREFERENCES_DIROTHER;Ostalo +PREFERENCES_DIRSELECTDLG;Ob začetki izberi mapo slik... +PREFERENCES_DIRSOFTWARE;Mapa namestitve +PREFERENCES_EDITORCMDLINE;Ukazna vrstica po meri +PREFERENCES_EDITORLAYOUT;Oblika urejevalnika +PREFERENCES_EXTERNALEDITOR;Zunanji urejevalnik +PREFERENCES_FBROWSEROPTS;Pregledovalnik datotek/ Nastavitve predoglednih sličic +PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Kompaktne orodne vrstice v pregledovalniku datotek +PREFERENCES_FLATFIELDFOUND;Najdeno +PREFERENCES_FLATFIELDSDIR;Flat-field mapa +PREFERENCES_FLATFIELDSHOTS;posnetki +PREFERENCES_FLATFIELDTEMPLATES;šablone +PREFERENCES_FORIMAGE;Za nesurove slike +PREFERENCES_FORRAW;Za surove slike +PREFERENCES_FSTRIP_SAME_THUMB_HEIGHT;Enaka višina predogledne sličice za pregled filmov in pregledovalnik datotek +PREFERENCES_FSTRIP_SAME_THUMB_HEIGHT_HINT;Različni višini zahtevata več časa za obdelavo ob preklopu iz urejevalnika slike v pregledovalnik datotek. +PREFERENCES_GIMPPATH;mapa, kje je nameščen GIMP +PREFERENCES_HISTOGRAMPOSITIONLEFT;Histogram v levem panoju +PREFERENCES_HISTOGRAM_TOOLTIP;Če je omogočen, za izdelavo histograma slike v navigacijskem panoju uporabim delovni profil, sicer pa popravljen profil game. +PREFERENCES_HLTHRESHOLD;Prag za prilepljene bleščave +PREFERENCES_ICCDIR;Mapa, kjer so barvni profili +PREFERENCES_IMPROCPARAMS;Privzeti profil obdelave +PREFERENCES_INSPECT_LABEL;Preglej +PREFERENCES_INSPECT_MAXBUFFERS_LABEL;Največje število shranjenih slik v vmesnem pomnilniku +PREFERENCES_INSPECT_MAXBUFFERS_TOOLTIP;Nastavi največje število slik v vmesnem pomnilniku v pregledovalniku datotek; sistemi z malo RAMa (2GB) naj imajo to postavljeno na 1 ali 2. +PREFERENCES_INTENT_ABSOLUTE;Absolutno kolorimetrično +PREFERENCES_INTENT_PERCEPTUAL;Perceptual +PREFERENCES_INTENT_RELATIVE;Relativno kolorimetrično +PREFERENCES_INTENT_SATURATION;Nasičenje +PREFERENCES_INTERNALTHUMBIFUNTOUCHED;Prikaži predogledno sličico JPEG, če je surova slika še neobdelana +PREFERENCES_LANG;Jezik +PREFERENCES_LANGAUTODETECT;Uporabi jezik sistema +PREFERENCES_MAXRECENTFOLDERS;Največje število zadnje obiskanih map +PREFERENCES_MENUGROUPEXTPROGS;Skupinski "Odpri z" +PREFERENCES_MENUGROUPFILEOPERATIONS;Skupinske "Operacija z datotekami" +PREFERENCES_MENUGROUPLABEL;Skupinska "Oznaka barve" +PREFERENCES_MENUGROUPPROFILEOPERATIONS;Skupinske "Operacije profilov obdelav" +PREFERENCES_MENUGROUPRANK;Skupinsko "Rangiranje" +PREFERENCES_MENUOPTIONS;Kontekstne nastavitve menuja +PREFERENCES_MONINTENT;Privzeta namera upodabljanja +PREFERENCES_MONITOR;Monitor +PREFERENCES_MONPROFILE;Privzeti barvni profil +PREFERENCES_MONPROFILE_WARNOSX;Podprt je samo sRGB zaradi omejitev MacOS. +PREFERENCES_MULTITAB;Način večih zavihkov urejevalnika +PREFERENCES_MULTITABDUALMON;Več zavihkov urejevalnika v svojem oknu +PREFERENCES_NAVIGATIONFRAME;Navigacija +PREFERENCES_OVERLAY_FILENAMES;Ime datotek čez predogledne sličice v pregledovalniku datotek +PREFERENCES_OVERLAY_FILENAMES_FILMSTRIP;Ime datotek čez predogledne sličice v urejevalniku slik +PREFERENCES_OVERWRITEOUTPUTFILE;Prepiši obstoječe izhodne datoteke +PREFERENCES_PANFACTORLABEL;Povečanje hitrosti zamikanja +PREFERENCES_PARSEDEXT;Razpoznani podaljški datotek +PREFERENCES_PARSEDEXTADD;Dodaj podaljšek +PREFERENCES_PARSEDEXTADDHINT;Dodaj vnesen podaljšek v seznam. +PREFERENCES_PARSEDEXTDELHINT;Odstrani vnesen podaljšek s seznama. +PREFERENCES_PARSEDEXTDOWNHINT;Premakni vnesen podaljšek po seznamu navzdol. +PREFERENCES_PARSEDEXTUPHINT;Premakni vnesen podaljšek po seznamu navzgor. +PREFERENCES_PERFORMANCE_MEASURE;Mere +PREFERENCES_PERFORMANCE_MEASURE_HINT;Beleži obdelovalne čase na konzoli +PREFERENCES_PERFORMANCE_THREADS;Niti +PREFERENCES_PERFORMANCE_THREADS_LABEL;Največje število niti za odstranjevanje šuma in nivoje valovčkov (0 = Avtomatika) +PREFERENCES_PREVDEMO;Predlogled metode odstranjevamja mozaičnosti +PREFERENCES_PREVDEMO_FAST;Hitro +PREFERENCES_PREVDEMO_LABEL;Metoda odstranjevanja mozaičnosti za predogled <100% zoom: +PREFERENCES_PREVDEMO_SIDECAR;Kot v PP3 +PREFERENCES_PRINTER;Tiskalnik (Poskusni odtis) +PREFERENCES_PROFILEHANDLING;Obdelava profila +PREFERENCES_PROFILELOADPR;Prednost nalaganja profila v obdelavi +PREFERENCES_PROFILEPRCACHE;Profil v predpomnilniku +PREFERENCES_PROFILEPRFILE;Profil poleg vhodne datoteke +PREFERENCES_PROFILESAVEBOTH;Shrani profil obdelave dvojno tako v vmesnem pomnilniku kot zraven vhodne datoteke +PREFERENCES_PROFILESAVECACHE;Shrani profil obdelave v vmesnem pomnilniku +PREFERENCES_PROFILESAVEINPUT;Shrani profil obdelave zraven vhodne datoteke +PREFERENCES_PROFILESAVELOCATION;Lokacija shranjevanja profila obdelave +PREFERENCES_PROFILE_NONE;Noben +PREFERENCES_PROPERTY;Lastnost +PREFERENCES_PRTINTENT;Namera upodabljanja +PREFERENCES_PRTPROFILE;Barvni profil +PREFERENCES_PSPATH;Mapa nameščenega programa Adobe Photoshop +PREFERENCES_REMEMBERZOOMPAN;Zapomni si zoom % in odmik od roba +PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Zapomni si zoom % in odmik od trenutne slike ob odpiranju nove slike.\n\nTa nastavitev deluje samo v posamičnem urejevalniku in kadar je metoda odstranjevanja mozaičnosti <100% zoom" in nastavitev "Kot v PP3". +PREFERENCES_SAVE_TP_OPEN_NOW;Shrani stanje orodja v skrčenem ali razširjenem stanju zdaj +PREFERENCES_SELECTLANG;Izbira jezika +PREFERENCES_SERIALIZE_TIFF_READ;Nastavitve branja TIFF +PREFERENCES_SERIALIZE_TIFF_READ_LABEL;Sekvenčno branje datotek TIFF +PREFERENCES_SERIALIZE_TIFF_READ_TOOLTIP;Omogočanje te opcije kadar delamo z mapami, ki vsebujejo nestisnjene datoteke TIFF, lahko izboljšajo generiranje predoglednih sličic. +PREFERENCES_SET;Nastavi +PREFERENCES_SHOWBASICEXIF;Prikaži osnovne Exif informacije +PREFERENCES_SHOWDATETIME;Prikaži datum in čas +PREFERENCES_SHOWEXPOSURECOMPENSATION;Dodaj prilagoditev ekspozicije +PREFERENCES_SHOWFILMSTRIPTOOLBAR;Prikaži orodno vrstico filmskega izseka +PREFERENCES_SHTHRESHOLD;Prag za obrezane sence +PREFERENCES_SINGLETAB;Način enega zavihka urejevalnika +PREFERENCES_SINGLETABVERTAB;Način enega zavihka urejevalnika, Navpični zavihki +PREFERENCES_SND_HELP;Vnesi polno pot za nastavitev zvoka ali pusti prazno za brez zvoka.\nZa sistemske zvoke na sistemu Windows uporabi "SystemDefault", "SystemAsterisk" itd. na Linuxu pa "complete", "window-attention" itd. +PREFERENCES_SND_LNGEDITPROCDONE;Obdelava urejevalnika končana +PREFERENCES_SND_QUEUEDONE;Obdelava v čakalni vrsti končana +PREFERENCES_SND_THRESHOLDSECS;Po sekundah +PREFERENCES_STARTUPIMDIR;Mapa s slikami ob začetku +PREFERENCES_TAB_BROWSER;Brskalnik datotek +PREFERENCES_TAB_COLORMGR;Upravljanje z barvami +PREFERENCES_TAB_DYNAMICPROFILE;Pravila dinamičnih profilov +PREFERENCES_TAB_GENERAL;Splošno +PREFERENCES_TAB_IMPROC;Obdelava slik +PREFERENCES_TAB_PERFORMANCE;Performanse +PREFERENCES_TAB_SOUND;Zvoki +PREFERENCES_THUMBNAIL_INSPECTOR_JPEG;Predoglev vdelane JPEG +PREFERENCES_THUMBNAIL_INSPECTOR_MODE;Slika za prikaz +PREFERENCES_THUMBNAIL_INSPECTOR_RAW;Nevtralno surovo upodabljanje +PREFERENCES_THUMBNAIL_INSPECTOR_RAW_IF_NO_JPEG_FULLSIZE;Vgrajen JPEG, če je polne velikosti, sicer nevtralno surovo +PREFERENCES_TP_LABEL;Pano z orodji: +PREFERENCES_TP_VSCROLLBAR;Skrij navpični drsnik +PREFERENCES_USEBUNDLEDPROFILES;Uporabi skupne profile +PREFERENCES_WORKFLOW;Razporeditev +PROFILEPANEL_COPYPPASTE;Parametri za kopiranje +PROFILEPANEL_GLOBALPROFILES;Skupni profili +PROFILEPANEL_LABEL;Profili za obdelovanje +PROFILEPANEL_LOADDLGLABEL;Naloži parametre obdelovanja... +PROFILEPANEL_LOADPPASTE;Parametri za nalaganje +PROFILEPANEL_MODE_TIP;Vnosni način profila za obdelovanje.\n\nPritisnjen gumb: delni profili bodo spremenjeni v polne profile; manjkajoče vrednosti bodo zamenjale fiksne privzete vrednosti.\n\nSproščen gumb: profili bodo uporabljeni kakršni so, zamenjajo se samo vnesene vrednosti. +PROFILEPANEL_MYPROFILES;Moji profili +PROFILEPANEL_PASTEPPASTE;Parameteri za lepljenje +PROFILEPANEL_PCUSTOM;Po meri +PROFILEPANEL_PDYNAMIC;Dinamični +PROFILEPANEL_PFILE;Iz datoteke +PROFILEPANEL_PINTERNAL;Nevtralno +PROFILEPANEL_PLASTSAVED;Zadnje shranjene +PROFILEPANEL_SAVEDLGLABEL;Shrani parametre obdelave... +PROFILEPANEL_SAVEPPASTE;Parametri za shranjevanje +PROFILEPANEL_TOOLTIPCOPY;Kopiraj trenutni profil obdelave na odložišče.\nCtrl-klik za izbiro parametrov za kopiranje. +PROFILEPANEL_TOOLTIPLOAD;Naloži profil iz datoteke.\nCtrl-klik za izbiro parametrov za nalaganje. +PROFILEPANEL_TOOLTIPPASTE;Prilepi profil iz odložišča.\nCtrl-klik za izbiro parametrov za leplenje. +PROFILEPANEL_TOOLTIPSAVE;Shrani trenutni profil.\nCtrl-klik za izbiro parametrov za shranjevanje. +PROGRESSBAR_DECODING;Dekodiram... +PROGRESSBAR_GREENEQUIL;Uravnoteženje zelene... +PROGRESSBAR_HLREC;Rekonstrukcija bleščav... +PROGRESSBAR_HOTDEADPIXELFILTER;Filter vročih/mrtvih pikslov... +PROGRESSBAR_LINEDENOISE;Filter linijskega šuma... +PROGRESSBAR_LOADING;Nalagam sliko... +PROGRESSBAR_LOADINGTHUMBS;Nalagam predogledne sličice... +PROGRESSBAR_LOADJPEG;Nalagam datoteko JPEG... +PROGRESSBAR_LOADPNG;Nalagam datoteko PNG... +PROGRESSBAR_LOADTIFF;Nalagam datoteko TIFF... +PROGRESSBAR_NOIMAGES;Ne najdem nobene slike +PROGRESSBAR_PROCESSING;Obdelujem sliko... +PROGRESSBAR_PROCESSING_PROFILESAVED;Profil obdelave shranjen +PROGRESSBAR_RAWCACORR;Popravek surove CA... +PROGRESSBAR_READY;Pripravljen +PROGRESSBAR_SAVEJPEG;Shranjujem datoteko JPEG... +PROGRESSBAR_SAVEPNG;Shranjujem datoteko PNG... +PROGRESSBAR_SAVETIFF;Shranjujem datoteko TIFF... +PROGRESSBAR_SNAPSHOT_ADDED;Posnetek dodan +PROGRESSDLG_PROFILECHANGEDINBROWSER;Profil obdelave je shranjen v pregledovalniku +QINFO_FRAMECOUNT;%2 okvirov +QINFO_HDR;HDR / %2 okvirov +QINFO_ISO;ISO +QINFO_NOEXIF;Podatki Exif niso na voljo. +QINFO_PIXELSHIFT;Pomik pikslov / %2 okvirjev +QUEUE_AUTOSTART;Avto-start +QUEUE_AUTOSTART_TOOLTIP;Avtomatično začni obdelavo, ko pride nov posel. +QUEUE_DESTFILENAME;Pot in ime datoteke +QUEUE_FORMAT_TITLE;Format datoteke +QUEUE_LOCATION_FOLDER;Shrani v mapo +QUEUE_LOCATION_TEMPLATE;Uporabi šablono +QUEUE_LOCATION_TEMPLATE_TOOLTIP;Določite izhodno lokacijo glede na lokacijo izvirne fotografije, rang, status smeti ali položaj v čakalni vrsti.\n\nZa primer poti uporabite naslednje:\n/home/tom/photos/2010-10-31/photo1.raw\npomen nizov sledi: :\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = photo1\n%p1 = /home/tom/photos/2010-10-31/\n%p2 = /home/tom/photos/\n%p3 = /home/tom/\n%p4 = /home/\n\n%r bo zamenjana z oceno fotografije. Če slika ni ocenjena, se uporabi '0'. Če je slika v smeteh uporabimo 'x'.\n\n%s1, ..., %s9 bo zamenjano za začetni položaj slike v čakalni vrsti, ko se ta začne. Število opisuje polnilo, npr. %s3 se spremeni v '001'.\n\nČe želite izhodno sliko shraniti poleg izvirne slike, napišite::\n%p1/%f\n\nČe želite izhodno sliko shraniti v mapo z imenom 'converted' ki se nahaja v mapi izvorne fotografije, napišite:\n%p1/converted/%f\n\nČe želite izhodno sliko shraniti v\n'/home/tom/photos/converted/2010-10-31', napišite:\n%p2/converted/%d1/%f +QUEUE_LOCATION_TITLE;Lokacija izhoda +QUEUE_STARTSTOP_TOOLTIP;Začni ali končaj obdelavo slik v čakalni vrsti.\n\nBližnjica: Ctrl+s +SAMPLEFORMAT_0;Neznan format podatkov +SAMPLEFORMAT_1;8-bit brez predznaka +SAMPLEFORMAT_2;16-bit brez predznaka +SAMPLEFORMAT_4;24-bit LogLuv +SAMPLEFORMAT_8;32-bit LogLuv +SAMPLEFORMAT_16;16-bit plavajoča vejica +SAMPLEFORMAT_32;24-bit plavajoča vejica +SAMPLEFORMAT_64;32-bit plavajoča vejica +SAVEDLG_AUTOSUFFIX;Avtomatično dodaj tip, če datoteka že obstaja +SAVEDLG_FILEFORMAT;Format datoteke +SAVEDLG_FILEFORMAT_FLOAT; plavajoča vejica +SAVEDLG_FORCEFORMATOPTS;Zahtevaj opcije shranjevanja +SAVEDLG_JPEGQUAL;JPEG kakovost +SAVEDLG_PUTTOQUEUE;Postavi v čakalno vrsto za obdelavo +SAVEDLG_PUTTOQUEUEHEAD;Postavi na začetek čakalne vrste za obdelavo +SAVEDLG_PUTTOQUEUETAIL;Postavi na konec čakalne vrste za obdelavo +SAVEDLG_SAVEIMMEDIATELY;Takoj shrani +SAVEDLG_SAVESPP;Shrani parametre obdelave skupaj s sliko +SAVEDLG_SUBSAMP;Podvzorčenje +SAVEDLG_SUBSAMP_1;Najboljše stiskanje +SAVEDLG_SUBSAMP_2;Uravnoteženo +SAVEDLG_SUBSAMP_3;Najboljša kakovost +SAVEDLG_SUBSAMP_TOOLTIP;Najbolj stisnjeno:\nJ:a:b 4:2:0\nh/v 2/2\nBarvitost razpolovljena vodoravno in navpično.\n\nUravnoteženo:\nJ:a:b 4:2:2\nh/v 2/1\nBarvitost razpolovljena vodoravno.\n\nNajbolj kakovostno:\nJ:a:b 4:4:4\nh/v 1/1\nBrez podvzorčenja barvitosti. +SAVEDLG_TIFFUNCOMPRESSED;Nestisnjen TIFF +SAVEDLG_WARNFILENAME;Datoteka bo poimenovana +SHCSELECTOR_TOOLTIP;Desni klik za ponastavitev pozicije 3 drsnikov. +SOFTPROOF_GAMUTCHECK_TOOLTIP;Osvetli piksle z barvo izven barvnega prostora glede na:\n- profil tiskalnika, če je nastavljen in je omogočen poskusni odtis,\n- izhodni profil, če tiskalnikov profil ni določen in je poskusni odtis omogočen,\n- profil zaslona, če je poskusni odtis onemogočen. +SOFTPROOF_TOOLTIP;Poskusni odtis simulira izgled slike:\n- ko je natisnjen, če je nastavljen profil tiskalnika v Preference > Upravljanje z barvami,\n- kadar ogledujemo sliko na zaslonu, ki uporablja trenutni profil zaslona, če profil tiskalnika ni določen. +THRESHOLDSELECTOR_B;Spodaj +THRESHOLDSELECTOR_BL;Spodaj-levo +THRESHOLDSELECTOR_BR;Spodaj-desno +THRESHOLDSELECTOR_HINT;Držite tipko Shift za premik posameznih kontrolnih točk. +THRESHOLDSELECTOR_T;Zgoraj +THRESHOLDSELECTOR_TL;Zgoraj-levo +THRESHOLDSELECTOR_TR;Zgoraj-desno +TOOLBAR_TOOLTIP_COLORPICKER;Izbirnik barv, ki ga je moč zakleniti\n\nKadar je orodje aktivno:\n- Dodajte izbiro: levi-klik.\n- Povlecite izbiro: levi-klik in poteg.\n- Briši izbiro: desni-klik.\n- Briši vse izbire: Ctrl+Shift+desni-klik.\n- Povratek na ročno orodje: desni-klik zunaj kateregakoli izbirnika. +TOOLBAR_TOOLTIP_CROP;Crop izbira.\nBližnjica: c\nPremakni obrezavo s Shift+potegom miške. +TOOLBAR_TOOLTIP_HAND;Ročno orodje.\nBližnjica: h +TOOLBAR_TOOLTIP_STRAIGHTEN;Ravnanje / fino vrtenje.\nBližnjica: s\n\nOznačite navpičnico ali vodoravnico z risanjem vodilne črte čez predogled slike. Kot vodilne črte bo prikazan zraven vodilne črte. Središče vrtenja je geometrijsko središče slike. +TOOLBAR_TOOLTIP_WB;Uravnotežena belina točke.\nBližnjica: w +TP_BWMIX_ALGO;Algoritem OYCPM +TP_BWMIX_ALGO_LI;Linearno +TP_BWMIX_ALGO_SP;Posebni učinki +TP_BWMIX_ALGO_TOOLTIP;Linearno: bo povzročil normalni linearni odziv.\nPosebni učinki: bodo povzročili posebne učinke z mešanjem kanalov na ne-linearen način. +TP_BWMIX_AUTOCH;Avto +TP_BWMIX_CC_ENABLED;Prilagodi komplementarno barvo +TP_BWMIX_CC_TOOLTIP;Dovoli avtomatično prilagajanje komplementarnih barv v načinu ROYGCBPM. +TP_BWMIX_CHANNEL;Ekvalizator svetlosti +TP_BWMIX_CURVEEDITOR1;Krivulja 'pred' +TP_BWMIX_CURVEEDITOR2;Krivulja 'po' +TP_BWMIX_CURVEEDITOR_AFTER_TOOLTIP;Krivulja tonov po predelavi v črno-belo ob koncu postopka. +TP_BWMIX_CURVEEDITOR_BEFORE_TOOLTIP;Krivulja tonov tik prek predelavo v črno-belo.\nLahko je odvisna od barvnih komponent. +TP_BWMIX_CURVEEDITOR_LH_TOOLTIP;Svetlost odvisna od odtenka L=f(H).\nPazite na skrajne vrednosti, ker lahko generirajo artefakte. +TP_BWMIX_FILTER;Barvni Filter +TP_BWMIX_FILTER_BLUE;Modra +TP_BWMIX_FILTER_BLUEGREEN;Modro-Zelena +TP_BWMIX_FILTER_GREEN;Zelena +TP_BWMIX_FILTER_GREENYELLOW;Zeleno-Rumena +TP_BWMIX_FILTER_NONE;Nobena +TP_BWMIX_FILTER_PURPLE;Vijolična +TP_BWMIX_FILTER_RED;Rdeča +TP_BWMIX_FILTER_REDYELLOW;Rdeče-Rumena +TP_BWMIX_FILTER_TOOLTIP;Barvni filter simulira slike posnete z barvnim filtrom pred objektivom. Barvni filtri zmanjšajo prenos določenega dela barv in zato vplivajo na svetlost. Npr. rdeči filtri zatemnijo modro nebo. +TP_BWMIX_FILTER_YELLOW;Rumena +TP_BWMIX_GAMMA;Popravek game +TP_BWMIX_GAM_TOOLTIP;Popravi gamo za vsak RGB kanal. +TP_BWMIX_LABEL;Črno-belo +TP_BWMIX_MET;Metoda +TP_BWMIX_MET_CHANMIX;Mešalnik kanalov +TP_BWMIX_MET_DESAT;Zmanjšanje nasičenosti +TP_BWMIX_MET_LUMEQUAL;Ekvalizator svetlosti +TP_BWMIX_MIXC;Mešalnik kanalov +TP_BWMIX_NEUTRAL;Ponastavi +TP_BWMIX_RGBLABEL;R: %1%% G: %2%% B: %3%% Total: %4%% +TP_BWMIX_RGBLABEL_HINT;Končni faktorji RGB, ki skrbijo za vse možnosti mešalnika.\n"Skupaj" prikaže vsoto RGB vrednosti:\n- vedno 100% v relativnem načinu\n- višje (svetlejše) ali nižje (temnejše) od 100% v absolutnem načinu. +TP_BWMIX_RGB_TOOLTIP;Zmešajte RGB kanale. Uporabite prednastavitve za vodenje.\nBodite pozorni na negativne vrednosti, ki lahko povzročijo artefakte ali napačno delovanje. +TP_BWMIX_SETTING;Prednastavitve +TP_BWMIX_SETTING_TOOLTIP;Različne prednastvitve (film, pokrajina, itd.) ali ročne nastavitve mešalnika kanalov. +TP_BWMIX_SET_HIGHCONTAST;Visok kontrast +TP_BWMIX_SET_HIGHSENSIT;Visoka občutljivost +TP_BWMIX_SET_HYPERPANCHRO;Hiper pankromatsko +TP_BWMIX_SET_INFRARED;Infrardeče +TP_BWMIX_SET_LANDSCAPE;Pokrajina +TP_BWMIX_SET_LOWSENSIT;Nizka občutljivost +TP_BWMIX_SET_LUMINANCE;Svetlost +TP_BWMIX_SET_NORMCONTAST;Normalen kontrast +TP_BWMIX_SET_ORTHOCHRO;Ortokromatsko +TP_BWMIX_SET_PANCHRO;Pankromatsko +TP_BWMIX_SET_PORTRAIT;Portret +TP_BWMIX_SET_RGBABS;Absolutno RGB +TP_BWMIX_SET_RGBREL;Relativno RGB +TP_BWMIX_SET_ROYGCBPMABS;Absolutno ROYGCBPM +TP_BWMIX_SET_ROYGCBPMREL;Relativno ROYGCBPM +TP_BWMIX_TCMODE_FILMLIKE;Kot čno-beli film +TP_BWMIX_TCMODE_SATANDVALBLENDING;Črno-belo nasičenje in mešanje vrednosti +TP_BWMIX_TCMODE_STANDARD;Standardno črno-belo +TP_BWMIX_TCMODE_WEIGHTEDSTD;Uteženo standardno črno-belo +TP_BWMIX_VAL;L +TP_CACORRECTION_BLUE;Modro +TP_CACORRECTION_LABEL;Popravek kromatske aberacije +TP_CACORRECTION_RED;Rdeče +TP_CBDL_AFT;Črno-belo 'po' +TP_CBDL_BEF;Črno-belo 'pred' +TP_CBDL_METHOD;Lokacija obdelave +TP_CBDL_METHOD_TOOLTIP;Izberi ali naj bo orodje nivojev kontrasta po transformaciji v črno-belo, ki deluje v prostorum L*a*b* , ali pred transformacijo, ki deluje v prostoru RGB. +TP_CHMIXER_BLUE;Modri kanali +TP_CHMIXER_GREEN;Zeleni kanal +TP_CHMIXER_LABEL;Mešalnik kanalov +TP_CHMIXER_RED;Rdeči kanal +TP_COARSETRAF_TOOLTIP_HFLIP;Vodoravno preobrni. +TP_COARSETRAF_TOOLTIP_ROTLEFT;Zavrti levo.\n\nBližnjica:\n[ - Način večih zavihkov,\nAlt-[ - Način enega zavihka. +TP_COARSETRAF_TOOLTIP_ROTRIGHT;Zavrti desno.\n\nBližnjica:\n] - Način večih zavihkov,\nAlt-] - Način enega zavihka. +TP_COARSETRAF_TOOLTIP_VFLIP;Preobrni navpično. +TP_COLORAPP_ABSOLUTELUMINANCE;Absolutna svetlost +TP_COLORAPP_ALGO;Algoritem +TP_COLORAPP_ALGO_ALL;Vse +TP_COLORAPP_ALGO_JC;Svetlost + Barvitost (JC) +TP_COLORAPP_ALGO_JS;Svetlost + Nasičenost (JS) +TP_COLORAPP_ALGO_QM;Bleščina + Polnost barv (QM) +TP_COLORAPP_ALGO_TOOLTIP;Dovoljuje izbiro podmnožice parametrov ali vseh. +TP_COLORAPP_BADPIXSL;Filter vročih/mrtvih pikslov +TP_COLORAPP_BADPIXSL_TOOLTIP;Zatiranje vročih/slabih (živobarvno prikazanih) pikslov.\n0 = Brez učinka\n1 = Mediana\n2 = po Gaussu.\nSicer prilagodi sliko tako da se izogiba zelo temnih senc.\n\nTi artefakti so zaradi omejitev CIECAM02. +TP_COLORAPP_BRIGHT;Svetlost (Q) +TP_COLORAPP_BRIGHT_TOOLTIP;Svetlost v CIECAM02 upošteva tudi belino in se razlikuje od svetlosti v L*a*b* . +TP_COLORAPP_CAT02ADAPTATION_TOOLTIP;Kadar jo nastavite ročno, priporočam vrednosti nad 65. +TP_COLORAPP_CHROMA;Barvitost (C) +TP_COLORAPP_CHROMA_M;Polnost barv (M) +TP_COLORAPP_CHROMA_M_TOOLTIP;Polnost barv v CIECAM02 se razlikuje od polnosti v L*a*b* in RGB. +TP_COLORAPP_CHROMA_S;Nasičenost (S) +TP_COLORAPP_CHROMA_S_TOOLTIP;Nasičenost v CIECAM02 se razlikuje od nasičenosti v L*a*b* in RGB. +TP_COLORAPP_CHROMA_TOOLTIP;Barvitost v CIECAM02 se razlikuje od barvitosti v L*a*b* in RGB. +TP_COLORAPP_CIECAT_DEGREE;CAT02 prilagoditev +TP_COLORAPP_CONTRAST;Kontrast (J) +TP_COLORAPP_CONTRAST_Q;Kontrast (Q) +TP_COLORAPP_CONTRAST_Q_TOOLTIP;Razlikujte med L*a*b* in RGB kontrastom. +TP_COLORAPP_CONTRAST_TOOLTIP;Razlikujte med L*a*b* in RGB kontrastom. +TP_COLORAPP_CURVEEDITOR1;Krivulja tonov 1 +TP_COLORAPP_CURVEEDITOR1_TOOLTIP;Prkaže histogram L* (L*a*b*) pred CIECAM02.\nČe je aktivno "Prikaži CIECAM02 izhodne histograme v krivuljah", prikaže histograme J ali Q po CIECAM02.\n\nJ in Q nista prikazana v glavnem panoju histogramov.\n\nKončni izhod se nanaša na glavni pano histogramov. +TP_COLORAPP_CURVEEDITOR2;Krivulja tonov 2 +TP_COLORAPP_CURVEEDITOR2_TOOLTIP;Enaka uporaba kot pri krivulji tonov druge ekspozicije. +TP_COLORAPP_CURVEEDITOR3;Krivulja barv +TP_COLORAPP_CURVEEDITOR3_TOOLTIP;Prilagodi barvitost, nasičenje ali polnost barv.\n\nPrikaže histogram barvitosti (L*a*b*) pred CIECAM02.\nČe je aktivirano "Prikaži CIECAM02 izhodne histograme v krivuljah", prikaže histograme C, s ali M po CIECAM02.\n\nC, s in M niso prikazani v glavnem panoju histogramov.\nKončni izhod se nanaša na glavni pano histogramov. +TP_COLORAPP_DATACIE;CIECAM02 izhodni histogrami v krivuljah +TP_COLORAPP_DATACIE_TOOLTIP;Kadar je aktivirano so histogrami, CIECAM02 krivulje prikazujejo približne vrednosti oz. intervale z J ali Q, in C, s ali M po prilagoditvah CIECAM02.\nTa izbira ne vpliva na glavni pano histogramov.\n\nKadar je deaktiviran, histogrami v CIECAM02 krivuljah kažejo vrednosti L*a*b* pred prilagoditvami CIECAM02. +TP_COLORAPP_FREE;Prosta temp+zelena + CAT02 + [output] +TP_COLORAPP_GAMUT;Lontrola barvega obsega (L*a*b*) +TP_COLORAPP_GAMUT_TOOLTIP;Dovoli kontrolo barvnega obsega v L*a*b* načinu. +TP_COLORAPP_HUE;Odtenek (h) +TP_COLORAPP_HUE_TOOLTIP;Odtenek (h) - kot med 0° in 360°. +TP_COLORAPP_LABEL;CIE Prikaz barv Model 2002 +TP_COLORAPP_LABEL_CAM02;Prilagoditve slike +TP_COLORAPP_LABEL_SCENE;Scenski pogoji +TP_COLORAPP_LABEL_VIEWING;Pogoji gledanja +TP_COLORAPP_LIGHT;Svetlost (J) +TP_COLORAPP_LIGHT_TOOLTIP;Svetlost v CIECAM02 se razlikuje od svetlosti v L*a*b* in RGB. +TP_COLORAPP_MEANLUMINANCE;Povprečna svetlost (Yb%) +TP_COLORAPP_MODEL;WP Model +TP_COLORAPP_MODEL_TOOLTIP;Model bele točke.\n\nWB [RT] + [output]: za sceno se uporabi RT-jevo ravnotežje beline, CIECAM02 je nastavljen na D50, nastavitev beline izhodne naprave je nastavljena v Pogojih gledanja.\n\nWB [RT+CAT02] + [output]: RT-jevo ravnotežje beline uporablja CAT02, ravnotežje beline izhodne naprave pa je nastavljeno v Pogojih gledanja.\n\nProsta temp+zelena + CAT02 + [output]: temp in zeleno določi uporabnik, ravnotežje beline izhodne naprave pa je nastavljeno v Pogojih gledanja. +TP_COLORAPP_NEUTRAL;Ponastavi +TP_COLORAPP_NEUTRAL_TIP;Ponastavi vse potrditvena polja in krivulje na njihove privzete vrednosti +TP_COLORAPP_RSTPRO;Varovanje rdečih in kožnih tonov +TP_COLORAPP_RSTPRO_TOOLTIP;Varovanje rdečih in kožnih tonov ima vpliv tako na drsnike kot na krivulje. +TP_COLORAPP_SURROUND;Obkroži +TP_COLORAPP_SURROUND_AVER;Povprečno +TP_COLORAPP_SURROUND_DARK;Temno +TP_COLORAPP_SURROUND_DIM;Zatemnjeno +TP_COLORAPP_SURROUND_EXDARK;Izjemno črno (Cutsheet) +TP_COLORAPP_SURROUND_TOOLTIP;Spremembe tonov in barv so odvisne od pogojev gledanja na izhodno enoto.\n\nPovprečje: Povprečno svetlobno okolje (standard). Slika se ne bo spremenila.\n\nZatemnjeno: Zatemnjeno okolje (TV). Slika bo postala malo temnejša.\n\nTemno: temno okolje (projektor). Slika bo postala bolj temna.\n\nIzredno temno: Izredno temno okolje (Cutsheet). Slika bo postala zelo temna. +TP_COLORAPP_TCMODE_BRIGHTNESS;Brightness +TP_COLORAPP_TCMODE_CHROMA;Barvitost +TP_COLORAPP_TCMODE_COLORF;Polnost barv +TP_COLORAPP_TCMODE_LABEL1;Krivulja način 1 +TP_COLORAPP_TCMODE_LABEL2;Krivulja način 2 +TP_COLORAPP_TCMODE_LABEL3;Krivulja barvitosti +TP_COLORAPP_TCMODE_LIGHTNESS;Svetlost +TP_COLORAPP_TCMODE_SATUR;Nasičenost +TP_COLORAPP_TEMP_TOOLTIP;Za izbrano svetilo vedno postavi Tint=1.\n\nA temp=2856\nD50 temp=5003\nD55 temp=5503\nD65 temp=6504\nD75 temp=7504 +TP_COLORAPP_TONECIE;Preslikava barvnih tonov s CIECAM02 +TP_COLORAPP_TONECIE_TOOLTIP;Če je ta opcija neaktivna, je preslikava barvnih tonov v prostoru L*a*b* .\nČe je aktivirana, je prenos barvnih tonov z uporabo CIECAM02.\nOrodje za prenos barvnih tonov mora biti aktivno, da ima učinek. +TP_COLORAPP_VIEWING_ABSOLUTELUMINANCE_TOOLTIP;Absolutna svetlost okolice gledanja\n(običajno 16 cd/m²). +TP_COLORAPP_WBCAM;WB [RT+CAT02] + [output] +TP_COLORAPP_WBRT;WB [RT] + [output] +TP_COLORTONING_AB;o C/L +TP_COLORTONING_AUTOSAT;Avtomatično +TP_COLORTONING_BALANCE;Uravnoteženo +TP_COLORTONING_BY;o C/L +TP_COLORTONING_CHROMAC;Neprosojnost +TP_COLORTONING_COLOR;Barva +TP_COLORTONING_CURVEEDITOR_CL_TOOLTIP;Neprosojnost barvitosti kot funkcija svetlosti oC=f(L) +TP_COLORTONING_HIGHLIGHT;Bleščave +TP_COLORTONING_HUE;Odtenki +TP_COLORTONING_LAB;L*a*b* mešanje +TP_COLORTONING_LABEL;Toniranje barv +TP_COLORTONING_LABGRID;L*a*b* mreža popravkov barv +TP_COLORTONING_LABGRID_VALUES;HL: a=%1 b=%2\nS: a=%3 b=%4 +TP_COLORTONING_LABREGIONS;Regije popravkov barv +TP_COLORTONING_LABREGION_ABVALUES;a=%1 b=%2 +TP_COLORTONING_LABREGION_CHANNEL;Kanal +TP_COLORTONING_LABREGION_CHANNEL_ALL;Vse +TP_COLORTONING_LABREGION_CHANNEL_B;Modra +TP_COLORTONING_LABREGION_CHANNEL_G;Zelena +TP_COLORTONING_LABREGION_CHANNEL_R;Rdeča +TP_COLORTONING_LABREGION_CHROMATICITYMASK;C +TP_COLORTONING_LABREGION_HUEMASK;H +TP_COLORTONING_LABREGION_LIGHTNESS;Svetlost +TP_COLORTONING_LABREGION_LIGHTNESSMASK;L +TP_COLORTONING_LABREGION_LIST_TITLE;Popravek +TP_COLORTONING_LABREGION_MASK;Maska +TP_COLORTONING_LABREGION_MASKBLUR;Maska zamegljenosti +TP_COLORTONING_LABREGION_OFFSET;Odmik +TP_COLORTONING_LABREGION_POWER;Moč +TP_COLORTONING_LABREGION_SATURATION;Nasičenje +TP_COLORTONING_LABREGION_SHOWMASK;Prikaži masko +TP_COLORTONING_LABREGION_SLOPE;Strmina +TP_COLORTONING_LUMA;Svetlost +TP_COLORTONING_LUMAMODE;Ohrani svetlost +TP_COLORTONING_LUMAMODE_TOOLTIP;Če je aktivno, se ob spremembi barve (rdeča, zelena, cian, modra, itd.) ohrani tudi svetlost vsakega piksla. +TP_COLORTONING_METHOD;Metoda +TP_COLORTONING_METHOD_TOOLTIP;"L*a*b* mešanje", "RGB drsniki" in "RGB krivulje" uporabljajo interpolirno mešanje barv.\n"Uravnoteženje barv (Sence/Srednji toni/Bleščave)" and "Nasičenje 2 barv" uporabljajo neposredne barve.\n\nČrno-belo orodje lahko uporabimo pri katerikoli metodi barvega toniranja. +TP_COLORTONING_MIDTONES;Srednji toni +TP_COLORTONING_NEUTRAL;Ponastavi drsnike +TP_COLORTONING_NEUTRAL_TIP;Ponastavi vse vrednosti (Sence, Srednji toni, Bleščave) na prizeto vrednost. +TP_COLORTONING_OPACITY;Neprosojnost +TP_COLORTONING_RGBCURVES;RGB - Krivulje +TP_COLORTONING_RGBSLIDERS;RGB - Drsniki +TP_COLORTONING_SA;Zavarovanje nasičenosti +TP_COLORTONING_SATURATEDOPACITY;Moč +TP_COLORTONING_SATURATIONTHRESHOLD;Prag +TP_COLORTONING_SHADOWS;Sence +TP_COLORTONING_SPLITCO;Sence/Srednje vrednosti/Bleščave +TP_COLORTONING_SPLITCOCO;Uravnoteženje barv Sence/Srednje vrednosti/Bleščave +TP_COLORTONING_SPLITLR;Nasičenje 2 barv +TP_COLORTONING_STR;Moč +TP_COLORTONING_STRENGTH;Moč +TP_COLORTONING_TWO2;Posebna barvitost '2 colors' +TP_COLORTONING_TWOALL;Posebna barvitost +TP_COLORTONING_TWOBY;Posebna a* in b* +TP_COLORTONING_TWOCOLOR_TOOLTIP;Standardna barvitost:\nLinearni odziv, a* = b*.\n\nPosebna barvitost:\nLinearni odziv, a* = b*, toda neomejen - poskusi pod diagonalo.\n\nPosebna a* in b*:\nLinearni neomejeni odziv s posebnima krivuljama za a* in b*. Namenjeno posebnim učinkom.\n\nPosebna barvitost 2 barv:\nBolj predvidljivo. +TP_COLORTONING_TWOSTD;Standardna barvitost +TP_CROP_FIXRATIO;Zakleni razmerje +TP_CROP_GTDIAGONALS;Pravilo diagonal +TP_CROP_GTEPASSPORT;Biometrični potni list +TP_CROP_GTFRAME;Okvir +TP_CROP_GTGRID;Mreža +TP_CROP_GTHARMMEANS;Harmonična povprečja +TP_CROP_GTNONE;Noben +TP_CROP_GTRULETHIRDS;Pravilo tretjin +TP_CROP_GTTRIANGLE1;Zlati trikotniki 1 +TP_CROP_GTTRIANGLE2;Zlati trikotniki 2 +TP_CROP_GUIDETYPE;Vodilo tipa: +TP_CROP_H;Višina +TP_CROP_LABEL;Obreži +TP_CROP_PPI;PPI +TP_CROP_RESETCROP;Ponastavi +TP_CROP_SELECTCROP;Izberi +TP_CROP_W;Širina +TP_CROP_X;Levo +TP_CROP_Y;Vrh +TP_DARKFRAME_AUTOSELECT;Avtomatičen izbor +TP_DARKFRAME_LABEL;Dark-frame +TP_DEFRINGE_LABEL;Odstrani artefakte +TP_DEFRINGE_RADIUS;Radij +TP_DEFRINGE_THRESHOLD;Prag +TP_DEHAZE_DEPTH;Globina +TP_DEHAZE_LABEL;Odstranjevanje zamegljenosti +TP_DEHAZE_LUMINANCE;Samo svetlost +TP_DEHAZE_SHOW_DEPTH_MAP;Prikaži karto globin +TP_DEHAZE_STRENGTH;Moč +TP_DIRPYRDENOISE_CHROMINANCE_AMZ;Avto multi-cone +TP_DIRPYRDENOISE_CHROMINANCE_AUTOGLOBAL;Avtomatično globalno +TP_DIRPYRDENOISE_CHROMINANCE_BLUEYELLOW;Krominanca - modro-rumeno +TP_DIRPYRDENOISE_CHROMINANCE_CURVE;Krivulja krominance +TP_DIRPYRDENOISE_CHROMINANCE_CURVE_TOOLTIP;Povečaj (pomnoži) vrednosti vseh krominanc drsnikov.\nTa krivulja omogoča prilagajanje moči zmanjševanje barvnega šuma kot funkcijo kromatičnosti, na primer za povečanje aktivnosti v področjih z nizko nasičenostjo in zmanjšanje na področjih visoke nasičenosti. +TP_DIRPYRDENOISE_CHROMINANCE_FRAME;Krominanca +TP_DIRPYRDENOISE_CHROMINANCE_MANUAL;Ročno +TP_DIRPYRDENOISE_CHROMINANCE_MASTER;Krominanca - Matična +TP_DIRPYRDENOISE_CHROMINANCE_METHOD;Metoda +TP_DIRPYRDENOISE_CHROMINANCE_METHODADVANCED_TOOLTIP;Ročno\nDeluje na vsej sliki.\nNastavitve odstranjevanja šuma upravljate ročno.\n\nAvtomatično globalno\nDeluje na vsej sliki.\nUporabljeno je 9 con za izračun parametrov globalnega zmanjšanja barvnega šuma.\n\nPreogled\nDeluje na celotni sliki.\nDel slike, ki je viden v predlogledu je uporabljen za izračun parametrov za odstranjevanje šuma. +TP_DIRPYRDENOISE_CHROMINANCE_METHOD_TOOLTIP;Manual\nDeluje na vsej sliki.\nastavitve odstranjevanja šuma upravljate ročno.\n\nAvtomatično globalno\nDeluje na vsej sliki.\nUporabljeno je 9 con za izračun parametrov globalnega zmanjšanja barvnega šuma.\n\nAvtomatično več-consko\nNi predogleda - deluje samo ob shranjevanju, toda z uporabo "Predogledne" metode tako, da je center slike center predogleda, velikost slike pa velikost predogleda tako, da dobite vtis o predvidenih učinkih.\nSlika je razdeljena na krpe (od 10 do 70 odvisno od velikosti slike) in vsaka krpa ima svoje nastavitve odpravljanja barvnega šuma.\n\nPredogled\nDeluje na celotni sliki.\nDel slike, ki je viden v predlogledu je uporabljen za izračun parametrov za odstranjevanje šuma. +TP_DIRPYRDENOISE_CHROMINANCE_PMZ;Multi-cone predogleda +TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW;Predogled +TP_DIRPYRDENOISE_CHROMINANCE_PREVIEWRESIDUAL_INFO_TOOLTIP;Prikaže preostale nivoje šuma na delu slike v predogledu po valovčku.\n\n>300 Z veliko šuma\n100-300 Šum\n50-100 Malo šuma\n<50 Zelo malo šuma\n\nVedite, da se vrednosti razlikujejo med RGB in L*a*b* . Vrednosti v RGB so manj natančne, ker RGB način v celoti ne loči svetlosti in barvitosti. +TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_INFO;Velikost predogleda=%1, Center: Px=%2 Py=%3 +TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_NOISEINFO;Šum predogleda: Povprečje=%1 Visoko=%2 +TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_NOISEINFO_EMPTY;Šum predogleda: Povprečje= - Visoko= - +TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_TILEINFO;Velikost krpe=%1, Center: Tx=%2 Ty=%3 +TP_DIRPYRDENOISE_CHROMINANCE_REDGREEN;Krominanca - Rdeča-Zelena +TP_DIRPYRDENOISE_LABEL;Odpravljanje šuma +TP_DIRPYRDENOISE_LUMINANCE_CONTROL;Upravljanje svetlosti +TP_DIRPYRDENOISE_LUMINANCE_CURVE;Krivulja svetlosti +TP_DIRPYRDENOISE_LUMINANCE_DETAIL;Podrobnost obnove +TP_DIRPYRDENOISE_LUMINANCE_FRAME;Svetlost +TP_DIRPYRDENOISE_LUMINANCE_SMOOTHING;Svetlost +TP_DIRPYRDENOISE_MAIN_COLORSPACE;Barvni prostor +TP_DIRPYRDENOISE_MAIN_COLORSPACE_LAB;L*a*b* +TP_DIRPYRDENOISE_MAIN_COLORSPACE_RGB;RGB +TP_DIRPYRDENOISE_MAIN_COLORSPACE_TOOLTIP;Za surove slike je moč uporabiti ali RGB ali L*a*b* .\n\nZa ne-surove slike bo ne glede na izbiro uporabljena metoda L*a*b* . +TP_DIRPYRDENOISE_MAIN_GAMMA;Gama +TP_DIRPYRDENOISE_MAIN_GAMMA_TOOLTIP;Gama ima vpliv na moč zmanjšanja šuma glede nabora tonov. Manjše vrednosti ciljajo na sence, večje vrednosti pa bodo raztegnile vpliv na svetlejše tone. +TP_DIRPYRDENOISE_MAIN_MODE;Način +TP_DIRPYRDENOISE_MAIN_MODE_AGGRESSIVE;Agresivno +TP_DIRPYRDENOISE_MAIN_MODE_CONSERVATIVE;Konservativno +TP_DIRPYRDENOISE_MAIN_MODE_TOOLTIP;"Konservativno" ohranja nizke frekvence vzorcev barvitosti, medtem ko jih "agresivne" izbrišejo. +TP_DIRPYRDENOISE_MEDIAN_METHOD;Metode mediane +TP_DIRPYRDENOISE_MEDIAN_METHOD_CHROMINANCE;Samo barvitost +TP_DIRPYRDENOISE_MEDIAN_METHOD_LAB;L*a*b* +TP_DIRPYRDENOISE_MEDIAN_METHOD_LABEL;Filter mediane +TP_DIRPYRDENOISE_MEDIAN_METHOD_LUMINANCE;Samo svetlost +TP_DIRPYRDENOISE_MEDIAN_METHOD_RGB;RGB +TP_DIRPYRDENOISE_MEDIAN_METHOD_TOOLTIP;Pri uporabi "Samo svetlost" in metodi "L*a*b*", se bo filtriranje po mediani izvedlo čisto po koraku valovčkov v zaporedju zmanjšanja šuma.\nOb uporabi načina "RGB" se bo izvedlo na samem koncu zaporedja postopkov za zmanjšanje šuma. +TP_DIRPYRDENOISE_MEDIAN_METHOD_WEIGHTED;Weighted L* (malo) + a*b* (normalno) +TP_DIRPYRDENOISE_MEDIAN_PASSES;Iteracij mediane +TP_DIRPYRDENOISE_MEDIAN_PASSES_TOOLTIP;Uporaba trikratnega filtra mediane v oknu 3×3 pogosto naredi boljši rezultat od ene iteracije filtra mediane na oknu velikosti 7×7. +TP_DIRPYRDENOISE_MEDIAN_TYPE;Tip mediane +TP_DIRPYRDENOISE_MEDIAN_TYPE_TOOLTIP;Uporabi filter mediane na željeni velikosti okna. Večje okno zahteva več časa obdelave.\n\n3×3 mehko: obdela 5 pikslov v oknu 3×3.\n3×3: obdela 9 pikslov v oknu 3×3.\n5×5 mehko: obdela 13 pikslov v oknu 5×5.\n5×5: obdela 25 pikslov v oknu 5×5.\n7×7: obdela 49 pikslov v oknu 7×7.\n9×9: obdela 81 pikslov v oknu 9×9.\n\nVčasih je moč dobiti boljšo kakovost z uporabo večkratnih filtrov na manjšem oknu kot enkratnemu filtru na večjem oknu. +TP_DIRPYRDENOISE_TYPE_3X3;3×3 +TP_DIRPYRDENOISE_TYPE_3X3SOFT;3×3 mehko +TP_DIRPYRDENOISE_TYPE_5X5;5×5 +TP_DIRPYRDENOISE_TYPE_5X5SOFT;5×5 mehko +TP_DIRPYRDENOISE_TYPE_7X7;7×7 +TP_DIRPYRDENOISE_TYPE_9X9;9×9 +TP_DIRPYREQUALIZER_ALGO;Barvni Obseg Kože +TP_DIRPYREQUALIZER_ALGO_TOOLTIP;Fino: bližje barvi kože, minimiziranje učinka na drugih barvah\nVeliko: izogibanje artefaktom. +TP_DIRPYREQUALIZER_ARTIF;Zmanjšanje artefaktov +TP_DIRPYREQUALIZER_HUESKIN;Odtenek kože +TP_DIRPYREQUALIZER_HUESKIN_TOOLTIP;Ta piramida je za gornji del, kjer algoritem deluje maksimalno učinkovito.\nNa spodnjem delu so cone pretvorbe.\nČe želite premakniti področje bistveno na levo ali na desno oz. če se pojavljajo arifakti: je ravnotežje beline napačno. Lahko rahlo zmanjšate cono, da preprečite vplive na ostali del slike. +TP_DIRPYREQUALIZER_LABEL;Kontrast glede nivojev podrobnosti +TP_DIRPYREQUALIZER_LUMACOARSEST;Najbolj grobo +TP_DIRPYREQUALIZER_LUMACONTRAST_MINUS;Kontrast - +TP_DIRPYREQUALIZER_LUMACONTRAST_PLUS;Kontrast + +TP_DIRPYREQUALIZER_LUMAFINEST;Najbolj fino +TP_DIRPYREQUALIZER_LUMANEUTRAL;Nevtralno +TP_DIRPYREQUALIZER_SKIN;Ciljna zaščita kože +TP_DIRPYREQUALIZER_SKIN_TOOLTIP;Pri -100 so ciljani toni kože.\nPri 0 so vsi toni obravnavani enako.\nPri +100 so zaščiteni toni kože, vsi ostali pa so spremenjeni. +TP_DIRPYREQUALIZER_THRESHOLD;Prag +TP_DIRPYREQUALIZER_TOOLTIP;Poskusi zmanjšati artefakte pri spremembi barve kože (odtenek, barvitost, luma) in preostankom slike. +TP_DISTORTION_AMOUNT;Količina +TP_DISTORTION_AUTO_TIP;Avtomatsko popravi popačitve objektiva pri surovih slikah s primerjavo z vgrajeno sliko JPEG, če obstaja in so popravki objektiva izvedeni v fotoaparatu. +TP_DISTORTION_LABEL;Popravek popačenja +TP_EPD_EDGESTOPPING;Zaustavljanje roba +TP_EPD_GAMMA;Gama +TP_EPD_LABEL;Preslikava tonov +TP_EPD_REWEIGHTINGITERATES;Ponovno tehtanje ponovitev +TP_EPD_SCALE;Merilo +TP_EPD_STRENGTH;Moč +TP_EXPOSURE_AUTOLEVELS;Avto nivoji +TP_EXPOSURE_AUTOLEVELS_TIP;Preklaplja izvajanje avto nivojev z vrednostmi izračunani iz analize slike.\nOmogoča rekonstrukcijo bleščav, če je potrebna. +TP_EXPOSURE_BLACKLEVEL;Črna +TP_EXPOSURE_BRIGHTNESS;Svetlost +TP_EXPOSURE_CLAMPOOG;Posnetek barv izven obsega +TP_EXPOSURE_CLIP;Posnetek % +TP_EXPOSURE_CLIP_TIP;Delež pikslov, ki naj bodo posneti v operaciji avto nivoji. +TP_EXPOSURE_COMPRHIGHLIGHTS;Stiskanje bleščav +TP_EXPOSURE_COMPRHIGHLIGHTSTHRESHOLD;Prag stiskanja bleščav +TP_EXPOSURE_COMPRSHADOWS;Stiskanje senc +TP_EXPOSURE_CONTRAST;Kontrast +TP_EXPOSURE_CURVEEDITOR1;Krivulja tonov 1 +TP_EXPOSURE_CURVEEDITOR2;Krivulja tonov 2 +TP_EXPOSURE_CURVEEDITOR2_TOOLTIP;Prosim preberite članek v Rawpediji "Exposure > Tone Curves" kako dosežete najboljše rezultate z uporabo krivulj dveh tonov. +TP_EXPOSURE_EXPCOMP;Prilagoditev ekspozicije +TP_EXPOSURE_HISTMATCHING;Avtomatsko pridobljena krivulja tonov +TP_EXPOSURE_HISTMATCHING_TOOLTIP;Avtomatsko prilagodi drsnike in krivulje (razen prilagoditve ekspozicije) da ustreza videzu vgrajene slike JPEG. +TP_EXPOSURE_LABEL;Ekspozicija +TP_EXPOSURE_SATURATION;Nasičenje +TP_EXPOSURE_TCMODE_FILMLIKE;Kot na filmu +TP_EXPOSURE_TCMODE_LABEL1;Krivulja način 1 +TP_EXPOSURE_TCMODE_LABEL2;Krivulja način 2 +TP_EXPOSURE_TCMODE_LUMINANCE;Svetlost +TP_EXPOSURE_TCMODE_PERCEPTUAL;Glede na zaznavo +TP_EXPOSURE_TCMODE_SATANDVALBLENDING;Nasičenje im mešanje vrednosti +TP_EXPOSURE_TCMODE_STANDARD;Standardno +TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Uteženo standardno +TP_EXPOS_BLACKPOINT_LABEL;Surove črne točke +TP_EXPOS_WHITEPOINT_LABEL;Surove bele točke +TP_FILMNEGATIVE_BLUE;Kvocient modre +TP_FILMNEGATIVE_GREEN;Referenčni eksponent (kontrast) +TP_FILMNEGATIVE_GUESS_TOOLTIP;Izračunajte eksponente tako, da na sliki izberete dve nevtralni referenčni točki; ena bela (svetlo siva) in ena črna (temno siva). Vrstni red ni pomemben. Eksponenti bodo izračunani takoj po izbiri drugega mesta. +TP_FILMNEGATIVE_LABEL;Filmski negativ +TP_FILMNEGATIVE_PICK;Poberite črne in bele točke +TP_FILMNEGATIVE_RED;Kvocient rdeče +TP_FILMSIMULATION_LABEL;Simulacija filma +TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee je nastavljen, da išče slike Hald CLUT, ki so uporabljene za orodje simulacije filma, v mapi, kje potrebujejo preveč časa za nalaganje.\nPojdite v Preference > Obdelava slik > Simulacija filma\n da si ogledate katera mapa je v uporabi. Nastaviti morate RawTherapee tako, da bodisi kaže v mapo, ki vsebuje samo slike Hald CLUT in nič drugega, ali v prazno mapo, če ne želite uporabiti orodja za simulacijo filma.\n\nZa več informacij preberite članek Film Simulation v Rawpediji.\n\nAli želite prekiniti skeniranje? +TP_FILMSIMULATION_STRENGTH;Moč +TP_FILMSIMULATION_ZEROCLUTSFOUND;Nastavi mapo za HaldCLUT v preferencah +TP_FLATFIELD_AUTOSELECT;Avtomatska selekcija +TP_FLATFIELD_BLURRADIUS;Radij zameglevanja +TP_FLATFIELD_BLURTYPE;Tip zameglevanja +TP_FLATFIELD_BT_AREA;Površina +TP_FLATFIELD_BT_HORIZONTAL;Vodoravno +TP_FLATFIELD_BT_VERTHORIZ;Navpično + Vodoravno +TP_FLATFIELD_BT_VERTICAL;Navpično +TP_FLATFIELD_CLIPCONTROL;Kontrola posnetka +TP_FLATFIELD_CLIPCONTROL_TOOLTIP;Kontrola posnetka se izogiba bleščav z uporabo poravnilnika. Če obstaja že nekaj posnetih poravnanih bleščav, lahko ta kontrola vodi k barvemu pridihu. +TP_FLATFIELD_LABEL;Flat-field +TP_GENERAL_11SCALE_TOOLTIP;Učinki tega so vidni in natančno prikazani samo v predogledu merila 1:1. +TP_GRADIENT_CENTER;Center +TP_GRADIENT_CENTER_X;Center X +TP_GRADIENT_CENTER_X_TOOLTIP;Pomakni gradient na levo (negativne vrednosti) ali desno (pozitivne vrednosti). +TP_GRADIENT_CENTER_Y;Center Y +TP_GRADIENT_CENTER_Y_TOOLTIP;Pomakni gradient navzgor (negativne vrednosti) ali dol (pozitivne vrednosti). +TP_GRADIENT_DEGREE;Kot +TP_GRADIENT_DEGREE_TOOLTIP;Kot vrtenja v stopinjah. +TP_GRADIENT_FEATHER;Pero +TP_GRADIENT_FEATHER_TOOLTIP;Širina gradienta v odstotkih diagonale slike. +TP_GRADIENT_LABEL;Postopni filter +TP_GRADIENT_STRENGTH;Moč +TP_GRADIENT_STRENGTH_TOOLTIP;Moč filtra v stopnjah. +TP_HLREC_BLEND;Zmešaj +TP_HLREC_CIELAB;Mešaj v CIELab +TP_HLREC_COLOR;Razmnoževanje barve +TP_HLREC_ENA_TOOLTIP;Je lahko aktivirano z avto nivoji. +TP_HLREC_LABEL;Restavriranje bleščav +TP_HLREC_LUMINANCE;Restavriranje svetlosti +TP_HLREC_METHOD;Metoda: +TP_HSVEQUALIZER_CHANNEL;Kanal +TP_HSVEQUALIZER_HUE;H +TP_HSVEQUALIZER_LABEL;Ekvalizator HSV +TP_HSVEQUALIZER_SAT;S +TP_HSVEQUALIZER_VAL;V +TP_ICM_APPLYBASELINEEXPOSUREOFFSET;Osnovna ekspozicija +TP_ICM_APPLYBASELINEEXPOSUREOFFSET_TOOLTIP;Uporabi vgrajeno osnovno tabelo odmikov DCP. Nastavitev je na voljo samo, če obstaja DCP. +TP_ICM_APPLYHUESATMAP;Osnovna tabela +TP_ICM_APPLYHUESATMAP_TOOLTIP;Uporabi vgrajeno osnovno tabelo DCP (HueSatMap). Nastavitev je na voljo samo če obstaja DCP. +TP_ICM_APPLYLOOKTABLE;Look table +TP_ICM_APPLYLOOKTABLE_TOOLTIP;Uporabi vgrajeno osnovno tabelo vpogledov DCP. Nastavitev je na voljo samo če obstaja DCP. +TP_ICM_BPC;Prilagoditev črne točke +TP_ICM_DCPILLUMINANT;Osvetljevalnik +TP_ICM_DCPILLUMINANT_INTERPOLATED;Interpolirano +TP_ICM_DCPILLUMINANT_TOOLTIP;Izberi katero vgrajeno DCP svetilo uporabiti. Privzeto je "interpolirano", ki je mešanica dveh glede na belino. Nastavitev je na voljo, samo če izbran dvojno osvetlitveni CDP s podporo za interpolacijo. +TP_ICM_INPUTCAMERA;Standardni fotoaparat +TP_ICM_INPUTCAMERAICC;Avtomatično usklajen profil s fotoaparatom +TP_ICM_INPUTCAMERAICC_TOOLTIP;Uporabi RawTherapee-jev specifičen DCP za ta fotoaparat ali vhodni ICC profil. Ti profili so bolj natančni kot enostavni matrični profili, a niso na voljo za vse fotoaparate. Ti profili so shranjeni v mapah /iccprofiles/input in /dcpprofiles in jih razpoznamo iz natančnega imena modela fotoaparata. +TP_ICM_INPUTCAMERA_TOOLTIP;Uporabi enostavno matriko iz dcraw, izboljšano verzijo RawTherapee (katerikoli je na voljo za ta model fotoaparata) ali profil vgrajen v DNG. +TP_ICM_INPUTCUSTOM;Po meri +TP_ICM_INPUTCUSTOM_TOOLTIP;Izberi vaš lastni barvni profil DCP/ICC za fotoaparat. +TP_ICM_INPUTDLGLABEL;Izberi vhodni DCP/ICC Profil... +TP_ICM_INPUTEMBEDDED;Uporabi vgrajenega, če je možno +TP_ICM_INPUTEMBEDDED_TOOLTIP;Uporabi profil vgrajen v ne-surove slike. +TP_ICM_INPUTNONE;Ni profila +TP_ICM_INPUTNONE_TOOLTIP;Ne uporabi nobenega profila.\nUporabi samo v posebnih primerih. +TP_ICM_INPUTPROFILE;Vhodni profil +TP_ICM_LABEL;Upravljanje barv +TP_ICM_NOICM;No ICM: sRGB output +TP_ICM_OUTPUTPROFILE;Izhodni profil +TP_ICM_PROFILEINTENT;Namera upodabljanja +TP_ICM_SAVEREFERENCE;Shrani referenčno sliko +TP_ICM_SAVEREFERENCE_APPLYWB;Uporabi uravnoteženje beline +TP_ICM_SAVEREFERENCE_APPLYWB_TOOLTIP;Na splošno uporabi uravnoteženje beline kadar shranjujete slike za tvorbo ICC profilov, ne porabljajte pa uravnoteženje beline za tvorbo DCP profilov. +TP_ICM_SAVEREFERENCE_TOOLTIP;Shrani linearno sliko TIFF pred uporabo vhodnega profila. Rezultat lahko uporabiš za kalibracijo in tvorbo profila fotoaparata. +TP_ICM_TONECURVE;Krivulja tonov +TP_ICM_TONECURVE_TOOLTIP;Uporabi vgrajeno krivuljo tonov DCP. Nastavitev je na voljo samo, če ima izbran DCP tudi krivuljo tonov. +TP_ICM_WORKINGPROFILE;Delovni profil +TP_ICM_WORKING_TRC;Krivulja tonskih odzivov: +TP_ICM_WORKING_TRC_CUSTOM;Po meri +TP_ICM_WORKING_TRC_GAMMA;Gama +TP_ICM_WORKING_TRC_NONE;Nič +TP_ICM_WORKING_TRC_SLOPE;Strmina +TP_ICM_WORKING_TRC_TOOLTIP;Samo za vgrajene profile. +TP_IMPULSEDENOISE_LABEL;Impulzno zmanjšanje šuma +TP_IMPULSEDENOISE_THRESH;Prag +TP_LABCURVE_AVOIDCOLORSHIFT;Izogibaj se barvnega pomika +TP_LABCURVE_AVOIDCOLORSHIFT_TOOLTIP;Prilagodi barve barvnemu prostoru delovnega barvnega prostora in uporabi Munsellov popravek. +TP_LABCURVE_BRIGHTNESS;Svetlost +TP_LABCURVE_CHROMATICITY;Kromatičnost +TP_LABCURVE_CHROMA_TOOLTIP;Za uporabo črno-belega toniranja nastavi kromatičnost na -100. +TP_LABCURVE_CONTRAST;Kontrast +TP_LABCURVE_CURVEEDITOR;Krivulja osvetljenosti +TP_LABCURVE_CURVEEDITOR_A_RANGE1;Nasičena zelena +TP_LABCURVE_CURVEEDITOR_A_RANGE2;Pastelno zelena +TP_LABCURVE_CURVEEDITOR_A_RANGE3;Pastelno rdeča +TP_LABCURVE_CURVEEDITOR_A_RANGE4;Nasičeno rdeča +TP_LABCURVE_CURVEEDITOR_B_RANGE1;Nasičeno modra +TP_LABCURVE_CURVEEDITOR_B_RANGE2;Pastelno modra +TP_LABCURVE_CURVEEDITOR_B_RANGE3;Pastelno rumena +TP_LABCURVE_CURVEEDITOR_B_RANGE4;Nasičeno rumena +TP_LABCURVE_CURVEEDITOR_CC;CC +TP_LABCURVE_CURVEEDITOR_CC_RANGE1;Nevtralna +TP_LABCURVE_CURVEEDITOR_CC_RANGE2;Dolgočasna +TP_LABCURVE_CURVEEDITOR_CC_RANGE3;Pastelna +TP_LABCURVE_CURVEEDITOR_CC_RANGE4;Nasičena +TP_LABCURVE_CURVEEDITOR_CC_TOOLTIP;Kromatičnost glede na kromatičnost C=f(C) +TP_LABCURVE_CURVEEDITOR_CH;CH +TP_LABCURVE_CURVEEDITOR_CH_TOOLTIP;Kromatičnost glede na odtenek C=f(H) +TP_LABCURVE_CURVEEDITOR_CL;CL +TP_LABCURVE_CURVEEDITOR_CL_TOOLTIP;Kromatičnost glede na svetlost C=f(L) +TP_LABCURVE_CURVEEDITOR_HH;HH +TP_LABCURVE_CURVEEDITOR_HH_TOOLTIP;Odtenek glede na odtenek H=f(H) +TP_LABCURVE_CURVEEDITOR_LC;LC +TP_LABCURVE_CURVEEDITOR_LC_TOOLTIP;Svetlost glede na kromatičnost L=f(C) +TP_LABCURVE_CURVEEDITOR_LH;LH +TP_LABCURVE_CURVEEDITOR_LH_TOOLTIP;Svetlost glede na odtenek L=f(H) +TP_LABCURVE_CURVEEDITOR_LL_TOOLTIP;Svetlost glede na svetlost L=f(L) +TP_LABCURVE_LABEL;Prilagoditve L*a*b* +TP_LABCURVE_LCREDSK;Omeji LC na rdečo in kožne barve +TP_LABCURVE_LCREDSK_TIP;Če je aktivna, krivulja LC vpliva samo na rdečo in kožne barve.\nČe je onemogočen, se nanaša na vse tone. +TP_LABCURVE_RSTPROTECTION;Zaščita rdeče in kožnih barv +TP_LABCURVE_RSTPRO_TOOLTIP;Deluje na drsniku kromatičnost in krivulji CC. +TP_LENSGEOM_AUTOCROP;Avtomatska obrezava +TP_LENSGEOM_FILL;Avtomatsko popolnitev +TP_LENSGEOM_LABEL;Objektiv / geometrija +TP_LENSPROFILE_CORRECTION_AUTOMATCH;Avtomatično izbrano +TP_LENSPROFILE_CORRECTION_LCPFILE;datoteka LCP +TP_LENSPROFILE_CORRECTION_MANUAL;Ročno izbrano +TP_LENSPROFILE_LABEL;Popravek objektiva s profilom +TP_LENSPROFILE_LENS_WARNING;Opozorilo: faktor obrezave za objektiv je večje od faktorja obrezave za fotoaparat, rezultat utegne biti napačen. +TP_LENSPROFILE_MODE_HEADER;Profil objektiva +TP_LENSPROFILE_USE_CA;Kromatska aberacija +TP_LENSPROFILE_USE_GEOMETRIC;Geometrično popačenje +TP_LENSPROFILE_USE_HEADER;Popravi +TP_LENSPROFILE_USE_VIGNETTING;Vinjetiranje +TP_LOCALCONTRAST_AMOUNT;Količina +TP_LOCALCONTRAST_DARKNESS;Nivo temine +TP_LOCALCONTRAST_LABEL;Lokalni kontrast +TP_LOCALCONTRAST_LIGHTNESS;Nivo svetlosti +TP_LOCALCONTRAST_RADIUS;Radij +TP_METADATA_EDIT;Izvedi spremembe +TP_METADATA_MODE;Način kopiranja metapodatkov +TP_METADATA_STRIP;Odstrani vse metapodatke +TP_METADATA_TUNNEL;Kopiraj nespremenjeno +TP_NEUTRAL;Ponastavi +TP_NEUTRAL_TIP;Ponastavi drsnike ekspozicije v nevtralno stanje.\nUporablja enake parametre kot pri Avtomatskih nivojih, ne glede na to ali so uporabljeni ali ne.. +TP_PCVIGNETTE_FEATHER;Pero +TP_PCVIGNETTE_FEATHER_TOOLTIP;Perje:\n0 = samo vogali,\n50 = na polovici do centra,\n100 = v centru. +TP_PCVIGNETTE_LABEL;Filter vinjetiranja +TP_PCVIGNETTE_ROUNDNESS;Okroglina +TP_PCVIGNETTE_ROUNDNESS_TOOLTIP;Okroglina:\n0 = pravokotnik,\n50 = včrtana elipsa,\n100 = krog. +TP_PCVIGNETTE_STRENGTH;Moč +TP_PCVIGNETTE_STRENGTH_TOOLTIP;Moč filtra v stopnjah (uporabljeno v vogalih). +TP_PDSHARPENING_LABEL;Ujemite ostrenje +TP_PERSPECTIVE_HORIZONTAL;Vodoravno +TP_PERSPECTIVE_LABEL;Perspektiva +TP_PERSPECTIVE_VERTICAL;Navpično +TP_PFCURVE_CURVEEDITOR_CH;Ostanek +TP_PFCURVE_CURVEEDITOR_CH_TOOLTIP;Kontrolira moč ostranjevanja artefaktov.\nVisoko = več,\nNizko = manj. +TP_PREPROCESS_DEADPIXFILT;Filter mrtvih pikslov +TP_PREPROCESS_DEADPIXFILT_TOOLTIP;Poskuša odstraniti mrtve piksle. +TP_PREPROCESS_GREENEQUIL;Uravnoteženje zelene +TP_PREPROCESS_HOTPIXFILT;Filter vročih pikslov +TP_PREPROCESS_HOTPIXFILT_TOOLTIP;Poskuša odstraniti vroče piksle. +TP_PREPROCESS_LABEL;Predobdelava +TP_PREPROCESS_LINEDENOISE;Filter linijskega šuma +TP_PREPROCESS_LINEDENOISE_DIRECTION;Smer +TP_PREPROCESS_LINEDENOISE_DIRECTION_BOTH;Obe +TP_PREPROCESS_LINEDENOISE_DIRECTION_HORIZONTAL;Vodoravno +TP_PREPROCESS_LINEDENOISE_DIRECTION_PDAF_LINES;Voporavno samo na vrsticah PDAF +TP_PREPROCESS_LINEDENOISE_DIRECTION_VERTICAL;Navpično +TP_PREPROCESS_NO_FOUND;Noben ni najden +TP_PREPROCESS_PDAFLINESFILTER;Linijski filter PDAF +TP_PRSHARPENING_LABEL;Ostrenje po spremembi velikosti +TP_PRSHARPENING_TOOLTIP;Naostri sliko po spremembi velikosti. Deluje samo z metodo "Lanczos". Nemogoče je izvesti predogled tega postopka. Glej Rawpedijo za navodila za uporabo. +TP_RAWCACORR_AUTO;Avtomatski popravki +TP_RAWCACORR_AUTOIT;Iteracije +TP_RAWCACORR_AUTOIT_TOOLTIP;Ta nastavitev je na voljo, če je omogočen "Avto-popravek"\nAvto-popravek je konzervativen, kar pomeni, da pogosto ne popravi vse kromatske aberacije.\nZa popravek preostale kromatske aberacije lahko uporabiš do pet iteracij avtomatske kromatske aberacije.\nVsaka iteracija bo zmanjšala preostalo kromatsko aberacijo glede na prejšnjo na račun dodatnega časa za obdelavo. +TP_RAWCACORR_AVOIDCOLORSHIFT;Izogibaj se pomiku barve +TP_RAWCACORR_CABLUE;Modra +TP_RAWCACORR_CARED;Rdeča +TP_RAWCACORR_LABEL;Popravek kromatske aberacije +TP_RAWEXPOS_BLACK_0;Zelena 1 (vodilna) +TP_RAWEXPOS_BLACK_1;Rdeča +TP_RAWEXPOS_BLACK_2;Modra +TP_RAWEXPOS_BLACK_3;Zelena 2 +TP_RAWEXPOS_BLACK_BLUE;Modra +TP_RAWEXPOS_BLACK_GREEN;Zelena +TP_RAWEXPOS_BLACK_RED;Rdeča +TP_RAWEXPOS_LINEAR;Popravek bele točke +TP_RAWEXPOS_RGB;Rdeča, Zelena, Modra +TP_RAWEXPOS_TWOGREEN;Poveži zelene +TP_RAW_1PASSMEDIUM;1-pass (Markesteijn) +TP_RAW_2PASS;1-pass+fast +TP_RAW_3PASSBEST;3-pass (Markesteijn) +TP_RAW_4PASS;3-prehodi+hitri +TP_RAW_AHD;AHD +TP_RAW_AMAZE;AMaZE +TP_RAW_AMAZEVNG4;AMaZE+VNG4 +TP_RAW_BORDER;Meja +TP_RAW_DCB;DCB +TP_RAW_DCBENHANCE;DCB izboljšava +TP_RAW_DCBITERATIONS;Število iteracij DCB +TP_RAW_DCBVNG4;DCB+VNG4 +TP_RAW_DMETHOD;Metoda +TP_RAW_DMETHOD_PROGRESSBAR;%1 odstranjevanje mozaičnosti... +TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Izboljšava odstranejvanja mozaičnosti... +TP_RAW_DMETHOD_TOOLTIP;Opomba: IGV in LMMSE sta namenjeni slikam z visokim ISO za pomoč pri odstranjevanju šuma ne da bi povzročali vzorce v obliki labirintov posterizacije ali izpranega videza.\nPomik pikslov je samo za datoteke Pentax/Sony Pixel Shift. Pri drugih datotekah je namesto tega uporabljen AMaZE. +TP_RAW_DUALDEMOSAICAUTOCONTRAST;Avtomatični prag +TP_RAW_DUALDEMOSAICAUTOCONTRAST_TOOLTIP;Če je ta opcija vključena (priporočljivo), RawTherapee izračuna optimalno vrednost glede na gladke dele slike.\nČe ni gladkega dela slike ali pa če je slika preveč šumna, bo vrednost postavljena na 0.\nČe želiš postaviti vrednost ročno, najprej izključi opcijo (primerna vrednost je odvisna od slike). +TP_RAW_DUALDEMOSAICCONTRAST;Prag kontrasta +TP_RAW_EAHD;EAHD +TP_RAW_FALSECOLOR;Število korakov zatiranja napačnih barv +TP_RAW_FAST;Hitro +TP_RAW_HD;Prag +TP_RAW_HD_TOOLTIP;Nizke vrednosti bodo bolj agresivno določale vroče/mrtve piksle in lažne točke bodo pridelale artefakte. Če opazite pojav artefaktov, ko ste omogočili filter vročih/mrtvih pikslov, postopno povečajte vrednost praga, dokler artefakti ne izginejo. +TP_RAW_HPHD;HPHD +TP_RAW_IGV;IGV +TP_RAW_IMAGENUM;Po-slika +TP_RAW_IMAGENUM_SN;SN način +TP_RAW_IMAGENUM_TOOLTIP;Nekatere surove slike vsebujejo več podslik (Pentax/Sony Pixel Shift, Pentax 3-in-1 HDR, Canon Dual Pixel, Fuji EXR).\n\nKadar uporabljate katerokoli metodo razen pomika pikslov, to določa katera podslika bo uporabljena.\n\nKadar uporabiš pomik pikslov na surovi sliki, so uporabljene vse podslike in to določa, katera podslika naj bo uporabljena za gibajoče dele. +TP_RAW_LABEL;Odstranjevanje mozaičnosti +TP_RAW_LMMSE;LMMSE +TP_RAW_LMMSEITERATIONS;LMMSE koraki izboljševanja +TP_RAW_LMMSE_TOOLTIP;Dodaj gamo (korak 1), mediano (koraki 2-4) in izboljševanje (koraka 5-6) za zmanjševanje artefaktov in izboljšanje razmerja signal šum. +TP_RAW_MONO;Mono +TP_RAW_NONE;None (Prikaži vzorec senzorja) +TP_RAW_PIXELSHIFT;Pomik pikslov +TP_RAW_PIXELSHIFTBLUR;Zamegli maska gibanja +TP_RAW_PIXELSHIFTDMETHOD;Metoda Odstranjevanja mozaičnosti +TP_RAW_PIXELSHIFTEPERISO;Občutljivost +TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;Privzeta vrednost 0 bi morala delovati za osnovni ISO.\nVišje vrednosti povečajo občutljivost za detekcijo gibanja.\nSpreminjajte počasi in opazujte masko gibanja.\nPovečajte občutljivost za podosvetljene slike ali slike z visokim ISO. +TP_RAW_PIXELSHIFTEQUALBRIGHT;Izenači svetlost okvirjev +TP_RAW_PIXELSHIFTEQUALBRIGHTCHANNEL;Izenači po kanalih +TP_RAW_PIXELSHIFTEQUALBRIGHTCHANNEL_TOOLTIP;Omogočeno: Izenači kanale RGB neodvisno.\nOnemogočeno: Uporabi enak faktor izenačevanja za vse kanale. +TP_RAW_PIXELSHIFTEQUALBRIGHT_TOOLTIP;Izenači svetlost okvirjev svetlosti izbranega okvirja.\nČe obstajajo preosvetljeni deli okvirjev, izberite najsvetlejšega, da se izognete barvnemu tonu magente pri preosvetljenih delih ali da omogočite popravke gibanja. +TP_RAW_PIXELSHIFTGREEN;Preveri zeleni kanal za gibanje +TP_RAW_PIXELSHIFTHOLEFILL;Zapolni luknje v maski gibanja +TP_RAW_PIXELSHIFTHOLEFILL_TOOLTIP;Zapolni luknje v maski gibanja +TP_RAW_PIXELSHIFTMEDIAN;Uporabi mediano za gibajoče se dele +TP_RAW_PIXELSHIFTMEDIAN_TOOLTIP;Uporabi mediano za vse okvirje namesto izbranega okvirja za dele z gibanjem.\nDaje efekt gibanja na počasi gibajočin (prekrivajočih se) predmetih. +TP_RAW_PIXELSHIFTMM_AUTO;Avtomatično +TP_RAW_PIXELSHIFTMM_CUSTOM;Po meri +TP_RAW_PIXELSHIFTMM_OFF;Izklopljeno +TP_RAW_PIXELSHIFTMOTIONMETHOD;Popravek gibanja +TP_RAW_PIXELSHIFTNONGREENCROSS;Preveri rdeč/moder kanal za gibanje +TP_RAW_PIXELSHIFTSHOWMOTION;Prikaži masko gibanja +TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY;Prikaži samo masko gibanja +TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY_TOOLTIP;Prikaže masko gibanja brez slike. +TP_RAW_PIXELSHIFTSHOWMOTION_TOOLTIP;Prekrij sliko z zeleno masko, ki prikazuje področja z gibanjem. +TP_RAW_PIXELSHIFTSIGMA;Radij zameglevanja +TP_RAW_PIXELSHIFTSIGMA_TOOLTIP;Privzet radij 1.0 običajno ustreza osnovnem ISO.\nVrednost povečajte za visok ISO, 5.0 je dobra začetna vrednost.\nOpazujte masko gibanja, ko spreminjate vrednost. +TP_RAW_PIXELSHIFTSMOOTH;Gladki prehodi +TP_RAW_PIXELSHIFTSMOOTH_TOOLTIP;Gladki prehodi med področji z gibanjem in področji brez.\nPostavite na 1, da dobite rezultat AMaZE/LMMSE za izbran okvir (odvisno ali je izbran "Uporabi LMMSE") ali mediana za vse štiri okvire, če je izbran "Uporabi mediano". +TP_RAW_RCD;RCD +TP_RAW_RCDVNG4;RCD+VNG4 +TP_RAW_SENSOR_BAYER_LABEL;Senzor z matriko Bayer +TP_RAW_SENSOR_XTRANS_DMETHOD_TOOLTIP;3-prehodi daje boljše rezultate (priporočljivo za nizek ISO).\n1-prehod je komaj različen od 3-prehodov za visoke ISO slike in je hitrejši.\n+fast daje manj artefaktov v gladkih predelih +TP_RAW_SENSOR_XTRANS_LABEL;Senzor z matriko X-Trans +TP_RAW_VNG4;VNG4 +TP_RAW_XTRANS;X-Trans +TP_RAW_XTRANSFAST;Fast X-Trans +TP_RESIZE_ALLOW_UPSCALING;Dovoli povečavo +TP_RESIZE_APPLIESTO;Se nanaša na: +TP_RESIZE_CROPPEDAREA;Izrezano področje +TP_RESIZE_FITBOX;Bounding Box +TP_RESIZE_FULLIMAGE;Celotna slika +TP_RESIZE_H;Višina: +TP_RESIZE_HEIGHT;Višina +TP_RESIZE_LABEL;Spremeni velikost +TP_RESIZE_LANCZOS;Lanczos +TP_RESIZE_METHOD;Metoda: +TP_RESIZE_NEAREST;Najbližji +TP_RESIZE_SCALE;Merilo +TP_RESIZE_SPECIFY;Opiši: +TP_RESIZE_W;Širina: +TP_RESIZE_WIDTH;Širina +TP_RETINEX_CONTEDIT_HSL;HSL histogram +TP_RETINEX_CONTEDIT_LAB;L*a*b* histogram +TP_RETINEX_CONTEDIT_LH;Odtenek +TP_RETINEX_CONTEDIT_MAP;Izenačevalnik +TP_RETINEX_CURVEEDITOR_CD;L=f(L) +TP_RETINEX_CURVEEDITOR_CD_TOOLTIP;Svetlost glede na svetlost L=f(L)\nPopravi surove podatke, da zmanjšaš odboje in artefakte. +TP_RETINEX_CURVEEDITOR_LH;Moč=f(H) +TP_RETINEX_CURVEEDITOR_LH_TOOLTIP;Moč glede na odtenek Moč=f(H)\nTa krivulja deluje tudi na barvitosti kadar uporabljamo metodo Retinex na bleščavah. +TP_RETINEX_CURVEEDITOR_MAP;L=f(L) +TP_RETINEX_CURVEEDITOR_MAP_TOOLTIP;To krivuljo lahko uporabimo samo ali pa z Gaussovo masko ali masko valovčkov.\nPazite na artefakte! +TP_RETINEX_EQUAL;Izenačevalnik +TP_RETINEX_FREEGAMMA;Prosta gama +TP_RETINEX_GAIN;Ojačenje +TP_RETINEX_GAINOFFS;Ojačenje in odmik (svetlost) +TP_RETINEX_GAINTRANSMISSION;Prenos ojačenja +TP_RETINEX_GAINTRANSMISSION_TOOLTIP;Ojačaj ali oslabi prenosno funkcijo da dosežete željeno svetlost.\nOs x je prenos.\nOs y je ojačenje. +TP_RETINEX_GAMMA;Gama +TP_RETINEX_GAMMA_FREE;Prost +TP_RETINEX_GAMMA_HIGH;Visok +TP_RETINEX_GAMMA_LOW;Nizek +TP_RETINEX_GAMMA_MID;Srednji +TP_RETINEX_GAMMA_NONE;Nič +TP_RETINEX_GAMMA_TOOLTIP;Obnovi tone z uporabo game pred ali po Retinexu. Krivulje so drugačne od Retinexovih ali drugih (Lab, Ekspozicija, itd.). +TP_RETINEX_GRAD;Gradient prenosa +TP_RETINEX_GRADS;Moč gradienta +TP_RETINEX_GRADS_TOOLTIP;Če je drsnik na 0, so vse iteracije identične.\nČe je > 0 moč pojema pri vsaki iteraciji in obratno. +TP_RETINEX_GRAD_TOOLTIP;Če je drsnik na 0, so vse iteracije identične.\nČe je > 0 Varianca in Prag pojemata pri vsaki iteraciji in obratno. +TP_RETINEX_HIGH;Visoko +TP_RETINEX_HIGHLIG;Bleščava +TP_RETINEX_HIGHLIGHT;Prag bleščave +TP_RETINEX_HIGHLIGHT_TOOLTIP;Poveča aktivnosti visokega algoritma.\nMorda bo zahtevala prilagoditev "Sosednjih pikslov" in povečanje "Popravka bele točke" v orodju v zavihku Surove -> Orodju Surova Bela Točka. +TP_RETINEX_HSLSPACE_LIN;HSL-Linearno +TP_RETINEX_HSLSPACE_LOG;HSL-Logaritmično +TP_RETINEX_ITER;Iteracije (Preslikava tonov) +TP_RETINEX_ITERF;Preslikava tonov +TP_RETINEX_ITER_TOOLTIP;Simuliraj operacijo preslikave tonov.\nVisoke vrednosti povečujejo čas obdelave. +TP_RETINEX_LABEL;Retinex +TP_RETINEX_LABEL_MASK;Maska +TP_RETINEX_LABSPACE;L*a*b* +TP_RETINEX_LOW;Nizko +TP_RETINEX_MAP;Metoda +TP_RETINEX_MAP_GAUS;Gaussova maska +TP_RETINEX_MAP_MAPP;Maska ostrenja (delni valovčki) +TP_RETINEX_MAP_MAPT;Maska ostrenja (popolni valovčki) +TP_RETINEX_MAP_METHOD_TOOLTIP;Uporabi masko, ki ga je generirala gornja Gaussova funkcija (Radin, Metoda) za zmanjševanja odbojev in artefaktov.\n\nSamo krivulja: uporabi diagonalni kontrast na maski.\nPazite na artefakte!\n\nGaussova maska: tvori in uporabi Gaussovo zameglitev izvorne maske.\nHitro.\n\nMaska ostrenja: tvori in uporabi valovčke na izvorni maski.\nPočasno. +TP_RETINEX_MAP_NONE;Nič +TP_RETINEX_MEDIAN;Fiter mediane prenosa +TP_RETINEX_METHOD;Metoda +TP_RETINEX_METHOD_TOOLTIP;Low = Ojačaj šibko svetlobo.\nEnakomerno = Izenači.\nVisoko = Ojačaj močno svetlobo.\nBleščave = Odstrani magento iz bleščav. +TP_RETINEX_MLABEL;Obnovi brez meglic Min=%1 Max=%2 +TP_RETINEX_MLABEL_TOOLTIP;Mora biti blizu min=0 max=32768\nObnovljena slika brez mešanja. +TP_RETINEX_NEIGHBOR;Radij +TP_RETINEX_NEUTRAL;Ponastavi +TP_RETINEX_NEUTRAL_TIP;Ponastavi vse drsnike in klrivulje na njihove privzete vrednosti. +TP_RETINEX_OFFSET;Odmik (svetlost) +TP_RETINEX_SCALES;Gaussov gradient +TP_RETINEX_SCALES_TOOLTIP;Če je drsnik na 0, so vse iteracije identične.\nČe je > 0 merilo in radij pojemata pri vsaki iteraciji in obratno. +TP_RETINEX_SETTINGS;Nastavitve +TP_RETINEX_SKAL;Merilo +TP_RETINEX_SLOPE;Prosta strmina game +TP_RETINEX_STRENGTH;Moč +TP_RETINEX_THRESHOLD;Prag +TP_RETINEX_THRESHOLD_TOOLTIP;Omejuje vhod/izhod.\nVhod = izvorna slika,\nIzhod = slika po Gaussu. +TP_RETINEX_TLABEL;TM Min=%1 Max=%2 Povprečje=%3 Sigma=%4 +TP_RETINEX_TLABEL2;TM Tm=%1 TM=%2 +TP_RETINEX_TLABEL_TOOLTIP;Transmission map result.\nMin and Max are used by Variance.\nMean and Sigma.\nTm=Min TM=Max of transmission map. +TP_RETINEX_TRANF;Prenos +TP_RETINEX_TRANSMISSION;Prenosna funkcija +TP_RETINEX_TRANSMISSION_TOOLTIP;Prenos glede na prenos.\nAbscisa: prenos negativnih vrednosti (min), povprečja, in pozitivnih vrednosti (max).\nOrdinata: ojačenje ali slabljenje. +TP_RETINEX_UNIFORM;Enakomerno +TP_RETINEX_VARIANCE;Kontrast +TP_RETINEX_VARIANCE_TOOLTIP;Nizka varianca povečuje lokalni kontrast in nasičenje, toda lahko tvori artefakte. +TP_RETINEX_VIEW;Obdelava +TP_RETINEX_VIEW_MASK;Maska +TP_RETINEX_VIEW_METHOD_TOOLTIP;Standardno - Normalen prikaz.\nMaska - Prikazuje masko.\nNeostra maska - Prikaže sliko z neostro masko z velikim radijem.\nPrenos - Avto/Fiksno - Prikaže prenosno funkcijo pred kakršnimkoli posegom na kontrastu ali svetlosti.\n\nPozor: maska ni realistična, ampak je ojačana, da se bolje vidi. +TP_RETINEX_VIEW_NONE;Standardno +TP_RETINEX_VIEW_TRAN;Prenos - Avto +TP_RETINEX_VIEW_TRAN2;Prenos - Fiksno +TP_RETINEX_VIEW_UNSHARP;Neostra maska +TP_RGBCURVES_BLUE;B +TP_RGBCURVES_CHANNEL;Kanal +TP_RGBCURVES_GREEN;G +TP_RGBCURVES_LABEL;RGB krivulje +TP_RGBCURVES_LUMAMODE;Način svetilnosti +TP_RGBCURVES_LUMAMODE_TOOLTIP;Način svetilnosti dovoljuje spreminjanje prispevka kanalov R, G in B na svetlost slike, ne da bi spreminjali barve slike. +TP_RGBCURVES_RED;R +TP_ROTATE_DEGREE;Stopnja +TP_ROTATE_LABEL;Zavrti +TP_ROTATE_SELECTLINE;Izberi ravno črto +TP_SAVEDIALOG_OK_TIP;Bližnjica: Ctrl-Enter +TP_SHADOWSHLIGHTS_HIGHLIGHTS;Bleščave +TP_SHADOWSHLIGHTS_HLTONALW;Tonska širina bleščav +TP_SHADOWSHLIGHTS_LABEL;Sence/bleščave +TP_SHADOWSHLIGHTS_RADIUS;Radij +TP_SHADOWSHLIGHTS_SHADOWS;Sence +TP_SHADOWSHLIGHTS_SHTONALW;Tonska širina senc +TP_SHARPENEDGE_AMOUNT;Količina +TP_SHARPENEDGE_LABEL;Robovi +TP_SHARPENEDGE_PASSES;Iteracij +TP_SHARPENEDGE_THREE;Samo svetlost +TP_SHARPENING_AMOUNT;Količina +TP_SHARPENING_BLUR;Radij zamegljevanja +TP_SHARPENING_CONTRAST;Prag kontrasta +TP_SHARPENING_EDRADIUS;Radij +TP_SHARPENING_EDTOLERANCE;Toleranca robov +TP_SHARPENING_GAMMA;Gama +TP_SHARPENING_HALOCONTROL;Kontrola odbojev +TP_SHARPENING_HCAMOUNT;Količina +TP_SHARPENING_LABEL;Ostrenje +TP_SHARPENING_METHOD;Metoda +TP_SHARPENING_ONLYEDGES;Naostri samo robove +TP_SHARPENING_RADIUS;Radij +TP_SHARPENING_RADIUS_BOOST;Povečanje polmera vogala +TP_SHARPENING_RLD;RL Dekonvolucija +TP_SHARPENING_RLD_AMOUNT;Količina +TP_SHARPENING_RLD_DAMPING;Blaženje +TP_SHARPENING_RLD_ITERATIONS;Iteracij +TP_SHARPENING_THRESHOLD;Prag +TP_SHARPENING_USM;Neostra maska +TP_SHARPENMICRO_AMOUNT;Količina +TP_SHARPENMICRO_CONTRAST;Prag kontrasta +TP_SHARPENMICRO_LABEL;Mikrokontrast +TP_SHARPENMICRO_MATRIX;3×3 matrika namesto 5×5 +TP_SHARPENMICRO_UNIFORMITY;Enakomernost +TP_SOFTLIGHT_LABEL;Mehka svetloba +TP_SOFTLIGHT_STRENGTH;Moč +TP_TM_FATTAL_AMOUNT;Količina +TP_TM_FATTAL_ANCHOR;Sidro +TP_TM_FATTAL_LABEL;Kompresija dinamičnega obsega +TP_TM_FATTAL_THRESHOLD;Podrobnost +TP_VIBRANCE_AVOIDCOLORSHIFT;Izogibaj se pomiku barve +TP_VIBRANCE_CURVEEDITOR_SKINTONES;HH +TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL;Kožni toni +TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE1;rdeča/rožnata +TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE2;rdeča +TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE3;rdeča/rumena +TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE4;rumena +TP_VIBRANCE_CURVEEDITOR_SKINTONES_TOOLTIP;Odtenek glede na odtenek H=f(H) +TP_VIBRANCE_LABEL;Živost +TP_VIBRANCE_PASTELS;Pastelni toni +TP_VIBRANCE_PASTSATTOG;Poveži pastelne in nasičene tone +TP_VIBRANCE_PROTECTSKINS;Zaščiti kožne tone +TP_VIBRANCE_PSTHRESHOLD;Prag pastelnih/nasičenih tonov +TP_VIBRANCE_PSTHRESHOLD_SATTHRESH;Prag nasičenja +TP_VIBRANCE_PSTHRESHOLD_TOOLTIP;Navpična os predstavlja pestelne tone spodaj in nasičene tone na vrhu.\nVodoravna os predstavlja obseg nasičenja. +TP_VIBRANCE_PSTHRESHOLD_WEIGTHING;Utež prenosa pastelno/nasičeno +TP_VIBRANCE_SATURATED;Nasičeni toni +TP_VIGNETTING_AMOUNT;Količina +TP_VIGNETTING_CENTER;Center +TP_VIGNETTING_CENTER_X;Center X +TP_VIGNETTING_CENTER_Y;Center Y +TP_VIGNETTING_LABEL;Popravek vinjetiranja +TP_VIGNETTING_RADIUS;Radij +TP_VIGNETTING_STRENGTH;Moč +TP_WAVELET_1;Nivo 1 +TP_WAVELET_2;Nivo 2 +TP_WAVELET_3;Nivo 3 +TP_WAVELET_4;Nivo 4 +TP_WAVELET_5;Nivo 5 +TP_WAVELET_6;Nivo 6 +TP_WAVELET_7;Nivo 7 +TP_WAVELET_8;Nivo 8 +TP_WAVELET_9;Nivo 9 +TP_WAVELET_APPLYTO;Uporabi na +TP_WAVELET_AVOID;Izogibaj se pomiku barv +TP_WAVELET_B0;Črna +TP_WAVELET_B1;Siva +TP_WAVELET_B2;Preostanek +TP_WAVELET_BACKGROUND;Ozadje +TP_WAVELET_BACUR;Krivulja +TP_WAVELET_BALANCE;Ravnotežje kontrasta d/v-h +TP_WAVELET_BALANCE_TOOLTIP;Spremeni ravnotežje med smermi valovčkov: navpično-vodoravno in diagonalno.\nČe so omogočeni kontrast, barvitost ali preostali prenos tonov, je učinek ojačan. +TP_WAVELET_BALCHRO;Ravnotežje barvitosti +TP_WAVELET_BALCHRO_TOOLTIP;Če je omogočen potem krivulja ravnotežja kontrasta ali drsnik tudi spreminja ravnotežje barvitosti. +TP_WAVELET_BANONE;Nič +TP_WAVELET_BASLI;Drsnik +TP_WAVELET_BATYPE;Metoda ravnotežja kontrasta +TP_WAVELET_CBENAB;Ravnotežje tonov in barve +TP_WAVELET_CB_TOOLTIP;Za močne vrednosti barvno toniranje izdelka, če ga kombinirate ali ne s stopnjami razkroja 'toniranje'\nZa nizke vrednosti lahko spremenite ravnovesje beline v ozadju (nebo, ...), ne da bi spremenili stanje sprednje ravnine, na splošno bolj kontrastno +TP_WAVELET_CCURVE;Lokalni kontrast +TP_WAVELET_CH1;Obseg vse barvitosti +TP_WAVELET_CH2;Nasičena/pastelna +TP_WAVELET_CH3;Nivoji povezav kontrastov +TP_WAVELET_CHCU;Krivulja +TP_WAVELET_CHR;Moč povezave barvitosti in kontrasta +TP_WAVELET_CHRO;Prag nasičenja/pastelnosti +TP_WAVELET_CHRO_TOOLTIP;Nastavi nivo valovčkov, ki določa prag med nasičenimi in pastelnimi barvami.\n1-x: nasičene\nx-9: pastelne\n\nČe vrednost presega štvilo nivojev valovčkov, ki jih uporabljate, vrednost zanemarimo. +TP_WAVELET_CHR_TOOLTIP;Prilagodi barvitost kot funkcijo "nivojev kontrasta" in "moč povezave barvitost-kontrast" +TP_WAVELET_CHSL;Drsniki +TP_WAVELET_CHTYPE;Metoda krominance +TP_WAVELET_COLORT;Neprosojnost rdeče-zelene +TP_WAVELET_COMPCONT;Kontrast +TP_WAVELET_COMPGAMMA;Stiskanje game +TP_WAVELET_COMPGAMMA_TOOLTIP;Prilagoditev game preostanka slike dovoljuje uravnoteženje podatkov in histograma. +TP_WAVELET_COMPTM;Prenosna funkcija tonov +TP_WAVELET_CONTEDIT;Krivulja kontrasta "Po" +TP_WAVELET_CONTR;Barvni obseg +TP_WAVELET_CONTRA;Kontrast +TP_WAVELET_CONTRAST_MINUS;Kontrast - +TP_WAVELET_CONTRAST_PLUS;Kontrast + +TP_WAVELET_CONTRA_TOOLTIP;Spremeni kontrast preostanka slike. +TP_WAVELET_CTYPE;Kontrola krominance +TP_WAVELET_CURVEEDITOR_CC_TOOLTIP;Spremeni lokalni kontrast kot funkcijo izvirnega lokalnega kontrasta (abscisa).\nSpodnje vrednosti na abscisi predstavljajo majhne izvirne lokalne kontraste (vrednosti med 100 in 300).\n66% na abscisi predstavlja standardno deviacijo lokalnih kontrastov (vrednosti med 300 in 800)\n100% na abscisi pa predstavlja maksimalne lokalne kontraste (vrednosti med 3000 in 8000). +TP_WAVELET_CURVEEDITOR_CH;Kontrast nivoji=f(Odtenek) +TP_WAVELET_CURVEEDITOR_CH_TOOLTIP;Spremeni kontrast vsake stopnje kot funkcijo odtenka.\nPazite, da ne boste prepisali sprememb, izvedenih s krmilnimi odtenki podorodja Gamut.\nKrivulja bo imela učinek le, če so drsniki na ravni valovnih kontrastov brez ničle. +TP_WAVELET_CURVEEDITOR_CL;L +TP_WAVELET_CURVEEDITOR_CL_TOOLTIP;Uporabi končno krivuljo svetilnosti kontrasta na koncu obdelave z valovčki. +TP_WAVELET_CURVEEDITOR_HH;HH +TP_WAVELET_CURVEEDITOR_HH_TOOLTIP;Spremeni odtenek preostale slike kot funkcijo odtenka. +TP_WAVELET_DALL;Vse smeri +TP_WAVELET_DAUB;Performance robov +TP_WAVELET_DAUB2;D2 - nizko +TP_WAVELET_DAUB4;D4 - standard +TP_WAVELET_DAUB6;D6 - standard plus +TP_WAVELET_DAUB10;D10 - srednje +TP_WAVELET_DAUB14;D14 - visoko +TP_WAVELET_DAUB_TOOLTIP;Spremeni Daubechiesove koeficiente:\nD4 = Standardno,\nD14 = Pogosto najboljše, 10% bolj časovno zahetvno.\n\nVpliva na razpoznavanje robov kot tudi splošno kakovost prvih nivojev. Kljub temu splošna kakovost ni strogo odvisna od tega koeficienta in se lahko spremeni v odvisnosti od slik in uporabe. +TP_WAVELET_DONE;Navpično +TP_WAVELET_DTHR;Diagonalno +TP_WAVELET_DTWO;Vodoravno +TP_WAVELET_EDCU;Krivulja +TP_WAVELET_EDGCONT;Lokalni kontrast +TP_WAVELET_EDGCONT_TOOLTIP;Prilagoditev točk na levi zmanjšuje kontrast in na desni ga povečuje.\nSpodaj-levo, zgoraj-levo, zgoraj-desno in spodaj-desno predstavljajo lokalni kontrast za nizke vrednosti, povprečje, povprečje+stdev in maximum. +TP_WAVELET_EDGE;Ostrina roba +TP_WAVELET_EDGEAMPLI;Osnovno ojačenje +TP_WAVELET_EDGEDETECT;Gradient občutljivosti +TP_WAVELET_EDGEDETECTTHR;Spodnji prag (šum) +TP_WAVELET_EDGEDETECTTHR2;Zgornji prag (občutljivost) +TP_WAVELET_EDGEDETECTTHR_TOOLTIP;Ta prilagojevalnik omogoča ciljno detekcijo robov za izogibanje ostrine robov na finih podrobnostih kot npr. šum na nebu. +TP_WAVELET_EDGEDETECT_TOOLTIP;Pomik drsnika na desno poveča občutljivost za robove. To vpliva na lokalni kontrast, nastavitve robov in šum. +TP_WAVELET_EDGESENSI;Rob občutljivosti +TP_WAVELET_EDGREINF_TOOLTIP;Ojači ali zmanjšaj vpliv prvega nivoja, nasprotni vpliv drugega nivoja, preostalo pusti nespremenjeno. +TP_WAVELET_EDGTHRESH;Podrobnost +TP_WAVELET_EDGTHRESH_TOOLTIP;Spremeni ponovne delitve med prvim nivojem in ostalimi. Višji kot je prag, več aktivnosti je osredotočeno na prve nivoje.Bodite previdni z negativnimi vrednostmi, ki povečaujejo aktivnosti visokih nivojev in lahko povzročajo artefakte. +TP_WAVELET_EDRAD;Radij +TP_WAVELET_EDRAD_TOOLTIP;Ta prilagoditev radija je bistveno drugačna kot pri drugih orodij ostrenja. Vrednost radija se primerja prek kompleksne funkcije z drugimi nivoji. Tako ima tudi vrednost 0 vpliv. +TP_WAVELET_EDSL;Prag drsnikov +TP_WAVELET_EDTYPE;Metoda Lokalnega kontrasta +TP_WAVELET_EDVAL;Moč +TP_WAVELET_FINAL;Končni poseg +TP_WAVELET_FINEST;Najbolj fino +TP_WAVELET_HIGHLIGHT;Obseg svetlosti bleščav +TP_WAVELET_HS1;Celotni obseg svetlosti +TP_WAVELET_HS2;Sence/bleščave +TP_WAVELET_HUESKIN;Kožni odtenek +TP_WAVELET_HUESKIN_TOOLTIP;Spodnje točke določajo začetek cone sprememb, zgornje točke pa konec, kjer so spremembe najmočnejše.\n\nČe morate področje bistveno premakniti ali pa se pojavljajo artefakti, potem je ravnotežje beline napačno. +TP_WAVELET_HUESKY;Odtenek neba +TP_WAVELET_HUESKY_TOOLTIP;Spodnje točke določajo začetek cone sprememb, zgornje točke pa konec, kjer so spremembe najmočnejše.\n\nČe morate področje bistveno premakniti ali pa se pojavljajo artefakti, potem je ravnotežje beline napačno. +TP_WAVELET_ITER;Nivoji ravnotežja Delta +TP_WAVELET_ITER_TOOLTIP;Levo: povečajne spodnje nivoje in zmanjšajte visoke nivoje,\nDesno: zmanjšajte nizke nivoje in povečajte visoke nivoje. +TP_WAVELET_LABEL;Nivoji valovčkov +TP_WAVELET_LARGEST;Najbolj grobo +TP_WAVELET_LEVCH;Barvitost +TP_WAVELET_LEVDIR_ALL;Vsi nivoji v vseh smereh +TP_WAVELET_LEVDIR_INF;Pod ali enako nivoju +TP_WAVELET_LEVDIR_ONE;En nivo +TP_WAVELET_LEVDIR_SUP;Nad nivojem +TP_WAVELET_LEVELS;Nivoji valovčkov +TP_WAVELET_LEVELS_TOOLTIP;Izberi število nivojev podrobnosti slike, ki naj se razdeli. Več nivojev zahteva več RAMa in več časa obdelovanja. +TP_WAVELET_LEVF;Kontrast +TP_WAVELET_LEVLABEL;Predogled največ možnih nivojev = %1 +TP_WAVELET_LEVONE;Nivo 2 +TP_WAVELET_LEVTHRE;Nivo 4 +TP_WAVELET_LEVTWO;Nivo 3 +TP_WAVELET_LEVZERO;Nivo 1 +TP_WAVELET_LINKEDG;Povežo z močjo ostrine robov +TP_WAVELET_LIPST;Izboljšan algoritem +TP_WAVELET_LOWLIGHT;Obseg svetlosti senc +TP_WAVELET_MEDGREINF;Prvi nivo +TP_WAVELET_MEDI;Odstrani artefakte na modrem nebu +TP_WAVELET_MEDILEV;Detekcija roba +TP_WAVELET_MEDILEV_TOOLTIP;Kadar omogočite detekcijo robov, priporočamo:\n- onemogočanje nizkih nivojev kontrasta za izogibanje artefaktom,\n- uporabo visokih vrednosti gradienta občutljivosti.\n\nMoč lahko nastavljate z izboljšavo od 'Odstranjevanja šuma' do 'Olepševanja'. +TP_WAVELET_NEUTRAL;Nevtralno +TP_WAVELET_NOIS;Odstrani šum +TP_WAVELET_NOISE;Odstrani šum in izpopolni +TP_WAVELET_NPHIGH;Visoko +TP_WAVELET_NPLOW;Nizko +TP_WAVELET_NPNONE;Nič +TP_WAVELET_NPTYPE;Sosednji piksli +TP_WAVELET_NPTYPE_TOOLTIP;Ta algoritem uporablja bližino piksla in osem njegovih sosedov. Če je majhna razlika, so robovi ojačeni. +TP_WAVELET_OPACITY;Neprosojnost modra-rumena +TP_WAVELET_OPACITYW;Krivulja ravnotežja kontrasta d/v-h +TP_WAVELET_OPACITYWL;Končni lokalni kontrast +TP_WAVELET_OPACITYWL_TOOLTIP;Spremeni končni lokalni kontrast ob koncu obdelave z valovčki\n\nLeva stran predstavlja najmanjši lokalni kontrast, ki se povečuje in doseže največji kontrast na desni strani. +TP_WAVELET_PASTEL;Pastelna barvitost +TP_WAVELET_PROC;Obdelaj +TP_WAVELET_RE1;Ojačeno +TP_WAVELET_RE2;Nespremenjeno +TP_WAVELET_RE3;Oslabljeno +TP_WAVELET_RESCHRO;Barvitost +TP_WAVELET_RESCON;Sence +TP_WAVELET_RESCONH;Bleščave +TP_WAVELET_RESID;Preostanek slike +TP_WAVELET_SAT;Nasičena barvitost +TP_WAVELET_SETTINGS;Nastavitev valovčkov +TP_WAVELET_SKIN;Ciljna zaščita kože +TP_WAVELET_SKIN_TOOLTIP;Pri -100 so odtenki kože ciljani.\nPri 0 so vsi toni obravnavani enako.\nPri +100 so kožni toni zaščiteni, vsi ostali pa spremenjeni. +TP_WAVELET_SKY;Ciljna zaščita neba +TP_WAVELET_SKY_TOOLTIP;Pri -100 so odtenki neba ciljani.\nPri 0 so vsi toni obravnavani enako.\nPri +100 so toni neba zaščiteni, vsi ostali pa spremenjeni. +TP_WAVELET_STREN;Moč +TP_WAVELET_STRENGTH;Moč +TP_WAVELET_SUPE;Ekstra +TP_WAVELET_THR;Prag senc +TP_WAVELET_THRESHOLD;Nivoji bleščav +TP_WAVELET_THRESHOLD2;Nivoji bleščav +TP_WAVELET_THRESHOLD2_TOOLTIP;Sprememba svetlosti v sencah bo samo na nivojih od 9 do 9 minus vrednost. Ostali nivoji bodo obdelani. Najvišji možni nivo je omejen z nivojem bleščav (9 minus nivo bleščav). +TP_WAVELET_THRESHOLD_TOOLTIP;Vpliv obsega lumninance bo samo na nivojih nad izbrano vrednostjo. Vsi ostali nivoji bodo obdelani. Izbrana vrednost omejuje najvišji možni nivo v sencah. +TP_WAVELET_THRH;Prag bleščav +TP_WAVELET_TILESBIG;Velike krpe +TP_WAVELET_TILESFULL;Celotna slika +TP_WAVELET_TILESIZE;Metoda pokrivanja +TP_WAVELET_TILESLIT;Majhne krpe +TP_WAVELET_TILES_TOOLTIP;Obdelava celotne slike zagotavlja boljšo kakovost in jo priporočamo, medtem ko je uporaba krp rezervna možnost za uporabnike z malo RAMa. Poglejte v RawPedio za potrebe po pomnilniku. +TP_WAVELET_TMSTRENGTH;Compression strength +TP_WAVELET_TMSTRENGTH_TOOLTIP;Upravlja z močjo tonske preslikave ali stiskanja kontrasta preostanka slike. Kadar je vrednost različna od 0, potem sta drsnika za moč in gamo posivela in onemogočena. +TP_WAVELET_TMTYPE;Metode stiskanja +TP_WAVELET_TON;Toniranje +TP_WBALANCE_AUTO;Avto +TP_WBALANCE_CAMERA;Camera +TP_WBALANCE_CLOUDY;Oblačno +TP_WBALANCE_CUSTOM;Po meri +TP_WBALANCE_DAYLIGHT;Dnevna svetloba (sončno) +TP_WBALANCE_EQBLUERED;Izenačevalnik modro/rdeče +TP_WBALANCE_EQBLUERED_TOOLTIP;Dovoljuje drugačno obnašanje od običajnega "uravnoteževanja beline" z urejanjem ravnotežja med rdečo in modro.\nTo je uporabno, kadar so pogoji snemanja:\na) daleč od običajnih pogojev osvetlitve (npr. pod vodo)\nb) so daleč od pogojev, kjer so bile izvedene nastavitve,\nc) ali, kjer so matrike ali ICC profili neprimerni. +TP_WBALANCE_FLASH55;Leica +TP_WBALANCE_FLASH60;Standard, Canon, Pentax, Olympus +TP_WBALANCE_FLASH65;Nikon, Panasonic, Sony, Minolta +TP_WBALANCE_FLASH_HEADER;Bliskavica +TP_WBALANCE_FLUO1;F1 - Dnevna svetloba +TP_WBALANCE_FLUO2;F2 - Hladna bela +TP_WBALANCE_FLUO3;F3 - Bela +TP_WBALANCE_FLUO4;F4 - Topla bela +TP_WBALANCE_FLUO5;F5 - Dnevna svetloba +TP_WBALANCE_FLUO6;F6 - Svetla bela +TP_WBALANCE_FLUO7;F7 - D65 Simulator dnevne svetlobe +TP_WBALANCE_FLUO8;F8 - D50 / Sylvania F40 Design +TP_WBALANCE_FLUO9;F9 - De luxe hladna bela +TP_WBALANCE_FLUO10;F10 - Philips TL85 +TP_WBALANCE_FLUO11;F11 - Philips TL84 +TP_WBALANCE_FLUO12;F12 - Philips TL83 +TP_WBALANCE_FLUO_HEADER;Fluorescent +TP_WBALANCE_GREEN;Odtenek +TP_WBALANCE_GTI;GTI +TP_WBALANCE_HMI;HMI +TP_WBALANCE_JUDGEIII;JudgeIII +TP_WBALANCE_LABEL;Uravnoteženje beline +TP_WBALANCE_LAMP_HEADER;Žarnica +TP_WBALANCE_LED_CRS;CRS SP12 WWMR16 +TP_WBALANCE_LED_HEADER;LED +TP_WBALANCE_LED_LSI;LSI Lumelex 2040 +TP_WBALANCE_METHOD;Metoda +TP_WBALANCE_PICKER;Poberi +TP_WBALANCE_SHADE;Senca +TP_WBALANCE_SIZE;Velikost: +TP_WBALANCE_SOLUX35;Solux 3500K +TP_WBALANCE_SOLUX41;Solux 4100K +TP_WBALANCE_SOLUX47;Solux 4700K (vendor) +TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) +TP_WBALANCE_SPOTWB;Uporabi pipeto za pridobivanje ravnotežne beline iz nevtralnega dela slike v predogledu. +TP_WBALANCE_TEMPBIAS;AWB pristranost temperature +TP_WBALANCE_TEMPBIAS_TOOLTIP;Dovoljuje spremenjen izračun "avtomatičnega ravnotežja beline"\nz spremembo proti toplejšemu ali hladnejšemu spektru. \nPristranost je izražena z odstotkom od izračunane temperature\ntako da je rezultat izražen z "izračunanaTemp + izračunanaTemp * pristranost". +TP_WBALANCE_TEMPERATURE;Temperatura +TP_WBALANCE_TUNGSTEN;Tungsten +TP_WBALANCE_WATER1;Podvodna 1 +TP_WBALANCE_WATER2;Podvodna 2 +TP_WBALANCE_WATER_HEADER;Pod vodo +ZOOMPANEL_100;(100%) +ZOOMPANEL_NEWCROPWINDOW;Odpri (novo) okno s podrobnostmi +ZOOMPANEL_ZOOM100;Zoom do 100%\nBližnjica: z +ZOOMPANEL_ZOOMFITCROPSCREEN;Prilagodi izrez zaslonu\nBližnjica: f +ZOOMPANEL_ZOOMFITSCREEN;Prilagodi celotno sliko zaslonu\nBližnjica: Alt-f +ZOOMPANEL_ZOOMIN;Zoom In\nBližnjica: + +ZOOMPANEL_ZOOMOUT;Zoom Out\nBližnjica: - + +!!!!!!!!!!!!!!!!!!!!!!!!! +! Untranslated keys follow; remove the ! prefix after an entry is translated. +!!!!!!!!!!!!!!!!!!!!!!!!! + +!GENERAL_HELP;Help +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_TRANS_Method;Geometry - Method +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic +!TP_SHARPENING_ITERCHECK;Auto limit iterations diff --git a/rtdata/languages/Swedish b/rtdata/languages/Swedish index 17bf0299f..f54b4de30 100644 --- a/rtdata/languages/Swedish +++ b/rtdata/languages/Swedish @@ -698,8 +698,8 @@ MAIN_TOOLTIP_BACKCOLOR1;Bakgrundsfärg: Svart\nKortkommando: 9 MAIN_TOOLTIP_BACKCOLOR2;Bakgrundsfärg: Vit\nKortkommando: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Lås / Lås upp före-vyn\n\nLås: behåll före-vyn oförändrad.\nAnvändbart för att utvärdera den sammanlagda effekten av flera stegs redigering. Dessutom kan jämförelser göras gentemot varje annat steg i historiken.\n\nLås upp: Före-vyn kommer hela tiden visa ett tidigare steg jämfört med efter-vyn, och visar därmed effekten av det verktyg som användes senast. MAIN_TOOLTIP_HIDEHP;Visa/göm den vänstra panelen. Kortkommando: l -MAIN_TOOLTIP_INDCLIPPEDH;Markera högdagerindikation.\nKortkommando: < -MAIN_TOOLTIP_INDCLIPPEDS;Markera skuggindikation.\nKortkommando: > +MAIN_TOOLTIP_INDCLIPPEDH;Markera högdagerindikation.\nKortkommando: > +MAIN_TOOLTIP_INDCLIPPEDS;Markera skuggindikation.\nKortkommando: < MAIN_TOOLTIP_PREVIEWB;Förhandsgranska den blå kanalen.\nGenväg: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Förhandsgranska fokusmasken.\nKortkommando: Shift-f\n\nNoggrannare på bilder med kort skärpedjup, lågt brus och där en hög zoom-grad är vald.\n\nFör att förbättra detekteringen för brusiga bilder, utvärdera vid en zoom-grad om 10-30%\n\nFörhandsvisningen görs långsammare med fokusmasken påslagen. MAIN_TOOLTIP_PREVIEWG;Förhandsgranska den gröna kanalen.\nGenväg: g @@ -1772,6 +1772,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !FILEBROWSER_RESETDEFAULTPROFILE;Reset to default !FILEBROWSER_SHOWNOTTRASHHINT;Show only images not in trash. !GENERAL_CURRENT;Current +!GENERAL_HELP;Help !GENERAL_RESET;Reset !GENERAL_SAVE_AS;Save as... !GENERAL_SLIDER;Slider @@ -1842,6 +1843,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !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 @@ -1859,6 +1861,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !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 @@ -1879,6 +1882,13 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CS - Auto threshold +!HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +!HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +!HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +!HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +!HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +!HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - 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 @@ -1893,6 +1903,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light !HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength !HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor +!HISTORY_MSG_TRANS_Method;Geometry - Method !ICCPROFCREATOR_COPYRIGHT;Copyright: !ICCPROFCREATOR_COPYRIGHT_RESET_TOOLTIP;Reset to the default copyright, granted to "RawTherapee, CC0" !ICCPROFCREATOR_CUSTOM;Custom @@ -1963,7 +1974,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 @@ -2100,6 +2111,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !TP_CROP_SELECTCROP;Select !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 @@ -2122,12 +2134,12 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. !TP_FILMNEGATIVE_LABEL;Film Negative -!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_PICK;Pick neutral 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_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, value 0 is used. !TP_ICM_APPLYBASELINEEXPOSUREOFFSET_TOOLTIP;Employ the embedded DCP baseline exposure offset. The setting is only available if the selected DCP has one. !TP_ICM_APPLYHUESATMAP_TOOLTIP;Employ the embedded DCP base table (HueSatMap). The setting is only available if the selected DCP has one. !TP_ICM_APPLYLOOKTABLE;Look table @@ -2139,6 +2151,8 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !TP_ICM_WORKING_TRC_NONE;None !TP_ICM_WORKING_TRC_SLOPE;Slope !TP_ICM_WORKING_TRC_TOOLTIP;Only for built-in profiles. +!TP_LENSGEOM_LIN;Linear +!TP_LENSGEOM_LOG;Logarithmic !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected @@ -2157,6 +2171,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !TP_METADATA_MODE;Metadata copy mode !TP_METADATA_STRIP;Strip all metadata !TP_METADATA_TUNNEL;Copy unchanged +!TP_PDSHARPENING_LABEL;Capture Sharpening !TP_PREPROCESS_LINEDENOISE_DIRECTION;Direction !TP_PREPROCESS_LINEDENOISE_DIRECTION_BOTH;Both !TP_PREPROCESS_LINEDENOISE_DIRECTION_HORIZONTAL;Horizontal @@ -2246,6 +2261,8 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !TP_RETINEX_VIEW_METHOD_TOOLTIP;Standard - Normal display.\nMask - Displays the mask.\nUnsharp mask - Displays the image with a high radius unsharp mask.\nTransmission - Auto/Fixed - Displays the file transmission-map, before any action on contrast and brightness.\n\nAttention: the mask does not correspond to reality, but is amplified to make it more visible. !TP_SHARPENING_BLUR;Blur radius !TP_SHARPENING_CONTRAST;Contrast threshold +!TP_SHARPENING_ITERCHECK;Auto limit iterations +!TP_SHARPENING_RADIUS_BOOST;Corner radius boost !TP_SHARPENMICRO_CONTRAST;Contrast threshold !TP_SOFTLIGHT_LABEL;Soft Light !TP_SOFTLIGHT_STRENGTH;Strength diff --git a/rtdata/languages/default b/rtdata/languages/default index 017554bff..0d7d46fab 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -22,7 +22,7 @@ CURVEEDITOR_EDITPOINT_HINT;Enable edition of node in/out values.\n\nRight-click CURVEEDITOR_HIGHLIGHTS;Highlights CURVEEDITOR_LIGHTS;Lights CURVEEDITOR_LINEAR;Linear -CURVEEDITOR_LOADDLGLABEL;Load curve... +CURVEEDITOR_LOADDLGLABEL;Load curve CURVEEDITOR_MINMAXCPOINTS;Equalizer CURVEEDITOR_NURBS;Control cage CURVEEDITOR_PARAMETRIC;Parametric @@ -225,6 +225,7 @@ GENERAL_DISABLED;Disabled GENERAL_ENABLE;Enable GENERAL_ENABLED;Enabled GENERAL_FILE;File +GENERAL_HELP;Help GENERAL_LANDSCAPE;Landscape GENERAL_NA;n/a GENERAL_NO;No @@ -742,7 +743,7 @@ HISTORY_MSG_490;DRC - Amount HISTORY_MSG_491;White Balance HISTORY_MSG_492;RGB Curves HISTORY_MSG_493;Local Adjustments -HISTORY_MSG_495;Local Spot created +HISTORY_MSG_494;Capture Sharpening HISTORY_MSG_496;Local Spot deleted HISTORY_MSG_497;Local Spot selected HISTORY_MSG_498;Local Spot name @@ -759,7 +760,7 @@ HISTORY_MSG_508;Local Spot circrad HISTORY_MSG_509;Local Spot quality method HISTORY_MSG_510;Local Spot transition HISTORY_MSG_511;Local Spot thresh -HISTORY_MSG_512;Local Spot deltaE-weakening +HISTORY_MSG_512;Local Spot ΔE -weakening HISTORY_MSG_513;Local Spot scope HISTORY_MSG_514;Local Spot structure HISTORY_MSG_515;Local Adjustements @@ -891,7 +892,7 @@ HISTORY_MSG_641;Local - Use SH mask HISTORY_MSG_642;Local - radius SH HISTORY_MSG_643;Local - Blur SH HISTORY_MSG_644;Local - inverse SH -HISTORY_MSG_645;Local - balance deltaE ab-L +HISTORY_MSG_645;Local - balance ΔE ab-L HISTORY_MSG_646;Local - Exp mask chroma HISTORY_MSG_647;Local - Exp mask gamma HISTORY_MSG_648;Local - Exp mask slope @@ -903,7 +904,7 @@ HISTORY_MSG_653;Local - SH mask chroma HISTORY_MSG_654;Local - SH mask gamma HISTORY_MSG_655;Local - SH mask slope HISTORY_MSG_656;Local - Color soft radius -HISTORY_MSG_657;Local - Retinex Guided Filter radius +HISTORY_MSG_657;Local - Retinex Reduce artifacts HISTORY_MSG_658;Local - CBDL soft radius HISTORY_MSG_659;Local Spot transition-weakening HISTORY_MSG_660;Local - cbdl clarity @@ -947,6 +948,7 @@ HISTORY_MSG_697;Local - TM Normalize HISTORY_MSG_698;Local - Local contrast Fast Fourier HISTORY_MSG_699;Local - Retinex Fast Fourier HISTORY_MSG_701;Local - Exp Shadows +HISTORY_MSG_702;Local - Exp Method HISTORY_MSG_703;Local - Exp Laplacian threshold HISTORY_MSG_704;Local - Exp PDE balance HISTORY_MSG_705;Local - Exp linearity @@ -962,7 +964,192 @@ HISTORY_MSG_714;Local - TM mask slope HISTORY_MSG_716;Local - Local method HISTORY_MSG_717;Local - Local contrast HISTORY_MSG_718;Local - Local contrast levels -HISTORY_MSG_719;Local - Local contrast residual +HISTORY_MSG_719;Local - Local contrast residual L +HISTORY_MSG_720;Local - Blur mask C +HISTORY_MSG_721;Local - Blur mask L +HISTORY_MSG_722;Local - Blur mask CL +HISTORY_MSG_723;Local - use Blur mask +HISTORY_MSG_725;Local - Blur mask Blend +HISTORY_MSG_726;Local - Blur mask radius +HISTORY_MSG_727;Local - Blur mask chroma +HISTORY_MSG_728;Local - Blur mask gamma +HISTORY_MSG_729;Local - Blur mask slope +HISTORY_MSG_730;Local - Blur method +HISTORY_MSG_731;Local - median method +HISTORY_MSG_732;Local - median iterations +HISTORY_MSG_733;Local - soft radius +HISTORY_MSG_734;Local - detail +HISTORY_MSG_738;Local - Local contrast Merge L +HISTORY_MSG_739;Local - Local contrast Soft radius +HISTORY_MSG_740;Local - Local contrast Merge C +HISTORY_MSG_741;Local - Local contrast Residual C +HISTORY_MSG_742;Local - Exp Laplacian gamma +HISTORY_MSG_743;Local - Exp Fattal Amount +HISTORY_MSG_744;Local - Exp Fattal Detail +HISTORY_MSG_745;Local - Exp Fattal Offset +HISTORY_MSG_746;Local - Exp Fattal Sigma +HISTORY_MSG_747;Local Spot created +HISTORY_MSG_748;Local - Exp Denoise +HISTORY_MSG_749;Local - Reti Depth +HISTORY_MSG_750;Local - Reti Mode log - lin +HISTORY_MSG_751;Local - Reti Dehaze luminance +HISTORY_MSG_752;Local - Reti Offset +HISTORY_MSG_753;Local - Reti Transmission map +HISTORY_MSG_754;Local - Reti Clip +HISTORY_MSG_755;Local - TM use tm mask +HISTORY_MSG_756;Local - Exp use algo exposure mask +HISTORY_MSG_757;Local - Exp Laplacian mask +HISTORY_MSG_758;Local - Reti Laplacian mask +HISTORY_MSG_759;Local - Exp Laplacian mask +HISTORY_MSG_760;Local - Color Laplacian mask +HISTORY_MSG_761;Local - SH Laplacian mask +HISTORY_MSG_762;Local - cbdl Laplacian mask +HISTORY_MSG_763;Local - Blur Laplacian mask +HISTORY_MSG_764;Local - Solve PDE Laplacian mask +HISTORY_MSG_765;Local - deNoise Detail threshold +HISTORY_MSG_766;Local - Blur Fast Fourier +HISTORY_MSG_767;Local - Grain Iso +HISTORY_MSG_768;Local - Grain Strength +HISTORY_MSG_769;Local - Grain Scale +HISTORY_MSG_770;Local - Color Mask contrast curve +HISTORY_MSG_771;Local - Exp Mask contrast curve +HISTORY_MSG_772;Local - SH Mask contrast curve +HISTORY_MSG_773;Local - TM Mask contrast curve +HISTORY_MSG_774;Local - Reti Mask contrast curve +HISTORY_MSG_775;Local - CBDL Mask contrast curve +HISTORY_MSG_776;Local - Blur Denoise Mask contrast curve +HISTORY_MSG_777;Local - Blur Mask local contrast curve +HISTORY_MSG_778;Local - Blur Mask highlights +HISTORY_MSG_779;Local - Color Mask local contrast curve +HISTORY_MSG_780;Local - Color Mask shadows +HISTORY_MSG_781;Local - Contrast Mask Wavelet level +HISTORY_MSG_782;Local - Blur Denoise Mask Wavelet levels +HISTORY_MSG_783;Local - Color Wavelet levels +HISTORY_MSG_784;Local - Mask ΔE +HISTORY_MSG_785;Local - Mask Scope ΔE +HISTORY_MSG_786;Local - SH method +HISTORY_MSG_787;Local - Equalizer multiplier +HISTORY_MSG_788;Local - Equalizer detail +HISTORY_MSG_789;Local - SH mask amount +HISTORY_MSG_790;Local - SH mask anchor +HISTORY_MSG_791;Local - Mask Short L curves +HISTORY_MSG_792;Local - Mask Luminance Background +HISTORY_MSG_793;Local - SH TRC gamma +HISTORY_MSG_794;Local - SH TRC slope +HISTORY_MSG_795;Local - Mask save restore image +HISTORY_MSG_796;Local - Recursive references +HISTORY_MSG_797;Local - Merge Original method +HISTORY_MSG_798;Local - Opacity +HISTORY_MSG_799;Local - Color RGB ToneCurve +HISTORY_MSG_800;Local - Color ToneCurve Method +HISTORY_MSG_801;Local - Color ToneCurve Special +HISTORY_MSG_802;Local - Contrast threshold +HISTORY_MSG_803;Local - Color Merge +HISTORY_MSG_804;Local - Color mask Structure +HISTORY_MSG_805;Local - Blur Noise mask Structure +HISTORY_MSG_806;Local - Color mask Structure as tool +HISTORY_MSG_807;Local - Blur Noise mask Structure as tool +HISTORY_MSG_808;Local - Color mask curve H(H) +HISTORY_MSG_809;Local - Vib mask curve C(C) +HISTORY_MSG_810;Local - Vib mask curve L(L) +HISTORY_MSG_811;Local - Vib mask curve LC(H) +HISTORY_MSG_813;Local - Use Vib mask +HISTORY_MSG_814;Local - Vib mask Blend +HISTORY_MSG_815;Local - Vib mask radius +HISTORY_MSG_816;Local - Vib mask chroma +HISTORY_MSG_817;Local - Vib mask gamma +HISTORY_MSG_818;Local - Vib mask slope +HISTORY_MSG_819;Local - Vib mask laplacian +HISTORY_MSG_820;Local - Vib mask contrast curve +HISTORY_MSG_821;Local - color grid background +HISTORY_MSG_822;Local - color background merge +HISTORY_MSG_823;Local - color background luminance +HISTORY_MSG_824;Local - Exp gradient mask strength +HISTORY_MSG_825;Local - Exp gradient mask angle +HISTORY_MSG_826;Local - Exp gradient strength +HISTORY_MSG_827;Local - Exp gradient angle +HISTORY_MSG_828;Local - SH gradient strength +HISTORY_MSG_829;Local - SH gradient angle +HISTORY_MSG_830;Local - Color gradient strength L +HISTORY_MSG_831;Local - Color gradient angle +HISTORY_MSG_832;Local - Color gradient strength C +HISTORY_MSG_833;Local - Gradient feather +HISTORY_MSG_834;Local - Color gradient strength H +HISTORY_MSG_835;Local - Vib gradient strength L +HISTORY_MSG_836;Local - Vib gradient angle +HISTORY_MSG_837;Local - Vib gradient strength C +HISTORY_MSG_838;Local - Vib gradient strength H +HISTORY_MSG_839;Local - Software complexity +HISTORY_MSG_840;Local - CL Curve +HISTORY_MSG_841;Local - LC curve +HISTORY_MSG_842;Local - Contrast Threshold Mask blur +HISTORY_MSG_843;Local - Radius Mask blur +HISTORY_MSG_844;Local - Color Mask fftw +HISTORY_MSG_845;Local - Encoding log +HISTORY_MSG_846;Local - Encoding auto +HISTORY_MSG_847;Local - Source Gray +HISTORY_MSG_848;Local - Source Gray auto +HISTORY_MSG_849;Local - Auto Grayon +HISTORY_MSG_850;Local - Black Ev +HISTORY_MSG_851;Local - White Ev +HISTORY_MSG_852;Local - Target Gray +HISTORY_MSG_853;Local - Local contrast +HISTORY_MSG_854;Local - Scope encoding log +HISTORY_MSG_855;Local - Entire image +HISTORY_MSG_856;Local - Base log +HISTORY_MSG_857;Local - Contrast Blur Residual +HISTORY_MSG_858;Local - Contrast Luminance only +HISTORY_MSG_859;Local - Contrast Maximum Blur levels +HISTORY_MSG_860;Local - Contrast Curve Blur levels +HISTORY_MSG_861;Local - Contrast Curve Contrast levels +HISTORY_MSG_862;Local - Contrast Sigma luminance +HISTORY_MSG_863;Local - Contrast Merge Original +HISTORY_MSG_864;Local - Contrast Detail +HISTORY_MSG_865;Local - Contrast Anchor +HISTORY_MSG_866;Local - Contrast Curve Compression +HISTORY_MSG_867;Local - Contrast Amount residual +HISTORY_MSG_868;Local - balance ΔE C-H +HISTORY_MSG_869;Local - denoise curve luminance +HISTORY_MSG_870;Local - LC mask curve LC(H) +HISTORY_MSG_871;Local - LC mask curve C(C) +HISTORY_MSG_872;Local - LC mask curve L(L) +HISTORY_MSG_873;Local - LC mask enable +HISTORY_MSG_875;Local - LC mask blend +HISTORY_MSG_876;Local - LC mask radius +HISTORY_MSG_877;Local - LC mask chroma +HISTORY_MSG_878;Local - LC mask curve contrast +HISTORY_MSG_879;Local - LC Chroma levels +HISTORY_MSG_880;Local - LC Chroma blur levels +HISTORY_MSG_881;Local - Contrast Offset Luminance +HISTORY_MSG_882;Local - Contrast Blur +HISTORY_MSG_883;Local - Contrast By Levels +HISTORY_MSG_884;Local - Contrast Dynamic Range Laplacian +HISTORY_MSG_885;Local - Contrast Dynamic Range Wavelet +HISTORY_MSG_886;Local - Contrast Wavelet Curve Compression +HISTORY_MSG_887;Local - Contrast Wavelet Compression Residual +HISTORY_MSG_888;Local - Contrast Wavelet Balance Threshold +HISTORY_MSG_889;Local - Contrast Wavelet Graduated Strength +HISTORY_MSG_890;Local - Contrast Wavelet Graduated angle +HISTORY_MSG_891;Local - Contrast Wavelet Graduated +HISTORY_MSG_892;Local - Encoding log Graduated Strength +HISTORY_MSG_893;Local - Encoding log Graduated angle +HISTORY_MSG_894;Local - Color Preview dE +HISTORY_MSG_897;Local - Contrast Wavelet ES strength +HISTORY_MSG_898;Local - Contrast Wavelet ES radius +HISTORY_MSG_899;Local - Contrast Wavelet ES detail +HISTORY_MSG_900;Local - Contrast Wavelet ES gradient +HISTORY_MSG_901;Local - Contrast Wavelet ES threshold low +HISTORY_MSG_902;Local - Contrast Wavelet ES threshold high +HISTORY_MSG_903;Local - Contrast Wavelet ES local contrast +HISTORY_MSG_904;Local - Contrast Wavelet ES first level +HISTORY_MSG_905;Local - Contrast Wavelet Edge Sharpness +HISTORY_MSG_906;Local - Contrast Wavelet ES sensitivity +HISTORY_MSG_907;Local - Contrast Wavelet ES amplification +HISTORY_MSG_908;Local - Contrast Wavelet ES neighboring +HISTORY_MSG_909;Local - Contrast Wavelet ES show +HISTORY_MSG_910;Local - Wavelet Edge performance +HISTORY_MSG_911;Local - Blur Chroma Luma +HISTORY_MSG_912;Local - Blur Guide filter strength HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction HISTORY_MSG_COLORTONING_LABREGION_AB;CT - Color correction @@ -980,6 +1167,7 @@ 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 @@ -1000,6 +1188,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_AUTO_CONTRAST;CS - Auto threshold +HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;CS - Auto radius +HISTORY_MSG_PDSHARPEN_CHECKITER;CS - Auto limit iterations +HISTORY_MSG_PDSHARPEN_CONTRAST;CS - Contrast threshold +HISTORY_MSG_PDSHARPEN_ITERATIONS;CS - Iterations +HISTORY_MSG_PDSHARPEN_RADIUS;CS - Radius +HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;CS - 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 @@ -1014,6 +1209,7 @@ HISTORY_MSG_SH_COLORSPACE;S/H - Colorspace HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor +HISTORY_MSG_TRANS_Method;Geometry - Method HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOT;Snapshot @@ -1138,7 +1334,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 @@ -1167,8 +1363,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Background color of the preview: white\nShortcut: MAIN_TOOLTIP_BACKCOLOR3;Background color of the preview: middle grey\nShortcut: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Lock / Unlock the Before view\n\nLock: keep the Before view unchanged.\nUseful to evaluate the cumulative effect of multiple tools.\nAdditionally, comparisons can be made to any state in the History.\n\nUnlock: the Before view will follow the After view one step behind, showing the image before the effect of the currently used tool. MAIN_TOOLTIP_HIDEHP;Show/Hide the left panel (including the history).\nShortcut: l -MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: < -MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: > +MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: > +MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: < MAIN_TOOLTIP_PREVIEWB;Preview the blue channel.\nShortcut: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Preview the focus mask.\nShortcut: Shift-f\n\nMore accurate on images with shallow depth of field, low noise and at higher zoom levels.\nZoom out to 10-30% to improve detection accuracy on noisy images. MAIN_TOOLTIP_PREVIEWG;Preview the green channel.\nShortcut: g @@ -1315,6 +1511,10 @@ PREFERENCES_CLUTSCACHE;HaldCLUT Cache PREFERENCES_CLUTSCACHE_LABEL;Maximum number of cached CLUTs PREFERENCES_CLUTSDIR;HaldCLUT directory PREFERENCES_CMMBPC;Black point compensation +PREFERENCES_COMPLEXITYLOC;Complexity Local Adjustements +PREFERENCES_COMPLEXITY_EXP;Expert +PREFERENCES_COMPLEXITY_CONF;Confirmed +PREFERENCES_COMPLEXITY_NORM;Normal PREFERENCES_CROP;Crop Editing PREFERENCES_CROP_AUTO_FIT;Automatically zoom to fit the crop PREFERENCES_CROP_GUIDES;Guides shown when not editing the crop @@ -1773,6 +1973,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 @@ -1883,9 +2084,9 @@ 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_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards. TP_FILMNEGATIVE_LABEL;Film Negative -TP_FILMNEGATIVE_PICK;Pick white and black spots +TP_FILMNEGATIVE_PICK;Pick neutral 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? @@ -1899,7 +2100,7 @@ TP_FLATFIELD_BT_HORIZONTAL;Horizontal TP_FLATFIELD_BT_VERTHORIZ;Vertical + Horizontal TP_FLATFIELD_BT_VERTICAL;Vertical 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_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, value 0 is used. TP_FLATFIELD_LABEL;Flat-Field TP_GENERAL_11SCALE_TOOLTIP;The effects of this tool are only visible or only accurate at a preview scale of 1:1. TP_GRADIENT_CENTER;Center @@ -2007,6 +2208,8 @@ TP_LABCURVE_RSTPRO_TOOLTIP;Works on the Chromaticity slider and the CC curve. TP_LENSGEOM_AUTOCROP;Auto-Crop TP_LENSGEOM_FILL;Auto-fill TP_LENSGEOM_LABEL;Lens / Geometry +TP_LENSGEOM_LIN;Linear +TP_LENSGEOM_LOG;Logarithmic TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected @@ -2017,22 +2220,30 @@ TP_LENSPROFILE_USE_CA;Chromatic aberration TP_LENSPROFILE_USE_GEOMETRIC;Geometric distortion TP_LENSPROFILE_USE_HEADER;Correct TP_LENSPROFILE_USE_VIGNETTING;Vignetting -TP_LOCALLAB_ACTIV;Blur luminance only +TP_LOCALLAB_ACTIV;Luminance only TP_LOCALLAB_ADJ;Equalizer blue-red +TP_LOCALLAB_ALL;All rubrics TP_LOCALLAB_AMOUNT;Amount TP_LOCALLAB_ARTIF;Shape detection TP_LOCALLAB_ARTIF_TOOLTIP;Increase deltaE Weakening improve shape detection, but can reduce the scope of detection.\nThreshold deltaE-scope increase the range of scope-deltaE - high values are for very wide gamut images.\nThreshold structure take into account the structure level of solid areas +TP_LOCALLAB_AUTOGRAY;Automatic TP_LOCALLAB_AVOID;Avoid color shift -TP_LOCALLAB_BALAN;Balance deltaE ab-L +TP_LOCALLAB_BALAN;Balance ΔE ab-L +TP_LOCALLAB_BALANH;Balance ΔE C-H +TP_LOCALLAB_BALAN_TOOLTIP;Change algorithm ΔE parameter.\nMore or less ab-L, more or less C - H.\nNot for Denoise +TP_LOCALLAB_BALANEXP;ΔØ PDE balance +TP_LOCALLAB_BASELOG;Logarithm base TP_LOCALLAB_BILATERAL;Bilateral filter +TP_LOCALLAB_BLACK_EV;Black Ev TP_LOCALLAB_BLENDMASKCOL;Blend -TP_LOCALLAB_SCALERETI;Scale -TP_LOCALLAB_BLMETHOD_TOOLTIP;Normal - direct blur and noise with all settings.\nInverse - Inverse blur and noise without scope and whithout enhanced algorithm.\nSymmetric - inverse blur and noise with all settings. Be careful some results may be curious -TP_LOCALLAB_BLUFR;Blur & Noise -TP_LOCALLAB_BLURDE;Blur Shape detection -TP_LOCALLAB_BLNORM;Normal +TP_LOCALLAB_BLGUID;Guided Filter TP_LOCALLAB_BLINV;Inverse -TP_LOCALLAB_BLURCBDL;Blur levels 0-1-2-3-4 +TP_LOCALLAB_BLCO;Chrominance only +TP_LOCALLAB_BLLO;Luminance only +TP_LOCALLAB_BLLC;Luminance & Chrominance +TP_LOCALLAB_BLMED;Median +TP_LOCALLAB_BLMETHOD_TOOLTIP;Normal - direct blur and noise with all settings.\nInverse - Inverse blur and noise without scope and without enhanced algorithm.\nSymmetric - inverse blur and noise with all settings. Be careful some results may be curious +TP_LOCALLAB_BLNORM;Normal TP_LOCALLAB_BLSYM;Symmetric TP_LOCALLAB_CENTER_X;Center X TP_LOCALLAB_CENTER_Y;Center Y @@ -2215,23 +2426,423 @@ TP_LOCALLAB_VIBRANCE;Vibrance TP_LOCALLAB_WARM;Warm - Cool & Color artifacts TP_LOCALLAB_WARM_TOOLTIP;This slider use Ciecam algorithm and acts as White Balance, it can warm or cool the area selected.\nIt can also in some cases reduce color artifacts. TP_LOCALLAB_SPOTNAME;New Spot +TP_LOCALLAB_BLUFR;Smooth - Blur - Grain (& additional denoise) +TP_LOCALLAB_BLUMETHOD_TOOLTIP;To blur the background and isolate the foreground:\n*Blur the background by a RT-spot fully covering the image (high values for scope and transition) - normal or inverse.\n*Isolate the foreground by one or more excluding RT-spot with the tools you want (increse scope), you can use a mask to enhance and amplify the effects.\n\nThis module can be used in additional noise reduction,including "median" and "Guided filter" +TP_LOCALLAB_BLUR;Gaussian Blur - Noise - Grain +TP_LOCALLAB_BLURCBDL;Blur levels 0-1-2-3-4 +TP_LOCALLAB_BLURCOL;Radius Mask Blur +TP_LOCALLAB_BLURDE;Blur Shape detection +TP_LOCALLAB_BLURLC;Luminance Only +TP_LOCALLAB_BLURLEVELFRA;Blur Levels +TP_LOCALLAB_BLURRESIDFRA;Blur Residual TP_LOCALLAB_BUTTON_ADD;Add TP_LOCALLAB_BUTTON_DEL;Delete TP_LOCALLAB_BUTTON_DUPL;Duplicate TP_LOCALLAB_BUTTON_REN;Rename TP_LOCALLAB_BUTTON_VIS;Show/Hide +TP_LOCALLAB_CBDL;Contrast by detail levels - Big defects +TP_LOCALLAB_CENTER_X;Center X +TP_LOCALLAB_CENTER_Y;Center Y +TP_LOCALLAB_CH;Curves CL - LC +TP_LOCALLAB_CHROMA;Chrominance +TP_LOCALLAB_CHROMACBDL;Chroma +TP_LOCALLAB_CHROMACB_TOOLTIP;Acts as an amplifier-reducer action compare to sliders of luminance.\nUnder 100 reduce, above 100 amplifie +TP_LOCALLAB_CHROMALEV;Chroma levels +TP_LOCALLAB_CHROMABLU;Chroma levels +TP_LOCALLAB_CHROMASKCOL;Chroma mask +TP_LOCALLAB_CHROMASK_TOOLTIP;You can use this slider to desaturated background (inverse mask - curve near 0).\nAlso to attenuate or enhance the action of a mask on the chroma +TP_LOCALLAB_CHRRT;Chroma +TP_LOCALLAB_CIRCRADIUS;Spot size +TP_LOCALLAB_CLARICRES;Merge Chroma +TP_LOCALLAB_CLARIFRA;Clarity & Sharp mask - Blend & Soft images +TP_LOCALLAB_CLARILRES;Merge Luma +TP_LOCALLAB_CLARISOFT;Soft radius +TP_LOCALLAB_CLARITYML;Clarity +TP_LOCALLAB_CLARI_TOOLTIP;Under or equal level wavelet 4, 'Sharp mask' is enabled.\nAbove level wavelet 5 'Clarity' is enabled.\nUsefull if you use 'Level dynamic Range Compression' +TP_LOCALLAB_CLIPTM;Clip Restored datas (gain) +TP_LOCALLAB_COFR;Color & Light - Small defects TP_LOCALLAB_COL_NAME;Name TP_LOCALLAB_COL_VIS;Status -TP_LOCALLAB_ROW_VIS;Visible -TP_LOCALLAB_ROW_NVIS;Not visible -TP_LOCALLAB_EV_VIS;Show -TP_LOCALLAB_EV_NVIS;Hide -TP_LOCALLAB_EV_VIS_ALL;Show all -TP_LOCALLAB_EV_NVIS_ALL;Hide all -TP_LOCALLAB_REN_DIALOG_NAME;Renaming Control Spot -TP_LOCALLAB_REN_DIALOG_LAB;Enter the new Control Spot name -TP_LOCALLAB_EV_DUPL;Copy of +TP_LOCALLAB_COLORDE;Color preview selection ΔE and Intensity +TP_LOCALLAB_COLORDE_TOOLTIP;Show preview selection ΔE in blue if negative and in green if positive.\nShow real modifications if positive, show enhanced modifications with blue and yellow if negative.\nThe intensity is function of the level.\nFor 'Denoise' the appearance is different. +TP_LOCALLAB_COMPFRA;Levels Dynamic Laplacian Range Compression ƒ +TP_LOCALLAB_COMPREFRA;Levels Dynamic Wavelet Range (un)Compression +TP_LOCALLAB_COMPRESS_TOOLTIP;Use if necessary the module 'Clarity & Sharp mask and Blend & Soft Images' by adjusting 'Soft radius' to reduce artifacts. +TP_LOCALLAB_COMPFRAME_TOOLTIP;Allows special effects. You can reduce artifacts with 'Clarity & Sharp mask - Blend & Soft Images".\nUses a lot of resources +TP_LOCALLAB_COMPLEX_METHOD;Software Complexity +TP_LOCALLAB_COMPLEX_TOOLTIP; Allow user to select Local adjustements rubrics. +TP_LOCALLAB_CONTCOL;Contrast threshold Mask Blur +TP_LOCALLAB_CONTFRA;Contrast by Level +TP_LOCALLAB_CONTRAST;Contrast +TP_LOCALLAB_CONTRESID;Contrast +TP_LOCALLAB_CONTTHR;Contrast Threshold +TP_LOCALLAB_CSTHRESHOLD;Ψ Wavelets Levels +TP_LOCALLAB_CSTHRESHOLDBLUR;Ψ Mask Wavelet level +TP_LOCALLAB_CURV;Lightness - Contrast - Chrominance "Super" +TP_LOCALLAB_CURVCURR;Normal +TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP;If curves at the top, mask is completely black no transformation is made by the mask on the image.\nAs you go down the curve, the mask gradually more colorful and brilliant, the image is changing more and more +TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP;To be active, you must check button 'Enable curves' +TP_LOCALLAB_CURVEEDITOR_TONES_LABEL;Tone curve +TP_LOCALLAB_CURVEEDITOR_TONES_TOOLTIP;L=f(L), can be used with L(H) in Color and Light +TP_LOCALLAB_CURVEMETHOD_TOOLTIP;'Normal', the curve L=f(L) has the same algorithm than slider lightness.\n'Super' the curve L=f(L) has an new improved algorithm, which can leeds in some cases to artifacts. +TP_LOCALLAB_CURVENCONTRAST;Super+Contrast threshold (experimental) +TP_LOCALLAB_CURVENH;Super +TP_LOCALLAB_CURVENHSU;Combined HueChroma (experimental) +TP_LOCALLAB_CURVENSOB2;Combined HueChroma + Contrast threshold (experimental) +TP_LOCALLAB_CURVNONE;Disable curves +TP_LOCALLAB_DARKRETI;Darkness +TP_LOCALLAB_DEHAFRA;Dehaze +TP_LOCALLAB_DEHAZ;Strength +TP_LOCALLAB_DEHAZ_TOOLTIP;Negative values add haze +TP_LOCALLAB_DELTAEC;Mask ΔE Image +TP_LOCALLAB_DENOIS;Ψ Denoise +TP_LOCALLAB_DENOI_TOOLTIP;This module can be used alone (at the end of process), or in complement of main denoise (at the beginning).\nScope allows to differentiate the action according to the color (deltaE).\nYou can complete the action with "median" or "Guided Filter" (Smooth Blur...).\nYou can complete the action with "Blur levels" "Wavelet pyramid" +TP_LOCALLAB_DEPTH;Depth +TP_LOCALLAB_DETAIL;Local contrast +TP_LOCALLAB_DETAILSH;Details +TP_LOCALLAB_DETAILTHR;Detail threshold Luminance Chroma (DCT ƒ) TP_LOCALLAB_DUPLSPOTNAME;Copy +TP_LOCALLAB_EDGFRA;Edge Sharpness +TP_LOCALLAB_EDGSHOW;Show all tools +TP_LOCALLAB_ELI;Elipse +TP_LOCALLAB_ENABLE_AFTER_MASK;Use Tone Mapping +TP_LOCALLAB_ENABLE_MASK;Enable mask +TP_LOCALLAB_ENABLE_MASKAFT;Use all algorithms Exposure +TP_LOCALLAB_ENARETIMASKTMAP_TOOLTIP;If enabled Mask uses Restored Datas after Transmission Map instead of Original datas +TP_LOCALLAB_ENH;Enhanced +TP_LOCALLAB_ENHDEN;Enhanced + chroma denoise +TP_LOCALLAB_EPSBL;Detail +TP_LOCALLAB_EQUIL;Normalize Luminance +TP_LOCALLAB_ESTOP;Edge stopping +TP_LOCALLAB_EV_DUPL;Copy of +TP_LOCALLAB_EV_NVIS;Hide +TP_LOCALLAB_EV_NVIS_ALL;Hide all +TP_LOCALLAB_EV_VIS;Show +TP_LOCALLAB_EV_VIS_ALL;Show all +TP_LOCALLAB_EXCLUF;Excluding +TP_LOCALLAB_EXCLUF_TOOLTIP;Can be used to exclude this part of datas - move Scope to extend color.\n You can apply all settings to this RT-spot. +TP_LOCALLAB_EXCLUTYPE;Spot method +TP_LOCALLAB_EXCLUTYPE_TOOLTIP;Normal spot use recursive data.\nExcluding spot reinitialize data to origin. +TP_LOCALLAB_EXECLU;Excluding spot +TP_LOCALLAB_EXNORM;Normal spot +TP_LOCALLAB_EXPCBDL_TOOLTIP;In the case of contaminated sensor (type "grease"), and when the area is important or for a series of small defects.\n\na) Put the selection spot on a pronounced default (adapting its size if necessary), use a large spot enough to allow wavelet; b) choose a wide selection area to cover most of the area affected by the defects; c) Select a transition value (low) and transition weakening (high value); d) act on levels 2, 3, 4 or 5 or lower by reducing the contrast (values below 100) and by acting on the chroma slider if necessary. e)possibly act on "scope" to reduce the extent of the action.\n\nYou can also complete with Blur levels and Gaussian blur (Smooth Blur and noise) +TP_LOCALLAB_EXPCHROMA;Chroma compensation +TP_LOCALLAB_EXPCOLOR_TOOLTIP;In the case of small defects.\n\nRed-eyes : red-centered circular selector, spot delimiters close to the eye, weak scope, "lightness" -100, "chrominance" -100.\n\nSpotIR :Circular selector centered on the defect, spot delimiters close to the default - reduce "chrominance", possibly act on "scope" to reduce the extent of the action.\n\nDust - grease (small) :Circular selector centered on the defect (adapt the size of the spot), spot delimiters not too close to the defect to allow an inconspicuous transition. a) "Transition" (low values) and "Transition weak" (high values); b) act on "lightness" and possibly on "chrominance" or "Color correction grid - direct" to approach the rendering of the polluted zone to that of the healthy zone; c) act moderately on "scope" to modulate the desired action.\n\nYou can also complete with Gaussian blur (Smooth Blur and noise) +TP_LOCALLAB_EXPCONTRAST_TOOLTIP;Avoid spots that are too small(< 50x50 pixels).\nUse low transition values and high weakening transition values and scope to simulate small RT-spot.\nUse if necessary the module 'Clarity & Sharp mask and Blend images' by adjusting 'Soft radius' to reduce artifacts. +TP_LOCALLAB_EXPCURV;Curves +TP_LOCALLAB_EXPGRAD;Graduated Filter +TP_LOCALLAB_EXPMETHOD_TOOLTIP;Standard : use an algorithm similar as main Exposure but in L*a*b* and taking account of deltaE.\n\nLaplacian & PDE : use another algorithm also with deltaE and with Poisson equation to solve Laplacian in Fourier space.\nPDE IPOL, PDE Fattal and Standard can be combined.\nFFTW Fourier Transform is optimized in size to reduce processing time.\nPDE reduce artifacts and noise. +TP_LOCALLAB_EXPOSE;Exposure +TP_LOCALLAB_EXPOSURE_TOOLTIP;In some cases (strong shadows ..) you can use the module "Shadows Highlights" +TP_LOCALLAB_EXPRETITOOLS;Advanced Retinex Tools +TP_LOCALLAB_EXPSHARP_TOOLTIP;RT-Spot minimum 39*39.\nUse low transition values and high weakening transition values and scope to simulate small RT-spot. +TP_LOCALLAB_EXPTOOL;Tools exposure +TP_LOCALLAB_EXPTRC;Tone Response Curve - TRC +TP_LOCALLAB_FATAMOUNT;Amount +TP_LOCALLAB_FATANCHOR;Anchor +TP_LOCALLAB_FATANCHORA;Offset +TP_LOCALLAB_FATDETAIL;Detail +TP_LOCALLAB_FATFRA;Dynamic Range Compression ƒ +TP_LOCALLAB_FATFRAME_TOOLTIP;PDE Fattal - use Fattal Tone mapping algorithm.\nAnchor allows selection according to the images over or under exposed.\nUseful to increase Luminance for a Second spot near the current and using mask +TP_LOCALLAB_FATLEVEL;Sigma +TP_LOCALLAB_FATRES;Amount Residual Image +TP_LOCALLAB_FATSHFRA;Dynamic Range Compression Mask ƒ +TP_LOCALLAB_FEATH_TOOLTIP;Gradient width in percent of the Spot diagonal\n.. +TP_LOCALLAB_FEATVALUE;Feather gradient +TP_LOCALLAB_FFTCOL_MASK;FFTW ƒ +TP_LOCALLAB_FFTW;ƒ - Use Fast Fourier Transform +TP_LOCALLAB_FFTW2;ƒ - Use Fast Fourier Transform (TIF, JPG,..) +TP_LOCALLAB_FFTWBLUR;ƒ - Always Use Fast Fourier Transform +TP_LOCALLAB_FULLIMAGE;Calculate DarkEv - WhiteEv - Value on the entire image +TP_LOCALLAB_GAM;Gamma +TP_LOCALLAB_GAMFRA;Tone response curve (TRC) +TP_LOCALLAB_GAMM;Gamma +TP_LOCALLAB_GAMMASKCOL;Gamma mask +TP_LOCALLAB_GAMSH;Gamma +TP_LOCALLAB_GRADANG;Gradient angle +TP_LOCALLAB_GRADANG_TOOLTIP;Rotation angle in degrees : -180 0 +180 +TP_LOCALLAB_GRADFRA;Graduated Filter +TP_LOCALLAB_GRADGEN_TOOLTIP;Graduated filter is supplied with Color and Light & merge file, Exposure & mask, Shadows Highlight, Vibrance.\n\nVibrance, Color and Light & merge file, are provided with GF luminance, chrominance, Hue.\nFeather is located in settings. +TP_LOCALLAB_GRADLOGFRA;Graduated Filter Luminance +TP_LOCALLAB_GRADSTR;Gradient strength +TP_LOCALLAB_GRADSTRAB_TOOLTIP;Filter chroma strength +TP_LOCALLAB_GRADSTRCHRO;Gradient strength Chrominance +TP_LOCALLAB_GRADSTRHUE2;Gradient strength Hue +TP_LOCALLAB_GRADSTRHUE;Gradient strength Hue (merge file) +TP_LOCALLAB_GRADSTRHUE_TOOLTIP;Filter Hue strength +TP_LOCALLAB_GRADSTRLUM;Gradient strength Luminance +TP_LOCALLAB_GRADSTR_TOOLTIP;Filter strength in stops +TP_LOCALLAB_GRAINFRA;Film Grain 1:1 +TP_LOCALLAB_GRALWFRA;Graduated Filter Local contrast +TP_LOCALLAB_GRIDFRAME_TOOLTIP;It is desirable that the spot is in a flat area.\n\nOnly mode NORMAL and eventually Hue, Saturation, Color, Luminosity are concerned by Merge background +TP_LOCALLAB_GRIDONE;Color Toning +TP_LOCALLAB_GRIDTWO;Direct +TP_LOCALLAB_GUIDBL;Soft radius +TP_LOCALLAB_GUIDFILTER;Guided filter radius +TP_LOCALLAB_GUIDFILTER_TOOLTIP;Adapt this values according to images - can reduce or increase artifacts. +TP_LOCALLAB_HIGHMASKCOL;Highlights mask +TP_LOCALLAB_HLH;Curves H +TP_LOCALLAB_IND;Independent (mouse) +TP_LOCALLAB_INDSL;Independent (mouse + sliders) +TP_LOCALLAB_INVERS;Inverse +TP_LOCALLAB_ISOGR;Coarseness (ISO) +TP_LOCALLAB_LABEL;Local Adjustements +TP_LOCALLAB_LABBLURM;Mask Blur +TP_LOCALLAB_LABGRID;Color correction grid +TP_LOCALLAB_LABGRIDMERG;Background +TP_LOCALLAB_LABGRID_VALUES;High(a)=%1 High(b)=%2\nLow(a)=%3 Low(b)=%4 +TP_LOCALLAB_LABSTRUM;Mask Structure +TP_LOCALLAB_LAPLACC;ΔØ Mask Laplacian solve PDE +TP_LOCALLAB_LAPLACE;Δ - Laplacian threshold ΔE +TP_LOCALLAB_LAPLACEXP;∆ - Laplacian threshold +TP_LOCALLAB_LAPMASKCOL;∆ - Laplacian threshold mask +TP_LOCALLAB_LAPRAD_TOOLTIP;Avoid using Radius and Laplace Threshold simultaneously +TP_LOCALLAB_LC_FFTW_TOOLTIP;FFT improve quality and allow big radius, but increases the treatment time.\nThe treatment time depends on the surface to be treated.\nTo be used preferably for large radius.\n\nDimensions can be reduced by a few pixels to optimize FFTW.\nThis optimization can reduce the treatment time by a factor of 1.5 to 10.\n +TP_LOCALLAB_LEVELBLUR;Maximum Blur levels +TP_LOCALLAB_LEVELWAV;Ψ Wavelets Levels +TP_LOCALLAB_LEVELWAV_TOOLTIP;The Level is automatically adapted to the size of the spot and the preview.\nFrom level 9 size max 512 to level 1 size max = 4 +TP_LOCALLAB_LIGHTNESS;Lightness +TP_LOCALLAB_LIGHTRETI;Lightness +TP_LOCALLAB_LINEAR;Linearity +TP_LOCALLAB_LMASK_LEVEL_TOOLTIP;Give priority to action on midtones and high lights and by choosing the concerned wavelet levels +TP_LOCALLAB_LMASK_LL_TOOLTIP;Give priority to action on midtones and high lights +TP_LOCALLAB_LOCCONT;Unsharp Mask +TP_LOCALLAB_LOC_CONTRAST;Local contrast & Wavelet Pyramid Ψ +TP_LOCALLAB_LOC_CONTRASTPYR;Ψ Pyramid 1: +TP_LOCALLAB_LOC_CONTRASTPYRLAB; Graduated Filter - Edge Sharpness - Blur +TP_LOCALLAB_LOC_CONTRASTPYR2;Ψ Pyramid 2: +TP_LOCALLAB_LOC_CONTRASTPYR2LAB; Contrast by Levels- Tone Mapping(s) +TP_LOCALLAB_LOG;Encoding log +TP_LOCALLAB_LOGAUTO;Automatic +TP_LOCALLAB_LOGFRA;Source Gray Point +TP_LOCALLAB_LOGLIN;Logarithm mode +TP_LOCALLAB_LOGPFRA;Relative Exposure Levels +TP_LOCALLAB_LUM;Curves LL - CC +TP_LOCALLAB_LUMADARKEST;Darkest +TP_LOCALLAB_LUMASK;Luminance Background Mask +TP_LOCALLAB_LUMAWHITESEST;Whiteest +TP_LOCALLAB_LUMONLY;Luminance only +TP_LOCALLAB_MASFRAME;Mask and Merge +TP_LOCALLAB_MASFRAME_TOOLTIP;For all masks.\nTake into account deltaE image to avoid retouching the selection area when sliders gamma mask, slope mask, chroma mask and curves contrast , levels contrasts, and mask blur, structure(if enabled tool) are used.\nDisabled in Inverse +TP_LOCALLAB_MASK2;Contrast curve mask +TP_LOCALLAB_MASK;Mask +TP_LOCALLAB_MASKCOL;Mask Curves +TP_LOCALLAB_MASKH;Hue curve mask +TP_LOCALLAB_MASK_TOOLTIP;You can enable multiple masks for a single tool, this requires activating another tool (but without using the tool : sliders to 0,...) where is the mask you want to activate.\nMasks with this ability are marked '+'\nMasks with additional features are marked '*'\nThe number indicates the order of use of the masks.\n\nYou can combine the mask associated with the tool with an inverse mask.\nIn this case the new tool associated with the mask must be selected in inverse. +TP_LOCALLAB_MED;Medium +TP_LOCALLAB_MEDIAN;Median Low +TP_LOCALLAB_MEDNONE;None +TP_LOCALLAB_MERCOL;Color +TP_LOCALLAB_MERDCOL;Merge background (ΔE) +TP_LOCALLAB_MERELE;Lighten only +TP_LOCALLAB_MERFIV;Addition +TP_LOCALLAB_MERFOR;Color Dodge +TP_LOCALLAB_MERFOU;Multiply +TP_LOCALLAB_MERGE1COLFRA;Merge with Original or Previous or Background +TP_LOCALLAB_MERGECOLFRA;Mask: LCH & Structure +TP_LOCALLAB_MERGEFIV;Previous Spot(Mask 7) + Mask LCH +TP_LOCALLAB_MERGEFOU;Previous Spot(Mask 7) +TP_LOCALLAB_MERGENONE;None +TP_LOCALLAB_MERGEONE;Short Curves 'L' Mask +TP_LOCALLAB_MERGEOPA_TOOLTIP;Opacity merge % current Spot with original or previous Spot.\nContrast threshold : adjust result in function of Original contrast +TP_LOCALLAB_MERGETHR;Original(Mask 7) + Mask LCH +TP_LOCALLAB_MERGETWO;Original(Mask 7) +TP_LOCALLAB_MERGETYPE;Merge image and mask +TP_LOCALLAB_MERGETYPE_TOOLTIP;None, use all mask in LCH mode.\nShort curves 'L' mask, use a short circuit for mask 2, 3, 4, 6, 7.\nOriginal mask 8, blend current image with original +TP_LOCALLAB_MERHEI;Overlay +TP_LOCALLAB_MERHUE;Hue +TP_LOCALLAB_MERLUCOL;Luminance +TP_LOCALLAB_MERLUM;Luminosity +TP_LOCALLAB_MERNIN;Screen +TP_LOCALLAB_MERONE;Normal +TP_LOCALLAB_MERSAT;Saturation +TP_LOCALLAB_MERSEV0;Soft Light Illusion +TP_LOCALLAB_MERSEV1;Soft Light W3C +TP_LOCALLAB_MERSEV2;Hard Light +TP_LOCALLAB_MERSEV;Soft Light Photshop +TP_LOCALLAB_MERSIX;Divide +TP_LOCALLAB_MERTEN;Darken only +TP_LOCALLAB_MERTHI;Color Burn +TP_LOCALLAB_MERTHR;Difference +TP_LOCALLAB_MERTWE;Exclusion +TP_LOCALLAB_MERTWO;Substract +TP_LOCALLAB_METHOD_TOOLTIP;'Enhanced + chroma denoise' significantly increases processing times.\nBut reduce artifacts. +TP_LOCALLAB_MLABEL;Restored datas Min=%1 Max=%2 (Clip - Offset) +TP_LOCALLAB_MLABEL_TOOLTIP;'Should be' near min=0 max=32768 but others values are possible.\nYou can act on Clip Restored datas and Offset to normalize.\n\nRestored image with no mixture. +TP_LOCALLAB_MRFIV;Background +TP_LOCALLAB_MRFOU;Previous Spot +TP_LOCALLAB_MRONE;None +TP_LOCALLAB_MRTHR;Original Image +TP_LOCALLAB_MRTWO;Short Curves 'L' Mask +TP_LOCALLAB_NEIGH;Radius +TP_LOCALLAB_NOISECHROCOARSE;Chroma coarse (Wav) +TP_LOCALLAB_NOISECHROC_TOOLTIP;If superior to zero, high quality algorithm is enabled.\nCoarse is for slider >=0.02 +TP_LOCALLAB_NOISECHRODETAIL;Chroma detail recovery (DCT ƒ) +TP_LOCALLAB_NOISECHROFINE;Chroma fine (Wav) +TP_LOCALLAB_NOISEDETAIL_TOOLTIP;Disabled if slider = 100 +TP_LOCALLAB_NOISELEQUAL;Equalizer white-black +TP_LOCALLAB_NOISELUMCOARSE;Luminance coarse (Wav) +TP_LOCALLAB_NOISELUMDETAIL;Luminance detail recovery (DCT ƒ) +TP_LOCALLAB_NOISELUMFINE;Luminance fine 1 (Wav) +TP_LOCALLAB_NOISELUMFINETWO;Luminance fine 2 (Wav) +TP_LOCALLAB_NOISELUMFINEZERO;Luminance fine 0 (Wav) +TP_LOCALLAB_NOISEMETH;Denoise +TP_LOCALLAB_NONENOISE;None +TP_LOCALLAB_OFFS;Offset +TP_LOCALLAB_OFFSETWAV;Offset +TP_LOCALLAB_OPACOL;Opacity +TP_LOCALLAB_ORIGLC;Merge only with original image +TP_LOCALLAB_PASTELS2;Vibrance +TP_LOCALLAB_PDE;Dynamic Range compression + Standard ƒ +TP_LOCALLAB_PDEFRA;PDE IPOL - Contrast attenuator ƒ +TP_LOCALLAB_PDEFRAME_TOOLTIP;PDE IPOL - personal algorithm adapted from IPOL to Rawtherapee: lead to very different results and needs differents settings that Standard (negative black, gamma < 1,...)\nMay be usefull for low exposure.\n +TP_LOCALLAB_PREVIEWSEL;Preview selection ΔE +TP_LOCALLAB_PROXI;ΔE weakening +TP_LOCALLAB_QUALCURV_METHOD;Curves type +TP_LOCALLAB_QUAL_METHOD;Global quality +TP_LOCALLAB_RADIUS;Radius +TP_LOCALLAB_RADIUS_TOOLTIP;Above Radius 30 Use Fast Fourier Transform +TP_LOCALLAB_RADMASKCOL;Smooth Radius Mask +TP_LOCALLAB_RECT;Rectangle +TP_LOCALLAB_RECURS;Recursive references +TP_LOCALLAB_RECURS_TOOLTIP;Recalculate references for hue, luma, chroma after each module and after each RT-spot.\nAlso useful for working with masks. +TP_LOCALLAB_REFLABEL;Ref. (0..1) Chroma=%1 Luma=%2 Hue=%3 +TP_LOCALLAB_REN_DIALOG_LAB;Enter the new Control Spot name +TP_LOCALLAB_REN_DIALOG_NAME;Renaming Control Spot +TP_LOCALLAB_RESETSHOW;Reset All Show Modifications +TP_LOCALLAB_RESID;Residual Image +TP_LOCALLAB_RESIDBLUR;Blur Residual Image +TP_LOCALLAB_RESIDCHRO;Residual image Chroma +TP_LOCALLAB_RESIDCOMP;Compress Residual image +TP_LOCALLAB_RESIDCONT;Residual image Contrast +TP_LOCALLAB_RETI;Dehaze - Retinex Strong local contrast +TP_LOCALLAB_RETIFRA;Retinex +TP_LOCALLAB_RETIM;Original Retinex +TP_LOCALLAB_RETITOOLFRA;Retinex Tools +TP_LOCALLAB_RETI_FFTW_TOOLTIP;FFT improve quality and allow big radius, but increases the treatment time.\nThe treatment time depends on the surface to be treated\nThe treatment time depends on the value of scale (be carefull to high values).\nTo be used preferably for large radius.\n\nDimensions can be reduced by a few pixels to optimize FFTW.\nThis optimization can reduce the treatment time by a factor of 1.5 to 10.\nOptimization not used in Preview +TP_LOCALLAB_RETI_NEIGH_VART_TOOLTIP;Adapt these values according to images - if misty images and depending on whether you want to act on the front or the background +TP_LOCALLAB_REWEI;Reweighting iterates +TP_LOCALLAB_RGB;RGB Tone Curve +TP_LOCALLAB_ROW_NVIS;Not visible +TP_LOCALLAB_ROW_VIS;Visible +TP_LOCALLAB_SATUR;Saturation +TP_LOCALLAB_SAVREST;Save - Restore Current Image +TP_LOCALLAB_SCALEGR;Scale +TP_LOCALLAB_SCALERETI;Scale +TP_LOCALLAB_SCALTM;Scale +TP_LOCALLAB_SCOPEMASK;Scope Mask ΔE Image +TP_LOCALLAB_SCOPEMASK_TOOLTIP;Enabled if Mask DeltaE Image is enabled.\nLow values avoid retouching selected area +TP_LOCALLAB_SENSI;Scope +TP_LOCALLAB_SENSIBN;Scope +TP_LOCALLAB_SENSICB;Scope +TP_LOCALLAB_SENSIDEN;Scope +TP_LOCALLAB_SENSIEXCLU;Scope +TP_LOCALLAB_SENSIEXCLU_TOOLTIP;Adjust color to include in exclusion! +TP_LOCALLAB_SENSIH;Scope +TP_LOCALLAB_SENSIH_TOOLTIP; Adjust scope of action:\nSmall values limit action to colors very similar to those under the center spot.\nHigh values let the tool act upon a wider range of colors.\nValues smaller than 20 lead to a better algorithm. +TP_LOCALLAB_SENSILOG;Scope +TP_LOCALLAB_SENSIS;Scope +TP_LOCALLAB_SENSIS_TOOLTIP;Adjust scope of action:\nSmall values limit action to colors very similar to those under the center spot.\nHigh values let the tool act upon a wider range of colors.\nValues smaller than 20 lead to a better algorithm. +TP_LOCALLAB_SENSI_TOOLTIP;Adjust scope of action:\nSmall values limit action to colors very similar to those under the center spot.\nHigh values let the tool act upon a wider range of colors.\nValues smaller than 20 lead to a better algorithm. +TP_LOCALLAB_SETTINGS;Settings +TP_LOCALLAB_SH1;Shadows Highlights +TP_LOCALLAB_SH2;Equalizer +TP_LOCALLAB_SHADEX;Shadows +TP_LOCALLAB_SHADEXCOMP;Shadows compression & tonal width +TP_LOCALLAB_SHADHIGH;Shadows Highlights-Gradient - Tone Equalizer - TRC +TP_LOCALLAB_SHADOWHIGHLIGHT_TOOLTIP;Can be used instead - or in complement - of exposure module in difficult cases.\nThe use of Denoise may be necessary : lightening the shadows.\n\nCan be used as graduated filter (increase Scope) +TP_LOCALLAB_SHAMASKCOL;Shadows mask +TP_LOCALLAB_SHAPETYPE;Shape RT-spot area +TP_LOCALLAB_SHAPE_TOOLTIP;Rectangle is only in normal mode. +TP_LOCALLAB_SHARAMOUNT;Amount +TP_LOCALLAB_SHARBLUR;Blur radius +TP_LOCALLAB_SHARDAMPING;Damping +TP_LOCALLAB_SHARITER;Iterations +TP_LOCALLAB_SHARFRAME;Modifications +TP_LOCALLAB_SHARP;Sharpening +TP_LOCALLAB_SHARRADIUS;Radius +TP_LOCALLAB_SHORTC;Short Curves 'L' Mask +TP_LOCALLAB_SHORTCMASK_TOOLTIP;Short circuit the 2 curves L(L) and L(H).\nAllows you to mix the current image with the original image modified by the mask job.\nUsable with masks 2, 3, 4, 6, 7 +TP_LOCALLAB_SHOWC1;Merge file +TP_LOCALLAB_SHOWC;9+* - Mask and modifications +TP_LOCALLAB_SHOWCB;2+ - Mask and modifications +TP_LOCALLAB_SHOWDCT;Show process Fourier ƒ +TP_LOCALLAB_SHOWE;8+ - Mask and modifications +TP_LOCALLAB_SHOWFOURIER;Fourier ƒ(dct) +TP_LOCALLAB_SHOWLAPLACE;∆ Laplacian (first) +TP_LOCALLAB_SHOWLC;6 - Mask and modifications +TP_LOCALLAB_SHOWMASK;Show mask +TP_LOCALLAB_SHOWMASKCOL_TOOLTIP;Display modifications.\nBeware, you can only view one modification (color and light or Exposure or Shadows-Highlight or TM or CBDL or Retinex MSR or Blur).\n\nUse Mask is before algorihtm shape detection +TP_LOCALLAB_SHOWMASKSOFT_TOOLTIP;Show process Fourier:\nShows the different stages of the process.\nLaplace - builds the second derivative according to the threshold (first step).\nFourier -shows the transformed Laplacian with DCT.\nPoisson - show solution of Poisson DCE.\nNormalize - show result without normalization luminance. +TP_LOCALLAB_SHOWMNONE;None +TP_LOCALLAB_SHOWMODIF;Show modifications without mask +TP_LOCALLAB_SHOWMODIFMASK;Show modifications with mask +TP_LOCALLAB_SHOWNORMAL;Normalize luminance (no) +TP_LOCALLAB_SHOWPLUS;1+* - Mask and modifications - Smooth-Blur & Denoise +TP_LOCALLAB_SHOWPOISSON;Poisson (pde ƒ) +TP_LOCALLAB_SHOWR;7 - Mask and modifications +TP_LOCALLAB_SHOWS;5+* - Mask and modifications +TP_LOCALLAB_SHOWSTRUC;Show structure Spot +TP_LOCALLAB_SHOWSTRUCEX;Show structure Spot - disabled in "normal" +TP_LOCALLAB_SHOWT;4 - Mask and modifications +TP_LOCALLAB_SHOWVI;3 - Mask and modifications +TP_LOCALLAB_SIGMAWAV;Sigma +TP_LOCALLAB_SIM;Simple +TP_LOCALLAB_SLOMASKCOL;Slope mask +TP_LOCALLAB_SLOSH;Slope +TP_LOCALLAB_SOFT;Soft Light & Original Retinex +TP_LOCALLAB_SOFTM;Soft Light +TP_LOCALLAB_SOFTMETHOD_TOOLTIP;Original Retinex is very different from others Retinex method.\nIts acts on grey and balance luminance. +TP_LOCALLAB_SOFTRADIUSCOL;Soft radius +TP_LOCALLAB_SOFTRETI;Reduce artifact ΔE +TP_LOCALLAB_SOFTRETI_TOOLTIP;Take into account deltaE to improve Transmission map +TP_LOCALLAB_SOURCE_GRAY;Value +TP_LOCALLAB_SPECIAL;Special use of RGB curves +TP_LOCALLAB_SPOTNAME;Control Spot # +TP_LOCALLAB_STD;Standard +TP_LOCALLAB_STR;Strength +TP_LOCALLAB_STRBL;Strength +TP_LOCALLAB_STREN;Compression Strength +TP_LOCALLAB_STRENG;Strength +TP_LOCALLAB_STRENGR;Strength +TP_LOCALLAB_STRENGTH;Noise +TP_LOCALLAB_STRGRID;Strength +TP_LOCALLAB_STRRETI_TOOLTIP;if Strength Retinex < 0.2 only Dehaze is enabled.\nif Strength Retinex >= 0.1 Dehaze is in luminance mode. +TP_LOCALLAB_STRUC;Structure +TP_LOCALLAB_STRUCCOL1;Structure Spot +TP_LOCALLAB_STRUCCOL;Structure +TP_LOCALLAB_STRUMASKCOL;Structure mask strength +TP_LOCALLAB_STYPE;Shape method +TP_LOCALLAB_STYPE_TOOLTIP;You can choose between:\nSymmetrical - left handle linked to right, top handle linked to bottom.\nIndependent - all handles are independent. +TP_LOCALLAB_SYM;Symmetrical (mouse) +TP_LOCALLAB_SYMSL;Symmetrical (mouse + sliders) +TP_LOCALLAB_TARGET_GRAY;Target Gray Point +TP_LOCALLAB_THRES;Threshold structure +TP_LOCALLAB_THRESDELTAE;Threshold ΔE-scope +TP_LOCALLAB_THRESRETI;Threshold +TP_LOCALLAB_THRESWAV;Balance Threshold +TP_LOCALLAB_TLABEL2;TM Effective Tm=%1 TM=%2 +TP_LOCALLAB_TLABEL;TM Datas Min=%1 Max=%2 Mean=%3 Sigma=%4 (Threshold) +TP_LOCALLAB_TLABEL_TOOLTIP;Transmission map result.\nMin and Max are used by Variance.\nTm=Min TM=Max of Transmission Map.\nYou can act on Threshold to normalize +TP_LOCALLAB_TM;Tone Mapping - Reinforced texture +TP_LOCALLAB_TM_MASK;Use transmission map +TP_LOCALLAB_TONEMAPESTOP_TOOLTIP;Increase Edge stopping - or Reweighting iterates, increase processing time - but increases the effects +TP_LOCALLAB_TONEMAP_TOOLTIP;Tone Mapping - main menu must be disabled +TP_LOCALLAB_TOOLCOL;Structure mask as tool +TP_LOCALLAB_TOOLMASK;Tools +TP_LOCALLAB_TRANSIT;Transition Gradient +TP_LOCALLAB_TRANSITGRAD;Transition differentiation XY +TP_LOCALLAB_TRANSITGRAD_TOOLTIP;Changes the transition of the abscissa to that of the ordinate +TP_LOCALLAB_TRANSITVALUE;Transition value +TP_LOCALLAB_TRANSITWEAK;Transition weakening +TP_LOCALLAB_TRANSITWEAK_TOOLTIP;Adjust weakening : change smoothness process - 1 linear - 2 parabolic - 3 cubic - 10 ^10 +TP_LOCALLAB_TRANSIT_TOOLTIP;Adjust smoothness of transition between affected and unaffected areas. +TP_LOCALLAB_TRANSMISSIONGAIN;Transmission gain +TP_LOCALLAB_TRANSMISSIONMAP;Transmission map +TP_LOCALLAB_TRANSMISSION_TOOLTIP;Transmission according to transmission.\nAbscissa: transmission from negative values (min), mean, and positives values (max).\nOrdinate: amplification or reduction.\nYou can act on this curve to change Transmission and reduce the artifacts +TP_LOCALLAB_USEMASK;Use mask +TP_LOCALLAB_VART;Variance (contrast) +TP_LOCALLAB_VIBRANCE;Vibrance - Warm & Cool TP_LOCALLAB_VIS_TOOLTIP;Click to show/hide selected Control Spot.\nCtrl+click to show/hide all Control Spot. TP_LOCALLAB_LIST_NAME;Add tool to current spot... TP_LOCALLAB_COLOR_TOOLNAME;Locallab Color&Light @@ -2246,6 +2857,26 @@ TP_LOCALLAB_SHARP_TOOLNAME;Locallab Sharpening TP_LOCALLAB_LC_TOOLNAME;Locallab Local Constrast TP_LOCALLAB_CBDL_TOOLNAME;Locallab CBDL TP_LOCALLAB_DEN_TOOLNAME;Locallab Denoise +TP_LOCALLAB_LOG_TOOLNAME;Locallab Encoding log +TP_LOCALLAB_WAMASKCOL;Ψ Mask Wavelet level +TP_LOCALLAB_WARM;Warm - Cool & Color artifacts +TP_LOCALLAB_WARM_TOOLTIP;This slider use Ciecam algorithm and acts as White Balance, it can warm or cool the area selected.\nIt can also in some cases reduce color artifacts. +TP_LOCALLAB_WAV;Levels local contrast +TP_LOCALLAB_WAVEDG;Local contrast +TP_LOCALLAB_WAVCOMP;Compression by Level +TP_LOCALLAB_WAVCOMPRE;(un)Compression by Level +TP_LOCALLAB_WAVCON;Contrast by Level +TP_LOCALLAB_WAVDEN;Luminance denoise by level (0 1 2 + 3 and more) +TP_LOCALLAB_WASDEN_TOOLTIP;Denoise luminance for the 3 first levels (fine).\nThe right limit of the curve correspond to coarse : level 3 and beyond +TP_LOCALLAB_WAVE;Ψ Wavelet +TP_LOCALLAB_WAVEEDG_TOOLTIP;Requires that at least the first 4 levels are usable +TP_LOCALLAB_WAVHIGH;Ψ Wavelet high +TP_LOCALLAB_WAVLEV;Blur by Level +TP_LOCALLAB_WAVLOW;Ψ Wavelet low +TP_LOCALLAB_WAVMASK;Ψ Mask Levels local contrast +TP_LOCALLAB_WAVMED;Ψ Wavelet normal +TP_LOCALLAB_WEDIANHI;Median Hi +TP_LOCALLAB_WHITE_EV;White Ev TP_LOCAL_HEIGHT;Bottom TP_LOCAL_HEIGHT_T;Top TP_LOCAL_WIDTH;Right @@ -2269,6 +2900,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 @@ -2441,8 +3073,8 @@ TP_RETINEX_MAP_NONE;None TP_RETINEX_MEDIAN;Transmission median filter TP_RETINEX_METHOD;Method TP_RETINEX_METHOD_TOOLTIP;Low = Reinforce low light.\nUniform = Equalize action.\nHigh = Reinforce high light.\nHighlights = Remove magenta in highlights. -TP_RETINEX_MLABEL;Restored haze-free Min=%1 Max=%2 -TP_RETINEX_MLABEL_TOOLTIP;Should be near min=0 max=32768\nRestored image with no mixture. +TP_RETINEX_MLABEL;Restored data Min=%1 Max=%2 +TP_RETINEX_MLABEL_TOOLTIP;'Should be' near min=0 max=32768 but others values are possible\nRestored image with no mixture. TP_RETINEX_NEIGHBOR;Radius TP_RETINEX_NEUTRAL;Reset TP_RETINEX_NEUTRAL_TIP;Reset all sliders and curves to their default values. @@ -2455,11 +3087,11 @@ TP_RETINEX_SLOPE;Free gamma slope TP_RETINEX_STRENGTH;Strength TP_RETINEX_THRESHOLD;Threshold TP_RETINEX_THRESHOLD_TOOLTIP;Limits in/out.\nIn = image source,\nOut = image gauss. -TP_RETINEX_TLABEL;TM Min=%1 Max=%2 Mean=%3 Sigma=%4 -TP_RETINEX_TLABEL2;TM Tm=%1 TM=%2 -TP_RETINEX_TLABEL_TOOLTIP;Transmission map result.\nMin and Max are used by Variance.\nMean and Sigma.\nTm=Min TM=Max of transmission map. +TP_RETINEX_TLABEL;TM Datas Min=%1 Max=%2 Mean=%3 Sigma=%4 +TP_RETINEX_TLABEL2;TM Effective Tm=%1 TM=%2 +TP_RETINEX_TLABEL_TOOLTIP;Transmission map result.\nMin and Max are used by Variance.\nTm=Min TM=Max of Transmission Map. TP_RETINEX_TRANF;Transmission -TP_RETINEX_TRANSMISSION;Transmission map +TP_RETINEX_TRANSMISSION;Transmission map TP_RETINEX_TRANSMISSION_TOOLTIP;Transmission according to transmission.\nAbscissa: transmission from negative values (min), mean, and positives values (max).\nOrdinate: amplification or reduction. TP_RETINEX_UNIFORM;Uniform TP_RETINEX_VARIANCE;Contrast @@ -2499,10 +3131,12 @@ TP_SHARPENING_EDRADIUS;Radius TP_SHARPENING_EDTOLERANCE;Edge tolerance TP_SHARPENING_HALOCONTROL;Halo control TP_SHARPENING_HCAMOUNT;Amount +TP_SHARPENING_ITERCHECK;Auto limit iterations 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 @@ -2518,7 +3152,7 @@ TP_SOFTLIGHT_LABEL;Soft Light TP_SOFTLIGHT_STRENGTH;Strength TP_TM_FATTAL_AMOUNT;Amount TP_TM_FATTAL_ANCHOR;Anchor -TP_TM_FATTAL_LABEL;Dynamic Range Compression +TP_TM_FATTAL_LABEL;Dynamic Range Compression ƒ TP_TM_FATTAL_THRESHOLD;Detail TP_VIBRANCE_AVOIDCOLORSHIFT;Avoid color shift TP_VIBRANCE_CURVEEDITOR_SKINTONES;HH @@ -2601,6 +3235,7 @@ TP_WAVELET_CURVEEDITOR_HH;HH TP_WAVELET_CURVEEDITOR_HH_TOOLTIP;Modifies the residual image's hue as a function of hue. TP_WAVELET_DALL;All directions TP_WAVELET_DAUB;Edge performance +TP_WAVELET_DAUBLOCAL;Wavelet Edge performance TP_WAVELET_DAUB2;D2 - low TP_WAVELET_DAUB4;D4 - standard TP_WAVELET_DAUB6;D6 - standard plus diff --git a/rtdata/mime-types b/rtdata/mime-types index 505b00140..bfd1ccbd9 100644 --- a/rtdata/mime-types +++ b/rtdata/mime-types @@ -6,6 +6,7 @@ image/png; image/tiff; image/x-adobe-dng; image/x-canon-cr2; +image/x-canon-cr3; image/x-canon-crf; image/x-canon-crw; image/x-fuji-raf; diff --git a/rtdata/options/options.lin b/rtdata/options/options.lin index 1d2f9faac..580390b28 100644 --- a/rtdata/options/options.lin +++ b/rtdata/options/options.lin @@ -12,8 +12,8 @@ MultiUser=true [File Browser] # Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include) -ParseExtensions=3fr;arw;arq;cr2;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; -ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1; +ParseExtensions=3fr;arw;arq;cr2;cr3;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; +ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1; [Output] PathTemplate=%p1/converted/%f diff --git a/rtdata/options/options.osx b/rtdata/options/options.osx index 11c5da4c8..58e0a5604 100644 --- a/rtdata/options/options.osx +++ b/rtdata/options/options.osx @@ -12,8 +12,8 @@ MultiUser=true [File Browser] # Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include) -ParseExtensions=3fr;arw;arq;cr2;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; -ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1; +ParseExtensions=3fr;arw;arq;cr2;cr3;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; +ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1; [Output] PathTemplate=%p1/converted/%f diff --git a/rtdata/options/options.win b/rtdata/options/options.win index a4a767bf4..a54e021b1 100644 --- a/rtdata/options/options.win +++ b/rtdata/options/options.win @@ -14,8 +14,8 @@ UseSystemTheme=false [File Browser] # Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include) -ParseExtensions=3fr;arw;arq;cr2;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; -ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1; +ParseExtensions=3fr;arw;arq;cr2;cr3;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; +ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1; [Output] PathTemplate=%p1/converted/%f 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/Pixel Shift/PS ISO Low.pp3 b/rtdata/profiles/Pixel Shift/PS ISO Low.pp3 index 5587b19e0..286b5a289 100644 --- a/rtdata/profiles/Pixel Shift/PS ISO Low.pp3 +++ b/rtdata/profiles/Pixel Shift/PS ISO Low.pp3 @@ -1,18 +1,8 @@ [Sharpening] -Enabled=true -Contrast=5 -Method=rld -DeconvRadius=0.75 -DeconvAmount=100 -DeconvDamping=0 -DeconvIterations=30 +Enabled=false [SharpenMicro] -Enabled=true -Contrast=15 -Matrix=false -Strength=20 -Uniformity=5 +Enabled=false [RAW] CA=true @@ -38,3 +28,6 @@ pixelShiftBlur=true pixelShiftSmoothFactor=0.69999999999999996 pixelShiftLmmse=false pixelShiftNonGreenCross=true + +[PostDemosaicSharpening] +Enabled=true diff --git a/rtdata/profiles/Pixel Shift/PS No Motion.pp3 b/rtdata/profiles/Pixel Shift/PS No Motion.pp3 index f1d889f97..0975251e2 100644 --- a/rtdata/profiles/Pixel Shift/PS No Motion.pp3 +++ b/rtdata/profiles/Pixel Shift/PS No Motion.pp3 @@ -1,18 +1,8 @@ [Sharpening] -Enabled=true -Contrast=5 -Method=rld -DeconvRadius=0.75 -DeconvAmount=100 -DeconvDamping=0 -DeconvIterations=30 +Enabled=false [SharpenMicro] -Enabled=true -Contrast=15 -Matrix=false -Strength=20 -Uniformity=5 +Enabled=false [RAW] CA=true @@ -22,3 +12,6 @@ Method=pixelshift PixelShiftMotion=0 PixelShiftMotionCorrection=5 PixelShiftMotionCorrectionMethod=0 + +[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..350afc45e 100644 --- a/rtdata/rawtherapee.desktop.in +++ b/rtdata/rawtherapee.desktop.in @@ -2,7 +2,7 @@ Type=Application Version=1.0 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,11 @@ 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; +MimeType=image/jpeg;image/png;image/tiff;image/x-adobe-dng;image/x-canon-cr2;image/x-canon-cr3;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;inode/directory; +Categories=Graphics;Photography;2DGraphics;RasterGraphics;GTK; +Keywords=raw;photo;photography;develop;pp3;graphics; +StartupNotify=true StartupWMClass=rawtherapee diff --git a/rtdata/themes/RawTherapee-GTK3-20_.css b/rtdata/themes/RawTherapee-GTK3-20_.css index eb3a89295..e9674302b 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 . */ /***************************/ @@ -640,11 +640,11 @@ spinbutton entry { } spinbutton button { margin: 0; - padding: 0; - border-radius: 0; + padding: 0; + border-radius: 0; } spinbutton button.up { - border-radius: 0 0.16666666666666666666em 0.16666666666666666666em 0; + border-radius: 0 0.16666666666666666666em 0.16666666666666666666em 0; } entry:disabled, spinbutton:disabled { @@ -852,7 +852,7 @@ flowboxchild:selected { color: #CCCCCC; padding: 0; margin: 0 0.25em 0 0.25em; - font-size: 1.1em; + font-size: 1.1em; } #MyExpanderTitle:hover { background-color: #202020; @@ -966,7 +966,7 @@ fontchooser scrolledwindow, } #PlacesPaned { - margin: 0; + margin: 0; padding: 0 0.4166666666666666em 0 0; } #PlacesPaned > box:nth-child(1) scrolledwindow + grid { @@ -1061,7 +1061,7 @@ dialog frame > label:not(.dummy) { #LabelRightNotebook { padding: 0.4166666666666666em; margin: 0.1666666666666666em; - font-size: 1.25em; + font-size: 1.25em; } #ToolPanelNotebook { diff --git a/rtdata/themes/RawTherapee-GTK3-_19.css b/rtdata/themes/RawTherapee-GTK3-_19.css index a796b60a1..f4bec23b1 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 . */ * { @@ -46,7 +46,7 @@ GtkBox { border-style: none; border-radius: 0; margin: 0; - padding: 0; + padding: 0; } GtkGrid { 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..f4d082199 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 . // //////////////////////////////////////////////////////////////// @@ -28,6 +28,14 @@ #include "gauss.h" #include "median.h" #include "StopWatch.h" + +namespace +{ +unsigned fc(const unsigned int cfa[2][2], int r, int c) { + return cfa[r & 1][c & 1]; +} +} + namespace { bool LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* pfSolution) @@ -134,6 +142,7 @@ float* RawImageSource::CA_correct_RT( } // multithreaded and vectorized by Ingo Weyrich + const unsigned int cfa[2][2] = {{FC(0,0), FC(0,1)}, {FC(1,0), FC(1,1)}}; constexpr int ts = 128; constexpr int tsh = ts / 2; constexpr int cb = 2; // 2 pixels border will be excluded from correction @@ -144,7 +153,7 @@ float* RawImageSource::CA_correct_RT( // Test for RGB cfa for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { - if (FC(i, j) == 3) { + if (fc(cfa, i, j) == 3) { std::cout << "CA correction supports only RGB Colour filter arrays" << std::endl; return buffer; } @@ -163,7 +172,7 @@ float* RawImageSource::CA_correct_RT( #pragma omp parallel for #endif for (int i = cb; i < H - cb; ++i) { - for (int j = cb + (FC(i, 0) & 1); j < W - cb; j += 2) { + for (int j = cb + (fc(cfa, i, 0) & 1); j < W - cb; j += 2) { (*oldraw)[i - cb][(j - cb) / 2] = rawData[i][j]; } } @@ -194,7 +203,7 @@ float* RawImageSource::CA_correct_RT( //block CA shift values and weight assigned to block float* const blockwt = buffer + (height * width); - memset(blockwt, 0, vblsz * hblsz * (2 * 2 + 1) * sizeof(float)); + memset(blockwt, 0, static_cast(vblsz) * hblsz * (2 * 2 + 1) * sizeof(float)); float (*blockshifts)[2][2] = (float (*)[2][2])(blockwt + vblsz * hblsz); // Because we can't break parallel processing, we need a switch do handle the errors @@ -316,12 +325,12 @@ float* RawImageSource::CA_correct_RT( int cc = ccmin; int col = cc + left; #ifdef __SSE2__ - int c0 = FC(rr, cc); + int c0 = fc(cfa, rr, cc); if (c0 == 1) { rgb[c0][rr * ts + cc] = rawData[row][col] / 65535.f; cc++; col++; - c0 = FC(rr, cc); + c0 = fc(cfa, rr, cc); } int indx1 = rr * ts + cc; for (; cc < ccmax - 7; cc+=8, col+=8, indx1 += 8) { @@ -334,7 +343,7 @@ float* RawImageSource::CA_correct_RT( } #endif for (; cc < ccmax; cc++, col++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); int indx1 = rr * ts + cc; rgb[c][indx1 >> ((c & 1) ^ 1)] = rawData[row][col] / 65535.f; } @@ -344,7 +353,7 @@ float* RawImageSource::CA_correct_RT( if (rrmin > 0) { for (int rr = 0; rr < border; rr++) { for (int cc = ccmin; cc < ccmax; cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][(rr * ts + cc) >> ((c & 1) ^ 1)] = rgb[c][((border2 - rr) * ts + cc) >> ((c & 1) ^ 1)]; } } @@ -353,7 +362,7 @@ float* RawImageSource::CA_correct_RT( if (rrmax < rr1) { for (int rr = 0; rr < border; rr++) { for (int cc = ccmin; cc < ccmax; cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][((rrmax + rr)*ts + cc) >> ((c & 1) ^ 1)] = rawData[(height - rr - 2)][left + cc] / 65535.f; } } @@ -362,7 +371,7 @@ float* RawImageSource::CA_correct_RT( if (ccmin > 0) { for (int rr = rrmin; rr < rrmax; rr++) { for (int cc = 0; cc < border; cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][(rr * ts + cc) >> ((c & 1) ^ 1)] = rgb[c][(rr * ts + border2 - cc) >> ((c & 1) ^ 1)]; } } @@ -371,7 +380,7 @@ float* RawImageSource::CA_correct_RT( if (ccmax < cc1) { for (int rr = rrmin; rr < rrmax; rr++) { for (int cc = 0; cc < border; cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][(rr * ts + ccmax + cc) >> ((c & 1) ^ 1)] = rawData[(top + rr)][(width - cc - 2)] / 65535.f; } } @@ -381,7 +390,7 @@ float* RawImageSource::CA_correct_RT( if (rrmin > 0 && ccmin > 0) { for (int rr = 0; rr < border; rr++) { for (int cc = 0; cc < border; cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][(rr * ts + cc) >> ((c & 1) ^ 1)] = rawData[border2 - rr][border2 - cc] / 65535.f; } } @@ -390,7 +399,7 @@ float* RawImageSource::CA_correct_RT( if (rrmax < rr1 && ccmax < cc1) { for (int rr = 0; rr < border; rr++) { for (int cc = 0; cc < border; cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][((rrmax + rr)*ts + ccmax + cc) >> ((c & 1) ^ 1)] = rawData[(height - rr - 2)][(width - cc - 2)] / 65535.f; } } @@ -399,7 +408,7 @@ float* RawImageSource::CA_correct_RT( if (rrmin > 0 && ccmax < cc1) { for (int rr = 0; rr < border; rr++) { for (int cc = 0; cc < border; cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][(rr * ts + ccmax + cc) >> ((c & 1) ^ 1)] = rawData[(border2 - rr)][(width - cc - 2)] / 65535.f; } } @@ -408,7 +417,7 @@ float* RawImageSource::CA_correct_RT( if (rrmax < rr1 && ccmin > 0) { for (int rr = 0; rr < border; rr++) { for (int cc = 0; cc < border; cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][((rrmax + rr)*ts + cc) >> ((c & 1) ^ 1)] = rawData[(height - rr - 2)][(border2 - cc)] / 65535.f; } } @@ -423,9 +432,9 @@ float* RawImageSource::CA_correct_RT( #endif for (int rr = 3; rr < rr1 - 3; rr++) { int row = rr + top; - int cc = 3 + (FC(rr,3) & 1); + int cc = 3 + (fc(cfa, rr,3) & 1); int indx = rr * ts + cc; - int c = FC(rr,cc); + int c = fc(cfa, rr,cc); #ifdef __SSE2__ for (; cc < cc1 - 9; cc+=8, indx+=8) { //compute directional weights using image gradients @@ -459,7 +468,7 @@ float* RawImageSource::CA_correct_RT( } if (row > -1 && row < height) { - int offset = (FC(row,max(left + 3, 0)) & 1); + int offset = (fc(cfa, row,max(left + 3, 0)) & 1); int col = max(left + 3, 0) + offset; int indx = rr * ts + 3 - (left < 0 ? (left+3) : 0) + offset; #ifdef __SSE2__ @@ -477,9 +486,9 @@ float* RawImageSource::CA_correct_RT( vfloat zd25v = F2V(0.25f); #endif for (int rr = 4; rr < rr1 - 4; rr++) { - int cc = 4 + (FC(rr, 2) & 1); + int cc = 4 + (fc(cfa, rr, 2) & 1); int indx = rr * ts + cc; - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); #ifdef __SSE2__ for (; cc < cc1 - 10; cc += 8, indx += 8) { vfloat rgb1v = LC2VFU(rgb[1][indx]); @@ -543,9 +552,9 @@ float* RawImageSource::CA_correct_RT( // along line segments, find the point along each segment that minimizes the colour variance // averaged over the tile; evaluate for up/down and left/right away from R/B grid point for (int rr = 8; rr < rr1 - 8; rr++) { - int cc = 8 + (FC(rr, 2) & 1); + int cc = 8 + (fc(cfa, rr, 2) & 1); int indx = rr * ts + cc; - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); #ifdef __SSE2__ vfloat coeff00v = ZEROV; vfloat coeff01v = ZEROV; @@ -701,7 +710,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 +812,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; } } @@ -863,14 +876,14 @@ float* RawImageSource::CA_correct_RT( int indx = row * width + col; int indx1 = rr * ts + cc; #ifdef __SSE2__ - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); if (c & 1) { rgb[1][indx1] = rawData[row][col] / 65535.f; indx++; indx1++; cc++; col++; - c = FC(rr, cc); + c = fc(cfa, rr, cc); } for (; cc < ccmax - 7; cc += 8, col += 8, indx += 8, indx1 += 8) { vfloat val1v = LVFU(rawData[row][col]) / c65535v; @@ -882,7 +895,7 @@ float* RawImageSource::CA_correct_RT( } #endif for (; cc < ccmax; cc++, col++, indx++, indx1++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][indx1 >> ((c & 1) ^ 1)] = rawData[row][col] / 65535.f; if ((c & 1) == 0) { @@ -895,7 +908,7 @@ float* RawImageSource::CA_correct_RT( if (rrmin > 0) { for (int rr = 0; rr < border; rr++) { for (int cc = ccmin; cc < ccmax; cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][(rr * ts + cc) >> ((c & 1) ^ 1)] = rgb[c][((border2 - rr) * ts + cc) >> ((c & 1) ^ 1)]; rgb[1][rr * ts + cc] = rgb[1][(border2 - rr) * ts + cc]; } @@ -905,7 +918,7 @@ float* RawImageSource::CA_correct_RT( if (rrmax < rr1) { for (int rr = 0; rr < std::min(border, rr1 - rrmax); rr++) { for (int cc = ccmin; cc < ccmax; cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][((rrmax + rr)*ts + cc) >> ((c & 1) ^ 1)] = (rawData[(height - rr - 2)][left + cc]) / 65535.f; if ((c & 1) == 0) { rgb[1][(rrmax + rr)*ts + cc] = Gtmp[((height - rr - 2) * width + left + cc) >> 1]; @@ -917,7 +930,7 @@ float* RawImageSource::CA_correct_RT( if (ccmin > 0) { for (int rr = rrmin; rr < rrmax; rr++) { for (int cc = 0; cc < border; cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][(rr * ts + cc) >> ((c & 1) ^ 1)] = rgb[c][(rr * ts + border2 - cc) >> ((c & 1) ^ 1)]; rgb[1][rr * ts + cc] = rgb[1][rr * ts + border2 - cc]; } @@ -927,7 +940,7 @@ float* RawImageSource::CA_correct_RT( if (ccmax < cc1) { for (int rr = rrmin; rr < rrmax; rr++) { for (int cc = 0; cc < std::min(border, cc1 - ccmax); cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][(rr * ts + ccmax + cc) >> ((c & 1) ^ 1)] = (rawData[(top + rr)][(width - cc - 2)]) / 65535.f; if ((c & 1) == 0) { rgb[1][rr * ts + ccmax + cc] = Gtmp[((top + rr) * width + (width - cc - 2)) >> 1]; @@ -940,7 +953,7 @@ float* RawImageSource::CA_correct_RT( if (rrmin > 0 && ccmin > 0) { for (int rr = 0; rr < border; rr++) { for (int cc = 0; cc < border; cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][(rr * ts + cc) >> ((c & 1) ^ 1)] = (rawData[border2 - rr][border2 - cc]) / 65535.f; if ((c & 1) == 0) { rgb[1][rr * ts + cc] = Gtmp[((border2 - rr) * width + border2 - cc) >> 1]; @@ -952,7 +965,7 @@ float* RawImageSource::CA_correct_RT( if (rrmax < rr1 && ccmax < cc1) { for (int rr = 0; rr < std::min(border, rr1 - rrmax); rr++) { for (int cc = 0; cc < std::min(border, cc1 - ccmax); cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][((rrmax + rr)*ts + ccmax + cc) >> ((c & 1) ^ 1)] = (rawData[(height - rr - 2)][(width - cc - 2)]) / 65535.f; if ((c & 1) == 0) { rgb[1][(rrmax + rr)*ts + ccmax + cc] = Gtmp[((height - rr - 2) * width + (width - cc - 2)) >> 1]; @@ -964,7 +977,7 @@ float* RawImageSource::CA_correct_RT( if (rrmin > 0 && ccmax < cc1) { for (int rr = 0; rr < border; rr++) { for (int cc = 0; cc < std::min(border, cc1 - ccmax); cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][(rr * ts + ccmax + cc) >> ((c & 1) ^ 1)] = (rawData[(border2 - rr)][(width - cc - 2)]) / 65535.f; if ((c & 1) == 0) { rgb[1][rr * ts + ccmax + cc] = Gtmp[((border2 - rr) * width + (width - cc - 2)) >> 1]; @@ -976,7 +989,7 @@ float* RawImageSource::CA_correct_RT( if (rrmax < rr1 && ccmin > 0) { for (int rr = 0; rr < std::min(border, rr1 - rrmax); rr++) { for (int cc = 0; cc < border; cc++) { - int c = FC(rr, cc); + int c = fc(cfa, rr, cc); rgb[c][((rrmax + rr)*ts + cc) >> ((c & 1) ^ 1)] = (rawData[(height - rr - 2)][(border2 - cc)]) / 65535.f; if ((c & 1) == 0) { rgb[1][(rrmax + rr)*ts + cc] = Gtmp[((height - rr - 2) * width + (border2 - cc)) >> 1]; @@ -993,7 +1006,7 @@ float* RawImageSource::CA_correct_RT( #endif //manual CA correction; use red/blue slider values to set CA shift parameters for (int rr = 3; rr < rr1 - 3; rr++) { - int cc = 3 + FC(rr, 1), c = FC(rr,cc), indx = rr * ts + cc; + int cc = 3 + fc(cfa, rr, 1), c = fc(cfa, rr,cc), indx = rr * ts + cc; #ifdef __SSE2__ for (; cc < cc1 - 10; cc += 8, indx += 8) { //compute directional weights using image gradients @@ -1074,8 +1087,8 @@ float* RawImageSource::CA_correct_RT( } for (int rr = 4; rr < rr1 - 4; rr++) { - int cc = 4 + (FC(rr, 2) & 1); - int c = FC(rr, cc); + int cc = 4 + (fc(cfa, rr, 2) & 1); + int c = fc(cfa, rr, cc); int indx = (rr * ts + cc) >> 1; int indxfc = (rr + shiftvfloor[c]) * ts + cc + shifthceil[c]; int indxff = (rr + shiftvfloor[c]) * ts + cc + shifthfloor[c]; @@ -1124,8 +1137,8 @@ float* RawImageSource::CA_correct_RT( vfloat epsv = F2V(eps); #endif for (int rr = 8; rr < rr1 - 8; rr++) { - int cc = 8 + (FC(rr, 2) & 1); - int c = FC(rr, cc); + int cc = 8 + (fc(cfa, rr, 2) & 1); + int c = fc(cfa, rr, cc); int GRBdir0 = GRBdir[0][c]; int GRBdir1 = GRBdir[1][c]; #ifdef __SSE2__ @@ -1162,7 +1175,7 @@ float* RawImageSource::CA_correct_RT( STVFU(rgb[c][indx >> 1], RBint); } #endif - for (int c = FC(rr, cc), indx = rr * ts + cc; cc < cc1 - 8; cc += 2, indx += 2) { + for (int c = fc(cfa, rr, cc), indx = rr * ts + cc; cc < cc1 - 8; cc += 2, indx += 2) { float grbdiffold = rgb[1][indx] - rgb[c][indx >> 1]; //interpolate colour difference from optical R/B locations to grid locations @@ -1204,9 +1217,9 @@ float* RawImageSource::CA_correct_RT( // copy CA corrected results to temporary image matrix for (int rr = border; rr < rr1 - border; rr++) { - int c = FC(rr + top, left + border + (FC(rr + top, 2) & 1)); + int c = fc(cfa, rr + top, left + border + (fc(cfa, rr + top, 2) & 1)); int row = rr + top; - int cc = border + (FC(rr, 2) & 1); + int cc = border + (fc(cfa, rr, 2) & 1); int indx = (row * width + cc + left) >> 1; int indx1 = (rr * ts + cc) >> 1; #ifdef __SSE2__ @@ -1241,16 +1254,16 @@ float* RawImageSource::CA_correct_RT( #endif for (int row = cb; row < height - cb; row++) { - int col = cb + (FC(row, 0) & 1); + int col = cb + (fc(cfa, row, 0) & 1); int indx = (row * width + col) >> 1; #ifdef __SSE2__ for (; col < width - 7 - cb; col += 8, indx += 4) { - vfloat val = LVFU(RawDataTmp[indx]); + const vfloat val = vmaxf(LVFU(RawDataTmp[indx]), ZEROV); STC2VFU(rawData[row][col], val); } #endif for (; col < width - cb; col += 2, indx++) { - rawData[row][col] = RawDataTmp[indx]; + rawData[row][col] = std::max(0.f, RawDataTmp[indx]); } } @@ -1276,8 +1289,8 @@ float* RawImageSource::CA_correct_RT( #pragma omp for #endif for (int i = 0; i < H - 2 * cb; ++i) { - const int firstCol = FC(i, 0) & 1; - const int colour = FC(i, firstCol); + const int firstCol = fc(cfa, i, 0) & 1; + const int colour = fc(cfa, i, firstCol); const array2D* nonGreen = colour == 0 ? redFactor : blueFactor; int j = firstCol; #ifdef __SSE2__ @@ -1309,9 +1322,9 @@ float* RawImageSource::CA_correct_RT( if (W % 2) { // odd width => factors for one channel are not set in last column => use value of preceding column - const int ngRow = 1 - (FC(0, 0) & 1); - const int ngCol = FC(ngRow, 0) & 1; - const int colour = FC(ngRow, ngCol); + const int ngRow = 1 - (fc(cfa, 0, 0) & 1); + const int ngCol = fc(cfa, ngRow, 0) & 1; + const int colour = fc(cfa, ngRow, ngCol); const array2D* nonGreen = colour == 0 ? redFactor : blueFactor; for (int i = 0; i < (H + 1 - 2 * cb) / 2; ++i) { (*nonGreen)[i][(W - 2 * cb + 1) / 2 - 1] = (*nonGreen)[i][(W - 2* cb + 1) / 2 - 2]; @@ -1328,8 +1341,8 @@ float* RawImageSource::CA_correct_RT( #pragma omp for #endif for (int i = 0; i < H - 2 * cb; ++i) { - const int firstCol = FC(i, 0) & 1; - const int colour = FC(i, firstCol); + const int firstCol = fc(cfa, i, 0) & 1; + const int colour = fc(cfa, i, firstCol); const array2D* nonGreen = colour == 0 ? redFactor : blueFactor; for (int j = firstCol; j < W - 2 * cb; j += 2) { rawData[i + cb][j + cb] *= (*nonGreen)[i / 2][j / 2]; diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index cd8c507b4..6538ecc61 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -11,7 +11,12 @@ include_directories(${EXTRA_INCDIR} ${LCMS_INCLUDE_DIRS} ${LENSFUN_INCLUDE_DIRS} ${RSVG_INCLUDE_DIRS} - ) +) +if(NOT WITH_SYSTEM_KLT) + include_directories("${CMAKE_SOURCE_DIR}/rtengine/klt") +else() + include_directories(${KLT_INCLUDE_DIRS}) +endif() link_directories("${PROJECT_SOURCE_DIR}/rtexif" ${EXPAT_LIBRARY_DIRS} @@ -25,24 +30,24 @@ link_directories("${PROJECT_SOURCE_DIR}/rtexif" ${LCMS_LIBRARY_DIRS} ${LENSFUN_LIBRARY_DIRS} ${RSVG_LIBRARY_DIRS} - ) +) set(CAMCONSTSFILE "camconst.json") set(RTENGINESOURCEFILES - badpixels.cc - CA_correct_RT.cc - EdgePreservingDecomposition.cc - FTblockDN.cc - PF_correct_RT.cc ahd_demosaic_RT.cc amaze_demosaic_RT.cc - cJSON.c + badpixels.cc + boxblur.cc + canon_cr3_decoder.cc + CA_correct_RT.cc calc_distort.cc camconst.cc + capturesharpening.cc cfa_linedn_RT.cc ciecam02.cc cieimage.cc + cJSON.c clutstore.cc color.cc colortemp.cc @@ -59,14 +64,19 @@ set(RTENGINESOURCEFILES dual_demosaic_RT.cc dynamicprofile.cc eahd_demosaic.cc + EdgePreservingDecomposition.cc fast_demo.cc ffmanager.cc filmnegativeproc.cc filmnegativethumb.cc flatcurves.cc + FTblockDN.cc + gamutwarning.cc gauss.cc green_equil_RT.cc + guidedfilter.cc hilite_recon.cc + histmatching.cc hphd_demosaic_RT.cc iccjpeg.cc iccstore.cc @@ -81,62 +91,53 @@ set(RTENGINESOURCEFILES improcfun.cc impulse_denoise.cc init.cc + ipdehaze.cc + ipgrain.cc iplab2rgb.cc - iplocallab.cc + iplocallab.cc + iplabregions.cc + iplocalcontrast.cc ipresize.cc ipretinex.cc + ipshadowshighlights.cc ipsharpen.cc + ipsoftlight.cc iptransform.cc ipvibrance.cc ipwavelet.cc jdatasrc.cc jpeg_ijg/jpeg_memsrc.cc - klt/convolve.cc - klt/error.cc - klt/klt.cc - klt/klt_util.cc - klt/pnmio.cc - klt/pyramid.cc - klt/selectGoodFeatures.cc - klt/storeFeatures.cc - klt/trackFeatures.cc - klt/writeFeatures.cc labimage.cc lcp.cc + lj92.c + lmmse_demosaic.cc loadinitial.cc myfile.cc + panasonic_decoders.cc + pdaflinesfilter.cc + PF_correct_RT.cc pipettebuffer.cc pixelshift.cc previewimage.cc processingjob.cc procparams.cc profilestore.cc + rawflatfield.cc rawimage.cc rawimagesource.cc rcd_demosaic.cc refreshmap.cc rt_algo.cc + rtlensfun.cc rtthumbnail.cc shmap.cc simpleprocess.cc - slicer.cc stdimagesource.cc - utils.cc - rtlensfun.cc tmo_fattal02.cc - iplocalcontrast.cc - histmatching.cc - pdaflinesfilter.cc - gamutwarning.cc - ipshadowshighlights.cc - xtrans_demosaic.cc + utils.cc vng4_demosaic_RT.cc - ipsoftlight.cc - guidedfilter.cc - ipdehaze.cc - iplabregions.cc - lj92.c - ) + xtrans_demosaic.cc +) if(LENSFUN_HAS_LOAD_DIRECTORY) set_source_files_properties(rtlensfun.cc PROPERTIES COMPILE_DEFINITIONS RT_LENSFUN_HAS_LOAD_DIRECTORY) @@ -150,21 +151,22 @@ if(NOT WITH_SYSTEM_KLT) set(RTENGINESOURCEFILES ${RTENGINESOURCEFILES} klt/convolve.cc klt/error.cc - klt/klt.cc klt/klt_util.cc + klt/klt.cc klt/pnmio.cc klt/pyramid.cc klt/selectGoodFeatures.cc klt/storeFeatures.cc klt/trackFeatures.cc klt/writeFeatures.cc - ) + ) set(KLT_LIBRARIES) endif() include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}") -add_library(rtengine ${RTENGINESOURCEFILES}) +add_library(rtengine STATIC ${RTENGINESOURCEFILES}) + add_dependencies(rtengine UpdateInfo) # It may be nice to store library version too @@ -190,6 +192,7 @@ target_link_libraries(rtengine rtexif ${ZLIB_LIBRARIES} ${LENSFUN_LIBRARIES} ${RSVG_LIBRARIES} - ) + ${KLT_LIBRARIES} +) install(FILES ${CAMCONSTSFILE} DESTINATION "${DATADIR}" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) diff --git a/rtengine/EdgePreservingDecomposition.cc b/rtengine/EdgePreservingDecomposition.cc index 0f85b14d5..a8d3575cf 100644 --- a/rtengine/EdgePreservingDecomposition.cc +++ b/rtengine/EdgePreservingDecomposition.cc @@ -4,8 +4,7 @@ #ifdef _OPENMP #include #endif -#include "sleef.c" -#include "opthelper.h" +#include "sleef.h" #define DIAGONALS 5 #define DIAGONALSP1 6 @@ -401,13 +400,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 +417,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 +487,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 +553,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 +569,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 +583,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 +600,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 +620,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 +634,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 445c6d290..297308a0b 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -18,36 +18,44 @@ // 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 "../rtgui/threadutils.h" -#include "rtengine.h" -#include "improcfun.h" -#include "LUT.h" + #include "array2D.h" -#include "iccmatrices.h" #include "boxblur.h" -#include "rt_math.h" -#include "mytime.h" -#include "sleef.c" -#include "opthelper.h" #include "cplx_wavelet_dec.h" -#include "median.h" +#include "color.h" +#include "curves.h" +#include "iccmatrices.h" #include "iccstore.h" +#include "imagefloat.h" +#include "improcfun.h" +#include "labimage.h" +#include "LUT.h" +#include "median.h" +#include "mytime.h" +#include "opthelper.h" #include "procparams.h" +#include "rt_math.h" +#include "sleef.h" + +#include "../rtgui/threadutils.h" +#include "../rtgui/options.h" + #ifdef _OPENMP #include #endif + //#define BENCHMARK #include "StopWatch.h" #define TS 64 // Tile size #define offset 25 // shift between tiles -#define fTS ((TS/2+1)) // second dimension of Fourier tiles #define blkrad 1 // radius of block averaging #define epsilon 0.001f/(TS*TS) //tolerance @@ -69,11 +77,7 @@ namespace rtengine */ -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -extern const Settings* settings; extern MyMutex *fftwMutex; @@ -687,8 +691,8 @@ BENCHFUN } } - int tilesize; - int overlap; + int tilesize = 0; + int overlap = 0; if (settings->leveldnti == 0) { tilesize = 1024; @@ -1342,8 +1346,6 @@ BENCHFUN #ifdef _OPENMP int masterThread = omp_get_thread_num(); -#endif -#ifdef _OPENMP #pragma omp parallel num_threads(denoiseNestedLevels) if (denoiseNestedLevels>1) #endif { @@ -1352,11 +1354,11 @@ BENCHFUN #else int subThread = 0; #endif - float blurbuffer[TS * TS] ALIGNED64; +// float blurbuffer[TS * TS] ALIGNED64; float *Lblox = LbloxArray[subThread]; float *fLblox = fLbloxArray[subThread]; float pBuf[width + TS + 2 * blkrad * offset] ALIGNED16; - float nbrwt[TS * TS] ALIGNED64; +// float nbrwt[TS * TS] ALIGNED64; #ifdef _OPENMP #pragma omp for #endif @@ -1431,7 +1433,8 @@ BENCHFUN for (int hblk = 0; hblk < numblox_W; ++hblk) { - RGBtile_denoise(fLblox, hblk, noisevar_Ldetail, nbrwt, blurbuffer); + RGBtile_denoise(fLblox, hblk, noisevar_Ldetail); + // RGBtile_denoise(fLblox, hblk, noisevar_Ldetail, nbrwt, blurbuffer); }//end of horizontal block loop //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1604,9 +1607,9 @@ BENCHFUN Color::Lab2RGBLimit(labdn->L[i1], labdn->a[i1], labdn->b[i1], labdn->L[i1], labdn->a[i1], labdn->b[i1], wip, 9000000.f, 1.f + qhighFactor * realred, 1.f + qhighFactor * realblue, width); for (int j = tileleft; j < tileright; ++j) { int j1 = j - tileleft; - float r_ = labdn->L[i1][j1]; - float g_ = labdn->a[i1][j1]; - float b_ = labdn->b[i1][j1]; + float r_ = std::max(0.f, labdn->L[i1][j1]); + float g_ = std::max(0.f, labdn->a[i1][j1]); + float b_ = std::max(0.f, labdn->b[i1][j1]); //inverse gamma standard (slider) r_ = r_ < 32768.f ? igamcurve[r_] : (Color::gammanf(r_ / 32768.f, igam) * 65535.f); g_ = g_ < 32768.f ? igamcurve[g_] : (Color::gammanf(g_ / 32768.f, igam) * 65535.f); @@ -2048,19 +2051,21 @@ BENCHFUN //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void ImProcFunctions::RGBtile_denoise(float * fLblox, int hblproc, float noisevar_Ldetail, float * nbrwt, float * blurbuffer) //for DCT +//void ImProcFunctions::RGBtile_denoise(float * fLblox, int hblproc, float noisevar_Ldetail, float * nbrwt, float * blurbuffer) //for DCT +void ImProcFunctions::RGBtile_denoise(float* fLblox, int hblproc, float noisevar_Ldetail) //for DCT { - int blkstart = hblproc * TS * TS; - boxabsblur(fLblox + blkstart, nbrwt, 3, 3, TS, TS, blurbuffer); //blur neighbor weights for more robust estimation //for DCT + float nbrwt[TS * TS] ALIGNED64; + const int blkstart = hblproc * TS * TS; + + boxabsblur(fLblox + blkstart, nbrwt, 3, TS, TS, false); //blur neighbor weights for more robust estimation //for DCT #ifdef __SSE2__ - __m128 tempv; - __m128 noisevar_Ldetailv = _mm_set1_ps(noisevar_Ldetail); - __m128 onev = _mm_set1_ps(1.0f); + const vfloat noisevar_Ldetailv = F2V(-1.f / noisevar_Ldetail); + const vfloat onev = F2V(1.f); for (int n = 0; n < TS * TS; n += 4) { //for DCT - tempv = onev - xexpf(-SQRV(LVF(nbrwt[n])) / noisevar_Ldetailv); - _mm_storeu_ps(&fLblox[blkstart + n], LVFU(fLblox[blkstart + n]) * tempv); + const vfloat tempv = onev - xexpf(SQRV(LVF(nbrwt[n])) * noisevar_Ldetailv); + STVF(fLblox[blkstart + n], LVF(fLblox[blkstart + n]) * tempv); }//output neighbor averaged result #else @@ -2071,10 +2076,7 @@ void ImProcFunctions::RGBtile_denoise(float * fLblox, int hblproc, float noiseva #endif - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //printf("vblk=%d hlk=%d wsqave=%f || ",vblproc,hblproc,wsqave); - -}//end of function tile_denoise +} //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2207,7 +2209,7 @@ void ImProcFunctions::Noise_residualAB(const wavelet_decomposition &WaveletCoeff chmaxresid = maxresid; } -bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels) +bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels) { int maxlvl = min(WaveletCoeffs_L.maxlevel(), 5); const float eps = 0.01f; @@ -2238,13 +2240,12 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &Wavelet #pragma omp parallel num_threads(denoiseNestedLevels) if (denoiseNestedLevels>1) #endif { - float *buffer[4]; + float *buffer[3]; buffer[0] = new (std::nothrow) float[maxWL * maxHL + 32]; buffer[1] = new (std::nothrow) float[maxWL * maxHL + 64]; buffer[2] = new (std::nothrow) float[maxWL * maxHL + 96]; - buffer[3] = new (std::nothrow) float[maxWL * maxHL + 128]; - if (buffer[0] == nullptr || buffer[1] == nullptr || buffer[2] == nullptr || buffer[3] == nullptr) { + if (buffer[0] == nullptr || buffer[1] == nullptr || buffer[2] == nullptr) { memoryAllocationFailed = true; } @@ -2267,8 +2268,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &Wavelet } else { //simple wavelet shrinkage float * sfave = buffer[0] + 32; - float * sfaved = buffer[1] + 64; - float * blurBuffer = buffer[2] + 96; + float * sfaved = buffer[2] + 96; float mad_Lr = madL[lvl][dir - 1]; /* @@ -2286,7 +2286,6 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &Wavelet for (int i = 0; i < Hlvl_L * Wlvl_L; ++i) { nvl[i] = 0.f; } - if ((edge == 1 || edge == 2 || edge == 3) && vari) { // nvl = blurBuffer; // we need one buffer, but fortunately we don't have to allocate a new one because we can use blurBuffer if ((edge == 1 || edge == 3)) { @@ -2313,17 +2312,17 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &Wavelet float levelFactor = mad_Lr * 5.f / (lvl + 1); #ifdef __SSE2__ - __m128 mad_Lv; - __m128 ninev = _mm_set1_ps(9.0f); - __m128 epsv = _mm_set1_ps(eps); - __m128 mag_Lv; - __m128 levelFactorv = _mm_set1_ps(levelFactor); + vfloat mad_Lv; + vfloat ninev = F2V(9.0f); + vfloat epsv = F2V(eps); + vfloat mag_Lv; + vfloat levelFactorv = F2V(levelFactor); int coeffloc_L; for (coeffloc_L = 0; coeffloc_L < Hlvl_L * Wlvl_L - 3; coeffloc_L += 4) { mad_Lv = LVFU(nvl[coeffloc_L]) * levelFactorv; mag_Lv = SQRV(LVFU(WavCoeffs_L[dir][coeffloc_L])); - _mm_storeu_ps(&sfave[coeffloc_L], mag_Lv / (mag_Lv + mad_Lv * xexpf(-mag_Lv / (mad_Lv * ninev)) + epsv)); + STVFU(sfave[coeffloc_L], mag_Lv / (mag_Lv + mad_Lv * xexpf(-mag_Lv / (mad_Lv * ninev)) + epsv)); } for (; coeffloc_L < Hlvl_L * Wlvl_L; ++coeffloc_L) { @@ -2343,15 +2342,16 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &Wavelet } #endif - boxblur(sfave, sfaved, blurBuffer, lvl + 2, lvl + 2, Wlvl_L, Hlvl_L); //increase smoothness by locally averaging shrinkage + boxblur(sfave, sfaved, lvl + 2, Wlvl_L, Hlvl_L, false); //increase smoothness by locally averaging shrinkage + #ifdef __SSE2__ - __m128 sfavev; - __m128 sf_Lv; + vfloat sfavev; + vfloat sf_Lv; for (coeffloc_L = 0; coeffloc_L < Hlvl_L * Wlvl_L - 3; coeffloc_L += 4) { sfavev = LVFU(sfaved[coeffloc_L]); sf_Lv = LVFU(sfave[coeffloc_L]); - _mm_storeu_ps(&WavCoeffs_L[dir][coeffloc_L], LVFU(WavCoeffs_L[dir][coeffloc_L]) * (SQRV(sfavev) + SQRV(sf_Lv)) / (sfavev + sf_Lv + epsv)); + STVFU(WavCoeffs_L[dir][coeffloc_L], LVFU(WavCoeffs_L[dir][coeffloc_L]) * (SQRV(sfavev) + SQRV(sf_Lv)) / (sfavev + sf_Lv + epsv)); //use smoothed shrinkage unless local shrinkage is much less } @@ -2381,7 +2381,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &Wavelet } } - for (int i = 3; i >= 0; i--) { + for (int i = 2; i >= 0; i--) { if (buffer[i] != nullptr) { delete[] buffer[i]; } @@ -2392,7 +2392,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &Wavelet } -bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels) +bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels) { int maxlvl = WaveletCoeffs_L.maxlevel(); @@ -2504,12 +2504,12 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &Wavele if (noisevarfc > 0.001f) { #ifdef __SSE2__ - __m128 onev = _mm_set1_ps(1.f); - __m128 mad_abrv = _mm_set1_ps(mad_abr); - __m128 rmad_Lm9v = onev / _mm_set1_ps(mad_Lr * 9.f); - __m128 mad_abv; - __m128 mag_Lv, mag_abv; - __m128 tempabv; + vfloat onev = F2V(1.f); + vfloat mad_abrv = F2V(mad_abr); + vfloat rmad_Lm9v = onev / F2V(mad_Lr * 9.f); + vfloat mad_abv; + vfloat mag_Lv, mag_abv; + vfloat tempabv; int coeffloc_ab; for (coeffloc_ab = 0; coeffloc_ab < Hlvl_ab * Wlvl_ab - 3; coeffloc_ab += 4) { @@ -2519,7 +2519,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &Wavele mag_Lv = LVFU(WavCoeffs_L[dir][coeffloc_ab]); mag_abv = SQRV(tempabv); mag_Lv = SQRV(mag_Lv) * rmad_Lm9v; - _mm_storeu_ps(&WavCoeffs_ab[dir][coeffloc_ab], tempabv * SQRV((onev - xexpf(-(mag_abv / mad_abv) - (mag_Lv))))); + STVFU(WavCoeffs_ab[dir][coeffloc_ab], tempabv * SQRV((onev - xexpf(-(mag_abv / mad_abv) - (mag_Lv))))); } // few remaining pixels @@ -2555,9 +2555,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &Wavele } for (int i = 2; i >= 0; i--) { - if (buffer[i] != nullptr) { - delete[] buffer[i]; - } + delete[] buffer[i]; } } @@ -2565,7 +2563,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &Wavele } -bool ImProcFunctions::WaveletDenoiseAllL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels)//mod JD +bool ImProcFunctions::WaveletDenoiseAllL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels)//mod JD { @@ -2619,16 +2617,14 @@ bool ImProcFunctions::WaveletDenoiseAllL(wavelet_decomposition &WaveletCoeffs_L, } for (int i = 3; i >= 0; i--) { - if (buffer[i] != nullptr) { - delete[] buffer[i]; - } + delete[] buffer[i]; } } return (!memoryAllocationFailed); } -bool ImProcFunctions::WaveletDenoiseAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, +bool ImProcFunctions::WaveletDenoiseAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels)//mod JD { @@ -2690,11 +2686,9 @@ bool ImProcFunctions::WaveletDenoiseAllAB(wavelet_decomposition &WaveletCoeffs_L return (!memoryAllocationFailed); } -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void ImProcFunctions::ShrinkAllL(wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, +void ImProcFunctions::ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, float *noisevarlum, float * madL, float * vari, int edge) { @@ -2703,13 +2697,14 @@ void ImProcFunctions::ShrinkAllL(wavelet_decomposition &WaveletCoeffs_L, float * float * sfave = buffer[0] + 32; float * sfaved = buffer[1] + 64; - float * blurBuffer = buffer[2] + 96; +// float * blurBuffer = buffer[2] + 96; - int W_L = WaveletCoeffs_L.level_W(level); - int H_L = WaveletCoeffs_L.level_H(level); + const int W_L = WaveletCoeffs_L.level_W(level); + const int H_L = WaveletCoeffs_L.level_H(level); float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(level); - float mad_L = madL[dir - 1] ; + const float mad_L = madL[dir - 1] ; + const float levelFactor = mad_L * 5.f / static_cast(level + 1); float *nvl = nullptr; nvl = new float[ H_L * W_L]; @@ -2740,101 +2735,51 @@ void ImProcFunctions::ShrinkAllL(wavelet_decomposition &WaveletCoeffs_L, float * } } - - /* - float kinterm = epsi + noiseLCurve[xdivf(LLum, 15) * 500.f]; - kinterm *= 100.f; - kinterm += noiseluma; - lumcalc[ii][jj] = SQR((kinterm / 125.f) * (1.f + kinterm / 25.f)); - - //TO DO perhaps needs ci=urve for L ?? ==> same as in shrinkallab - float noisevarfc; - - float *nvc = nullptr; - nvc = new float[ H_ab * W_ab]; - - if ((local == 2 || local == 3) && variC && useNoiseCCurve) { - noisevarfc = variC[level]; - - for (int p = 0; p < H_ab * W_ab; p++) { - nvc[p] = 10.f * sqrt(variC[level]) * SQR(1.f + 4.f * noisevarchrom[p]); - } - - } else { - noisevarfc = noisevar_ab; - - for (int p = 0; p < H_ab * W_ab; p++) { - nvc[p] = noisevarchrom[p]; - } - - } - */ - float levelFactor = mad_L * 5.f / static_cast(level + 1); + int i = 0; #ifdef __SSE2__ - __m128 magv; - __m128 levelFactorv = _mm_set1_ps(levelFactor); - __m128 mad_Lv; - __m128 ninev = _mm_set1_ps(9.0f); - __m128 epsv = _mm_set1_ps(eps); - int i; + const vfloat levelFactorv = F2V(levelFactor); + const vfloat ninev = F2V(9.f); + const vfloat epsv = F2V(eps); + for (i = 0; i < W_L * H_L - 3; i += 4) { - mad_Lv = LVFU(nvl[i]) * levelFactorv; - magv = SQRV(LVFU(WavCoeffs_L[dir][i])); - _mm_storeu_ps(&sfave[i], magv / (magv + mad_Lv * xexpf(-magv / (ninev * mad_Lv)) + epsv)); + // const vfloat mad_Lv = LVFU(noisevarlum[i]) * levelFactorv; + const vfloat mad_Lv = LVFU(nvl[i]) * levelFactorv; + const vfloat magv = SQRV(LVFU(WavCoeffs_L[dir][i])); + STVFU(sfave[i], magv / (magv + mad_Lv * xexpf(-magv / (ninev * mad_Lv)) + epsv)); } +#endif // few remaining pixels for (; i < W_L * H_L; ++i) { float mag = SQR(WavCoeffs_L[dir][i]); sfave[i] = mag / (mag + levelFactor * nvl[i] * xexpf(-mag / (9 * levelFactor * nvl[i])) + eps); } -#else - - for (int i = 0; i < W_L * H_L; ++i) { - - float mag = SQR(WavCoeffs_L[dir][i]); - float shrinkfactor = mag / (mag + levelFactor * nvl[i] * xexpf(-mag / (9 * levelFactor * nvl[i])) + eps); - sfave[i] = shrinkfactor; - } - -#endif - boxblur(sfave, sfaved, blurBuffer, level + 2, level + 2, W_L, H_L); //increase smoothness by locally averaging shrinkage - delete [] nvl; + boxblur(sfave, sfaved, level + 2, W_L, H_L, false); //increase smoothness by locally averaging shrinkage + i = 0; #ifdef __SSE2__ - __m128 sfv; - for (i = 0; i < W_L * H_L - 3; i += 4) { - sfv = LVFU(sfave[i]); + for (; i < W_L * H_L - 3; i += 4) { + const vfloat sfv = LVFU(sfave[i]); //use smoothed shrinkage unless local shrinkage is much less - _mm_storeu_ps(&WavCoeffs_L[dir][i], _mm_loadu_ps(&WavCoeffs_L[dir][i]) * (SQRV(LVFU(sfaved[i])) + SQRV(sfv)) / (LVFU(sfaved[i]) + sfv + epsv)); + STVFU(WavCoeffs_L[dir][i], LVFU(WavCoeffs_L[dir][i]) * (SQRV(LVFU(sfaved[i])) + SQRV(sfv)) / (LVFU(sfaved[i]) + sfv + epsv)); } - +#endif // few remaining pixels for (; i < W_L * H_L; ++i) { - float sf = sfave[i]; - + const float sf = sfave[i]; //use smoothed shrinkage unless local shrinkage is much less WavCoeffs_L[dir][i] *= (SQR(sfaved[i]) + SQR(sf)) / (sfaved[i] + sf + eps); }//now luminance coefficients are denoised -#else + delete [] nvl; - for (int i = 0; i < W_L * H_L; ++i) { - float sf = sfave[i]; - - //use smoothed shrinkage unless local shrinkage is much less - WavCoeffs_L[dir][i] *= (SQR(sfaved[i]) + SQR(sf)) / (sfaved[i] + sf + eps); - - }//now luminance coefficients are denoised - -#endif } -void ImProcFunctions::ShrinkAllAB(wavelet_decomposition & WaveletCoeffs_L, wavelet_decomposition & WaveletCoeffs_ab, float **buffer, int level, int dir, +void ImProcFunctions::ShrinkAllAB(const wavelet_decomposition & WaveletCoeffs_L, const wavelet_decomposition & WaveletCoeffs_ab, float **buffer, int level, int dir, float * noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, float * madL, float * variC, int local, float * madaab, bool madCalculated) @@ -2848,7 +2793,7 @@ void ImProcFunctions::ShrinkAllAB(wavelet_decomposition & WaveletCoeffs_L, wavel float * sfaveab = buffer[0] + 32; float * sfaveabd = buffer[1] + 64; - float * blurBuffer = buffer[2] + 96; + // float * blurBuffer = buffer[2] + 96; int W_ab = WaveletCoeffs_ab.level_W(level); int H_ab = WaveletCoeffs_ab.level_H(level); @@ -2868,7 +2813,6 @@ void ImProcFunctions::ShrinkAllAB(wavelet_decomposition & WaveletCoeffs_L, wavel madab = SQR(MadRgb(WavCoeffs_ab[dir], W_ab * H_ab)); } } - float noisevarfc; float *nvc = nullptr; @@ -2876,7 +2820,6 @@ void ImProcFunctions::ShrinkAllAB(wavelet_decomposition & WaveletCoeffs_L, wavel if ((local == 2 || local == 3) && variC && useNoiseCCurve) { noisevarfc = variC[level]; - for (int p = 0; p < H_ab * W_ab; p++) { nvc[p] = 10.f * sqrt(variC[level]) * SQR(1.f + 4.f * noisevarchrom[p]); } @@ -2890,17 +2833,18 @@ void ImProcFunctions::ShrinkAllAB(wavelet_decomposition & WaveletCoeffs_L, wavel } -// printf("varfc=%f nvc0=%f nvc1=%f nvc2=%f\n", noisevarfc, nvc[10], nvc[H_ab * W_ab /3], nvc[H_ab * W_ab /2]); + // printf("varfc=%f nvc0=%f nvc1=%f nvc2=%f\n", noisevarfc, nvc[10], nvc[H_ab * W_ab /3], nvc[H_ab * W_ab /2]); if (noisevarfc > 0.001f) {//noisevar_ab //madab = useNoiseCCurve ? madab : madab * noisevar_ab; madab = useNoiseCCurve ? madab : madab * noisevarfc; #ifdef __SSE2__ - __m128 onev = _mm_set1_ps(1.f); - __m128 mad_abrv = _mm_set1_ps(madab); + vfloat onev = F2V(1.f); + vfloat mad_abrv = F2V(madab); + + vfloat rmadLm9v = onev / F2V(mad_L * 9.f); + vfloat mad_abv ; + vfloat mag_Lv, mag_abv; - __m128 rmadLm9v = onev / _mm_set1_ps(mad_L * 9.f); - __m128 mad_abv ; - __m128 mag_Lv, mag_abv; int coeffloc_ab; for (coeffloc_ab = 0; coeffloc_ab < H_ab * W_ab - 3; coeffloc_ab += 4) { @@ -2909,7 +2853,7 @@ void ImProcFunctions::ShrinkAllAB(wavelet_decomposition & WaveletCoeffs_L, wavel mag_Lv = LVFU(WavCoeffs_L[dir][coeffloc_ab]); mag_abv = SQRV(LVFU(WavCoeffs_ab[dir][coeffloc_ab])); mag_Lv = (SQRV(mag_Lv)) * rmadLm9v; - _mm_storeu_ps(&sfaveab[coeffloc_ab], (onev - xexpf(-(mag_abv / mad_abv) - (mag_Lv)))); + STVFU(sfaveab[coeffloc_ab], (onev - xexpf(-(mag_abv / mad_abv) - (mag_Lv)))); } // few remaining pixels @@ -2931,19 +2875,20 @@ void ImProcFunctions::ShrinkAllAB(wavelet_decomposition & WaveletCoeffs_L, wavel }//now chrominance coefficients are denoised #endif + boxblur(sfaveab, sfaveabd, level + 2, W_ab, H_ab, false); //increase smoothness by locally averaging shrinkage - boxblur(sfaveab, sfaveabd, blurBuffer, level + 2, level + 2, W_ab, H_ab); //increase smoothness by locally averaging shrinkage +// boxblur(sfaveab, sfaveabd, blurBuffer, level + 2, level + 2, W_ab, H_ab); //increase smoothness by locally averaging shrinkage #ifdef __SSE2__ - __m128 epsv = _mm_set1_ps(eps); - __m128 sfabv; - __m128 sfaveabv; + vfloat epsv = F2V(eps); + vfloat sfabv; + vfloat sfaveabv; for (coeffloc_ab = 0; coeffloc_ab < H_ab * W_ab - 3; coeffloc_ab += 4) { sfabv = LVFU(sfaveab[coeffloc_ab]); sfaveabv = LVFU(sfaveabd[coeffloc_ab]); //use smoothed shrinkage unless local shrinkage is much less - _mm_storeu_ps(&WavCoeffs_ab[dir][coeffloc_ab], LVFU(WavCoeffs_ab[dir][coeffloc_ab]) * (SQRV(sfaveabv) + SQRV(sfabv)) / (sfaveabv + sfabv + epsv)); + STVFU(WavCoeffs_ab[dir][coeffloc_ab], LVFU(WavCoeffs_ab[dir][coeffloc_ab]) * (SQRV(sfaveabv) + SQRV(sfabv)) / (sfaveabv + sfabv + epsv)); } // few remaining pixels @@ -3091,8 +3036,8 @@ void ImProcFunctions::ShrinkAll_info(float ** WavCoeffs_a, float ** WavCoeffs_b, } -void ImProcFunctions::WaveletDenoiseAll_info(int levwav, wavelet_decomposition & WaveletCoeffs_a, - wavelet_decomposition & WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float & chaut, int &Nb, float & redaut, float & blueaut, float & maxredaut, float & maxblueaut, float & minredaut, float & minblueaut, int schoice, +void ImProcFunctions::WaveletDenoiseAll_info(int levwav, const wavelet_decomposition & WaveletCoeffs_a, + const wavelet_decomposition & WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float & chaut, int &Nb, float & redaut, float & blueaut, float & maxredaut, float & maxblueaut, float & minredaut, float & minblueaut, int schoice, float & chromina, float & sigma, float & lumema, float & sigma_L, float & redyel, float & skinc, float & nsknc, float & maxchred, float & maxchblue, float & minchred, float & minchblue, int &nb, float & chau, float & chred, float & chblue, bool denoiseMethodRgb) { @@ -3278,7 +3223,7 @@ void ImProcFunctions::calcautodn_info(float & chaut, float & delta, int Nb, int } -void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, const bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread) +void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, const bool isRAW, const LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread) { if ((settings->leveldnautsimpl == 1 && dnparams.Cmethod == "MAN") || (settings->leveldnautsimpl == 0 && dnparams.C2method == "MANU")) { //nothing to do @@ -3345,8 +3290,8 @@ void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, const float gain = pow(2.0f, float(expcomp)); - int tilesize; - int overlap; + int tilesize = 0; + int overlap = 0; if (settings->leveldnti == 0) { tilesize = 1024; @@ -3447,16 +3392,16 @@ void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, for (int i = tiletop; i < tilebottom; i += 2) { int i1 = i - tiletop; #ifdef __SSE2__ - __m128 aNv, bNv; - __m128 c100v = _mm_set1_ps(100.f); + vfloat aNv, bNv; + vfloat c100v = F2V(100.f); int j; for (j = tileleft; j < tileright - 7; j += 8) { int j1 = j - tileleft; aNv = LVFU(acalc[i >> 1][j >> 1]); bNv = LVFU(bcalc[i >> 1][j >> 1]); - _mm_storeu_ps(&noisevarhue[i1 >> 1][j1 >> 1], xatan2f(bNv, aNv)); - _mm_storeu_ps(&noisevarchrom[i1 >> 1][j1 >> 1], vmaxf(vsqrtf(SQRV(aNv) + SQRV(bNv)),c100v)); + STVFU(noisevarhue[i1 >> 1][j1 >> 1], xatan2f(bNv, aNv)); + STVFU(noisevarchrom[i1 >> 1][j1 >> 1], vmaxf(vsqrtf(SQRV(aNv) + SQRV(bNv)),c100v)); } for (; j < tileright; j += 2) { diff --git a/rtengine/LUT.h b/rtengine/LUT.h index 6584eefe6..a80e5996d 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 . */ /* @@ -56,21 +56,18 @@ * LUTuc stands for LUT */ -#ifndef LUT_H_ -#define LUT_H_ +#pragma once #include #include #include #ifndef NDEBUG -#include #include #endif #include "opthelper.h" #include "rt_math.h" -#include "noncopyable.h" // Bit representations of flags enum { @@ -485,26 +482,6 @@ public: return (p1 + p2 * diff); } -#ifndef NDEBUG - // Debug facility ; dump the content of the LUT in a file. No control of the filename is done - void dump(Glib::ustring fname) - { - if (size) { - Glib::ustring fname_ = fname + ".xyz"; // TopSolid'Design "plot" file format - std::ofstream f (fname_.c_str()); - f << "$" << std::endl; - - for (unsigned int iter = 0; iter < size; iter++) { - f << iter << ", " << data[iter] << ", 0." << std::endl; - } - - f << "$" << std::endl; - f.close (); - } - } -#endif - - operator bool (void) const { return size > 0; @@ -649,5 +626,3 @@ public: }; - -#endif /* LUT_H_ */ diff --git a/rtengine/PF_correct_RT.cc b/rtengine/PF_correct_RT.cc index fe89a7b65..9a95b8e2f 100644 --- a/rtengine/PF_correct_RT.cc +++ b/rtengine/PF_correct_RT.cc @@ -23,14 +23,18 @@ // 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 "gauss.h" #include "improcfun.h" -#include "sleef.c" -#include "../rtgui/myflatcurve.h" +#include "cieimage.h" +#include "color.h" +#include "curves.h" +#include "labimage.h" +#include "sleef.h" +#include "curves.h" #include "rt_math.h" #include "opthelper.h" #include "median.h" 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..064dfd6e1 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 . */ // @@ -27,12 +27,17 @@ #include "rtengine.h" #include "rawimagesource.h" #include "rt_math.h" -#include "procparams.h" #include "../rtgui/multilangmgr.h" #include "median.h" //#define BENCHMARK #include "StopWatch.h" +namespace +{ +unsigned fc(const unsigned int cfa[2][2], int r, int c) { + return cfa[r & 1][c & 1]; +} +} namespace rtengine { #define TS 144 @@ -40,7 +45,8 @@ void RawImageSource::ahd_demosaic() { BENCHFUN - constexpr int dir[4] = { -1, 1, -TS, TS }; + const unsigned int cfa[2][2] = {{FC(0,0), FC(0,1)}, {FC(1,0), FC(1,1)}}; + constexpr int dirs[4] = { -1, 1, -TS, TS }; float xyz_cam[3][3]; LUTf cbrt(65536); @@ -55,9 +61,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,15 +72,16 @@ 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_interpolate(W, H, 5, rawData, red, green, blue); - border_interpolate2(W, H, 5, rawData, red, green, blue); #ifdef _OPENMP #pragma omp parallel @@ -92,7 +100,7 @@ void RawImageSource::ahd_demosaic() for (int left = 2; left < width - 5; left += TS - 6) { // Interpolate green horizontally and vertically: for (int row = top; row < top + TS && row < height - 2; row++) { - for (int col = left + (FC(row, left) & 1); col < std::min(left + TS, width - 2); col += 2) { + for (int col = left + (fc(cfa, row, left) & 1); col < std::min(left + TS, width - 2); col += 2) { auto pix = &rawData[row][col]; float val0 = 0.25f * ((pix[-1] + pix[0] + pix[1]) * 2 - pix[-2] - pix[2]) ; @@ -106,12 +114,12 @@ void RawImageSource::ahd_demosaic() // Interpolate red and blue, and convert to CIELab: for (int d = 0; d < 2; d++) for (int row = top + 1; row < top + TS - 1 && row < height - 3; row++) { - int cng = FC(row + 1, FC(row + 1, 0) & 1); + int cng = fc(cfa, row + 1, fc(cfa, row + 1, 0) & 1); for (int col = left + 1; col < std::min(left + TS - 1, width - 3); col++) { auto pix = &rawData[row][col]; auto rix = &rgb[d][row - top][col - left]; auto lix = lab[d][row - top][col - left]; - if (FC(row, col) == 1) { + if (fc(cfa, row, col) == 1) { rix[0][2 - cng] = CLIP(pix[0] + (0.5f * (pix[-1] + pix[1] - rix[-1][1] - rix[1][1] ) )); rix[0][cng] = CLIP(pix[0] + (0.5f * (pix[-width] + pix[width] @@ -153,9 +161,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..05a965766 100644 --- a/rtengine/alignedbuffer.h +++ b/rtengine/alignedbuffer.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 _ALIGNEDBUFFER_ -#define _ALIGNEDBUFFER_ +#pragma once #include #include @@ -142,5 +141,3 @@ public: return unitSize ? allocatedSize / unitSize : 0; } }; - -#endif diff --git a/rtengine/amaze_demosaic_RT.cc b/rtengine/amaze_demosaic_RT.cc index ffb68dbdd..2041f3130 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 . // //////////////////////////////////////////////////////////////// @@ -30,12 +30,18 @@ #include "rawimagesource.h" #include "rt_math.h" #include "../rtgui/multilangmgr.h" -#include "sleef.c" +#include "sleef.h" #include "opthelper.h" #include "median.h" -#include "procparams.h" #include "StopWatch.h" +namespace +{ +unsigned fc(const unsigned int cfa[2][2], int r, int c) { + return cfa[r & 1][c & 1]; +} +} + namespace rtengine { @@ -49,13 +55,14 @@ 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 unsigned int cfarray[2][2] = {{FC(0,0), FC(0,1)}, {FC(1,0), FC(1,1)}}; const int width = winw, height = winh; const float clip_pt = 1.0 / initialGain; const float clip_pt8 = 0.8 / initialGain; @@ -74,8 +81,8 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c int ex, ey; //determine GRBG coset; (ey,ex) is the offset of the R subarray - if (FC(0, 0) == 1) { //first pixel is G - if (FC(0, 1) == 0) { + if (fc(cfarray, 0, 0) == 1) { //first pixel is G + if (fc(cfarray, 0, 1) == 0) { ey = 0; ex = 1; } else { @@ -83,7 +90,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c ex = 0; } } else {//first pixel is R or B - if (FC(0, 0) == 0) { + if (fc(cfarray, 0, 0) == 0) { ey = 0; ex = 0; } else { @@ -373,7 +380,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c #ifdef __SSE2__ vfloat sgnv; - if( !(FC(4, 4) & 1) ) { + if( !(fc(cfarray, 4, 4) & 1) ) { sgnv = _mm_set_ps( 1.f, -1.f, 1.f, -1.f ); } else { sgnv = _mm_set_ps( -1.f, 1.f, -1.f, 1.f ); @@ -440,7 +447,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c #else for (int rr = 4; rr < rr1 - 4; rr++) { - bool fcswitch = FC(rr, 4) & 1; + bool fcswitch = fc(cfarray, rr, 4) & 1; for (int cc = 4, indx = rr * ts + cc; cc < cc1 - 4; cc++, indx++) { @@ -532,7 +539,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c vfloat clip_ptv = F2V( clip_pt ); vfloat sgn3v; - if( !(FC(4, 4) & 1) ) { + if( !(fc(cfarray, 4, 4) & 1) ) { sgnv = _mm_set_ps( 1.f, -1.f, 1.f, -1.f ); } else { sgnv = _mm_set_ps( -1.f, 1.f, -1.f, 1.f ); @@ -590,7 +597,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c #else for (int rr = 4; rr < rr1 - 4; rr++) { - for (int cc = 4, indx = rr * ts + cc, c = FC(rr, cc) & 1; cc < cc1 - 4; cc++, indx++) { + for (int cc = 4, indx = rr * ts + cc, c = fc(cfarray, rr, cc) & 1; cc < cc1 - 4; cc++, indx++) { float hcdvar = 3.f * (SQR(hcd[indx - 2]) + SQR(hcd[indx]) + SQR(hcd[indx + 2])) - SQR(hcd[indx - 2] + hcd[indx] + hcd[indx + 2]); float hcdaltvar = 3.f * (SQR(hcdalt[indx - 2]) + SQR(hcdalt[indx]) + SQR(hcdalt[indx + 2])) - SQR(hcdalt[indx - 2] + hcdalt[indx] + hcdalt[indx + 2]); float vcdvar = 3.f * (SQR(vcd[indx - v2]) + SQR(vcd[indx]) + SQR(vcd[indx + v2])) - SQR(vcd[indx - v2] + vcd[indx] + vcd[indx + v2]); @@ -686,7 +693,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c vfloat epssqv = F2V( epssq ); for (int rr = 6; rr < rr1 - 6; rr++) { - for (int indx = rr * ts + 6 + (FC(rr, 2) & 1); indx < rr * ts + cc1 - 6; indx += 8) { + for (int indx = rr * ts + 6 + (fc(cfarray, rr, 2) & 1); indx < rr * ts + cc1 - 6; indx += 8) { //compute colour difference variances in cardinal directions vfloat tempv = LC2VFU(vcd[indx]); vfloat uavev = tempv + LC2VFU(vcd[indx - v1]) + LC2VFU(vcd[indx - v2]) + LC2VFU(vcd[indx - v3]); @@ -732,7 +739,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c #else for (int rr = 6; rr < rr1 - 6; rr++) { - for (int cc = 6 + (FC(rr, 2) & 1), indx = rr * ts + cc; cc < cc1 - 6; cc += 2, indx += 2) { + for (int cc = 6 + (fc(cfarray, rr, 2) & 1), indx = rr * ts + cc; cc < cc1 - 6; cc += 2, indx += 2) { //compute colour difference variances in cardinal directions @@ -768,7 +775,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; @@ -794,7 +801,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c // precompute nyquist for (int rr = 6; rr < rr1 - 6; rr++) { - int cc = 6 + (FC(rr, 2) & 1); + int cc = 6 + (fc(cfarray, rr, 2) & 1); int indx = rr * ts + cc; #ifdef __SSE2__ @@ -857,7 +864,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c int nyendcol = 0; for (int rr = 6; rr < rr1 - 6; rr++) { - for (int cc = 6 + (FC(rr, 2) & 1), indx = rr * ts + cc; cc < cc1 - 6; cc += 2, indx += 2) { + for (int cc = 6 + (fc(cfarray, rr, 2) & 1), indx = rr * ts + cc; cc < cc1 - 6; cc += 2, indx += 2) { //nyquist texture test: ask if difference of vcd compared to hcd is larger or smaller than RGGB gradients if(nyqutest[indx >> 1] > 0.f) { @@ -908,7 +915,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c #else - for (int indx = rr * ts + nystartcol + (FC(rr, 2) & 1); indx < rr * ts + nyendcol; indx += 2) { + for (int indx = rr * ts + nystartcol + (fc(cfarray, rr, 2) & 1); indx < rr * ts + nyendcol; indx += 2) { unsigned int nyquisttemp = (nyquist[(indx - v2) >> 1] + nyquist[(indx - m1) >> 1] + nyquist[(indx + p1) >> 1] + nyquist[(indx - 2) >> 1] + nyquist[(indx + 2) >> 1] + nyquist[(indx - p1) >> 1] + nyquist[(indx + m1) >> 1] + nyquist[(indx + v2) >> 1]); @@ -923,7 +930,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c // in areas of Nyquist texture, do area interpolation for (int rr = nystartrow; rr < nyendrow; rr++) - for (int indx = rr * ts + nystartcol + (FC(rr, 2) & 1); indx < rr * ts + nyendcol; indx += 2) { + for (int indx = rr * ts + nystartcol + (fc(cfarray, rr, 2) & 1); indx < rr * ts + nyendcol; indx += 2) { if (nyquist2[indx >> 1]) { // area interpolation @@ -963,7 +970,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c //populate G at R/B sites for (int rr = 8; rr < rr1 - 8; rr++) - for (int indx = rr * ts + 8 + (FC(rr, 2) & 1); indx < rr * ts + cc1 - 8; indx += 2) { + for (int indx = rr * ts + 8 + (fc(cfarray, rr, 2) & 1); indx < rr * ts + cc1 - 8; indx += 2) { //first ask if one gets more directional discrimination from nearby B/R sites float hvwtalt = xdivf(hvwt[(indx - m1) >> 1] + hvwt[(indx + p1) >> 1] + hvwt[(indx - p1) >> 1] + hvwt[(indx + m1) >> 1], 2); @@ -986,7 +993,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c // refine Nyquist areas using G curvatures if(doNyquist) { for (int rr = nystartrow; rr < nyendrow; rr++) - for (int indx = rr * ts + nystartcol + (FC(rr, 2) & 1); indx < rr * ts + nyendcol; indx += 2) { + for (int indx = rr * ts + nystartcol + (fc(cfarray, rr, 2) & 1); indx < rr * ts + nyendcol; indx += 2) { if (nyquist2[indx >> 1]) { //local averages (over Nyquist pixels only) of G curvature squared @@ -1009,7 +1016,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c #ifdef __SSE2__ for (int rr = 6; rr < rr1 - 6; rr++) { - if((FC(rr, 2) & 1) == 0) { + if((fc(cfarray, rr, 2) & 1) == 0) { for (int cc = 6, indx = rr * ts + cc; cc < cc1 - 6; cc += 8, indx += 8) { vfloat tempv = LC2VFU(cfa[indx + 1]); vfloat Dgrbsq1pv = (SQRV(tempv - LC2VFU(cfa[indx + 1 - p1])) + SQRV(tempv - LC2VFU(cfa[indx + 1 + p1]))); @@ -1035,7 +1042,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c #else for (int rr = 6; rr < rr1 - 6; rr++) { - if((FC(rr, 2) & 1) == 0) { + if((fc(cfarray, rr, 2) & 1) == 0) { for (int cc = 6, indx = rr * ts + cc; cc < cc1 - 6; cc += 2, indx += 2) { delp[indx >> 1] = fabsf(cfa[indx + p1] - cfa[indx - p1]); delm[indx >> 1] = fabsf(cfa[indx + m1] - cfa[indx - m1]); @@ -1064,7 +1071,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c for (int rr = 8; rr < rr1 - 8; rr++) { #ifdef __SSE2__ - for (int indx = rr * ts + 8 + (FC(rr, 2) & 1), indx1 = indx >> 1; indx < rr * ts + cc1 - 8; indx += 8, indx1 += 4) { + for (int indx = rr * ts + 8 + (fc(cfarray, rr, 2) & 1), indx1 = indx >> 1; indx < rr * ts + cc1 - 8; indx += 8, indx1 += 4) { //diagonal colour ratios vfloat cfav = LC2VFU(cfa[indx]); @@ -1129,7 +1136,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c #else - for (int cc = 8 + (FC(rr, 2) & 1), indx = rr * ts + cc, indx1 = indx >> 1; cc < cc1 - 8; cc += 2, indx += 2, indx1++) { + for (int cc = 8 + (fc(cfarray, rr, 2) & 1), indx = rr * ts + cc, indx1 = indx >> 1; cc < cc1 - 8; cc += 2, indx += 2, indx1++) { //diagonal colour ratios float crse = xmul2f(cfa[indx + m1]) / (eps + cfa[indx] + (cfa[indx + m2])); @@ -1219,7 +1226,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c for (int rr = 10; rr < rr1 - 10; rr++) #ifdef __SSE2__ - for (int indx = rr * ts + 10 + (FC(rr, 2) & 1), indx1 = indx >> 1; indx < rr * ts + cc1 - 10; indx += 8, indx1 += 4) { + for (int indx = rr * ts + 10 + (fc(cfarray, rr, 2) & 1), indx1 = indx >> 1; indx < rr * ts + cc1 - 10; indx += 8, indx1 += 4) { //first ask if one gets more directional discrimination from nearby B/R sites vfloat pmwtaltv = zd25v * (LVFU(pmwt[(indx - m1) >> 1]) + LVFU(pmwt[(indx + p1) >> 1]) + LVFU(pmwt[(indx - p1) >> 1]) + LVFU(pmwt[(indx + m1) >> 1])); @@ -1231,12 +1238,12 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c #else - for (int cc = 10 + (FC(rr, 2) & 1), indx = rr * ts + cc, indx1 = indx >> 1; cc < cc1 - 10; cc += 2, indx += 2, indx1++) { + for (int cc = 10 + (fc(cfarray, rr, 2) & 1), indx = rr * ts + cc, indx1 = indx >> 1; cc < cc1 - 10; cc += 2, indx += 2, indx1++) { //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 } @@ -1247,7 +1254,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c for (int rr = 12; rr < rr1 - 12; rr++) #ifdef __SSE2__ - for (int indx = rr * ts + 12 + (FC(rr, 2) & 1), indx1 = indx >> 1; indx < rr * ts + cc1 - 12; indx += 8, indx1 += 4) { + for (int indx = rr * ts + 12 + (fc(cfarray, rr, 2) & 1), indx1 = indx >> 1; indx < rr * ts + cc1 - 12; indx += 8, indx1 += 4) { vmask copymask = vmaskf_ge(vabsf(zd5v - LVFU(pmwt[indx1])), vabsf(zd5v - LVFU(hvwt[indx1]))); if(_mm_movemask_ps((vfloat)copymask)) { // if for any of the 4 pixels the condition is true, do the maths for all 4 pixels and mask the unused out at the end @@ -1302,9 +1309,9 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c #else - for (int cc = 12 + (FC(rr, 2) & 1), indx = rr * ts + cc, indx1 = indx >> 1; cc < cc1 - 12; cc += 2, indx += 2, indx1++) { + for (int cc = 12 + (fc(cfarray, 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; } @@ -1400,7 +1407,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c for (int rr = 14; rr < rr1 - 14; rr++) #ifdef __SSE2__ - for (int cc = 14 + (FC(rr, 2) & 1), indx = rr * ts + cc, c = 1 - FC(rr, cc) / 2; cc < cc1 - 14; cc += 8, indx += 8) { + for (int cc = 14 + (fc(cfarray, rr, 2) & 1), indx = rr * ts + cc, c = 1 - fc(cfarray, rr, cc) / 2; cc < cc1 - 14; cc += 8, indx += 8) { vfloat tempv = epsv + vabsf(LVFU(Dgrb[c][(indx - m1) >> 1]) - LVFU(Dgrb[c][(indx + m1) >> 1])); vfloat temp2v = epsv + vabsf(LVFU(Dgrb[c][(indx + p1) >> 1]) - LVFU(Dgrb[c][(indx - p1) >> 1])); vfloat wtnwv = onev / (tempv + vabsf(LVFU(Dgrb[c][(indx - m1) >> 1]) - LVFU(Dgrb[c][(indx - m3) >> 1])) + vabsf(LVFU(Dgrb[c][(indx + m1) >> 1]) - LVFU(Dgrb[c][(indx - m3) >> 1]))); @@ -1416,7 +1423,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c #else - for (int cc = 14 + (FC(rr, 2) & 1), indx = rr * ts + cc, c = 1 - FC(rr, cc) / 2; cc < cc1 - 14; cc += 2, indx += 2) { + for (int cc = 14 + (fc(cfarray, rr, 2) & 1), indx = rr * ts + cc, c = 1 - fc(cfarray, rr, cc) / 2; cc < cc1 - 14; cc += 2, indx += 2) { float wtnw = 1.f / (eps + fabsf(Dgrb[c][(indx - m1) >> 1] - Dgrb[c][(indx + m1) >> 1]) + fabsf(Dgrb[c][(indx - m1) >> 1] - Dgrb[c][(indx - m3) >> 1]) + fabsf(Dgrb[c][(indx + m1) >> 1] - Dgrb[c][(indx - m3) >> 1])); float wtne = 1.f / (eps + fabsf(Dgrb[c][(indx + p1) >> 1] - Dgrb[c][(indx - p1) >> 1]) + fabsf(Dgrb[c][(indx + p1) >> 1] - Dgrb[c][(indx + p3) >> 1]) + fabsf(Dgrb[c][(indx - p1) >> 1] - Dgrb[c][(indx + p3) >> 1])); float wtsw = 1.f / (eps + fabsf(Dgrb[c][(indx - p1) >> 1] - Dgrb[c][(indx + p1) >> 1]) + fabsf(Dgrb[c][(indx - p1) >> 1] - Dgrb[c][(indx + m3) >> 1]) + fabsf(Dgrb[c][(indx + p1) >> 1] - Dgrb[c][(indx - p3) >> 1])); @@ -1435,7 +1442,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c vfloat twov = F2V(2.f); vmask selmask; - if((FC(16, 2) & 1) == 1) { + if((fc(cfarray, 16, 2) & 1) == 1) { selmask = _mm_set_epi32(0xffffffff, 0, 0xffffffff, 0); offset = 1; } else { @@ -1463,91 +1470,91 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c vfloat bluev1 = greenv - (temp00v * vdup(LVFU(Dgrb[1][(indx - v1) >> 1])) + (onev - vdup(LVFU(hvwt[(indx + 1 + offset) >> 1]))) * vdup(LVFU(Dgrb[1][(indx + 1 + offset) >> 1])) + (onev - vdup(LVFU(hvwt[(indx - 1 + offset) >> 1]))) * vdup(LVFU(Dgrb[1][(indx - 1 + offset) >> 1])) + temp01v * vdup(LVFU(Dgrb[1][(indx + v1) >> 1]))) * tempv; vfloat redv2 = greenv - vdup(LVFU(Dgrb[0][indx >> 1])); vfloat bluev2 = greenv - vdup(LVFU(Dgrb[1][indx >> 1])); - STVFU(red[row][col], c65535v * vself(selmask, redv1, redv2)); - STVFU(blue[row][col], c65535v * vself(selmask, bluev1, bluev2)); + STVFU(red[row][col], vmaxf(c65535v * vself(selmask, redv1, redv2), ZEROV)); + STVFU(blue[row][col], vmaxf(c65535v * vself(selmask, bluev1, bluev2), ZEROV)); } if(offset == 0) { for (; indx < rr * ts + cc1 - 16 - (cc1 & 1); indx++, col++) { float temp = 1.f / (hvwt[(indx - v1) >> 1] + 2.f - hvwt[(indx + 1) >> 1] - hvwt[(indx - 1) >> 1] + hvwt[(indx + v1) >> 1]); - red[row][col] = 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * - temp); - blue[row][col] = 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * - temp); + red[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * + temp)); + blue[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * + temp)); indx++; col++; - red[row][col] = 65535.f * (rgbgreen[indx] - Dgrb[0][indx >> 1]); - blue[row][col] = 65535.f * (rgbgreen[indx] - Dgrb[1][indx >> 1]); + red[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - Dgrb[0][indx >> 1])); + blue[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - Dgrb[1][indx >> 1])); } if(cc1 & 1) { // width of tile is odd float temp = 1.f / (hvwt[(indx - v1) >> 1] + 2.f - hvwt[(indx + 1) >> 1] - hvwt[(indx - 1) >> 1] + hvwt[(indx + v1) >> 1]); - red[row][col] = 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * - temp); - blue[row][col] = 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * - temp); + red[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * + temp)); + blue[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * + temp)); } } else { for (; indx < rr * ts + cc1 - 16 - (cc1 & 1); indx++, col++) { - red[row][col] = 65535.f * (rgbgreen[indx] - Dgrb[0][indx >> 1]); - blue[row][col] = 65535.f * (rgbgreen[indx] - Dgrb[1][indx >> 1]); + red[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - Dgrb[0][indx >> 1])); + blue[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - Dgrb[1][indx >> 1])); indx++; col++; float temp = 1.f / (hvwt[(indx - v1) >> 1] + 2.f - hvwt[(indx + 1) >> 1] - hvwt[(indx - 1) >> 1] + hvwt[(indx + v1) >> 1]); - red[row][col] = 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * - temp); - blue[row][col] = 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * - temp); + red[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * + temp)); + blue[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * + temp)); } if(cc1 & 1) { // width of tile is odd - red[row][col] = 65535.f * (rgbgreen[indx] - Dgrb[0][indx >> 1]); - blue[row][col] = 65535.f * (rgbgreen[indx] - Dgrb[1][indx >> 1]); + red[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - Dgrb[0][indx >> 1])); + blue[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - Dgrb[1][indx >> 1])); } } #else - if((FC(rr, 2) & 1) == 1) { + if((fc(cfarray, rr, 2) & 1) == 1) { for (; indx < rr * ts + cc1 - 16 - (cc1 & 1); indx++, col++) { float temp = 1.f / (hvwt[(indx - v1) >> 1] + 2.f - hvwt[(indx + 1) >> 1] - hvwt[(indx - 1) >> 1] + hvwt[(indx + v1) >> 1]); - red[row][col] = 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * - temp); - blue[row][col] = 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * - temp); + red[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * + temp)); + blue[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * + temp)); indx++; col++; - red[row][col] = 65535.f * (rgbgreen[indx] - Dgrb[0][indx >> 1]); - blue[row][col] = 65535.f * (rgbgreen[indx] - Dgrb[1][indx >> 1]); + red[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - Dgrb[0][indx >> 1])); + blue[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - Dgrb[1][indx >> 1])); } if(cc1 & 1) { // width of tile is odd float temp = 1.f / (hvwt[(indx - v1) >> 1] + 2.f - hvwt[(indx + 1) >> 1] - hvwt[(indx - 1) >> 1] + hvwt[(indx + v1) >> 1]); - red[row][col] = 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * - temp); - blue[row][col] = 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * - temp); + red[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * + temp)); + blue[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * + temp)); } } else { for (; indx < rr * ts + cc1 - 16 - (cc1 & 1); indx++, col++) { - red[row][col] = 65535.f * (rgbgreen[indx] - Dgrb[0][indx >> 1]); - blue[row][col] = 65535.f * (rgbgreen[indx] - Dgrb[1][indx >> 1]); + red[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - Dgrb[0][indx >> 1])); + blue[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - Dgrb[1][indx >> 1])); indx++; col++; float temp = 1.f / (hvwt[(indx - v1) >> 1] + 2.f - hvwt[(indx + 1) >> 1] - hvwt[(indx - 1) >> 1] + hvwt[(indx + v1) >> 1]); - red[row][col] = 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * - temp); - blue[row][col] = 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * - temp); + red[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * + temp)); + blue[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * + temp)); } if(cc1 & 1) { // width of tile is odd - red[row][col] = 65535.f * (rgbgreen[indx] - Dgrb[0][indx >> 1]); - blue[row][col] = 65535.f * (rgbgreen[indx] - Dgrb[1][indx >> 1]); + red[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - Dgrb[0][indx >> 1])); + blue[row][col] = std::max(0.f, 65535.f * (rgbgreen[indx] - Dgrb[1][indx >> 1])); } } @@ -1561,13 +1568,13 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c #ifdef __SSE2__ for (; cc < cc1 - 19; cc += 4) { - STVFU(green[row][cc + left], LVF(rgbgreen[rr * ts + cc]) * c65535v); + STVFU(green[row][cc + left], vmaxf(LVF(rgbgreen[rr * ts + cc]) * c65535v, ZEROV)); } #endif for (; cc < cc1 - 16; cc++) { - green[row][cc + left] = 65535.f * rgbgreen[rr * ts + cc]; + green[row][cc + left] = std::max(0.f, 65535.f * rgbgreen[rr * ts + cc]); } } @@ -1592,7 +1599,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, c free(buffer); } if(border < 4) { - border_interpolate2(W, H, 3, rawData, red, green, blue); + border_interpolate(W, H, 3, rawData, red, green, blue); } if(plistener) { diff --git a/rtengine/array2D.h b/rtengine/array2D.h index 48a789bf8..de6381aeb 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 . */ /* @@ -52,8 +52,8 @@ * * !! locked arrays cannot be resized and cannot be unlocked again !! */ -#ifndef ARRAY2D_H_ -#define ARRAY2D_H_ +#pragma once + #include // for raise() #include @@ -188,6 +188,16 @@ public: } } + void fill(const T val, bool multiThread = false) + { +#ifdef _OPENMP + #pragma omp parallel for if(multiThread) +#endif + for (int i = 0; i < x * y; ++i) { + data[i] = val; + } + } + void free() { if ((owner) && (data)) { @@ -214,6 +224,12 @@ public: return ptr; } + // use as pointer to T** + operator const T* const *() + { + return ptr; + } + // use as pointer to data operator T*() { @@ -243,7 +259,7 @@ public: ar_realloc(w, h, offset); if (flags & ARRAY2D_CLEAR_DATA) { - memset(data + offset, 0, w * h * sizeof(T)); + memset(data + offset, 0, static_cast(w) * h * sizeof(T)); } } @@ -307,4 +323,3 @@ public: return list[index]; } }; -#endif /* array2D_H_ */ diff --git a/rtengine/badpixels.cc b/rtengine/badpixels.cc index 376e58b3b..0ae63a618 100644 --- a/rtengine/badpixels.cc +++ b/rtengine/badpixels.cc @@ -14,13 +14,48 @@ * GNU General Public License for more details. * * 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" #include "median.h" #include "pixelsmap.h" +#include "rawimage.h" #include "rawimagesource.h" +//#define BENCHMARK +#include "StopWatch.h" + +namespace +{ +unsigned fc(const unsigned int cfa[2][2], int r, int c) { + return cfa[r & 1][c & 1]; +} + +inline void sum5x5(const array2D& in, int col, float &sum) { +#ifdef __SSE2__ + // sum up 5*4 = 20 values using SSE + // 10 fabs function calls and 10 float additions with SSE + const vfloat sumv = (vabsf(LVFU(in[0][col])) + vabsf(LVFU(in[1][col]))) + + (vabsf(LVFU(in[2][col])) + vabsf(LVFU(in[3][col]))) + + vabsf(LVFU(in[4][col])); + // horizontally add the values and add the result to hfnbrave + sum += vhadd(sumv); + + // add remaining 5 values of last column + sum += (fabsf(in[0][col + 4]) + fabsf(in[1][col + 4])) + + (fabsf(in[2][col + 4]) + fabsf(in[3][col + 4])) + + fabsf(in[4][col + 4]); +#else + // 25 fabs function calls and 25 float additions without SSE + for (int nn = col; nn < col + 5; ++nn) { + sum += (fabsf(in[0][nn]) + fabsf(in[1][nn])) + + (fabsf(in[2][nn]) + fabsf(in[3][nn])) + + fabsf(in[4][nn]); + } +#endif + +} +} namespace rtengine { @@ -30,6 +65,7 @@ namespace rtengine */ int RawImageSource::interpolateBadPixelsBayer(const PixelsMap &bitmapBads, array2D &rawData) { + const unsigned int cfarray[2][2] = {{FC(0,0), FC(0,1)}, {FC(1,0), FC(1,1)}}; constexpr float eps = 1.f; int counter = 0; @@ -53,7 +89,7 @@ int RawImageSource::interpolateBadPixelsBayer(const PixelsMap &bitmapBads, array float wtdsum = 0.f, norm = 0.f; // diagonal interpolation - if (FC(row, col) == 1) { + if (fc(cfarray, row, col) == 1) { // green channel. We can use closer pixels than for red or blue channel. Distance to center pixel is sqrt(2) => weighting is 0.70710678 // For green channel following pixels will be used for interpolation. Pixel to be interpolated is in center. // 1 means that pixel is used in this step, if itself and his counterpart are not marked bad @@ -436,126 +472,124 @@ int RawImageSource::interpolateBadPixelsXtrans(const PixelsMap &bitmapBads) /* Search for hot or dead pixels in the image and update the map * For each pixel compare its value to the average of similar color surrounding * (Taken from Emil Martinec idea) - * (Optimized by Ingo Weyrich 2013 and 2015) - */ + * (Optimized by Ingo Weyrich 2013, 2015, and 2019) +*/ int RawImageSource::findHotDeadPixels(PixelsMap &bpMap, const float thresh, const bool findHotPixels, const bool findDeadPixels) const { + BENCHFUN const float varthresh = (20.0 * (thresh / 100.0) + 1.0) / 24.f; - // allocate temporary buffer - float* cfablur = new float[H * W]; - // counter for dead or hot pixels int counter = 0; #ifdef _OPENMP - #pragma omp parallel + #pragma omp parallel reduction(+:counter) #endif { + array2D cfablur(W, 5, ARRAY2D_CLEAR_DATA); + int firstRow = -1; + int lastRow = -1; + #ifdef _OPENMP - #pragma omp for schedule(dynamic,16) nowait + // note, static scheduling is important in this implementation + #pragma omp for schedule(static) nowait #endif - for (int i = 2; i < H - 2; i++) { - for (int j = 2; j < W - 2; j++) { + for (int i = 2; i < H - 2; ++i) { + if (firstRow == -1) { + firstRow = i; + if (firstRow > 2) { + for (int row = firstRow - 2; row < firstRow; ++row) { + const int destRow = row % 5; + for (int j = 2; j < W - 2; ++j) { + const float temp = median(rawData[row - 2][j - 2], rawData[row - 2][j], rawData[row - 2][j + 2], + rawData[row][j - 2], rawData[row][j], rawData[row][j + 2], + rawData[row + 2][j - 2], rawData[row + 2][j], rawData[row + 2][j + 2]); + cfablur[destRow][j] = rawData[row][j] - temp; + } + } + } + } + lastRow = i; + const int destRow = i % 5; + for (int j = 2; j < W - 2; ++j) { const float temp = median(rawData[i - 2][j - 2], rawData[i - 2][j], rawData[i - 2][j + 2], rawData[i][j - 2], rawData[i][j], rawData[i][j + 2], rawData[i + 2][j - 2], rawData[i + 2][j], rawData[i + 2][j + 2]); - cfablur[i * W + j] = rawData[i][j] - temp; + cfablur[destRow][j] = rawData[i][j] - temp; + } + + if (i - 1 > firstRow) { + const int rr = i - 2; + const int rr0 = rr % 5; + for (int cc = 2; cc < W - 2; ++cc) { + //evaluate pixel for heat/death + float pixdev = cfablur[rr0][cc]; + + if (!findDeadPixels && pixdev <= 0.f) { + continue; + } + + if (!findHotPixels && pixdev >= 0.f) { + continue; + } + + pixdev = fabsf(pixdev); + float hfnbrave = -pixdev; + sum5x5(cfablur, cc - 2, hfnbrave); + if (pixdev > varthresh * hfnbrave) { + // mark the pixel as "bad" + bpMap.set(cc, rr); + ++counter; + } + } //end of pixel evaluation } } - // process borders. Former version calculated the median using mirrored border which does not make sense because the original pixel loses weight - // Setting the difference between pixel and median for border pixels to zero should do the job not worse then former version -#ifdef _OPENMP - #pragma omp single -#endif - { - for (int i = 0; i < 2; ++i) { - for (int j = 0; j < W; ++j) { - cfablur[i * W + j] = 0.f; - } - } - - for (int i = 2; i < H - 2; ++i) { - for (int j = 0; j < 2; ++j) { - cfablur[i * W + j] = 0.f; - } - - for (int j = W - 2; j < W; ++j) { - cfablur[i * W + j] = 0.f; - } - } - - for (int i = H - 2; i < H; ++i) { - for (int j = 0; j < W; ++j) { - cfablur[i * W + j] = 0.f; - } - } - } - -#ifdef _OPENMP - #pragma omp barrier // barrier because of nowait clause above - - #pragma omp for reduction(+:counter) schedule(dynamic,16) -#endif - - //cfa pixel heat/death evaluation - for (int rr = 2; rr < H - 2; ++rr) { - for (int cc = 2, rrmWpcc = rr * W + 2; cc < W - 2; ++cc, ++rrmWpcc) { - //evaluate pixel for heat/death - float pixdev = cfablur[rrmWpcc]; - - if (pixdev == 0.f) { - continue; - } - - if ((!findDeadPixels) && pixdev < 0) { - continue; - } - - if ((!findHotPixels) && pixdev > 0) { - continue; - } - - pixdev = fabsf(pixdev); - float hfnbrave = -pixdev; - -#ifdef __SSE2__ - // sum up 5*4 = 20 values using SSE - // 10 fabs function calls and 10 float additions with SSE - vfloat sum = vabsf(LVFU(cfablur[(rr - 2) * W + cc - 2])) + vabsf(LVFU(cfablur[(rr - 1) * W + cc - 2])); - sum += vabsf(LVFU(cfablur[(rr) * W + cc - 2])); - sum += vabsf(LVFU(cfablur[(rr + 1) * W + cc - 2])); - sum += vabsf(LVFU(cfablur[(rr + 2) * W + cc - 2])); - // horizontally add the values and add the result to hfnbrave - hfnbrave += vhadd(sum); - - // add remaining 5 values of last column - for (int mm = rr - 2; mm <= rr + 2; ++mm) { - hfnbrave += fabsf(cfablur[mm * W + cc + 2]); - } - -#else - - // 25 fabs function calls and 25 float additions without SSE - for (int mm = rr - 2; mm <= rr + 2; ++mm) { - for (int nn = cc - 2; nn <= cc + 2; ++nn) { - hfnbrave += fabsf(cfablur[mm * W + nn]); + if (lastRow > 0 && lastRow < H - 2) { + //cfa pixel heat/death evaluation + for (int rr = lastRow - 1; rr < lastRow + 1; ++rr) { + const int i = rr + 2; + const int destRow = i % 5; + if (i >= H - 2) { + for (int j = 2; j < W - 2; j++) { + cfablur[destRow][j] = 0.f; + } + } else { + for (int j = 2; j < W - 2; ++j) { + const float temp = median(rawData[i - 2][j - 2], rawData[i - 2][j], rawData[i - 2][j + 2], + rawData[i][j - 2], rawData[i][j], rawData[i][j + 2], + rawData[i + 2][j - 2], rawData[i + 2][j], rawData[i + 2][j + 2]); + cfablur[destRow][j] = rawData[i][j] - temp; } } -#endif + const int rr0 = rr % 5; + for (int cc = 2; cc < W - 2; ++cc) { + //evaluate pixel for heat/death + float pixdev = cfablur[rr0][cc]; - if (pixdev > varthresh * hfnbrave) { - // mark the pixel as "bad" - bpMap.set(cc, rr); - counter++; - } - }//end of pixel evaluation + if (!findDeadPixels && pixdev <= 0.f) { + continue; + } + + if (!findHotPixels && pixdev >= 0.f) { + continue; + } + + pixdev = fabsf(pixdev); + float hfnbrave = -pixdev; + sum5x5(cfablur, cc - 2, hfnbrave); + if (pixdev > varthresh * hfnbrave) { + // mark the pixel as "bad" + bpMap.set(cc, rr); + ++counter; + } + }//end of pixel evaluation + } } }//end of parallel processing - delete [] cfablur; + return counter; } diff --git a/rtengine/bilateral2.h b/rtengine/bilateral2.h index e754ac891..53e18fb20 100644 --- a/rtengine/bilateral2.h +++ b/rtengine/bilateral2.h @@ -14,24 +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 _BILATERAL2_ -#define _BILATERAL2_ +#pragma once +#include #include -#include #include -#include - -#include "rtengine.h" -#include "rt_math.h" -#include "mytime.h" +#include #include "array2D.h" -#ifdef _OPENMP -#include -#endif +#include "LUT.h" +#include "rt_math.h" using namespace rtengine; @@ -573,7 +567,7 @@ template void bilateral (T** src, T** dst, int W, int H, int sigmar, do // calculate histogram at the beginning of the row rhist.clear(); - for (int x = MAX(0, row_from - r); x <= MIN(H, row_from + r); x++) + for (int x = std::max(0, row_from - r); x <= std::min(H, row_from + r); x++) for (int y = 0; y < r + 1; y++) { rhist[((int)src[x][y]) >> TRANSBIT]++; } @@ -584,12 +578,12 @@ template void bilateral (T** src, T** dst, int W, int H, int sigmar, do // calculate histogram at the beginning of the row if (i > r) - for (int x = 0; x <= MIN(H, r); x++) { + for (int x = 0; x <= std::min(H, r); x++) { rhist[((int)src[i - r - 1][x]) >> TRANSBIT]--; } if (i < H - r) - for (int x = 0; x <= MIN(H, r); x++) { + for (int x = 0; x <= std::min(H, r); x++) { rhist[((int)src[i + r][x]) >> TRANSBIT]++; } @@ -599,12 +593,12 @@ template void bilateral (T** src, T** dst, int W, int H, int sigmar, do // subtract pixels at the left and add pixels at the right if (j > r) - for (int x = MAX(0, i - r); x <= MIN(i + r, H - 1); x++) { + for (int x = std::max(0, i - r); x <= std::min(i + r, H - 1); x++) { hist[(int)(src[x][j - r - 1]) >> TRANSBIT]--; } if (j < W - r) - for (int x = MAX(0, i - r); x <= MIN(i + r, H - 1); x++) { + for (int x = std::max(0, i - r); x <= std::min(i + r, H - 1); x++) { hist[((int)src[x][j + r]) >> TRANSBIT]++; } @@ -643,5 +637,3 @@ template void bilateral (T** src, T** dst, int W, int H, int sigmar, do } #undef BINBIT #undef TRANSBIT - -#endif diff --git a/rtengine/boxblur.cc b/rtengine/boxblur.cc new file mode 100644 index 000000000..045c7ac3f --- /dev/null +++ b/rtengine/boxblur.cc @@ -0,0 +1,421 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (C) 2010 Emil Martinec + * Copyright (C) 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 + * 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 "boxblur.h" + +#include "rt_math.h" +#include "opthelper.h" + +namespace rtengine +{ + +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 + + radius = rtengine::min(radius, W - 1, H - 1); + 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[numCols * (radius + 1)]); + + //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; + } + int pos = 0; + for (int col = radius + 1; col < W - radius; ++col) { + const float oldVal = lineBuffer[pos]; + lineBuffer[pos] = src[row][col]; + tempval = tempval + (src[row][col + radius] - oldVal) / len; + dst[row][col] = tempval; + ++pos; + pos = pos <= radius ? pos : 0; + } + + for (int col = W - radius; col < W; ++col) { + tempval = (tempval * len - lineBuffer[pos]) / (len - 1); + dst[row][col] = tempval; + --len; + ++pos; + pos = pos <= radius ? pos : 0; + } + } + + //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; + int pos = 0; + for (int row = radius + 1; row < H - radius; ++row) { + vfloat oldVal0 = rowBuffer[pos][0]; + vfloat oldVal1 = rowBuffer[pos][1]; + rowBuffer[pos][0] = LVFU(dst[row][col]); + rowBuffer[pos][1] = LVFU(dst[row][col + 4]); + tempv = tempv + (LVFU(dst[row + radius][col]) - oldVal0) * rlenv ; + temp1v = temp1v + (LVFU(dst[row + radius][col + 4]) - oldVal1) * rlenv ; + STVFU(dst[row][col], tempv); + STVFU(dst[row][col + 4], temp1v); + ++pos; + pos = pos <= radius ? pos : 0; + } + + for (int row = H - radius; row < H; ++row) { + lenm1v = lenv - onev; + tempv = (tempv * lenv - rowBuffer[pos][0]) / lenm1v; + temp1v = (temp1v * lenv - rowBuffer[pos][1]) / lenm1v; + STVFU(dst[row][col], tempv); + STVFU(dst[row][col + 4], temp1v); + lenv = lenm1v; + ++pos; + pos = pos <= radius ? pos : 0; + } + } + +#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 ++; + } + + int pos = 0; + for (int row = radius + 1; row < H - radius; ++row) { + for(int k = 0; k < numCols; ++k) { + float oldVal = rowBuffer[pos][k]; + rowBuffer[pos][k] = dst[row][col + k]; + dst[row][col + k] = dst[row - 1][col + k] + (dst[row + radius][col + k] - oldVal) / len; + } + ++pos; + pos = pos <= radius ? pos : 0; + } + + 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[pos][k]) / (len - 1); + } + len --; + ++pos; + pos = pos <= radius ? pos : 0; + } + } + +#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; + int pos = 0; + for (int row = radius + 1; row < H - radius; ++row) { + for(int k = 0; k < remaining; ++k) { + float oldVal = rowBuffer[pos][k]; + rowBuffer[pos][k] = dst[row][col + k]; + dst[row][col + k] = dst[row - 1][col + k] + (dst[row + radius][col + k] - oldVal) * rlen; + } + ++pos; + pos = pos <= radius ? pos : 0; + } + 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[pos][k]) / (len - 1); + } + len --; + ++pos; + pos = pos <= radius ? pos : 0; + } + } + } + } +} + +void boxabsblur(float** src, float** dst, int radius, int W, int H, bool multiThread) +{ + //abs box blur using rowbuffers and linebuffers instead of a full size buffer, W should be a multiple of 16 + + 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] = std::fabs(src[row][col]); + } + } + } + return; + } + + constexpr int numCols = 16; // process numCols columns at once for better usage of L1 cpu cache +#ifdef _OPENMP + #pragma omp parallel if (multiThread) +#endif + { + float buffer[numCols * (radius + 1)] ALIGNED64; + + //horizontal blur + float* const lineBuffer = buffer; +#ifdef _OPENMP + #pragma omp for +#endif + for (int row = 0; row < H; ++row) { + float len = radius + 1; + float tempval = std::fabs(src[row][0]); + lineBuffer[0] = tempval; + for (int j = 1; j <= radius; j++) { + tempval += std::fabs(src[row][j]); + } + + tempval /= len; + dst[row][0] = tempval; + + for (int col = 1; col <= radius; ++col) { + lineBuffer[col] = std::fabs(src[row][col]); + tempval = (tempval * len + std::fabs(src[row][col + radius])) / (len + 1); + dst[row][col] = tempval; + ++len; + } + + const float rlen = 1.f / len; + int pos = 0; + for (int col = radius + 1; col < W - radius; ++col) { + const float oldVal = lineBuffer[pos]; + lineBuffer[pos] = std::fabs(src[row][col]); + tempval = tempval + (std::fabs(src[row][col + radius]) - oldVal) * rlen; + dst[row][col] = tempval; + ++pos; + pos = pos <= radius ? pos : 0; + } + + for (int col = W - radius; col < W; ++col) { + tempval = (tempval * len - lineBuffer[pos]) / (len - 1); + dst[row][col] = tempval; + --len; + ++pos; + pos = pos <= radius ? pos : 0; + } + } + + //vertical blur + float (* const rowBuffer)[numCols] = (float(*)[numCols]) buffer; +#ifdef _OPENMP + #pragma omp for +#endif + + for (int col = 0; col < W; col += numCols) { + 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; + } + + const float rlen = 1.f / len; + int pos = 0; + for (int row = radius + 1; row < H - radius; ++row) { + for(int k = 0; k < numCols; ++k) { + float oldVal = rowBuffer[pos][k]; + rowBuffer[pos][k] = dst[row][col + k]; + dst[row][col + k] = dst[row - 1][col + k] + (dst[row + radius][col + k] - oldVal) * rlen; + } + ++pos; + pos = pos <= radius ? pos : 0; + } + + 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[pos][k]) / (len - 1); + } + --len; + ++pos; + pos = pos <= radius ? pos : 0; + } + } + } +} + +void boxblur(float* src, float* dst, int radius, int W, int H, bool multiThread) +{ + float* srcp[H]; + float* dstp[H]; + for (int i = 0; i < H; ++i) { + srcp[i] = src + i * W; + dstp[i] = dst + i * W; + } + boxblur(srcp, dstp, radius, W, H, multiThread); +} + +void boxabsblur(float* src, float* dst, int radius, int W, int H, bool multiThread) +{ + float* srcp[H]; + float* dstp[H]; + for (int i = 0; i < H; ++i) { + srcp[i] = src + i * W; + dstp[i] = dst + i * W; + } + boxabsblur(srcp, dstp, radius, W, H, multiThread); +} + +} diff --git a/rtengine/boxblur.h b/rtengine/boxblur.h index d686ad43e..57fba9119 100644 --- a/rtengine/boxblur.h +++ b/rtengine/boxblur.h @@ -1,7 +1,7 @@ /* * This file is part of RawTherapee. * - * Copyright (C) 2010 Emil Martinec + * Copyright (C) 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 @@ -14,633 +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 . - */ -#ifndef _BOXBLUR_H_ -#define _BOXBLUR_H_ - -#include -#include -#include -#include -#include "alignedbuffer.h" -#include "rt_math.h" -#include "opthelper.h" - + * along with RawTherapee. If not, see . +*/ +#pragma once namespace rtengine { -// classical filtering if the support window is small: - -template void boxblur (T** src, A** dst, int radx, int rady, int W, int H) -{ - //box blur image; box range = (radx,rady) - assert(2*radx+1 < W); - assert(2*rady+1 < H); - - AlignedBuffer* buffer = new AlignedBuffer (W * H); - float* temp = buffer->data; - - if (radx == 0) { -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int row = 0; row < H; row++) - for (int col = 0; col < W; col++) { - temp[row * W + col] = (float)src[row][col]; - } - } else { - //horizontal blur -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int row = 0; row < H; row++) { - int len = radx + 1; - temp[row * W + 0] = (float)src[row][0] / len; - - for (int j = 1; j <= radx; j++) { - temp[row * W + 0] += (float)src[row][j] / len; - } - - for (int col = 1; col <= radx; col++) { - temp[row * W + col] = (temp[row * W + col - 1] * len + (float)src[row][col + radx]) / (len + 1); - len ++; - } - - for (int col = radx + 1; col < W - radx; col++) { - temp[row * W + col] = temp[row * W + col - 1] + ((float)(src[row][col + radx] - src[row][col - radx - 1])) / len; - } - - for (int col = W - radx; col < W; col++) { - temp[row * W + col] = (temp[row * W + col - 1] * len - src[row][col - radx - 1]) / (len - 1); - len --; - } - } - } - - if (rady == 0) { -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int row = 0; row < H; row++) - for (int col = 0; col < W; col++) { - dst[row][col] = temp[row * W + col]; - } - } else { - //vertical blur -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int col = 0; col < W; col++) { - int len = rady + 1; - dst[0][col] = temp[0 * W + col] / len; - - for (int i = 1; i <= rady; i++) { - dst[0][col] += temp[i * W + col] / len; - } - - for (int row = 1; row <= rady; row++) { - dst[row][col] = (dst[(row - 1)][col] * len + temp[(row + rady) * W + col]) / (len + 1); - len ++; - } - - for (int row = rady + 1; row < H - rady; row++) { - dst[row][col] = dst[(row - 1)][col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len; - } - - for (int row = H - rady; row < H; row++) { - dst[row][col] = (dst[(row - 1)][col] * len - temp[(row - rady - 1) * W + col]) / (len - 1); - len --; - } - } - } - - delete buffer; +void boxblur(float** src, float** dst, int radius, int W, int H, bool multiThread); +void boxblur(float* src, float* dst, int radius, int W, int H, bool multiThread); +void boxabsblur(float** src, float** dst, int radius, int W, int H, bool multiThread); +void boxabsblur(float* src, float* dst, int radius, int W, int H, bool multiThread); } - -template void boxblur (T** src, A** dst, T* buffer, int radx, int rady, int W, int H) -{ - //box blur image; box range = (radx,rady) - - float* temp = buffer; - - if (radx == 0) { -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 0; row < H; row++) - for (int col = 0; col < W; col++) { - temp[row * W + col] = (float)src[row][col]; - } - } else { - //horizontal blur -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 0; row < H; row++) { - float len = radx + 1; - float tempval = (float)src[row][0]; - - for (int j = 1; j <= radx; j++) { - tempval += (float)src[row][j]; - } - - tempval /= len; - temp[row * W + 0] = tempval; - - for (int col = 1; col <= radx; col++) { - temp[row * W + col] = tempval = (tempval * len + (float)src[row][col + radx]) / (len + 1); - len ++; - } - - for (int col = radx + 1; col < W - radx; col++) { - temp[row * W + col] = tempval = tempval + ((float)(src[row][col + radx] - src[row][col - radx - 1])) / len; - } - - for (int col = W - radx; col < W; col++) { - temp[row * W + col] = tempval = (tempval * len - src[row][col - radx - 1]) / (len - 1); - len --; - } - } - } - - if (rady == 0) { -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 0; row < H; row++) - for (int col = 0; col < W; col++) { - dst[row][col] = temp[row * W + col]; - } - } else { - const int numCols = 8; // process numCols columns at once for better usage of L1 cpu cache -#ifdef __SSE2__ - vfloat leninitv = F2V( (float)(rady + 1)); - vfloat onev = F2V( 1.f ); - vfloat tempv, temp1v, lenv, lenp1v, lenm1v, rlenv; - -#ifdef _OPENMP - #pragma omp for -#endif - - for (int col = 0; col < W - 7; col += 8) { - lenv = leninitv; - tempv = LVFU(temp[0 * W + col]); - temp1v = LVFU(temp[0 * W + col + 4]); - - for (int i = 1; i <= rady; i++) { - tempv = tempv + LVFU(temp[i * W + col]); - temp1v = temp1v + LVFU(temp[i * W + col + 4]); - } - - tempv = tempv / lenv; - temp1v = temp1v / lenv; - 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); - lenv = lenp1v; - } - - rlenv = onev / lenv; - - 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); - } - - 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); - lenv = lenm1v; - } - } - -#else - //vertical blur -#ifdef _OPENMP - #pragma omp for -#endif - - for (int col = 0; col < W - numCols + 1; col += 8) { - float len = rady + 1; - - for(int k = 0; k < numCols; k++) { - dst[0][col + k] = temp[0 * W + col + k]; - } - - for (int i = 1; i <= rady; i++) { - for(int k = 0; k < numCols; k++) { - dst[0][col + k] += temp[i * W + col + k]; - } - } - - for(int k = 0; k < numCols; k++) { - dst[0][col + k] /= len; - } - - for (int row = 1; row <= rady; row++) { - for(int k = 0; k < numCols; k++) { - dst[row][col + k] = (dst[(row - 1)][col + k] * len + temp[(row + rady) * W + col + k]) / (len + 1); - } - - len ++; - } - - for (int row = rady + 1; row < H - rady; row++) { - for(int k = 0; k < numCols; k++) { - dst[row][col + k] = dst[(row - 1)][col + k] + (temp[(row + rady) * W + col + k] - temp[(row - rady - 1) * W + col + k]) / len; - } - } - - for (int row = H - rady; row < H; row++) { - for(int k = 0; k < numCols; k++) { - dst[row][col + k] = (dst[(row - 1)][col + k] * len - temp[(row - rady - 1) * W + col + k]) / (len - 1); - } - - len --; - } - } - -#endif -#ifdef _OPENMP - #pragma omp single -#endif - - for (int col = W - (W % numCols); col < W; col++) { - float len = rady + 1; - dst[0][col] = temp[0 * W + col] / len; - - for (int i = 1; i <= rady; i++) { - dst[0][col] += temp[i * W + col] / len; - } - - for (int row = 1; row <= rady; row++) { - dst[row][col] = (dst[(row - 1)][col] * len + temp[(row + rady) * W + col]) / (len + 1); - len ++; - } - - for (int row = rady + 1; row < H - rady; row++) { - dst[row][col] = dst[(row - 1)][col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len; - } - - for (int row = H - rady; row < H; row++) { - dst[row][col] = (dst[(row - 1)][col] * len - temp[(row - rady - 1) * W + col]) / (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) - - float* temp = buffer; - - if (radx == 0) { - for (int row = 0; row < H; row++) - for (int col = 0; col < W; col++) { - temp[row * W + col] = src[row * W + col]; - } - } else { - //horizontal blur - for (int row = H - 1; row >= 0; row--) { - int len = radx + 1; - float tempval = (float)src[row * W]; - - for (int j = 1; j <= radx; j++) { - tempval += (float)src[row * W + j]; - } - - tempval = tempval / len; - temp[row * W] = tempval; - - for (int col = 1; col <= radx; col++) { - tempval = (tempval * len + src[row * W + col + radx]) / (len + 1); - temp[row * W + col] = tempval; - len ++; - } - - float reclen = 1.f / len; - - for (int col = radx + 1; col < W - radx; col++) { - tempval = tempval + ((float)(src[row * W + col + radx] - src[row * W + col - radx - 1])) * reclen; - temp[row * W + col] = tempval; - } - - for (int col = W - radx; col < W; col++) { - tempval = (tempval * len - src[row * W + col - radx - 1]) / (len - 1); - temp[row * W + col] = tempval; - len --; - } - } - } - - if (rady == 0) { - for (int row = 0; row < H; row++) - for (int col = 0; col < W; col++) { - dst[row * W + col] = temp[row * W + col]; - } - } else { - //vertical blur -#ifdef __SSE2__ - vfloat leninitv = F2V( (float)(rady + 1)); - vfloat onev = F2V( 1.f ); - vfloat tempv, temp1v, lenv, lenp1v, lenm1v, rlenv; - int col; - - for (col = 0; col < W - 7; col += 8) { - lenv = leninitv; - tempv = LVFU(temp[0 * W + col]); - temp1v = LVFU(temp[0 * W + col + 4]); - - for (int i = 1; i <= rady; i++) { - tempv = tempv + LVFU(temp[i * W + col]); - temp1v = temp1v + LVFU(temp[i * W + col + 4]); - } - - tempv = tempv / lenv; - temp1v = temp1v / lenv; - 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); - lenv = lenp1v; - } - - rlenv = onev / lenv; - - 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); - } - - 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); - lenv = lenm1v; - } - } - - for (; col < W - 3; col += 4) { - lenv = leninitv; - tempv = LVFU(temp[0 * W + col]); - - for (int i = 1; i <= rady; i++) { - tempv = tempv + LVFU(temp[i * W + col]); - } - - tempv = tempv / lenv; - 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); - lenv = lenp1v; - } - - rlenv = onev / lenv; - - 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); - } - - 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); - lenv = lenm1v; - } - } - - for (; col < W; col++) { - int len = rady + 1; - dst[0 * W + col] = temp[0 * W + col] / len; - - for (int i = 1; i <= rady; i++) { - dst[0 * W + col] += temp[i * W + col] / len; - } - - for (int row = 1; row <= rady; row++) { - dst[row * W + col] = (dst[(row - 1) * W + col] * len + temp[(row + rady) * W + col]) / (len + 1); - len ++; - } - - for (int row = rady + 1; row < H - rady; row++) { - dst[row * W + col] = dst[(row - 1) * W + col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len; - } - - for (int row = H - rady; row < H; row++) { - dst[row * W + col] = (dst[(row - 1) * W + col] * len - temp[(row - rady - 1) * W + col]) / (len - 1); - len --; - } - } - -#else - - for (int col = 0; col < W; col++) { - int len = rady + 1; - dst[0 * W + col] = temp[0 * W + col] / len; - - for (int i = 1; i <= rady; i++) { - dst[0 * W + col] += temp[i * W + col] / len; - } - - for (int row = 1; row <= rady; row++) { - dst[row * W + col] = (dst[(row - 1) * W + col] * len + temp[(row + rady) * W + col]) / (len + 1); - len ++; - } - - for (int row = rady + 1; row < H - rady; row++) { - dst[row * W + col] = dst[(row - 1) * W + col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len; - } - - for (int row = H - rady; row < H; row++) { - dst[row * W + col] = (dst[(row - 1) * W + col] * len - temp[(row - rady - 1) * W + col]) / (len - 1); - len --; - } - } - -#endif - } - -} - -template void boxabsblur (T* src, A* dst, int radx, int rady, int W, int H, float * temp) -{ - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1) - - if (radx == 0) { - for (int row = 0; row < H; row++) - for (int col = 0; col < W; col++) { - temp[row * W + col] = fabs(src[row * W + col]); - } - } else { - //horizontal blur - for (int row = 0; row < H; row++) { - int len = radx + 1; - float tempval = fabsf((float)src[row * W + 0]); - - for (int j = 1; j <= radx; j++) { - tempval += fabsf((float)src[row * W + j]); - } - - tempval /= len; - temp[row * W + 0] = tempval; - - for (int col = 1; col <= radx; col++) { - tempval = (tempval * len + fabsf(src[row * W + col + radx])) / (len + 1); - temp[row * W + col] = tempval; - len ++; - } - - float rlen = 1.f / (float)len; - - for (int col = radx + 1; col < W - radx; col++) { - tempval = tempval + ((float)(fabsf(src[row * W + col + radx]) - fabsf(src[row * W + col - radx - 1]))) * rlen; - temp[row * W + col] = tempval; - } - - for (int col = W - radx; col < W; col++) { - tempval = (tempval * len - fabsf(src[row * W + col - radx - 1])) / (len - 1); - temp[row * W + col] = tempval; - len --; - } - } - } - - if (rady == 0) { - for (int row = 0; row < H; row++) - for (int col = 0; col < W; col++) { - dst[row * W + col] = temp[row * W + col]; - } - } else { - //vertical blur -#ifdef __SSE2__ - vfloat leninitv = F2V( (float)(rady + 1)); - vfloat onev = F2V( 1.f ); - vfloat tempv, lenv, lenp1v, lenm1v, rlenv; - - for (int col = 0; col < W - 3; col += 4) { - lenv = leninitv; - tempv = LVF(temp[0 * W + col]); - - for (int i = 1; i <= rady; i++) { - tempv = tempv + LVF(temp[i * W + col]); - } - - tempv = tempv / lenv; - STVF(dst[0 * W + col], tempv); - - for (int row = 1; row <= rady; row++) { - lenp1v = lenv + onev; - tempv = (tempv * lenv + LVF(temp[(row + rady) * W + col])) / lenp1v; - STVF(dst[row * W + col], tempv); - lenv = lenp1v; - } - - rlenv = onev / lenv; - - for (int row = rady + 1; row < H - rady; row++) { - tempv = tempv + (LVF(temp[(row + rady) * W + col]) - LVF(temp[(row - rady - 1) * W + col])) * rlenv; - STVF(dst[row * W + col], tempv); - } - - for (int row = H - rady; row < H; row++) { - lenm1v = lenv - onev; - tempv = (tempv * lenv - LVF(temp[(row - rady - 1) * W + col])) / lenm1v; - STVF(dst[row * W + col], tempv); - lenv = lenm1v; - } - } - - for (int col = W - (W % 4); col < W; col++) { - int len = rady + 1; - dst[0 * W + col] = temp[0 * W + col] / len; - - for (int i = 1; i <= rady; i++) { - dst[0 * W + col] += temp[i * W + col] / len; - } - - for (int row = 1; row <= rady; row++) { - dst[row * W + col] = (dst[(row - 1) * W + col] * len + temp[(row + rady) * W + col]) / (len + 1); - len ++; - } - - for (int row = rady + 1; row < H - rady; row++) { - dst[row * W + col] = dst[(row - 1) * W + col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len; - } - - for (int row = H - rady; row < H; row++) { - dst[row * W + col] = (dst[(row - 1) * W + col] * len - temp[(row - rady - 1) * W + col]) / (len - 1); - len --; - } - } - -#else - - for (int col = 0; col < W; col++) { - int len = rady + 1; - dst[0 * W + col] = temp[0 * W + col] / len; - - for (int i = 1; i <= rady; i++) { - dst[0 * W + col] += temp[i * W + col] / len; - } - - for (int row = 1; row <= rady; row++) { - dst[row * W + col] = (dst[(row - 1) * W + col] * len + temp[(row + rady) * W + col]) / (len + 1); - len ++; - } - - for (int row = rady + 1; row < H - rady; row++) { - dst[row * W + col] = dst[(row - 1) * W + col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len; - } - - for (int row = H - rady; row < H; row++) { - dst[row * W + col] = (dst[(row - 1) * W + col] * len - temp[(row - rady - 1) * W + col]) / (len - 1); - len --; - } - } - -#endif - } - -} - -} -#endif /* _BOXBLUR_H_ */ diff --git a/rtengine/cJSON.c b/rtengine/cJSON.c index fb8ce27e8..130c8e2a5 100644 --- a/rtengine/cJSON.c +++ b/rtengine/cJSON.c @@ -445,9 +445,7 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) p->buffer = NULL; return NULL; - } - if (newbuffer) - { + } else { memcpy(newbuffer, p->buffer, p->offset + 1); } p->hooks.deallocate(p->buffer); @@ -1436,7 +1434,7 @@ fail: static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) { unsigned char *output_pointer = NULL; - size_t length = 0; + size_t length; cJSON *current_element = item->child; if (output_buffer == NULL) diff --git a/rtengine/cJSON.h b/rtengine/cJSON.h index 786dd2e0e..49fd67b72 100644 --- a/rtengine/cJSON.h +++ b/rtengine/cJSON.h @@ -195,7 +195,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); /* Create a string where valuestring references a string so * it will not be freed by cJSON_Delete */ CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); -/* Create an object/arrray that only references it's elements so +/* Create an object/array that only references it's elements so * they will not be freed by cJSON_Delete */ CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); 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/calc_distort.cc b/rtengine/calc_distort.cc index 7af47adb2..3a7a4a1c4 100644 --- a/rtengine/calc_distort.cc +++ b/rtengine/calc_distort.cc @@ -5,8 +5,8 @@ locations (before and after tracking) to text files and to PPM files, and prints the features to the screen. **********************************************************************/ -#include "klt/pnmio.h" -#include "klt/klt.h" +#include +#include #include #include diff --git a/rtengine/calc_distort.h b/rtengine/calc_distort.h index 711bf9515..7d0c5ef54 100644 --- a/rtengine/calc_distort.h +++ b/rtengine/calc_distort.h @@ -1,4 +1,3 @@ -#ifndef CALC_DISTORTION__H -#define CALC_DISTORTION__H +#pragma once + int calcDistortion (unsigned char* img1, unsigned char* img2, int ncols, int nrows, int nfactor, double &distortion); -#endif diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc index 43de5d688..c5cfc26fa 100644 --- a/rtengine/camconst.cc +++ b/rtengine/camconst.cc @@ -2,6 +2,9 @@ * This file is part of RawTherapee. */ #include "camconst.h" +#include +#include +#include #include "settings.h" #include "rt_math.h" #include @@ -17,8 +20,6 @@ namespace rtengine { -extern const Settings* settings; - CameraConst::CameraConst() : pdafOffset(0) { memset(dcraw_matrix, 0, sizeof(dcraw_matrix)); @@ -252,7 +253,7 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model) } if (i % 4 != 0) { - fprintf(stderr, "\"masked_areas\" array length must be divisable by 4\n"); + fprintf(stderr, "\"masked_areas\" array length must be divisible by 4\n"); goto parse_error; } } @@ -637,7 +638,7 @@ CameraConst::update_globalGreenEquilibration(bool other) } bool -CameraConstantsStore::parse_camera_constants_file(Glib::ustring filename_) +CameraConstantsStore::parse_camera_constants_file(const Glib::ustring& filename_) { // read the file into a single long string const char *filename = filename_.c_str(); @@ -808,7 +809,7 @@ CameraConstantsStore::~CameraConstantsStore() } } -void CameraConstantsStore::init(Glib::ustring baseDir, Glib::ustring userSettingsDir) +void CameraConstantsStore::init(const Glib::ustring& baseDir, const Glib::ustring& userSettingsDir) { parse_camera_constants_file(Glib::build_filename(baseDir, "camconst.json")); diff --git a/rtengine/camconst.h b/rtengine/camconst.h index eb43da483..3af05ab01 100644 --- a/rtengine/camconst.h +++ b/rtengine/camconst.h @@ -1,11 +1,18 @@ /* * This file is part of RawTherapee. */ -#ifndef __CAMCONST__ -#define __CAMCONST__ +#pragma once -#include #include +#include +#include + +namespace Glib +{ + +class ustring; + +} namespace rtengine { @@ -14,7 +21,7 @@ struct camera_const_levels { int levels[4]; }; -class CameraConst +class CameraConst final { private: std::string make_model; @@ -56,21 +63,19 @@ public: void update_globalGreenEquilibration(bool other); }; -class CameraConstantsStore +class CameraConstantsStore final { private: std::map mCameraConstants; CameraConstantsStore(); - bool parse_camera_constants_file(Glib::ustring filename); + bool parse_camera_constants_file(const Glib::ustring& filename); public: ~CameraConstantsStore(); - void init(Glib::ustring baseDir, Glib::ustring userSettingsDir); + void init(const Glib::ustring& baseDir, const Glib::ustring& userSettingsDir); static CameraConstantsStore *getInstance(void); CameraConst *get(const char make[], const char model[]); }; } - -#endif diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 9551d5e16..ab42f3d19 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -1,4 +1,5 @@ /* +vim: set syntax=javascript: DO NOT EDIT THIS FILE! @@ -48,7 +49,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 +116,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 +160,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 +168,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 +202,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 +210,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 +240,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 +439,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 +463,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 +498,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 +523,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 +533,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 +589,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 +621,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": [ @@ -1082,9 +1083,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, @@ -1104,10 +1105,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": [ @@ -1116,9 +1117,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, @@ -1137,6 +1138,16 @@ Camera constants: } }, + { // Quality C, only raw crop + "make_model": [ "Canon EOS M6 Mark II", "Canon EOS 90D" ], + "raw_crop": [ 144, 72, 6984, 4660 ] + }, + + { // Quality C, only raw crop + "make_model": [ "Canon EOS R" ], + "raw_crop": [ 144, 46, 6744, 4500 ] + }, + // Canon Powershot { // Quality C, CHDK DNGs, raw frame correction "make_model": "Canon PowerShot A3100 IS", @@ -1176,7 +1187,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 } @@ -1277,6 +1288,16 @@ Camera constants: "ranges": { "white": 16100 } }, + { // Quality C + "make_model": "Fujifilm X10", + "ranges": { "white": 3788 } + }, + + { // Quality C + "make_model": "Fujifilm HS30EXR", + "ranges": { "white": 3765 } + }, + { // Quality B "make_model": "FUJIFILM X70", "dcraw_matrix": [ 10450,-4329,-878,-3217,11105,2421,-752,1758,6519 ], // DNG_v9.4 D65 @@ -1302,6 +1323,11 @@ Camera constants: "ranges": { "white": 16100 } }, + { // Quality C, bisected from the overexposed region of one pre-release sample file + "make_model": "FUJIFILM X-A7", + "ranges": { "white": 16382 } + }, + { // Quality B "make_model": "FUJIFILM X-A10", "dcraw_matrix": [ 11540,-4999,-991,-2949,10963,2278,-382,1049,5605 ], // DNGv9.12 D65 @@ -1346,8 +1372,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 @@ -1377,6 +1403,11 @@ Camera constants: "raw_crop": [ 4, 4, -4, -4 ] // full raw 6016x4016, Official 6000x4000 }, + { // Quality C, only raw crop + "make_model": "Leica SL2", + "raw_crop": [ 0, 0, 0, -18 ] // 18 rows at bottom are garbage + }, + { // Quality C "make_model": "LG mobile LG-H815", "dcraw_matrix": [ 5859,547,-1250,-6484,15547,547,-2422,5625,3906 ], // DNG D65 @@ -1481,6 +1512,12 @@ Camera constants: } }, + { // Quality B + "make_model": "NIKON COOLPIX P1000", + "dcraw_matrix": [ 14294, -6116, -1333, -1628, 10219, 1637, -14, 1158, 5022 ], // ColorMatrix2 from Adobe DNG Converter 11.4 + "ranges": { "black": 200, "white": 4093 } + }, + { // Quality B, no LENR samples "make_model": "Nikon D5", "dcraw_matrix": [ 9200,-3522,-992,-5755,13803,2117,-753,1486,6338 ], // adobe dng_v9.5 d65 @@ -1622,14 +1659,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], @@ -1725,9 +1762,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 @@ -1753,6 +1796,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 @@ -1800,7 +1852,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": [ @@ -1891,7 +1943,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 @@ -1911,7 +1964,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 @@ -1919,7 +1973,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 @@ -2118,6 +2173,31 @@ Camera constants: } }, + { // Quality A, issue #5204. + "make_model": [ "Panasonic DC-S1" ], + "dcraw_matrix": [ 9744, -3905, -779, -4899, 12807, 2324, -798, 1630, 5827 ], // ColorMatrix2 using illuminant D65 from Adobe DNG Converter 11.4 + "ranges": { + "white": [ + { "iso": 50, "levels": 8400 }, // LENR 8000 + { "iso": 64, "levels": 10450 }, // LENR 10000 + { "iso": 80, "levels": 13050 }, // LENR 12400 + { "iso": 100, "levels": 16320 } + ] + } + }, + + { // Quality X, issue #5204. No white frames available. + "make_model": [ "Panasonic DC-S1R" ], + "dcraw_matrix": [ 11822, -5321, -1249, -5958, 15114, 766, -614, 1264, 7043 ], // ColorMatrix2 using illuminant D65 from Adobe DNG Converter 11.4 + "ranges": { + "white": [ + { "iso": 50, "levels": 9500 }, + { "iso": [64, 80], "levels": 11600 }, + { "iso": 100, "levels": 16336 } + ] + } + }, + { // Quality B, per ISO info missing "make_model": "PENTAX K-x", "dcraw_matrix": [ 8843,-2837,-625,-5025,12644,2668,-411,1234,7410 ], // adobe dcp d65 @@ -2232,7 +2312,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 @@ -2255,8 +2340,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 @@ -2295,7 +2380,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 }, @@ -2379,7 +2464,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 @@ -2414,8 +2499,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": [ @@ -2451,7 +2536,7 @@ Camera constants: { // Quality C, "make_model": "Sony ILCE-7RM4", - "raw_crop": [ 0, 0, 9568, 0 ] // full raw frame 9600x6376 - 32 rightmost columns are garbage + "raw_crop": [ 0, 0, -32, 0 ] // full raw frame 9600x6376 - 32 rightmost columns are garbage. Using -32 instead of 9568 to support also 16-shot pixelshift files }, { // Quality B, color matrix copied from a7rm2 diff --git a/rtengine/canon_cr3_decoder.cc b/rtengine/canon_cr3_decoder.cc new file mode 100644 index 000000000..d9a10900c --- /dev/null +++ b/rtengine/canon_cr3_decoder.cc @@ -0,0 +1,3247 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2019 RawTherapee development team + * + * 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 . + */ + +// Code adapted from ART +// https://bitbucket.org/agriggio/art/ +/* + * + * This file is part of ART. + * + * ART 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. + * + * ART 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 ART. If not, see . +*/ + +// Code adapted from libraw +// https://github.com/LibRaw/LibRaw/ +/* + * File: libraw_crxdec.cpp + * Copyright (C) 2018-2019 Alexey Danilchenko + * Copyright (C) 2019 Alex Tutubalin, LibRaw LLC + * + Canon CR3 file decoder + +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). + + */ + +#include +#include +#include +#include +#include + +#include "dcraw.h" + +#include "rt_math.h" + +void DCraw::parse_canon_cr3() +{ + strncpy(make, "Canon", sizeof(make)); + + unsigned long long szAtomList = ifp->size; + short nesting = -1; + char AtomNameStack[128]; + unsigned short nTrack = 0; + short TrackType; + + const int err = parseCR3(0, szAtomList, nesting, AtomNameStack, nTrack, TrackType); + + if (err == 0 || err == -14) { // no error, or too deep nesting + selectCRXTrack(nTrack); + } +} + +void DCraw::selectCRXTrack(unsigned short maxTrack) +{ + std::int64_t bitcounts[CanonCR3Data::CRXTRACKS_MAXCOUNT] = {}; + std::int64_t maxbitcount = 0; + std::uint32_t maxjpegbytes = 0; + + for (unsigned int i = 0; i <= maxTrack && i < RT_canon_CR3_data.CRXTRACKS_MAXCOUNT; ++i) { + CanonCR3Data::crx_data_header_t* const d = &RT_canon_CR3_data.crx_header[i]; + + if (d->MediaType == 1) { // RAW + bitcounts[i] = std::int64_t(d->nBits) * std::int64_t(d->f_width) * std::int64_t(d->f_height); + + if (bitcounts[i] > maxbitcount) { + maxbitcount = bitcounts[i]; + } + } else if (d->MediaType == 2) { // JPEG + if (d->MediaSize > maxjpegbytes) { + maxjpegbytes = d->MediaSize; + thumb_offset = d->MediaOffset; + thumb_length = d->MediaSize; + } + } + } + + if (maxbitcount < 8) { + return; + } + + bool has_framei = false; + unsigned int framei = 0; + unsigned int framecnt = 0; + + for (unsigned int i = 0; i <= maxTrack && i < RT_canon_CR3_data.CRXTRACKS_MAXCOUNT; ++i) { + if (bitcounts[i] == maxbitcount) { + if (framecnt <= shot_select) { + has_framei = true; + framei = i; + } + + framecnt++; + } + } + + is_raw = framecnt; + + if (has_framei) { + CanonCR3Data::crx_data_header_t* const d = &RT_canon_CR3_data.crx_header[framei]; + data_offset = d->MediaOffset; + // data_size = d->MediaSize; + raw_width = d->f_width; + raw_height = d->f_height; + load_raw = &DCraw::crxLoadRaw; + + switch (d->cfaLayout) { + case 0: { + filters = 0x94949494; + break; + } + + case 1: { + filters = 0x61616161; + break; + } + + case 2: { + filters = 0x49494949; + break; + } + + case 3: { + filters = 0x16161616; + break; + } + } + + RT_canon_CR3_data.crx_track_selected = framei; + + int tiff_idx = -1; + std::int64_t tpixels = 0; + + for (unsigned int i = 0; i < tiff_nifds; ++i) { + if (std::int64_t(tiff_ifd[i].height) * std::int64_t(tiff_ifd[i].height) > tpixels) { + tpixels = std::int64_t(tiff_ifd[i].height) * std::int64_t(tiff_ifd[i].height); + tiff_idx = i; + } + } + + if (tiff_idx >= 0) { + flip = tiff_ifd[tiff_idx].flip; + } + } +} + +int DCraw::parseCR3( + unsigned long long oAtomList, + unsigned long long szAtomList, + short& nesting, + char* AtomNameStack, + unsigned short& nTrack, + short& TrackType +) +{ + /* + Atom starts with 4 bytes for Atom size and 4 bytes containing Atom name + Atom size includes the length of the header and the size of all "contained" + Atoms if Atom size == 1, Atom has the extended size stored in 8 bytes located + after the Atom name if Atom size == 0, it is the last top-level Atom extending + to the end of the file Atom name is often a 4 symbol mnemonic, but can be a + 4-byte integer + */ + const char UIID_Canon[17] = + "\x85\xc0\xb6\x87\x82\x0f\x11\xe0\x81\x11\xf4\xce\x46\x2b\x6a\x48"; +// const char UIID_Preview[17] = +// "\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16"; + + /* + AtomType = 0 - unknown: "unk." + AtomType = 1 - container atom: "cont" + AtomType = 2 - leaf atom: "leaf" + AtomType = 3 - can be container, can be leaf: "both" + */ +// const char sAtomeType[4][5] = {"unk.", "cont", "leaf", "both"}; + short AtomType; + static const struct { + char AtomName[5]; + short AtomType; + } AtomNamesList[] = { + {"dinf", 1}, + {"edts", 1}, + {"fiin", 1}, + {"ipro", 1}, + {"iprp", 1}, + {"mdia", 1}, + {"meco", 1}, + {"mere", 1}, + {"mfra", 1}, + {"minf", 1}, + {"moof", 1}, + {"moov", 1}, + {"mvex", 1}, + {"paen", 1}, + {"schi", 1}, + {"sinf", 1}, + {"skip", 1}, + {"stbl", 1}, + {"stsd", 1}, + {"strk", 1}, + {"tapt", 1}, + {"traf", 1}, + {"trak", 1}, + + {"cdsc", 2}, + {"colr", 2}, + {"dimg", 2}, + // {"dref", 2}, + {"free", 2}, + {"frma", 2}, + {"ftyp", 2}, + {"hdlr", 2}, + {"hvcC", 2}, + {"iinf", 2}, + {"iloc", 2}, + {"infe", 2}, + {"ipco", 2}, + {"ipma", 2}, + {"iref", 2}, + {"irot", 2}, + {"ispe", 2}, + {"meta", 2}, + {"mvhd", 2}, + {"pitm", 2}, + {"pixi", 2}, + {"schm", 2}, + {"thmb", 2}, + {"tkhd", 2}, + {"url ", 2}, + {"urn ", 2}, + + {"CCTP", 1}, + {"CRAW", 1}, + + {"JPEG", 2}, + {"CDI1", 2}, + {"CMP1", 2}, + + {"CNCV", 2}, + {"CCDT", 2}, + {"CTBO", 2}, + {"CMT1", 2}, + {"CMT2", 2}, + {"CMT3", 2}, + {"CMT4", 2}, + {"THMB", 2}, + {"co64", 2}, + {"mdat", 2}, + {"mdhd", 2}, + {"nmhd", 2}, + {"stsc", 2}, + {"stsz", 2}, + {"stts", 2}, + {"vmhd", 2}, + + {"dref", 3}, + {"uuid", 3}, + }; + + const char sHandlerType[5][5] = { + "unk.", + "soun", + "vide", + "hint", + "meta" + }; + + int err = 0; + + unsigned short tL; // Atom length represented in 4 or 8 bytes + char nmAtom[5]; // Atom name + unsigned long long oAtom; + unsigned long long szAtom; // Atom offset and Atom size + unsigned long long oAtomContent; + unsigned long long szAtomContent; // offset and size of Atom content + unsigned long long lHdr; + + char UIID[16]; + uchar CMP1[36]; + char HandlerType[5]; + char MediaFormatID[5]; +// unsigned int ImageWidth, ImageHeight; + unsigned long relpos_inDir; + unsigned long relpos_inBox; + unsigned int szItem; + unsigned int Tag; + unsigned int lTag; + unsigned short tItem; + + nmAtom[0] = MediaFormatID[0] = nmAtom[4] = MediaFormatID[4] = '\0'; + strncpy(HandlerType, sHandlerType[0], sizeof(HandlerType)); +// ImageWidth = ImageHeight = 0U; + oAtom = oAtomList; + ++nesting; + + if (nesting > 31) { + return -14; // too deep nesting + } + + short s_order = order; + + const auto is_bad_header = + [this]() -> bool + { + return + ( + order != 0x4D4D + && order != 0x4949 + ) + || get2() != 0x002A + || get4() != 0x00000008; + }; + + while ((oAtom + 8) <= (oAtomList + szAtomList)) { + lHdr = 0U; + err = 0; + order = 0x4D4D; + fseek(ifp, oAtom, SEEK_SET); + szAtom = get4(); + for (unsigned int c = 0; c < 4; ++c) { + nmAtom[c] = AtomNameStack[nesting * 4 + c] = fgetc(ifp); + } + AtomNameStack[(nesting + 1) * 4] = '\0'; + tL = 4; + AtomType = 0; + + for (const auto& atom : AtomNamesList) { + if (!strcmp(nmAtom, atom.AtomName)) { + AtomType = atom.AtomType; + break; + } + } + + if (!AtomType) { + err = 1; + } + + if (szAtom == 0) { + if (nesting != 0) { + err = -2; + goto fin; + } + + szAtom = szAtomList - oAtom; + oAtomContent = oAtom + 8; + szAtomContent = szAtom - 8; + } else if (szAtom == 1) { + if ((oAtom + 16) > (oAtomList + szAtomList)) { + err = -3; + goto fin; + } + + tL = 8; + szAtom = (static_cast(get4()) << 32) | get4(); + oAtomContent = oAtom + 16; + szAtomContent = szAtom - 16; + } else { + oAtomContent = oAtom + 8; + szAtomContent = szAtom - 8; + } + + if (!strcmp(nmAtom, "trak")) { + nTrack++; + TrackType = 0; + + if (nTrack >= RT_canon_CR3_data.CRXTRACKS_MAXCOUNT) { + break; + } + } + + if (!strcmp(AtomNameStack, "moovuuid")) { + lHdr = 16; + fread(UIID, 1, lHdr, ifp); + + if (!strncmp(UIID, UIID_Canon, lHdr)) { + AtomType = 1; + } else { + fseek(ifp, -lHdr, SEEK_CUR); + } + } else if (!strcmp(AtomNameStack, "moovuuidCCTP")) { + lHdr = 12; + } else if (!strcmp(AtomNameStack, "moovuuidCMT1")) { + const short q_order = order; + order = get2(); + + if (tL != 4 || is_bad_header()) { + err = -4; + goto fin; + } + + parse_tiff_ifd(oAtomContent); + order = q_order; + } else if (!strcmp(AtomNameStack, "moovuuidCMT2")) { + const short q_order = order; + order = get2(); + + if (tL != 4 || is_bad_header()) { + err = -5; + goto fin; + } + + parse_exif(oAtomContent); + order = q_order; + } else if (!strcmp(AtomNameStack, "moovuuidCMT3")) { + const short q_order = order; + order = get2(); + + if (tL != 4 || is_bad_header()) { + err = -6; + goto fin; + } + + fseek(ifp, -12L, SEEK_CUR); + parse_makernote(oAtomContent, 0); + order = q_order; + } else if (!strcmp(AtomNameStack, "moovuuidCMT4")) { + const short q_order = order; + order = get2(); + + if (tL != 4 || is_bad_header()) { + err = -6; + goto fin; + } + + const long off = ftell(ifp); + parse_gps(oAtomContent); + fseek(ifp, off, SEEK_SET); +// parse_gps_libraw(oAtomContent); + order = q_order; + } else if (!strcmp(AtomNameStack, "moovtrakmdiahdlr")) { + fseek(ifp, 8, SEEK_CUR); + for (unsigned int c = 0; c < 4; ++c) { + HandlerType[c] = fgetc(ifp); + } + + for (unsigned int c = 1; c < sizeof(sHandlerType) / sizeof(*sHandlerType); ++c) { + if (!strcmp(HandlerType, sHandlerType[c])) { + TrackType = c; + break; + } + } + } else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsd")) { + if (szAtomContent >= 16) { + fseek(ifp, 12, SEEK_CUR); + lHdr = 8; + } else { + err = -7; + goto fin; + } + + for (unsigned int c = 0; c < 4; ++c) { + MediaFormatID[c] = fgetc(ifp); + } + + if (TrackType == 2 && !strcmp(MediaFormatID, "CRAW")) { + if (szAtomContent >= 44) { + fseek(ifp, 24, SEEK_CUR); + } else { + err = -8; + goto fin; + } + } else { + AtomType = 2; // only continue for CRAW + lHdr = 0; + } + + /*ImageWidth = */ get2(); + /*ImageHeight = */ get2(); + } else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAW")) { + lHdr = 82; + } else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAWCMP1")) { + if (szAtomContent >= 40) { + fread(CMP1, 1, 36, ifp); + } else { + err = -7; + goto fin; + } + + if (crxParseImageHeader(CMP1, nTrack)) { + RT_canon_CR3_data.crx_header[nTrack].MediaType = 1; + } + } else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAWJPEG")) { + RT_canon_CR3_data.crx_header[nTrack].MediaType = 2; + } else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsz")) { + if (szAtomContent == 12) { + fseek(ifp, 4, SEEK_CUR); + } else if (szAtomContent == 16) { + fseek(ifp, 12, SEEK_CUR); + } else { + err = -9; + goto fin; + } + + RT_canon_CR3_data.crx_header[nTrack].MediaSize = get4(); + } else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblco64")) { + if (szAtomContent == 16) { + fseek(ifp, 8, SEEK_CUR); + } else { + err = -10; + goto fin; + } + + RT_canon_CR3_data.crx_header[nTrack].MediaOffset = (static_cast(get4()) << 32) | get4(); + } + + if ( + RT_canon_CR3_data.crx_header[nTrack].MediaSize + && RT_canon_CR3_data.crx_header[nTrack].MediaOffset + && oAtom + szAtom >= oAtomList + szAtomList + && !strncmp(AtomNameStack, "moovtrakmdiaminfstbl", 20) + ) { + if (TrackType == 4 && !strcmp(MediaFormatID, "CTMD")) { + order = 0x4949; + relpos_inDir = 0; + + while (relpos_inDir + 6 < RT_canon_CR3_data.crx_header[nTrack].MediaSize) { + fseek(ifp, RT_canon_CR3_data.crx_header[nTrack].MediaOffset + relpos_inDir, SEEK_SET); + szItem = get4(); + tItem = get2(); + + if ((relpos_inDir + szItem) > RT_canon_CR3_data.crx_header[nTrack].MediaSize) { + err = -11; + goto fin; + } + + if ( + tItem == 7 + || tItem == 8 + || tItem == 9 + ) { + relpos_inBox = relpos_inDir + 12; + + while (relpos_inBox + 8 < relpos_inDir + szItem) { + fseek(ifp, RT_canon_CR3_data.crx_header[nTrack].MediaOffset + relpos_inBox, SEEK_SET); + lTag = get4(); + Tag = get4(); + + if (lTag < 8) { + err = -12; + goto fin; + } else if (relpos_inBox + lTag > relpos_inDir + szItem) { + err = -11; + goto fin; + } + + if ( + Tag == 0x927C + && ( + tItem == 7 + || tItem == 8 + ) + ) { + fseek(ifp, RT_canon_CR3_data.crx_header[nTrack].MediaOffset + relpos_inBox + 8, SEEK_SET); + const short q_order = order; + order = get2(); + + if (is_bad_header()) { + err = -13; + goto fin; + } + + fseek(ifp, -8, SEEK_CUR); + RT_canon_CR3_data.CR3_CTMDtag = 1; + parse_makernote(RT_canon_CR3_data.crx_header[nTrack].MediaOffset + relpos_inBox + 8, 0); + RT_canon_CR3_data.CR3_CTMDtag = 0; + order = q_order; + } + + relpos_inBox += lTag; + } + } + + relpos_inDir += szItem; + } + + order = 0x4D4D; + } + } + + if (AtomType == 1) { + err = parseCR3(oAtomContent + lHdr, szAtomContent - lHdr, nesting, AtomNameStack, nTrack, TrackType); + + if (err) { + goto fin; + } + } + + oAtom += szAtom; + } + +fin: + --nesting; + + if (nesting >= 0) { + AtomNameStack[nesting * 4] = '\0'; + } + + order = s_order; + return err; +} + +// ----------------------------------------------------------------------------- + +namespace +{ + +unsigned int sgetn(int n, unsigned char* s) +{ + unsigned int result = 0; + + while (n-- > 0) { + result = (result << 8) | (*s++); + } + + return result; +} + +// this should be divisible by 4 +constexpr std::uint64_t CRX_BUF_SIZE = 0x10000; + +#if !defined (_WIN32) || (defined (__GNUC__) && !defined (__INTRINSIC_SPECIAL__BitScanReverse)) +/* __INTRINSIC_SPECIAL__BitScanReverse found in MinGW32-W64 v7.30 headers, may be there is a better solution? */ +inline void _BitScanReverse(std::uint32_t* Index, unsigned long Mask) +{ + *Index = sizeof(unsigned long) * 8 - 1 - __builtin_clzl(Mask); +} +std::uint32_t _byteswap_ulong(std::uint32_t x) +{ +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + return x; +#else + return __builtin_bswap32(x); +#endif +} +#endif + +struct LibRaw_abstract_datastream { + IMFILE* ifp; + + void lock() + { + } + void unlock() + { + } + void seek(long p, int how) + { + fseek(ifp, p, how); + } + int read(void* dst, int es, int count) + { + return fread(dst, es, count, ifp); + } +}; + +struct CrxBitstream { + std::uint8_t mdatBuf[CRX_BUF_SIZE]; + std::uint64_t mdatSize; + std::uint64_t curBufOffset; + std::uint32_t curPos; + std::uint32_t curBufSize; + std::uint32_t bitData; + std::int32_t bitsLeft; + LibRaw_abstract_datastream* input; +}; + +struct CrxBandParam { + CrxBitstream bitStream; + std::int16_t subbandWidth; + std::int16_t subbandHeight; + std::int32_t roundedBitsMask; + std::int32_t roundedBits; + std::int16_t curLine; + std::int32_t* lineBuf0; + std::int32_t* lineBuf1; + std::int32_t* lineBuf2; + std::int32_t sParam; + std::int32_t kParam; + std::int32_t* paramData; + std::int32_t* nonProgrData; + bool supportsPartial; +}; + +struct CrxWaveletTransform { + std::int32_t* subband0Buf; + std::int32_t* subband1Buf; + std::int32_t* subband2Buf; + std::int32_t* subband3Buf; + std::int32_t* lineBuf[8]; + std::int16_t curLine; + std::int16_t curH; + std::int8_t fltTapH; + std::int16_t height; + std::int16_t width; +}; + +struct CrxSubband { + CrxBandParam* bandParam; + std::uint64_t mdatOffset; + std::uint8_t* bandBuf; + std::int32_t bandSize; + std::uint64_t dataSize; + bool supportsPartial; + std::int32_t quantValue; + std::uint16_t width; + std::uint16_t height; + std::int32_t paramK; + std::int64_t dataOffset; +}; + +struct CrxPlaneComp { + std::uint8_t* compBuf; + CrxSubband* subBands; + CrxWaveletTransform* waveletTransform; + std::int8_t compNumber; + std::int64_t dataOffset; + std::int32_t compSize; + bool supportsPartial; + std::int32_t roundedBitsMask; + std::int8_t tileFlag; +}; + +struct CrxTile { + CrxPlaneComp* comps; + std::int8_t tileFlag; + std::int8_t tileNumber; + std::int64_t dataOffset; + std::int32_t tileSize; + std::uint16_t width; + std::uint16_t height; +}; + +struct CrxImage { + std::uint8_t nPlanes; + std::uint16_t planeWidth; + std::uint16_t planeHeight; + std::uint8_t samplePrecision; + std::uint8_t subbandCount; + std::uint8_t levels; + std::uint8_t nBits; + std::uint8_t encType; + std::uint8_t tileCols; + std::uint8_t tileRows; + CrxTile* tiles; + std::uint64_t mdatOffset; + std::uint64_t mdatSize; + std::int16_t* outBufs[4]; // one per plane + std::int16_t* planeBuf; + LibRaw_abstract_datastream* input; +}; + +enum TileFlags { + E_HAS_TILES_ON_THE_RIGHT = 1, + E_HAS_TILES_ON_THE_LEFT = 2, + E_HAS_TILES_ON_THE_BOTTOM = 4, + E_HAS_TILES_ON_THE_TOP = 8 +}; + +const std::int32_t exCoefNumTbl[0x120] = { + // level 1 + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + // level 2 + 1, 1, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 3, 2, 1, 0, 1, 0, 0, 0, 0, 0, 1, + 2, 4, 4, 2, 1, 2, 1, 0, 0, 0, 0, 1, 1, 4, 3, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, + 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 3, 2, 1, 0, 1, 0, 0, 0, 0, 0, 1, 2, 4, + 4, 2, 1, 2, 1, 0, 0, 0, 0, 1, 1, 4, 3, 1, 1, 1, 1, 0, 0, 0, 0, + + // level 3 + 1, 1, 7, 7, 1, 1, 3, 3, 1, 1, 1, 1, 1, 0, 7, 6, 1, 0, 3, 2, 1, 0, 1, 0, 1, + 2, 10, 10, 2, 2, 5, 4, 2, 1, 2, 1, 1, 1, 10, 9, 1, 2, 4, 4, 2, 1, 2, 1, 1, + 1, 9, 9, 1, 2, 4, 4, 2, 1, 2, 1, 1, 0, 9, 8, 1, 1, 4, 3, 1, 1, 1, 1, 1, 2, + 8, 8, 2, 1, 4, 3, 1, 1, 1, 1, 1, 1, 8, 7, 1, 1, 3, 3, 1, 1, 1, 1 +}; + +const std::uint32_t JS[32] = { + 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0002, 0x0002, 0x0002, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0010, 0x0010, 0x0020, 0x0020, 0x0040, 0x0040, 0x0080, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 +}; + +const std::uint32_t J[32] = { + 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x2, + 0x2, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x5, 0x5, 0x6, 0x6, + 0x7, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF +}; + +inline void crxFillBuffer(CrxBitstream* bitStrm) +{ + if (bitStrm->curPos >= bitStrm->curBufSize && bitStrm->mdatSize) { + bitStrm->curPos = 0; + bitStrm->curBufOffset += bitStrm->curBufSize; +#ifdef _OPENMP + #pragma omp critical +#endif + { +#ifndef _OPENMP + bitStrm->input->lock(); +#endif + bitStrm->input->seek(bitStrm->curBufOffset, SEEK_SET); + bitStrm->curBufSize = bitStrm->input->read(bitStrm->mdatBuf, 1, std::min(bitStrm->mdatSize, CRX_BUF_SIZE)); +#ifndef _OPENMP + bitStrm->input->unlock(); +#endif + + if (bitStrm->curBufSize < 1) { // nothing read + throw std::exception(); + } + + bitStrm->mdatSize -= bitStrm->curBufSize; + } + } +} + +inline int crxBitstreamGetZeros(CrxBitstream* bitStrm) +{ +// std::uint32_t bitData = bitStrm->bitData; + std::uint32_t nonZeroBit = 0; + std::uint64_t nextData = 0; + std::int32_t result = 0; + + if (bitStrm->bitData) { + _BitScanReverse(&nonZeroBit, bitStrm->bitData); + result = 31 - nonZeroBit; + bitStrm->bitData <<= 32 - nonZeroBit; + bitStrm->bitsLeft -= 32 - nonZeroBit; + } else { + std::uint32_t bitsLeft = bitStrm->bitsLeft; + + while (true) { + while (bitStrm->curPos + 4 <= bitStrm->curBufSize) { + nextData = _byteswap_ulong(*reinterpret_cast(bitStrm->mdatBuf + bitStrm->curPos)); + bitStrm->curPos += 4; + crxFillBuffer(bitStrm); + + if (nextData) { + _BitScanReverse(&nonZeroBit, static_cast(nextData)); + result = bitsLeft + 31 - nonZeroBit; + bitStrm->bitData = nextData << (32 - nonZeroBit); + bitStrm->bitsLeft = nonZeroBit; + return result; + } + + bitsLeft += 32; + } + + if (bitStrm->curBufSize < bitStrm->curPos + 1) { + break; // error + } + + nextData = bitStrm->mdatBuf[bitStrm->curPos++]; + crxFillBuffer(bitStrm); + + if (nextData) { + break; + } + + bitsLeft += 8; + } + + _BitScanReverse(&nonZeroBit, static_cast(nextData)); + result = static_cast(bitsLeft + 7 - nonZeroBit); + bitStrm->bitData = nextData << (32 - nonZeroBit); + bitStrm->bitsLeft = nonZeroBit; + } + + return result; +} + +inline std::uint32_t crxBitstreamGetBits(CrxBitstream* bitStrm, int bits) +{ + int bitsLeft = bitStrm->bitsLeft; + std::uint32_t bitData = bitStrm->bitData; + std::uint32_t nextWord; + std::uint8_t nextByte; + std::uint32_t result; + + if (bitsLeft < bits) { + // get them from stream + if (bitStrm->curPos + 4 <= bitStrm->curBufSize) { + nextWord = _byteswap_ulong(*reinterpret_cast(bitStrm->mdatBuf + bitStrm->curPos)); + bitStrm->curPos += 4; + crxFillBuffer(bitStrm); + bitStrm->bitsLeft = 32 - (bits - bitsLeft); + result = ((nextWord >> bitsLeft) | bitData) >> (32 - bits); + bitStrm->bitData = nextWord << (bits - bitsLeft); + return result; + } + + // less than a word left - read byte at a time + do { + if (bitStrm->curPos >= bitStrm->curBufSize) { + break; // error + } + + bitsLeft += 8; + nextByte = bitStrm->mdatBuf[bitStrm->curPos++]; + crxFillBuffer(bitStrm); + bitData |= nextByte << (32 - bitsLeft); + } while (bitsLeft < bits); + } + + result = bitData >> (32 - bits); // 32-bits + bitStrm->bitData = bitData << bits; + bitStrm->bitsLeft = bitsLeft - bits; + return result; +} + +inline std::int32_t crxPredictKParameter(std::int32_t prevK, std::int32_t bitCode, std::int32_t maxVal = 0) +{ + const std::int32_t newKParam = + prevK + - (bitCode < (1 << prevK >> 1)) + + ((bitCode >> prevK) > 2) + ((bitCode >> prevK) > 5); + + return + !maxVal || newKParam < maxVal + ? newKParam + : maxVal; +} + +inline void crxDecodeSymbolL1(CrxBandParam* param, bool doMedianPrediction, bool notEOL = false) +{ + if (doMedianPrediction) { + const std::int32_t delta = param->lineBuf0[1] - param->lineBuf0[0]; + const std::int32_t symb[4] = { + delta + param->lineBuf1[0], + delta + param->lineBuf1[0], + param->lineBuf1[0], + param->lineBuf0[1] + }; + + param->lineBuf1[1] = symb[ + (((param->lineBuf0[0] < param->lineBuf1[0]) ^ (delta < 0)) << 1) + + ((param->lineBuf1[0] < param->lineBuf0[1]) ^ (delta < 0)) + ]; + } else { + param->lineBuf1[1] = param->lineBuf0[1]; + } + + // get next error symbol + std::uint32_t bitCode = crxBitstreamGetZeros(¶m->bitStream); + + if (bitCode >= 41) { + bitCode = crxBitstreamGetBits(¶m->bitStream, 21); + } else if (param->kParam) { + bitCode = crxBitstreamGetBits(¶m->bitStream, param->kParam) | (bitCode << param->kParam); + } + + // add converted (+/-) error code to predicted value + param->lineBuf1[1] += -(bitCode & 1) ^ (bitCode >> 1); + + // for not end of the line - use one symbol ahead to estimate next K + if (notEOL) { + const std::int32_t nextDelta = (param->lineBuf0[2] - param->lineBuf0[1]) << 1; + bitCode = (bitCode + std::abs(nextDelta)) >> 1; + ++param->lineBuf0; + } + + // update K parameter + param->kParam = crxPredictKParameter(param->kParam, bitCode, 15); + + ++param->lineBuf1; +} + +bool crxDecodeLine(CrxBandParam* param) +{ + int length = param->subbandWidth; + + param->lineBuf1[0] = param->lineBuf0[1]; + + for (; length > 1; --length) { + if (param->lineBuf1[0] != param->lineBuf0[1] || param->lineBuf1[0] != param->lineBuf0[2]) { + crxDecodeSymbolL1(param, true, true); + } else { + if (crxBitstreamGetBits(¶m->bitStream, 1)) { + int nSyms = 1; + + while (crxBitstreamGetBits(¶m->bitStream, 1)) { + nSyms += JS[param->sParam]; + + if (nSyms > length) { + nSyms = length; + break; + } + + if (param->sParam < 31) { + ++param->sParam; + } + + if (nSyms == length) { + break; + } + } + + if (nSyms < length) { + if (J[param->sParam]) { + nSyms += crxBitstreamGetBits(¶m->bitStream, J[param->sParam]); + } + + if (param->sParam > 0) { + --param->sParam; + } + + if (nSyms > length) { + return false; + } + } + + length -= nSyms; + + // copy symbol nSyms times + param->lineBuf0 += nSyms; + + // copy symbol nSyms times + while (nSyms-- > 0) { + param->lineBuf1[1] = param->lineBuf1[0]; + ++param->lineBuf1; + } + } + + if (length > 0) { + crxDecodeSymbolL1(param, false, length > 1); + } + } + } + + if (length == 1) { + crxDecodeSymbolL1(param, true, false); + } + + param->lineBuf1[1] = param->lineBuf1[0] + 1; + + return true; +} + +inline void crxDecodeSymbolL1Rounded(CrxBandParam* param, bool doSym = true, bool doCode = true) +{ + std::int32_t sym = param->lineBuf0[1]; + + if (doSym) { + // calculate the next symbol gradient + const std::int32_t deltaH = param->lineBuf0[1] - param->lineBuf0[0]; + const std::int32_t symb[4] = { + deltaH + param->lineBuf1[0], + deltaH + param->lineBuf1[0], + param->lineBuf1[0], + param->lineBuf0[1] + }; + sym = symb[ + (((param->lineBuf0[0] < param->lineBuf1[0]) ^ (deltaH < 0)) << 1) + + ((param->lineBuf1[0] < param->lineBuf0[1]) ^ (deltaH < 0)) + ]; + } + + std::uint32_t bitCode = crxBitstreamGetZeros(¶m->bitStream); + + if (bitCode >= 41) { + bitCode = crxBitstreamGetBits(¶m->bitStream, 21); + } else if (param->kParam) { + bitCode = crxBitstreamGetBits(¶m->bitStream, param->kParam) | (bitCode << param->kParam); + } + + std::int32_t code = -(bitCode & 1) ^ (bitCode >> 1); + param->lineBuf1[1] = param->roundedBitsMask * 2 * code + (code < 0) + sym; + + if (doCode) { + if (param->lineBuf0[2] > param->lineBuf0[1]) { + code = (param->lineBuf0[2] - param->lineBuf0[1] + param->roundedBitsMask - 1) >> param->roundedBits; + } else { + code = -((param->lineBuf0[1] - param->lineBuf0[2] + param->roundedBitsMask) >> param->roundedBits); + } + + param->kParam = crxPredictKParameter(param->kParam, (bitCode + 2 * std::abs(code)) >> 1, 15); + } else { + param->kParam = crxPredictKParameter(param->kParam, bitCode, 15); + } + + ++param->lineBuf1; +} + +bool crxDecodeLineRounded(CrxBandParam* param) +{ + bool valueReached = false; + + param->lineBuf0[0] = param->lineBuf0[1]; + param->lineBuf1[0] = param->lineBuf0[1]; + std::int32_t length = param->subbandWidth; + + for (; length > 1; --length) { + if (std::abs(param->lineBuf0[2] - param->lineBuf0[1]) > param->roundedBitsMask) { + crxDecodeSymbolL1Rounded(param); + ++param->lineBuf0; + valueReached = true; + } else if (valueReached || std::abs(param->lineBuf0[0] - param->lineBuf1[0]) > param->roundedBitsMask) { + crxDecodeSymbolL1Rounded(param); + ++param->lineBuf0; + valueReached = false; + } else { + int nSyms = 0; + + if (crxBitstreamGetBits(¶m->bitStream, 1)) { + nSyms = 1; + + while (crxBitstreamGetBits(¶m->bitStream, 1)) { + nSyms += JS[param->sParam]; + + if (nSyms > length) { + nSyms = length; + break; + } + + if (param->sParam < 31) { + ++param->sParam; + } + + if (nSyms == length) { + break; + } + } + + if (nSyms < length) { + if (J[param->sParam]) { + nSyms += crxBitstreamGetBits(¶m->bitStream, J[param->sParam]); + } + + if (param->sParam > 0) { + --param->sParam; + } + } + + if (nSyms > length) { + return false; + } + } + + length -= nSyms; + + // copy symbol nSyms times + param->lineBuf0 += nSyms; + + // copy symbol nSyms times + while (nSyms-- > 0) { + param->lineBuf1[1] = param->lineBuf1[0]; + ++param->lineBuf1; + } + + if (length > 1) { + crxDecodeSymbolL1Rounded(param, false); + ++param->lineBuf0; + valueReached = std::abs(param->lineBuf0[1] - param->lineBuf0[0]) > param->roundedBitsMask; + } else if (length == 1) { + crxDecodeSymbolL1Rounded(param, false, false); + } + } + } + + if (length == 1) { + crxDecodeSymbolL1Rounded(param, true, false); + } + + param->lineBuf1[1] = param->lineBuf1[0] + 1; + + return true; +} + +bool crxDecodeLineNoRefPrevLine(CrxBandParam* param) +{ + std::int32_t i = 0; + + for (; i < param->subbandWidth - 1; ++i) { + if (param->lineBuf0[i + 2] || param->lineBuf0[i + 1] || param->lineBuf1[i]) { + std::uint32_t bitCode = crxBitstreamGetZeros(¶m->bitStream); + + if (bitCode >= 41) { + bitCode = crxBitstreamGetBits(¶m->bitStream, 21); + } else if (param->kParam) { + bitCode = crxBitstreamGetBits(¶m->bitStream, param->kParam) | (bitCode << param->kParam); + } + + param->lineBuf1[i + 1] = -(bitCode & 1) ^ (bitCode >> 1); + param->kParam = crxPredictKParameter(param->kParam, bitCode); + + if (param->lineBuf2[i + 1] - param->kParam <= 1) { + if (param->kParam >= 15) { + param->kParam = 15; + } + } else { + ++param->kParam; + } + } else { + int nSyms = 0; + + if (crxBitstreamGetBits(¶m->bitStream, 1)) { + nSyms = 1; + + if (i != param->subbandWidth - 1) { + while (crxBitstreamGetBits(¶m->bitStream, 1)) { + nSyms += JS[param->sParam]; + + if (i + nSyms > param->subbandWidth) { + nSyms = param->subbandWidth - i; + break; + } + + if (param->sParam < 31) { + ++param->sParam; + } + + if (i + nSyms == param->subbandWidth) { + break; + } + } + + if (i + nSyms < param->subbandWidth) { + if (J[param->sParam]) { + nSyms += crxBitstreamGetBits(¶m->bitStream, J[param->sParam]); + } + + if (param->sParam > 0) { + --param->sParam; + } + } + + if (i + nSyms > param->subbandWidth) { + return false; + } + } + } else if (i > param->subbandWidth) { + return false; + } + + if (nSyms > 0) { + memset(param->lineBuf1 + i + 1, 0, nSyms * sizeof(std::int32_t)); + memset(param->lineBuf2 + i, 0, nSyms * sizeof(std::int32_t)); + i += nSyms; + } + + if (i >= param->subbandWidth - 1) { + if (i == param->subbandWidth - 1) { + std::uint32_t bitCode = crxBitstreamGetZeros(¶m->bitStream); + + if (bitCode >= 41) { + bitCode = crxBitstreamGetBits(¶m->bitStream, 21); + } else if (param->kParam) { + bitCode = crxBitstreamGetBits(¶m->bitStream, param->kParam) | (bitCode << param->kParam); + } + + param->lineBuf1[i + 1] = -((bitCode + 1) & 1) ^ ((bitCode + 1) >> 1); + param->kParam = crxPredictKParameter(param->kParam, bitCode, 15); + param->lineBuf2[i] = param->kParam; + } + + continue; + } else { + std::uint32_t bitCode = crxBitstreamGetZeros(¶m->bitStream); + + if (bitCode >= 41) { + bitCode = crxBitstreamGetBits(¶m->bitStream, 21); + } else if (param->kParam) { + bitCode = crxBitstreamGetBits(¶m->bitStream, param->kParam) | (bitCode << param->kParam); + } + + param->lineBuf1[i + 1] = -((bitCode + 1) & 1) ^ ((bitCode + 1) >> 1); + param->kParam = crxPredictKParameter(param->kParam, bitCode); + + if (param->lineBuf2[i + 1] - param->kParam <= 1) { + if (param->kParam >= 15) { + param->kParam = 15; + } + } else { + ++param->kParam; + } + } + } + + param->lineBuf2[i] = param->kParam; + } + + if (i == param->subbandWidth - 1) { + std::int32_t bitCode = crxBitstreamGetZeros(¶m->bitStream); + + if (bitCode >= 41) { + bitCode = crxBitstreamGetBits(¶m->bitStream, 21); + } else if (param->kParam) { + bitCode = crxBitstreamGetBits(¶m->bitStream, param->kParam) | (bitCode << param->kParam); + } + + param->lineBuf1[i + 1] = -(bitCode & 1) ^ (bitCode >> 1); + param->kParam = crxPredictKParameter(param->kParam, bitCode, 15); + param->lineBuf2[i] = param->kParam; + } + + return true; +} + +bool crxDecodeTopLine(CrxBandParam* param) +{ + param->lineBuf1[0] = 0; + + std::int32_t length = param->subbandWidth; + + // read the line from bitstream + for (; length > 1; --length) { + if (param->lineBuf1[0]) { + param->lineBuf1[1] = param->lineBuf1[0]; + } else { + if (crxBitstreamGetBits(¶m->bitStream, 1)) { + int nSyms = 1; + + while (crxBitstreamGetBits(¶m->bitStream, 1)) { + nSyms += JS[param->sParam]; + + if (nSyms > length) { + nSyms = length; + break; + } + + if (param->sParam < 31) { + ++param->sParam; + } + + if (nSyms == length) { + break; + } + } + + if (nSyms < length) { + if (J[param->sParam]) { + nSyms += crxBitstreamGetBits(¶m->bitStream, J[param->sParam]); + } + + if (param->sParam > 0) { + --param->sParam; + } + + if (nSyms > length) { + return false; + } + } + + length -= nSyms; + + // copy symbol nSyms times + while (nSyms-- > 0) { + param->lineBuf1[1] = param->lineBuf1[0]; + ++param->lineBuf1; + } + + if (length <= 0) { + break; + } + } + + param->lineBuf1[1] = 0; + } + + std::uint32_t bitCode = crxBitstreamGetZeros(¶m->bitStream); + + if (bitCode >= 41) { + bitCode = crxBitstreamGetBits(¶m->bitStream, 21); + } else if (param->kParam) { + bitCode = crxBitstreamGetBits(¶m->bitStream, param->kParam) | (bitCode << param->kParam); + } + + param->lineBuf1[1] += -(bitCode & 1) ^ (bitCode >> 1); + param->kParam = crxPredictKParameter(param->kParam, bitCode, 15); + ++param->lineBuf1; + } + + if (length == 1) { + param->lineBuf1[1] = param->lineBuf1[0]; + std::uint32_t bitCode = crxBitstreamGetZeros(¶m->bitStream); + + if (bitCode >= 41) { + bitCode = crxBitstreamGetBits(¶m->bitStream, 21); + } else if (param->kParam) { + bitCode = crxBitstreamGetBits(¶m->bitStream, param->kParam) | (bitCode << param->kParam); + } + + param->lineBuf1[1] += -(bitCode & 1) ^ (bitCode >> 1); + param->kParam = crxPredictKParameter(param->kParam, bitCode, 15); + ++param->lineBuf1; + } + + param->lineBuf1[1] = param->lineBuf1[0] + 1; + + return true; +} + +bool crxDecodeTopLineRounded(CrxBandParam* param) +{ + param->lineBuf1[0] = 0; + + std::int32_t length = param->subbandWidth; + + // read the line from bitstream + for (; length > 1; --length) { + if (std::abs(param->lineBuf1[0]) > param->roundedBitsMask) { + param->lineBuf1[1] = param->lineBuf1[0]; + } else { + int nSyms = 0; + + if (crxBitstreamGetBits(¶m->bitStream, 1)) { + nSyms = 1; + + while (crxBitstreamGetBits(¶m->bitStream, 1)) { + nSyms += JS[param->sParam]; + + if (nSyms > length) { + nSyms = length; + break; + } + + if (param->sParam < 31) { + ++param->sParam; + } + + if (nSyms == length) { + break; + } + } + + if (nSyms < length) { + if (J[param->sParam]) { + nSyms += crxBitstreamGetBits(¶m->bitStream, J[param->sParam]); + } + + if (param->sParam > 0) { + --param->sParam; + } + + if (nSyms > length) { + return false; + } + } + } + + length -= nSyms; + + // copy symbol nSyms times + while (nSyms-- > 0) { + param->lineBuf1[1] = param->lineBuf1[0]; + ++param->lineBuf1; + } + + if (length <= 0) { + break; + } + + param->lineBuf1[1] = 0; + } + + std::uint32_t bitCode = crxBitstreamGetZeros(¶m->bitStream); + + if (bitCode >= 41) { + bitCode = crxBitstreamGetBits(¶m->bitStream, 21); + } else if (param->kParam) { + bitCode = crxBitstreamGetBits(¶m->bitStream, param->kParam) | (bitCode << param->kParam); + } + + const std::int32_t sVal = -(bitCode & 1) ^ (bitCode >> 1); + param->lineBuf1[1] += param->roundedBitsMask * 2 * sVal + (sVal >> 31); + param->kParam = crxPredictKParameter(param->kParam, bitCode, 15); + ++param->lineBuf1; + } + + if (length == 1) { + std::uint32_t bitCode = crxBitstreamGetZeros(¶m->bitStream); + + if (bitCode >= 41) { + bitCode = crxBitstreamGetBits(¶m->bitStream, 21); + } else if (param->kParam) { + bitCode = crxBitstreamGetBits(¶m->bitStream, param->kParam) | (bitCode << param->kParam); + } + + const std::int32_t sVal = -(bitCode & 1) ^ (bitCode >> 1); + param->lineBuf1[1] += param->roundedBitsMask * 2 * sVal + (sVal >> 31); + param->kParam = crxPredictKParameter(param->kParam, bitCode, 15); + ++param->lineBuf1; + } + + param->lineBuf1[1] = param->lineBuf1[0] + 1; + + return true; +} + +bool crxDecodeTopLineNoRefPrevLine(CrxBandParam* param) +{ + param->lineBuf0[0] = 0; + param->lineBuf1[0] = 0; + std::int32_t length = param->subbandWidth; + + for (; length > 1; --length) { + if (param->lineBuf1[0]) { + std::uint32_t bitCode = crxBitstreamGetZeros(¶m->bitStream); + + if (bitCode >= 41) { + bitCode = crxBitstreamGetBits(¶m->bitStream, 21); + } else if (param->kParam) { + bitCode = crxBitstreamGetBits(¶m->bitStream, param->kParam) | (bitCode << param->kParam); + } + + param->lineBuf1[1] = -(bitCode & 1) ^ (bitCode >> 1); + param->kParam = crxPredictKParameter(param->kParam, bitCode, 15); + } else { + int nSyms = 0; + + if (crxBitstreamGetBits(¶m->bitStream, 1)) { + nSyms = 1; + + while (crxBitstreamGetBits(¶m->bitStream, 1)) { + nSyms += JS[param->sParam]; + + if (nSyms > length) { + nSyms = length; + break; + } + + if (param->sParam < 31) { + ++param->sParam; + } + + if (nSyms == length) { + break; + } + } + + if (nSyms < length) { + if (J[param->sParam]) { + nSyms += crxBitstreamGetBits(¶m->bitStream, J[param->sParam]); + } + + if (param->sParam > 0) { + --param->sParam; + } + + if (nSyms > length) { + return false; + } + } + } + + length -= nSyms; + + // copy symbol nSyms times + while (nSyms-- > 0) { + param->lineBuf2[0] = 0; + param->lineBuf1[1] = 0; + ++param->lineBuf1; + ++param->lineBuf2; + } + + if (length <= 0) { + break; + } + + std::uint32_t bitCode = crxBitstreamGetZeros(¶m->bitStream); + + if (bitCode >= 41) { + bitCode = crxBitstreamGetBits(¶m->bitStream, 21); + } else if (param->kParam) { + bitCode = crxBitstreamGetBits(¶m->bitStream, param->kParam) | (bitCode << param->kParam); + } + + param->lineBuf1[1] = -((bitCode + 1) & 1) ^ ((bitCode + 1) >> 1); + param->kParam = crxPredictKParameter(param->kParam, bitCode, 15); + } + + param->lineBuf2[0] = param->kParam; + ++param->lineBuf2; + ++param->lineBuf1; + } + + if (length == 1) { + std::uint32_t bitCode = crxBitstreamGetZeros(¶m->bitStream); + + if (bitCode >= 41) { + bitCode = crxBitstreamGetBits(¶m->bitStream, 21); + } else if (param->kParam) { + bitCode = crxBitstreamGetBits(¶m->bitStream, param->kParam) | (bitCode << param->kParam); + } + + param->lineBuf1[1] = -(bitCode & 1) ^ (bitCode >> 1); + param->kParam = crxPredictKParameter(param->kParam, bitCode, 15); + param->lineBuf2[0] = param->kParam; + ++param->lineBuf1; + } + + param->lineBuf1[1] = 0; + + return true; +} + +bool crxDecodeLine(CrxBandParam* param, std::uint8_t* bandBuf) +{ + if (!param || !bandBuf) { + return false; + } + + if (param->curLine >= param->subbandHeight) { + return false; + } + + if (param->curLine == 0) { + const std::int32_t lineLength = param->subbandWidth + 2; + + param->sParam = 0; + param->kParam = 0; + + if (param->supportsPartial) { + if (param->roundedBitsMask <= 0) { + param->lineBuf0 = param->paramData; + param->lineBuf1 = param->lineBuf0 + lineLength; + const std::int32_t* const lineBuf = param->lineBuf1 + 1; + + if (!crxDecodeTopLine(param)) { + return false; + } + + memcpy(bandBuf, lineBuf, param->subbandWidth * sizeof(std::int32_t)); + ++param->curLine; + } else { + param->roundedBits = 1; + + if (param->roundedBitsMask & ~1) { + while (param->roundedBitsMask >> param->roundedBits) { + ++param->roundedBits; + } + } + + param->lineBuf0 = param->paramData; + param->lineBuf1 = param->lineBuf0 + lineLength; + const std::int32_t* const lineBuf = param->lineBuf1 + 1; + + if (!crxDecodeTopLineRounded(param)) { + return false; + } + + memcpy(bandBuf, lineBuf, param->subbandWidth * sizeof(std::int32_t)); + ++param->curLine; + } + } else { + param->lineBuf2 = param->nonProgrData; + param->lineBuf0 = param->paramData; + param->lineBuf1 = param->lineBuf0 + lineLength; + const std::int32_t* const lineBuf = param->lineBuf1 + 1; + + if (!crxDecodeTopLineNoRefPrevLine(param)) { + return false; + } + + memcpy(bandBuf, lineBuf, param->subbandWidth * sizeof(std::int32_t)); + ++param->curLine; + } + } else if (!param->supportsPartial) { + const std::int32_t lineLength = param->subbandWidth + 2; + param->lineBuf2 = param->nonProgrData; + + if (param->curLine & 1) { + param->lineBuf1 = param->paramData; + param->lineBuf0 = param->lineBuf1 + lineLength; + } else { + param->lineBuf0 = param->paramData; + param->lineBuf1 = param->lineBuf0 + lineLength; + } + + const std::int32_t* const lineBuf = param->lineBuf1 + 1; + + if (!crxDecodeLineNoRefPrevLine(param)) { + return false; + } + + memcpy(bandBuf, lineBuf, param->subbandWidth * sizeof(std::int32_t)); + ++param->curLine; + } else if (param->roundedBitsMask <= 0) { + const std::int32_t lineLength = param->subbandWidth + 2; + + if (param->curLine & 1) { + param->lineBuf1 = param->paramData; + param->lineBuf0 = param->lineBuf1 + lineLength; + } else { + param->lineBuf0 = param->paramData; + param->lineBuf1 = param->lineBuf0 + lineLength; + } + + const std::int32_t* const lineBuf = param->lineBuf1 + 1; + + if (!crxDecodeLine(param)) { + return false; + } + + memcpy(bandBuf, lineBuf, param->subbandWidth * sizeof(std::int32_t)); + ++param->curLine; + } else { + const std::int32_t lineLength = param->subbandWidth + 2; + + if (param->curLine & 1) { + param->lineBuf1 = param->paramData; + param->lineBuf0 = param->lineBuf1 + lineLength; + } else { + param->lineBuf0 = param->paramData; + param->lineBuf1 = param->lineBuf0 + lineLength; + } + + const std::int32_t* const lineBuf = param->lineBuf1 + 1; + + if (!crxDecodeLineRounded(param)) { + return false; + } + + memcpy(bandBuf, lineBuf, param->subbandWidth * sizeof(std::int32_t)); + ++param->curLine; + } + + return true; +} + +bool crxDecodeLineWithIQuantization(CrxSubband* subband) +{ + constexpr std::int32_t q_step_tbl[6] = {0x28, 0x2D, 0x33, 0x39, 0x40, 0x48}; + + if (!subband->dataSize) { + memset(subband->bandBuf, 0, subband->bandSize); + return true; + } + + if (subband->supportsPartial) { + std::uint32_t bitCode = crxBitstreamGetZeros(&subband->bandParam->bitStream); + + if (bitCode >= 23) { + bitCode = crxBitstreamGetBits(&subband->bandParam->bitStream, 8); + } else if (subband->paramK) { + bitCode = crxBitstreamGetBits(&subband->bandParam->bitStream, subband->paramK) | (bitCode << subband->paramK); + } + + subband->quantValue += -(bitCode & 1) ^ (bitCode >> 1); // converting encoded to signed integer + subband->paramK = crxPredictKParameter(subband->paramK, bitCode); + + if (subband->paramK > 7) { + return false; + } + } + + if (!crxDecodeLine(subband->bandParam, subband->bandBuf)) { + return false; + } + + if (subband->width == 0) { + return true; + } + + // update subband buffers + std::int32_t* const bandBuf = reinterpret_cast(subband->bandBuf); + std::int32_t qScale = q_step_tbl[subband->quantValue % 6] >> (6 - subband->quantValue / 6); + + if (subband->quantValue / 6 >= 6) { + qScale = q_step_tbl[subband->quantValue % 6] * (1 << (subband->quantValue / 6 + 26)); + } + + if (qScale != 1) { + for (std::int32_t i = 0; i < subband->width; ++i) { + bandBuf[i] *= qScale; + } + } + + return true; +} + +void crxHorizontal53( + std::int32_t* lineBufLA, + std::int32_t* lineBufLB, + CrxWaveletTransform* wavelet, + std::uint32_t tileFlag +) +{ + std::int32_t* band0Buf = wavelet->subband0Buf; + std::int32_t* band1Buf = wavelet->subband1Buf; + std::int32_t* band2Buf = wavelet->subband2Buf; + std::int32_t* band3Buf = wavelet->subband3Buf; + + if (wavelet->width <= 1) { + lineBufLA[0] = band0Buf[0]; + lineBufLB[0] = band2Buf[0]; + } else { + if (tileFlag & E_HAS_TILES_ON_THE_LEFT) { + lineBufLA[0] = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2); + lineBufLB[0] = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2); + ++band1Buf; + ++band3Buf; + } else { + lineBufLA[0] = band0Buf[0] - ((band1Buf[0] + 1) >> 1); + lineBufLB[0] = band2Buf[0] - ((band3Buf[0] + 1) >> 1); + } + + ++band0Buf; + ++band2Buf; + + for (int i = 0; i < wavelet->width - 3; i += 2) { + std::int32_t delta = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2); + lineBufLA[1] = band1Buf[0] + ((delta + lineBufLA[0]) >> 1); + lineBufLA[2] = delta; + + delta = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2); + lineBufLB[1] = band3Buf[0] + ((delta + lineBufLB[0]) >> 1); + lineBufLB[2] = delta; + + ++band0Buf; + ++band1Buf; + ++band2Buf; + ++band3Buf; + lineBufLA += 2; + lineBufLB += 2; + } + + if (tileFlag & E_HAS_TILES_ON_THE_RIGHT) { + const std::int32_t deltaA = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2); + lineBufLA[1] = band1Buf[0] + ((deltaA + lineBufLA[0]) >> 1); + + const std::int32_t deltaB = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2); + lineBufLB[1] = band3Buf[0] + ((deltaB + lineBufLB[0]) >> 1); + + if (wavelet->width & 1) { + lineBufLA[2] = deltaA; + lineBufLB[2] = deltaB; + } + } else if (wavelet->width & 1) { + lineBufLA[1] = band1Buf[0] + ((lineBufLA[0] + band0Buf[0] - ((band1Buf[0] + 1) >> 1)) >> 1); + lineBufLA[2] = band0Buf[0] - ((band1Buf[0] + 1) >> 1); + + lineBufLB[1] = band3Buf[0] + ((lineBufLB[0] + band2Buf[0] - ((band3Buf[0] + 1) >> 1)) >> 1); + lineBufLB[2] = band2Buf[0] - ((band3Buf[0] + 1) >> 1); + } else { + lineBufLA[1] = lineBufLA[0] + band1Buf[0]; + lineBufLB[1] = lineBufLB[0] + band3Buf[0]; + } + } +} + +std::int32_t* crxIdwt53FilterGetLine(CrxPlaneComp* comp, std::int32_t level) +{ + std::int32_t* const result = comp->waveletTransform[level].lineBuf[ + (comp->waveletTransform[level].fltTapH - comp->waveletTransform[level].curH + 5) % 5 + 3 + ]; + --comp->waveletTransform[level].curH; + return result; +} + +bool crxIdwt53FilterDecode(CrxPlaneComp* comp, std::int32_t level) +{ + if (comp->waveletTransform[level].curH) { + return true; + } + + CrxSubband* const sband = comp->subBands + 3 * level; + + if (comp->waveletTransform[level].height - 3 <= comp->waveletTransform[level].curLine && !(comp->tileFlag & E_HAS_TILES_ON_THE_BOTTOM)) { + if (comp->waveletTransform[level].height & 1) { + if (level) { + if (!crxIdwt53FilterDecode(comp, level - 1)) { + return false; + } + } else if (!crxDecodeLineWithIQuantization(sband)) { + return false; + } + + if (!crxDecodeLineWithIQuantization(sband + 1)) { + return false; + } + } + } else { + if (level) { + if (!crxIdwt53FilterDecode(comp, level - 1)) { + return false; + } + } else if (!crxDecodeLineWithIQuantization(sband)) { // LL band + return false; + } + + if ( + !crxDecodeLineWithIQuantization(sband + 1) // HL band + || !crxDecodeLineWithIQuantization(sband + 2) // LH band + || !crxDecodeLineWithIQuantization(sband + 3) // HH band + ) { + return false; + } + } + + return true; +} + +bool crxIdwt53FilterTransform(CrxPlaneComp* comp, std::uint32_t level) +{ + CrxWaveletTransform* const wavelet = comp->waveletTransform + level; + + if (wavelet->curH) { + return true; + } + + if (wavelet->curLine >= wavelet->height - 3) { + if (!(comp->tileFlag & E_HAS_TILES_ON_THE_BOTTOM)) { + if (wavelet->height & 1) { + if (level) { + if (!wavelet[-1].curH) { + if (!crxIdwt53FilterTransform(comp, level - 1)) { + return false; + } + } + + wavelet->subband0Buf = crxIdwt53FilterGetLine(comp, level - 1); + } + + const std::int32_t* band0Buf = wavelet->subband0Buf; + const std::int32_t* band1Buf = wavelet->subband1Buf; + const std::int32_t* const lineBufH0 = wavelet->lineBuf[wavelet->fltTapH + 3]; + std::int32_t* const lineBufH1 = wavelet->lineBuf[(wavelet->fltTapH + 1) % 5 + 3]; + std::int32_t* const lineBufH2 = wavelet->lineBuf[(wavelet->fltTapH + 2) % 5 + 3]; + + std::int32_t* lineBufL0 = wavelet->lineBuf[0]; + std::int32_t* lineBufL1 = wavelet->lineBuf[1]; + wavelet->lineBuf[1] = wavelet->lineBuf[2]; + wavelet->lineBuf[2] = lineBufL1; + + // process L bands + if (wavelet->width <= 1) { + lineBufL0[0] = band0Buf[0]; + } else { + if (comp->tileFlag & E_HAS_TILES_ON_THE_LEFT) { + lineBufL0[0] = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2); + ++band1Buf; + } else { + lineBufL0[0] = band0Buf[0] - ((band1Buf[0] + 1) >> 1); + } + + ++band0Buf; + + for (int i = 0; i < wavelet->width - 3; i += 2) { + const std::int32_t delta = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2); + lineBufL0[1] = band1Buf[0] + ((lineBufL0[0] + delta) >> 1); + lineBufL0[2] = delta; + ++band0Buf; + ++band1Buf; + lineBufL0 += 2; + } + + if (comp->tileFlag & E_HAS_TILES_ON_THE_RIGHT) { + const std::int32_t delta = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2); + lineBufL0[1] = band1Buf[0] + ((lineBufL0[0] + delta) >> 1); + + if (wavelet->width & 1) { + lineBufL0[2] = delta; + } + } else if (wavelet->width & 1) { + const std::int32_t delta = band0Buf[0] - ((band1Buf[0] + 1) >> 1); + lineBufL0[1] = band1Buf[0] + ((lineBufL0[0] + delta) >> 1); + lineBufL0[2] = delta; + } else { + lineBufL0[1] = band1Buf[0] + lineBufL0[0]; + } + } + + // process H bands + lineBufL0 = wavelet->lineBuf[0]; + lineBufL1 = wavelet->lineBuf[1]; + + for (std::int32_t i = 0; i < wavelet->width; ++i) { + const std::int32_t delta = lineBufL0[i] - ((lineBufL1[i] + 1) >> 1); + lineBufH1[i] = lineBufL1[i] + ((delta + lineBufH0[i]) >> 1); + lineBufH2[i] = delta; + } + + wavelet->curH += 3; + wavelet->curLine += 3; + wavelet->fltTapH = (wavelet->fltTapH + 3) % 5; + } else { + std::int32_t* const lineBufL2 = wavelet->lineBuf[2]; + const std::int32_t* const lineBufH0 = wavelet->lineBuf[wavelet->fltTapH + 3]; + std::int32_t* const lineBufH1 = wavelet->lineBuf[(wavelet->fltTapH + 1) % 5 + 3]; + wavelet->lineBuf[1] = lineBufL2; + wavelet->lineBuf[2] = wavelet->lineBuf[1]; + + for (std::int32_t i = 0; i < wavelet->width; ++i) { + lineBufH1[i] = lineBufH0[i] + lineBufL2[i]; + } + + wavelet->curH += 2; + wavelet->curLine += 2; + wavelet->fltTapH = (wavelet->fltTapH + 2) % 5; + } + } + } else { + if (level) { + if (!wavelet[-1].curH && !crxIdwt53FilterTransform(comp, level - 1)) { + return false; + } + + wavelet->subband0Buf = crxIdwt53FilterGetLine(comp, level - 1); + } + + const std::int32_t* band0Buf = wavelet->subband0Buf; + const std::int32_t* band1Buf = wavelet->subband1Buf; + const std::int32_t* band2Buf = wavelet->subband2Buf; + const std::int32_t* band3Buf = wavelet->subband3Buf; + + std::int32_t* lineBufL0 = wavelet->lineBuf[0]; + std::int32_t* lineBufL1 = wavelet->lineBuf[1]; + const std::int32_t* const lineBufH0 = wavelet->lineBuf[wavelet->fltTapH + 3]; + std::int32_t* const lineBufH1 = wavelet->lineBuf[(wavelet->fltTapH + 1) % 5 + 3]; + std::int32_t* const lineBufH2 = wavelet->lineBuf[(wavelet->fltTapH + 2) % 5 + 3]; + + wavelet->lineBuf[1] = wavelet->lineBuf[2]; + wavelet->lineBuf[2] = lineBufL1; + + // process L bands + if (wavelet->width <= 1) { + lineBufL0[0] = band0Buf[0]; + lineBufL1[0] = band2Buf[0]; + } else { + if (comp->tileFlag & E_HAS_TILES_ON_THE_LEFT) { + lineBufL0[0] = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2); + lineBufL1[0] = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2); + ++band1Buf; + ++band3Buf; + } else { + lineBufL0[0] = band0Buf[0] - ((band1Buf[0] + 1) >> 1); + lineBufL1[0] = band2Buf[0] - ((band3Buf[0] + 1) >> 1); + } + + ++band0Buf; + ++band2Buf; + + for (int i = 0; i < wavelet->width - 3; i += 2) { + std::int32_t delta = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2); + lineBufL0[1] = band1Buf[0] + ((delta + lineBufL0[0]) >> 1); + lineBufL0[2] = delta; + + delta = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2); + lineBufL1[1] = band3Buf[0] + ((delta + lineBufL1[0]) >> 1); + lineBufL1[2] = delta; + + ++band0Buf; + ++band1Buf; + ++band2Buf; + ++band3Buf; + lineBufL0 += 2; + lineBufL1 += 2; + } + + if (comp->tileFlag & E_HAS_TILES_ON_THE_RIGHT) { + const std::int32_t deltaA = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2); + lineBufL0[1] = band1Buf[0] + ((deltaA + lineBufL0[0]) >> 1); + + const std::int32_t deltaB = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2); + lineBufL1[1] = band3Buf[0] + ((deltaB + lineBufL1[0]) >> 1); + + if (wavelet->width & 1) { + lineBufL0[2] = deltaA; + lineBufL1[2] = deltaB; + } + } else if (wavelet->width & 1) { + std::int32_t delta = band0Buf[0] - ((band1Buf[0] + 1) >> 1); + lineBufL0[1] = band1Buf[0] + ((delta + lineBufL0[0]) >> 1); + lineBufL0[2] = delta; + + delta = band2Buf[0] - ((band3Buf[0] + 1) >> 1); + lineBufL1[1] = band3Buf[0] + ((delta + lineBufL1[0]) >> 1); + lineBufL1[2] = delta; + } else { + lineBufL0[1] = lineBufL0[0] + band1Buf[0]; + lineBufL1[1] = lineBufL1[0] + band3Buf[0]; + } + } + + // process H bands + lineBufL0 = wavelet->lineBuf[0]; + lineBufL1 = wavelet->lineBuf[1]; + const std::int32_t* lineBufL2 = wavelet->lineBuf[2]; + + for (std::int32_t i = 0; i < wavelet->width; ++i) { + const std::int32_t delta = lineBufL0[i] - ((lineBufL2[i] + lineBufL1[i] + 2) >> 2); + lineBufH1[i] = lineBufL1[i] + ((delta + lineBufH0[i]) >> 1); + lineBufH2[i] = delta; + } + + if (wavelet->curLine >= wavelet->height - 3 && (wavelet->height & 1)) { + wavelet->curH += 3; + wavelet->curLine += 3; + wavelet->fltTapH = (wavelet->fltTapH + 3) % 5; + } else { + wavelet->curH += 2; + wavelet->curLine += 2; + wavelet->fltTapH = (wavelet->fltTapH + 2) % 5; + } + } + + return true; +} + +bool crxIdwt53FilterInitialize(CrxPlaneComp* comp, std::int32_t prevLevel) +{ + if (prevLevel < 0) { + return true; + } + + for (int curLevel = 0, curBand = 0; curLevel < prevLevel + 1; ++curLevel, curBand += 3) { + CrxWaveletTransform* const wavelet = comp->waveletTransform + curLevel; + + if (curLevel) { + wavelet[0].subband0Buf = crxIdwt53FilterGetLine(comp, curLevel - 1); + } else if (!crxDecodeLineWithIQuantization(comp->subBands + curBand)) { + return false; + } + + std::int32_t* lineBufH0 = wavelet->lineBuf[wavelet->fltTapH + 3]; + + if (wavelet->height > 1) { + if ( + !crxDecodeLineWithIQuantization(comp->subBands + curBand + 1) + || !crxDecodeLineWithIQuantization(comp->subBands + curBand + 2) + || !crxDecodeLineWithIQuantization(comp->subBands + curBand + 3) + ) { + return false; + } + + std::int32_t* const lineBufL0 = wavelet->lineBuf[0]; + const std::int32_t* const lineBufL1 = wavelet->lineBuf[1]; + std::int32_t* lineBufL2 = wavelet->lineBuf[2]; + + if (comp->tileFlag & E_HAS_TILES_ON_THE_TOP) { + crxHorizontal53(lineBufL0, wavelet->lineBuf[1], wavelet, comp->tileFlag); + + if (!crxDecodeLineWithIQuantization(comp->subBands + curBand + 3)|| !crxDecodeLineWithIQuantization(comp->subBands + curBand + 2)) { + return false; + } + + const std::int32_t* band2Buf = wavelet->subband2Buf; + const std::int32_t* band3Buf = wavelet->subband3Buf; + + // process L band + if (wavelet->width <= 1) { + lineBufL2[0] = band2Buf[0]; + } else { + if (comp->tileFlag & E_HAS_TILES_ON_THE_LEFT) { + lineBufL2[0] = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2); + ++band3Buf; + } else { + lineBufL2[0] = band2Buf[0] - ((band3Buf[0] + 1) >> 1); + } + + ++band2Buf; + + for (int i = 0; i < wavelet->width - 3; i += 2) { + const std::int32_t delta = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2); + lineBufL2[1] = band3Buf[0] + ((lineBufL2[0] + delta) >> 1); + lineBufL2[2] = delta; + + ++band2Buf; + ++band3Buf; + lineBufL2 += 2; + } + + if (comp->tileFlag & E_HAS_TILES_ON_THE_RIGHT) { + const std::int32_t delta = band2Buf[0] - ((band3Buf[0] + band3Buf[1] + 2) >> 2); + lineBufL2[1] = band3Buf[0] + ((lineBufL2[0] + delta) >> 1); + + if (wavelet->width & 1) { + lineBufL2[2] = delta; + } + } else if (wavelet->width & 1) { + const std::int32_t delta = band2Buf[0] - ((band3Buf[0] + 1) >> 1); + + lineBufL2[1] = band3Buf[0] + ((lineBufL2[0] + delta) >> 1); + lineBufL2[2] = delta; + } else { + lineBufL2[1] = band3Buf[0] + lineBufL2[0]; + } + } + + // process H band + for (std::int32_t i = 0; i < wavelet->width; ++i) { + lineBufH0[i] = lineBufL0[i] - ((lineBufL1[i] + lineBufL2[i] + 2) >> 2); + } + } else { + crxHorizontal53(lineBufL0, wavelet->lineBuf[2], wavelet, comp->tileFlag); + + for (int i = 0; i < wavelet->width; ++i) { + lineBufH0[i] = lineBufL0[i] - ((lineBufL2[i] + 1) >> 1); + } + } + + if (!crxIdwt53FilterDecode(comp, curLevel) || !crxIdwt53FilterTransform(comp, curLevel)) { + return false; + } + } else { + if (!crxDecodeLineWithIQuantization(comp->subBands + curBand + 1)) { + return false; + } + + const std::int32_t* band0Buf = wavelet->subband0Buf; + const std::int32_t* band1Buf = wavelet->subband1Buf; + + // process H band + if (wavelet->width <= 1) { + lineBufH0[0] = band0Buf[0]; + } else { + if (comp->tileFlag & E_HAS_TILES_ON_THE_LEFT) { + lineBufH0[0] = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2); + ++band1Buf; + } else { + lineBufH0[0] = band0Buf[0] - ((band1Buf[0] + 1) >> 1); + } + + ++band0Buf; + + for (int i = 0; i < wavelet->width - 3; i += 2) { + std::int32_t delta = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2); + lineBufH0[1] = band1Buf[0] + ((lineBufH0[0] + delta) >> 1); + lineBufH0[2] = delta; + + ++band0Buf; + ++band1Buf; + lineBufH0 += 2; + } + + if (comp->tileFlag & E_HAS_TILES_ON_THE_RIGHT) { + const std::int32_t delta = band0Buf[0] - ((band1Buf[0] + band1Buf[1] + 2) >> 2); + lineBufH0[1] = band1Buf[0] + ((lineBufH0[0] + delta) >> 1); + lineBufH0[2] = delta; + } else if (wavelet->width & 1) { + const std::int32_t delta = band0Buf[0] - ((band1Buf[0] + 1) >> 1); + lineBufH0[1] = band1Buf[0] + ((lineBufH0[0] + delta) >> 1); + lineBufH0[2] = delta; + } else { + lineBufH0[1] = band1Buf[0] + lineBufH0[0]; + } + } + + ++wavelet->curLine; + ++wavelet->curH; + wavelet->fltTapH = (wavelet->fltTapH + 1) % 5; + } + } + + return true; +} + +void crxFreeSubbandData(CrxImage* image, CrxPlaneComp* comp) +{ + if (comp->compBuf) { + free(comp->compBuf); + comp->compBuf = nullptr; + } + + if (!comp->subBands) { + return; + } + + for (std::int32_t i = 0; i < image->subbandCount; ++i) { + if (comp->subBands[i].bandParam) { + free(comp->subBands[i].bandParam); + comp->subBands[i].bandParam = nullptr; + } + + comp->subBands[i].bandBuf = nullptr; + comp->subBands[i].bandSize = 0; + } +} + +void crxConvertPlaneLine( + CrxImage* img, + int imageRow, + int imageCol = 0, + int plane = 0, + const std::int32_t* lineData = nullptr, + int lineLength = 0 +) +{ + if (lineData) { + std::uint64_t rawOffset = 4 * img->planeWidth * imageRow + 2 * imageCol; + + if (img->encType == 1) { + const std::int32_t maxVal = 1 << (img->nBits - 1); + const std::int32_t minVal = -maxVal; + + for (int i = 0; i < lineLength; ++i) { + img->outBufs[plane][rawOffset + 2 * i] = rtengine::LIM(lineData[i], minVal, maxVal - 1); + } + } else if (img->encType == 3) { + // copy to intermediate planeBuf + rawOffset = plane * img->planeWidth * img->planeHeight + img->planeWidth * imageRow + imageCol; + + for (int i = 0; i < lineLength; ++i) { + img->planeBuf[rawOffset + i] = lineData[i]; + } + } else if (img->nPlanes == 4) { + const std::int32_t median = 1 << (img->nBits - 1); + const std::int32_t maxVal = (1 << img->nBits) - 1; + + for (int i = 0; i < lineLength; ++i) { + img->outBufs[plane][rawOffset + 2 * i] = rtengine::LIM(median + lineData[i], 0, maxVal); + } + } else if (img->nPlanes == 1) { + const std::int32_t maxVal = (1 << img->nBits) - 1; + const std::int32_t median = 1 << (img->nBits - 1); + + rawOffset = img->planeWidth * imageRow + imageCol; + + for (int i = 0; i < lineLength; ++i) { + img->outBufs[0][rawOffset + i] = rtengine::LIM(median + lineData[i], 0, maxVal); + } + } + } else if (img->encType == 3 && img->planeBuf) { + const std::int32_t planeSize = img->planeWidth * img->planeHeight; + const std::int16_t* const plane0 = img->planeBuf + imageRow * img->planeWidth; + const std::int16_t* const plane1 = plane0 + planeSize; + const std::int16_t* const plane2 = plane1 + planeSize; + const std::int16_t* const plane3 = plane2 + planeSize; + + const std::int32_t median = 1 << (img->nBits - 1) << 10; + const std::int32_t maxVal = (1 << img->nBits) - 1; + const std::uint32_t rawLineOffset = 4 * img->planeWidth * imageRow; + + // for this stage - all except imageRow is ignored + for (int i = 0; i < img->planeWidth; ++i) { + std::int32_t gr = median + (plane0[i] << 10) - 168 * plane1[i] - 585 * plane3[i]; + + if (gr < 0) { + gr = -(((std::abs(gr) + 512) >> 9) & ~1); + } else { + gr = ((std::abs(gr) + 512) >> 9) & ~1; + } + + // Essentially R = round(median + P0 + 1.474*P3) + std::int32_t val = (median + (plane0[i] << 10) + 1510 * plane3[i] + 512) >> 10; + img->outBufs[0][rawLineOffset + 2 * i] = rtengine::LIM(val, 0, maxVal); + // Essentially G1 = round(median + P0 + P2 - 0.164*P1 - 0.571*P3) + val = (plane2[i] + gr + 1) >> 1; + img->outBufs[1][rawLineOffset + 2 * i] = rtengine::LIM(val, 0, maxVal); + // Essentially G1 = round(median + P0 - P2 - 0.164*P1 - 0.571*P3) + val = (gr - plane2[i] + 1) >> 1; + img->outBufs[2][rawLineOffset + 2 * i] = rtengine::LIM(val, 0, maxVal); + // Essentially B = round(median + P0 + 1.881*P1) + val = (median + (plane0[i] << 10) + 1927 * plane1[i] + 512) >> 10; + img->outBufs[3][rawLineOffset + 2 * i] = rtengine::LIM(val, 0, maxVal); + } + } +} + +bool crxParamInit( + CrxBandParam** param, + std::uint64_t subbandMdatOffset, + std::uint64_t subbandDataSize, + std::uint32_t subbandWidth, + std::uint32_t subbandHeight, + bool supportsPartial, + std::uint32_t roundedBitsMask, + LibRaw_abstract_datastream* input +) +{ + const std::int32_t progrDataSize = + supportsPartial + ? 0 + : sizeof(std::int32_t) * subbandWidth; + const std::int32_t paramLength = 2 * subbandWidth + 4; + + std::uint8_t* paramBuf = static_cast(calloc(1, sizeof(CrxBandParam) + sizeof(std::int32_t) * paramLength + progrDataSize)); + + if (!paramBuf) { + return false; + } + + *param = reinterpret_cast(paramBuf); + + paramBuf += sizeof(CrxBandParam); + + (*param)->paramData = reinterpret_cast(paramBuf); + (*param)->nonProgrData = + progrDataSize + ? (*param)->paramData + paramLength + : nullptr; + (*param)->subbandWidth = subbandWidth; + (*param)->subbandHeight = subbandHeight; + (*param)->roundedBits = 0; + (*param)->curLine = 0; + (*param)->roundedBitsMask = roundedBitsMask; + (*param)->supportsPartial = supportsPartial; + (*param)->bitStream.bitData = 0; + (*param)->bitStream.bitsLeft = 0; + (*param)->bitStream.mdatSize = subbandDataSize; + (*param)->bitStream.curPos = 0; + (*param)->bitStream.curBufSize = 0; + (*param)->bitStream.curBufOffset = subbandMdatOffset; + (*param)->bitStream.input = input; + + crxFillBuffer(&(*param)->bitStream); + + return true; +} + +bool crxSetupSubbandData( + CrxImage* img, + CrxPlaneComp* planeComp, + const CrxTile* tile, + std::uint32_t mdatOffset +) +{ + long compDataSize = 0; + long waveletDataOffset = 0; + long compCoeffDataOffset = 0; + const std::int32_t toSubbands = 3 * img->levels + 1; + + CrxSubband* const subbands = planeComp->subBands; + + // calculate sizes + for (std::int32_t subbandNum = 0; subbandNum < toSubbands; ++subbandNum) { + subbands[subbandNum].bandSize = subbands[subbandNum].width * sizeof(std::int32_t); // 4 bytes + compDataSize += subbands[subbandNum].bandSize; + } + + if (img->levels) { + const std::int32_t encLevels = + img->levels + ? img->levels + : 1; + waveletDataOffset = (compDataSize + 7) & ~7; + compDataSize = (sizeof(CrxWaveletTransform) * encLevels + waveletDataOffset + 7) & ~7; + compCoeffDataOffset = compDataSize; + + // calc wavelet line buffer sizes (always at one level up from current) + for (int level = 0; level < img->levels; ++level) { + if (level < img->levels - 1) { + compDataSize += 8 * sizeof(std::int32_t) * planeComp->subBands[3 * (level + 1) + 2].width; + } else { + compDataSize += 8 * sizeof(std::int32_t) * tile->width; + } + } + } + + // buffer allocation + planeComp->compBuf = static_cast(malloc(compDataSize)); + + if (!planeComp->compBuf) { + return false; + } + + // subbands buffer and sizes initialisation + const std::uint64_t subbandMdatOffset = img->mdatOffset + mdatOffset; + std::uint8_t* subbandBuf = planeComp->compBuf; + + for (std::int32_t subbandNum = 0; subbandNum < toSubbands; ++subbandNum) { + subbands[subbandNum].bandBuf = subbandBuf; + subbandBuf += subbands[subbandNum].bandSize; + subbands[subbandNum].mdatOffset = subbandMdatOffset + subbands[subbandNum].dataOffset; + } + + // wavelet data initialisation + if (img->levels) { + CrxWaveletTransform* const waveletTransforms = reinterpret_cast(planeComp->compBuf + waveletDataOffset); + std::int32_t* paramData = reinterpret_cast(planeComp->compBuf + compCoeffDataOffset); + + planeComp->waveletTransform = waveletTransforms; + waveletTransforms[0].subband0Buf = reinterpret_cast(subbands->bandBuf); + + for (int level = 0; level < img->levels; ++level) { + const std::int32_t band = 3 * level + 1; + + std::int32_t transformWidth = 0; + + if (level >= img->levels - 1) { + waveletTransforms[level].height = tile->height; + transformWidth = tile->width; + } else { + waveletTransforms[level].height = subbands[band + 3].height; + transformWidth = subbands[band + 4].width; + } + + waveletTransforms[level].width = transformWidth; + waveletTransforms[level].lineBuf[0] = paramData; + waveletTransforms[level].lineBuf[1] = waveletTransforms[level].lineBuf[0] + transformWidth; + waveletTransforms[level].lineBuf[2] = waveletTransforms[level].lineBuf[1] + transformWidth; + waveletTransforms[level].lineBuf[3] = waveletTransforms[level].lineBuf[2] + transformWidth; + waveletTransforms[level].lineBuf[4] = waveletTransforms[level].lineBuf[3] + transformWidth; + waveletTransforms[level].lineBuf[5] = waveletTransforms[level].lineBuf[4] + transformWidth; + waveletTransforms[level].lineBuf[6] = waveletTransforms[level].lineBuf[5] + transformWidth; + waveletTransforms[level].lineBuf[7] = waveletTransforms[level].lineBuf[6] + transformWidth; + waveletTransforms[level].curLine = 0; + waveletTransforms[level].curH = 0; + waveletTransforms[level].fltTapH = 0; + waveletTransforms[level].subband1Buf = reinterpret_cast(subbands[band].bandBuf); + waveletTransforms[level].subband2Buf = reinterpret_cast(subbands[band + 1].bandBuf); + waveletTransforms[level].subband3Buf = reinterpret_cast(subbands[band + 2].bandBuf); + + paramData = waveletTransforms[level].lineBuf[7] + transformWidth; + } + } + + // decoding params and bitstream initialisation + for (std::int32_t subbandNum = 0; subbandNum < toSubbands; ++subbandNum) { + if (subbands[subbandNum].dataSize) { + bool supportsPartial = false; + std::uint32_t roundedBitsMask = 0; + + if (planeComp->supportsPartial && subbandNum == 0) { + roundedBitsMask = planeComp->roundedBitsMask; + supportsPartial = true; + } + + if ( + !crxParamInit( + &subbands[subbandNum].bandParam, + subbands[subbandNum].mdatOffset, + subbands[subbandNum].dataSize, + subbands[subbandNum].width, + subbands[subbandNum].height, + supportsPartial, + roundedBitsMask, + img->input + ) + ) { + return false; + } + } + } + + return true; +} + +} // namespace + +bool DCraw::crxDecodePlane(void* p, std::uint32_t planeNumber) +{ + CrxImage* const img = static_cast(p); + int imageRow = 0; + + for (int tRow = 0; tRow < img->tileRows; ++tRow) { + int imageCol = 0; + + for (int tCol = 0; tCol < img->tileCols; ++tCol) { + const CrxTile* const tile = img->tiles + tRow * img->tileRows + tCol; + CrxPlaneComp* const planeComp = tile->comps + planeNumber; + const std::uint64_t tileMdatOffset = tile->dataOffset + planeComp->dataOffset; + + // decode single tile + if (!crxSetupSubbandData(img, planeComp, tile, tileMdatOffset)) { + return false; + } + + if (img->levels) { + if (!crxIdwt53FilterInitialize(planeComp, img->levels - 1)) { + return false; + } + + for (int i = 0; i < tile->height; ++i) { + if (!crxIdwt53FilterDecode(planeComp, img->levels - 1) || !crxIdwt53FilterTransform(planeComp, img->levels - 1)) { + return false; + } + + const std::int32_t* const lineData = crxIdwt53FilterGetLine(planeComp, img->levels - 1); + crxConvertPlaneLine(img, imageRow + i, imageCol, planeNumber, lineData, tile->width); + } + } else { + // we have the only subband in this case + if (!planeComp->subBands->dataSize) { + memset(planeComp->subBands->bandBuf, 0, planeComp->subBands->bandSize); + return true; + } + + for (int i = 0; i < tile->height; ++i) { + if (!crxDecodeLine(planeComp->subBands->bandParam, planeComp->subBands->bandBuf)) { + return false; + } + + const std::int32_t* const lineData = reinterpret_cast(planeComp->subBands->bandBuf); + crxConvertPlaneLine(img, imageRow + i, imageCol, planeNumber, lineData, tile->width); + } + } + + imageCol += tile->width; + } + + imageRow += img->tiles[tRow * img->tileRows].height; + } + + return true; +} + +namespace +{ + +using crx_data_header_t = DCraw::CanonCR3Data::crx_data_header_t; + +bool crxReadSubbandHeaders( + CrxImage* img, + CrxTile* tile, + CrxPlaneComp* comp, + std::uint8_t** subbandMdatPtr, + std::uint32_t* mdatSize +) +{ + CrxSubband* band = comp->subBands + img->subbandCount - 1; // set to last band + std::uint32_t bandHeight = tile->height; + std::uint32_t bandWidth = tile->width; + std::int32_t bandWidthExCoef = 0; + std::int32_t bandHeightExCoef = 0; + + if (img->levels) { + // Build up subband sequences to crxDecode to a level in a header + + // Coefficient structure is a bit unclear and convoluted: + // 3 levels max - 8 groups (for tile width rounded to 8 bytes) + // of 3 band per level 4 sets of coefficients for each + const std::int32_t* rowExCoef = exCoefNumTbl + 0x60 * (img->levels - 1) + 12 * (tile->width & 7); + const std::int32_t* colExCoef = exCoefNumTbl + 0x60 * (img->levels - 1) + 12 * (tile->height & 7); + + for (int level = 0; level < img->levels; ++level) { + const std::int32_t widthOddPixel = bandWidth & 1; + const std::int32_t heightOddPixel = bandHeight & 1; + bandWidth = (widthOddPixel + bandWidth) >> 1; + bandHeight = (heightOddPixel + bandHeight) >> 1; + + std::int32_t bandWidthExCoef0 = 0; + std::int32_t bandWidthExCoef1 = 0; + std::int32_t bandHeightExCoef0 = 0; + std::int32_t bandHeightExCoef1 = 0; + + if (tile->tileFlag & E_HAS_TILES_ON_THE_RIGHT) { + bandWidthExCoef0 = rowExCoef[0]; + bandWidthExCoef1 = rowExCoef[1]; + } + + if (tile->tileFlag & E_HAS_TILES_ON_THE_LEFT) { + ++bandWidthExCoef0; + } + + if (tile->tileFlag & E_HAS_TILES_ON_THE_BOTTOM) { + bandHeightExCoef0 = colExCoef[0]; + bandHeightExCoef1 = colExCoef[1]; + } + + if (tile->tileFlag & E_HAS_TILES_ON_THE_TOP) { + ++bandHeightExCoef0; + } + + band[0].width = bandWidth + bandWidthExCoef0 - widthOddPixel; + band[0].height = bandHeight + bandHeightExCoef0 - heightOddPixel; + + band[-1].width = bandWidth + bandWidthExCoef1; + band[-1].height = bandHeight + bandHeightExCoef0 - heightOddPixel; + + band[-2].width = bandWidth + bandWidthExCoef0 - widthOddPixel; + band[-2].height = bandHeight + bandHeightExCoef1; + + rowExCoef += 4; + colExCoef += 4; + band -= 3; + } + + bandWidthExCoef = 0; + bandHeightExCoef = 0; + + if (tile->tileFlag & E_HAS_TILES_ON_THE_RIGHT) { + bandWidthExCoef = exCoefNumTbl[0x60 * (img->levels - 1) + 12 * (tile->width & 7) + 4 * (img->levels - 1) + 1]; + } + + if (tile->tileFlag & E_HAS_TILES_ON_THE_BOTTOM) { + bandHeightExCoef = exCoefNumTbl[0x60 * (img->levels - 1) + 12 * (tile->height & 7) + 4 * (img->levels - 1) + 1]; + } + } + + band->width = bandWidthExCoef + bandWidth; + band->height = bandHeightExCoef + bandHeight; + + if (!img->subbandCount) { + return true; + } + + std::int32_t subbandOffset = 0; + band = comp->subBands; + + for (unsigned int curSubband = 0; curSubband < img->subbandCount; curSubband++, band++) { + if (*mdatSize < 0xC) { + return false; + } + + if (sgetn(2, *subbandMdatPtr) != 0xFF03) { + return false; + } + + const std::uint32_t bitData = sgetn(4, *subbandMdatPtr + 8); + const std::uint32_t subbandSize = sgetn(4, *subbandMdatPtr + 4); + + if (curSubband != bitData >> 28) { + band->dataSize = subbandSize; + return false; + } + + band->dataSize = subbandSize - (bitData & 0x7FF); + band->supportsPartial = bitData & 0x8000; + band->dataOffset = subbandOffset; + band->quantValue = (bitData >> 19) & 0xFF; + band->paramK = 0; + band->bandParam = nullptr; + band->bandBuf = nullptr; + band->bandSize = 0; + + subbandOffset += subbandSize; + + *subbandMdatPtr += 0xC; + *mdatSize -= 0xC; + } + + return true; +} + +bool crxReadImageHeaders( + crx_data_header_t* hdr, + CrxImage* img, + std::uint8_t* mdatPtr, + std::uint32_t mdatSize +) +{ + const unsigned int nTiles = img->tileRows * img->tileCols; + + if (!nTiles) { + return false; + } + + if (!img->tiles) { + img->tiles = static_cast( + malloc( + sizeof(CrxTile) * nTiles + + sizeof(CrxPlaneComp) * nTiles * img->nPlanes + + sizeof(CrxSubband) * nTiles * img->nPlanes * img->subbandCount + ) + ); + + if (!img->tiles) { + return false; + } + + // memory areas in allocated chunk + CrxTile* tile = img->tiles; + CrxPlaneComp* const comps = reinterpret_cast(tile + nTiles); + CrxSubband* const bands = reinterpret_cast(comps + img->nPlanes * nTiles); + + for (unsigned int curTile = 0; curTile < nTiles; curTile++, tile++) { + tile->tileFlag = 0; // tile neighbouring flags + tile->tileNumber = curTile; + tile->tileSize = 0; + tile->comps = comps + curTile * img->nPlanes; + + if ((curTile + 1) % img->tileCols) { + // not the last tile in a tile row + tile->width = hdr->tileWidth; + + if (img->tileCols > 1) { + tile->tileFlag = E_HAS_TILES_ON_THE_RIGHT; + + if (curTile % img->tileCols) { + // not the first tile in tile row + tile->tileFlag |= E_HAS_TILES_ON_THE_LEFT; + } + } + } else { + // last tile in a tile row + tile->width = img->planeWidth - hdr->tileWidth * (img->tileCols - 1); + + if (img->tileCols > 1) { + tile->tileFlag = E_HAS_TILES_ON_THE_LEFT; + } + } + + if (curTile < nTiles - img->tileCols) { + // in first tile row + tile->height = hdr->tileHeight; + + if (img->tileRows > 1) { + tile->tileFlag |= E_HAS_TILES_ON_THE_BOTTOM; + + if (curTile >= img->tileCols) { + tile->tileFlag |= E_HAS_TILES_ON_THE_TOP; + } + } + } else { + // non first tile row + tile->height = img->planeHeight - hdr->tileHeight * (img->tileRows - 1); + + if (img->tileRows > 1) { + tile->tileFlag |= E_HAS_TILES_ON_THE_TOP; + } + } + + if (img->nPlanes) { + CrxPlaneComp* comp = tile->comps; + CrxSubband* band = bands + curTile * img->nPlanes * img->subbandCount; + + for (int curComp = 0; curComp < img->nPlanes; curComp++, comp++) { + comp->compNumber = curComp; + comp->supportsPartial = true; + comp->tileFlag = tile->tileFlag; + comp->subBands = band; + comp->compBuf = nullptr; + comp->waveletTransform = nullptr; + + if (img->subbandCount) { + for (int curBand = 0; curBand < img->subbandCount; curBand++, band++) { + band->supportsPartial = false; + band->quantValue = 4; + band->bandParam = nullptr; + band->dataSize = 0; + } + } + } + } + } + } + + std::uint32_t tileOffset = 0; + std::uint32_t dataSize = mdatSize; + std::uint8_t* dataPtr = mdatPtr; + CrxTile* tile = img->tiles; + + for (unsigned int curTile = 0; curTile < nTiles; curTile++, tile++) { + if (dataSize < 0xC) { + return false; + } + + if (sgetn(2, dataPtr) != 0xFF01) { + return false; + } + + if (sgetn(2, dataPtr + 8) != curTile) { + return false; + } + + dataSize -= 0xC; + + tile->tileSize = sgetn(4, dataPtr + 4); + tile->dataOffset = tileOffset; + + const std::int32_t hdrExtraBytes = sgetn(2, dataPtr + 2) - 8; + tileOffset += tile->tileSize; + dataPtr += hdrExtraBytes + 0xC; + dataSize -= hdrExtraBytes; + + std::uint32_t compOffset = 0; + CrxPlaneComp* comp = tile->comps; + + for (int compNum = 0; compNum < img->nPlanes; compNum++, comp++) { + if (dataSize < 0xC) { + return false; + } + + if (sgetn(2, dataPtr) != 0xFF02) { + return false; + } + + if (compNum != dataPtr[8] >> 4) { + return false; + } + + comp->compSize = sgetn(4, dataPtr + 4); + + std::int32_t compHdrRoundedBits = (dataPtr[8] >> 1) & 3; + comp->supportsPartial = (dataPtr[8] & 8) != 0; + + comp->dataOffset = compOffset; + comp->tileFlag = tile->tileFlag; + + compOffset += comp->compSize; + dataSize -= 0xC; + dataPtr += 0xC; + + comp->roundedBitsMask = 0; + + if (compHdrRoundedBits) { + if (img->levels || !comp->supportsPartial) { + return false; + } + + comp->roundedBitsMask = 1 << (compHdrRoundedBits - 1); + } + + if (!crxReadSubbandHeaders(img, tile, comp, &dataPtr, &dataSize)) { + return false; + } + } + } + + return true; +} + +bool crxSetupImageData( + crx_data_header_t* hdr, + CrxImage* img, + std::int16_t* outBuf, + std::uint64_t mdatOffset, + std::uint32_t mdatSize, + std::uint8_t* mdatHdrPtr +) +{ + constexpr bool IncrBitTable[32] = { + false, false, false, false, false, false, false, false, false, true, true, false, false, false, true, false, + false, false, true, false, false, true, true, true, false, true, true, true, false, false, false, false + }; + + img->planeWidth = hdr->f_width; + img->planeHeight = hdr->f_height; + + if ( + hdr->tileWidth < 0x16 + || hdr->tileHeight < 0x16 + || img->planeWidth > 0x7FFF + || img->planeHeight > 0x7FFF + ) { + return false; + } + + img->tileCols = (img->planeWidth + hdr->tileWidth - 1) / hdr->tileWidth; + img->tileRows = (img->planeHeight + hdr->tileHeight - 1) / hdr->tileHeight; + + if (img->planeWidth - hdr->tileWidth * (img->tileCols - 1) < 0x16 || img->planeHeight - hdr->tileHeight * (img->tileRows - 1) < 0x16) { + return false; + } + + img->tiles = nullptr; + img->levels = hdr->imageLevels; + img->subbandCount = 3 * img->levels + 1; // 3 bands per level + one last LL + img->nPlanes = hdr->nPlanes; + img->nBits = hdr->nBits; + img->encType = hdr->encType; + img->samplePrecision = hdr->nBits + IncrBitTable[4 * hdr->encType + 2] + 1; + img->mdatOffset = mdatOffset + hdr->mdatHdrSize; + img->mdatSize = mdatSize; + img->planeBuf = nullptr; + img->outBufs[0] = img->outBufs[1] = img->outBufs[2] = img->outBufs[3] = nullptr; + + // The encoding type 3 needs all 4 planes to be decoded to generate row of + // RGGB values. It seems to be using some other colour space for raw encoding + // It is a massive buffer so ideallly it will need a different approach: + // decode planes line by line and convert single line then without + // intermediate plane buffer. At the moment though it's too many changes so + // left as is. + if (img->encType == 3 && img->nPlanes == 4 && img->nBits > 8) { + img->planeBuf = static_cast( + malloc(img->planeHeight * img->planeWidth * img->nPlanes * ((img->samplePrecision + 7) >> 3)) + ); + + if (!img->planeBuf) { + return false; + } + } + + const std::int32_t rowSize = 2 * img->planeWidth; + + if (img->nPlanes == 1) { + img->outBufs[0] = outBuf; + } else { + switch (hdr->cfaLayout) { + case 0: { + // R G + // G B + img->outBufs[0] = outBuf; + img->outBufs[1] = outBuf + 1; + img->outBufs[2] = outBuf + rowSize; + img->outBufs[3] = img->outBufs[2] + 1; + break; + } + + case 1: { + // G R + // B G + img->outBufs[1] = outBuf; + img->outBufs[0] = outBuf + 1; + img->outBufs[3] = outBuf + rowSize; + img->outBufs[2] = img->outBufs[3] + 1; + break; + } + + case 2: { + // G B + // R G + img->outBufs[2] = outBuf; + img->outBufs[3] = outBuf + 1; + img->outBufs[0] = outBuf + rowSize; + img->outBufs[1] = img->outBufs[0] + 1; + break; + } + + case 3: { + // B G + // G R + img->outBufs[3] = outBuf; + img->outBufs[2] = outBuf + 1; + img->outBufs[1] = outBuf + rowSize; + img->outBufs[0] = img->outBufs[1] + 1; + break; + } + } + } + + // read header + return crxReadImageHeaders(hdr, img, mdatHdrPtr, mdatSize); +} + +void crxFreeImageData(CrxImage* img) +{ + CrxTile* tile = img->tiles; + const int nTiles = img->tileRows * img->tileCols; + + if (img->tiles) { + for (std::int32_t curTile = 0; curTile < nTiles; curTile++, tile++) { + if (tile[curTile].comps) { + for (std::int32_t curPlane = 0; curPlane < img->nPlanes; ++curPlane) { + crxFreeSubbandData(img, tile[curTile].comps + curPlane); + } + } + } + + free(img->tiles); + img->tiles = nullptr; + } + + if (img->planeBuf) { + free(img->planeBuf); + img->planeBuf = nullptr; + } +} + +} // namespace + +void DCraw::crxLoadDecodeLoop(void* img, int nPlanes) +{ +#ifdef _OPENMP + bool results[4]; // nPlanes is always <= 4 + #pragma omp parallel for + + for (std::int32_t plane = 0; plane < nPlanes; ++plane) { + results[plane] = crxDecodePlane(img, plane); + } + + for (std::int32_t plane = 0; plane < nPlanes; ++plane) { + if (!results[plane]) { + derror(); + } + } + +#else + + for (std::int32_t plane = 0; plane < nPlanes; ++plane) { + if (!crxDecodePlane(img, plane)) { + derror(); + } + } + +#endif +} + +void DCraw::crxConvertPlaneLineDf(void* p, int imageRow) +{ + crxConvertPlaneLine(static_cast(p), imageRow); +} + +void DCraw::crxLoadFinalizeLoopE3(void* p, int planeHeight) +{ +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < planeHeight; ++i) { + crxConvertPlaneLineDf(p, i); + } +} + +void DCraw::crxLoadRaw() +{ + CrxImage img; + + if (RT_canon_CR3_data.crx_track_selected >= RT_canon_CR3_data.CRXTRACKS_MAXCOUNT) { + derror(); + } + + crx_data_header_t hdr = RT_canon_CR3_data.crx_header[RT_canon_CR3_data.crx_track_selected]; + + LibRaw_abstract_datastream input = {ifp}; + img.input = &input; // libraw_internal_data.internal_data.input; + + // update sizes for the planes + if (hdr.nPlanes == 4) { + hdr.f_width >>= 1; + hdr.f_height >>= 1; + hdr.tileWidth >>= 1; + hdr.tileHeight >>= 1; + } + +// /*imgdata.color.*/maximum = (1 << hdr.nBits) - 1; + + std::uint8_t* const hdrBuf = static_cast(malloc(hdr.mdatHdrSize)); + + // read image header +#ifdef _OPENMP + #pragma omp critical +#endif + { +#ifndef _OPENMP + /*libraw_internal_data.internal_data.input->*/ input.lock(); +#endif + /*libraw_internal_data.internal_data.input->*/ input.seek(data_offset, SEEK_SET); + /*libraw_internal_data.internal_data.input->*/ input.read(hdrBuf, 1, hdr.mdatHdrSize); +#ifndef _OPENMP + /*libraw_internal_data.internal_data.input->*/ input.unlock(); +#endif + } + + // parse and setup the image data + if (!crxSetupImageData(&hdr, &img, reinterpret_cast(raw_image), hdr.MediaOffset /*data_offset*/, hdr.MediaSize /*RT_canon_CR3_data.data_size*/, hdrBuf)) { + derror(); + } + + free(hdrBuf); + + crxLoadDecodeLoop(&img, hdr.nPlanes); + + if (img.encType == 3) { + crxLoadFinalizeLoopE3(&img, img.planeHeight); + } + + crxFreeImageData(&img); +} + +bool DCraw::crxParseImageHeader(uchar* cmp1TagData, unsigned int nTrack) +{ + if (nTrack >= RT_canon_CR3_data.CRXTRACKS_MAXCOUNT) { + return false; + } + + if (!cmp1TagData) { + return false; + } + + crx_data_header_t* const hdr = &RT_canon_CR3_data.crx_header[nTrack]; + + hdr->version = sgetn(2, cmp1TagData + 4); + hdr->f_width = sgetn(4, cmp1TagData + 8); + hdr->f_height = sgetn(4, cmp1TagData + 12); + hdr->tileWidth = sgetn(4, cmp1TagData + 16); + hdr->tileHeight = sgetn(4, cmp1TagData + 20); + hdr->nBits = cmp1TagData[24]; + hdr->nPlanes = cmp1TagData[25] >> 4; + hdr->cfaLayout = cmp1TagData[25] & 0xF; + hdr->encType = cmp1TagData[26] >> 4; + hdr->imageLevels = cmp1TagData[26] & 0xF; + hdr->hasTileCols = cmp1TagData[27] >> 7; + hdr->hasTileRows = (cmp1TagData[27] >> 6) & 1; + hdr->mdatHdrSize = sgetn(4, cmp1TagData + 28); + + // validation + if (hdr->version != 0x100 || !hdr->mdatHdrSize) { + return false; + } + + if (hdr->encType == 1) { + if (hdr->nBits > 15) { + return false; + } + } else { + if (hdr->encType && hdr->encType != 3) { + return false; + } + + if (hdr->nBits > 14) { + return false; + } + } + + if (hdr->nPlanes == 1) { + if (hdr->cfaLayout || hdr->encType) { + return false; + } + + if (hdr->nBits != 8) { + return false; + } + } else if ( + hdr->nPlanes != 4 + || (hdr->f_width & 1) + || (hdr->f_height & 1) + || (hdr->tileWidth & 1) + || (hdr->tileHeight & 1) + || hdr->cfaLayout > 3 + || ( + hdr->encType + && hdr->encType != 1 + && hdr->encType != 3 + ) + || hdr->nBits == 8 + ) { + return false; + } + + if (hdr->tileWidth > hdr->f_width || hdr->tileHeight > hdr->f_height) { + return false; + } + + if (hdr->imageLevels > 3 || hdr->hasTileCols > 1 || hdr->hasTileRows > 1) { + return false; + } + + return true; +} diff --git a/rtengine/capturesharpening.cc b/rtengine/capturesharpening.cc new file mode 100644 index 000000000..9b60694f2 --- /dev/null +++ b/rtengine/capturesharpening.cc @@ -0,0 +1,1190 @@ +/* + * 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 "rawimage.h" +#include "rawimagesource.h" +#include "rt_math.h" +#include "procparams.h" +#include "color.h" +#include "rt_algo.h" +//#define BENCHMARK +#include "StopWatch.h" +#include "opthelper.h" +#include "../rtgui/multilangmgr.h" + +namespace { + +void compute13x13kernel(float sigma, float kernel[13][13]) { + + const double temp = -2.f * rtengine::SQR(sigma); + float sum = 0.f; + for (int i = -6; i <= 6; ++i) { + for (int j = -6; j <= 6; ++j) { + if((rtengine::SQR(i) + rtengine::SQR(j)) <= rtengine::SQR(3.0 * 2.0)) { + kernel[i + 6][j + 6] = std::exp((rtengine::SQR(i) + rtengine::SQR(j)) / temp); + sum += kernel[i + 6][j + 6]; + } else { + kernel[i + 6][j + 6] = 0.f; + } + } + } + + for (int i = 0; i < 13; ++i) { + for (int j = 0; j < 13; ++j) { + kernel[i][j] /= sum; + } + } +} + +void compute9x9kernel(float sigma, float kernel[9][9]) { + + const double temp = -2.f * rtengine::SQR(sigma); + float sum = 0.f; + for (int i = -4; i <= 4; ++i) { + for (int j = -4; j <= 4; ++j) { + if((rtengine::SQR(i) + rtengine::SQR(j)) <= rtengine::SQR(3.0 * 1.5)) { + kernel[i + 4][j + 4] = std::exp((rtengine::SQR(i) + rtengine::SQR(j)) / temp); + sum += kernel[i + 4][j + 4]; + } else { + kernel[i + 4][j + 4] = 0.f; + } + } + } + + for (int i = 0; i < 9; ++i) { + for (int j = 0; j < 9; ++j) { + kernel[i][j] /= sum; + } + } +} + +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; + } + } +} + +void gauss3x3div (float** RESTRICT src, float** RESTRICT dst, float** RESTRICT divBuffer, const int tileSize, 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 < tileSize - 1; i++) { +#if defined(__clang__) + #pragma clang loop vectorize(assume_safety) +#elif defined(__GNUC__) + #pragma GCC ivdep +#endif + for (int j = 1; j < tileSize - 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); + } + } +} + +void gauss5x5div (float** RESTRICT src, float** RESTRICT dst, float** RESTRICT divBuffer, const int tileSize, 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 < tileSize - 2; ++i) { + // I tried hand written SSE code but gcc vectorizes better +#if defined(__clang__) + #pragma clang loop vectorize(assume_safety) +#elif defined(__GNUC__) + #pragma GCC ivdep +#endif + for (int j = 2; j < tileSize - 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); + } + } +} + +void gauss7x7div(float** RESTRICT src, float** RESTRICT dst, float** RESTRICT divBuffer, const int tileSize, 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 < tileSize - 3; ++i) { + // I tried hand written SSE code but gcc vectorizes better +#if defined(__clang__) + #pragma clang loop vectorize(assume_safety) +#elif defined(__GNUC__) + #pragma GCC ivdep +#endif + for (int j = 3; j < tileSize - 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]) + (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); + } + } +} + +void gauss9x9div(float** RESTRICT src, float** RESTRICT dst, float** RESTRICT divBuffer, const int tileSize, const float kernel[9][9]) +{ + + const float c42 = kernel[0][2]; + const float c41 = kernel[0][3]; + const float c40 = kernel[0][4]; + const float c33 = kernel[1][1]; + const float c32 = kernel[1][2]; + const float c31 = kernel[1][3]; + const float c30 = kernel[1][4]; + const float c22 = kernel[2][2]; + const float c21 = kernel[2][3]; + const float c20 = kernel[2][4]; + const float c11 = kernel[3][3]; + const float c10 = kernel[3][4]; + const float c00 = kernel[4][4]; + + for (int i = 4; i < tileSize - 4; ++i) { + // I tried hand written SSE code but gcc vectorizes better +#if defined(__clang__) + #pragma clang loop vectorize(assume_safety) +#elif defined(__GNUC__) + #pragma GCC ivdep +#endif + for (int j = 4; j < tileSize - 4; ++j) { + const float val = c42 * ((src[i - 4][j - 2] + src[i - 4][j + 2]) + (src[i - 2][j - 4] + src[i - 2][j + 4]) + (src[i + 2][j - 4] + src[i + 2][j + 4]) + (src[i + 4][j - 2] + src[i + 4][j + 2])) + + c41 * ((src[i - 4][j - 1] + src[i - 4][j + 1]) + (src[i - 1][j - 4] + src[i - 1][j + 4]) + (src[i + 1][j - 4] + src[i + 1][j + 4]) + (src[i + 4][j - 1] + src[i + 4][j + 1])) + + c40 * (src[i - 4][j] + src[i][j - 4] + src[i][j + 4] + src[i + 4][j]) + + c33 * (src[i - 3][j - 3] + src[i - 3][j + 3] + src[i + 3][j - 3] + src[i + 3][j + 3]) + + c32 * ((src[i - 3][j - 2] + src[i - 3][j + 2]) + (src[i - 2][j - 3] + src[i - 2][j + 3]) + (src[i + 2][j - 3] + src[i + 2][j + 3]) + (src[i + 3][j - 2] + src[i + 3][j + 2])) + + 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]) + (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); + } + } +} + +void gauss13x13div(float** RESTRICT src, float** RESTRICT dst, float** RESTRICT divBuffer, const int tileSize, const float kernel[13][13]) +{ + const float c60 = kernel[0][6]; + const float c53 = kernel[1][3]; + const float c52 = kernel[1][4]; + const float c51 = kernel[1][5]; + const float c50 = kernel[1][6]; + const float c44 = kernel[2][2]; + const float c42 = kernel[2][4]; + const float c41 = kernel[2][5]; + const float c40 = kernel[2][6]; + const float c33 = kernel[3][3]; + const float c32 = kernel[3][4]; + const float c31 = kernel[3][5]; + const float c30 = kernel[3][6]; + const float c22 = kernel[4][4]; + const float c21 = kernel[4][5]; + const float c20 = kernel[4][6]; + const float c11 = kernel[5][5]; + const float c10 = kernel[5][6]; + const float c00 = kernel[6][6]; + + for (int i = 6; i < tileSize - 6; ++i) { + // I tried hand written SSE code but gcc vectorizes better +#if defined(__clang__) + #pragma clang loop vectorize(assume_safety) +#elif defined(__GNUC__) + #pragma GCC ivdep +#endif + for (int j = 6; j < tileSize - 6; ++j) { + const float val = c60 * (src[i - 6][j] + src[i][j - 6] + src[i][j + 6] + src[i + 6][j]) + + c53 * ((src[i - 5][j - 3] + src[i - 5][j + 3]) + (src[i - 3][j - 5] + src[i - 3][j + 5]) + (src[i + 3][j - 5] + src[i + 3][j + 5]) + (src[i + 5][j - 3] + src[i + 5][j + 3])) + + c52 * ((src[i - 5][j - 2] + src[i - 5][j + 2]) + (src[i - 2][j - 5] + src[i - 2][j + 5]) + (src[i + 2][j - 5] + src[i + 2][j + 5]) + (src[i + 5][j - 2] + src[i + 5][j + 2])) + + c51 * ((src[i - 5][j - 1] + src[i - 5][j + 1]) + (src[i - 1][j - 5] + src[i - 1][j + 5]) + (src[i + 1][j - 5] + src[i + 1][j + 5]) + (src[i + 5][j - 1] + src[i + 5][j + 1])) + + c50 * ((src[i - 5][j] + src[i][j - 5] + src[i][j + 5] + src[i + 5][j]) + ((src[i - 4][j - 3] + src[i - 4][j + 3]) + (src[i - 3][j - 4] + src[i - 3][j + 4]) + (src[i + 3][j - 4] + src[i + 3][j + 4]) + (src[i + 4][j - 3] + src[i + 4][j + 3]))) + + c44 * (src[i - 4][j - 4] + src[i - 4][j + 4] + src[i + 4][j - 4] + src[i + 4][j + 4]) + + c42 * ((src[i - 4][j - 2] + src[i - 4][j + 2]) + (src[i - 2][j - 4] + src[i - 2][j + 4]) + (src[i + 2][j - 4] + src[i + 2][j + 4]) + (src[i + 4][j - 2] + src[i + 4][j + 2])) + + c41 * ((src[i - 4][j - 1] + src[i - 4][j + 1]) + (src[i - 1][j - 4] + src[i - 1][j + 4]) + (src[i + 1][j - 4] + src[i + 1][j + 4]) + (src[i + 4][j - 1] + src[i + 4][j + 1])) + + c40 * (src[i - 4][j] + src[i][j - 4] + src[i][j + 4] + src[i + 4][j]) + + c33 * (src[i - 3][j - 3] + src[i - 3][j + 3] + src[i + 3][j - 3] + src[i + 3][j + 3]) + + c32 * ((src[i - 3][j - 2] + src[i - 3][j + 2]) + (src[i - 2][j - 3] + src[i - 2][j + 3]) + (src[i + 2][j - 3] + src[i + 2][j + 3]) + (src[i + 3][j - 2] + src[i + 3][j + 2])) + + 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]) + (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); + } + } +} + +void gauss3x3mult(float** RESTRICT src, float** RESTRICT dst, const int tileSize, 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 < tileSize - 1; i++) { +#if defined(__clang__) + #pragma clang loop vectorize(assume_safety) +#elif defined(__GNUC__) + #pragma GCC ivdep +#endif + for (int j = 1; j < tileSize - 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; + } + } + +} + +void gauss5x5mult (float** RESTRICT src, float** RESTRICT dst, const int tileSize, 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 < tileSize - 2; ++i) { + // I tried hand written SSE code but gcc vectorizes better +#if defined(__clang__) + #pragma clang loop vectorize(assume_safety) +#elif defined(__GNUC__) + #pragma GCC ivdep +#endif + for (int j = 2; j < tileSize - 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; + } + } +} + +void gauss7x7mult(float** RESTRICT src, float** RESTRICT dst, const int tileSize, 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 < tileSize - 3; ++i) { + // I tried hand written SSE code but gcc vectorizes better +#if defined(__clang__) + #pragma clang loop vectorize(assume_safety) +#elif defined(__GNUC__) + #pragma GCC ivdep +#endif + for (int j = 3; j < tileSize - 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]) + (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 gauss9x9mult(float** RESTRICT src, float** RESTRICT dst, const int tileSize, const float kernel[9][9]) +{ + + const float c42 = kernel[0][2]; + const float c41 = kernel[0][3]; + const float c40 = kernel[0][4]; + const float c33 = kernel[1][1]; + const float c32 = kernel[1][2]; + const float c31 = kernel[1][3]; + const float c30 = kernel[1][4]; + const float c22 = kernel[2][2]; + const float c21 = kernel[2][3]; + const float c20 = kernel[2][4]; + const float c11 = kernel[3][3]; + const float c10 = kernel[3][4]; + const float c00 = kernel[4][4]; + + for (int i = 4; i < tileSize - 4; ++i) { + // I tried hand written SSE code but gcc vectorizes better +#if defined(__clang__) + #pragma clang loop vectorize(assume_safety) +#elif defined(__GNUC__) + #pragma GCC ivdep +#endif + for (int j = 4; j < tileSize - 4; ++j) { + const float val = c42 * ((src[i - 4][j - 2] + src[i - 4][j + 2]) + (src[i - 2][j - 4] + src[i - 2][j + 4]) + (src[i + 2][j - 4] + src[i + 2][j + 4]) + (src[i + 4][j - 2] + src[i + 4][j + 2])) + + c41 * ((src[i - 4][j - 1] + src[i - 4][j + 1]) + (src[i - 1][j - 4] + src[i - 1][j + 4]) + (src[i + 1][j - 4] + src[i + 1][j + 4]) + (src[i + 4][j - 1] + src[i + 4][j + 1])) + + c40 * (src[i - 4][j] + src[i][j - 4] + src[i][j + 4] + src[i + 4][j]) + + c33 * (src[i - 3][j - 3] + src[i - 3][j + 3] + src[i + 3][j - 3] + src[i + 3][j + 3]) + + c32 * ((src[i - 3][j - 2] + src[i - 3][j + 2]) + (src[i - 2][j - 3] + src[i - 2][j + 3]) + (src[i + 2][j - 3] + src[i + 2][j + 3]) + (src[i + 3][j - 2] + src[i + 3][j + 2])) + + 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]) + (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 gauss13x13mult(float** RESTRICT src, float** RESTRICT dst, const int tileSize, const float kernel[13][13]) +{ + + const float c60 = kernel[0][6]; + const float c53 = kernel[1][3]; + const float c52 = kernel[1][4]; + const float c51 = kernel[1][5]; + const float c50 = kernel[1][6]; + const float c44 = kernel[2][2]; + const float c42 = kernel[2][4]; + const float c41 = kernel[2][5]; + const float c40 = kernel[2][6]; + const float c33 = kernel[3][3]; + const float c32 = kernel[3][4]; + const float c31 = kernel[3][5]; + const float c30 = kernel[3][6]; + const float c22 = kernel[4][4]; + const float c21 = kernel[4][5]; + const float c20 = kernel[4][6]; + const float c11 = kernel[5][5]; + const float c10 = kernel[5][6]; + const float c00 = kernel[6][6]; + + for (int i = 6; i < tileSize - 6; ++i) { + // I tried hand written SSE code but gcc vectorizes better +#if defined(__clang__) + #pragma clang loop vectorize(assume_safety) +#elif defined(__GNUC__) + #pragma GCC ivdep +#endif + for (int j = 6; j < tileSize - 6; ++j) { + const float val = c60 * (src[i - 6][j] + src[i][j - 6] + src[i][j + 6] + src[i + 6][j]) + + c53 * ((src[i - 5][j - 3] + src[i - 5][j + 3]) + (src[i - 3][j - 5] + src[i - 3][j + 5]) + (src[i + 3][j - 5] + src[i + 3][j + 5]) + (src[i + 5][j - 3] + src[i + 5][j + 3])) + + c52 * ((src[i - 5][j - 2] + src[i - 5][j + 2]) + (src[i - 2][j - 5] + src[i - 2][j + 5]) + (src[i + 2][j - 5] + src[i + 2][j + 5]) + (src[i + 5][j - 2] + src[i + 5][j + 2])) + + c51 * ((src[i - 5][j - 1] + src[i - 5][j + 1]) + (src[i - 1][j - 5] + src[i - 1][j + 5]) + (src[i + 1][j - 5] + src[i + 1][j + 5]) + (src[i + 5][j - 1] + src[i + 5][j + 1])) + + c50 * ((src[i - 5][j] + src[i][j - 5] + src[i][j + 5] + src[i + 5][j]) + ((src[i - 4][j - 3] + src[i - 4][j + 3]) + (src[i - 3][j - 4] + src[i - 3][j + 4]) + (src[i + 3][j - 4] + src[i + 3][j + 4]) + (src[i + 4][j - 3] + src[i + 4][j + 3]))) + + c44 * (src[i - 4][j - 4] + src[i - 4][j + 4] + src[i + 4][j - 4] + src[i + 4][j + 4]) + + c42 * ((src[i - 4][j - 2] + src[i - 4][j + 2]) + (src[i - 2][j - 4] + src[i - 2][j + 4]) + (src[i + 2][j - 4] + src[i + 2][j + 4]) + (src[i + 4][j - 2] + src[i + 4][j + 2])) + + c41 * ((src[i - 4][j - 1] + src[i - 4][j + 1]) + (src[i - 1][j - 4] + src[i - 1][j + 4]) + (src[i + 1][j - 4] + src[i + 1][j + 4]) + (src[i + 4][j - 1] + src[i + 4][j + 1])) + + c40 * (src[i - 4][j] + src[i][j - 4] + src[i][j + 4] + src[i + 4][j]) + + c33 * (src[i - 3][j - 3] + src[i - 3][j + 3] + src[i + 3][j - 3] + src[i + 3][j + 3]) + + c32 * ((src[i - 3][j - 2] + src[i - 3][j + 2]) + (src[i - 2][j - 3] + src[i - 2][j + 3]) + (src[i + 2][j - 3] + src[i + 2][j + 3]) + (src[i + 3][j - 2] + src[i + 3][j + 2])) + + 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]) + (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 + 2; row < H - 4; row += 3) { + for (int col = startx + 2; col < W - 4; col += 3) { + const float valp1p1 = rawData[row + 1][col + 1]; + const bool squareClipped = rtengine::max(valp1p1, rawData[row + 1][col + 2], rawData[row + 2][col + 1], rawData[row + 2][col + 2]) >= upperLimit; + const float greenSolitary = rawData[row][col]; + if (greenSolitary > 1.f && std::max(rawData[row - 1][col - 1], rawData[row - 1][col + 1]) < upperLimit) { + if (greenSolitary < upperLimit) { + const float valp1m1 = rawData[row + 1][col - 1]; + if (valp1m1 > 1.f && rtengine::max(rawData[row + 1][col - 2], valp1m1, rawData[row + 2][col - 2], rawData[row + 1][col - 1]) < upperLimit) { + const float maxVal = std::max(greenSolitary, valp1m1); + if (maxVal > lowerLimit) { + const float minVal = std::min(greenSolitary, valp1m1); + if (UNLIKELY(maxVal > maxRatio * minVal)) { + maxRatio = maxVal / minVal; + } + } + } + if (valp1p1 > 1.f && !squareClipped) { + const float maxVal = std::max(greenSolitary, valp1p1); + if (maxVal > lowerLimit) { + const float minVal = std::min(greenSolitary, valp1p1); + if (UNLIKELY(maxVal > maxRatio * minVal)) { + maxRatio = maxVal / minVal; + } + } + } + } + } + if (!squareClipped) { + const float valp2p2 = rawData[row + 2][col + 2]; + if (valp2p2 > 1.f) { + if (valp1p1 > 1.f) { + const float maxVal = std::max(valp1p1, valp2p2); + if (maxVal > lowerLimit) { + const float minVal = std::min(valp1p1, valp2p2); + if (UNLIKELY(maxVal > maxRatio * minVal)) { + maxRatio = maxVal / minVal; + } + } + } + const float greenSolitaryRight = rawData[row + 3][col + 3]; + if (rtengine::max(greenSolitaryRight, rawData[row + 4][col + 2], rawData[row + 4][col + 4]) < upperLimit) { + if (greenSolitaryRight > 1.f) { + const float maxVal = std::max(greenSolitaryRight, valp2p2); + if (maxVal > lowerLimit) { + const float minVal = std::min(greenSolitaryRight, valp2p2); + if (UNLIKELY(maxVal > maxRatio * minVal)) { + maxRatio = maxVal / minVal; + } + } + } + } + } + const float valp1p2 = rawData[row + 1][col + 2]; + const float valp2p1 = rawData[row + 2][col + 1]; + if (valp2p1 > 1.f) { + if (valp1p2 > 1.f) { + const float maxVal = std::max(valp1p2, valp2p1); + if (maxVal > lowerLimit) { + const float minVal = std::min(valp1p2, valp2p1); + if (UNLIKELY(maxVal > maxRatio * minVal)) { + maxRatio = maxVal / minVal; + } + } + } + const float greenSolitaryLeft = rawData[row + 3][col]; + if (rtengine::max(greenSolitaryLeft, rawData[row + 4][col - 1], rawData[row + 4][col + 1]) < upperLimit) { + if (greenSolitaryLeft > 1.f) { + const float maxVal = std::max(greenSolitaryLeft, valp2p1); + if (maxVal > lowerLimit) { + const float minVal = std::min(greenSolitaryLeft, valp2p1); + if (UNLIKELY(maxVal > maxRatio * minVal)) { + maxRatio = maxVal / minVal; + } + } + } + } + } + } + } + } + return std::sqrt((1.f / (std::log(1.f / maxRatio) / 2.f)) / -2.f); +} + +bool checkForStop(float** tmpIThr, float** iterCheck, int fullTileSize, int border) +{ + for (int ii = border; ii < fullTileSize - border; ++ii) { +#ifdef __SSE2__ + for (int jj = border; jj < fullTileSize - border; jj += 4) { + if (UNLIKELY(_mm_movemask_ps((vfloat)vmaskf_lt(LVFU(tmpIThr[ii][jj]), LVFU(iterCheck[ii - border][jj - border]))))) { + return true; + } + } +#else + for (int jj = border; jj < fullTileSize - border; ++jj) { + if (tmpIThr[ii][jj] < iterCheck[ii - border][jj - border]) { + return true; + } + } +#endif + } + return false; +} + +void CaptureDeconvSharpening (float** luminance, const float* const * oldLuminance, const float * const * blend, int W, int H, double sigma, double sigmaCornerOffset, int iterations, bool checkIterStop, rtengine::ProgressListener* plistener, double startVal, double endVal) +{ +BENCHFUN + const bool is9x9 = (sigma <= 1.50 && sigmaCornerOffset == 0.0); + const bool is7x7 = (sigma <= 1.15 && sigmaCornerOffset == 0.0); + const bool is5x5 = (sigma <= 0.84 && sigmaCornerOffset == 0.0); + const bool is3x3 = (sigma < 0.6 && sigmaCornerOffset == 0.0); + float kernel13[13][13]; + float kernel9[9][9]; + float kernel7[7][7]; + float kernel5[5][5]; + float kernel3[3][3]; + if (is3x3) { + compute3x3kernel(sigma, kernel3); + } else if (is5x5) { + compute5x5kernel(sigma, kernel5); + } else if (is7x7) { + compute7x7kernel(sigma, kernel7); + } else if (is9x9) { + compute9x9kernel(sigma, kernel9); + } else { + compute13x13kernel(sigma, kernel13); + } + + constexpr int tileSize = 32; + const int border = (is3x3 || is5x5 || is7x7) ? iterations <= 30 ? 5 : 7 : 8; + const int fullTileSize = tileSize + 2 * border; + const float cornerRadius = std::min(2.f, sigma + sigmaCornerOffset); + const float cornerDistance = sqrt(rtengine::SQR(W * 0.5f) + rtengine::SQR(H * 0.5f)); + const float distanceFactor = (cornerRadius - sigma) / cornerDistance; + + double progress = startVal; + const double progressStep = (endVal - startVal) * rtengine::SQR(tileSize) / (W * H); + + constexpr float minBlend = 0.01f; + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + int progresscounter = 0; + array2D tmpIThr(fullTileSize, fullTileSize); + array2D tmpThr(fullTileSize, fullTileSize); + tmpThr.fill(1.f); + array2D lumThr(fullTileSize, fullTileSize); + array2D iterCheck(tileSize, tileSize); +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) collapse(2) +#endif + 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 + float maxVal = 0.f; + if (checkIterStop) { + for (int k = 0, ii = endOfCol ? H - fullTileSize + border : i; k < tileSize; ++k, ++ii) { + for (int l = 0, jj = endOfRow ? W - fullTileSize + border : j; l < tileSize; ++l, ++jj) { + iterCheck[k][l] = oldLuminance[ii][jj] * blend[ii][jj] * 0.5f; + maxVal = std::max(maxVal, blend[ii][jj]); + } + } + } else { + for (int k = 0, ii = endOfCol ? H - fullTileSize + border : i; k < tileSize; ++k, ++ii) { + for (int l = 0, jj = endOfRow ? W - fullTileSize + border : j; l < tileSize; ++l, ++jj) { + maxVal = std::max(maxVal, blend[ii][jj]); + } + } + } + if (maxVal < minBlend) { + // no pixel of the tile has a blend factor >= minBlend => skip the tile + continue; + } + for (int k = 0, ii = endOfCol ? H - fullTileSize : i - border; k < fullTileSize; ++k, ++ii) { + for (int l = 0, jj = endOfRow ? W - fullTileSize : j - border; l < fullTileSize; ++l, ++jj) { + tmpIThr[k][l] = oldLuminance[ii][jj]; + lumThr[k][l] = oldLuminance[ii][jj]; + } + } + } else { + float maxVal = 0.f; + if (checkIterStop) { + for (int ii = 0; ii < tileSize; ++ii) { + for (int jj = 0; jj < tileSize; ++jj) { + iterCheck[ii][jj] = oldLuminance[i + ii][j + jj] * blend[i + ii][j + jj] * 0.5f; + maxVal = std::max(maxVal, blend[i + ii][j + jj]); + } + } + } else { + for (int ii = 0; ii < tileSize; ++ii) { + for (int jj = 0; jj < tileSize; ++jj) { + maxVal = std::max(maxVal, blend[i + ii][j + jj]); + } + } + } + if (maxVal < minBlend) { + // no pixel of the tile has a blend factor >= minBlend => skip the tile + continue; + } + 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, kernel3); + gauss3x3mult(tmpThr, tmpIThr, fullTileSize, kernel3); + if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) { + break; + } + } + } 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, kernel5); + gauss5x5mult(tmpThr, tmpIThr, fullTileSize, kernel5); + if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) { + break; + } + } + } else if (is7x7) { + for (int k = 0; k < iterations; ++k) { + // apply 5x5 gaussian blur and divide luminance by result of gaussian blur + gauss7x7div(tmpIThr, tmpThr, lumThr, fullTileSize, kernel7); + gauss7x7mult(tmpThr, tmpIThr, fullTileSize, kernel7); + if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) { + break; + } + } + } else if (is9x9) { + for (int k = 0; k < iterations; ++k) { + // apply 5x5 gaussian blur and divide luminance by result of gaussian blur + gauss9x9div(tmpIThr, tmpThr, lumThr, fullTileSize, kernel9); + gauss9x9mult(tmpThr, tmpIThr, fullTileSize, kernel9); + if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) { + break; + } + } + } else { + if (sigmaCornerOffset != 0.0) { + const float distance = sqrt(rtengine::SQR(i + tileSize / 2 - H / 2) + rtengine::SQR(j + tileSize / 2 - W / 2)); + const float sigmaTile = static_cast(sigma) + distanceFactor * distance; + if (sigmaTile >= 0.4f) { + if (sigmaTile > 1.50) { // have to use 13x13 kernel + float lkernel13[13][13]; + compute13x13kernel(static_cast(sigma) + distanceFactor * distance, lkernel13); + for (int k = 0; k < iterations; ++k) { + // apply 13x13 gaussian blur and divide luminance by result of gaussian blur + gauss13x13div(tmpIThr, tmpThr, lumThr, fullTileSize, lkernel13); + gauss13x13mult(tmpThr, tmpIThr, fullTileSize, lkernel13); + if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) { + break; + } + } + } else if (sigmaTile > 1.15) { // have to use 9x9 kernel + float lkernel9[9][9]; + compute9x9kernel(static_cast(sigma) + distanceFactor * distance, lkernel9); + for (int k = 0; k < iterations; ++k) { + // apply 9x9 gaussian blur and divide luminance by result of gaussian blur + gauss9x9div(tmpIThr, tmpThr, lumThr, fullTileSize, lkernel9); + gauss9x9mult(tmpThr, tmpIThr, fullTileSize, lkernel9); + if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) { + break; + } + } + } else if (sigmaTile > 0.84) { // have to use 7x7 kernel + float lkernel7[7][7]; + compute7x7kernel(static_cast(sigma) + distanceFactor * distance, lkernel7); + for (int k = 0; k < iterations; ++k) { + // apply 7x7 gaussian blur and divide luminance by result of gaussian blur + gauss7x7div(tmpIThr, tmpThr, lumThr, fullTileSize, lkernel7); + gauss7x7mult(tmpThr, tmpIThr, fullTileSize, lkernel7); + if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) { + break; + } + } + } else { // can use 5x5 kernel + float lkernel5[5][5]; + compute5x5kernel(static_cast(sigma) + distanceFactor * distance, lkernel5); + for (int k = 0; k < iterations; ++k) { + // apply 7x7 gaussian blur and divide luminance by result of gaussian blur + gauss5x5div(tmpIThr, tmpThr, lumThr, fullTileSize, lkernel5); + gauss5x5mult(tmpThr, tmpIThr, fullTileSize, lkernel5); + if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) { + break; + } + } + } + } + } else { + for (int k = 0; k < iterations; ++k) { + // apply 13x13 gaussian blur and divide luminance by result of gaussian blur + gauss13x13div(tmpIThr, tmpThr, lumThr, fullTileSize, kernel13); + gauss13x13mult(tmpThr, tmpIThr, fullTileSize, kernel13); + if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) { + break; + } + } + } + } + if (endOfRow || endOfCol) { + // special handling for small tiles at end of row or column + for (int k = border, ii = endOfCol ? H - fullTileSize : i - border; k < fullTileSize - border; ++k) { + for (int l = border, jj = endOfRow ? W - fullTileSize : j - border; l < fullTileSize - border; ++l) { + luminance[ii + k][jj + l] = rtengine::intp(blend[ii + k][jj + l], tmpIThr[k][l], 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], tmpIThr[ii][jj], luminance[i + ii - border][j + jj - border]); + } + } + } + if (plistener) { + if (++progresscounter % 32 == 0) { +#ifdef _OPENMP + #pragma omp critical(csprogress) +#endif + { + progress += 32.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 (!(ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS || ri->get_colors() == 1)) { + return; + } + + if (plistener) { + plistener->setProgressStr(M("TP_PDSHARPENING_LABEL")); + plistener->setProgress(0.0); + } +BENCHFUN + + constexpr 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]; + + const array2D& redVals = redCache ? *redCache : red; + const array2D& greenVals = greenCache ? *greenCache : green; + const array2D& blueVals = blueCache ? *blueCache : blue; + + array2D clipMask(W, H); + constexpr float clipLimit = 0.95f; + constexpr float maxSigma = 2.f; + + if (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 = std::min(calcRadiusBayer(rawData, W, H, 1000.f, clipVal, fc), maxSigma); + } + } else if (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 = std::min(calcRadiusXtrans(rawData, W, H, 1000.f, clipVal, i, j), maxSigma); + } + + } 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 = std::min(calcRadiusBayer(rawData, W, H, 1000.f, clipVal, fc), maxSigma); + } + } + + if (std::isnan(radius)) { + return; + } + + 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); + } + + buildBlendMask(L, clipMask, W, H, contrast, 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] = clipMask[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; + +#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], W); + } + if (plistener) { + plistener->setProgress(0.1); + } + + // calculate contrast based blend factors to reduce sharpening in regions with low contrast + buildBlendMask(L, clipMask, W, H, contrast, sharpeningParams.autoContrast, clipMask); + if (plistener) { + plistener->setProgress(0.2); + } + conrastThreshold = contrast * 100.f; + CaptureDeconvSharpening(YNew, YOld, clipMask, W, H, radius, sharpeningParams.deconvradiusOffset, sharpeningParams.deconviter, sharpeningParams.deconvitercheck, 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__ + for (; j < W - 3; j += 4) { + const vfloat factor = LVFU(YNew[i][j]) / vmaxf(LVFU(YOld[i][j]), F2V(0.00001f)); + 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 = YNew[i][j] / std::max(YOld[i][j], 0.00001f); + 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); + } + rgbSourceModified = false; +} + +} /* namespace */ diff --git a/rtengine/cfa_linedn_RT.cc b/rtengine/cfa_linedn_RT.cc index b5d171034..ba26740c1 100644 --- a/rtengine/cfa_linedn_RT.cc +++ b/rtengine/cfa_linedn_RT.cc @@ -18,13 +18,12 @@ // 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 "rtengine.h" #include "rawimagesource.h" #include "rt_math.h" @@ -54,16 +53,16 @@ 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)); + float* RawDataTmp = (float*)malloc(static_cast(width) * height * sizeof(float)); #ifdef _OPENMP #pragma omp parallel #endif diff --git a/rtengine/ciecam02.cc b/rtengine/ciecam02.cc index 86b67e000..c7e49b2ed 100644 --- a/rtengine/ciecam02.cc +++ b/rtengine/ciecam02.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 "ciecam02.h" -#include "rtengine.h" +#include "rt_math.h" #include "curves.h" #include -#include "sleef.c" +#include "sleef.h" #ifdef _DEBUG #include "settings.h" @@ -34,10 +34,6 @@ namespace rtengine { -#ifdef _DEBUG -extern const Settings* settings; -#endif - void Ciecam02::curvecolorfloat (float satind, float satval, float &sres, float parsat) { if (satind > 0.f) { @@ -145,8 +141,8 @@ void Ciecam02::curveJfloat (float br, float contr, const LUTu & histogram, LUTf } outCurve *= 32767.f; - //printf("out500=%f out15000=%f\n", outCurve[500], outCurve[15000]); - //outCurve.dump("brig"); + //printf("out500=%f out15000=%f\n", outCurve[500], outCurve[15000]); + //outCurve.dump("brig"); } /** @@ -408,7 +404,7 @@ void Ciecam02::calculate_abfloat ( vfloat &aa, vfloat &bb, vfloat h, vfloat e, v #endif void Ciecam02::initcam1float (float yb, float pilotd, float f, float la, float xw, float yw, float zw, float &n, float &d, float &nbb, float &ncb, - float &cz, float &aw, float &wh, float &pfl, float &fl, float &c) + float &cz, float &aw, float &wh, float &pfl, float &fl, float c) { n = yb / yw; diff --git a/rtengine/ciecam02.h b/rtengine/ciecam02.h index 68763b965..75ccfaa8c 100644 --- a/rtengine/ciecam02.h +++ b/rtengine/ciecam02.h @@ -14,14 +14,21 @@ * GNU General Public License for more details. * * 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_ +#pragma once + #include -#include "LUT.h" +#include + #include "opthelper.h" +template +class LUT; + +using LUTu = LUT; +using LUTf = LUT; + namespace rtengine { @@ -77,7 +84,7 @@ public: * Forward transform from XYZ to CIECAM02 JCh. */ static void initcam1float (float yb, float pilotd, float f, float la, float xw, float yw, float zw, float &n, float &d, float &nbb, float &ncb, - float &cz, float &aw, float &wh, float &pfl, float &fl, float &c); + float &cz, float &aw, float &wh, float &pfl, float &fl, float c); static void initcam2float (float yb, float pilotd, float f, float la, float xw, float yw, float zw, float &n, float &d, float &nbb, float &ncb, float &cz, float &aw, float &fl); @@ -106,4 +113,3 @@ public: }; } -#endif diff --git a/rtengine/cieimage.cc b/rtengine/cieimage.cc index be122febf..f19808df7 100644 --- a/rtengine/cieimage.cc +++ b/rtengine/cieimage.cc @@ -1,5 +1,7 @@ #include "cieimage.h" -#include + +#include +#include namespace rtengine { @@ -10,7 +12,6 @@ CieImage::CieImage (int w, int h) : fromImage(false), W(w), H(h) M_p = new float*[H]; C_p = new float*[H]; sh_p = new float*[H]; - // ch_p = new float*[H]; h_p = new float*[H]; // Initialize the pointers to zero @@ -98,9 +99,6 @@ CieImage::CieImage (int w, int h) : fromImage(false), W(w), H(h) ++c; - // for (int i=0; i. + * along with RawTherapee. If not, see . */ -#ifndef _CIEIMAGE_H_ -#define _CIEIMAGE_H_ +#pragma once -#include "image16.h" #include "noncopyable.h" namespace rtengine { -class CieImage : +class CieImage final : public NonCopyable { private: @@ -39,7 +37,6 @@ public: float** M_p; float** C_p; float** sh_p; -// float** ch_p; float** h_p; CieImage (int w, int h); @@ -50,4 +47,3 @@ public: }; } -#endif diff --git a/rtengine/clutstore.cc b/rtengine/clutstore.cc index 10b7a2c38..e3bd9c988 100644 --- a/rtengine/clutstore.cc +++ b/rtengine/clutstore.cc @@ -1,7 +1,11 @@ #include +#include +#include + #include "clutstore.h" +#include "colortemp.h" #include "iccstore.h" #include "imagefloat.h" #include "opthelper.h" diff --git a/rtengine/clutstore.h b/rtengine/clutstore.h index cd94bc18b..7c570df98 100644 --- a/rtengine/clutstore.h +++ b/rtengine/clutstore.h @@ -3,8 +3,6 @@ #include #include -#include - #include "cache.h" #include "alignedbuffer.h" #include "noncopyable.h" diff --git a/rtengine/color.cc b/rtengine/color.cc index d7d26dc42..d7767b5f5 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -14,24 +14,25 @@ * GNU General Public License for more details. * * 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 "color.h" #include "iccmatrices.h" -#include "mytime.h" -#include "sleef.c" +#include "sleef.h" #include "opthelper.h" #include "iccstore.h" +#ifdef _DEBUG +#include "mytime.h" +#endif + using namespace std; namespace rtengine { -extern const Settings* settings; - cmsToneCurve* Color::linearGammaTRC; LUTf Color::cachef; LUTf Color::cachefy; @@ -1876,21 +1877,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]; @@ -1901,7 +1902,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]; @@ -2057,46 +2058,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 * Copyright (c) 2010-2011 Emil Martinec diff --git a/rtengine/color.h b/rtengine/color.h index 670f13f51..ad51dd49b 100644 --- a/rtengine/color.h +++ b/rtengine/color.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 . */ #pragma once #include -#include #include "rt_math.h" #include "LUT.h" -#include "labimage.h" #include "iccmatrices.h" #include "lcms2.h" -#include "sleef.c" +#include "sleef.h" #define SAT(a,b,c) ((float)max(a,b,c)-(float)min(a,b,c))/(float)max(a,b,c) +namespace Glib +{ + +class ustring; + +} + namespace rtengine { @@ -213,6 +218,13 @@ public: return r * workingspace[1][0] + g * workingspace[1][1] + b * workingspace[1][2]; } +#ifdef __SSE2__ + static vfloat rgbLuminance(vfloat r, vfloat g, vfloat b, const vfloat workingspace[3]) + { + return r * workingspace[0] + g * workingspace[1] + b * workingspace[2]; + } +#endif + /** * @brief Convert red/green/blue to L*a*b * @brief Convert red/green/blue to hue/saturation/luminance @@ -243,20 +255,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 } } } @@ -264,11 +276,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; @@ -276,14 +288,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); @@ -689,32 +701,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: @@ -1092,12 +1078,11 @@ public: */ static inline double gamma2(double x) // g3 1+g4 { - // return x <= 0.003041 ? x * 12.92310 : 1.055 * exp(log(x) / 2.39990) - 0.055;//calculate with calcgamma + // return x <= 0.003041 ? x * 12.92310 : 1.055 * exp(log(x) / 2.39990) - 0.055;//calculate with calcgamma //return x <= 0.0031308 ? x * 12.92310 : 1.055 * exp(log(x) / sRGBGammaCurve) - 0.055;//standard discontinuous - //very small differences between the 2 + //very small differences between the 2 return x <= 0.003040 ? x * 12.92310 : 1.055 * exp(log(x) / sRGBGammaCurve) - 0.055;//continuous - // return x <= 0.003041 ? x * 12.92310 : 1.055011 * exp(log(x) / sRGBGammaCurve) - 0.055011;//continuous - + // return x <= 0.003041 ? x * 12.92310 : 1.055011 * exp(log(x) / sRGBGammaCurve) - 0.055011;//continuous } @@ -1109,12 +1094,11 @@ public: */ static inline double igamma2(double x) //g2 { - // return x <= 0.039289 ? x / 12.92310 : exp(log((x + 0.055) / 1.055) * 2.39990);//calculate with calcgamma - // return x <= 0.04045 ? x / 12.92310 : exp(log((x + 0.055) / 1.055) * sRGBGammaCurve);//standard discontinuous - //very small differences between the 4 + // return x <= 0.039289 ? x / 12.92310 : exp(log((x + 0.055) / 1.055) * 2.39990);//calculate with calcgamma + // return x <= 0.04045 ? x / 12.92310 : exp(log((x + 0.055) / 1.055) * sRGBGammaCurve);//standard discontinuous + //very small differences between the 4 return x <= 0.039286 ? x / 12.92310 : exp(log((x + 0.055) / 1.055) * sRGBGammaCurve);//continuous - // return x <= 0.039293 ? x / 12.92310 : exp(log((x + 0.055011) / 1.055011) * sRGBGammaCurve);//continuous - + // return x <= 0.039293 ? x / 12.92310 : exp(log((x + 0.055011) / 1.055011) * sRGBGammaCurve);//continuous } @@ -1404,7 +1388,7 @@ public: * @param HH hue before [-PI ; +PI] * @param Chprov1 chroma after [0 ; 180 (can be superior)] * @param CC chroma before [0 ; 180] - * @param corectionHuechroma hue correction depending on chromaticity (saturation), in radians [0 ; 0.45] (return value) + * @param correctionHueChroma hue correction depending on chromaticity (saturation), in radians [0 ; 0.45] (return value) * @param correctlum hue correction depending on luminance (brightness, contrast,...), in radians [0 ; 0.45] (return value) * @param munsDbgInfo (Debug target only) object to collect information */ @@ -1889,6 +1873,29 @@ public: return (hr); } + + static inline void RGB2Y(const float* R, const float* G, const float* B, float* Y1, float * Y2, int W) { + int i = 0; +#ifdef __SSE2__ + 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 = c1v * Rv + c2v * Gv + c3v * Bv; + 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] = 0.2627f * r + 0.6780f * g + 0.0593f * b; + } + } }; } diff --git a/rtengine/colortemp.cc b/rtengine/colortemp.cc index a7a769d93..02d3e0e6d 100644 --- a/rtengine/colortemp.cc +++ b/rtengine/colortemp.cc @@ -14,21 +14,23 @@ * GNU General Public License for more details. * * 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 "colortemp.h" -#include "rtengine.h" +#include "iccmatrices.h" +#include "rt_math.h" #include #include #include -#include "sleef.c" +#include "sleef.h" #include "settings.h" namespace rtengine { -extern const Settings* settings; - static const double cie_colour_match_jd[97][3] = {//350nm to 830nm 5 nm J.Desmis 2° Standard Observer. {0.0000000, 0.000000, 0.000000}, {0.0000000, 0.000000, 0.000000}, {0.0001299, 0.0003917, 0.0006061}, {0.0002321, 0.000006965, 0.001086}, {0.0004149, 0.00001239, 0.001946}, {0.0007416, 0.00002202, 0.003846}, @@ -1088,11 +1090,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 +1106,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 +1114,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 +1221,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 +1282,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 +1308,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..a38e01072 100644 --- a/rtengine/colortemp.h +++ b/rtengine/colortemp.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 _COLORTEMP_ -#define _COLORTEMP_ +#pragma once #include #include @@ -207,4 +206,3 @@ public: }; } -#endif 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..6a7decdda 100644 --- a/rtengine/coord.h +++ b/rtengine/coord.h @@ -14,11 +14,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 . */ -#ifndef __COORD__ -#define __COORD__ +#pragma once namespace rtengine { @@ -253,5 +252,3 @@ inline const PolarCoord operator* (const double lhs, const PolarCoord& rhs) } } - -#endif diff --git a/rtengine/coord2d.h b/rtengine/coord2d.h index bc030f22e..9f0784b9a 100644 --- a/rtengine/coord2d.h +++ b/rtengine/coord2d.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 __COORD2D__ -#define __COORD2D__ +#pragma once namespace rtengine { @@ -35,5 +34,5 @@ public: y = y_; } }; + } -#endif 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..1137a0937 100644 --- a/rtengine/cplx_wavelet_dec.h +++ b/rtengine/cplx_wavelet_dec.h @@ -12,14 +12,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 . * * 2010 Ilya Popov * 2012 Emil Martinec */ - -#ifndef CPLX_WAVELET_DEC_H_INCLUDED -#define CPLX_WAVELET_DEC_H_INCLUDED +#pragma once #include #include @@ -45,7 +43,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 +94,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 @@ -138,6 +135,14 @@ wavelet_decomposition::wavelet_decomposition(E * src, int width, int height, int //n=0 lopass, n=1 hipass } } +/* } else if(wavfilt_len == 22) { + for (int n = 0; n < 2; n++) { + for (int i = 0; i < wavfilt_len; i++) { + wavfilt_anal[wavfilt_len * (n) + i] = Daub4_anal22[n][i]; + wavfilt_synth[wavfilt_len * (n) + i] = Daub4_anal22[n][wavfilt_len - 1 - i]; + //n=0 lopass, n=1 hipass + } + } */ } else if(wavfilt_len == 4) { for (int n = 0; n < 2; n++) { for (int i = 0; i < wavfilt_len; i++) { @@ -147,7 +152,7 @@ wavelet_decomposition::wavelet_decomposition(E * src, int width, int height, int } } } - +//printf("OK cplx\n"); // after coefficient rotation, data structure is: // wavelet_decomp[scale][channel={lo,hi1,hi2,hi3}][pixel_array] @@ -267,5 +272,3 @@ void wavelet_decomposition::reconstruct(E * dst, const float blend) } } - -#endif diff --git a/rtengine/cplx_wavelet_filter_coeffs.h b/rtengine/cplx_wavelet_filter_coeffs.h index bd333d4b9..3386be8d0 100644 --- a/rtengine/cplx_wavelet_filter_coeffs.h +++ b/rtengine/cplx_wavelet_filter_coeffs.h @@ -12,12 +12,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 . * * 2012 Emil Martinec * 2014 Jacques Desmis */ - +#pragma once namespace rtengine { @@ -49,6 +49,13 @@ const float Daub4_anal16[2][16] ALIGNED16 = {//Daub 14 { -0.0002501134f, -0.0012739524f, -0.0003037575f, 0.008874895f, 0.01171997f , -0.026891225f, -0.057001725f, 0.05042335f, 0.158417505f, -0.10175691f, -0.33218624f, 0.515574245f, -0.28039564f, 0.055049715f, 0.f, 0.f} }; -// if necessary ?? we can add D20 !! +const float Daub4_anal22[2][22] ALIGNED16 = {//Daub 20 + {0.f, 0.f, 0.01885858f, 0.13306109f, 0.37278535f, 0.48681406f, 0.19881887f, -0.1766681f, -0.13855494f, 0.09006372f, 0.0658015f, -0.05048328f, -0.02082962f, + 0.0234849f, 0.002550218f, -0.0075895f, 0.0009866627f, 0.001408843f, -0.000484973f, -0.0000823545f, 0.0000661271f, -0.00000939f}, + {0.00000939f, -0.0000661271f, 0.0000823545f, 0.000484973f, -0.001408843f, -0.0009866627f, 0.0075895f, -0.002550218f, -0.0234849f, + 0.02082962f, 0.05048328f, -0.0658015f, -0.09006372f, 0.13855494f, 0.1766681f, -0.19881887f, -0.48681406f, -0.37278535f, -0.13306109f, -0.01885858f, 0.f, 0.f} +}; + +// if necessary ?? we can add D20 !! } diff --git a/rtengine/cplx_wavelet_level.h b/rtengine/cplx_wavelet_level.h index cab0d8e3e..09b4e4a88 100644 --- a/rtengine/cplx_wavelet_level.h +++ b/rtengine/cplx_wavelet_level.h @@ -12,15 +12,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 . * * 2010 Ilya Popov * 2012 Emil Martinec * 2014 Ingo Weyrich - */ - -#ifndef CPLX_WAVELET_LEVEL_H_INCLUDED -#define CPLX_WAVELET_LEVEL_H_INCLUDED +*/ +#pragma once #include #include "rt_math.h" @@ -274,7 +272,7 @@ template void wavelet_level::SynthesisFilterHaarVertical (const T #pragma omp for nowait #endif - for(int i = 0; i < skip; i++) + for(int i = 0; i < std::min(skip, height); i++) { for(int j = 0; j < width; j++) { dst[width * i + j] = (srcLo[i * width + j] + srcHi[i * width + j]); @@ -759,5 +757,3 @@ template template void wavelet_level::reconstruct_lev } #endif } - -#endif diff --git a/rtengine/curves.cc b/rtengine/curves.cc index 9d10c4c0e..35cc34089 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -14,18 +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 . */ #include #include #include #include #include -#include -#include -#ifdef _OPENMP -#include -#endif +#include #include "rt_math.h" @@ -520,6 +516,26 @@ void CurveFactory::curveexLocal(bool & localexutili, const std::vector& } +void CurveFactory::curvemaskLocal(bool & localmaskutili, const std::vector& curvePoints, LUTf & LocalmaskCurve, int skip) +{ + bool needed = false; + std::unique_ptr dCurve; + +// if (localexutili && !curvePoints.empty() && curvePoints[0] != 0) { + if (!curvePoints.empty() && curvePoints[0] != 0) { + dCurve = std::unique_ptr (new DiagonalCurve(curvePoints, CURVES_MIN_POLY_POINTS / skip)); + + if (dCurve && !dCurve->isIdentity()) { + needed = true; + localmaskutili = true; + } + } + + fillCurveArray(dCurve.get(), LocalmaskCurve, skip, needed); + +} + + void CurveFactory::localLCurve(double br, double contr, /*const std::vector& curvePoints,*/ LUTu & histogram, LUTf & outCurve, @@ -772,16 +788,16 @@ void CurveFactory::complexsgnCurve(bool & autili, bool & butili, bool & ccutili } -void CurveFactory::complexCurve(double ecomp, double black, double hlcompr, double hlcomprthresh, - double shcompr, double br, double contr, - const std::vector& curvePoints, - const std::vector& curvePoints2, - LUTu & histogram, - LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, - LUTu & outBeforeCCurveHistogram, - ToneCurve & customToneCurve1, - ToneCurve & customToneCurve2, - int skip) +void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, double hlcomprthresh, + double shcompr, double br, double contr, + const std::vector& curvePoints, + const std::vector& curvePoints2, + const LUTu & histogram, + LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, + LUTu & outBeforeCCurveHistogram, + ToneCurve & customToneCurve1, + ToneCurve & customToneCurve2, + int skip) { // the curve shapes are defined in sRGB gamma, but the output curves will operate on linear floating point data, @@ -904,15 +920,15 @@ void CurveFactory::complexCurve(double ecomp, double black, double hlcompr, doub } // 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++) { @@ -1640,6 +1656,142 @@ void LocretigainCurverab::Set(const std::vector &curvePoints) Reset(); } } +LocHHmaskblCurve::LocHHmaskblCurve() : sum(0.f) {}; + +void LocHHmaskblCurve::Reset() +{ + lutLocHHmaskblCurve.reset(); + sum = 0.f; +} + + +void LocHHmaskblCurve::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + Reset(); // raise this value if the quality suffers from this number of samples + return; + } + + lutLocHHmaskblCurve(501); // raise this value if the quality suffers from this number of samples + sum = 0.f; + + for (int i = 0; i < 501; i++) { + lutLocHHmaskblCurve[i] = pCurve.getVal(double (i) / 500.); + + if (lutLocHHmaskblCurve[i] < 0.02f) { + lutLocHHmaskblCurve[i] = 0.02f; + } + + sum += lutLocHHmaskblCurve[i]; + } + + //lutLocHHCurve.dump("wav"); +} + +void LocHHmaskblCurve::Set(const std::vector &curvePoints, bool & lhmasblutili) +{ + // if (HHutili && !curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve ttcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + ttcurve.setIdentityValue(0.); + lhmasblutili = true; + Set(ttcurve); + } else { + Reset(); + } +} + +LocLLmaskblCurve::LocLLmaskblCurve() : sum(0.f) {}; + +void LocLLmaskblCurve::Reset() +{ + lutLocLLmaskblCurve.reset(); + sum = 0.f; +} + +void LocLLmaskblCurve::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + Reset(); // raise this value if the quality suffers from this number of samples + return; + } + + lutLocLLmaskblCurve(501); // raise this value if the quality suffers from this number of samples + sum = 0.f; + + for (int i = 0; i < 501; i++) { + lutLocLLmaskblCurve[i] = pCurve.getVal(double (i) / 500.); + + if (lutLocLLmaskblCurve[i] < 0.02f) { + lutLocLLmaskblCurve[i] = 0.02f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value + } + + sum += lutLocLLmaskblCurve[i]; + } + + //lutLocHHCurve.dump("wav"); +} + + + +void LocLLmaskblCurve::Set(const std::vector &curvePoints, bool & llmasblutili) +{ + // if (HHutili && !curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve ttcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + ttcurve.setIdentityValue(0.); + llmasblutili = true; + Set(ttcurve); + } else { + Reset(); + } +} + +LocCCmaskblCurve::LocCCmaskblCurve() : sum(0.f) {}; + +void LocCCmaskblCurve::Reset() +{ + lutLocCCmaskblCurve.reset(); + sum = 0.f; +} + +void LocCCmaskblCurve::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + Reset(); // raise this value if the quality suffers from this number of samples + return; + } + + lutLocCCmaskblCurve(501); // raise this value if the quality suffers from this number of samples + sum = 0.f; + + for (int i = 0; i < 501; i++) { + lutLocCCmaskblCurve[i] = pCurve.getVal(double (i) / 500.); + + if (lutLocCCmaskblCurve[i] < 0.02f) { + lutLocCCmaskblCurve[i] = 0.02f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value + } + + sum += lutLocCCmaskblCurve[i]; + } + + //lutLocHHCurve.dump("wav"); +} + + + +void LocCCmaskblCurve::Set(const std::vector &curvePoints, bool & lcmasblutili) +{ + // if (HHutili && !curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve ttcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + ttcurve.setIdentityValue(0.); + lcmasblutili = true; + Set(ttcurve); + } else { + Reset(); + } +} @@ -2629,7 +2781,50 @@ void LocwavCurve::Set(const Curve &pCurve) //lutLocCurve.dump("wav"); } -void LocwavCurve::Set(const std::vector &curvePoints) +void LocwavCurve::Set(const std::vector &curvePoints, bool & lcwavutili) +{ + + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve tcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + tcurve.setIdentityValue(0.); + lcwavutili = true; + Set(tcurve); + } else { + Reset(); + } +} + +LocretitransCurve::LocretitransCurve() : sum(0.f) {}; + +void LocretitransCurve::Reset() +{ + lutLocretitransCurve.reset(); + sum = 0.f; +} + +void LocretitransCurve::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + Reset(); // raise this value if the quality suffers from this number of samples + return; + } + + lutLocretitransCurve(501); // raise this value if the quality suffers from this number of samples + sum = 0.f; + + for (int i = 0; i < 501; i++) { + lutLocretitransCurve[i] = pCurve.getVal(double (i) / 500.); + + if (lutLocretitransCurve[i] < 0.02f) { + lutLocretitransCurve[i] = 0.02f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value + } + + sum += lutLocretitransCurve[i]; + } + + //lutLocCurve.dump("wav"); +} +void LocretitransCurve::Set(const std::vector &curvePoints) { if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { @@ -2642,7 +2837,6 @@ void LocwavCurve::Set(const std::vector &curvePoints) } - LocretigainCurve::LocretigainCurve() : sum(0.f) {}; void LocretigainCurve::Reset() @@ -3184,10 +3378,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; @@ -3498,12 +3692,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); @@ -3670,15 +3864,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 } @@ -3698,15 +3892,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; } @@ -3724,15 +3918,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; } @@ -3800,15 +3994,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 } @@ -3909,7 +4103,7 @@ void PerceptualToneCurve::init() } } -void PerceptualToneCurve::initApplyState(PerceptualToneCurveState & state, Glib::ustring workingSpace) const +void PerceptualToneCurve::initApplyState(PerceptualToneCurveState & state, const Glib::ustring &workingSpace) const { // Get the curve's contrast value, and convert to a chroma scaling diff --git a/rtengine/curves.h b/rtengine/curves.h index fa8cd079e..5d9e19940 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -14,32 +14,31 @@ * GNU General Public License for more details. * * 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__ +#pragma once #include #include #include -#include - #include "rt_math.h" -#include "../rtgui/mycurve.h" -#include "../rtgui/myflatcurve.h" -#include "../rtgui/mydiagonalcurve.h" -#include "color.h" -#include "pipettebuffer.h" - +#include "flatcurvetypes.h" +#include "diagonalcurvetypes.h" +#include "noncopyable.h" #include "LUT.h" - +#include "sleef.h" #define CURVES_MIN_POLY_POINTS 1000 -#include "rt_math.h" - #define CLIPI(a) ((a)>0?((a)<65534?(a):65534):0) +namespace Glib +{ + +class ustring; + +} + using namespace std; namespace rtengine @@ -356,8 +355,7 @@ public: public: static void complexCurve(double ecomp, double black, double hlcompr, double hlcomprthresh, double shcompr, double br, double contr, const std::vector& curvePoints, const std::vector& curvePoints2, - LUTu & histogram, LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, LUTu & outBeforeCCurveHistogram, ToneCurve & outToneCurve, ToneCurve & outToneCurve2, - + const LUTu & histogram, LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, LUTu & outBeforeCCurveHistogram, ToneCurve & outToneCurve, ToneCurve & outToneCurve2, int skip = 1); static void complexCurvelocal(double ecomp, double black, double hlcompr, double hlcomprthresh, double shcompr, double br, double cont, double lumare, @@ -381,6 +379,7 @@ public: static void curveCCLocal(bool & localcutili, const std::vector& curvePoints, LUTf & LocalCCurve, int skip); static void curveskLocal(bool & localskutili, const std::vector& curvePoints, LUTf & LocalskCurve, int skip); static void curveexLocal(bool & localexutili, const std::vector& curvePoints, LUTf & LocalexCurve, int skip); + static void curvemaskLocal(bool & localmaskutili, const std::vector& curvePoints, LUTf & LocalmaskCurve, int skip); static void complexsgnCurve(bool & autili, bool & butili, bool & ccutili, bool & clcutili, const std::vector& acurvePoints, const std::vector& bcurvePoints, const std::vector& cccurvePoints, const std::vector& lccurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve, @@ -478,7 +477,7 @@ public: virtual bool isIdentity() const = 0; }; -class DiagonalCurve : public Curve +class DiagonalCurve final : public Curve { protected: @@ -500,7 +499,7 @@ public: }; }; -class FlatCurve : public Curve +class FlatCurve final : public Curve { private: @@ -649,6 +648,92 @@ public: } }; +class LocHHmaskblCurve +{ +private: + LUTf lutLocHHmaskblCurve; // 0xffff range + void Set(const Curve &pCurve); + +public: + float sum; + + virtual ~LocHHmaskblCurve() {}; + LocHHmaskblCurve(); + void Reset(); + void Set(const std::vector &curvePoints, bool & lhmasblutili); + float getSum() const + { + return sum; + } + + float operator[](float index) const + { + return lutLocHHmaskblCurve[index]; + } + operator bool (void) const + { + return lutLocHHmaskblCurve; + } +}; + +class LocCCmaskblCurve +{ +private: + LUTf lutLocCCmaskblCurve; // 0xffff range + void Set(const Curve &pCurve); + +public: + float sum; + + virtual ~LocCCmaskblCurve() {}; + LocCCmaskblCurve(); + void Reset(); + void Set(const std::vector &curvePoints, bool & lcmasblutili); + float getSum() const + { + return sum; + } + + float operator[](float index) const + { + return lutLocCCmaskblCurve[index]; + } + operator bool (void) const + { + return lutLocCCmaskblCurve; + } +}; + +class LocLLmaskblCurve +{ +private: + LUTf lutLocLLmaskblCurve; // 0xffff range + void Set(const Curve &pCurve); + +public: + float sum; + + virtual ~LocLLmaskblCurve() {}; + LocLLmaskblCurve(); + void Reset(); + void Set(const std::vector &curvePoints, bool & llmasblutili); + float getSum() const + { + return sum; + } + + float operator[](float index) const + { + return lutLocLLmaskblCurve[index]; + } + operator bool (void) const + { + return lutLocLLmaskblCurve; + } +}; + + + class LocHHmasktmCurve { private: @@ -1229,6 +1314,34 @@ public: } }; +class LocretitransCurve +{ +private: + LUTf lutLocretitransCurve; // 0xffff range + void Set(const Curve &pCurve); + +public: + float sum; + + virtual ~LocretitransCurve() {}; + LocretitransCurve(); + void Reset(); + void Set(const std::vector &curvePoints); + float getSum() const + { + return sum; + } + + float operator[](float index) const + { + return lutLocretitransCurve[index]; + } + operator bool (void) const + { + return lutLocretitransCurve; + } +}; + class LocwavCurve { @@ -1242,7 +1355,7 @@ public: virtual ~LocwavCurve() {}; LocwavCurve(); void Reset(); - void Set(const std::vector &curvePoints); + void Set(const std::vector &curvePoints, bool &lcwavutili); float getSum() const { return sum; @@ -1584,12 +1697,6 @@ public: float *r, float *g, float *b) const; }; -class SatAndValueBlendingToneCurve : public ToneCurve -{ -public: - void Apply(float& r, float& g, float& b) const; -}; - class WeightedStdToneCurve : public ToneCurve { private: @@ -1637,7 +1744,7 @@ private: float calculateToneCurveContrastValue() const; public: static void init(); - void initApplyState(PerceptualToneCurveState & state, Glib::ustring workingSpace) const; + void initApplyState(PerceptualToneCurveState & state, const Glib::ustring& workingSpace) const; void BatchApply(const size_t start, const size_t end, float *r, float *g, float *b, const PerceptualToneCurveState &state) const; }; @@ -1650,6 +1757,7 @@ inline void StandardToneCurve::Apply(float& r, float& g, float& b) const curves::setLutVal(lutToneCurve, r, g, b); } + inline void StandardToneCurve::BatchApply( const size_t start, const size_t end, float *r, float *g, float *b) const @@ -1969,47 +2077,6 @@ inline void WeightedStdToneCurve::BatchApply(const size_t start, const size_t en #endif } -// Tone curve modifying the value channel only, preserving hue and saturation -// values in 0xffff space -inline void SatAndValueBlendingToneCurve::Apply(float& ir, float& ig, float& ib) const -{ - - assert(lutToneCurve); - - float r = CLIP(ir); - float g = CLIP(ig); - float b = CLIP(ib); - - const float lum = (r + g + b) / 3.f; - const float newLum = lutToneCurve[lum]; - - if (newLum == lum) { - return; - } - - float h, s, v; - Color::rgb2hsvtc(r, g, b, h, s, v); - - float dV; - - if (newLum > lum) { - // Linearly targeting Value = 1 and Saturation = 0 - const float coef = (newLum - lum) / (65535.f - lum); - dV = (1.f - v) * coef; - s *= 1.f - coef; - } else { - // Linearly targeting Value = 0 - const float coef = (newLum - lum) / lum ; - dV = v * coef; - } - - Color::hsv2rgbdcp(h, s, v + dV, r, g, b); - - setUnlessOOG(ir, ig, ib, r, g, b); -} - } #undef CLIPI - -#endif diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index 56855b604..11fe306b8 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -14,29 +14,29 @@ * GNU General Public License for more details. * * 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 #include +#include +#include +#include #include "dcp.h" #include "cJSON.h" +#include "color.h" #include "iccmatrices.h" #include "iccstore.h" -#include "improcfun.h" +#include "imagefloat.h" #include "rawimagesource.h" #include "rt_math.h" - -namespace rtengine -{ - -extern const Settings* settings; - -} +#include "utils.h" +#include "../rtexif/rtexif.h" +#include "../rtgui/options.h" using namespace rtengine; using namespace rtexif; @@ -334,8 +334,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. @@ -371,23 +369,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; @@ -446,7 +432,7 @@ std::map getAliases(const Glib::ustring& profile_dir) } -struct DCPProfile::ApplyState::Data { +struct DCPProfileApplyState::Data { float pro_photo[3][3]; float work[3][3]; bool already_pro_photo; @@ -455,14 +441,12 @@ struct DCPProfile::ApplyState::Data { float bl_scale; }; -DCPProfile::ApplyState::ApplyState() : +DCPProfileApplyState::DCPProfileApplyState() : data(new Data{}) { } -DCPProfile::ApplyState::~ApplyState() -{ -} +DCPProfileApplyState::~DCPProfileApplyState() = default; DCPProfile::DCPProfile(const Glib::ustring& filename) : has_color_matrix_1(false), @@ -1162,7 +1146,7 @@ void DCPProfile::apply( } } -void DCPProfile::setStep2ApplyState(const Glib::ustring& working_space, bool use_tone_curve, bool apply_look_table, bool apply_baseline_exposure, ApplyState& as_out) +void DCPProfile::setStep2ApplyState(const Glib::ustring& working_space, bool use_tone_curve, bool apply_look_table, bool apply_baseline_exposure, DCPProfileApplyState& as_out) { as_out.data->use_tone_curve = use_tone_curve; as_out.data->apply_look_table = apply_look_table; @@ -1206,7 +1190,7 @@ void DCPProfile::setStep2ApplyState(const Glib::ustring& working_space, bool use } } -void DCPProfile::step2ApplyTile(float* rc, float* gc, float* bc, int width, int height, int tile_width, const ApplyState& as_in) const +void DCPProfile::step2ApplyTile(float* rc, float* gc, float* bc, int width, int height, int tile_width, const DCPProfileApplyState& as_in) const { #define FCLIP(a) ((a)>0.0?((a)<65535.5?(a):65535.5):0.0) @@ -1882,7 +1866,7 @@ DCPProfile* DCPStore::getProfile(const Glib::ustring& filename) const if (res->isValid()) { // Add profile profile_cache[key] = res; - if (options.rtSettings.verbose) { + if (settings->verbose) { printf("DCP profile '%s' loaded from disk\n", filename.c_str()); } return res; diff --git a/rtengine/dcp.h b/rtengine/dcp.h index 48b881661..573349348 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 @@ -24,35 +24,23 @@ #include #include -#include +#include #include "../rtgui/threadutils.h" -#include "imagefloat.h" #include "curves.h" -#include "colortemp.h" #include "noncopyable.h" namespace rtengine { +class ColorTemp; +class Imagefloat; +class DCPProfileApplyState; + class DCPProfile final { public: - class ApplyState final - { - public: - ApplyState(); - ~ApplyState(); - - private: - struct Data; - - const std::unique_ptr data; - - friend class DCPProfile; - }; - struct Illuminants { short light_source_1; short light_source_2; @@ -86,8 +74,8 @@ public: const Matrix& cam_wb_matrix, bool apply_hue_sat_map = true ) const; - void setStep2ApplyState(const Glib::ustring& working_space, bool use_tone_curve, bool apply_look_table, bool apply_baseline_exposure, ApplyState& as_out); - void step2ApplyTile(float* r, float* g, float* b, int width, int height, int tile_width, const ApplyState& as_in) const; + void setStep2ApplyState(const Glib::ustring& working_space, bool use_tone_curve, bool apply_look_table, bool apply_baseline_exposure, DCPProfileApplyState& as_out); + void step2ApplyTile(float* r, float* g, float* b, int width, int height, int tile_width, const DCPProfileApplyState& as_in) const; private: struct HsbModify { @@ -148,6 +136,20 @@ private: AdobeToneCurve tone_curve; }; +class DCPProfileApplyState final +{ +public: + DCPProfileApplyState(); + ~DCPProfileApplyState(); + +private: + struct Data; + + const std::unique_ptr data; + + friend class DCPProfile; +}; + class DCPStore final : public NonCopyable { diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 280b692e7..537bf1334 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -26,12 +26,13 @@ /*RT*/#include /*RT*/#endif +#include #include #include #include "opthelper.h" //#define BENCHMARK #include "StopWatch.h" - +#include "utils.h" #include #include @@ -93,7 +94,6 @@ #ifdef WIN32 #include #include -#define snprintf _snprintf #define strcasecmp stricmp #define strncasecmp strnicmp typedef __int64 INT64; @@ -157,7 +157,6 @@ const float d65_white[3] = { 0.950456, 1, 1.088754 }; #define MIN(a,b) rtengine::min(a,static_cast<__typeof__(a)>(b)) #define MAX(a,b) rtengine::max(a,static_cast<__typeof__(a)>(b)) #define LIM(x,min,max) rtengine::LIM(x,static_cast<__typeof__(x)>(min),static_cast<__typeof__(x)>(max)) -#define ULIM(x,y,z) rtengine::median(x,static_cast<__typeof__(x)>(y),static_cast<__typeof__(x)>(z)) #define CLIP(x) rtengine::CLIP(x) #define SWAP(a,b) { a=a+b; b=a-b; a=a-b; } @@ -240,7 +239,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 +2416,63 @@ 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 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); + const int shot = LIM(shot_select, 1, tiff_samples) - 1; + const int predictor_init = static_cast(0x8000 + load_flags); + for (int row = 0; row < raw_height; ++row) { + int stashed_predictors[2] = {predictor_init, predictor_init}; + 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 = stashed_predictors[s & 1]; + for (int c = 0; c < tiff_samples; ++c) { + pred += diff[(s & 1) * tiff_samples + c]; + const unsigned upix = pred & 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; + } + } + if (c == (tiff_samples-1)) { + stashed_predictors[s & 1] = pred; + } + } + } + } + } + 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() @@ -2683,93 +2686,6 @@ void CLASS canon_rmf_load_raw() maximum = curve[0x3ff]; } -unsigned CLASS pana_bits_t::operator() (int nbits, unsigned *bytes) -{ -/*RT static uchar buf[0x4000]; */ -/*RT static int vbits;*/ - int byte; - - if (!nbits && !bytes) return vbits=0; - if (!vbits) { - fread (buf+load_flags, 1, 0x4000-load_flags, ifp); - fread (buf, 1, load_flags, ifp); - } - if (encoding == 5) { - for (byte = 0; byte < 16; byte++) - { - bytes[byte] = buf[vbits++]; - vbits &= 0x3FFF; - } - return 0; - } else { - vbits = (vbits - nbits) & 0x1ffff; - byte = vbits >> 3 ^ 0x3ff0; - return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits); - } -} - -void CLASS panasonic_load_raw() -{ - pana_bits_t pana_bits(ifp,load_flags, RT_pana_info.encoding); - int row, col, i, j, sh=0, pred[2], nonz[2]; - unsigned bytes[16] = {}; - ushort *raw_block_data; - - pana_bits(0, 0); - int enc_blck_size = RT_pana_info.bpp == 12 ? 10 : 9; - if (RT_pana_info.encoding == 5) { - for (row = 0; row < raw_height; row++) - { - raw_block_data = raw_image + row * raw_width; - - for (col = 0; col < raw_width; col += enc_blck_size) { - pana_bits(0, bytes); - - if (RT_pana_info.bpp == 12) { - raw_block_data[col] = ((bytes[1] & 0xF) << 8) + bytes[0]; - raw_block_data[col + 1] = 16 * bytes[2] + (bytes[1] >> 4); - raw_block_data[col + 2] = ((bytes[4] & 0xF) << 8) + bytes[3]; - raw_block_data[col + 3] = 16 * bytes[5] + (bytes[4] >> 4); - raw_block_data[col + 4] = ((bytes[7] & 0xF) << 8) + bytes[6]; - raw_block_data[col + 5] = 16 * bytes[8] + (bytes[7] >> 4); - raw_block_data[col + 6] = ((bytes[10] & 0xF) << 8) + bytes[9]; - raw_block_data[col + 7] = 16 * bytes[11] + (bytes[10] >> 4); - raw_block_data[col + 8] = ((bytes[13] & 0xF) << 8) + bytes[12]; - raw_block_data[col + 9] = 16 * bytes[14] + (bytes[13] >> 4); - } - else if (RT_pana_info.bpp == 14) { - raw_block_data[col] = bytes[0] + ((bytes[1] & 0x3F) << 8); - raw_block_data[col + 1] = (bytes[1] >> 6) + 4 * (bytes[2]) + - ((bytes[3] & 0xF) << 10); - raw_block_data[col + 2] = (bytes[3] >> 4) + 16 * (bytes[4]) + - ((bytes[5] & 3) << 12); - raw_block_data[col + 3] = ((bytes[5] & 0xFC) >> 2) + (bytes[6] << 6); - raw_block_data[col + 4] = bytes[7] + ((bytes[8] & 0x3F) << 8); - raw_block_data[col + 5] = (bytes[8] >> 6) + 4 * bytes[9] + ((bytes[10] & 0xF) << 10); - raw_block_data[col + 6] = (bytes[10] >> 4) + 16 * bytes[11] + ((bytes[12] & 3) << 12); - raw_block_data[col + 7] = ((bytes[12] & 0xFC) >> 2) + (bytes[13] << 6); - raw_block_data[col + 8] = bytes[14] + ((bytes[15] & 0x3F) << 8); - } - } - } - } else { - for (row=0; row < height; row++) - for (col=0; col < raw_width; col++) { - if ((i = col % 14) == 0) - pred[0] = pred[1] = nonz[0] = nonz[1] = 0; - if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2)); - if (nonz[i & 1]) { - if ((j = pana_bits(8))) { - if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4) - pred[i & 1] &= ~(-1 << sh); - pred[i & 1] += j << sh; - } - } else if ((nonz[i & 1] = pana_bits(8)) || i > 11) - pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4); - if ((RAW(row,col) = pred[col & 1]) > 4098 && col < width) derror(); - } - } -} void CLASS olympus_load_raw() { @@ -4216,8 +4132,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++) { @@ -4515,6 +4431,10 @@ void CLASS foveon_interpolate() void CLASS crop_masked_pixels() { + if (data_error) { + return; + } + int row, col; unsigned r, c, m, mblack[8], zero, val; @@ -5677,13 +5597,26 @@ nf: order = 0x4949; else if (!strcmp (buf,"AOC") || !strcmp (buf,"QVC")) fseek (ifp, -4, SEEK_CUR); + // ALB -- taken from LibRaw ------------------------------------------------ + else if (!strncmp(buf, "CMT3", 4)) + { + order = sget2((uchar *)(buf + 4)); + fseek(ifp, 2L, SEEK_CUR); + } + else if (RT_canon_CR3_data.CR3_CTMDtag) + { + order = sget2((uchar *)buf); + fseek(ifp, -2L, SEEK_CUR); + } + // ------------------------------------------------------------------------- + else { fseek (ifp, -10, SEEK_CUR); if (!strncmp(make,"SAMSUNG",7)) base = ftell(ifp); } entries = get2(); - if (entries > 1000) return; + if (entries > 2000) return; morder = order; while (entries--) { order = morder; @@ -5888,16 +5821,335 @@ get2_256: parse_thumb_note (base, 136, 137); } if (tag == 0x4001 && len > 500) { - i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126; - fseek (ifp, i, SEEK_CUR); - FORC4 cam_mul[c ^ (c >> 1)] = get2(); - for (i+=18; i <= len; i+=10) { - get2(); - FORC4 sraw_mul[c ^ (c >> 1)] = get2(); - if (sraw_mul[1] == 1170) break; + // i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126; + // fseek (ifp, i, SEEK_CUR); + // FORC4 cam_mul[c ^ (c >> 1)] = get2(); + // for (i+=18; i <= len; i+=10) { + // get2(); + // FORC4 sraw_mul[c ^ (c >> 1)] = get2(); + // if (sraw_mul[1] == 1170) break; + // } + // -- ALB -- adapted from LibRaw -------------------------------------- + int bls = 0; + long int offsetChannelBlackLevel = 0L; + long int offsetChannelBlackLevel2 = 0L; + long int offsetWhiteLevels = 0L; + struct { + int AverageBlackLevel; + int ColorDataSubVer; + int NormalWhiteLevel; + int SpecularWhiteLevel; + } imCanon = { 0, 0, 0, 0 }; + long int save1 = ftell(ifp); + + switch (len) + { + + case 582: + // imCanon.ColorDataVer = 1; // 20D / 350D + + fseek(ifp, save1 + (0x0019 << 1), SEEK_SET); + FORC4 cam_mul[c ^ (c >> 1)] = (float)get2(); + // fseek(ifp, save1 + (0x001e << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0041 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom1][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0046 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom2][c ^ (c >> 1)] = get2(); + + // fseek(ifp, save1 + (0x0023 << 1), SEEK_SET); + // Canon_WBpresets(2, 2); + // fseek(ifp, save1 + (0x004b << 1), SEEK_SET); + // Canon_WBCTpresets(1); // ABCT + offsetChannelBlackLevel = save1 + (0x00a6 << 1); + break; + + case 653: + // imCanon.ColorDataVer = 2; // 1Dmk2 / 1DsMK2 + + // fseek(ifp, save1 + (0x0018 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x0022 << 1), SEEK_SET); + FORC4 cam_mul[c ^ (c >> 1)] = (float)get2(); + // fseek(ifp, save1 + (0x0090 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom1][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0095 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom2][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x009a << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom3][c ^ (c >> 1)] = get2(); + + // fseek(ifp, save1 + (0x0027 << 1), SEEK_SET); + // Canon_WBpresets(2, 12); + // fseek(ifp, save1 + (0x00a4 << 1), SEEK_SET); + // Canon_WBCTpresets(1); // ABCT + offsetChannelBlackLevel = save1 + (0x011e << 1); + break; + + case 796: + // imCanon.ColorDataVer = 3; // 1DmkIIN / 5D / 30D / 400D + // imCanon.ColorDataSubVer = get2(); + + fseek(ifp, save1 + (0x003f << 1), SEEK_SET); + FORC4 cam_mul[c ^ (c >> 1)] = (float)get2(); + // fseek(ifp, save1 + (0x0044 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0049 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0071 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom1][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0076 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom2][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x007b << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom3][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0080 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom][c ^ (c >> 1)] = get2(); + + // fseek(ifp, save1 + (0x004e << 1), SEEK_SET); + // Canon_WBpresets(2, 12); + // fseek(ifp, save1 + (0x0085 << 1), SEEK_SET); + // Canon_WBCTpresets(0); // BCAT + offsetChannelBlackLevel = save1 + (0x00c4 << 1); + break; + + // 1DmkIII / 1DSmkIII / 1DmkIV / 5DmkII + // 7D / 40D / 50D / 60D / 450D / 500D + // 550D / 1000D / 1100D + case 674: + case 692: + case 702: + case 1227: + case 1250: + case 1251: + case 1337: + case 1338: + case 1346: + // imCanon.ColorDataVer = 4; + imCanon.ColorDataSubVer = get2(); + + fseek(ifp, save1 + (0x003f << 1), SEEK_SET); + FORC4 cam_mul[c ^ (c >> 1)] = (float)get2(); + // fseek(ifp, save1 + (0x0044 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0049 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = get2(); + + fseek(ifp, save1 + (0x004e << 1), SEEK_SET); + FORC4 sraw_mul[c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0053 << 1), SEEK_SET); + // Canon_WBpresets(2, 12); + // fseek(ifp, save1 + (0x00a8 << 1), SEEK_SET); + // Canon_WBCTpresets(0); // BCAT + + if ((imCanon.ColorDataSubVer == 4) || + (imCanon.ColorDataSubVer == 5)) + { + offsetChannelBlackLevel = save1 + (0x02b4 << 1); + offsetWhiteLevels = save1 + (0x02b8 << 1); } + else if ((imCanon.ColorDataSubVer == 6) || + (imCanon.ColorDataSubVer == 7)) + { + offsetChannelBlackLevel = save1 + (0x02cb << 1); + offsetWhiteLevels = save1 + (0x02cf << 1); + } + else if (imCanon.ColorDataSubVer == 9) + { + offsetChannelBlackLevel = save1 + (0x02cf << 1); + offsetWhiteLevels = save1 + (0x02d3 << 1); + } + else + offsetChannelBlackLevel = save1 + (0x00e7 << 1); + break; + + case 5120: // PowerShot G10, G12, G5 X, G7 X, G9 X, EOS M3, EOS M5, EOS M6 + // imCanon.ColorDataVer = 5; + imCanon.ColorDataSubVer = get2(); + + fseek(ifp, save1 + (0x0047 << 1), SEEK_SET); + FORC4 cam_mul[c ^ (c >> 1)] = (float)get2(); + + if (imCanon.ColorDataSubVer == 0xfffc) + { // -4: G7 X Mark II, G9 X Mark II, G1 X Mark III, M5, M100, M6 + // fseek(ifp, save1 + (0x004f << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + // fseek(ifp, 8, SEEK_CUR); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = + // get2(); + // fseek(ifp, 8, SEEK_CUR); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Other][c ^ (c >> 1)] = get2(); + // fseek(ifp, 8, SEEK_CUR); + // Canon_WBpresets(8, 24); + // fseek(ifp, 168, SEEK_CUR); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][c ^ (c >> 1)] = get2(); + // fseek(ifp, 24, SEEK_CUR); + // Canon_WBCTpresets(2); // BCADT + offsetChannelBlackLevel = save1 + (0x014d << 1); + offsetWhiteLevels = save1 + (0x0569 << 1); + } + else if (imCanon.ColorDataSubVer == 0xfffd) + { // -3: M10/M3/G1 X/G1 X II/G10/G11/G12/G15/G16/G3 X/G5 X/G7 X/G9 + // X/S100/S110/S120/S90/S95/SX1 IX/SX50 HS/SX60 HS + // fseek(ifp, save1 + (0x004c << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + // get2(); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = + // get2(); + // get2(); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Other][c ^ (c >> 1)] = get2(); + // get2(); + // Canon_WBpresets(2, 12); + // fseek(ifp, save1 + (0x00ba << 1), SEEK_SET); + // Canon_WBCTpresets(2); // BCADT + offsetChannelBlackLevel = save1 + (0x0108 << 1); + } + break; + + case 1273: + case 1275: + // imCanon.ColorDataVer = 6; // 600D / 1200D + imCanon.ColorDataSubVer = get2(); + + fseek(ifp, save1 + (0x003f << 1), SEEK_SET); + FORC4 cam_mul[c ^ (c >> 1)] = (float)get2(); + // fseek(ifp, save1 + (0x0044 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0049 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = get2(); + + fseek(ifp, save1 + (0x0062 << 1), SEEK_SET); + FORC4 sraw_mul[c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0067 << 1), SEEK_SET); + // Canon_WBpresets(2, 12); + // fseek(ifp, save1 + (0x00bc << 1), SEEK_SET); + // Canon_WBCTpresets(0); // BCAT + offsetChannelBlackLevel = save1 + (0x01df << 1); + offsetWhiteLevels = save1 + (0x01e3 << 1); + break; + + // 1DX / 5DmkIII / 6D / 100D / 650D / 700D / EOS M / 7DmkII / 750D / 760D + case 1312: + case 1313: + case 1316: + case 1506: + // imCanon.ColorDataVer = 7; + imCanon.ColorDataSubVer = get2(); + + fseek(ifp, save1 + (0x003f << 1), SEEK_SET); + FORC4 cam_mul[c ^ (c >> 1)] = (float)get2(); + // fseek(ifp, save1 + (0x0044 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0049 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = get2(); + + fseek(ifp, save1 + (0x007b << 1), SEEK_SET); + FORC4 sraw_mul[c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0080 << 1), SEEK_SET); + // Canon_WBpresets(2, 12); + // fseek(ifp, save1 + (0x00d5 << 1), SEEK_SET); + // Canon_WBCTpresets(0); // BCAT + + if (imCanon.ColorDataSubVer == 10) + { + offsetChannelBlackLevel = save1 + (0x01f8 << 1); + offsetWhiteLevels = save1 + (0x01fc << 1); + } + else if (imCanon.ColorDataSubVer == 11) + { + offsetChannelBlackLevel = save1 + (0x02d8 << 1); + offsetWhiteLevels = save1 + (0x02dc << 1); + } + break; + + // 5DS / 5DS R / 80D / 1300D / 1500D / 3000D / 5D4 / 800D / 77D / 6D II / + // 200D + case 1560: + case 1592: + case 1353: + case 1602: + // imCanon.ColorDataVer = 8; + imCanon.ColorDataSubVer = get2(); + + fseek(ifp, save1 + (0x003f << 1), SEEK_SET); + FORC4 cam_mul[c ^ (c >> 1)] = (float)get2(); + // fseek(ifp, save1 + (0x0044 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0049 << 1), SEEK_SET); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = get2(); + + fseek(ifp, save1 + (0x0080 << 1), SEEK_SET); + FORC4 sraw_mul[c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0085 << 1), SEEK_SET); + // Canon_WBpresets(2, 12); + // fseek(ifp, save1 + (0x0107 << 1), SEEK_SET); + // Canon_WBCTpresets(0); // BCAT + + if (imCanon.ColorDataSubVer == 14) + { // 1300D / 1500D / 3000D + offsetChannelBlackLevel = save1 + (0x022c << 1); + offsetWhiteLevels = save1 + (0x0230 << 1); + } + else + { + offsetChannelBlackLevel = save1 + (0x030a << 1); + offsetWhiteLevels = save1 + (0x030e << 1); + } + break; + + case 1820: // M50, ColorDataSubVer 16 + case 1824: // EOS R, SX740HS, ColorDataSubVer 17 + case 1816: // EOS RP, SX70HS, ColorDataSubVer 18; + // EOS M6 Mark II, EOS 90D, G7XmkIII, ColorDataSubVer 19 + // imCanon.ColorDataVer = 9; + imCanon.ColorDataSubVer = get2(); + + fseek(ifp, save1 + (0x0047 << 1), SEEK_SET); + FORC4 cam_mul[c ^ (c >> 1)] = (float)get2(); + // get2(); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + // get2(); + // FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = get2(); + // fseek(ifp, save1 + (0x0088 << 1), SEEK_SET); + // Canon_WBpresets(2, 12); + // fseek(ifp, save1 + (0x010a << 1), SEEK_SET); + // Canon_WBCTpresets(0); + offsetChannelBlackLevel = save1 + (0x0318 << 1); + offsetChannelBlackLevel2 = save1 + (0x0149 << 1); + offsetWhiteLevels = save1 + (0x031c << 1); + break; } - if (tag == 0x4021 && get4() && get4()) + + if (offsetChannelBlackLevel) + { + fseek(ifp, offsetChannelBlackLevel, SEEK_SET); + FORC4 + bls += (cblack/*imCanon.ChannelBlackLevel*/[c ^ (c >> 1)] = get2()); + imCanon.AverageBlackLevel = bls / 4; + // RT_blacklevel_from_constant = ThreeValBool::F; + } + if (offsetWhiteLevels) + { + if ((offsetWhiteLevels - offsetChannelBlackLevel) != 8L) + fseek(ifp, offsetWhiteLevels, SEEK_SET); + imCanon.NormalWhiteLevel = get2(); + imCanon.SpecularWhiteLevel = get2(); + // FORC4 + // imgdata.color.linear_max[c] = imCanon.SpecularWhiteLevel; + maximum = imCanon.SpecularWhiteLevel; + // RT_whitelevel_from_constant = ThreeValBool::F; + } + + if(!imCanon.AverageBlackLevel && offsetChannelBlackLevel2) + { + fseek(ifp, offsetChannelBlackLevel2, SEEK_SET); + FORC4 + bls += (cblack/*imCanon.ChannelBlackLevel*/[c ^ (c >> 1)] = get2()); + imCanon.AverageBlackLevel = bls / 4; + // RT_blacklevel_from_constant = ThreeValBool::F; + } + fseek(ifp, save1, SEEK_SET); + + //--------------------------------------------------------------------- + } if (tag == 0x4021 && get4() && get4()) FORC4 cam_mul[c] = 1024; if (tag == 0xa021) FORC4 cam_mul[c ^ (c >> 1)] = get4(); @@ -6549,6 +6801,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); @@ -6740,7 +7017,8 @@ int CLASS parse_tiff (int base) void CLASS apply_tiff() { - int max_samp=0, ties=0, os, ns, raw=-1, thm=-1, i; + int max_samp=0, ties=0, /*os, ns,*/ raw=-1, thm=-1, i; + uint64_t os, ns; // RT struct jhead jh; thumb_misc = 16; @@ -6770,6 +7048,7 @@ void CLASS apply_tiff() } if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) && (tiff_ifd[i].width | tiff_ifd[i].height) < 0x10000 && + (unsigned)tiff_ifd[i].bps < 33 && (unsigned)tiff_ifd[i].samples < 13 && // RT ns && ((ns > os && (ties = 1)) || (ns == os && shot_select == ties++))) { raw_width = tiff_ifd[i].width; @@ -6837,7 +7116,7 @@ void CLASS apply_tiff() load_raw = &CLASS olympus_load_raw; // ------- RT ------- if (!strncmp(make,"SONY",4) && - !strncmp(model,"ILCE-7RM3",9) && + (!strncmp(model,"ILCE-7RM3",9) || !strncmp(model,"ILCE-7RM4",9)) && tiff_samples == 4 && tiff_ifd[raw].bytes == raw_width*raw_height*tiff_samples*2) { load_raw = &CLASS sony_arq_load_raw; @@ -9233,8 +9512,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) { @@ -9370,6 +9649,11 @@ void CLASS identify() parse_foveon(); else if (!memcmp (head,"CI",2)) parse_cine(); + //--- RT ---------------------------------------------------------------- + else if (!memcmp(head + 4, "ftypcrx ", 8)) { + parse_canon_cr3(); + } + //------------------------------------------------------------------------- if (make[0] == 0) for (zero_fsize=i=0; i < sizeof table / sizeof *table; i++) if (fsize == table[i].fsize) { @@ -9582,6 +9866,7 @@ void CLASS identify() filters = 0; tiff_samples = colors = 3; load_raw = &CLASS canon_sraw_load_raw; + FORC4 cblack[c] = 0; // ALB } else if (!strcmp(model,"PowerShot 600")) { height = 613; width = 854; @@ -10729,15 +11014,12 @@ void CLASS nikon_14bit_load_raw() free(buf); } -//----------------------------------------------------------------------------- - /* RT: Delete from here */ /*RT*/#undef SQR /*RT*/#undef MAX /*RT*/#undef MIN /*RT*/#undef ABS /*RT*/#undef LIM -/*RT*/#undef ULIM /*RT*/#undef CLIP #ifdef __GNUC__ #pragma GCC diagnostic pop diff --git a/rtengine/dcraw.h b/rtengine/dcraw.h index 81da41718..89c1fcaff 100644 --- a/rtengine/dcraw.h +++ b/rtengine/dcraw.h @@ -14,11 +14,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 . */ -#ifndef DCRAW_H -#define DCRAW_H +#pragma once #include "myfile.h" #include @@ -69,6 +68,7 @@ public: gamm[0]=0.45;gamm[1]=4.5;gamm[2]=gamm[3]=gamm[4]=gamm[5]=0; user_mul[0]=user_mul[1]=user_mul[2]=user_mul[3]=0; greybox[0]=greybox[1]=0; greybox[2]=greybox[3]= UINT_MAX; + RT_canon_CR3_data.CR3_CTMDtag = 0; } protected: @@ -165,11 +165,39 @@ protected: PanasonicRW2Info(): bpp(0), encoding(0) {} }; PanasonicRW2Info RT_pana_info; +public: + struct CanonCR3Data { + // contents of tag CMP1 for relevant track in CR3 file + struct crx_data_header_t { + int32_t version; + int32_t f_width; + int32_t f_height; + int32_t tileWidth; + int32_t tileHeight; + int32_t nBits; + int32_t nPlanes; + int32_t cfaLayout; + int32_t encType; + int32_t imageLevels; + int32_t hasTileCols; + int32_t hasTileRows; + int32_t mdatHdrSize; + // Not from header, but from datastream + uint32_t MediaSize; + int64_t MediaOffset; + uint32_t MediaType; /* 1 -> /C/RAW, 2-> JPEG */ + }; + static constexpr size_t CRXTRACKS_MAXCOUNT = 16; + crx_data_header_t crx_header[CRXTRACKS_MAXCOUNT]; + unsigned int crx_track_selected; + short CR3_CTMDtag; + }; +protected: + CanonCR3Data RT_canon_CR3_data; float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4]; - int histogram[4][0x2000]; - void (DCraw::*write_thumb)(), (DCraw::*write_fun)(); + void (DCraw::*write_thumb)(); void (DCraw::*load_raw)(), (DCraw::*thumb_load_raw)(); jmp_buf failure; @@ -413,6 +441,9 @@ private: unsigned encoding; }; +void panasonicC6_load_raw(); +void panasonicC7_load_raw(); + void canon_rmf_load_raw(); void panasonic_load_raw(); void olympus_load_raw(); @@ -528,7 +559,20 @@ void shiftXtransMatrix( const int offsy, const int offsx) { void nikon_14bit_load_raw(); // ported from LibRaw +//----------------------------------------------------------------------------- +// Canon CR3 support ported from LibRaw +//----------------------------------------------------------------------------- +void parse_canon_cr3(); +void selectCRXTrack(unsigned short maxTrack); +int parseCR3(unsigned long long oAtomList, + unsigned long long szAtomList, short &nesting, + char *AtomNameStack, unsigned short &nTrack, short &TrackType); +bool crxDecodePlane(void *p, uint32_t planeNumber); +void crxLoadDecodeLoop(void *img, int nPlanes); +void crxConvertPlaneLineDf(void *p, int imageRow); +void crxLoadFinalizeLoopE3(void *p, int planeHeight); +void crxLoadRaw(); +bool crxParseImageHeader(uchar *cmp1TagData, unsigned int nTrack); +//----------------------------------------------------------------------------- + }; - - -#endif //DCRAW_H diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 751bf1892..3de2f5e67 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -15,22 +15,21 @@ * GNU General Public License for more details. * * 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 "cieimage.h" #include "curves.h" +#include "dcp.h" #include "dcrop.h" +#include "image8.h" +#include "imagefloat.h" +#include "improccoordinator.h" +#include "labimage.h" #include "mytime.h" #include "procparams.h" #include "refreshmap.h" #include "rt_math.h" -#include -#include -#include -#include - -//#include -// "ceil" rounding -//#define SKIPS(a,b) ((a) / (b) + ((a) % (b) > 0)) #include "../rtgui/editcallbacks.h" #pragma GCC diagnostic warning "-Wall" @@ -50,10 +49,8 @@ constexpr T skips(T a, T b) namespace rtengine { -extern const Settings* settings; - Crop::Crop(ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow) - : PipetteBuffer(editDataProvider), origCrop(nullptr), laboCrop(nullptr), labnCrop(nullptr), reservCrop(nullptr), + : PipetteBuffer(editDataProvider), origCrop(nullptr), laboCrop(nullptr), labnCrop(nullptr), reservCrop(nullptr), lastorigCrop(nullptr), cropImg(nullptr), shbuf_real(nullptr), transCrop(nullptr), cieCrop(nullptr), shbuffer(nullptr), updating(false), newUpdatePending(false), skip(10), cropx(0), cropy(0), cropw(-1), croph(-1), @@ -178,8 +175,6 @@ void Crop::update(int todo) int widIm = parent->fw;//full image int heiIm = parent->fh; - bool needstransform = parent->ipf.needsTransform(); - if (todo & (M_INIT | M_LINDENOISE | M_HDR)) { MyMutex::MyLock lock(parent->minit); // Also used in improccoord @@ -200,24 +195,12 @@ void Crop::update(int todo) params.dirpyrDenoise.getCurves(noiseLCurve, noiseCCurve); - int tilesize; - int overlap; - - if (settings->leveldnti == 0) { - tilesize = 1024; - overlap = 128; - } - - if (settings->leveldnti == 1) { - tilesize = 768; - overlap = 96; - } + const int tilesize = settings->leveldnti == 0 ? 1024 : 768; + const int overlap = settings->leveldnti == 0 ? 128 : 96; 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]; @@ -663,10 +646,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); @@ -754,7 +736,7 @@ void Crop::update(int todo) if (need_fattal) { parent->ipf.dehaze(f, params.dehaze); - parent->ipf.ToneMapFattal02(f); + parent->ipf.ToneMapFattal02(f, params.fattal, 3, 0, nullptr, 0, 0, 0); } // crop back to the size expected by the rest of the pipeline @@ -784,8 +766,9 @@ void Crop::update(int todo) } } + const bool needstransform = parent->ipf.needsTransform(skips(parent->fw, skip), skips(parent->fh, skip), parent->imgsrc->getRotateDegree(), parent->imgsrc->getMetaData()); // transform - if (needstransform || ((todo & (M_TRANSFORM | M_RGBCURVE)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled)) { + if (needstransform || ((todo & (M_TRANSFORM | M_RGBCURVE)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled)) { if (!transCrop) { transCrop = new Imagefloat(cropw, croph); } @@ -802,10 +785,7 @@ void Crop::update(int todo) baseCrop = transCrop; } } else { - if (transCrop) { - delete transCrop; - } - + delete transCrop; transCrop = nullptr; } @@ -837,7 +817,7 @@ void Crop::update(int todo) } } double rrm, ggm, bbm; - DCPProfile::ApplyState as; + DCPProfileApplyState as; DCPProfile *dcpProf = parent->imgsrc->getDCP(params.icm, as); LUTu histToneCurve; @@ -873,6 +853,7 @@ void Crop::update(int todo) //I made a little change here. Rather than have luminanceCurve (and others) use in/out lab images, we can do more if we copy right here. labnCrop->CopyFrom(laboCrop); reservCrop->CopyFrom(laboCrop); + lastorigCrop->CopyFrom(laboCrop); //parent->ipf.luminanceCurve (labnCrop, labnCrop, parent->lumacurve); @@ -885,10 +866,34 @@ void Crop::update(int todo) bool locallutili = parent->locallutili; LUTf lllocalcurve2(65536, 0); + bool localclutili = parent->localclutili; + LUTf cllocalcurve2(65536, 0); + bool locallcutili = parent->locallcutili; + LUTf lclocalcurve2(65536, 0); bool localcutili = parent->locallutili; LUTf cclocalcurve2(65536, 0); + bool localrgbutili = parent->localrgbutili; + LUTf rgblocalcurve2(65536, 0); bool localexutili = parent->localexutili; LUTf exlocalcurve2(65536, 0); + bool localmaskutili = parent->localmaskutili; + bool localmaskexputili = parent->localmaskexputili; + bool localmaskSHutili = parent->localmaskSHutili; + bool localmaskvibutili = parent->localmaskvibutili; + bool localmasktmutili = parent->localmasktmutili; + bool localmaskretiutili = parent->localmaskretiutili; + bool localmaskcbutili = parent->localmaskcbutili; + bool localmaskblutili = parent->localmaskblutili; + bool localmasklcutili = parent->localmasklcutili; + LUTf lmasklocalcurve2(65536, 0); + LUTf lmaskexplocalcurve2(65536, 0); + LUTf lmaskSHlocalcurve2(65536, 0); + LUTf lmaskviblocalcurve2(65536, 0); + LUTf lmasktmlocalcurve2(65536, 0); + LUTf lmaskretilocalcurve2(65536, 0); + LUTf lmaskcblocalcurve2(65536, 0); + LUTf lmaskbllocalcurve2(65536, 0); + LUTf lmasklclocalcurve2(65536, 0); LUTf hltonecurveloc2(65536, 0); //65536 LUTf shtonecurveloc2(65536, 0); LUTf tonecurveloc2(65536, 0); @@ -897,6 +902,7 @@ void Crop::update(int todo) bool HHutili = parent->HHutili; bool llmasutili = parent->llmasutili; bool lhmasutili = parent->lhmasutili; + bool lhhmasutili = parent->lhhmasutili; bool lcmasutili = parent->lcmasutili; bool lhmasexputili = parent->lhmasexputili; bool lcmasexputili = parent->lcmasexputili; @@ -904,6 +910,12 @@ void Crop::update(int todo) bool lhmasSHutili = parent->lhmasSHutili; bool lcmasSHutili = parent->lcmasSHutili; bool llmasSHutili = parent->llmasSHutili; + bool lhmasvibutili = parent->lhmasvibutili; + bool lcmasvibutili = parent->lcmasvibutili; + bool llmasvibutili = parent->llmasvibutili; + bool lhmaslcutili = parent->lhmaslcutili; + bool lcmaslcutili = parent->lcmaslcutili; + bool llmaslcutili = parent->llmaslcutili; bool lhmascbutili = parent->lhmascbutili; bool lcmascbutili = parent->lcmascbutili; bool llmascbutili = parent->llmascbutili; @@ -913,32 +925,64 @@ void Crop::update(int todo) bool lhmastmutili = parent->lhmastmutili; bool lcmastmutili = parent->lcmastmutili; bool llmastmutili = parent->llmastmutili; - + bool lhmasblutili = parent->lhmasblutili; + bool lcmasblutili = parent->lcmasblutili; + bool llmasblutili = parent->llmasblutili; + bool locwavutili = parent->locwavutili; + bool locwavdenutili = parent->locwavdenutili; + bool loclevwavutili = parent->loclevwavutili; + bool locconwavutili = parent->locconwavutili; + bool loccompwavutili = parent->loccompwavutili; + bool loccomprewavutili = parent->loccomprewavutili; + bool locedgwavutili = parent->locedgwavutili; + bool lmasutiliblwav = parent->lmasutiliblwav; + bool lmasutilicolwav = parent->lmasutilicolwav; + // float avg = parent->avg; LUTu dummy; bool needslocal = params.locallab.enabled; LocretigainCurve locRETgainCurve; + LocretitransCurve locRETtransCurve; LocLHCurve loclhCurve; LocHHCurve lochhCurve; LocCCmaskCurve locccmasCurve; LocLLmaskCurve locllmasCurve; LocHHmaskCurve lochhmasCurve; - LocCCmaskexpCurve locccmasexpCurve; - LocLLmaskexpCurve locllmasexpCurve; - LocHHmaskexpCurve lochhmasexpCurve; - LocCCmaskSHCurve locccmasSHCurve; - LocLLmaskSHCurve locllmasSHCurve; - LocHHmaskSHCurve lochhmasSHCurve; - LocCCmaskcbCurve locccmascbCurve; - LocLLmaskcbCurve locllmascbCurve; - LocHHmaskcbCurve lochhmascbCurve; - LocCCmaskretiCurve locccmasretiCurve; - LocLLmaskretiCurve locllmasretiCurve; - LocHHmaskretiCurve lochhmasretiCurve; - LocCCmasktmCurve locccmastmCurve; - LocLLmasktmCurve locllmastmCurve; - LocHHmasktmCurve lochhmastmCurve; + LocHHmaskCurve lochhhmasCurve; + LocCCmaskCurve locccmasexpCurve; + LocLLmaskCurve locllmasexpCurve; + LocHHmaskCurve lochhmasexpCurve; + LocCCmaskCurve locccmasSHCurve; + LocLLmaskCurve locllmasSHCurve; + LocHHmaskCurve lochhmasSHCurve; + // LocHHmaskCurve lochhhmasSHCurve; + LocCCmaskCurve locccmasvibCurve; + LocLLmaskCurve locllmasvibCurve; + LocHHmaskCurve lochhmasvibCurve; + LocCCmaskCurve locccmaslcCurve; + LocLLmaskCurve locllmaslcCurve; + LocHHmaskCurve lochhmaslcCurve; + LocCCmaskCurve locccmascbCurve; + LocLLmaskCurve locllmascbCurve; + LocHHmaskCurve lochhmascbCurve; + LocCCmaskCurve locccmasretiCurve; + LocLLmaskCurve locllmasretiCurve; + LocHHmaskCurve lochhmasretiCurve; + LocCCmaskCurve locccmastmCurve; + LocLLmaskCurve locllmastmCurve; + LocHHmaskCurve lochhmastmCurve; + LocCCmaskCurve locccmasblCurve; + LocLLmaskCurve locllmasblCurve; + LocHHmaskCurve lochhmasblCurve; LocwavCurve locwavCurve; + LocwavCurve loclmasCurveblwav; + LocwavCurve loclmasCurvecolwav; + LocwavCurve loclevwavCurve; + LocwavCurve locconwavCurve; + LocwavCurve loccompwavCurve; + LocwavCurve loccomprewavCurve; + LocwavCurve locedgwavCurve; + LocwavCurve locwavCurveden; LocretigainCurverab locRETgainCurverab; locallutili = false; @@ -950,17 +994,22 @@ void Crop::update(int todo) if (needslocal) { for (int sp = 0; sp < (int)params.locallab.spots.size(); sp++) { locRETgainCurve.Set(params.locallab.spots.at(sp).localTgaincurve); + locRETtransCurve.Set(params.locallab.spots.at(sp).localTtranscurve); loclhCurve.Set(params.locallab.spots.at(sp).LHcurve, LHutili); lochhCurve.Set(params.locallab.spots.at(sp).HHcurve, HHutili); locccmasCurve.Set(params.locallab.spots.at(sp).CCmaskcurve, lcmasutili); locllmasCurve.Set(params.locallab.spots.at(sp).LLmaskcurve, llmasutili); lochhmasCurve.Set(params.locallab.spots.at(sp).HHmaskcurve, lhmasutili); + lochhhmasCurve.Set(params.locallab.spots.at(sp).HHhmaskcurve, lhhmasutili); locccmasexpCurve.Set(params.locallab.spots.at(sp).CCmaskexpcurve, lcmasexputili); locllmasexpCurve.Set(params.locallab.spots.at(sp).LLmaskexpcurve, llmasexputili); lochhmasexpCurve.Set(params.locallab.spots.at(sp).HHmaskexpcurve, lhmasexputili); locccmasSHCurve.Set(params.locallab.spots.at(sp).CCmaskSHcurve, lcmasSHutili); locllmasSHCurve.Set(params.locallab.spots.at(sp).LLmaskSHcurve, llmasSHutili); lochhmasSHCurve.Set(params.locallab.spots.at(sp).HHmaskSHcurve, lhmasSHutili); + locccmasvibCurve.Set(params.locallab.spots.at(sp).CCmaskvibcurve, lcmasvibutili); + locllmasvibCurve.Set(params.locallab.spots.at(sp).LLmaskvibcurve, llmasvibutili); + lochhmasvibCurve.Set(params.locallab.spots.at(sp).HHmaskvibcurve, lhmasvibutili); locccmascbCurve.Set(params.locallab.spots.at(sp).CCmaskcbcurve, lcmascbutili); locllmascbCurve.Set(params.locallab.spots.at(sp).LLmaskcbcurve, llmascbutili); lochhmascbCurve.Set(params.locallab.spots.at(sp).HHmaskcbcurve, lhmascbutili); @@ -970,12 +1019,50 @@ void Crop::update(int todo) locccmastmCurve.Set(params.locallab.spots.at(sp).CCmasktmcurve, lcmastmutili); locllmastmCurve.Set(params.locallab.spots.at(sp).LLmasktmcurve, llmastmutili); lochhmastmCurve.Set(params.locallab.spots.at(sp).HHmasktmcurve, lhmastmutili); - locwavCurve.Set(params.locallab.spots.at(sp).locwavcurve); + locccmasblCurve.Set(params.locallab.spots.at(sp).CCmaskblcurve, lcmasblutili); + locllmasblCurve.Set(params.locallab.spots.at(sp).LLmaskblcurve, llmasblutili); + lochhmasblCurve.Set(params.locallab.spots.at(sp).HHmaskblcurve, lhmasblutili); + loclmasCurveblwav.Set(params.locallab.spots.at(sp).LLmaskblcurvewav, lmasutiliblwav); + loclmasCurvecolwav.Set(params.locallab.spots.at(sp).LLmaskcolcurvewav, lmasutilicolwav); + locccmaslcCurve.Set(params.locallab.spots.at(sp).CCmasklccurve, lcmaslcutili); + locllmaslcCurve.Set(params.locallab.spots.at(sp).LLmasklccurve, llmaslcutili); + lochhmaslcCurve.Set(params.locallab.spots.at(sp).HHmasklccurve, lhmaslcutili); + + locwavCurve.Set(params.locallab.spots.at(sp).locwavcurve, locwavutili); + locwavCurveden.Set(params.locallab.spots.at(sp).locwavcurveden, locwavdenutili); + loclevwavCurve.Set(params.locallab.spots.at(sp).loclevwavcurve, loclevwavutili); + locconwavCurve.Set(params.locallab.spots.at(sp).locconwavcurve, locconwavutili); + loccompwavCurve.Set(params.locallab.spots.at(sp).loccompwavcurve, loccompwavutili); + loccomprewavCurve.Set(params.locallab.spots.at(sp).loccomprewavcurve, loccomprewavutili); + locedgwavCurve.Set(params.locallab.spots.at(sp).locedgwavcurve, locedgwavutili); locallutili = false; CurveFactory::curveLocal(locallutili, params.locallab.spots.at(sp).llcurve, lllocalcurve2, sca); + localclutili = false; + CurveFactory::curveLocal(localclutili, params.locallab.spots.at(sp).clcurve, cllocalcurve2, sca); + locallcutili = false; + CurveFactory::curveLocal(locallcutili, params.locallab.spots.at(sp).lccurve, lclocalcurve2, sca); + localrgbutili = false; + CurveFactory::curveLocal(localrgbutili, params.locallab.spots.at(sp).rgbcurve, rgblocalcurve2, sca); localcutili = false; CurveFactory::curveCCLocal(localcutili, params.locallab.spots.at(sp).cccurve, cclocalcurve2, sca); + localexutili = false; CurveFactory::curveexLocal(localexutili, params.locallab.spots.at(sp).excurve, exlocalcurve2, sca); + localmaskutili = false; + CurveFactory::curvemaskLocal(localmaskutili, params.locallab.spots.at(sp).Lmaskcurve, lmasklocalcurve2, sca); + localmaskexputili = false; + CurveFactory::curvemaskLocal(localmaskexputili, params.locallab.spots.at(sp).Lmaskexpcurve, lmaskexplocalcurve2, sca); + localmaskSHutili = false; + CurveFactory::curvemaskLocal(localmaskSHutili, params.locallab.spots.at(sp).LmaskSHcurve, lmaskSHlocalcurve2, sca); + localmaskvibutili = false; + CurveFactory::curvemaskLocal(localmaskvibutili, params.locallab.spots.at(sp).Lmaskvibcurve, lmaskviblocalcurve2, sca); + localmasktmutili = false; + CurveFactory::curvemaskLocal(localmasktmutili, params.locallab.spots.at(sp).Lmasktmcurve, lmasktmlocalcurve2, sca); + localmaskretiutili = false; + CurveFactory::curvemaskLocal(localmaskretiutili, params.locallab.spots.at(sp).Lmaskreticurve, lmaskretilocalcurve2, sca); + localmaskcbutili = false; + CurveFactory::curvemaskLocal(localmaskcbutili, params.locallab.spots.at(sp).Lmaskcbcurve, lmaskcblocalcurve2, sca); + localmasklcutili = false; + CurveFactory::curvemaskLocal(localmasklcutili, params.locallab.spots.at(sp).Lmasklccurve, lmasklclocalcurve2, sca); double ecomp = params.locallab.spots.at(sp).expcomp; @@ -984,9 +1071,13 @@ void Crop::update(int todo) double hlcomprthresh = params.locallab.spots.at(sp).hlcomprthresh; double shcompr = params.locallab.spots.at(sp).shcompr; double br = params.locallab.spots.at(sp).lightness; + if(black < 0. && params.locallab.spots.at(sp).expMethod == "pde" ) { + black *= 1.5; + } double cont = params.locallab.spots.at(sp).contrast; double huere, chromare, lumare, huerefblu, chromarefblu, lumarefblu, sobelre; + int lastsav; float avge; huerefblu = parent->huerefblurs[sp]; chromarefblu = parent->chromarefblurs[sp]; @@ -996,48 +1087,131 @@ void Crop::update(int todo) lumare = parent->lumarefs[sp]; sobelre = parent->sobelrefs[sp]; avge = parent->avgs[sp]; + + lastsav = parent->lastsavrests[sp]; + + float minCD; + float maxCD; + float mini; + float maxi; + float Tmean; + float Tsigma; + float Tmin; + float Tmax; CurveFactory::complexCurvelocal(ecomp, black / 65535., hlcompr, hlcomprthresh, shcompr, br, cont, lumare, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, avge, sca); // Locallab mask are only shown for selected spot if (sp == params.locallab.selspot) { - parent->ipf.Lab_Local(1, sp, (float**)shbuffer, labnCrop, labnCrop, reservCrop, cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, lllocalcurve2,locallutili, - loclhCurve, lochhCurve, locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, - locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, - locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, - locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, - locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, - locwavCurve, - LHutili, HHutili, cclocalcurve2, localcutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, parent->locallColorMask, parent->locallExpMask, parent->locallSHMask, parent->locallcbMask, parent->locallretiMask, parent->locallsoftMask, parent->localltmMask); + parent->ipf.Lab_Local(1, sp, (float**)shbuffer, labnCrop, labnCrop, reservCrop, lastorigCrop, cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, locRETtransCurve, + lllocalcurve2,locallutili, + cllocalcurve2, localclutili, + lclocalcurve2, locallcutili, + loclhCurve, lochhCurve, + lmasklocalcurve2, localmaskutili, + lmaskexplocalcurve2, localmaskexputili, + lmaskSHlocalcurve2, localmaskSHutili, + lmaskviblocalcurve2, localmaskvibutili, + lmasktmlocalcurve2, localmasktmutili, + lmaskretilocalcurve2, localmaskretiutili, + lmaskcblocalcurve2, localmaskcbutili, + lmaskbllocalcurve2, localmaskblutili, + lmasklclocalcurve2, localmasklcutili, + locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, lochhhmasCurve, lhhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, + locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, + locccmasvibCurve, lcmasvibutili, locllmasvibCurve, llmasvibutili, lochhmasvibCurve, lhmasvibutili, + locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, + locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, + locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, + locccmasblCurve, lcmasblutili, locllmasblCurve, llmasblutili, lochhmasblCurve, lhmasblutili, + locccmaslcCurve, lcmaslcutili, locllmaslcCurve, llmaslcutili, lochhmaslcCurve, lhmaslcutili, + loclmasCurveblwav,lmasutiliblwav, + loclmasCurvecolwav,lmasutilicolwav, + locwavCurve, locwavutili, + loclevwavCurve, loclevwavutili, + locconwavCurve, locconwavutili, + loccompwavCurve, loccompwavutili, + loccomprewavCurve, loccomprewavutili, + locwavCurveden, locwavdenutili, + locedgwavCurve, locedgwavutili, + LHutili, HHutili, cclocalcurve2, localcutili, rgblocalcurve2, localrgbutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, + huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, lastsav, + parent->locallColorMask, parent->locallColorMaskinv, parent->locallExpMask, parent->locallExpMaskinv, parent->locallSHMask, parent->locallSHMaskinv, parent->locallvibMask, parent->localllcMask, parent->locallsharMask, parent->locallcbMask, parent->locallretiMask, parent->locallsoftMask, parent->localltmMask, parent->locallblMask, + minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax); } else { - parent->ipf.Lab_Local(1, sp, (float**)shbuffer, labnCrop, labnCrop, reservCrop, cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, lllocalcurve2,locallutili, - loclhCurve, lochhCurve, locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, - locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, - locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, - locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, - locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, - locwavCurve, - LHutili, HHutili, cclocalcurve2, localcutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, 0, 0, 0, 0, 0, 0, 0); + parent->ipf.Lab_Local(1, sp, (float**)shbuffer, labnCrop, labnCrop, reservCrop, lastorigCrop, cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, locRETtransCurve, + lllocalcurve2,locallutili, + cllocalcurve2, localclutili, + lclocalcurve2, locallcutili, + loclhCurve, lochhCurve, + lmasklocalcurve2, localmaskutili, + lmaskexplocalcurve2, localmaskexputili, + lmaskSHlocalcurve2, localmaskSHutili, + lmaskviblocalcurve2, localmaskvibutili, + lmasktmlocalcurve2, localmasktmutili, + lmaskretilocalcurve2, localmaskretiutili, + lmaskcblocalcurve2, localmaskcbutili, + lmaskbllocalcurve2, localmaskblutili, + lmasklclocalcurve2, localmasklcutili, + locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili,lochhhmasCurve, lhhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, + locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, + locccmasvibCurve, lcmasvibutili, locllmasvibCurve, llmasvibutili, lochhmasvibCurve, lhmasvibutili, + locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, + locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, + locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, + locccmasblCurve, lcmasblutili, locllmasblCurve, llmasblutili, lochhmasblCurve, lhmasblutili, + locccmaslcCurve, lcmaslcutili, locllmaslcCurve, llmaslcutili, lochhmaslcCurve, lhmaslcutili, + loclmasCurveblwav,lmasutiliblwav, + loclmasCurvecolwav,lmasutilicolwav, + locwavCurve, locwavutili, + loclevwavCurve, loclevwavutili, + locconwavCurve, locconwavutili, + loccompwavCurve, loccompwavutili, + loccomprewavCurve, loccomprewavutili, + locwavCurveden, locwavdenutili, + locedgwavCurve, locedgwavutili, + LHutili, HHutili, cclocalcurve2, localcutili, rgblocalcurve2, localrgbutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, + huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, lastsav, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax); } + + lastorigCrop->CopyFrom(labnCrop); + lllocalcurve2.clear(); + lclocalcurve2.clear(); + cllocalcurve2.clear(); lightCurveloc2.clear(); + rgblocalcurve2.clear(); cclocalcurve2.clear(); exlocalcurve2.clear(); + lmasklocalcurve2.clear(); + lmaskexplocalcurve2.clear(); + lmaskSHlocalcurve2.clear(); + lmaskviblocalcurve2.clear(); + lmasktmlocalcurve2.clear(); + lmaskretilocalcurve2.clear(); + lmaskcblocalcurve2.clear(); + lmaskbllocalcurve2.clear(); hltonecurveloc2.clear(); shtonecurveloc2.clear(); tonecurveloc2.clear(); locRETgainCurve.Reset(); + locRETtransCurve.Reset(); loclhCurve.Reset(); lochhCurve.Reset(); locccmasCurve.Reset(); locllmasCurve.Reset(); lochhmasCurve.Reset(); + lochhhmasCurve.Reset(); locllmasexpCurve.Reset(); locccmasexpCurve.Reset(); lochhmasexpCurve.Reset(); locllmasSHCurve.Reset(); locccmasSHCurve.Reset(); lochhmasSHCurve.Reset(); + locllmasvibCurve.Reset(); + locccmasvibCurve.Reset(); + lochhmasvibCurve.Reset(); locllmascbCurve.Reset(); locccmascbCurve.Reset(); lochhmascbCurve.Reset(); @@ -1047,9 +1221,22 @@ void Crop::update(int todo) locllmastmCurve.Reset(); locccmastmCurve.Reset(); lochhmastmCurve.Reset(); + locllmasblCurve.Reset(); + locccmasblCurve.Reset(); + lochhmasblCurve.Reset(); + locllmaslcCurve.Reset(); + locccmaslcCurve.Reset(); + lochhmaslcCurve.Reset(); + locwavCurve.Reset(); + loclevwavCurve.Reset(); + locconwavCurve.Reset(); + locconwavCurve.Reset(); + locwavCurveden.Reset(); + loclmasCurveblwav.Reset(); + loclmasCurvecolwav.Reset(); if (skip <= 2) { - usleep(settings->cropsleep); //wait to avoid crash when crop 100% and move window + Glib::usleep(settings->cropsleep); //wait to avoid crash when crop 100% and move window } } } @@ -1068,9 +1255,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); } @@ -1083,7 +1267,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))) { @@ -1092,74 +1275,75 @@ 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; @@ -1167,7 +1351,6 @@ void Crop::update(int todo) WavOpacityCurveWL waOpacityCurveWL; LUTf wavclCurve; - LUTu dummy; params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL); @@ -1285,6 +1468,11 @@ void Crop::freeAll() reservCrop = nullptr; } + if (lastorigCrop) { + delete lastorigCrop; + lastorigCrop = nullptr; + } + /* if (lablocCrop ) { delete lablocCrop; @@ -1377,41 +1565,42 @@ bool Crop::setCropSizes(int rcx, int rcy, int rcw, int rch, int skip, bool inter parent->ipf.transCoord(parent->fw, parent->fh, bx1, by1, bw, bh, orx, ory, orw, orh); - if (check_need_larger_crop_for_lcp_distortion(parent->fw, parent->fh, orx, ory, orw, orh, *parent->params)) { - // TODO - this is an estimate of the max distortion relative to the image size. ATM it is hardcoded to be 15%, which seems enough. If not, need to revise - int dW = int (double (parent->fw) * 0.15 / (2 * skip)); - int dH = int (double (parent->fh) * 0.15 / (2 * skip)); - int x1 = orx - dW; - int x2 = orx + orw + dW; - int y1 = ory - dH; - int y2 = ory + orh + dH; + if (parent->ipf.needsTransform(skips(parent->fw, skip), skips(parent->fh, skip), parent->imgsrc->getRotateDegree(), parent->imgsrc->getMetaData())) { + if (check_need_larger_crop_for_lcp_distortion(parent->fw, parent->fh, orx, ory, orw, orh, *parent->params)) { + // TODO - this is an estimate of the max distortion relative to the image size. ATM it is hardcoded to be 15%, which seems enough. If not, need to revise + int dW = int (double (parent->fw) * 0.15 / (2 * skip)); + int dH = int (double (parent->fh) * 0.15 / (2 * skip)); + int x1 = orx - dW; + int x2 = orx + orw + dW; + int y1 = ory - dH; + int y2 = ory + orh + dH; - if (x1 < 0) { - x2 += -x1; - x1 = 0; + if (x1 < 0) { + x2 += -x1; + x1 = 0; + } + + if (x2 > parent->fw) { + x1 -= x2 - parent->fw; + x2 = parent->fw; + } + + if (y1 < 0) { + y2 += -y1; + y1 = 0; + } + + if (y2 > parent->fh) { + y1 -= y2 - parent->fh; + y2 = parent->fh; + } + + orx = max(x1, 0); + ory = max(y1, 0); + orw = min(x2 - x1, parent->fw - orx); + orh = min(y2 - y1, parent->fh - ory); } - - if (x2 > parent->fw) { - x1 -= x2 - parent->fw; - x2 = parent->fw; - } - - if (y1 < 0) { - y2 += -y1; - y1 = 0; - } - - if (y2 > parent->fh) { - y1 -= y2 - parent->fh; - y2 = parent->fh; - } - - orx = max(x1, 0); - ory = max(y1, 0); - orw = min(x2 - x1, parent->fw - orx); - orh = min(y2 - y1, parent->fh - ory); } - leftBorder = skips(rqx1 - bx1, skip); upperBorder = skips(rqy1 - by1, skip); @@ -1471,6 +1660,11 @@ bool Crop::setCropSizes(int rcx, int rcy, int rcw, int rch, int skip, bool inter reservCrop = new LabImage(cropw, croph); + if (lastorigCrop) { + delete lastorigCrop; // labnCrop can't be resized + } + + lastorigCrop = new LabImage(cropw, croph); /* if (lablocCrop) { delete lablocCrop; // labnCrop can't be resized diff --git a/rtengine/dcrop.h b/rtengine/dcrop.h index bfd41e5ef..3f8a8ad6d 100644 --- a/rtengine/dcrop.h +++ b/rtengine/dcrop.h @@ -14,28 +14,25 @@ * GNU General Public License for more details. * * 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 "improccoordinator.h" #include "rtengine.h" -#include "improcfun.h" -#include "image8.h" -#include "image16.h" -#include "imagesource.h" -#include "procevents.h" #include "pipettebuffer.h" #include "../rtgui/threadutils.h" namespace rtengine { +class Image8; +class CieImage; + using namespace procparams; class ImProcCoordinator; -class Crop : public DetailedCrop, public PipetteBuffer +class Crop final : public DetailedCrop, public PipetteBuffer { protected: @@ -44,6 +41,7 @@ protected: LabImage* laboCrop; // "one chunk" allocation LabImage* labnCrop; // "one chunk" allocation LabImage* reservCrop; // "one chunk" allocation + LabImage* lastorigCrop; // "one chunk" allocation Image8* cropImg; // "one chunk" allocation ; displayed image in monitor color space, showing the output profile as well (soft-proofing enabled, which then correspond to workimg) or not float * shbuf_real; // "one chunk" allocation diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index dc12bc01a..538858a9a 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -14,20 +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 "rawimagesource.h" #include "rawimage.h" -#include "mytime.h" -#include "image8.h" #include "rt_math.h" #include "color.h" #include "../rtgui/multilangmgr.h" -#include "procparams.h" -#include "sleef.c" #include "opthelper.h" #include "median.h" //#define BENCHMARK @@ -41,176 +37,13 @@ using namespace std; namespace rtengine { -extern const Settings* settings; - -#undef ABS - -#define ABS(a) ((a)<0?-(a):(a)) -#define CLIREF(x) LIM(x,-200000.0f,200000.0f) // avoid overflow : do not act directly on image[] or pix[] -#define x1125(a) (a + xdivf(a, 3)) -#define x0875(a) (a - xdivf(a, 3)) -#define x0250(a) xdivf(a, 2) -#define x00625(a) xdivf(a, 4) -#define x0125(a) xdivf(a, 3) - #undef fc #define fc(row,col) \ (ri->get_filters() >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) #define FORCC for (unsigned int c=0; c < colors; c++) -/* - Patterned Pixel Grouping Interpolation by Alain Desbiolles -*/ -void RawImageSource::ppg_demosaic() -{ - int width = W, height = H; - int dir[5] = { 1, width, -1, -width, 1 }; - int row, col, diff[2] = {}, guess[2], c, d, i; - float (*pix)[4]; - - float (*image)[4]; - - if (plistener) { - // looks like ppg isn't supported anymore - //plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::ppg))); - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), M("GENERAL_NA"))); - plistener->setProgress (0.0); - } - - image = (float (*)[4]) calloc (H * W, sizeof * image); - - for (int ii = 0; ii < H; ii++) - for (int jj = 0; jj < W; jj++) { - image[ii * W + jj][fc(ii, jj)] = rawData[ii][jj]; - } - - border_interpolate(3, image); - - /* Fill in the green layer with gradients and pattern recognition: */ - for (row = 3; row < height - 3; row++) { - for (col = 3 + (FC(row, 3) & 1), c = FC(row, col); col < width - 3; col += 2) { - pix = image + row * width + col; - - for (i = 0; (d = dir[i]) > 0; i++) { - guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2 - - pix[-2 * d][c] - pix[2 * d][c]; - diff[i] = ( ABS(pix[-2 * d][c] - pix[ 0][c]) + - ABS(pix[ 2 * d][c] - pix[ 0][c]) + - ABS(pix[ -d][1] - pix[ d][1]) ) * 3 + - ( ABS(pix[ 3 * d][1] - pix[ d][1]) + - ABS(pix[-3 * d][1] - pix[-d][1]) ) * 2; - } - - d = dir[i = diff[0] > diff[1]]; - pix[0][1] = median(static_cast(guess[i] >> 2), pix[d][1], pix[-d][1]); - } - - if(plistener) { - plistener->setProgress(0.33 * row / (height - 3)); - } - } - - /* Calculate red and blue for each green pixel: */ - for (row = 1; row < height - 1; row++) { - for (col = 1 + (FC(row, 2) & 1), c = FC(row, col + 1); col < width - 1; col += 2) { - pix = image + row * width + col; - - for (i = 0; (d = dir[i]) > 0; c = 2 - c, i++) - pix[0][c] = CLIP(0.5 * (pix[-d][c] + pix[d][c] + 2 * pix[0][1] - - pix[-d][1] - pix[d][1]) ); - } - - if(plistener) { - plistener->setProgress(0.33 + 0.33 * row / (height - 1)); - } - } - - /* Calculate blue for red pixels and vice versa: */ - for (row = 1; row < height - 1; row++) { - for (col = 1 + (FC(row, 1) & 1), c = 2 - FC(row, col); col < width - 1; col += 2) { - pix = image + row * width + col; - - for (i = 0; (d = dir[i] + dir[i + 1]) > 0; i++) { - diff[i] = ABS(pix[-d][c] - pix[d][c]) + - ABS(pix[-d][1] - pix[0][1]) + - ABS(pix[ d][1] - pix[0][1]); - guess[i] = pix[-d][c] + pix[d][c] + 2 * pix[0][1] - - pix[-d][1] - pix[d][1]; - } - - if (diff[0] != diff[1]) { - pix[0][c] = CLIP(guess[diff[0] > diff[1]] / 2); - } else { - pix[0][c] = CLIP((guess[0] + guess[1]) / 4); - } - } - - if(plistener) { - plistener->setProgress(0.67 + 0.33 * row / (height - 1)); - } - } - - red(W, H); - - for (int i = 0; i < H; i++) - for (int j = 0; j < W; j++) { - red[i][j] = image[i * W + j][0]; - } - - green(W, H); - - for (int i = 0; i < H; i++) - for (int j = 0; j < W; j++) { - green[i][j] = image[i * W + j][1]; - } - - blue(W, H); - - for (int i = 0; i < H; i++) - for (int j = 0; j < W; j++) { - blue[i][j] = image[i * W + j][2]; - } - - free (image); -} - -void RawImageSource::border_interpolate(unsigned int border, float (*image)[4], unsigned int start, unsigned int end) -{ - unsigned row, col, y, x, f; - float sum[8]; - unsigned int width = W, height = H; - unsigned int colors = 3; - - if (end == 0 ) { - end = H; - } - - for (row = start; row < end; row++) - for (col = 0; col < width; col++) { - if (col == border && row >= border && row < height - border) { - col = width - border; - } - - memset (sum, 0, sizeof sum); - - for (y = row - 1; y != row + 2; y++) - for (x = col - 1; x != col + 2; x++) - if (y < height && x < width) { - f = fc(y, x); - sum[f] += image[y * width + x][f]; - sum[f + 4]++; - } - - f = fc(row, col); - - FORCC if (c != f && sum[c + 4]) { - image[row * width + col][c] = sum[c] / sum[c + 4]; - } - } -} - -void RawImageSource::border_interpolate2( int winw, int winh, int lborders, const array2D &rawData, array2D &red, array2D &green, array2D &blue) +void RawImageSource::border_interpolate( int winw, int winh, int lborders, const array2D &rawData, array2D &red, array2D &green, array2D &blue) { int bord = lborders; int width = winw; @@ -365,751 +198,6 @@ void RawImageSource::border_interpolate2( int winw, int winh, int lborders, cons } -// Joint Demosaicing and Denoising using High Order Interpolation Techniques -// Revision 0.9.1a - 09/02/2010 - Contact info: luis.sanz.rodriguez@gmail.com -// Copyright Luis Sanz Rodriguez 2010 -// Adapted to RawTherapee by Jacques Desmis 3/2013 - -void RawImageSource::jdl_interpolate_omp() // from "Lassus" -{ - int width = W, height = H; - int row, col, c, d, i, u = width, v = 2 * u, w = 3 * u, x = 4 * u, y = 5 * u, z = 6 * u, indx, (*dif)[2], (*chr)[2]; - float f[4], g[4]; - float (*image)[4]; - image = (float (*)[4]) calloc (width * height, sizeof * image); - dif = (int (*)[2]) calloc(width * height, sizeof * dif); - chr = (int (*)[2]) calloc(width * height, sizeof * chr); - - if (plistener) { - // this function seems to be unused - //plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::jdl))); - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), M("GENERAL_NA"))); - plistener->setProgress (0.0); - } - -#ifdef _OPENMP - #pragma omp parallel shared(image,width,height,u,w,v,y,x,z,dif,chr) private(row,col,f,g,indx,c,d,i) -#endif - { -#ifdef _OPENMP - #pragma omp for -#endif - - for (int ii = 0; ii < height; ii++) - for (int jj = 0; jj < width; jj++) { - image[ii * width + jj][fc(ii, jj)] = rawData[ii][jj]; - } - - border_interpolate(6, image); - -#ifdef _OPENMP - #pragma omp for -#endif - - for (row = 5; row < height - 5; row++) - for (col = 5 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col); col < u - 5; col += 2, indx += 2) { - f[0] = 1.f + abs(image[indx - u][1] - image[indx - w][1]) + abs(image[indx - u][1] - image[indx + u][1]) + abs(image[indx][c] - image[indx - v][c]) + abs(image[indx - v][c] - image[indx - x][c]); - f[1] = 1.f + abs(image[indx + 1][1] - image[indx + 3][1]) + abs(image[indx + 1][1] - image[indx - 1][1]) + abs(image[indx][c] - image[indx + 2][c]) + abs(image[indx + 2][c] - image[indx + 4][c]); - f[2] = 1.f + abs(image[indx - 1][1] - image[indx - 3][1]) + abs(image[indx - 1][1] - image[indx + 1][1]) + abs(image[indx][c] - image[indx - 2][c]) + abs(image[indx - 2][c] - image[indx - 4][c]); - f[3] = 1.f + abs(image[indx + u][1] - image[indx + w][1]) + abs(image[indx + u][1] - image[indx - u][1]) + abs(image[indx][c] - image[indx + v][c]) + abs(image[indx + v][c] - image[indx + x][c]); - g[0] = CLIP((22.f * image[indx - u][1] + 22.f * image[indx - w][1] + 2.f * image[indx - y][1] + 2.f * image[indx + u][1] + 40.f * image[indx][c] - 32.f * image[indx - v][c] - 8.f * image[indx - x][c]) / 48.f); - g[1] = CLIP((22.f * image[indx + 1][1] + 22.f * image[indx + 3][1] + 2.f * image[indx + 5][1] + 2.f * image[indx - 1][1] + 40.f * image[indx][c] - 32.f * image[indx + 2][c] - 8.f * image[indx + 4][c]) / 48.f); - g[2] = CLIP((22.f * image[indx - 1][1] + 22.f * image[indx - 3][1] + 2.f * image[indx - 5][1] + 2.f * image[indx + 1][1] + 40.f * image[indx][c] - 32.f * image[indx - 2][c] - 8.f * image[indx - 4][c]) / 48.f); - g[3] = CLIP((22.f * image[indx + u][1] + 22.f * image[indx + w][1] + 2.f * image[indx + y][1] + 2.f * image[indx - u][1] + 40.f * image[indx][c] - 32.f * image[indx + v][c] - 8.f * image[indx + x][c]) / 48.f); - dif[indx][0] = CLIP((f[3] * g[0] + f[0] * g[3]) / (f[0] + f[3])) - image[indx][c]; - dif[indx][1] = CLIP((f[2] * g[1] + f[1] * g[2]) / (f[1] + f[2])) - image[indx][c]; - } - -#ifdef _OPENMP - #pragma omp for -#endif - - for (row = 6; row < height - 6; row++) - for (col = 6 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col) / 2; col < u - 6; col += 2, indx += 2) { - f[0] = 1.f + 78.f * SQR((float)dif[indx][0]) + 69.f * (SQR((float) dif[indx - v][0]) + SQR((float)dif[indx + v][0])) + 51.f * (SQR((float)dif[indx - x][0]) + SQR((float)dif[indx + x][0])) + 21.f * (SQR((float)dif[indx - z][0]) + SQR((float)dif[indx + z][0])) - 6.f * SQR((float)dif[indx - v][0] + dif[indx][0] + dif[indx + v][0]) - 10.f * (SQR((float)dif[indx - x][0] + dif[indx - v][0] + dif[indx][0]) + SQR((float)dif[indx][0] + dif[indx + v][0] + dif[indx + x][0])) - 7.f * (SQR((float)dif[indx - z][0] + dif[indx - x][0] + dif[indx - v][0]) + SQR((float)dif[indx + v][0] + dif[indx + x][0] + dif[indx + z][0])); - f[1] = 1.f + 78.f * SQR((float)dif[indx][1]) + 69.f * (SQR((float)dif[indx - 2][1]) + SQR((float)dif[indx + 2][1])) + 51.f * (SQR((float)dif[indx - 4][1]) + SQR((float)dif[indx + 4][1])) + 21.f * (SQR((float)dif[indx - 6][1]) + SQR((float)dif[indx + 6][1])) - 6.f * SQR((float)dif[indx - 2][1] + dif[indx][1] + dif[indx + 2][1]) - 10.f * (SQR((float)dif[indx - 4][1] + dif[indx - 2][1] + dif[indx][1]) + SQR((float)dif[indx][1] + dif[indx + 2][1] + dif[indx + 4][1])) - 7.f * (SQR((float)dif[indx - 6][1] + dif[indx - 4][1] + dif[indx - 2][1]) + SQR((float)dif[indx + 2][1] + dif[indx + 4][1] + dif[indx + 6][1])); - g[0] = median(0.725f * dif[indx][0] + 0.1375f * dif[indx - v][0] + 0.1375f * dif[indx + v][0], static_cast(dif[indx - v][0]), static_cast(dif[indx + v][0])); - g[1] = median(0.725f * dif[indx][1] + 0.1375f * dif[indx - 2][1] + 0.1375f * dif[indx + 2][1], static_cast(dif[indx - 2][1]), static_cast(dif[indx + 2][1])); - chr[indx][c] = (f[1] * g[0] + f[0] * g[1]) / (f[0] + f[1]); - } - -#ifdef _OPENMP - #pragma omp for -#endif - - for (row = 6; row < height - 6; row++) - for (col = 6 + (FC(row, 2) & 1), indx = row * width + col, c = 1 - FC(row, col) / 2, d = 2 * c; col < u - 6; col += 2, indx += 2) { - f[0] = 1.f / (float)(1.f + fabs((float)chr[indx - u - 1][c] - chr[indx + u + 1][c]) + fabs((float)chr[indx - u - 1][c] - chr[indx - w - 3][c]) + fabs((float)chr[indx + u + 1][c] - chr[indx - w - 3][c])); - f[1] = 1.f / (float)(1.f + fabs((float)chr[indx - u + 1][c] - chr[indx + u - 1][c]) + fabs((float)chr[indx - u + 1][c] - chr[indx - w + 3][c]) + fabs((float)chr[indx + u - 1][c] - chr[indx - w + 3][c])); - f[2] = 1.f / (float)(1.f + fabs((float)chr[indx + u - 1][c] - chr[indx - u + 1][c]) + fabs((float)chr[indx + u - 1][c] - chr[indx + w + 3][c]) + fabs((float)chr[indx - u + 1][c] - chr[indx + w - 3][c])); - f[3] = 1.f / (float)(1.f + fabs((float)chr[indx + u + 1][c] - chr[indx - u - 1][c]) + fabs((float)chr[indx + u + 1][c] - chr[indx + w - 3][c]) + fabs((float)chr[indx - u - 1][c] - chr[indx + w + 3][c])); - g[0] = median(chr[indx - u - 1][c], chr[indx - w - 1][c], chr[indx - u - 3][c]); - g[1] = median(chr[indx - u + 1][c], chr[indx - w + 1][c], chr[indx - u + 3][c]); - g[2] = median(chr[indx + u - 1][c], chr[indx + w - 1][c], chr[indx + u - 3][c]); - g[3] = median(chr[indx + u + 1][c], chr[indx + w + 1][c], chr[indx + u + 3][c]); - chr[indx][c] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); - image[indx][1] = CLIP(image[indx][2 - d] + chr[indx][1 - c]); - image[indx][d] = CLIP(image[indx][1] - chr[indx][c]); - } - -#ifdef _OPENMP - #pragma omp for -#endif - - for (row = 6; row < height - 6; row++) - for (col = 6 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col + 1) / 2, d = 2 * c; col < u - 6; col += 2, indx += 2) - for(i = 0; i <= 1; c = 1 - c, d = 2 * c, i++) { - f[0] = 1.f / (float)(1.f + fabs((float)chr[indx - u][c] - chr[indx + u][c]) + fabs((float)chr[indx - u][c] - chr[indx - w][c]) + fabs((float)chr[indx + u][c] - chr[indx - w][c])); - f[1] = 1.f / (float)(1.f + fabs((float)chr[indx + 1][c] - chr[indx - 1][c]) + fabs((float)chr[indx + 1][c] - chr[indx + 3][c]) + fabs((float)chr[indx - 1][c] - chr[indx + 3][c])); - f[2] = 1.f / (float)(1.f + fabs((float)chr[indx - 1][c] - chr[indx + 1][c]) + fabs((float)chr[indx - 1][c] - chr[indx - 3][c]) + fabs((float)chr[indx + 1][c] - chr[indx - 3][c])); - f[3] = 1.f / (float)(1.f + fabs((float)chr[indx + u][c] - chr[indx - u][c]) + fabs((float)chr[indx + u][c] - chr[indx + w][c]) + fabs((float)chr[indx - u][c] - chr[indx + w][c])); - g[0] = 0.875f * chr[indx - u][c] + 0.125f * chr[indx - w][c]; - g[1] = 0.875f * chr[indx + 1][c] + 0.125f * chr[indx + 3][c]; - g[2] = 0.875f * chr[indx - 1][c] + 0.125f * chr[indx - 3][c]; - g[3] = 0.875f * chr[indx + u][c] + 0.125f * chr[indx + w][c]; - image[indx][d] = CLIP(image[indx][1] - (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3])); - } - -#ifdef _OPENMP - #pragma omp for -#endif - - for (int ii = 0; ii < height; ii++) { - for (int jj = 0; jj < width; jj++) { - red[ii][jj] = CLIP(image[ii * width + jj][0]); - green[ii][jj] = CLIP(image[ii * width + jj][1]); - blue[ii][jj] = CLIP(image[ii * width + jj][2]); - } - } - } // End of parallelization - free (image); - free(dif); - free(chr); - //RawImageSource::refinement_lassus(); -} - -// LSMME demosaicing algorithm -// L. Zhang and X. Wu, -// Color demozaicing via directional Linear Minimum Mean Square-error Estimation, -// IEEE Trans. on Image Processing, vol. 14, pp. 2167-2178, -// Dec. 2005. -// Adapted to RawTherapee by Jacques Desmis 3/2013 -// Improved speed and reduced memory consumption by Ingo Weyrich 2/2015 -//TODO Tiles to reduce memory consumption -void RawImageSource::lmmse_interpolate_omp(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations) -{ - const int width = winw, height = winh; - const int ba = 10; - const int rr1 = height + 2 * ba; - const int cc1 = width + 2 * ba; - const int w1 = cc1; - const int w2 = 2 * w1; - const int w3 = 3 * w1; - const int w4 = 4 * w1; - float h0, h1, h2, h3, h4, hs; - h0 = 1.0f; - h1 = exp( -1.0f / 8.0f); - h2 = exp( -4.0f / 8.0f); - h3 = exp( -9.0f / 8.0f); - h4 = exp(-16.0f / 8.0f); - hs = h0 + 2.0f * (h1 + h2 + h3 + h4); - h0 /= hs; - h1 /= hs; - h2 /= hs; - h3 /= hs; - h4 /= hs; - int passref = 0; - int iter = 0; - - if(iterations <= 4) { - iter = iterations - 1; - passref = 0; - } else if (iterations <= 6) { - iter = 3; - passref = iterations - 4; - } else if (iterations <= 8) { - iter = 3; - passref = iterations - 6; - } - - bool applyGamma = true; - - if(iterations == 0) { - applyGamma = false; - iter = 0; - } else { - applyGamma = true; - } - - float *rix[5]; - float *qix[5]; - float *buffer = (float *)calloc(rr1 * cc1 * 5 * sizeof(float), 1); - - if(buffer == nullptr) { // allocation of big block of memory failed, try to get 5 smaller ones - printf("lmmse_interpolate_omp: allocation of big memory block failed, try to get 5 smaller ones now...\n"); - bool allocationFailed = false; - - for(int i = 0; i < 5; i++) { - qix[i] = (float *)calloc(rr1 * cc1 * sizeof(float), 1); - - if(!qix[i]) { // allocation of at least one small block failed - allocationFailed = true; - } - } - - if(allocationFailed) { // fall back to igv_interpolate - printf("lmmse_interpolate_omp: allocation of 5 small memory blocks failed, falling back to igv_interpolate...\n"); - - for(int i = 0; i < 5; i++) { // free the already allocated buffers - if(qix[i]) { - free(qix[i]); - } - } - - igv_interpolate(winw, winh); - return; - } - } else { - qix[0] = buffer; - - for(int i = 1; i < 5; i++) { - qix[i] = qix[i - 1] + rr1 * cc1; - } - } - - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), M("TP_RAW_LMMSE"))); - plistener->setProgress (0.0); - } - - - LUTf *gamtab; - - if(applyGamma) { - gamtab = &(Color::gammatab_24_17a); - } else { - gamtab = new LUTf(65536, LUT_CLIP_ABOVE | LUT_CLIP_BELOW); - gamtab->makeIdentity(65535.f); - } - - -#ifdef _OPENMP - #pragma omp parallel private(rix) -#endif - { -#ifdef _OPENMP - #pragma omp for -#endif - - for (int rrr = ba; rrr < rr1 - ba; rrr++) { - for (int ccc = ba, row = rrr - ba; ccc < cc1 - ba; ccc++) { - int col = ccc - ba; - float *rix = qix[4] + rrr * cc1 + ccc; - rix[0] = (*gamtab)[rawData[row][col]]; - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.1); - } - } - - // G-R(B) -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) -#endif - - for (int rr = 2; rr < rr1 - 2; rr++) { - // G-R(B) at R(B) location - for (int cc = 2 + (FC(rr, 2) & 1); cc < cc1 - 2; cc += 2) { - rix[4] = qix[4] + rr * cc1 + cc; - float v0 = x00625(rix[4][-w1 - 1] + rix[4][-w1 + 1] + rix[4][w1 - 1] + rix[4][w1 + 1]) + x0250(rix[4][0]); - // horizontal - rix[0] = qix[0] + rr * cc1 + cc; - rix[0][0] = - x0250(rix[4][ -2] + rix[4][ 2]) + xdiv2f(rix[4][ -1] + rix[4][0] + rix[4][ 1]); - float Y = v0 + xdiv2f(rix[0][0]); - - if (rix[4][0] > 1.75f * Y) { - rix[0][0] = median(rix[0][0], rix[4][ -1], rix[4][ 1]); - } else { - rix[0][0] = LIM(rix[0][0], 0.0f, 1.0f); - } - - rix[0][0] -= rix[4][0]; - // vertical - rix[1] = qix[1] + rr * cc1 + cc; - rix[1][0] = -x0250(rix[4][-w2] + rix[4][w2]) + xdiv2f(rix[4][-w1] + rix[4][0] + rix[4][w1]); - Y = v0 + xdiv2f(rix[1][0]); - - if (rix[4][0] > 1.75f * Y) { - rix[1][0] = median(rix[1][0], rix[4][-w1], rix[4][w1]); - } else { - rix[1][0] = LIM(rix[1][0], 0.0f, 1.0f); - } - - rix[1][0] -= rix[4][0]; - } - - // G-R(B) at G location - for (int ccc = 2 + (FC(rr, 3) & 1); ccc < cc1 - 2; ccc += 2) { - rix[0] = qix[0] + rr * cc1 + ccc; - rix[1] = qix[1] + rr * cc1 + ccc; - rix[4] = qix[4] + rr * cc1 + ccc; - rix[0][0] = x0250(rix[4][ -2] + rix[4][ 2]) - xdiv2f(rix[4][ -1] + rix[4][0] + rix[4][ 1]); - rix[1][0] = x0250(rix[4][-w2] + rix[4][w2]) - xdiv2f(rix[4][-w1] + rix[4][0] + rix[4][w1]); - rix[0][0] = LIM(rix[0][0], -1.0f, 0.0f) + rix[4][0]; - rix[1][0] = LIM(rix[1][0], -1.0f, 0.0f) + rix[4][0]; - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.2); - } - } - - - // apply low pass filter on differential colors -#ifdef _OPENMP - #pragma omp for -#endif - - for (int rr = 4; rr < rr1 - 4; rr++) - for (int cc = 4; cc < cc1 - 4; cc++) { - rix[0] = qix[0] + rr * cc1 + cc; - rix[2] = qix[2] + rr * cc1 + cc; - rix[2][0] = h0 * rix[0][0] + h1 * (rix[0][ -1] + rix[0][ 1]) + h2 * (rix[0][ -2] + rix[0][ 2]) + h3 * (rix[0][ -3] + rix[0][ 3]) + h4 * (rix[0][ -4] + rix[0][ 4]); - rix[1] = qix[1] + rr * cc1 + cc; - rix[3] = qix[3] + rr * cc1 + cc; - rix[3][0] = h0 * rix[1][0] + h1 * (rix[1][-w1] + rix[1][w1]) + h2 * (rix[1][-w2] + rix[1][w2]) + h3 * (rix[1][-w3] + rix[1][w3]) + h4 * (rix[1][-w4] + rix[1][w4]); - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.3); - } - } - - // interpolate G-R(B) at R(B) -#ifdef _OPENMP - #pragma omp for -#endif - - for (int rr = 4; rr < rr1 - 4; rr++) { - int cc = 4 + (FC(rr, 4) & 1); -#ifdef __SSE2__ - __m128 p1v, p2v, p3v, p4v, p5v, p6v, p7v, p8v, p9v, muv, vxv, vnv, xhv, vhv, xvv, vvv; - __m128 epsv = _mm_set1_ps(1e-7); - __m128 ninev = _mm_set1_ps(9.f); - - for (; cc < cc1 - 10; cc += 8) { - rix[0] = qix[0] + rr * cc1 + cc; - rix[1] = qix[1] + rr * cc1 + cc; - rix[2] = qix[2] + rr * cc1 + cc; - rix[3] = qix[3] + rr * cc1 + cc; - rix[4] = qix[4] + rr * cc1 + cc; - // horizontal - p1v = LC2VFU(rix[2][-4]); - p2v = LC2VFU(rix[2][-3]); - p3v = LC2VFU(rix[2][-2]); - p4v = LC2VFU(rix[2][-1]); - p5v = LC2VFU(rix[2][ 0]); - p6v = LC2VFU(rix[2][ 1]); - p7v = LC2VFU(rix[2][ 2]); - p8v = LC2VFU(rix[2][ 3]); - p9v = LC2VFU(rix[2][ 4]); - muv = (p1v + p2v + p3v + p4v + p5v + p6v + p7v + p8v + p9v) / ninev; - vxv = epsv + SQRV(p1v - muv) + SQRV(p2v - muv) + SQRV(p3v - muv) + SQRV(p4v - muv) + SQRV(p5v - muv) + SQRV(p6v - muv) + SQRV(p7v - muv) + SQRV(p8v - muv) + SQRV(p9v - muv); - p1v -= LC2VFU(rix[0][-4]); - p2v -= LC2VFU(rix[0][-3]); - p3v -= LC2VFU(rix[0][-2]); - p4v -= LC2VFU(rix[0][-1]); - p5v -= LC2VFU(rix[0][ 0]); - p6v -= LC2VFU(rix[0][ 1]); - p7v -= LC2VFU(rix[0][ 2]); - p8v -= LC2VFU(rix[0][ 3]); - p9v -= LC2VFU(rix[0][ 4]); - vnv = epsv + SQRV(p1v) + SQRV(p2v) + SQRV(p3v) + SQRV(p4v) + SQRV(p5v) + SQRV(p6v) + SQRV(p7v) + SQRV(p8v) + SQRV(p9v); - xhv = (LC2VFU(rix[0][0]) * vxv + LC2VFU(rix[2][0]) * vnv) / (vxv + vnv); - vhv = vxv * vnv / (vxv + vnv); - - // vertical - p1v = LC2VFU(rix[3][-w4]); - p2v = LC2VFU(rix[3][-w3]); - p3v = LC2VFU(rix[3][-w2]); - p4v = LC2VFU(rix[3][-w1]); - p5v = LC2VFU(rix[3][ 0]); - p6v = LC2VFU(rix[3][ w1]); - p7v = LC2VFU(rix[3][ w2]); - p8v = LC2VFU(rix[3][ w3]); - p9v = LC2VFU(rix[3][ w4]); - muv = (p1v + p2v + p3v + p4v + p5v + p6v + p7v + p8v + p9v) / ninev; - vxv = epsv + SQRV(p1v - muv) + SQRV(p2v - muv) + SQRV(p3v - muv) + SQRV(p4v - muv) + SQRV(p5v - muv) + SQRV(p6v - muv) + SQRV(p7v - muv) + SQRV(p8v - muv) + SQRV(p9v - muv); - p1v -= LC2VFU(rix[1][-w4]); - p2v -= LC2VFU(rix[1][-w3]); - p3v -= LC2VFU(rix[1][-w2]); - p4v -= LC2VFU(rix[1][-w1]); - p5v -= LC2VFU(rix[1][ 0]); - p6v -= LC2VFU(rix[1][ w1]); - p7v -= LC2VFU(rix[1][ w2]); - p8v -= LC2VFU(rix[1][ w3]); - p9v -= LC2VFU(rix[1][ w4]); - vnv = epsv + SQRV(p1v) + SQRV(p2v) + SQRV(p3v) + SQRV(p4v) + SQRV(p5v) + SQRV(p6v) + SQRV(p7v) + SQRV(p8v) + SQRV(p9v); - xvv = (LC2VFU(rix[1][0]) * vxv + LC2VFU(rix[3][0]) * vnv) / (vxv + vnv); - vvv = vxv * vnv / (vxv + vnv); - // interpolated G-R(B) - muv = (xhv * vvv + xvv * vhv) / (vhv + vvv); - STC2VFU(rix[4][0], muv); - } - -#endif - - for (; cc < cc1 - 4; cc += 2) { - rix[0] = qix[0] + rr * cc1 + cc; - rix[1] = qix[1] + rr * cc1 + cc; - rix[2] = qix[2] + rr * cc1 + cc; - rix[3] = qix[3] + rr * cc1 + cc; - rix[4] = qix[4] + rr * cc1 + cc; - // horizontal - float p1 = rix[2][-4]; - float p2 = rix[2][-3]; - float p3 = rix[2][-2]; - float p4 = rix[2][-1]; - float p5 = rix[2][ 0]; - float p6 = rix[2][ 1]; - float p7 = rix[2][ 2]; - float p8 = rix[2][ 3]; - float p9 = rix[2][ 4]; - float mu = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) / 9.f; - float vx = 1e-7 + SQR(p1 - mu) + SQR(p2 - mu) + SQR(p3 - mu) + SQR(p4 - mu) + SQR(p5 - mu) + SQR(p6 - mu) + SQR(p7 - mu) + SQR(p8 - mu) + SQR(p9 - mu); - p1 -= rix[0][-4]; - p2 -= rix[0][-3]; - p3 -= rix[0][-2]; - p4 -= rix[0][-1]; - p5 -= rix[0][ 0]; - p6 -= rix[0][ 1]; - p7 -= rix[0][ 2]; - p8 -= rix[0][ 3]; - p9 -= rix[0][ 4]; - float vn = 1e-7 + SQR(p1) + SQR(p2) + SQR(p3) + SQR(p4) + SQR(p5) + SQR(p6) + SQR(p7) + SQR(p8) + SQR(p9); - float xh = (rix[0][0] * vx + rix[2][0] * vn) / (vx + vn); - float vh = vx * vn / (vx + vn); - - // vertical - p1 = rix[3][-w4]; - p2 = rix[3][-w3]; - p3 = rix[3][-w2]; - p4 = rix[3][-w1]; - p5 = rix[3][ 0]; - p6 = rix[3][ w1]; - p7 = rix[3][ w2]; - p8 = rix[3][ w3]; - p9 = rix[3][ w4]; - mu = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) / 9.f; - vx = 1e-7 + SQR(p1 - mu) + SQR(p2 - mu) + SQR(p3 - mu) + SQR(p4 - mu) + SQR(p5 - mu) + SQR(p6 - mu) + SQR(p7 - mu) + SQR(p8 - mu) + SQR(p9 - mu); - p1 -= rix[1][-w4]; - p2 -= rix[1][-w3]; - p3 -= rix[1][-w2]; - p4 -= rix[1][-w1]; - p5 -= rix[1][ 0]; - p6 -= rix[1][ w1]; - p7 -= rix[1][ w2]; - p8 -= rix[1][ w3]; - p9 -= rix[1][ w4]; - vn = 1e-7 + SQR(p1) + SQR(p2) + SQR(p3) + SQR(p4) + SQR(p5) + SQR(p6) + SQR(p7) + SQR(p8) + SQR(p9); - float xv = (rix[1][0] * vx + rix[3][0] * vn) / (vx + vn); - float vv = vx * vn / (vx + vn); - // interpolated G-R(B) - rix[4][0] = (xh * vv + xv * vh) / (vh + vv); - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.4); - } - } - - // copy CFA values -#ifdef _OPENMP - #pragma omp for -#endif - - for (int rr = 0; rr < rr1; rr++) - for (int cc = 0, row = rr - ba; cc < cc1; cc++) { - int col = cc - ba; - int c = FC(rr, cc); - rix[c] = qix[c] + rr * cc1 + cc; - - if ((row >= 0) & (row < height) & (col >= 0) & (col < width)) { - rix[c][0] = (*gamtab)[rawData[row][col]]; - } else { - rix[c][0] = 0.f; - } - - if (c != 1) { - rix[1] = qix[1] + rr * cc1 + cc; - rix[4] = qix[4] + rr * cc1 + cc; - rix[1][0] = rix[c][0] + rix[4][0]; - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.5); - } - } - - // bilinear interpolation for R/B - // interpolate R/B at G location -#ifdef _OPENMP - #pragma omp for -#endif - - for (int rr = 1; rr < rr1 - 1; rr++) - for (int cc = 1 + (FC(rr, 2) & 1), c = FC(rr, cc + 1); cc < cc1 - 1; cc += 2) { - rix[c] = qix[c] + rr * cc1 + cc; - rix[1] = qix[1] + rr * cc1 + cc; - rix[c][0] = rix[1][0] + xdiv2f(rix[c][ -1] - rix[1][ -1] + rix[c][ 1] - rix[1][ 1]); - c = 2 - c; - rix[c] = qix[c] + rr * cc1 + cc; - rix[c][0] = rix[1][0] + xdiv2f(rix[c][-w1] - rix[1][-w1] + rix[c][w1] - rix[1][w1]); - c = 2 - c; - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.6); - } - } - - // interpolate R/B at B/R location -#ifdef _OPENMP - #pragma omp for -#endif - - for (int rr = 1; rr < rr1 - 1; rr++) - for (int cc = 1 + (FC(rr, 1) & 1), c = 2 - FC(rr, cc); cc < cc1 - 1; cc += 2) { - rix[c] = qix[c] + rr * cc1 + cc; - rix[1] = qix[1] + rr * cc1 + cc; - rix[c][0] = rix[1][0] + x0250(rix[c][-w1] - rix[1][-w1] + rix[c][ -1] - rix[1][ -1] + rix[c][ 1] - rix[1][ 1] + rix[c][ w1] - rix[1][ w1]); - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.7); - } - } - - }// End of parallelization 1 - - // median filter/ - for (int pass = 0; pass < iter; pass++) { - // Apply 3x3 median filter - // Compute median(R-G) and median(B-G) - -#ifdef _OPENMP - #pragma omp parallel for private(rix) -#endif - - for (int rr = 1; rr < rr1 - 1; rr++) { - for (int c = 0; c < 3; c += 2) { - int d = c + 3 - (c == 0 ? 0 : 1); - int cc = 1; -#ifdef __SSE2__ - - for (; cc < cc1 - 4; cc += 4) { - rix[d] = qix[d] + rr * cc1 + cc; - rix[c] = qix[c] + rr * cc1 + cc; - rix[1] = qix[1] + rr * cc1 + cc; - // Assign 3x3 differential color values - const std::array p = { - LVFU(rix[c][-w1 - 1]) - LVFU(rix[1][-w1 - 1]), - LVFU(rix[c][-w1]) - LVFU(rix[1][-w1]), - LVFU(rix[c][-w1 + 1]) - LVFU(rix[1][-w1 + 1]), - LVFU(rix[c][ -1]) - LVFU(rix[1][ -1]), - LVFU(rix[c][ 0]) - LVFU(rix[1][ 0]), - LVFU(rix[c][ 1]) - LVFU(rix[1][ 1]), - LVFU(rix[c][ w1 - 1]) - LVFU(rix[1][ w1 - 1]), - LVFU(rix[c][ w1]) - LVFU(rix[1][ w1]), - LVFU(rix[c][ w1 + 1]) - LVFU(rix[1][ w1 + 1]) - }; - _mm_storeu_ps(&rix[d][0], median(p)); - } - -#endif - - for (; cc < cc1 - 1; cc++) { - rix[d] = qix[d] + rr * cc1 + cc; - rix[c] = qix[c] + rr * cc1 + cc; - rix[1] = qix[1] + rr * cc1 + cc; - // Assign 3x3 differential color values - const std::array p = { - rix[c][-w1 - 1] - rix[1][-w1 - 1], - rix[c][-w1] - rix[1][-w1], - rix[c][-w1 + 1] - rix[1][-w1 + 1], - rix[c][ -1] - rix[1][ -1], - rix[c][ 0] - rix[1][ 0], - rix[c][ 1] - rix[1][ 1], - rix[c][ w1 - 1] - rix[1][ w1 - 1], - rix[c][ w1] - rix[1][ w1], - rix[c][ w1 + 1] - rix[1][ w1 + 1] - }; - rix[d][0] = median(p); - } - } - } - - // red/blue at GREEN pixel locations & red/blue and green at BLUE/RED pixel locations -#ifdef _OPENMP - #pragma omp parallel for private (rix) -#endif - - for (int rr = 0; rr < rr1; rr++) { - rix[0] = qix[0] + rr * cc1; - rix[1] = qix[1] + rr * cc1; - rix[2] = qix[2] + rr * cc1; - rix[3] = qix[3] + rr * cc1; - rix[4] = qix[4] + rr * cc1; - int c0 = FC(rr, 0); - int c1 = FC(rr, 1); - - if(c0 == 1) { - c1 = 2 - c1; - int d = c1 + 3 - (c1 == 0 ? 0 : 1); - int cc; - - for (cc = 0; cc < cc1 - 1; cc += 2) { - rix[0][0] = rix[1][0] + rix[3][0]; - rix[2][0] = rix[1][0] + rix[4][0]; - rix[0]++; - rix[1]++; - rix[2]++; - rix[3]++; - rix[4]++; - rix[c1][0] = rix[1][0] + rix[d][0]; - rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); - rix[0]++; - rix[1]++; - rix[2]++; - rix[3]++; - rix[4]++; - } - - if(cc < cc1) { // remaining pixel, only if width is odd - rix[0][0] = rix[1][0] + rix[3][0]; - rix[2][0] = rix[1][0] + rix[4][0]; - } - } else { - c0 = 2 - c0; - int d = c0 + 3 - (c0 == 0 ? 0 : 1); - int cc; - - for (cc = 0; cc < cc1 - 1; cc += 2) { - rix[c0][0] = rix[1][0] + rix[d][0]; - rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); - rix[0]++; - rix[1]++; - rix[2]++; - rix[3]++; - rix[4]++; - rix[0][0] = rix[1][0] + rix[3][0]; - rix[2][0] = rix[1][0] + rix[4][0]; - rix[0]++; - rix[1]++; - rix[2]++; - rix[3]++; - rix[4]++; - } - - if(cc < cc1) { // remaining pixel, only if width is odd - rix[c0][0] = rix[1][0] + rix[d][0]; - rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); - } - } - } - } - - if (plistener) { - plistener->setProgress (0.8); - } - - if(applyGamma) { - gamtab = &(Color::igammatab_24_17); - } else { - gamtab->makeIdentity(); - } - - array2D* rgb[3]; - rgb[0] = &red; - rgb[1] = &green; - rgb[2] = &blue; - - // copy result back to image matrix -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int row = 0; row < height; row++) { - for (int col = 0, rr = row + ba; col < width; col++) { - int cc = col + ba; - int c = FC(row, col); - - for (int ii = 0; ii < 3; ii++) - if (ii != c) { - float *rix = qix[ii] + rr * cc1 + cc; - (*(rgb[ii]))[row][col] = (*gamtab)[65535.f * rix[0]]; - } else { - (*(rgb[ii]))[row][col] = CLIP(rawData[row][col]); - } - } - } - - if (plistener) { - plistener->setProgress (1.0); - } - - if(buffer) { - free(buffer); - } else - for(int i = 0; i < 5; i++) { - free(qix[i]); - } - - if(!applyGamma) { - delete gamtab; - } - - if(iterations > 4 && iterations <= 6) { - refinement(passref); - } else if(iterations > 6) { - refinement_lassus(passref); - } - -} - /*** * * Bayer CFA Demosaicing using Integrated Gaussian Vector on Color Differences @@ -1121,13 +209,12 @@ 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 // SSE version by Ingo Weyrich 5/2013 #ifdef __SSE2__ -#define CLIPV(a) vclampf(a,zerov,c65535v) void RawImageSource::igv_interpolate(int winw, int winh) { static const float eps = 1e-5f, epssq = 1e-5f; //mod epssq -10f =>-5f Jacques 3/2013 to prevent artifact (divide by zero) @@ -1145,7 +232,7 @@ void RawImageSource::igv_interpolate(int winw, int winh) vdif = (float (*)) calloc( width * height / 2, sizeof * vdif ); hdif = (float (*)) calloc( width * height / 2, sizeof * hdif ); - chrarray = (float (*)) calloc( width * height, sizeof( float ) ); + chrarray = (float (*)) calloc(static_cast(width) * height, sizeof( float ) ); chr[0] = chrarray; chr[1] = chrarray + (width * height) / 2; @@ -1196,9 +283,9 @@ void RawImageSource::igv_interpolate(int winw, int winh) for (col = 0, indx = row * width + col; col < width - 7; col += 8, indx += 8) { temp1v = LVFU( rawData[row][col] ); - temp1v = CLIPV( temp1v ); + temp1v = vmaxf(temp1v, ZEROV); temp2v = LVFU( rawData[row][col + 4] ); - temp2v = CLIPV( temp2v ); + temp2v = vmaxf(temp2v, ZEROV); tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 2, 0, 2, 0 ) ); _mm_storeu_ps( &dest1[indx >> 1], tempv ); tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 3, 1, 3, 1 ) ); @@ -1206,10 +293,10 @@ void RawImageSource::igv_interpolate(int winw, int winh) } for (; col < width; col++, indx += 2) { - dest1[indx >> 1] = CLIP(rawData[row][col]); //rawData = RT data + dest1[indx >> 1] = std::max(0.f, rawData[row][col]); //rawData = RT data col++; if(col < width) - dest2[indx >> 1] = CLIP(rawData[row][col]); //rawData = RT data + dest2[indx >> 1] = std::max(0.f, rawData[row][col]); //rawData = RT data } } @@ -1468,46 +555,46 @@ void RawImageSource::igv_interpolate(int winw, int winh) temp2v = LVFU( src2[(indx + 1) >> 1] ); tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 1, 0, 1, 0 ) ); tempv = _mm_shuffle_ps( tempv, tempv, _MM_SHUFFLE( 3, 1, 2, 0 ) ); - _mm_storeu_ps( &green[row][col], CLIPV( tempv )); + _mm_storeu_ps( &green[row][col], vmaxf(tempv, ZEROV)); temp5v = LVFU(redsrc0[indx >> 1]); temp6v = LVFU(redsrc1[(indx + 1) >> 1]); temp3v = _mm_shuffle_ps( temp5v, temp6v, _MM_SHUFFLE( 1, 0, 1, 0 ) ); temp3v = _mm_shuffle_ps( temp3v, temp3v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); - temp3v = CLIPV( tempv - c65535v * temp3v ); + temp3v = vmaxf(tempv - c65535v * temp3v, ZEROV); _mm_storeu_ps( &red[row][col], temp3v); temp7v = LVFU(bluesrc0[indx >> 1]); temp8v = LVFU(bluesrc1[(indx + 1) >> 1]); temp4v = _mm_shuffle_ps( temp7v, temp8v, _MM_SHUFFLE( 1, 0, 1, 0 ) ); temp4v = _mm_shuffle_ps( temp4v, temp4v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); - temp4v = CLIPV( tempv - c65535v * temp4v ); + temp4v = vmaxf(tempv - c65535v * temp4v, ZEROV); _mm_storeu_ps( &blue[row][col], temp4v); tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 3, 2, 3, 2 ) ); tempv = _mm_shuffle_ps( tempv, tempv, _MM_SHUFFLE( 3, 1, 2, 0 ) ); - _mm_storeu_ps( &green[row][col + 4], CLIPV( tempv )); + _mm_storeu_ps( &green[row][col + 4], vmaxf(tempv, ZEROV)); temp3v = _mm_shuffle_ps( temp5v, temp6v, _MM_SHUFFLE( 3, 2, 3, 2 ) ); temp3v = _mm_shuffle_ps( temp3v, temp3v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); - temp3v = CLIPV( tempv - c65535v * temp3v ); + temp3v = vmaxf(tempv - c65535v * temp3v, ZEROV); _mm_storeu_ps( &red[row][col + 4], temp3v); temp4v = _mm_shuffle_ps( temp7v, temp8v, _MM_SHUFFLE( 3, 2, 3, 2 ) ); temp4v = _mm_shuffle_ps( temp4v, temp4v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); - temp4v = CLIPV( tempv - c65535v * temp4v ); + temp4v = vmaxf(tempv - c65535v * temp4v, ZEROV); _mm_storeu_ps( &blue[row][col + 4], temp4v); } for(; col < width - 7; col++, indx += 2) { - red [row][col] = CLIP(src1[indx >> 1] - 65535.f * redsrc0[indx >> 1]); - green[row][col] = CLIP(src1[indx >> 1]); - blue [row][col] = CLIP(src1[indx >> 1] - 65535.f * bluesrc0[indx >> 1]); + red [row][col] = std::max(0.f, src1[indx >> 1] - 65535.f * redsrc0[indx >> 1]); + green[row][col] = std::max(0.f, src1[indx >> 1]); + blue [row][col] = std::max(0.f, src1[indx >> 1] - 65535.f * bluesrc0[indx >> 1]); col++; - red [row][col] = CLIP(src2[(indx + 1) >> 1] - 65535.f * redsrc1[(indx + 1) >> 1]); - green[row][col] = CLIP(src2[(indx + 1) >> 1]); - blue [row][col] = CLIP(src2[(indx + 1) >> 1] - 65535.f * bluesrc1[(indx + 1) >> 1]); + red [row][col] = std::max(0.f, src2[(indx + 1) >> 1] - 65535.f * redsrc1[(indx + 1) >> 1]); + green[row][col] = std::max(0.f, src2[(indx + 1) >> 1]); + blue [row][col] = std::max(0.f, src2[(indx + 1) >> 1] - 65535.f * bluesrc1[(indx + 1) >> 1]); } } }// End of parallelization - border_interpolate2(winw, winh, 8, rawData, red, green, blue); + border_interpolate(winw, winh, 8, rawData, red, green, blue); if (plistener) { plistener->setProgress (1.0); @@ -1518,7 +605,6 @@ void RawImageSource::igv_interpolate(int winw, int winh) free(vdif); free(hdif); } -#undef CLIPV #else void RawImageSource::igv_interpolate(int winw, int winh) { @@ -1561,11 +647,9 @@ void RawImageSource::igv_interpolate(int winw, int winh) for (int row = 0; row < height - 0; row++) for (int col = 0, indx = row * width + col; col < width - 0; col++, indx++) { int c = FC(row, col); - rgb[c][indx] = CLIP(rawData[row][col]); //rawData = RT data + rgb[c][indx] = std::max(0.f, rawData[row][col]); //rawData = RT data } -// border_interpolate2(7, rgb); - #ifdef _OPENMP #pragma omp single #endif @@ -1740,9 +824,6 @@ void RawImageSource::igv_interpolate(int winw, int winh) if (plistener) { plistener->setProgress (0.91); } - - //Interpolate borders -// border_interpolate2(7, rgb); } /* #ifdef _OPENMP @@ -1765,12 +846,12 @@ void RawImageSource::igv_interpolate(int winw, int winh) for(int row = 7; row < height - 7; row++) for(int col = 7, indx = row * width + col; col < width - 7; col++, indx++) { - red [row][col] = CLIP(rgb[1][indx] - 65535.f * chr[0][indx]); - green[row][col] = CLIP(rgb[1][indx]); - blue [row][col] = CLIP(rgb[1][indx] - 65535.f * chr[1][indx]); + red [row][col] = std::max(0.f, rgb[1][indx] - 65535.f * chr[0][indx]); + green[row][col] = std::max(0.f, rgb[1][indx]); + blue [row][col] = std::max(0.f, rgb[1][indx] - 65535.f * chr[1][indx]); } }// End of parallelization - border_interpolate2(winw, winh, 8, rawData, red, green, blue); + border_interpolate(winw, winh, 8, rawData, red, green, blue); if (plistener) { @@ -1836,356 +917,6 @@ void RawImageSource::nodemosaic(bool bw) } } -/* - Refinement based on EECI demosaicing algorithm by L. Chang and Y.P. Tan - Paul Lee - Adapted for RawTherapee - Jacques Desmis 04/2013 -*/ - -#ifdef __SSE2__ -#define CLIPV(a) vclampf(a,ZEROV,c65535v) -#endif -void RawImageSource::refinement(int PassCount) -{ - MyTime t1e, t2e; - t1e.set(); - - int width = W; - int height = H; - int w1 = width; - int w2 = 2 * w1; - - if (plistener) { - plistener->setProgressStr (M("TP_RAW_DMETHOD_PROGRESSBAR_REFINE")); - } - - array2D *rgb[3]; - rgb[0] = &red; - rgb[1] = &green; - rgb[2] = &blue; - - for (int b = 0; b < PassCount; b++) { - if (plistener) { - plistener->setProgress ((float)b / PassCount); - } - - -#ifdef _OPENMP - #pragma omp parallel -#endif - { - float *pix[3]; - - /* Reinforce interpolated green pixels on RED/BLUE pixel locations */ -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 2; row < height - 2; row++) { - int col = 2 + (FC(row, 2) & 1); - int c = FC(row, col); -#ifdef __SSE2__ - __m128 dLv, dRv, dUv, dDv, v0v; - __m128 onev = _mm_set1_ps(1.f); - __m128 zd5v = _mm_set1_ps(0.5f); - __m128 c65535v = _mm_set1_ps(65535.f); - - for (; col < width - 8; col += 8) { - int indx = row * width + col; - pix[c] = (float*)(*rgb[c]) + indx; - pix[1] = (float*)(*rgb[1]) + indx; - dLv = onev / (onev + vabsf(LC2VFU(pix[c][ -2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); - dRv = onev / (onev + vabsf(LC2VFU(pix[c][ 2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); - dUv = onev / (onev + vabsf(LC2VFU(pix[c][-w2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); - dDv = onev / (onev + vabsf(LC2VFU(pix[c][ w2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); - v0v = CLIPV(LC2VFU(pix[c][0]) + zd5v + ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); - STC2VFU(pix[1][0], v0v); - } - -#endif - - for (; col < width - 2; col += 2) { - int indx = row * width + col; - pix[c] = (float*)(*rgb[c]) + indx; - pix[1] = (float*)(*rgb[1]) + indx; - float dL = 1.f / (1.f + fabsf(pix[c][ -2] - pix[c][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); - float dR = 1.f / (1.f + fabsf(pix[c][ 2] - pix[c][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); - float dU = 1.f / (1.f + fabsf(pix[c][-w2] - pix[c][0]) + fabsf(pix[1][w1] - pix[1][-w1])); - float dD = 1.f / (1.f + fabsf(pix[c][ w2] - pix[c][0]) + fabsf(pix[1][w1] - pix[1][-w1])); - float v0 = (pix[c][0] + 0.5f + ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); - pix[1][0] = CLIP(v0); - } - } - - /* Reinforce interpolated red/blue pixels on GREEN pixel locations */ -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 2; row < height - 2; row++) { - int col = 2 + (FC(row, 3) & 1); - int c = FC(row, col + 1); -#ifdef __SSE2__ - __m128 dLv, dRv, dUv, dDv, v0v; - __m128 onev = _mm_set1_ps(1.f); - __m128 zd5v = _mm_set1_ps(0.5f); - __m128 c65535v = _mm_set1_ps(65535.f); - - for (; col < width - 8; col += 8) { - int indx = row * width + col; - pix[1] = (float*)(*rgb[1]) + indx; - - for (int i = 0; i < 2; c = 2 - c, i++) { - pix[c] = (float*)(*rgb[c]) + indx; - dLv = onev / (onev + vabsf(LC2VFU(pix[1][ -2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][ 1]) - LC2VFU(pix[c][ -1]))); - dRv = onev / (onev + vabsf(LC2VFU(pix[1][ 2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][ 1]) - LC2VFU(pix[c][ -1]))); - dUv = onev / (onev + vabsf(LC2VFU(pix[1][-w2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][w1]) - LC2VFU(pix[c][-w1]))); - dDv = onev / (onev + vabsf(LC2VFU(pix[1][ w2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][w1]) - LC2VFU(pix[c][-w1]))); - v0v = CLIPV(LC2VFU(pix[1][0]) + zd5v - ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); - STC2VFU(pix[c][0], v0v); - } - } - -#endif - - for (; col < width - 2; col += 2) { - int indx = row * width + col; - pix[1] = (float*)(*rgb[1]) + indx; - - for (int i = 0; i < 2; c = 2 - c, i++) { - pix[c] = (float*)(*rgb[c]) + indx; - float dL = 1.f / (1.f + fabsf(pix[1][ -2] - pix[1][0]) + fabsf(pix[c][ 1] - pix[c][ -1])); - float dR = 1.f / (1.f + fabsf(pix[1][ 2] - pix[1][0]) + fabsf(pix[c][ 1] - pix[c][ -1])); - float dU = 1.f / (1.f + fabsf(pix[1][-w2] - pix[1][0]) + fabsf(pix[c][w1] - pix[c][-w1])); - float dD = 1.f / (1.f + fabsf(pix[1][ w2] - pix[1][0]) + fabsf(pix[c][w1] - pix[c][-w1])); - float v0 = (pix[1][0] + 0.5f - ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); - pix[c][0] = CLIP(v0); - } - } - } - - /* Reinforce integrated red/blue pixels on BLUE/RED pixel locations */ -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 2; row < height - 2; row++) { - int col = 2 + (FC(row, 2) & 1); - int c = 2 - FC(row, col); -#ifdef __SSE2__ - __m128 dLv, dRv, dUv, dDv, v0v; - __m128 onev = _mm_set1_ps(1.f); - __m128 zd5v = _mm_set1_ps(0.5f); - __m128 c65535v = _mm_set1_ps(65535.f); - - for (; col < width - 8; col += 8) { - int indx = row * width + col; - pix[0] = (float*)(*rgb[0]) + indx; - pix[1] = (float*)(*rgb[1]) + indx; - pix[2] = (float*)(*rgb[2]) + indx; - int d = 2 - c; - dLv = onev / (onev + vabsf(LC2VFU(pix[d][ -2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); - dRv = onev / (onev + vabsf(LC2VFU(pix[d][ 2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); - dUv = onev / (onev + vabsf(LC2VFU(pix[d][-w2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); - dDv = onev / (onev + vabsf(LC2VFU(pix[d][ w2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); - v0v = CLIPV(LC2VFU(pix[1][0]) + zd5v - ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); - STC2VFU(pix[c][0], v0v); - } - -#endif - - for (; col < width - 2; col += 2) { - int indx = row * width + col; - pix[0] = (float*)(*rgb[0]) + indx; - pix[1] = (float*)(*rgb[1]) + indx; - pix[2] = (float*)(*rgb[2]) + indx; - int d = 2 - c; - float dL = 1.f / (1.f + fabsf(pix[d][ -2] - pix[d][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); - float dR = 1.f / (1.f + fabsf(pix[d][ 2] - pix[d][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); - float dU = 1.f / (1.f + fabsf(pix[d][-w2] - pix[d][0]) + fabsf(pix[1][w1] - pix[1][-w1])); - float dD = 1.f / (1.f + fabsf(pix[d][ w2] - pix[d][0]) + fabsf(pix[1][w1] - pix[1][-w1])); - float v0 = (pix[1][0] + 0.5f - ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); - pix[c][0] = CLIP(v0); - } - } - } // end parallel - } - - t2e.set(); - - if (settings->verbose) { - printf("Refinement Lee %d usec\n", t2e.etime(t1e)); - } -} -#ifdef __SSE2__ -#undef CLIPV -#endif - - -// 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 -// reduce color artifacts, improves the interpolation -// but it's relatively slow -// -// Should be DISABLED if it decreases image quality by increases some image noise and generates blocky edges -void RawImageSource::refinement_lassus(int PassCount) -{ - // const int PassCount=1; - - // if (settings->verbose) printf("Refinement\n"); - - MyTime t1e, t2e; - t1e.set(); - int u = W, v = 2 * u, w = 3 * u, x = 4 * u, y = 5 * u; - float (*image)[3]; - image = (float(*)[3]) calloc(W * H, sizeof * image); -#ifdef _OPENMP - #pragma omp parallel shared(image) -#endif - { - // convert red, blue, green to image -#ifdef _OPENMP - #pragma omp for -#endif - - for (int i = 0; i < H; i++) { - for (int j = 0; j < W; j++) { - image[i * W + j][0] = red [i][j]; - image[i * W + j][1] = green[i][j]; - image[i * W + j][2] = blue [i][j]; - } - } - - for (int b = 0; b < PassCount; b++) { - if (plistener) { - plistener->setProgressStr (M("TP_RAW_DMETHOD_PROGRESSBAR_REFINE")); - plistener->setProgress ((float)b / PassCount); - } - - // Reinforce interpolated green pixels on RED/BLUE pixel locations -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 6; row < H - 6; row++) { - for (int col = 6 + (FC(row, 2) & 1), c = FC(row, col); col < W - 6; col += 2) { - float (*pix)[3] = image + row * W + col; - - // Cubic Spline Interpolation by Li and Randhawa, modified by Luis Sanz Rodriguez - - float f[4]; - f[0] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[-v][c]) - x0875(pix[0][c]) - x0250(pix[-x][c]))) + fabs(x0875(pix[u][1]) - x1125(pix[-u][1]) + x0250(pix[-w][1])) + fabs(x0875(pix[-w][1]) - x1125(pix[-u][1]) + x0250(pix[-y][1]))); - f[1] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[+2][c]) - x0875(pix[0][c]) - x0250(pix[+4][c]))) + fabs(x0875(pix[1][1]) - x1125(pix[-1][1]) + x0250(pix[+3][1])) + fabs(x0875(pix[+3][1]) - x1125(pix[+1][1]) + x0250(pix[+5][1]))); - f[2] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[-2][c]) - x0875(pix[0][c]) - x0250(pix[-4][c]))) + fabs(x0875(pix[1][1]) - x1125(pix[-1][1]) + x0250(pix[-3][1])) + fabs(x0875(pix[-3][1]) - x1125(pix[-1][1]) + x0250(pix[-5][1]))); - f[3] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[+v][c]) - x0875(pix[0][c]) - x0250(pix[+x][c]))) + fabs(x0875(pix[u][1]) - x1125(pix[-u][1]) + x0250(pix[+w][1])) + fabs(x0875(pix[+w][1]) - x1125(pix[+u][1]) + x0250(pix[+y][1]))); - - float g[4];//CLIREF avoid overflow - g[0] = pix[0][c] + (x0875(CLIREF(pix[-u][1] - pix[-u][c])) + x0125(CLIREF(pix[+u][1] - pix[+u][c]))); - g[1] = pix[0][c] + (x0875(CLIREF(pix[+1][1] - pix[+1][c])) + x0125(CLIREF(pix[-1][1] - pix[-1][c]))); - g[2] = pix[0][c] + (x0875(CLIREF(pix[-1][1] - pix[-1][c])) + x0125(CLIREF(pix[+1][1] - pix[+1][c]))); - g[3] = pix[0][c] + (x0875(CLIREF(pix[+u][1] - pix[+u][c])) + x0125(CLIREF(pix[-u][1] - pix[-u][c]))); - - pix[0][1] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); - - } - } - - // Reinforce interpolated red/blue pixels on GREEN pixel locations -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 6; row < H - 6; row++) { - for (int col = 6 + (FC(row, 3) & 1), c = FC(row, col + 1); col < W - 6; col += 2) { - float (*pix)[3] = image + row * W + col; - - for (int i = 0; i < 2; c = 2 - c, i++) { - float f[4]; - f[0] = 1.0f / (1.0f + xmul2f(fabs(x0875(pix[-v][1]) - x1125(pix[0][1]) + x0250(pix[-x][1]))) + fabs(pix[u] [c] - pix[-u][c]) + fabs(pix[-w][c] - pix[-u][c])); - f[1] = 1.0f / (1.0f + xmul2f(fabs(x0875(pix[+2][1]) - x1125(pix[0][1]) + x0250(pix[+4][1]))) + fabs(pix[+1][c] - pix[-1][c]) + fabs(pix[+3][c] - pix[+1][c])); - f[2] = 1.0f / (1.0f + xmul2f(fabs(x0875(pix[-2][1]) - x1125(pix[0][1]) + x0250(pix[-4][1]))) + fabs(pix[+1][c] - pix[-1][c]) + fabs(pix[-3][c] - pix[-1][c])); - f[3] = 1.0f / (1.0f + xmul2f(fabs(x0875(pix[+v][1]) - x1125(pix[0][1]) + x0250(pix[+x][1]))) + fabs(pix[u] [c] - pix[-u][c]) + fabs(pix[+w][c] - pix[+u][c])); - - float g[5];//CLIREF avoid overflow - g[0] = CLIREF(pix[-u][1] - pix[-u][c]); - g[1] = CLIREF(pix[+1][1] - pix[+1][c]); - g[2] = CLIREF(pix[-1][1] - pix[-1][c]); - g[3] = CLIREF(pix[+u][1] - pix[+u][c]); - g[4] = ((f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3])); - pix[0][c] = pix[0][1] - (0.65f * g[4] + 0.35f * CLIREF(pix[0][1] - pix[0][c])); - } - } - } - - // Reinforce integrated red/blue pixels on BLUE/RED pixel locations -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 6; row < H - 6; row++) { - for (int col = 6 + (FC(row, 2) & 1), c = 2 - FC(row, col), d = 2 - c; col < W - 6; col += 2) { - float (*pix)[3] = image + row * W + col; - - float f[4]; - f[0] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[-v][d]) - x0875(pix[0][d]) - x0250(pix[-x][d]))) + fabs(x0875(pix[u][1]) - x1125(pix[-u][1]) + x0250(pix[-w][1])) + fabs(x0875(pix[-w][1]) - x1125(pix[-u][1]) + x0250(pix[-y][1]))); - f[1] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[+2][d]) - x0875(pix[0][d]) - x0250(pix[+4][d]))) + fabs(x0875(pix[1][1]) - x1125(pix[-1][1]) + x0250(pix[+3][1])) + fabs(x0875(pix[+3][1]) - x1125(pix[+1][1]) + x0250(pix[+5][1]))); - f[2] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[-2][d]) - x0875(pix[0][d]) - x0250(pix[-4][d]))) + fabs(x0875(pix[1][1]) - x1125(pix[-1][1]) + x0250(pix[-3][1])) + fabs(x0875(pix[-3][1]) - x1125(pix[-1][1]) + x0250(pix[-5][1]))); - f[3] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[+v][d]) - x0875(pix[0][d]) - x0250(pix[+x][d]))) + fabs(x0875(pix[u][1]) - x1125(pix[-u][1]) + x0250(pix[+w][1])) + fabs(x0875(pix[+w][1]) - x1125(pix[+u][1]) + x0250(pix[+y][1]))); - - float g[5]; - g[0] = (x0875((pix[-u][1] - pix[-u][c])) + x0125((pix[-v][1] - pix[-v][c]))); - g[1] = (x0875((pix[+1][1] - pix[+1][c])) + x0125((pix[+2][1] - pix[+2][c]))); - g[2] = (x0875((pix[-1][1] - pix[-1][c])) + x0125((pix[-2][1] - pix[-2][c]))); - g[3] = (x0875((pix[+u][1] - pix[+u][c])) + x0125((pix[+v][1] - pix[+v][c]))); - - g[4] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); - - const std::array p = { - pix[-u - 1][1] - pix[-u - 1][c], - pix[-u + 0][1] - pix[-u + 0][c], - pix[-u + 1][1] - pix[-u + 1][c], - pix[+0 - 1][1] - pix[+0 - 1][c], - pix[+0 + 0][1] - pix[+0 + 0][c], - pix[+0 + 1][1] - pix[+0 + 1][c], - pix[+u - 1][1] - pix[+u - 1][c], - pix[+u + 0][1] - pix[+u + 0][c], - pix[+u + 1][1] - pix[+u + 1][c] - }; - - const float med = median(p); - - pix[0][c] = LIM(pix[0][1] - (1.30f * g[4] - 0.30f * (pix[0][1] - pix[0][c])), 0.99f * (pix[0][1] - med), 1.01f * (pix[0][1] - med)); - - } - } - - } - - // put modified values to red, green, blue -#ifdef _OPENMP - #pragma omp for -#endif - - for (int i = 0; i < H; i++) { - for (int j = 0; j < W; j++) { - red [i][j] = image[i * W + j][0]; - green[i][j] = image[i * W + j][1]; - blue [i][j] = image[i * W + j][2]; - } - } - } - - free(image); - - t2e.set(); - - if (settings->verbose) { - printf("Refinement Lassus %d usec\n", t2e.etime(t1e)); - } -} - - /* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -2787,9 +1518,9 @@ BENCHFUN */ for(int y = 0; y < TILESIZE && y0 + y < H; y++) { for (int j = 0; j < TILESIZE && x0 + j < W; j++) { - red[y0 + y][x0 + j] = tile[(y + TILEBORDER) * CACHESIZE + TILEBORDER + j][0]; - green[y0 + y][x0 + j] = tile[(y + TILEBORDER) * CACHESIZE + TILEBORDER + j][1]; - blue[y0 + y][x0 + j] = tile[(y + TILEBORDER) * CACHESIZE + TILEBORDER + j][2]; + red[y0 + y][x0 + j] = std::max(0.f, tile[(y + TILEBORDER) * CACHESIZE + TILEBORDER + j][0]); + green[y0 + y][x0 + j] = std::max(0.f, tile[(y + TILEBORDER) * CACHESIZE + TILEBORDER + j][1]); + blue[y0 + y][x0 + j] = std::max(0.f, tile[(y + TILEBORDER) * CACHESIZE + TILEBORDER + j][2]); } } @@ -2812,7 +1543,7 @@ BENCHFUN free(buffer0); } - border_interpolate2(W, H, 1, rawData, red, green, blue); + border_interpolate(W, H, 1, rawData, red, green, blue); if(plistener) { plistener->setProgress (1.0); } diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc index c41c8a180..1fb1d2e1b 100644 --- a/rtengine/dfmanager.cc +++ b/rtengine/dfmanager.cc @@ -14,25 +14,29 @@ * GNU General Public License for more details. * * 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" -#include -#include "../rtgui/guiutils.h" -#include "rawimage.h" + #include #include #include -#include "imagedata.h" +#include #include +#include "dfmanager.h" +#include "../rtgui/options.h" +#include "rawimage.h" +#include "imagedata.h" +#include "utils.h" + namespace rtengine { -extern const Settings* settings; - // *********************** class dfInfo ************************************** +dfInfo::~dfInfo() +{ + delete ri; +} inline dfInfo& dfInfo::operator =(const dfInfo &o) { @@ -328,8 +332,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 541981492..b23981ffb 100644 --- a/rtengine/dfmanager.h +++ b/rtengine/dfmanager.h @@ -14,23 +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 . */ #pragma once #include +#include #include #include #include #include "pixelsmap.h" -#include "rawimage.h" namespace rtengine { -class dfInfo +class RawImage; +class dfInfo final { public: @@ -48,13 +49,7 @@ public: dfInfo( const dfInfo &o) : pathname(o.pathname), maker(o.maker), model(o.model), iso(o.iso), shutter(o.shutter), timestamp(o.timestamp), ri(nullptr) {} - ~dfInfo() - { - if( ri ) { - delete ri; - } - } - + ~dfInfo(); dfInfo &operator =(const dfInfo &o); bool operator <(const dfInfo &e2) const; @@ -79,7 +74,7 @@ protected: void updateRawImage(); }; -class DFManager +class DFManager final { public: void init(const Glib::ustring &pathname); diff --git a/rtengine/diagonalcurves.cc b/rtengine/diagonalcurves.cc index b4c88fd68..e81f2fe92 100644 --- a/rtengine/diagonalcurves.cc +++ b/rtengine/diagonalcurves.cc @@ -14,10 +14,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 . */ -#include -#include #include "curves.h" #include #include @@ -230,7 +228,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 +311,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 +325,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 +504,6 @@ double DiagonalCurve::getVal (double t) const ++d; } return LIM01(*(poly_y.begin() + d)); - break; } case DCT_NURBS : { diff --git a/rtengine/diagonalcurvetypes.h b/rtengine/diagonalcurvetypes.h new file mode 100644 index 000000000..0d304957a --- /dev/null +++ b/rtengine/diagonalcurvetypes.h @@ -0,0 +1,31 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2019 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 . +*/ +#pragma once + +// For compatibility and simplicity reason, order shouldn't change, and must be identical to the order specified in the curveType widget +enum DiagonalCurveType { + DCT_Empty = -1, // Also used for identity curves + DCT_Linear, // 0 + DCT_Spline, // 1 + DCT_Parametric, // 2 + DCT_NURBS, // 3 + DCT_CatumullRom, // 4 + // Insert new curve type above this line + DCT_Unchanged // Must remain the last of the enum +}; diff --git a/rtengine/dirpyr_equalizer.cc b/rtengine/dirpyr_equalizer.cc index 7681b4c93..9d48bea47 100644 --- a/rtengine/dirpyr_equalizer.cc +++ b/rtengine/dirpyr_equalizer.cc @@ -12,280 +12,558 @@ * GNU General Public License for more details. * * 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 #include -#include "improcfun.h" +#include + #include "array2D.h" -#include "rt_math.h" +#include "cieimage.h" +#include "color.h" +#include "curves.h" +#include "improcfun.h" +#include "LUT.h" #include "opthelper.h" #include "boxblur.h" +#include "rt_math.h" +#include "settings.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]))) ) -#define CLIPLL(x) LIM(x,0.f,32768.f) -#define CLIPLLN(x) LIM(-32768.f,0.f,32768.f) +namespace { + +float rangeFn(float i) { + return 1.f / (i + 1000.f); +} + + +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) { + //generate domain kernel + // 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__ + const vfloat thousandv = F2V(1000.f); +#endif + +#ifdef _OPENMP + #pragma omp for +#endif + + 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 = std::max(0, i - scalewin); inbr <= std::min(height - 1, i + scalewin); inbr += scale) { + for (int jnbr = std::max(0, 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 + } + +#ifdef __SSE2__ + + 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) { + 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; + } + } + STVFU(data_coarse[i][j], valv / normv); //low pass filter + } +#endif + for (; j < width - scalewin; j++) { + float val = 0.f; + float norm = 0.f; + + for (int inbr = std::max(0, i - scalewin); inbr <= std::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 = std::max(0, i - scalewin); inbr <= std::min(height - 1, i + scalewin); inbr += scale) { + for (int jnbr = j - scalewin; jnbr <= std::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 +#ifdef _OPENMP + #pragma omp parallel +#endif + { +#ifdef __SSE2__ + const vfloat thousandv = F2V(1000.0f); +#endif +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) +#endif + + for (int i = 0; i < height; i++) + { + int j = 0; + for (; j < scale; j++) { + float val = 0.f; + float norm = 0.f; + + for (int inbr = std::max(0, i - scale); inbr <= std::min(height - 1, i + scale); inbr += scale) { + for (int jnbr = std::max(0, 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 + } + +#ifdef __SSE2__ + + 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 jnbr = j - scale; jnbr <= j + scale; jnbr += scale) { + const vfloat dftemp2v = LVFU(data_fine[inbr][jnbr]); + const vfloat dirwtv = thousandv / (vabsf(dftemp2v - dftemp1v) + thousandv); + valv += dirwtv * dftemp2v; + normv += dirwtv; + } + } + STVFU(data_coarse[i][j], valv / normv); //low pass filter + } +#endif + + for (; j < width - scale; j++) { + float val = 0.f; + float norm = 0.f; + + for (int inbr = std::max(0, i - scale); inbr <= std::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 = std::max(0, i - scale); inbr <= std::min(height - 1, i + scale); inbr += scale) { + for (int jnbr = j - scale; jnbr <= std::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 + } + } + } + } +} + +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_loc(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float mult, const float blurcb, const double dirpyrThreshold, float ** hue, float ** chrom, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scaleprev, bool multiThread) +{ + LUTf irangefn(0x20000); + fillLut(irangefn, level, dirpyrThreshold, mult, 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]); + buffer[i][j] += irangefn[hipass + 0x10000] * hipass; + + } + } + + if(blurcb > 0.f && choice == 0 && level != 5) { + 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 + } + AlignedBuffer blurbufcbdl(width * height); + float rad = 0.05f * blurcb * fabs((level + 1) * (multbis - 1.f)) / scaleprev; + // printf("rad=%f level=%i\n", rad, level); + +#ifdef _OPENMP + #pragma omp parallel if (multiThread) +#endif +// rtengine::boxblur(buffer, buffer, blurbufcbdl.data, rad, rad, width, height); + rtengine::boxblur(buffer, buffer, rad, width, height, false); + blurbufcbdl.resize(0); + } + + irangefn.clear(); +} + +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); + + LUTf irangefn(0x20000); + fillLut(irangefn, level, dirpyrThreshold, mult, skinprot); + + 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++) { + float scale = 1.f; + 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 { +#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 scale = 1.f; + 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; + } else { //image soft with scale < 1 ==> skin + buffer[i][j] += (1.f + correct) * hipass; + } + } + } + } +} + +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; + + LUTf irangefn(0x20000); + fillLut(irangefn, level, dirpyrThreshold, mult, skinprot); + + 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 { +#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; + 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; + } else { //image soft + buffer[i][j] += (1.f + correct) * hipass; + } + } + } + } +} + +} namespace rtengine { -constexpr int maxlevel = 6; -constexpr int maxlevelloc = 6;//5 -constexpr float noise = 2000; - -//sequence of scales -constexpr int scales[maxlevel] = {1, 2, 4, 8, 16, 32}; -constexpr int scalesloc[6] = {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) +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; - - 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); + --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]; + float multi[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]; - } + 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); + multi_array2D dirpyrlo (srcwidth, srcheight); - level = 0; + dirpyr_channel(src, dirpyrlo[0], srcwidth, srcheight, 0, std::max(scales[0] / scaleprev, 1)); - //int thresh = 100 * mult[5]; - int scale = (int)(scales[level]) / scaleprev; - - if (scale < 1) { - scale = 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; - 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) { + 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 = new float*[srcheight]; + tmpHue(srcwidth, srcheight); + tmpChr(srcwidth, 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 __SSE2__ + const vfloat div = F2V(327.68f); +#endif #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); + 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; } } } -#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]; + 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); + 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); } - 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; - } + 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 i = 0; i < srcheight; i++) { for (int j = 0; j < srcwidth; j++) { - dst[i][j] = /*CLIP*/(buffer[i][j]); // TODO: Really a clip necessary? + dst[i][j] = buffer[i][j]; } + } +} +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) +{ + + //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 (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]; + } + } + } } void ImProcFunctions::cbdl_local_temp(float ** src, float ** loctemp, int srcwidth, int srcheight, const float * mult, float kchro, const double dirpyrThreshold, const float mergeL, const float contres, const float blurcb, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scaleprev, bool multiThread) { + constexpr int maxlevelloc = 6; + constexpr int scalesloc[maxlevelloc] = {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 = maxlevelloc; if (settings->verbose) { printf("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; - } - - 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--; @@ -296,29 +574,14 @@ void ImProcFunctions::cbdl_local_temp(float ** src, float ** loctemp, int srcwid return; } - int level; - float multi[6] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f}; - float scalefl[6]; + float multi[6]; - for (int lv = 0; lv < 6; lv++) { - scalefl[lv] = ((float) scalesloc[lv]) / (float) scaleprev; - - if (lv >= 1) { - if (scalefl[lv] < 1.f) { - if (mult[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) { - if (mult[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]; - } + for (int lv = 0; lv < 6; ++lv) { + if (scalesloc[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]; } } @@ -328,31 +591,12 @@ void ImProcFunctions::cbdl_local_temp(float ** src, float ** loctemp, int srcwid multi_array2D dirpyrlo(srcwidth, srcheight); - level = 0; - //int thresh = 100 * mult[5]; - int scale = (int)(scalesloc[level]) / scaleprev; - - if (scale < 1) { - scale = 1; - } + dirpyr_channel(src, dirpyrlo[0], srcwidth, srcheight, 0, std::max(scalesloc[0] / scaleprev, 1)); - dirpyr_channel(src, dirpyrlo[0], srcwidth, srcheight, 0, scale); - - level = 1; - - while (level < lastlevel) { - - scale = (int)(scalesloc[level]) / scaleprev; - - if (scale < 1) { - scale = 1; - } - - dirpyr_channel(dirpyrlo[level - 1], dirpyrlo[level], srcwidth, srcheight, level, scale); - - level ++; + for (int level = 1; level < lastlevel; ++level) { + dirpyr_channel(dirpyrlo[level - 1], dirpyrlo[level], srcwidth, srcheight, level, std::max(scalesloc[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 @@ -360,13 +604,13 @@ void ImProcFunctions::cbdl_local_temp(float ** src, float ** loctemp, int srcwid array2D residbuff(srcwidth, srcheight); array2D resid5(srcwidth, srcheight); - #pragma omp parallel for + #pragma omp parallel for for (int i = 0; i < srcheight; i++) for (int j = 0; j < srcwidth; j++) { residbuff[i][j] = 0.f; } - #pragma omp parallel for + #pragma omp parallel for for (int i = 0; i < srcheight; i++) for (int j = 0; j < srcwidth; j++) { residbuff[i][j] = dirpyrlo[lastlevel - 1][i][j]; @@ -377,6 +621,8 @@ void ImProcFunctions::cbdl_local_temp(float ** src, float ** loctemp, int srcwid double avg = 0.f; if(contres != 0.f) { int ng = 0; + + #pragma omp parallel for reduction(+:avg, ng) for (int i = 0; i < srcheight; i++) { for (int j = 0; j < srcwidth; j++) { avg += residbuff[i][j]; @@ -409,19 +655,19 @@ void ImProcFunctions::cbdl_local_temp(float ** src, float ** loctemp, int srcwid for (int level = lastlevel - 1; level > 0; level--) { - idirpyr_eq_channel_loc(dirpyrlo[level], dirpyrlo[level - 1], residbuff, srcwidth, srcheight, level, multi, blurcb, dirpyrThreshold, nullptr, nullptr, skinprot, gamutlab, b_l, t_l, t_r, b_r, choice, scaleprev, multiThread); + idirpyr_eq_channel_loc(dirpyrlo[level], dirpyrlo[level - 1], residbuff, srcwidth, srcheight, level, multi[level], blurcb, dirpyrThreshold, nullptr, nullptr, skinprot, gamutlab, b_l, t_l, t_r, b_r, choice, scaleprev, multiThread); } scale = scalesloc[0]; - idirpyr_eq_channel_loc(dirpyrlo[0], src, residbuff, srcwidth, srcheight, 0, multi, blurcb, dirpyrThreshold, nullptr, nullptr, skinprot, gamutlab, b_l, t_l, t_r, b_r, choice, scaleprev, multiThread); + idirpyr_eq_channel_loc(dirpyrlo[0], src, residbuff, srcwidth, srcheight, 0, multi[0], blurcb, dirpyrThreshold, nullptr, nullptr, skinprot, gamutlab, b_l, t_l, t_r, b_r, choice, scaleprev, multiThread); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% array2D loct(srcwidth, srcheight); #pragma omp parallel for for (int i = 0; i < srcheight; i++) for (int j = 0; j < srcwidth; j++) { - loct[i][j] = CLIPLL(residbuff[i][j]); // TODO: Really a clip necessary? + loct[i][j] = LIM(residbuff[i][j],0.f,32768.f); // TODO: Really a clip necessary? } float clar = 0.01f * mergeL; @@ -436,657 +682,15 @@ void ImProcFunctions::cbdl_local_temp(float ** src, float ** loctemp, int srcwid #pragma omp parallel for for (int i = 0; i < srcheight; i++) for (int j = 0; j < srcwidth; j++) { - loctemp[i][j] = CLIPLL((1.f + clar) * loct[i][j] - clar * resid5[i][j]); + loctemp[i][j] = LIM((1.f + clar) * loct[i][j] - clar * resid5[i][j],0.f,32768.f); } } else { #pragma omp parallel for for (int i = 0; i < srcheight; i++) for (int j = 0; j < srcwidth; j++) { - loctemp[i][j] = CLIPLL(loct[i][j]); + loctemp[i][j] = LIM(loct[i][j],0.f,32768.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) -{ - // scale is spacing of directional averaging weights - // calculate weights, compute directionally weighted average - - 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; -#ifdef _OPENMP - #pragma omp parallel -#endif - { -#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) -#endif - - for (int i = 0; i < height; i++) { - float dirwt; - - 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 jnbr = max(0, j - scalewin); jnbr <= j + scalewin; jnbr += scale) { - //printf("i=%d ",(inbr-i)/scale+halfwin); - dirwt = DIRWT(inbr, jnbr, i, j); - val += dirwt * data_fine[inbr][jnbr]; - norm += dirwt; - } - } - - data_coarse[i][j] = val / norm; //low pass filter - } - -#ifdef __SSE2__ - - for (; j < width - scalewin - 3; j += 4) { - valv = _mm_setzero_ps(); - normv = _mm_setzero_ps(); - 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); - valv += dirwtv * dftemp2v; - normv += dirwtv; - } - } - - _mm_storeu_ps(&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++) { - 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); - 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; -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) -#endif - - for (int i = 0; i < height; i++) - { - float dirwt; - - for (j = 0; 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 jnbr = max(0, 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 - } - -#ifdef __SSE2__ - - for (; j < width - scale - 3; j += 4) { - valv = _mm_setzero_ps(); - normv = _mm_setzero_ps(); - dftemp1v = LVFU(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) { - dftemp2v = LVFU(data_fine[inbr][jnbr]); - dirwtv = thousandv / (vabsf(dftemp2v - dftemp1v) + thousandv); - valv += dirwtv * dftemp2v; - normv += dirwtv; - } - } - - _mm_storeu_ps(&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++) { - 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])); - val += dirwt * data_fine[inbr][jnbr]; - norm += dirwt; - } - } - - data_coarse[i][j] = val / norm; //low pass filter - } - } - } - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void ImProcFunctions::idirpyr_eq_channel_loc(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float mult[6], const float blurcb, const double dirpyrThreshold, float ** hue, float ** chrom, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scaleprev, bool multiThread) -{ - // const float skinprotneg = -skinprot; -// const float factorHard = (1.f - skinprotneg / 100.f); - - float offs; - - if (skinprot == 0.f) { - offs = 0.f; - } else { - offs = -1.f; - } - float multbis[6]; - - 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); - } - - double sensicrash = 1.;//settings->cbdlsensi; - LUTf irangefn(0x20000); - { - const float noisehi = 1.33f * noise * sensicrash * dirpyrThreshold / expf(level * log(3.0)), noiselo = 0.66f * noise * sensicrash * dirpyrThreshold / expf(level * log(3.0)); - // printf("level=%i multlev=%f noisehi=%f noiselo=%f skinprot=%f\n",level,mult[level], noisehi, noiselo, skinprot); - // printf("noihi=%f noilo=%f\n", noisehi, noiselo); - - 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) ; - } - } - } - } - - - -#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; - - } - } - - if(blurcb > 0.f && choice == 0 && level != 5) { - AlignedBuffer blurbufcbdl(width * height); - float rad = 0.05f * blurcb * fabs((level + 1) * (multbis[level] - 1.f)) / scaleprev; - // printf("rad=%f level=%i\n", rad, level); - -#ifdef _OPENMP - #pragma omp parallel if (multiThread) -#endif - boxblur(buffer, buffer, blurbufcbdl.data, rad, rad, width, height); - blurbufcbdl.resize(0); - } - - irangefn.clear(); -} - -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) -{ - const float skinprotneg = -skinprot; - const float factorHard = (1.f - skinprotneg / 100.f); - - float offs; - - 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) -#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 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 ; - } - } 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 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]; - - if (scale == 1.f) {//image hard - buffer[i][j] += (1.f + (correct) * (factorHard)) * hipass ; - } else { //image soft with scale < 1 ==> skin - 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) -{ - - const float skinprotneg = -skinprot; - const float factorHard = (1.f - skinprotneg / 100.f); - - float offs; - - 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) -#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]); - 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); - - if (scale == 1.f) {//image hard - buffer[i][j] += (1.f + (correct) * factorHard) * hipass ; - - } else { //image soft - 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; - } - */ -} - -// float hipass = (data_fine[i][j]-data_coarse[i][j]); -// buffer[i][j] += irangefn[hipass+0x10000] * hipass ; - -#undef DIRWT_L -#undef DIRWT_AB - -#undef NRWT_L -#undef NRWT_AB - -} - diff --git a/rtengine/dual_demosaic_RT.cc b/rtengine/dual_demosaic_RT.cc index 4873ee670..93508808c 100644 --- a/rtengine/dual_demosaic_RT.cc +++ b/rtengine/dual_demosaic_RT.cc @@ -19,40 +19,44 @@ // 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 "color.h" #include "jaggedarray.h" -#include "rtengine.h" -#include "rawimagesource.h" -#include "rt_math.h" #include "procparams.h" +#include "rawimagesource.h" +#include "rt_algo.h" +#include "rt_math.h" +#include "rtengine.h" + +#include "../rtgui/options.h" + //#define BENCHMARK #include "StopWatch.h" -#include "rt_algo.h" using namespace std; namespace rtengine { -void RawImageSource::dual_demosaic_RT(bool isBayer, const RAWParams &raw, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, double &contrast, bool autoContrast) +void RawImageSource::dual_demosaic_RT(bool isBayer, const procparams::RAWParams &raw, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, double &contrast, bool autoContrast) { BENCHFUN if (contrast == 0.f && !autoContrast) { // contrast == 0.0 means only first demosaicer will be used if(isBayer) { - if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZEVNG4) ) { + if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEVNG4) ) { amaze_demosaic_RT(0, 0, winw, winh, rawData, red, green, blue, options.chunkSizeAMAZE, options.measure); - } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::DCBVNG4) ) { + } else if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBVNG4) ) { dcb_demosaic(raw.bayersensor.dcb_iterations, raw.bayersensor.dcb_enhance); - } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::RCDVNG4) ) { + } else if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCDVNG4) ) { rcd_demosaic(options.chunkSizeRCD, options.measure); } } else { - if (raw.xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FOUR_PASS) ) { + if (raw.xtranssensor.method == procparams::RAWParams::XTransSensor::getMethodString(procparams::RAWParams::XTransSensor::Method::FOUR_PASS) ) { xtrans_interpolate (3, true, options.chunkSizeXT, options.measure); } else { xtrans_interpolate (1, false, options.chunkSizeXT, options.measure); @@ -62,28 +66,22 @@ void RawImageSource::dual_demosaic_RT(bool isBayer, const RAWParams &raw, int wi return; } - array2D redTmp(winw, winh); - array2D greenTmp(winw, winh); - array2D blueTmp(winw, winh); array2D L(winw, winh); if (isBayer) { - vng4_demosaic(rawData, redTmp, greenTmp, blueTmp); - - if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZEVNG4) || raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::PIXELSHIFT)) { + if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEVNG4) || raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::PIXELSHIFT)) { amaze_demosaic_RT(0, 0, winw, winh, rawData, red, green, blue, options.chunkSizeAMAZE, options.measure); - } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::DCBVNG4) ) { + } else if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBVNG4) ) { dcb_demosaic(raw.bayersensor.dcb_iterations, raw.bayersensor.dcb_enhance); - } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::RCDVNG4) ) { + } else if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCDVNG4) ) { rcd_demosaic(options.chunkSizeRCD, options.measure); } } else { - if (raw.xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FOUR_PASS) ) { + if (raw.xtranssensor.method == procparams::RAWParams::XTransSensor::getMethodString(procparams::RAWParams::XTransSensor::Method::FOUR_PASS) ) { xtrans_interpolate (3, true, options.chunkSizeXT, options.measure); } else { xtrans_interpolate (1, false, options.chunkSizeXT, options.measure); } - fast_xtrans_interpolate(rawData, redTmp, greenTmp, blueTmp); } const float xyz_rgb[3][3] = { // XYZ from RGB @@ -107,9 +105,20 @@ void RawImageSource::dual_demosaic_RT(bool isBayer, const RAWParams &raw, int wi JaggedArray blend(winw, winh); float contrastf = contrast / 100.f; - buildBlendMask(L, blend, winw, winh, contrastf, 1.f, autoContrast); + buildBlendMask(L, blend, winw, winh, contrastf, autoContrast); contrast = contrastf * 100.f; + array2D& redTmp = L; // L is not needed anymore => reuse it + array2D greenTmp(winw, winh); + array2D blueTmp(winw, winh); + + if (isBayer) { + vng4_demosaic(rawData, redTmp, greenTmp, blueTmp); + } else { + fast_xtrans_interpolate(rawData, redTmp, greenTmp, blueTmp); + } + + // the following is split into 3 loops intentionally to avoid cache conflicts on CPUs with only 4-way cache #ifdef _OPENMP #pragma omp parallel for diff --git a/rtengine/dynamicprofile.cc b/rtengine/dynamicprofile.cc index 7b7f2a517..617ec2747 100644 --- a/rtengine/dynamicprofile.cc +++ b/rtengine/dynamicprofile.cc @@ -14,13 +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 . */ -#include "../rtengine/dynamicprofile.h" +#include "dynamicprofile.h" #include #include +#include +#include + +#include "rtengine.h" +#include "../rtgui/options.h" using namespace rtengine; using namespace rtengine::procparams; @@ -176,7 +181,7 @@ bool DynamicProfileRules::loadRules() return false; } - if (options.rtSettings.verbose) { + if (settings->verbose) { printf ("loading dynamic profiles...\n"); } @@ -195,7 +200,7 @@ bool DynamicProfileRules::loadRules() return false; } - if (options.rtSettings.verbose) { + if (settings->verbose) { printf (" loading rule %d\n", serial); } @@ -225,7 +230,7 @@ bool DynamicProfileRules::loadRules() bool DynamicProfileRules::storeRules() { - if (options.rtSettings.verbose) { + if (settings->verbose) { printf ("saving dynamic profiles...\n"); } diff --git a/rtengine/dynamicprofile.h b/rtengine/dynamicprofile.h index fc5c85e4c..d91b91aee 100644 --- a/rtengine/dynamicprofile.h +++ b/rtengine/dynamicprofile.h @@ -14,14 +14,17 @@ * GNU General Public License for more details. * * 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_ +#pragma once -#include +#include #include -#include "../rtgui/options.h" + +namespace rtengine +{ + class FramesMetaData; +} class DynamicProfileRule { @@ -76,5 +79,3 @@ public: const std::vector &getRules(); void setRules (const std::vector &r); }; - -#endif // _DYNAMICPROFILE_H_ diff --git a/rtengine/eahd_demosaic.cc b/rtengine/eahd_demosaic.cc index 1663a087d..ad4bda3cd 100644 --- a/rtengine/eahd_demosaic.cc +++ b/rtengine/eahd_demosaic.cc @@ -15,19 +15,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 . */ #include #include "color.h" +#include "rawimage.h" #include "rawimagesource.h" #include "rawimagesource_i.h" #include "jaggedarray.h" -#include "rawimage.h" #include "iccmatrices.h" #include "rt_math.h" #include "../rtgui/multilangmgr.h" -#include "procparams.h" //#define BENCHMARK #include "StopWatch.h" @@ -401,11 +400,11 @@ void RawImageSource::eahd_demosaic () int vc = homv[imx][j]; if (hc > vc) { - green[i - 1][j] = gh[(i - 1) % 4][j]; + green[i - 1][j] = std::max(0.f, gh[(i - 1) % 4][j]); } else if (hc < vc) { - green[i - 1][j] = gv[(i - 1) % 4][j]; + green[i - 1][j] = std::max(0.f, gv[(i - 1) % 4][j]); } else { - green[i - 1][j] = (gh[(i - 1) % 4][j] + gv[(i - 1) % 4][j]) / 2; + green[i - 1][j] = std::max(0.f, (gh[(i - 1) % 4][j] + gv[(i - 1) % 4][j]) / 2); } } } @@ -422,11 +421,11 @@ void RawImageSource::eahd_demosaic () int vc = homv[(i - 1) % 3][j]; if (hc > vc) { - green[i - 1][j] = gh[(i - 1) % 4][j]; + green[i - 1][j] = std::max(0.f, gh[(i - 1) % 4][j]); } else if (hc < vc) { - green[i - 1][j] = gv[(i - 1) % 4][j]; + green[i - 1][j] = std::max(0.f, gv[(i - 1) % 4][j]); } else { - green[i - 1][j] = (gh[(i - 1) % 4][j] + gv[(i - 1) % 4][j]) / 2; + green[i - 1][j] = std::max(0.f, (gh[(i - 1) % 4][j] + gv[(i - 1) % 4][j]) / 2); } } 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..772096b87 100644 --- a/rtengine/fast_demo.cc +++ b/rtengine/fast_demo.cc @@ -18,19 +18,25 @@ // 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 "rawimagesource.h" #include "../rtgui/multilangmgr.h" -#include "procparams.h" #include "opthelper.h" using namespace std; using namespace rtengine; +namespace +{ +unsigned fc(const unsigned int cfa[2][2], int r, int c) { + return cfa[r & 1][c & 1]; +} +} + #define TS 224 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -67,6 +73,7 @@ void RawImageSource::fast_demosaic() } + const unsigned int cfarray[2][2] = {{FC(0,0), FC(0,1)}, {FC(1,0), FC(1,1)}}; const int bord = 5; float clip_pt = 4 * 65535 * initialGain; @@ -117,12 +124,12 @@ void RawImageSource::fast_demosaic() for (int i1 = imin; i1 < imax; i1++) for (int j1 = jmin; j1 < j + 2; j1++) { - int c = FC(i1, j1); + int c = fc(cfarray, i1, j1); sum[c] += rawData[i1][j1]; sum[c + 3]++; } - int c = FC(i, j); + int c = fc(cfarray, i, j); if (c == 1) { red[i][j] = sum[0] / sum[3]; @@ -150,12 +157,12 @@ void RawImageSource::fast_demosaic() for (int i1 = imin; i1 < imax; i1++) for (int j1 = j - 1; j1 < jmax; j1++) { - int c = FC(i1, j1); + int c = fc(cfarray, i1, j1); sum[c] += rawData[i1][j1]; sum[c + 3]++; } - int c = FC(i, j); + int c = fc(cfarray, i, j); if (c == 1) { red[i][j] = sum[0] / sum[3]; @@ -193,12 +200,12 @@ void RawImageSource::fast_demosaic() for (int i1 = max(0, i - 1); i1 < i + 2; i1++) for (int j1 = j - 1; j1 < j + 2; j1++) { - int c = FC(i1, j1); + int c = fc(cfarray, i1, j1); sum[c] += rawData[i1][j1]; sum[c + 3]++; } - int c = FC(i, j); + int c = fc(cfarray, i, j); if (c == 1) { red[i][j] = sum[0] / sum[3]; @@ -224,12 +231,12 @@ void RawImageSource::fast_demosaic() for (int i1 = i - 1; i1 < min(i + 2, H); i1++) for (int j1 = j - 1; j1 < j + 2; j1++) { - int c = FC(i1, j1); + int c = fc(cfarray, i1, j1); sum[c] += rawData[i1][j1]; sum[c + 3]++; } - int c = FC(i, j); + int c = fc(cfarray, i, j); if (c == 1) { red[i][j] = sum[0] / sum[3]; @@ -282,7 +289,7 @@ void RawImageSource::fast_demosaic() vmask selmask; vmask andmask = _mm_set_epi32( 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff ); - if(FC(top, left) == 1) { + if(fc(cfarray, top, left) == 1) { selmask = _mm_set_epi32( 0, 0xffffffff, 0, 0xffffffff ); } else { selmask = _mm_set_epi32( 0xffffffff, 0, 0xffffffff, 0 ); @@ -312,7 +319,7 @@ void RawImageSource::fast_demosaic() for (; j < right; j++, cc++) { - if (FC(i, j) == 1) { + if (fc(cfarray, i, j) == 1) { greentile[rr * TS + cc] = rawData[i][j]; } else { @@ -333,7 +340,7 @@ void RawImageSource::fast_demosaic() #else for (int j = left, cc = 0; j < right; j++, cc++) { - if (FC(i, j) == 1) { + if (fc(cfarray, i, j) == 1) { greentile[rr * TS + cc] = rawData[i][j]; } else { //compute directional weights using image gradients @@ -359,7 +366,7 @@ void RawImageSource::fast_demosaic() #endif for (int i = top + 1, rr = 1; i < bottom - 1; i++, rr++) { - if (FC(i, left + (FC(i, 2) & 1) + 1) == 0) + if (fc(cfarray, i, left + (fc(cfarray, i, 2) & 1) + 1) == 0) #ifdef __SSE2__ for (int j = left + 1, cc = 1; j < right - 1; j += 4, cc += 4) { //interpolate B/R colors at R/B sites @@ -369,7 +376,7 @@ void RawImageSource::fast_demosaic() #else - for (int cc = (FC(i, 2) & 1) + 1, j = left + cc; j < right - 1; j += 2, cc += 2) { + for (int cc = (fc(cfarray, i, 2) & 1) + 1, j = left + cc; j < right - 1; j += 2, cc += 2) { //interpolate B/R colors at R/B sites bluetile[rr * TS + cc] = greentile[rr * TS + cc] - 0.25f * ((greentile[(rr - 1) * TS + (cc - 1)] + greentile[(rr - 1) * TS + (cc + 1)] + greentile[(rr + 1) * TS + cc + 1] + greentile[(rr + 1) * TS + cc - 1]) - min(clip_pt, rawData[i - 1][j - 1] + rawData[i - 1][j + 1] + rawData[i + 1][j + 1] + rawData[i + 1][j - 1])); @@ -386,7 +393,7 @@ void RawImageSource::fast_demosaic() #else - for (int cc = (FC(i, 2) & 1) + 1, j = left + cc; j < right - 1; j += 2, cc += 2) { + for (int cc = (fc(cfarray, i, 2) & 1) + 1, j = left + cc; j < right - 1; j += 2, cc += 2) { //interpolate B/R colors at R/B sites redtile[rr * TS + cc] = greentile[rr * TS + cc] - 0.25f * ((greentile[(rr - 1) * TS + cc - 1] + greentile[(rr - 1) * TS + cc + 1] + greentile[(rr + 1) * TS + cc + 1] + greentile[(rr + 1) * TS + cc - 1]) - min(clip_pt, rawData[i - 1][j - 1] + rawData[i - 1][j + 1] + rawData[i + 1][j + 1] + rawData[i + 1][j - 1])); @@ -405,7 +412,7 @@ void RawImageSource::fast_demosaic() for (int i = top + 2, rr = 2; i < bottom - 2; i++, rr++) { #ifdef __SSE2__ - for (int cc = 2 + (FC(i, 2) & 1), j = left + cc; j < right - 2; j += 4, cc += 4) { + for (int cc = 2 + (fc(cfarray, i, 2) & 1), j = left + cc; j < right - 2; j += 4, cc += 4) { // no need to take care about the borders of the tile. There's enough free space. //interpolate R and B colors at G sites greenv = LVFU(greentile[rr * TS + cc]); @@ -429,7 +436,7 @@ void RawImageSource::fast_demosaic() #else - for (int cc = 2 + (FC(i, 2) & 1), j = left + cc; j < right - 2; j += 2, cc += 2) { + for (int cc = 2 + (fc(cfarray, i, 2) & 1), j = left + cc; j < right - 2; j += 2, cc += 2) { //interpolate R and B colors at G sites redtile[rr * TS + cc] = greentile[rr * TS + cc] - 0.25f * ((greentile[(rr - 1) * TS + cc] - redtile[(rr - 1) * TS + cc]) + (greentile[(rr + 1) * TS + cc] - redtile[(rr + 1) * TS + cc]) + (greentile[rr * TS + cc - 1] - redtile[rr * TS + cc - 1]) + (greentile[rr * TS + cc + 1] - redtile[rr * TS + cc + 1])); @@ -445,23 +452,23 @@ void RawImageSource::fast_demosaic() #ifdef __SSE2__ for (j = left + 2, cc = 2; j < right - 5; j += 4, cc += 4) { - _mm_storeu_ps(&red[i][j], LVFU(redtile[rr * TS + cc])); - _mm_storeu_ps(&green[i][j], LVFU(greentile[rr * TS + cc])); - _mm_storeu_ps(&blue[i][j], LVFU(bluetile[rr * TS + cc])); + _mm_storeu_ps(&red[i][j], vmaxf(LVFU(redtile[rr * TS + cc]), ZEROV)); + _mm_storeu_ps(&green[i][j], vmaxf(LVFU(greentile[rr * TS + cc]), ZEROV)); + _mm_storeu_ps(&blue[i][j], vmaxf(LVFU(bluetile[rr * TS + cc]), ZEROV)); } for (; j < right - 2; j++, cc++) { - red[i][j] = redtile[rr * TS + cc]; - green[i][j] = greentile[rr * TS + cc]; - blue[i][j] = bluetile[rr * TS + cc]; + red[i][j] = std::max(0.f, redtile[rr * TS + cc]); + green[i][j] = std::max(0.f, greentile[rr * TS + cc]); + blue[i][j] = std::max(0.f, bluetile[rr * TS + cc]); } #else for (int j = left + 2, cc = 2; j < right - 2; j++, cc++) { - red[i][j] = redtile[rr * TS + cc]; - green[i][j] = greentile[rr * TS + cc]; - blue[i][j] = bluetile[rr * TS + cc]; + red[i][j] = std::max(0.f, redtile[rr * TS + cc]); + green[i][j] = std::max(0.f, greentile[rr * TS + cc]); + blue[i][j] = std::max(0.f, bluetile[rr * TS + cc]); } #endif diff --git a/rtengine/ffmanager.cc b/rtengine/ffmanager.cc index 6e4977076..ce60277e1 100644 --- a/rtengine/ffmanager.cc +++ b/rtengine/ffmanager.cc @@ -14,8 +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 +#include + #include "ffmanager.h" #include "../rtgui/options.h" #include "rawimage.h" @@ -26,8 +30,6 @@ namespace rtengine { -extern const Settings* settings; - // *********************** class ffInfo ************************************** inline ffInfo& ffInfo::operator =(const ffInfo &o) @@ -50,6 +52,11 @@ inline ffInfo& ffInfo::operator =(const ffInfo &o) return *this; } +ffInfo::~ffInfo() +{ + delete ri; +} + bool ffInfo::operator <(const ffInfo &e2) const { if( this->maker.compare( e2.maker) >= 0 ) { @@ -277,8 +284,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 43fb2f368..f3303f12b 100644 --- a/rtengine/ffmanager.h +++ b/rtengine/ffmanager.h @@ -14,22 +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 . */ #pragma once #include +#include #include #include #include -#include "rawimage.h" - namespace rtengine { -class ffInfo +class RawImage; +class ffInfo final { public: @@ -48,13 +48,8 @@ public: ffInfo( const ffInfo &o) : pathname(o.pathname), maker(o.maker), model(o.model), lens(o.lens), aperture(o.aperture), focallength(o.focallength), timestamp(o.timestamp), ri(nullptr) {} - ~ffInfo() - { - if( ri ) { - delete ri; - } - } + ~ffInfo(); ffInfo &operator =(const ffInfo &o); bool operator <(const ffInfo &e2) const; @@ -76,7 +71,7 @@ protected: void updateRawImage(); }; -class FFManager +class FFManager final { public: void init(const Glib::ustring &pathname); diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index 12f19fba9..1f27983ed 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -14,33 +14,25 @@ * GNU General Public License for more details. * * 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 -#ifdef _OPENMP -#include -#endif - +#include "rawimage.h" #include "rawimagesource.h" +#include "coord.h" #include "mytime.h" #include "opthelper.h" +#include "pixelsmap.h" #include "procparams.h" #include "rt_algo.h" #include "rtengine.h" - +#include "sleef.h" //#define BENCHMARK #include "StopWatch.h" -namespace rtengine -{ - -extern const Settings* settings; - -} - namespace { @@ -77,8 +69,8 @@ bool channelsAvg( } std::array pxCount = {}; // Per-channel sample counts - for (int c = spotPos.x - spotSize; c < spotPos.x + spotSize; ++c) { - for (int r = spotPos.y - spotSize; r < spotPos.y + spotSize; ++r) { + 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]; @@ -98,7 +90,7 @@ bool channelsAvg( } -bool rtengine::RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, std::array& newExps) +bool rtengine::RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D spotB, int tran, const procparams::FilmNegativeParams ¤tParams, std::array& newExps) { newExps = { static_cast(currentParams.redRatio * currentParams.greenExp), diff --git a/rtengine/filmnegativethumb.cc b/rtengine/filmnegativethumb.cc index 8c7564b86..b31432a55 100644 --- a/rtengine/filmnegativethumb.cc +++ b/rtengine/filmnegativethumb.cc @@ -14,27 +14,21 @@ * GNU General Public License for more details. * * 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 "LUT.h" #include "rtengine.h" #include "rtthumbnail.h" #include "opthelper.h" +#include "sleef.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, 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/rtgui/ilabel.h b/rtengine/flatcurvetypes.h similarity index 53% rename from rtgui/ilabel.h rename to rtengine/flatcurvetypes.h index 1f5340fa2..9efe0d259 100644 --- a/rtgui/ilabel.h +++ b/rtengine/flatcurvetypes.h @@ -1,7 +1,7 @@ /* * This file is part of RawTherapee. * - * Copyright (c) 2004-2010 Gabor Horvath + * Copyright (c) 2004-2019 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 @@ -14,24 +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 . - */ -#ifndef _ILABEL_ -#define _ILABEL_ + * along with RawTherapee. If not, see . +*/ +#pragma once -#include - -class ILabel : public Gtk::DrawingArea -{ - - Glib::ustring label; - -public: - explicit ILabel (const Glib::ustring &lab); - bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override; - void on_realize() override; - void on_style_updated () override; +// For compatibility and simplicity reason, order shouldn't change, and must be identical to the order specified in the curveType widget +enum FlatCurveType { + FCT_Empty = -1, // Also used for identity curves + FCT_Linear, // 0 + FCT_MinMaxCPoints, // 1 + //FCT_Parametric, // 2 + // Insert new curve type above this line + FCT_Unchanged // Must remain the last of the enum }; - -#endif - diff --git a/rtengine/gamutwarning.cc b/rtengine/gamutwarning.cc index c76e2a285..569ea3066 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 . */ /** @@ -23,10 +23,14 @@ * also distributed under the GPL V3+ */ -#include "gamutwarning.h" #include -namespace rtengine { +#include "gamutwarning.h" +#include "iccstore.h" +#include "image8.h" + +namespace rtengine +{ GamutWarning::GamutWarning(cmsHPROFILE iprof, cmsHPROFILE gamutprof, RenderingIntent intent, bool gamutbpc): lab2ref(nullptr), @@ -126,5 +130,4 @@ inline void GamutWarning::mark(Image8 *image, int y, int x) image->b(y, x) = 255; } - } // namespace rtengine diff --git a/rtengine/gamutwarning.h b/rtengine/gamutwarning.h index 19a27cdfd..b940b911f 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 . */ /** @@ -25,11 +25,14 @@ #pragma once -#include "iccstore.h" -#include "noncopyable.h" -#include "image8.h" +#include -namespace rtengine { +#include "noncopyable.h" + +namespace rtengine +{ + +class Image8; enum RenderingIntent : int; diff --git a/rtengine/gauss.cc b/rtengine/gauss.cc index 419e2cff3..99201a860 100644 --- a/rtengine/gauss.cc +++ b/rtengine/gauss.cc @@ -14,17 +14,63 @@ * GNU General Public License for more details. * * 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 #include -#include "opthelper.h" +#include + +#include "gauss.h" + #include "boxblur.h" +#include "opthelper.h" +#include "rt_math.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 +253,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) @@ -1139,12 +1353,14 @@ template void gaussVerticalmult (T** src, T** dst, const int W, const i } #endif -template void gaussianBlurImpl(T** src, T** dst, const int W, const int H, const double sigma, T *buffer = nullptr, eGaussType gausstype = GAUSS_STANDARD, T** buffer2 = nullptr) +template void gaussianBlurImpl(T** src, T** dst, const int W, const int H, const double sigma, bool useBoxBlur, eGaussType gausstype = GAUSS_STANDARD, T** buffer2 = nullptr) { 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) { + if (useBoxBlur) { // special variant for very large sigma, currently only used by retinex algorithm // use iterated boxblur to approximate gaussian blur // Compute ideal averaging filter width and number of iterations @@ -1180,10 +1396,10 @@ template void gaussianBlurImpl(T** src, T** dst, const int W, const int sizes[i] = ((i < m ? wl : wu) - 1) / 2; } - rtengine::boxblur(src, dst, buffer, sizes[0], sizes[0], W, H); + rtengine::boxblur(src, dst, sizes[0], W, H, true); for(int i = 1; i < n; i++) { - rtengine::boxblur(dst, dst, buffer, sizes[i], sizes[i], W, H); + rtengine::boxblur(dst, dst, sizes[i], W, H, true); } } else { if (sigma < GAUSS_SKIP) { @@ -1243,14 +1459,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; } @@ -1270,14 +1498,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; } @@ -1298,8 +1538,8 @@ template void gaussianBlurImpl(T** src, T** dst, const int W, const int } } -void gaussianBlur(float** src, float** dst, const int W, const int H, const double sigma, float *buffer, eGaussType gausstype, float** buffer2) +void gaussianBlur(float** src, float** dst, const int W, const int H, const double sigma, bool useBoxBlur, eGaussType gausstype, float** buffer2) { - gaussianBlurImpl(src, dst, W, H, sigma, buffer, gausstype, buffer2); + gaussianBlurImpl(src, dst, W, H, sigma, useBoxBlur, gausstype, buffer2); } diff --git a/rtengine/gauss.h b/rtengine/gauss.h index a8cd26161..71e3506da 100644 --- a/rtengine/gauss.h +++ b/rtengine/gauss.h @@ -14,15 +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 _GAUSS_H_ -#define _GAUSS_H_ +#pragma once enum eGaussType {GAUSS_STANDARD, GAUSS_MULT, GAUSS_DIV}; static constexpr auto GAUSS_SKIP = 0.25; -void gaussianBlur(float** src, float** dst, const int W, const int H, const double sigma, float *buffer = nullptr, eGaussType gausstype = GAUSS_STANDARD, float** buffer2 = nullptr); - -#endif \ No newline at end of file +void gaussianBlur(float** src, float** dst, const int W, const int H, const double sigma, bool useBoxBlur = false, eGaussType gausstype = GAUSS_STANDARD, float** buffer2 = nullptr); 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..b3f843bc1 100644 --- a/rtengine/guidedfilter.cc +++ b/rtengine/guidedfilter.cc @@ -28,8 +28,11 @@ * available at https://arxiv.org/abs/1505.00996 */ +#include "array2D.h" +#include "boxblur.h" #include "guidedfilter.h" #include "boxblur.h" +#include "sleef.h" #include "rescale.h" #include "imagefloat.h" @@ -139,25 +142,31 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 const auto f_subsample = [=](array2D &d, const array2D &s) -> void { - rescaleBilinear(s, d, multithread); + if (d.width() == s.width() && d.height() == s.height()) { +#ifdef _OPENMP +# pragma omp parallel for if (multithread) +#endif + for (int y = 0; y < s.height(); ++y) { + for (int x = 0; x < s.width(); ++x) { + d[y][x] = s[y][x]; + } + } + } else { + rescaleBilinear(s, d, multithread); + } }; - const auto f_upsample = f_subsample; + // 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); + boxblur(static_cast(s), static_cast(d), rad, s.width(), s.height(), multithread); }; array2D I1(w, h); @@ -207,9 +216,6 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 apply(SUBMUL, b, a, meanI, meanp); DEBUG_DUMP(b); - meanI.free(); // frees w * h * 4 byte - meanp.free(); // frees w * h * 4 byte - array2D &meana = a; f_mean(meana, a, r1); DEBUG_DUMP(meana); @@ -218,18 +224,57 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 f_mean(meanb, b, r1); DEBUG_DUMP(meanb); - blur_buf.resize(0); // frees w * h * 4 byte + // speedup by heckflosse67 + const int Ws = meana.width(); + const int Hs = meana.height(); + const int Wd = q.width(); + const int Hd = q.height(); + const float col_scale = float(Ws) / float(Wd); + const float row_scale = float(Hs) / float(Hd); - array2D meanA(W, H); - f_upsample(meanA, meana); - DEBUG_DUMP(meanA); +#ifdef _OPENMP +# pragma omp parallel for if (multithread) +#endif + for (int y = 0; y < Hd; ++y) { + float ymrs = y * row_scale; + for (int x = 0; x < Wd; ++x) { + q[y][x] = getBilinearValue(meana, x * col_scale, ymrs) * I[y][x] + getBilinearValue(meanb, x * col_scale, ymrs); + } + } +} - array2D &meanB = q; - f_upsample(meanB, meanb); - DEBUG_DUMP(meanB); - apply(ADDMUL, q, meanA, I, meanB); - DEBUG_DUMP(q); +void guidedFilterLog(const array2D &guide, float base, array2D &chan, int r, float eps, bool multithread, int subsampling) +{ +#ifdef _OPENMP +# pragma omp parallel for if (multithread) +#endif + for (int y = 0; y < chan.height(); ++y) { + for (int x = 0; x < chan.width(); ++x) { + chan[y][x] = xlin2log(max(chan[y][x], 0.f), base); + } + } + + guidedFilter(guide, chan, chan, r, eps, multithread, subsampling); + +#ifdef _OPENMP +# pragma omp parallel for if (multithread) +#endif + for (int y = 0; y < chan.height(); ++y) { + for (int x = 0; x < chan.width(); ++x) { + chan[y][x] = xlog2lin(max(chan[y][x], 0.f), base); + } + } +} + + +void guidedFilterLog(float base, array2D &chan, int r, float eps, bool multithread, int subsampling) +{ + guidedFilterLog(chan, base, chan, r, eps, multithread, subsampling); } } // namespace rtengine + + + + diff --git a/rtengine/guidedfilter.h b/rtengine/guidedfilter.h index 6691af251..94147b411 100644 --- a/rtengine/guidedfilter.h +++ b/rtengine/guidedfilter.h @@ -20,10 +20,16 @@ #pragma once -#include "array2D.h" +template class array2D; + +namespace rtengine +{ -namespace rtengine { void guidedFilter(const array2D &guide, const array2D &src, array2D &dst, int r, float epsilon, bool multithread, int subsampling=0); +void guidedFilterLog(float base, array2D &chan, int r, float eps, bool multithread, int subsampling=0); + +void guidedFilterLog(const array2D &guide, float base, array2D &chan, int r, float eps, bool multithread, int subsampling=0); + } // namespace rtengine 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 b0a7e6229..697a5e3d3 100644 --- a/rtengine/hilite_recon.cc +++ b/rtengine/hilite_recon.cc @@ -20,7 +20,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 . // //////////////////////////////////////////////////////////////// @@ -288,8 +288,6 @@ void boxblur_resamp(const float* const* src, float** dst, float** temp, int H, i namespace rtengine { -extern const Settings* settings; - void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue) { double progress = 0.0; @@ -970,8 +968,8 @@ void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue for (int c = 0; c < 3; ++c) { lab[i2][c] = 0; - for (int j = 0; j < 3; ++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]; } } @@ -996,8 +994,8 @@ void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue for (int c = 0; c < 3; ++c) { cam[0][c] = 0.f; - for (int j = 0; j < 3; ++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]; } } @@ -1081,12 +1079,11 @@ void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue //now correct clipped channels if (pixel[0] > max_f[0] && pixel[1] > max_f[1] && pixel[2] > max_f[2]) { //all channels clipped - const float Y = 0.299f * clipfix[0] + 0.587f * clipfix[1] + 0.114f * clipfix[2]; - const float factor = whitept / Y; - red[i + miny][j + minx] = clipfix[0] * factor; - green[i + miny][j + minx] = clipfix[1] * factor; - blue[i + miny][j + minx] = 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 const float notclipped[3] = { pixel[0] <= max_f[0] ? 1.f : 0.f, @@ -1113,11 +1110,11 @@ void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue 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) { - const float factor = whitept / Y; + const float mult = whitept / Y; - red[i + miny][j + minx] *= factor; - green[i + miny][j + minx] *= factor; - blue[i + miny][j + minx] *= factor; + red[i + miny][j + minx] *= mult; + green[i + miny][j + minx] *= mult; + blue[i + miny][j + minx] *= mult; } } } diff --git a/rtengine/histmatching.cc b/rtengine/histmatching.cc index e48f2017a..f5d16866e 100644 --- a/rtengine/histmatching.cc +++ b/rtengine/histmatching.cc @@ -15,26 +15,25 @@ * GNU General Public License for more details. * * 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" -#include "rtthumbnail.h" -#include "curves.h" -#include "color.h" -#include "rt_math.h" -#include "iccstore.h" -#include "procparams.h" -#include "../rtgui/mydiagonalcurve.h" -#include "improcfun.h" -//#define BENCHMARK -#include "StopWatch.h" #include +#include "color.h" +#include "curves.h" +#include "improcfun.h" +#include "procparams.h" +#include "rawimagesource.h" +#include "rt_math.h" +#include "rtthumbnail.h" +#include "settings.h" -namespace rtengine { +//#define BENCHMARK +#include "StopWatch.h" -extern const Settings *settings; +namespace rtengine +{ namespace { @@ -329,8 +328,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..936c8fa4f 100644 --- a/rtengine/hphd_demosaic_RT.cc +++ b/rtengine/hphd_demosaic_RT.cc @@ -14,16 +14,15 @@ * GNU General Public License for more details. * * 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 "rawimage.h" #include "rawimagesource.h" #include "rawimagesource_i.h" #include "jaggedarray.h" -#include "rawimage.h" #include "rt_math.h" -#include "procparams.h" #include "../rtgui/multilangmgr.h" #include "opthelper.h" //#define BENCHMARK @@ -218,7 +217,7 @@ void hphd_green(const RawImage *ri, const array2D &rawData, float** hpmap const float e4 = 1.f / (dx + (std::fabs(d1) + std::fabs(d2)) + (std::fabs(d3) + std::fabs(d4)) * 0.5f); - green[i][j] = rawData[i][j] * 0.5f + (e2 * g2 + e4 * g4) / (e2 + e4); + green[i][j] = std::max(0.f, rawData[i][j] * 0.5f + (e2 * g2 + e4 * g4) / (e2 + e4)); } else if (hpmap[i][j] == 2) { const float g1 = rawData[i - 1][j] - rawData[i - 2][j] * 0.5f; const float g3 = rawData[i + 1][j] - rawData[i + 2][j] * 0.5f; @@ -238,7 +237,7 @@ void hphd_green(const RawImage *ri, const array2D &rawData, float** hpmap const float e3 = 1.f / (dy + (std::fabs(d1) + std::fabs(d2)) + (std::fabs(d3) + std::fabs(d4)) * 0.5f); - green[i][j] = rawData[i][j] * 0.5f + (e1 * g1 + e3 * g3) / (e1 + e3); + green[i][j] = std::max(0.f, rawData[i][j] * 0.5f + (e1 * g1 + e3 * g3) / (e1 + e3)); } else { const float g1 = rawData[i - 1][j] - rawData[i - 2][j] * 0.5f; const float g2 = rawData[i][j + 1] - rawData[i][j + 2] * 0.5f; @@ -276,7 +275,7 @@ void hphd_green(const RawImage *ri, const array2D &rawData, float** hpmap const float e4 = 1.f / (dx + (std::fabs(d1) + std::fabs(d2)) + (std::fabs(d3) + std::fabs(d4)) * 0.5f); - green[i][j] = rawData[i][j] * 0.5f + ((e1 * g1 + e2 * g2) + (e3 * g3 + e4 * g4)) / (e1 + e2 + e3 + e4); + green[i][j] = std::max(0.f, rawData[i][j] * 0.5f + ((e1 * g1 + e2 * g2) + (e3 * g3 + e4 * g4)) / (e1 + e2 + e3 + e4)); } } } @@ -353,7 +352,7 @@ void RawImageSource::hphd_demosaic () interpolate_row_rb_mul_pp(rawData, red[i], blue[i], green[i - 1], green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); } - border_interpolate2(W, H, 4, rawData, red, green, blue); + border_interpolate(W, H, 4, rawData, red, green, blue); if (plistener) { plistener->setProgress(1.0); diff --git a/rtengine/iccmatrices.h b/rtengine/iccmatrices.h index 29426c62d..5b9883421 100644 --- a/rtengine/iccmatrices.h +++ b/rtengine/iccmatrices.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 _ICCMATRICES_ -#define _ICCMATRICES_ +#pragma once // Bradford transform between illuminants constexpr double d65_d50[3][3] = { @@ -296,4 +295,3 @@ constexpr double d50_best[3][3] = { {-0.253000840399762, 0.0215532098817316,1.22569552576991} }; */ -#endif diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index 268a6b1c2..9d7024bff 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -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 . */ #include -#include +#include +#include +#include #include #ifdef WIN32 @@ -32,6 +34,7 @@ #include "iccstore.h" #include "iccmatrices.h" +#include "utils.h" #include "../rtgui/options.h" #include "../rtgui/threadutils.h" @@ -40,13 +43,6 @@ #include "color.h" #include "cJSON.h" -#define inkc_constant 0x696E6B43 -namespace rtengine -{ - -extern const Settings* settings; - -} namespace { diff --git a/rtengine/iccstore.h b/rtengine/iccstore.h index 6b57fd072..117124122 100644 --- a/rtengine/iccstore.h +++ b/rtengine/iccstore.h @@ -14,20 +14,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 +#include #include #include -#include +#include #include -#include "color.h" - namespace rtengine { @@ -40,7 +39,7 @@ namespace procparams typedef const double(*TMatrix)[3]; -class ProfileContent +class ProfileContent final { public: ProfileContent(); @@ -55,7 +54,7 @@ private: std::string data; }; -class ICCStore +class ICCStore final { public: enum class ProfileType { diff --git a/rtengine/iimage.cc b/rtengine/iimage.cc index c9a4f223a..7548fc8bf 100644 --- a/rtengine/iimage.cc +++ b/rtengine/iimage.cc @@ -14,9 +14,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 . */ +#include "color.h" #include "procparams.h" #include "rtengine.h" @@ -45,3 +46,7 @@ int rtengine::getCoarseBitMask( const procparams::CoarseTransformParams &coarse) return tr; } + +const LUTf& rtengine::getigammatab() { + return Color::igammatab_srgb; +} diff --git a/rtengine/iimage.h b/rtengine/iimage.h index ff016df1a..247d0cdaa 100644 --- a/rtengine/iimage.h +++ b/rtengine/iimage.h @@ -14,19 +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 _IIMAGE_ -#define _IIMAGE_ +#pragma once -#include #include -#include "rt_math.h" + +#include + #include "alignedbuffer.h" +#include "coord2d.h" #include "imagedimensions.h" #include "LUT.h" -#include "coord2d.h" -#include "color.h" +#include "rt_math.h" + #include "../rtgui/threadutils.h" #define TR_NONE 0 @@ -39,6 +40,13 @@ #define CHECK_BOUNDS 0 +namespace Glib +{ + +class ustring; + +} + namespace rtengine { @@ -57,6 +65,7 @@ extern const char sImage16[]; extern const char sImagefloat[]; int getCoarseBitMask(const procparams::CoarseTransformParams& coarse); +const LUTf& getigammatab(); enum TypeInterpolation { TI_Nearest, TI_Bilinear }; @@ -655,7 +664,7 @@ public: /* If any of the required allocation fails, "width" and "height" are set to -1, and all remaining buffer are freed * Can be safely used to reallocate an existing image */ - void allocate (int W, int H) override + void allocate (int W, int H) final { if (W == width && H == height) { @@ -743,7 +752,7 @@ public: } } - void rotate (int deg) override + void rotate (int deg) final { if (deg == 90) { @@ -870,7 +879,7 @@ public: } } - void hflip () override + void hflip () final { int width2 = width / 2; @@ -902,7 +911,7 @@ public: #endif } - void vflip () override + void vflip () final { int height2 = height / 2; @@ -955,34 +964,52 @@ public: histogram(65536 >> histcompr); histogram.clear(); + const LUTf& igammatab = getigammatab(); - for (int i = 0; i < height; i++) - for (int j = 0; j < width; j++) { - float r_, g_, b_; - convertTo(r(i, j), r_); - convertTo(g(i, j), g_); - convertTo(b(i, j), b_); - histogram[(int)Color::igamma_srgb (r_) >> histcompr]++; - histogram[(int)Color::igamma_srgb (g_) >> histcompr]++; - histogram[(int)Color::igamma_srgb (b_) >> histcompr]++; +#ifdef _OPENMP + #pragma omp parallel +#endif + { + LUTu histThr(histogram.getSize()); + histThr.clear(); +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) nowait +#endif + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + float r_, g_, b_; + convertTo(r(i, j), r_); + convertTo(g(i, j), g_); + convertTo(b(i, j), b_); + histThr[static_cast(igammatab[r_]) >> histcompr]++; + histThr[static_cast(igammatab[g_]) >> histcompr]++; + histThr[static_cast(igammatab[b_]) >> histcompr]++; + } } +#ifdef _OPENMP + #pragma omp critical +#endif + { + histogram += histThr; + } + } } - void computeHistogramAutoWB (double &avg_r, double &avg_g, double &avg_b, int &n, LUTu &histogram, const int compression) const override + void computeHistogramAutoWB (double &avg_r, double &avg_g, double &avg_b, int &n, LUTu &histogram, const int compression) const final { histogram.clear(); avg_r = avg_g = avg_b = 0.; n = 0; - + const LUTf& igammatab = getigammatab(); for (unsigned int i = 0; i < (unsigned int)(height); i++) for (unsigned int j = 0; j < (unsigned int)(width); j++) { float r_, g_, b_; convertTo(r(i, j), r_); convertTo(g(i, j), g_); convertTo(b(i, j), b_); - int rtemp = Color::igamma_srgb (r_); - int gtemp = Color::igamma_srgb (g_); - int btemp = Color::igamma_srgb (b_); + int rtemp = igammatab[r_]; + int gtemp = igammatab[g_]; + int btemp = igammatab[b_]; histogram[rtemp >> compression]++; histogram[gtemp >> compression] += 2; @@ -1009,6 +1036,9 @@ public: int n = 0; //int p = 6; +#ifdef _OPENMP + #pragma omp parallel for reduction(+:avg_r,avg_g,avg_b,n) schedule(dynamic,16) +#endif for (unsigned int i = 0; i < (unsigned int)(height); i++) for (unsigned int j = 0; j < (unsigned int)(width); j++) { float r_, g_, b_; @@ -1304,7 +1334,7 @@ public: * If any of the required allocation fails, "width" and "height" are set to -1, and all remaining buffer are freed * Can be safely used to reallocate an existing image or to free up it's memory with "allocate (0,0);" */ - void allocate (int W, int H) override + void allocate (int W, int H) final { if (W == width && H == height) { @@ -1358,7 +1388,7 @@ public: memcpy (dest->data, data, 3 * width * height * sizeof(T)); } - void rotate (int deg) override + void rotate (int deg) final { if (deg == 90) { @@ -1492,7 +1522,7 @@ public: } } - void hflip () override + void hflip () final { int width2 = width / 2; @@ -1528,7 +1558,7 @@ public: } } - void vflip () override + void vflip () final { AlignedBuffer lBuffer(3 * width); @@ -1564,24 +1594,43 @@ public: histogram(65536 >> histcompr); histogram.clear(); + const LUTf& igammatab = getigammatab(); - for (int i = 0; i < height; i++) - for (int j = 0; j < width; j++) { - float r_, g_, b_; - convertTo(r(i, j), r_); - convertTo(g(i, j), g_); - convertTo(b(i, j), b_); - histogram[(int)Color::igamma_srgb (r_) >> histcompr]++; - histogram[(int)Color::igamma_srgb (g_) >> histcompr]++; - histogram[(int)Color::igamma_srgb (b_) >> histcompr]++; +#ifdef _OPENMP + #pragma omp parallel +#endif + { + LUTu histThr(histogram.getSize()); + histThr.clear(); +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) nowait +#endif + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + float r_, g_, b_; + convertTo(r(i, j), r_); + convertTo(g(i, j), g_); + convertTo(b(i, j), b_); + histThr[static_cast(igammatab[r_]) >> histcompr]++; + histThr[static_cast(igammatab[g_]) >> histcompr]++; + histThr[static_cast(igammatab[b_]) >> histcompr]++; + } } +#ifdef _OPENMP + #pragma omp critical +#endif + { + histogram += histThr; + } + } } - void computeHistogramAutoWB (double &avg_r, double &avg_g, double &avg_b, int &n, LUTu &histogram, const int compression) const override + void computeHistogramAutoWB (double &avg_r, double &avg_g, double &avg_b, int &n, LUTu &histogram, const int compression) const final { histogram.clear(); avg_r = avg_g = avg_b = 0.; n = 0; + const LUTf& igammatab = getigammatab(); for (unsigned int i = 0; i < (unsigned int)(height); i++) for (unsigned int j = 0; j < (unsigned int)(width); j++) { @@ -1589,9 +1638,9 @@ public: convertTo(r(i, j), r_); convertTo(g(i, j), g_); convertTo(b(i, j), b_); - int rtemp = Color::igamma_srgb (r_); - int gtemp = Color::igamma_srgb (g_); - int btemp = Color::igamma_srgb (b_); + int rtemp = igammatab[r_]; + int gtemp = igammatab[g_]; + int btemp = igammatab[b_]; histogram[rtemp >> compression]++; histogram[gtemp >> compression] += 2; @@ -1618,6 +1667,9 @@ public: int n = 0; //int p = 6; +#ifdef _OPENMP + #pragma omp parallel for reduction(+:avg_r,avg_g,avg_b,n) schedule(dynamic,16) +#endif for (unsigned int i = 0; i < (unsigned int)(height); i++) for (unsigned int j = 0; j < (unsigned int)(width); j++) { float r_, g_, b_; @@ -1808,5 +1860,3 @@ public: }; } - -#endif diff --git a/rtengine/image16.cc b/rtengine/image16.cc index c0e97557a..4bcd9d5c0 100644 --- a/rtengine/image16.cc +++ b/rtengine/image16.cc @@ -14,13 +14,15 @@ * GNU General Public License for more details. * * 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 "colortemp.h" #include "image16.h" #include "imagefloat.h" #include "image8.h" -#include -#include "rtengine.h" +#include "rt_math.h" namespace { @@ -74,7 +76,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 +103,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) { @@ -185,8 +187,6 @@ void Image16::getStdImage(const ColorTemp &ctemp, int tran, Imagefloat* image, P gm /= area; bm /= area; -#define GCLIP( x ) Color::gamma_srgb(CLIP(x)) - #ifdef _OPENMP #pragma omp parallel { diff --git a/rtengine/image16.h b/rtengine/image16.h index 9762af990..de9288f2d 100644 --- a/rtengine/image16.h +++ b/rtengine/image16.h @@ -14,24 +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 . */ // // A class representing a 16 bit rgb image with separate planes and 16 byte aligned data // -#ifndef _IMAGE16_ -#define _IMAGE16_ +#pragma once #include "imageio.h" -#include "rtengine.h" -#include "imagefloat.h" namespace rtengine { class Image8; +class Imagefloat; -class Image16 : public IImage16, public ImageIO +class Image16 final : public IImage16, public ImageIO { public: @@ -56,7 +54,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 @@ -109,4 +107,3 @@ public: }; } -#endif diff --git a/rtengine/image8.cc b/rtengine/image8.cc index 513b0049e..8784c962e 100644 --- a/rtengine/image8.cc +++ b/rtengine/image8.cc @@ -14,11 +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 . */ #include #include + +#include "colortemp.h" #include "image8.h" +#include "imagefloat.h" #include "rtengine.h" using namespace rtengine; @@ -55,7 +58,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 +77,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]); @@ -148,8 +151,6 @@ void Image8::getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, P gm /= area; bm /= area; -#define GCLIP( x ) Color::gamma_srgb(CLIP(x)) - #ifdef _OPENMP #pragma omp parallel { @@ -230,10 +231,10 @@ void Image8::getStdImage (const ColorTemp &ctemp, int tran, Imagefloat* image, P lineB[dst_x] = CLIP(bm * btot); } else { // computing a special factor for this incomplete sub-region - float area = src_sub_width * src_sub_height; - lineR[dst_x] = CLIP(rm2 * rtot / area); - lineG[dst_x] = CLIP(gm2 * gtot / area); - lineB[dst_x] = CLIP(bm2 * btot / area); + float larea = src_sub_width * src_sub_height; + lineR[dst_x] = CLIP(rm2 * rtot / larea); + lineG[dst_x] = CLIP(gm2 * gtot / larea); + lineB[dst_x] = CLIP(bm2 * btot / larea); } } } diff --git a/rtengine/image8.h b/rtengine/image8.h index 8928cf85b..c11d9d7fc 100644 --- a/rtengine/image8.h +++ b/rtengine/image8.h @@ -14,22 +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 . */ // // A class representing a 8 bit rgb image without alpha channel // -#ifndef _IMAGE8_ -#define _IMAGE8_ +#pragma once #include "imageio.h" -#include "rtengine.h" -#include "imagefloat.h" namespace rtengine { +class Imagefloat; -class Image8 : public IImage8, public ImageIO +class Image8 final : public IImage8, public ImageIO { public: @@ -53,7 +51,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 @@ -104,4 +102,3 @@ public: }; } -#endif diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 6e39a27ad..bbbe8794e 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -14,18 +14,25 @@ * GNU General Public License for more details. * * 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 + #include +#include + +#include + #include "imagedata.h" -#include "iptcpairs.h" #include "imagesource.h" -#include "rt_math.h" +#include "iptcpairs.h" #include "procparams.h" +#include "rt_math.h" +#include "utils.h" +#include "../rtexif/rtexif.h" #pragma GCC diagnostic warning "-Wextra" #define PRINT_HDR_PS_DETECTION 0 @@ -265,7 +272,6 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* tag = exif->getTag("SubjectDistance"); if (tag) { - int num, denom; tag->toRational(num, denom); } else { // Second try, XMP data @@ -533,9 +539,8 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* if (flt->toDouble() > 0) { focal_len = flt->toDouble(); } - } else if ((flt = mnote->getTagP("FocalLength"))) { - rtexif::Tag* flt = mnote->getTag("FocalLength"); - focal_len = flt->toDouble(); + } else if ((flt = mnote->getTagP ("FocalLength"))) { + focal_len = mnote->getTag("FocalLength")->toDouble (); } if (mnote->getTag("FocalLengthIn35mmFilm")) { diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index d06820296..4bf9bdf5b 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -14,24 +14,37 @@ * GNU General Public License for more details. * * 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 __IMAGEDATA_H__ -#define __IMAGEDATA_H__ +#pragma once #include #include -#include "rawimage.h" #include -#include -#include "../rtexif/rtexif.h" +#include + + #include -#include "rtengine.h" + +#include "imageio.h" + +namespace Glib +{ + +class ustring; + +} + +namespace rtexif +{ + +class TagDirectory; +} namespace rtengine { -class FrameData +class FrameData final { protected: @@ -88,7 +101,7 @@ public: int getRating () const; }; -class FramesData : public FramesMetaData { +class FramesData final : public FramesMetaData { private: // frame's root IFD, can be a file root IFD or a SUB-IFD std::vector> frames; @@ -98,7 +111,7 @@ private: unsigned int dcrawFrameCount; public: - FramesData (const Glib::ustring& fname, std::unique_ptr rml = nullptr, bool firstFrameOnly = false); + explicit FramesData (const Glib::ustring& fname, std::unique_ptr rml = nullptr, bool firstFrameOnly = false); ~FramesData () override; void setDCRawFrameCount (unsigned int frameCount); @@ -133,4 +146,3 @@ public: } -#endif 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..1da91a4b4 100644 --- a/rtengine/imagefloat.cc +++ b/rtengine/imagefloat.cc @@ -14,15 +14,17 @@ * GNU General Public License for more details. * * 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 "colortemp.h" #include "imagefloat.h" #include "image16.h" #include "image8.h" +#include "labimage.h" #include #include "rtengine.h" -#include "mytime.h" #include "iccstore.h" #include "alignedbuffer.h" #include "rt_math.h" @@ -45,7 +47,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 +60,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 +73,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 +87,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..cd08daf70 100644 --- a/rtengine/imagefloat.h +++ b/rtengine/imagefloat.h @@ -14,16 +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 . */ // // A class representing a 16 bit rgb image with separate planes and 16 byte aligned data // -#ifndef _IMAGEFLOAT_ -#define _IMAGEFLOAT_ +#pragma once #include "imageio.h" -#include "rtengine.h" namespace rtengine { @@ -31,11 +29,12 @@ using namespace procparams; class Image8; class Image16; +class LabImage; /* * Image type used by most tools; expected range: [0.0 ; 65535.0] */ -class Imagefloat : public IImagefloat, public ImageIO +class Imagefloat final : public IImagefloat, public ImageIO { public: @@ -62,7 +61,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 @@ -227,4 +226,3 @@ public: }; } -#endif diff --git a/rtengine/imageformat.h b/rtengine/imageformat.h index 22708daef..f8fee4c59 100644 --- a/rtengine/imageformat.h +++ b/rtengine/imageformat.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 _IMAGEFORMAT_ -#define _IMAGEFORMAT_ +#pragma once namespace rtengine { @@ -51,5 +50,3 @@ typedef enum SensorType { } eSensorType; } - -#endif diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index 3b0fdcf6d..fce181c3f 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 @@ -27,8 +27,10 @@ #include #include "rt_math.h" #include "procparams.h" +#include "utils.h" #include "../rtgui/options.h" #include "../rtgui/version.h" +#include "../rtexif/rtexif.h" #ifdef WIN32 #include @@ -89,7 +91,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot) } if (eroot) { - rtexif::TagDirectory* td = ((rtexif::TagDirectory*)eroot)->clone (nullptr); + rtexif::TagDirectory* td = eroot->clone (nullptr); // make IPTC and XMP pass through td->keepTag(0x83bb); // IPTC @@ -113,7 +115,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr } if (eroot) { - exifRoot = ((rtexif::TagDirectory*)eroot)->clone (nullptr); + exifRoot = eroot->clone (nullptr); } if (iptc != nullptr) { @@ -140,7 +142,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr for (unsigned int j = 0; j < i->second.size(); j++) { IptcDataSet * ds = iptc_dataset_new (); iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_KEYWORDS); - iptc_dataset_set_data (ds, (unsigned char*)i->second.at(j).c_str(), min(static_cast(64), i->second.at(j).bytes()), IPTC_DONT_VALIDATE); + iptc_dataset_set_data (ds, (const unsigned char*)i->second.at(j).c_str(), min(static_cast(64), i->second.at(j).bytes()), IPTC_DONT_VALIDATE); iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); } @@ -150,7 +152,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr for (unsigned int j = 0; j < i->second.size(); j++) { IptcDataSet * ds = iptc_dataset_new (); iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_SUPPL_CATEGORY); - iptc_dataset_set_data (ds, (unsigned char*)i->second.at(j).c_str(), min(static_cast(32), i->second.at(j).bytes()), IPTC_DONT_VALIDATE); + iptc_dataset_set_data (ds, (const unsigned char*)i->second.at(j).c_str(), min(static_cast(32), i->second.at(j).bytes()), IPTC_DONT_VALIDATE); iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); } @@ -162,7 +164,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr if (i->first == strTags[j].field && !(i->second.empty())) { IptcDataSet * ds = iptc_dataset_new (); iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, strTags[j].tag); - iptc_dataset_set_data (ds, (unsigned char*)i->second.at(0).c_str(), min(strTags[j].size, i->second.at(0).bytes()), IPTC_DONT_VALIDATE); + iptc_dataset_set_data (ds, (const unsigned char*)i->second.at(0).c_str(), min(strTags[j].size, i->second.at(0).bytes()), IPTC_DONT_VALIDATE); iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); } @@ -810,7 +812,7 @@ int ImageIO::loadTIFF (const Glib::ustring &fname) * TIFFTAG_SMAXSAMPLEVALUE, but for now, we normalize the image to the * effective minimum and maximum values */ - if (options.rtSettings.verbose) { + if (settings->verbose) { printf("Information of \"%s\":\n", fname.c_str()); uint16 tiffDefaultScale, tiffBaselineExposure, tiffLinearResponseLimit; if (TIFFGetField(in, TIFFTAG_DEFAULTSCALE, &tiffDefaultScale)) { @@ -910,12 +912,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 05a11655a..d9afa926f 100644 --- a/rtengine/imageio.h +++ b/rtengine/imageio.h @@ -14,37 +14,53 @@ * GNU General Public License for more details. * * 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_ - -#define IMIO_SUCCESS 0 -#define IMIO_CANNOTREADFILE 1 -#define IMIO_INVALIDHEADER 2 -#define IMIO_HEADERERROR 3 -#define IMIO_READERROR 4 -#define IMIO_VARIANTNOTSUPPORTED 5 -#define IMIO_FILETYPENOTSUPPORTED 6 -#define IMIO_CANNOTWRITEFILE 7 +#pragma once #include -#include +#include + #include -#include "rtengine.h" -#include "imageformat.h" -#include "../rtexif/rtexif.h" -#include "imagedimensions.h" + #include "iimage.h" -#include "colortemp.h" +#include "imagedimensions.h" +#include "imageformat.h" +#include "rtengine.h" + +enum { + IMIO_SUCCESS, + IMIO_CANNOTREADFILE, + IMIO_INVALIDHEADER, + IMIO_HEADERERROR, + IMIO_READERROR, + IMIO_VARIANTNOTSUPPORTED, + IMIO_FILETYPENOTSUPPORTED, + IMIO_CANNOTWRITEFILE +}; + +namespace rtexif +{ + +class TagDirectory; + +} namespace rtengine { +class ColorTemp; class ProgressListener; class Imagefloat; +namespace procparams +{ + +class ExifPairs; + +} + class ImageIO : virtual public ImageDatas { @@ -81,7 +97,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); @@ -111,4 +127,3 @@ public: }; } -#endif diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index bf73b5bb2..76f4e435a 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -14,28 +14,37 @@ * GNU General Public License for more details. * * 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 #include -#include +#include -#include "colortemp.h" #include "coord2d.h" -#include "dcp.h" -#include "image16.h" -#include "image8.h" #include "imagedata.h" -#include "imagefloat.h" -#include "LUT.h" #include "rtengine.h" +template +class LUT; + +using LUTf = LUT; + +template +class multi_array2D; + namespace rtengine { +class ColorTemp; +class DCPProfile; +class DCPProfileApplyState; +class Imagefloat; +class RetinexgaintransmissionCurve; +class RetinextransmissionCurve; + namespace procparams { @@ -46,8 +55,8 @@ struct LensProfParams; struct RAWParams; struct RetinexParams; struct ToneCurveParams; - -} +struct CaptureSharpeningParams; +}; class ImageMatrices { @@ -82,8 +91,8 @@ public: 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 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) {}; + virtual bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const procparams::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) {}; @@ -101,13 +110,13 @@ public: // use right after demosaicing image, add coarse transformation and put the result in the provided Imagefloat* - virtual void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hlp, const RAWParams &raw) = 0; + virtual void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hlp, const procparams::RAWParams &raw) = 0; virtual eSensorType getSensorType () const = 0; virtual bool isMono () const = 0; // true is ready to provide the AutoWB, i.e. when the image has been demosaiced for RawImageSource virtual bool isWBProviderReady () = 0; - virtual void convertColorSpace (Imagefloat* image, const ColorManagementParams &cmp, const ColorTemp &wb) = 0; // DIRTY HACK: this method is derived in rawimagesource and strimagesource, but (...,RAWParams raw) will be used ONLY for raw images + virtual void convertColorSpace (Imagefloat* image, const procparams::ColorManagementParams &cmp, const ColorTemp &wb) = 0; // DIRTY HACK: this method is derived in rawimagesource and strimagesource, but (...,RAWParams raw) will be used ONLY for raw images virtual void getAutoWBMultipliers (double &rm, double &gm, double &bm) = 0; virtual ColorTemp getWB () const = 0; virtual ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal) = 0; @@ -126,18 +135,18 @@ public: virtual ImageMatrices* getImageMatrices () = 0; virtual bool isRAW () const = 0; - virtual DCPProfile* getDCP (const procparams::ColorManagementParams &cmp, DCPProfile::ApplyState &as) + virtual DCPProfile* getDCP (const procparams::ColorManagementParams &cmp, DCPProfileApplyState &as) { return nullptr; }; virtual void setProgressListener (ProgressListener* pl) {} - void increaseRef () override + void increaseRef () final { references++; } - void decreaseRef () override + void decreaseRef () final { references--; @@ -165,15 +174,15 @@ public: return dirpyrdenoiseExpComp; } // functions inherited from the InitialImage interface - Glib::ustring getFileName () override + Glib::ustring getFileName () final { return fileName; } - cmsHPROFILE getEmbeddedProfile () override + cmsHPROFILE getEmbeddedProfile () final { return embProfile; } - const FramesMetaData* getMetaData () override + const FramesMetaData* getMetaData () final { return idata; } @@ -182,6 +191,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; }; } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index da687567a..ed8b63b34 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -14,35 +14,40 @@ * GNU General Public License for more details. * * 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" -#include "mytime.h" -#include "refreshmap.h" -#include "../rtgui/ppversion.h" -#include "colortemp.h" -#include "improcfun.h" -#include #include +#include #include -#include -#include "jaggedarray.h" +#include -#include "iccstore.h" -#include "procparams.h" -#include -#include -#include +#include "improccoordinator.h" + +#include "cieimage.h" #include "color.h" +#include "colortemp.h" +#include "jaggedarray.h" +#include "curves.h" +#include "dcp.h" +#include "iccstore.h" +#include "image8.h" +#include "imagefloat.h" +#include "improcfun.h" +#include "labimage.h" +#include "lcp.h" +#include "procparams.h" +#include "refreshmap.h" + +#include "../rtgui/options.h" + #ifdef _OPENMP #include #endif + + namespace rtengine { -extern const Settings* settings; - ImProcCoordinator::ImProcCoordinator() : orig_prev(nullptr), oprevi(nullptr), @@ -51,14 +56,15 @@ ImProcCoordinator::ImProcCoordinator() : fattal_11_dcrop_cache(nullptr), previmg(nullptr), workimg(nullptr), - ncie (nullptr), - imgsrc (nullptr), - lastAwbEqual (0.), - lastAwbTempBias (0.0), - monitorIntent (RI_RELATIVE), + ncie(nullptr), + imgsrc(nullptr), + lastAwbEqual(0.), + lastAwbTempBias(0.0), + monitorIntent(RI_RELATIVE), softProof(false), gamutCheck(false), sharpMask(false), + sharpMaskChanged(false), scale(10), highDetailPreprocessComputed(false), highDetailRawComputed(false), @@ -126,6 +132,8 @@ ImProcCoordinator::ImProcCoordinator() : flatFieldAutoClipListener(nullptr), bayerAutoContrastListener(nullptr), xtransAutoContrastListener(nullptr), + pdSharpenAutoContrastListener(nullptr), + pdSharpenAutoRadiusListener(nullptr), frameCountListener(nullptr), imageTypeListener(nullptr), actListener(nullptr), @@ -157,34 +165,86 @@ ImProcCoordinator::ImProcCoordinator() : customTransformIn(nullptr), customTransformOut(nullptr), ipf(params.get(), true), - //locallab + + // Locallab locallListener(nullptr), reserv(nullptr), + lastorigimp(nullptr), coordX(0), coordY(0), localX(0), localY(0), lllocalcurve(65536, 0), + cllocalcurve(65536, 0), + lclocalcurve(65536, 0), cclocalcurve(65536, 0), + rgblocalcurve(65536, 0), exlocalcurve(65536, 0), hltonecurveloc(65536, 0), //32768 shtonecurveloc(65536, 0), tonecurveloc(65536, 0), lightCurveloc(32770, 0), - locallutili(false), - localcutili(false), + lmasklocalcurve(65536, 0), + lmaskexplocalcurve(65536, 0), + lmaskSHlocalcurve(65536, 0), + lmaskviblocalcurve(65536, 0), + lmasktmlocalcurve(65536, 0), + lmaskretilocalcurve(65536, 0), + lmaskcblocalcurve(65536, 0), + lmaskbllocalcurve(65536, 0), + lmasklclocalcurve(65536, 0), + locallutili(false), + localclutili(false), + locallcutili(false), + localcutili(false), + localrgbutili(false), localexutili(false), llmasutili(false), lhmasutili(false), + lhhmasutili(false), lcmasutili(false), + localmaskutili(false), + localmaskexputili(false), + localmaskSHutili(false), + localmaskvibutili(false), + localmasktmutili(false), + localmaskretiutili(false), + localmaskcbutili(false), + localmaskblutili(false), + localmasklcutili(false), lcmasexputili(false), lhmasexputili(false), llmasexputili(false), lcmasSHutili(false), lhmasSHutili(false), - llmasSHutili(false), + llmasSHutili(false), + lcmasvibutili(false), + lhmasvibutili(false), + llmasvibutili(false), + lcmaslcutili(false), + lhmaslcutili(false), + llmaslcutili(false), lcmascbutili(false), lhmascbutili(false), - llmascbutili(false), - LHutili(false), + llmascbutili(false), + lcmasretiutili(false), + lhmasretiutili(false), + llmasretiutili(false), + lcmastmutili(false), + lhmastmutili(false), + llmastmutili(false), + lcmasblutili(false), + lhmasblutili(false), + llmasblutili(false), + locwavutili(false), + locwavdenutili(false), + loclevwavutili(false), + locconwavutili(false), + loccompwavutili(false), + loccomprewavutili(false), + locedgwavutili(false), + lmasutiliblwav(false), + lmasutilicolwav(false), + LHutili(false), HHutili(false), + lastsavrests(500, -10000), huerefs(500, -100000.f), huerefblurs(500, -100000.f), chromarefblurs(500, -100000.f), @@ -200,16 +260,24 @@ ImProcCoordinator::ImProcCoordinator() : chromar(0), lumar(0), sobeler(0), + lastsav(0), avg(0), lastspotdup(false), locallColorMask(0), + locallColorMaskinv(0), locallExpMask(0), + locallExpMaskinv(0), locallSHMask(0), + locallSHMaskinv(0), + locallvibMask(0), + localllcMask(0), locallcbMask(0), locallretiMask(0), locallsoftMask(0), + localltmMask(0), + locallblMask(0), + locallsharMask(0), retistrsav(nullptr) - { } @@ -240,12 +308,12 @@ ImProcCoordinator::~ImProcCoordinator() imgsrc->decreaseRef(); - if(customTransformIn) { + if (customTransformIn) { cmsDeleteTransform(customTransformIn); customTransformIn = nullptr; } - if(customTransformOut) { + if (customTransformOut) { cmsDeleteTransform(customTransformOut); customTransformOut = nullptr; } @@ -278,9 +346,6 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) MyMutex::MyLock processingLock(mProcessing); - constexpr int numofphases = 14; - int readyphase = 0; - bool highDetailNeeded = options.prevdemo == PD_Sidecar ? true : (todo & M_HIGHQUAL); // Check if any detail crops need high detail. If not, take a fast path short cut @@ -321,8 +386,6 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) //rp.deadPixelFilter = rp.hotPixelFilter = false; } - progress("Applying white balance, color correction & sRGB conversion...", 100 * readyphase / numofphases); - if (frameCountListener) { frameCountListener->FrameCountChanged(imgsrc->getFrameCount(), params->raw.bayersensor.imageNum); } @@ -332,9 +395,11 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) imgsrc->setCurrentFrame(params->raw.bayersensor.imageNum); imgsrc->preprocess(rp, params->lensProf, params->coarse); + if (flatFieldAutoClipListener && rp.ff_AutoClipControl) { flatFieldAutoClipListener->flatFieldAutoClipValueChanged(imgsrc->getFlatFieldAutoClipValue()); } + imgsrc->getRAWHistogram(histRedRaw, histGreenRaw, histBlueRaw); highDetailPreprocessComputed = highDetailNeeded; @@ -380,8 +445,9 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) printf("Demosaic X-Trans image with using method: %s\n", rp.xtranssensor.method.c_str()); } } - if(imgsrc->getSensorType() == ST_BAYER) { - if(params->raw.bayersensor.method != RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::PIXELSHIFT)) { + + if (imgsrc->getSensorType() == ST_BAYER) { + if (params->raw.bayersensor.method != RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::PIXELSHIFT)) { imgsrc->setBorder(params->raw.bayersensor.border); } else { imgsrc->setBorder(std::max(params->raw.bayersensor.border, 2)); @@ -389,20 +455,41 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) } else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) { imgsrc->setBorder(params->raw.xtranssensor.border); } + 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 { @@ -564,8 +651,6 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) ipf.firstAnalysis(orig_prev, *params, vhist16); } - readyphase++; - if ((todo & M_HDR) && (params->fattal.enabled || params->dehaze.enabled)) { if (fattal_11_dcrop_cache) { delete fattal_11_dcrop_cache; @@ -573,7 +658,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) } ipf.dehaze(orig_prev, params->dehaze); - ipf.ToneMapFattal02(orig_prev); + ipf.ToneMapFattal02(orig_prev, params->fattal, 3, 0, nullptr, 0, 0, 0); if (oprevi != orig_prev) { delete oprevi; @@ -582,9 +667,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) oprevi = orig_prev; - progress("Rotate / Distortion...", 100 * readyphase / numofphases); // Remove transformation if unneeded - bool needstransform = ipf.needsTransform(); + bool needstransform = ipf.needsTransform(fw, fh, imgsrc->getRotateDegree(), imgsrc->getMetaData()); if ((needstransform || ((todo & (M_TRANSFORM | M_RGBCURVE)) && params->dirpyrequalizer.cbdlMethod == "bef" && params->dirpyrequalizer.enabled && !params->colorappearance.enabled))) { assert(oprevi); @@ -608,11 +692,6 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) ipf.lab2rgb(labcbdl, *oprevi, params->icm.workingProfile); } - readyphase++; - progress("Preparing shadow/highlight map...", 100 * readyphase / numofphases); - - readyphase++; - if (todo & M_AUTOEXP) { if (params->toneCurve.autoexp) { LUTu aehist; @@ -647,11 +726,104 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) aeListener->autoMatchedToneCurveChanged(params->toneCurve.curveMode, params->toneCurve.curve); } } + + // Encoding log with locallab + if (params->locallab.enabled) { + const int sizespot = (int)params->locallab.spots.size(); + + float *sourceg = nullptr; + sourceg = new float[sizespot]; + float *targetg = nullptr; + targetg = new float[sizespot]; + bool *log = nullptr; + log = new bool[sizespot]; + bool *autocomput = nullptr; + autocomput = new bool[sizespot]; + float *blackev = nullptr; + blackev = new float[sizespot]; + float *whiteev = nullptr; + whiteev = new float[sizespot]; + bool *Autogr = nullptr; + Autogr = new bool[sizespot]; + + float *locx = nullptr; + locx = new float[sizespot]; + float *locy = nullptr; + locy = new float[sizespot]; + float *locxL = nullptr; + locxL = new float[sizespot]; + float *locyT = nullptr; + locyT = new float[sizespot]; + float *centx = nullptr; + centx = new float[sizespot]; + float *centy = nullptr; + centy = new float[sizespot]; + + for (int sp = 0; sp < sizespot; sp++) { + log[sp] = params->locallab.spots.at(sp).explog; + autocomput[sp] = params->locallab.spots.at(sp).autocompute; + blackev[sp] = params->locallab.spots.at(sp).blackEv; + whiteev[sp] = params->locallab.spots.at(sp).whiteEv; + sourceg[sp] = params->locallab.spots.at(sp).sourceGray; + Autogr[sp] = params->locallab.spots.at(sp).Autogray; + targetg[sp] = params->locallab.spots.at(sp).targetGray; + locx[sp] = params->locallab.spots.at(sp).locX / 2000.0; + locy[sp] = params->locallab.spots.at(sp).locY / 2000.0; + locxL[sp] = params->locallab.spots.at(sp).locXL / 2000.0; + locyT[sp] = params->locallab.spots.at(sp).locYT / 2000.0; + centx[sp] = params->locallab.spots.at(sp).centerX / 2000.0 + 0.5; + centy[sp] = params->locallab.spots.at(sp).centerY / 2000.0 + 0.5; + + const bool fullim = params->locallab.spots.at(sp).fullimage; + + if (log[sp] && autocomput[sp]) { + constexpr int SCALE = 10; + int fw, fh, tr = TR_NONE; + imgsrc->getFullSize(fw, fh, tr); + PreviewProps pp(0, 0, fw, fh, SCALE); + + float ysta = std::max(static_cast(centy[sp] - locyT[sp]), 0.f); + float yend = std::min(static_cast(centy[sp] + locy[sp]), 1.f); + float xsta = std::max(static_cast(centx[sp] - locxL[sp]), 0.f); + float xend = std::min(static_cast(centx[sp] + locx[sp]), 1.f); + + if (fullim) { + ysta = 0.f; + yend = 1.f; + xsta = 0.f; + xend = 1.f; + } + + ipf.getAutoLogloc(sp, imgsrc, sourceg, blackev, whiteev, Autogr, fw, fh, xsta, xend, ysta, yend, SCALE); + + params->locallab.spots.at(sp).blackEv = blackev[sp]; + params->locallab.spots.at(sp).whiteEv = whiteev[sp]; + params->locallab.spots.at(sp).sourceGray = sourceg[sp]; + + if (locallListener) { + locallListener->logencodChanged(blackev[sp], whiteev[sp], sourceg[sp], targetg[sp]); + } + } + } + + delete [] locx; + delete [] locy; + delete [] locxL; + delete [] locyT; + delete [] centx; + delete [] centy; + + delete [] Autogr; + delete [] whiteev; + delete [] blackev; + delete [] targetg; + delete [] sourceg; + delete [] log; + delete [] autocomput; + } } - progress("Exposure curve & CIELAB conversion...", 100 * readyphase / numofphases); - - if (todo & (M_AUTOEXP | M_RGBCURVE)) { + if (todo & (M_AUTOEXP | M_RGBCURVE)) { if (params->icm.workingTRC == "Custom") { //exec TRC IN free if (oprevi == orig_prev) { oprevi = new Imagefloat(pW, pH); @@ -663,17 +835,21 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) if (profile == "sRGB" || profile == "Adobe RGB" || profile == "ProPhoto" || profile == "WideGamut" || profile == "BruceRGB" || profile == "Beta RGB" || profile == "BestRGB" || profile == "Rec2020" || profile == "ACESp0" || profile == "ACESp1") { const int cw = oprevi->getWidth(); const int ch = oprevi->getHeight(); + // put gamma TRC to 1 - if(customTransformIn) { + if (customTransformIn) { cmsDeleteTransform(customTransformIn); customTransformIn = nullptr; } + ipf.workingtrc(oprevi, oprevi, cw, ch, -5, params->icm.workingProfile, 2.4, 12.92310, customTransformIn, true, false, true); + //adjust TRC - if(customTransformOut) { + if (customTransformOut) { cmsDeleteTransform(customTransformOut); customTransformOut = nullptr; } + ipf.workingtrc(oprevi, oprevi, cw, ch, 5, params->icm.workingProfile, params->icm.workingTRCGamma, params->icm.workingTRCSlope, customTransformOut, false, true, true); } } @@ -681,7 +857,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) if ((todo & M_RGBCURVE) || (todo & M_CROP)) { - // if (hListener) oprevi->calcCroppedHistogram(params, scale, histCropped); + // if (hListener) oprevi->calcCroppedHistogram(params, scale, histCropped); //complexCurve also calculated pre-curves histogram depending on crop CurveFactory::complexCurve(params->toneCurve.expcomp, params->toneCurve.black / 65535.0, @@ -772,10 +948,10 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) double ggm = 33.; double bbm = 33.; - DCPProfile::ApplyState as; + DCPProfileApplyState as; DCPProfile *dcpProf = imgsrc->getDCP(params->icm, as); - ipf.rgbProc (oprevi, oprevl, nullptr, hltonecurve, shtonecurve, tonecurve, params->toneCurve.saturation, + ipf.rgbProc(oprevi, oprevl, nullptr, hltonecurve, shtonecurve, tonecurve, params->toneCurve.saturation, rCurve, gCurve, bCurve, colourToningSatLimit, colourToningSatLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, beforeToneCurveBW, afterToneCurveBW, rrm, ggm, bbm, bwAutoR, bwAutoG, bwAutoB, params->toneCurve.expcomp, params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh, dcpProf, as, histToneCurve); if (params->blackwhite.enabled && params->blackwhite.autoc && abwListener) { @@ -793,16 +969,14 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) // correct GUI black and white with value } - // ipf.Lab_Tile(oprevl, oprevl, scale); + // ipf.Lab_Tile(oprevl, oprevl, scale); // compute L channel histogram int x1, y1, x2, y2; params->crop.mapToResized(pW, pH, scale, x1, x2, y1, y2); } - readyphase++; // lhist16(32768); - if (todo & (M_LUMACURVE | M_CROP)) { LUTu lhist16(32768); lhist16.clear(); @@ -842,191 +1016,353 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) params->labCurve.lccurve, chroma_acurve, chroma_bcurve, satcurve, lhskcurve, scale == 1 ? 1 : 16); } - //scale = 1; - if (todo & (M_LUMINANCE + M_COLOR)) { + //scale = 1; + + if ((todo & (M_LUMINANCE + M_COLOR)) || (todo & M_AUTOEXP)) { nprevl->CopyFrom(oprevl); - reserv->CopyFrom(oprevl); + reserv->CopyFrom(oprevl); + lastorigimp->CopyFrom(oprevl); - // int maxspot = 1; - progress("Applying Color Boost...", 100 * readyphase / numofphases); + // int maxspot = 1; + //************************************************************* + // locallab + //************************************************************* - //************************************************************* - // locallab - //************************************************************* - - if (params->locallab.enabled) { - /* - * 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 . - * 2017 2018 Jacques Desmis - * 2019 Pierre Cabrera - */ - - float **shbuffer = nullptr; - int sca = 1; - double huere, chromare, lumare, huerefblu, chromarefblu, lumarefblu, sobelre; - float avge; - std::vector locallref; - - for (size_t sp = 0; sp < params->locallab.spots.size(); sp++) { - // Set local curves of current spot to LUT - LHutili = false; - HHutili = false; - locallutili = false; - localexutili = false; - localcutili = false; - llmasutili = false; - lcmasexputili = false; - lhmasexputili = false; - llmasexputili = false; - lcmasSHutili = false; - lhmasSHutili = false; - llmasSHutili = false; - lcmascbutili = false; - lhmascbutili = false; - llmascbutili = false; - lcmasretiutili = false; - lhmasretiutili = false; - llmasretiutili = false; - lcmastmutili = false; - lhmastmutili = false; - llmastmutili = false; - lhmasutili = false; - lcmasutili = false; - locRETgainCurve.Set(params->locallab.spots.at(sp).localTgaincurve); - loclhCurve.Set(params->locallab.spots.at(sp).LHcurve, LHutili); - lochhCurve.Set(params->locallab.spots.at(sp).HHcurve, HHutili); - locccmasCurve.Set(params->locallab.spots.at(sp).CCmaskcurve, lcmasutili); - locllmasCurve.Set(params->locallab.spots.at(sp).LLmaskcurve, llmasutili); - lochhmasCurve.Set(params->locallab.spots.at(sp).HHmaskcurve, lhmasutili); - locllmasexpCurve.Set(params->locallab.spots.at(sp).LLmaskexpcurve, llmasexputili); - locccmasexpCurve.Set(params->locallab.spots.at(sp).CCmaskexpcurve, lcmasexputili); - lochhmasexpCurve.Set(params->locallab.spots.at(sp).HHmaskexpcurve, lhmasexputili); - locllmasSHCurve.Set(params->locallab.spots.at(sp).LLmaskSHcurve, llmasSHutili); - locccmasSHCurve.Set(params->locallab.spots.at(sp).CCmaskSHcurve, lcmasSHutili); - lochhmasSHCurve.Set(params->locallab.spots.at(sp).HHmaskSHcurve, lhmasSHutili); - locllmascbCurve.Set(params->locallab.spots.at(sp).LLmaskcbcurve, llmascbutili); - locccmascbCurve.Set(params->locallab.spots.at(sp).CCmaskcbcurve, lcmascbutili); - lochhmascbCurve.Set(params->locallab.spots.at(sp).HHmaskcbcurve, lhmascbutili); - locllmasretiCurve.Set(params->locallab.spots.at(sp).LLmaskreticurve, llmasretiutili); - locccmasretiCurve.Set(params->locallab.spots.at(sp).CCmaskreticurve, lcmasretiutili); - lochhmasretiCurve.Set(params->locallab.spots.at(sp).HHmaskreticurve, lhmasretiutili); - locllmastmCurve.Set(params->locallab.spots.at(sp).LLmasktmcurve, llmastmutili); - locccmastmCurve.Set(params->locallab.spots.at(sp).CCmasktmcurve, lcmastmutili); - lochhmastmCurve.Set(params->locallab.spots.at(sp).HHmasktmcurve, lhmastmutili); - locwavCurve.Set(params->locallab.spots.at(sp).locwavcurve); - CurveFactory::curveLocal(locallutili, params->locallab.spots.at(sp).llcurve, lllocalcurve, sca); - CurveFactory::curveCCLocal(localcutili, params->locallab.spots.at(sp).cccurve, cclocalcurve, sca); - CurveFactory::curveexLocal(localexutili, params->locallab.spots.at(sp).excurve, exlocalcurve, sca); - double ecomp = params->locallab.spots.at(sp).expcomp; - double black = params->locallab.spots.at(sp).black; - double hlcompr = params->locallab.spots.at(sp).hlcompr; - double hlcomprthresh = params->locallab.spots.at(sp).hlcomprthresh; - double shcompr = params->locallab.spots.at(sp).shcompr; - double br = params->locallab.spots.at(sp).lightness; - double cont = params->locallab.spots.at(sp).contrast; - - // Reference parameters computation - if (params->locallab.spots.at(sp).spotMethod == "exc") { - ipf.calc_ref(sp, reserv, reserv, 0, 0, pW, pH, scale, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avge); - } else { - ipf.calc_ref(sp, nprevl, nprevl, 0, 0, pW, pH, scale, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avge); - } - -// printf("improc avg=%f\n", avg); - huerblu = huerefblurs[sp] = huerefblu; - chromarblu = chromarefblurs[sp] = chromarefblu; - lumarblu = lumarefblurs[sp] = lumarefblu; - huer = huerefs[sp] = huere; - chromar = chromarefs[sp] = chromare; - lumar = lumarefs[sp] = lumare ; - sobeler = sobelrefs[sp] = sobelre; - avg = avgs[sp] = avge; - CurveFactory::complexCurvelocal(ecomp, black / 65535., hlcompr, hlcomprthresh, shcompr, br, cont, lumar, - hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, avg, - sca); - - // Save Locallab mask curve references for current spot - LocallabListener::locallabRef spotref; - spotref.huer = huer; - spotref.lumar = lumar; - spotref.chromar = chromar; - locallref.push_back(spotref); - - // Locallab tools computation - /* Notes: - * - shbuffer is used as nullptr + if (params->locallab.enabled) { + /* + * 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 . + * 2017 2018 Jacques Desmis + * 2019 Pierre Cabrera */ - // Locallab mask is only showed in detailed image - ipf.Lab_Local(3, sp, (float**)shbuffer, nprevl, nprevl, reserv, 0, 0, pW, pH, scale, locRETgainCurve, lllocalcurve, locallutili, loclhCurve, lochhCurve, locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, - locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, - locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, - locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, - locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, - locwavCurve, - LHutili, HHutili, cclocalcurve, localcutili, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, huerblu, chromarblu, lumarblu, huer, chromar, lumar, sobeler, 0, 0, 0, 0, 0, 0, 0); - //recalculate references after - if (params->locallab.spots.at(sp).spotMethod == "exc") { - ipf.calc_ref(sp, reserv, reserv, 0, 0, pW, pH, scale, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avg); - } else { - ipf.calc_ref(sp, nprevl, nprevl, 0, 0, pW, pH, scale, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avg); + float **shbuffer = nullptr; + int sca = 1; + double huere, chromare, lumare, huerefblu, chromarefblu, lumarefblu, sobelre; + float avge; + std::vector locallref; + std::vector locallretiminmax; + + for (int sp = 0; sp < (int)params->locallab.spots.size(); sp++) { + // Set local curves of current spot to LUT + LHutili = false; + HHutili = false; + locallutili = false; + localclutili = false; + locallcutili = false; + localexutili = false; + localrgbutili = false; + localcutili = false; + llmasutili = false; + lhmasutili = false; + lhhmasutili = false; + lcmasutili = false; + localmaskutili = false; + lcmasexputili = false; + lhmasexputili = false; + llmasexputili = false; + localmaskexputili = false; + localmaskSHutili = false; + localmaskvibutili = false; + localmasktmutili = false; + localmaskretiutili = false; + localmaskcbutili = false; + localmaskblutili = false; + localmasklcutili = false; + lcmasSHutili = false; + lhmasSHutili = false; + llmasSHutili = false; + lcmasvibutili = false; + lhmasvibutili = false; + llmasvibutili = false; + lcmascbutili = false; + lhmascbutili = false; + llmascbutili = false; + lcmaslcutili = false; + lhmaslcutili = false; + llmaslcutili = false; + lcmasretiutili = false; + lhmasretiutili = false; + llmasretiutili = false; + lcmastmutili = false; + lhmastmutili = false; + llmastmutili = false; + lcmasblutili = false; + lhmasblutili = false; + llmasblutili = false; + lcmasutili = false; + locwavutili = false; + locwavdenutili = false; + loclevwavutili = false; + locconwavutili = false; + loccompwavutili = false; + loccomprewavutili = false; + locedgwavutili = false; + lmasutiliblwav = false; + lmasutilicolwav = false; + locRETgainCurve.Set(params->locallab.spots.at(sp).localTgaincurve); + locRETtransCurve.Set(params->locallab.spots.at(sp).localTtranscurve); + loclhCurve.Set(params->locallab.spots.at(sp).LHcurve, LHutili); + lochhCurve.Set(params->locallab.spots.at(sp).HHcurve, HHutili); + locccmasCurve.Set(params->locallab.spots.at(sp).CCmaskcurve, lcmasutili); + locllmasCurve.Set(params->locallab.spots.at(sp).LLmaskcurve, llmasutili); + lochhmasCurve.Set(params->locallab.spots.at(sp).HHmaskcurve, lhmasutili); + lochhhmasCurve.Set(params->locallab.spots.at(sp).HHhmaskcurve, lhhmasutili); + locllmasexpCurve.Set(params->locallab.spots.at(sp).LLmaskexpcurve, llmasexputili); + locccmasexpCurve.Set(params->locallab.spots.at(sp).CCmaskexpcurve, lcmasexputili); + lochhmasexpCurve.Set(params->locallab.spots.at(sp).HHmaskexpcurve, lhmasexputili); + locllmasSHCurve.Set(params->locallab.spots.at(sp).LLmaskSHcurve, llmasSHutili); + locccmasSHCurve.Set(params->locallab.spots.at(sp).CCmaskSHcurve, lcmasSHutili); + lochhmasSHCurve.Set(params->locallab.spots.at(sp).HHmaskSHcurve, lhmasSHutili); + locllmasvibCurve.Set(params->locallab.spots.at(sp).LLmaskvibcurve, llmasvibutili); + locccmasvibCurve.Set(params->locallab.spots.at(sp).CCmaskvibcurve, lcmasvibutili); + lochhmasvibCurve.Set(params->locallab.spots.at(sp).HHmaskvibcurve, lhmasvibutili); + locllmascbCurve.Set(params->locallab.spots.at(sp).LLmaskcbcurve, llmascbutili); + locccmascbCurve.Set(params->locallab.spots.at(sp).CCmaskcbcurve, lcmascbutili); + lochhmascbCurve.Set(params->locallab.spots.at(sp).HHmaskcbcurve, lhmascbutili); + locllmaslcCurve.Set(params->locallab.spots.at(sp).LLmasklccurve, llmaslcutili); + locccmaslcCurve.Set(params->locallab.spots.at(sp).CCmasklccurve, lcmaslcutili); + lochhmaslcCurve.Set(params->locallab.spots.at(sp).HHmasklccurve, lhmaslcutili); + locllmasretiCurve.Set(params->locallab.spots.at(sp).LLmaskreticurve, llmasretiutili); + locccmasretiCurve.Set(params->locallab.spots.at(sp).CCmaskreticurve, lcmasretiutili); + lochhmasretiCurve.Set(params->locallab.spots.at(sp).HHmaskreticurve, lhmasretiutili); + locllmastmCurve.Set(params->locallab.spots.at(sp).LLmasktmcurve, llmastmutili); + locccmastmCurve.Set(params->locallab.spots.at(sp).CCmasktmcurve, lcmastmutili); + lochhmastmCurve.Set(params->locallab.spots.at(sp).HHmasktmcurve, lhmastmutili); + locllmasblCurve.Set(params->locallab.spots.at(sp).LLmaskblcurve, llmasblutili); + locccmasblCurve.Set(params->locallab.spots.at(sp).CCmaskblcurve, lcmasblutili); + lochhmasblCurve.Set(params->locallab.spots.at(sp).HHmaskblcurve, lhmasblutili); + loclmasCurveblwav.Set(params->locallab.spots.at(sp).LLmaskblcurvewav, lmasutiliblwav); + loclmasCurvecolwav.Set(params->locallab.spots.at(sp).LLmaskcolcurvewav, lmasutilicolwav); + locwavCurve.Set(params->locallab.spots.at(sp).locwavcurve, locwavutili); + loclevwavCurve.Set(params->locallab.spots.at(sp).loclevwavcurve, loclevwavutili); + locconwavCurve.Set(params->locallab.spots.at(sp).locconwavcurve, locconwavutili); + loccompwavCurve.Set(params->locallab.spots.at(sp).loccompwavcurve, loccompwavutili); + loccomprewavCurve.Set(params->locallab.spots.at(sp).loccomprewavcurve, loccomprewavutili); + locwavCurveden.Set(params->locallab.spots.at(sp).locwavcurveden, locwavdenutili); + locedgwavCurve.Set(params->locallab.spots.at(sp).locedgwavcurve, locedgwavutili); + CurveFactory::curveLocal(locallutili, params->locallab.spots.at(sp).llcurve, lllocalcurve, sca); + CurveFactory::curveLocal(localclutili, params->locallab.spots.at(sp).clcurve, cllocalcurve, sca); + CurveFactory::curveLocal(locallcutili, params->locallab.spots.at(sp).lccurve, lclocalcurve, sca); + CurveFactory::curveCCLocal(localcutili, params->locallab.spots.at(sp).cccurve, cclocalcurve, sca); + CurveFactory::curveLocal(localrgbutili, params->locallab.spots.at(sp).rgbcurve, rgblocalcurve, sca); + CurveFactory::curveexLocal(localexutili, params->locallab.spots.at(sp).excurve, exlocalcurve, sca); + CurveFactory::curvemaskLocal(localmaskutili, params->locallab.spots.at(sp).Lmaskcurve, lmasklocalcurve, sca); + CurveFactory::curvemaskLocal(localmaskexputili, params->locallab.spots.at(sp).Lmaskexpcurve, lmaskexplocalcurve, sca); + CurveFactory::curvemaskLocal(localmaskSHutili, params->locallab.spots.at(sp).LmaskSHcurve, lmaskSHlocalcurve, sca); + CurveFactory::curvemaskLocal(localmaskvibutili, params->locallab.spots.at(sp).Lmaskvibcurve, lmaskviblocalcurve, sca); + CurveFactory::curvemaskLocal(localmasktmutili, params->locallab.spots.at(sp).Lmasktmcurve, lmasktmlocalcurve, sca); + CurveFactory::curvemaskLocal(localmaskretiutili, params->locallab.spots.at(sp).Lmaskreticurve, lmaskretilocalcurve, sca); + CurveFactory::curvemaskLocal(localmaskcbutili, params->locallab.spots.at(sp).Lmaskcbcurve, lmaskcblocalcurve, sca); + CurveFactory::curvemaskLocal(localmaskblutili, params->locallab.spots.at(sp).Lmaskblcurve, lmaskbllocalcurve, sca); + CurveFactory::curvemaskLocal(localmasklcutili, params->locallab.spots.at(sp).Lmasklccurve, lmasklclocalcurve, sca); + double ecomp = params->locallab.spots.at(sp).expcomp; + double black = params->locallab.spots.at(sp).black; + double hlcompr = params->locallab.spots.at(sp).hlcompr; + double hlcomprthresh = params->locallab.spots.at(sp).hlcomprthresh; + double shcompr = params->locallab.spots.at(sp).shcompr; + double br = params->locallab.spots.at(sp).lightness; + double cont = params->locallab.spots.at(sp).contrast; + + if (black < 0. && params->locallab.spots.at(sp).expMethod == "pde") { + black *= 1.5; + } + + // Reference parameters computation + if (params->locallab.spots.at(sp).spotMethod == "exc") { + ipf.calc_ref(sp, reserv, reserv, 0, 0, pW, pH, scale, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avge, locwavCurveden, locwavdenutili); + } else { + ipf.calc_ref(sp, nprevl, nprevl, 0, 0, pW, pH, scale, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avge, locwavCurveden, locwavdenutili); + } + + huerblu = huerefblurs[sp] = huerefblu; + chromarblu = chromarefblurs[sp] = chromarefblu; + lumarblu = lumarefblurs[sp] = lumarefblu; + huer = huerefs[sp] = huere; + chromar = chromarefs[sp] = chromare; + lumar = lumarefs[sp] = lumare ; + sobeler = sobelrefs[sp] = sobelre; + avg = avgs[sp] = avge; + CurveFactory::complexCurvelocal(ecomp, black / 65535., hlcompr, hlcomprthresh, shcompr, br, cont, lumar, + hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, avg, + sca); + + // Save Locallab mask curve references for current spot + LocallabListener::locallabRef spotref; + spotref.huer = huer; + spotref.lumar = lumar; + spotref.chromar = chromar; + locallref.push_back(spotref); + + // Locallab tools computation + /* Notes: + * - shbuffer is used as nullptr + */ + // Locallab mask is only showed in detailed image + float minCD; + float maxCD; + float mini; + float maxi; + float Tmean; + float Tsigma; + float Tmin; + float Tmax; + ipf.Lab_Local(3, sp, (float**)shbuffer, nprevl, nprevl, reserv, lastorigimp, 0, 0, pW, pH, scale, locRETgainCurve, locRETtransCurve, + lllocalcurve, locallutili, + cllocalcurve, localclutili, + lclocalcurve, locallcutili, + loclhCurve, lochhCurve, + lmasklocalcurve, localmaskutili, + lmaskexplocalcurve, localmaskexputili, + lmaskSHlocalcurve, localmaskSHutili, + lmaskviblocalcurve, localmaskvibutili, + lmasktmlocalcurve, localmasktmutili, + lmaskretilocalcurve, localmaskretiutili, + lmaskcblocalcurve, localmaskcbutili, + lmaskbllocalcurve, localmaskblutili, + lmasklclocalcurve, localmasklcutili, + locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, lochhhmasCurve, lhhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, + locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, + locccmasvibCurve, lcmasvibutili, locllmasvibCurve, llmasvibutili, lochhmasvibCurve, lhmasvibutili, + locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, + locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, + locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, + locccmasblCurve, lcmasblutili, locllmasblCurve, llmasblutili, lochhmasblCurve, lhmasblutili, + locccmaslcCurve, lcmaslcutili, locllmaslcCurve, llmaslcutili, lochhmaslcCurve, lhmaslcutili, + loclmasCurveblwav, lmasutiliblwav, + loclmasCurvecolwav, lmasutilicolwav, + locwavCurve, locwavutili, + loclevwavCurve, loclevwavutili, + locconwavCurve, locconwavutili, + loccompwavCurve, loccompwavutili, + loccomprewavCurve, loccomprewavutili, + locwavCurveden, locwavdenutili, + locedgwavCurve, locedgwavutili, + LHutili, HHutili, cclocalcurve, localcutili, rgblocalcurve, localrgbutili, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, + huerblu, chromarblu, lumarblu, huer, chromar, lumar, sobeler, lastsav, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax); + + lastorigimp->CopyFrom(nprevl); + + // Save Locallab Retinex min/max for current spot + LocallabListener::locallabRetiMinMax retiMinMax; + retiMinMax.cdma = maxCD; + retiMinMax.cdmin = minCD; + retiMinMax.mini = mini; + retiMinMax.maxi = maxi; + retiMinMax.Tmean = Tmean; + retiMinMax.Tsigma = Tsigma; + retiMinMax.Tmin = Tmin; + retiMinMax.Tmax = Tmax; + locallretiminmax.push_back(retiMinMax); + + // Recalculate references after + if (params->locallab.spots.at(sp).spotMethod == "exc") { + ipf.calc_ref(sp, reserv, reserv, 0, 0, pW, pH, scale, huerefblu, chromarefblu, lumarefblu, huer, chromar, lumar, sobeler, avg, locwavCurveden, locwavdenutili); + } else { + ipf.calc_ref(sp, nprevl, nprevl, 0, 0, pW, pH, scale, huerefblu, chromarefblu, lumarefblu, huer, chromar, lumar, sobeler, avg, locwavCurveden, locwavdenutili); + } + + // Update Locallab reference values according to recurs parameter + if (params->locallab.spots.at(sp).recurs) { + locallref.at(sp).chromar = chromar; + locallref.at(sp).lumar = lumar; + locallref.at(sp).huer = huer; + } + + /* + //very bad idea : it's the story of the cat biting its tail + // brings big bugs.. + //restore ref values + huerefs[sp] = huer; + chromarefs[sp] = chromar; + lumarefs[sp] = lumar ; + sobelrefs[sp] = sobeler; + */ + lllocalcurve.clear(); + lclocalcurve.clear(); + cllocalcurve.clear(); + lightCurveloc.clear(); + cclocalcurve.clear(); + rgblocalcurve.clear(); + exlocalcurve.clear(); + lmasklocalcurve.clear(); + lmaskexplocalcurve.clear(); + lmaskSHlocalcurve.clear(); + lmaskviblocalcurve.clear(); + lmasktmlocalcurve.clear(); + lmaskretilocalcurve.clear(); + lmaskcblocalcurve.clear(); + lmaskbllocalcurve.clear(); + lmasklclocalcurve.clear(); + hltonecurveloc.clear(); + shtonecurveloc.clear(); + tonecurveloc.clear(); + locRETgainCurve.Reset(); + locRETtransCurve.Reset(); + loclhCurve.Reset(); + lochhCurve.Reset(); + locccmasCurve.Reset(); + locllmasCurve.Reset(); + lochhmasCurve.Reset(); + lochhhmasCurve.Reset(); + locllmasexpCurve.Reset(); + locccmasexpCurve.Reset(); + lochhmasexpCurve.Reset(); + locllmasSHCurve.Reset(); + locccmasSHCurve.Reset(); + lochhmasSHCurve.Reset(); + locllmasvibCurve.Reset(); + locccmasvibCurve.Reset(); + lochhmasvibCurve.Reset(); + locllmascbCurve.Reset(); + locccmascbCurve.Reset(); + lochhmascbCurve.Reset(); + locllmasretiCurve.Reset(); + locccmasretiCurve.Reset(); + lochhmasretiCurve.Reset(); + locllmastmCurve.Reset(); + locccmastmCurve.Reset(); + lochhmastmCurve.Reset(); + locllmasblCurve.Reset(); + locccmasblCurve.Reset(); + lochhmasblCurve.Reset(); + locllmaslcCurve.Reset(); + locccmaslcCurve.Reset(); + lochhmaslcCurve.Reset(); + locwavCurve.Reset(); + loclevwavCurve.Reset(); + locconwavCurve.Reset(); + locwavCurveden.Reset(); + locwavCurve.Reset(); + loclmasCurveblwav.Reset(); + loclmasCurvecolwav.Reset(); } - lllocalcurve.clear(); - lightCurveloc.clear(); - cclocalcurve.clear(); - exlocalcurve.clear(); - hltonecurveloc.clear(); - shtonecurveloc.clear(); - tonecurveloc.clear(); - locRETgainCurve.Reset(); - loclhCurve.Reset(); - lochhCurve.Reset(); - locccmasCurve.Reset(); - locllmasCurve.Reset(); - lochhmasCurve.Reset(); - locllmasexpCurve.Reset(); - locccmasexpCurve.Reset(); - lochhmasexpCurve.Reset(); - locllmasSHCurve.Reset(); - locccmasSHCurve.Reset(); - lochhmasSHCurve.Reset(); - locllmascbCurve.Reset(); - locccmascbCurve.Reset(); - lochhmascbCurve.Reset(); - locllmasretiCurve.Reset(); - locccmasretiCurve.Reset(); - lochhmasretiCurve.Reset(); - locllmastmCurve.Reset(); - locccmastmCurve.Reset(); - lochhmastmCurve.Reset(); - + // Transmit Locallab reference values and Locallab Retinex min/max to LocallabListener + if (locallListener) { + locallListener->refChanged(locallref, params->locallab.selspot); + locallListener->minmaxChanged(locallretiminmax, params->locallab.selspot); + } } - // Transmit Locallab reference values to LocallabListener - if (locallListener) { - locallListener->refChanged(locallref, params->locallab.selspot); - } - } - - //************************************************************* - // end locallab - //************************************************************* + //************************************************************* + // end locallab + //************************************************************* histCCurve.clear(); histLCurve.clear(); @@ -1038,72 +1374,22 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) ipf.EPDToneMap(nprevl, 0, scale); } - // for all treatments Defringe, Sharpening, Contrast detail , Microcontrast they are activated if "CIECAM" function are disabled - readyphase++; - - /* Issue 2785, disabled some 1:1 tools - if (scale==1) { - if((params->colorappearance.enabled && !settings->autocielab) || (!params->colorappearance.enabled)){ - progress ("Denoising luminance impulse...",100*readyphase/numofphases); - ipf.impulsedenoise (nprevl); - readyphase++; - } - if((params->colorappearance.enabled && !settings->autocielab) || (!params->colorappearance.enabled)){ - progress ("Defringing...",100*readyphase/numofphases); - ipf.defringe (nprevl); - readyphase++; - } - if (params->sharpenEdge.enabled) { - progress ("Edge sharpening...",100*readyphase/numofphases); - ipf.MLsharpen (nprevl); - readyphase++; - } - if (params->sharpenMicro.enabled) { - if(( params->colorappearance.enabled && !settings->autocielab) || (!params->colorappearance.enabled)){ - progress ("Microcontrast...",100*readyphase/numofphases); - ipf.MLmicrocontrast (nprevl); - readyphase++; - } - } - if(((params->colorappearance.enabled && !settings->autocielab) || (!params->colorappearance.enabled)) && params->sharpening.enabled) { - progress ("Sharpening...",100*readyphase/numofphases); - - float **buffer = new float*[pH]; - for (int i=0; idirpyrequalizer.cbdlMethod == "aft") { if (((params->colorappearance.enabled && !settings->autocielab) || (!params->colorappearance.enabled))) { - progress("Pyramid wavelet...", 100 * readyphase / numofphases); ipf.dirpyrequalizer(nprevl, scale); - //ipf.Lanczoslab (ip_wavelet(LabImage * lab, LabImage * dst, const procparams::EqualizerParams & eqparams), nprevl, 1.f/scale); - readyphase++; } } wavcontlutili = false; - //CurveFactory::curveWavContL ( wavcontlutili,params->wavelet.lcurve, wavclCurve, LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,int skip); CurveFactory::curveWavContL(wavcontlutili, params->wavelet.wavclCurve, wavclCurve, scale == 1 ? 1 : 16); if ((params->wavelet.enabled)) { WaveletParams WaveParams = params->wavelet; - // WaveParams.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY); WaveParams.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL); int kall = 0; - progress("Wavelet...", 100 * readyphase / numofphases); - // ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, scale); ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, scale); } @@ -1111,7 +1397,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) ipf.softLight(nprevl, params->softlight); if (params->colorappearance.enabled) { - //L histo and Chroma histo for ciecam + // L histo and Chroma histo for ciecam // histogram well be for Lab (Lch) values, because very difficult to do with J,Q, M, s, C int x1, y1, x2, y2; params->crop.mapToResized(pW, pH, scale, x1, x2, y1, y2); @@ -1179,7 +1465,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) CAMBrightCurveJ.dirty = true; CAMBrightCurveQ.dirty = true; - ipf.ciecam_02float(ncie, float (adap), pW, 2, nprevl, params.get(), customColCurve1, customColCurve2, customColCurve3, histLCAM, histCCAM, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 0 , scale, execsharp, d, dj, yb, 1); + ipf.ciecam_02float(ncie, float (adap), pW, 2, nprevl, params.get(), customColCurve1, customColCurve2, customColCurve3, histLCAM, histCCAM, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 0, scale, execsharp, d, dj, yb, 1); if ((params->colorappearance.autodegree || params->colorappearance.autodegreeout) && acListener && params->colorappearance.enabled) { acListener->autoCamChanged(100.* (double)d, 100.* (double)dj); @@ -1192,8 +1478,6 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) if (params->colorappearance.autoybscen && acListener && params->colorappearance.enabled) { acListener->ybCamChanged((int) yb); //real value Yb scene } - - readyphase++; } else { // CIECAM is disabled, we free up its image buffer to save some space if (ncie) { @@ -1226,9 +1510,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) if (crops[i]->hasListener() && (panningRelatedChange || (highDetailNeeded && options.prevdemo != PD_Sidecar) || (todo & (M_MONITOR | M_RGBCURVE | M_LUMACURVE)) || crops[i]->get_skip() == 1)) { crops[i]->update(todo); // may call ourselves } - if (panningRelatedChange || (todo & M_MONITOR)) { - progress("Conversion to RGB...", 100 * readyphase / numofphases); + if (panningRelatedChange || (todo & M_MONITOR)) { if ((todo != CROP && todo != MINUPDATE) || (todo & M_MONITOR)) { MyMutex::MyLock prevImgLock(previmg->getMutex()); @@ -1240,7 +1523,6 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) delete workimg; workimg = ipf.lab2rgb(nprevl, 0, 0, pW, pH, params->icm); } catch (char * str) { - progress("Error converting file...", 0); return; } } @@ -1259,13 +1541,12 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) imageListener->imageReady(params->crop); } - readyphase++; - if (hListener) { updateLRGBHistograms(); hListener->histogramChanged(histRed, histGreen, histBlue, histLuma, histToneCurve, histLCurve, histCCurve, /*histCLurve, histLLCurve,*/ histLCAM, histCCAM, histRedRaw, histGreenRaw, histBlueRaw, histChroma, histLRETI); } } + if (orig_prev != oprevi) { delete oprevi; oprevi = nullptr; @@ -1292,6 +1573,8 @@ void ImProcCoordinator::freeAll() nprevl = nullptr; delete reserv; reserv = nullptr; + delete lastorigimp; + lastorigimp = nullptr; if (ncie) { delete ncie; @@ -1346,6 +1629,7 @@ void ImProcCoordinator::setScale(int prevscale) oprevl = new LabImage(pW, pH); nprevl = new LabImage(pW, pH); reserv = new LabImage(pW, pH); + lastorigimp = new LabImage(pW, pH); // nprevloc = new LabImage (pW, pH); //ncie is only used in ImProcCoordinator::updatePreviewImage, it will be allocated on first use and deleted if not used anymore @@ -1428,15 +1712,6 @@ void ImProcCoordinator::updateLRGBHistograms() } -void ImProcCoordinator::progress(Glib::ustring str, int pr) -{ - - /* if (plistener) { - plistener->setProgressStr (str); - plistener->setProgress ((double)pr / 100.0); - }*/ -} - bool ImProcCoordinator::getAutoWB(double& temp, double& green, double equal, double tempBias) { @@ -1516,17 +1791,16 @@ bool ImProcCoordinator::getFilmNegativeExponents(int xA, int yA, int xB, int yB, MyMutex::MyLock lock(mProcessing); const auto xlate = - [this](int x, int y) -> Coord2D - { - const std::vector points = {Coord2D(x, y)}; + [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); + std::vector red; + std::vector green; + std::vector blue; + ipf.transCoord(fw, fh, points, red, green, blue); - return green[0]; - }; + return green[0]; + }; const int tr = getCoarseBitMask(params->coarse); @@ -1593,9 +1867,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) @@ -1646,7 +1927,7 @@ void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool a imgsrc->getImage(currWB, tr, im, pp, ppar.toneCurve, ppar.raw); ImProcFunctions ipf(&ppar, true); - if (ipf.needsTransform()) { + if (ipf.needsTransform(fW, fH, imgsrc->getRotateDegree(), imgsrc->getMetaData())) { Imagefloat* trImg = new Imagefloat(fW, fH); ipf.transform(im, trImg, 0, 0, 0, 0, fW, fH, fW, fH, imgsrc->getMetaData(), imgsrc->getRotateDegree(), true); @@ -1763,14 +2044,14 @@ void ImProcCoordinator::process() while (changeSinceLast) { const bool panningRelatedChange = - params->toneCurve != nextParams->toneCurve + params->toneCurve.isPanningRelatedChange(nextParams->toneCurve) || params->labCurve != nextParams->labCurve || params->locallab != nextParams->locallab || 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 @@ -1796,8 +2077,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 120aad1af..b0bbed66d 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.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 _IMPROCCOORDINATOR_H_ -#define _IMPROCCOORDINATOR_H_ +#pragma once #include -#include "rtengine.h" -#include "improcfun.h" -#include "image8.h" -#include "image16.h" -#include "imagesource.h" -#include "procevents.h" +#include "array2D.h" +#include "colortemp.h" +#include "curves.h" #include "dcrop.h" +#include "imagesource.h" +#include "improcfun.h" #include "LUT.h" +#include "rtengine.h" + #include "../rtgui/threadutils.h" +namespace Glib +{ +class Thread; +} + namespace rtengine { @@ -49,7 +54,7 @@ class Crop; * but using this class' LUT and other precomputed parameters. The main preview area is displaying a non framed Crop object, * while detail windows are framed Crop objects. */ -class ImProcCoordinator : public StagedImageProcessor +class ImProcCoordinator final : public StagedImageProcessor { friend class Crop; @@ -77,7 +82,7 @@ protected: bool softProof; bool gamutCheck; bool sharpMask; - + bool sharpMaskChanged; int scale; bool highDetailPreprocessComputed; bool highDetailRawComputed; @@ -161,6 +166,8 @@ protected: FlatFieldAutoClipListener *flatFieldAutoClipListener; AutoContrastListener *bayerAutoContrastListener; AutoContrastListener *xtransAutoContrastListener; + AutoContrastListener *pdSharpenAutoContrastListener; + AutoRadiusListener *pdSharpenAutoRadiusListener; FrameCountListener *frameCountListener; ImageTypeListener *imageTypeListener; AutoColorTonListener* actListener; @@ -179,7 +186,6 @@ protected: MyMutex minit; // to gain mutually exclusive access to ... to what exactly? - void progress(Glib::ustring str, int pr); void reallocAll(); void updateLRGBHistograms(); void setScale(int prevscale); @@ -222,52 +228,103 @@ protected: //locallab LocallabListener* locallListener; - LabImage *reserv; + LabImage *reserv; + LabImage *lastorigimp; int coordX, coordY, localX, localY; LUTf lllocalcurve; + LUTf cllocalcurve; + LUTf lclocalcurve; LUTf cclocalcurve; + LUTf rgblocalcurve; LUTf exlocalcurve; LUTf hltonecurveloc; LUTf shtonecurveloc; LUTf tonecurveloc; LUTf lightCurveloc; + LUTf lmasklocalcurve; + LUTf lmaskexplocalcurve; + LUTf lmaskSHlocalcurve; + LUTf lmaskviblocalcurve; + LUTf lmasktmlocalcurve; + LUTf lmaskretilocalcurve; + LUTf lmaskcblocalcurve; + LUTf lmaskbllocalcurve; + LUTf lmasklclocalcurve; // LUTu lhist16loc; LocretigainCurve locRETgainCurve; + LocretitransCurve locRETtransCurve; LocretigainCurverab locRETgainCurverab; LocLHCurve loclhCurve; LocHHCurve lochhCurve; LocCCmaskCurve locccmasCurve; LocLLmaskCurve locllmasCurve; LocHHmaskCurve lochhmasCurve; - LocCCmaskexpCurve locccmasexpCurve; - LocLLmaskexpCurve locllmasexpCurve; - LocHHmaskexpCurve lochhmasexpCurve; - LocCCmaskSHCurve locccmasSHCurve; - LocLLmaskSHCurve locllmasSHCurve; - LocHHmaskSHCurve lochhmasSHCurve; - LocCCmaskcbCurve locccmascbCurve; - LocLLmaskcbCurve locllmascbCurve; - LocHHmaskcbCurve lochhmascbCurve; - LocCCmaskretiCurve locccmasretiCurve; - LocLLmaskretiCurve locllmasretiCurve; - LocHHmaskretiCurve lochhmasretiCurve; - LocCCmasktmCurve locccmastmCurve; - LocLLmasktmCurve locllmastmCurve; - LocHHmasktmCurve lochhmastmCurve; + LocHHmaskCurve lochhhmasCurve; + LocCCmaskCurve locccmasexpCurve; + LocLLmaskCurve locllmasexpCurve; + LocHHmaskCurve lochhmasexpCurve; + LocCCmaskCurve locccmasSHCurve; + LocLLmaskCurve locllmasSHCurve; + LocHHmaskCurve lochhmasSHCurve; + LocCCmaskCurve locccmasvibCurve; + LocLLmaskCurve locllmasvibCurve; + LocHHmaskCurve lochhmasvibCurve; + LocCCmaskCurve locccmaslcCurve; + LocLLmaskCurve locllmaslcCurve; + LocHHmaskCurve lochhmaslcCurve; + LocCCmaskCurve locccmascbCurve; + LocLLmaskCurve locllmascbCurve; + LocHHmaskCurve lochhmascbCurve; + LocCCmaskCurve locccmasretiCurve; + LocLLmaskCurve locllmasretiCurve; + LocHHmaskCurve lochhmasretiCurve; + LocCCmaskCurve locccmastmCurve; + LocLLmaskCurve locllmastmCurve; + LocHHmaskCurve lochhmastmCurve; + LocCCmaskCurve locccmasblCurve; + LocLLmaskCurve locllmasblCurve; + LocHHmaskCurve lochhmasblCurve; LocwavCurve locwavCurve; + LocwavCurve loclmasCurveblwav; + LocwavCurve loclmasCurvecolwav; + LocwavCurve loclevwavCurve; + LocwavCurve locconwavCurve; + LocwavCurve loccompwavCurve; + LocwavCurve loccomprewavCurve; + LocwavCurve locwavCurveden; + LocwavCurve locedgwavCurve; bool locallutili; + bool localclutili; + bool locallcutili; bool localcutili; + bool localrgbutili; bool localexutili; bool llmasutili; bool lhmasutili; + bool lhhmasutili; bool lcmasutili; + bool localmaskutili; + bool localmaskexputili; + bool localmaskSHutili; + bool localmaskvibutili; + bool localmasktmutili; + bool localmaskretiutili; + bool localmaskcbutili; + bool localmaskblutili; + bool localmasklcutili; bool lcmasexputili; bool lhmasexputili; bool llmasexputili; bool lcmasSHutili; bool lhmasSHutili; bool llmasSHutili; + bool lcmasvibutili; + bool lhmasvibutili; + bool llmasvibutili; + bool lcmaslcutili; + bool lhmaslcutili; + bool llmaslcutili; bool lcmascbutili; bool lhmascbutili; bool llmascbutili; @@ -277,8 +334,21 @@ protected: bool lcmastmutili; bool lhmastmutili; bool llmastmutili; + bool lcmasblutili; + bool lhmasblutili; + bool llmasblutili; + bool locwavutili; + bool locwavdenutili; + bool loclevwavutili; + bool locconwavutili; + bool loccompwavutili; + bool loccomprewavutili; + bool locedgwavutili; + bool lmasutiliblwav; + bool lmasutilicolwav; bool LHutili; bool HHutili; + LUTu lastsavrests; LUTf huerefs; LUTf huerefblurs; LUTf chromarefblurs; @@ -288,16 +358,24 @@ protected: LUTf sobelrefs; LUTf avgs; double huer, huerblu, chromarblu, lumarblu, chromar, lumar, sobeler; + int lastsav; float avg; bool lastspotdup; int locallColorMask; + int locallColorMaskinv; int locallExpMask; + int locallExpMaskinv; int locallSHMask; + int locallSHMaskinv; + int locallvibMask; + int localllcMask; int locallcbMask; int locallretiMask; int locallsoftMask; int localltmMask; - + int locallblMask; + int locallsharMask; + public: ImProcCoordinator (); @@ -356,7 +434,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(); @@ -366,15 +444,22 @@ public: updaterThreadStart.unlock(); } - void setLocallabMaskVisibility (int locallColorMask, int locallExpMask, int locallSHMask, int locallcbMask, int locallretiMask, int locallsoftMask, int localltmMask) override + void setLocallabMaskVisibility (int locallColorMask, int locallColorMaskinv, int locallExpMask, int locallExpMaskinv, int locallSHMask, int locallSHMaskinv, int locallvibMask, int locallsoftMask, int locallblMask, int localltmMask, int locallretiMask, int locallsharMask, int localllcMask, int locallcbMask) override { this->locallColorMask = locallColorMask; + this->locallColorMaskinv = locallColorMaskinv; this->locallExpMask = locallExpMask; + this->locallExpMaskinv = locallExpMaskinv; this->locallSHMask = locallSHMask; - this->locallcbMask = locallcbMask; - this->locallretiMask = locallretiMask; + this->locallSHMaskinv = locallSHMaskinv; + this->locallvibMask = locallvibMask; this->locallsoftMask = locallsoftMask; + this->locallblMask = locallblMask; this->localltmMask = localltmMask; + this->locallretiMask = locallretiMask; + this->locallsharMask = locallsharMask; + this->localllcMask = localllcMask; + this->locallcbMask = locallcbMask; } void setProgressListener (ProgressListener* pl) override @@ -457,6 +542,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; @@ -490,5 +585,5 @@ public: } denoiseInfoStore; }; + } -#endif diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index acc330e9b..a75275c97 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -14,43 +14,48 @@ * GNU General Public License for more details. * * 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 +#include + #ifdef _OPENMP #include #endif #include "alignedbuffer.h" -#include "rtengine.h" -#include "improcfun.h" +#include "calc_distort.h" +#include "ciecam02.h" +#include "cieimage.h" +#include "clutstore.h" +#include "color.h" +#include "colortemp.h" #include "curves.h" -#include "mytime.h" +#include "dcp.h" +#include "EdgePreservingDecomposition.h" +#include "iccmatrices.h" #include "iccstore.h" #include "imagesource.h" -#include "rtthumbnail.h" -#include "utils.h" -#include "iccmatrices.h" -#include "color.h" -#include "calc_distort.h" -#include "rt_math.h" -#include "EdgePreservingDecomposition.h" -#include "improccoordinator.h" -#include "clutstore.h" -#include "ciecam02.h" -#include "StopWatch.h" +#include "improcfun.h" +#include "labimage.h" +#include "pipettebuffer.h" #include "procparams.h" -#include "../rtgui/ppversion.h" -#include "../rtgui/guiutils.h" +#include "rt_math.h" +#include "rtengine.h" +#include "rtthumbnail.h" +#include "satandvalueblendingcurve.h" +#include "StopWatch.h" +#include "utils.h" + #include "../rtgui/editcallbacks.h" -#undef CLIPD -#define CLIPD(a) ((a)>0.0f?((a)<1.0f?(a):1.0f):0.0f) +#ifdef _DEBUG +#include "mytime.h" +#endif -namespace -{ +namespace { using namespace rtengine; @@ -273,10 +278,7 @@ namespace rtengine using namespace procparams; -extern const Settings* settings; - - -ImProcFunctions::~ImProcFunctions() +ImProcFunctions::~ImProcFunctions () { if (monitorTransform) { cmsDeleteTransform(monitorTransform); @@ -306,7 +308,7 @@ void ImProcFunctions::updateColorProfiles(const Glib::ustring& monitorProfile, R #if !defined(__APPLE__) // No support for monitor profiles on OS X, all data is sRGB monitor = ICCStore::getInstance()->getProfile(monitorProfile); #else - monitor = ICCStore::getInstance()->getProfile (options.rtSettings.srgb); + monitor = ICCStore::getInstance()->getProfile (settings->srgb); #endif } @@ -885,7 +887,9 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb mean = (sum / ((height) * width)) / 327.68f; //for Yb for all image...if one day "pipette" we can adapt Yb for each zone } } - +#ifdef _OPENMP + static_cast(numThreads); // to silence cppcheck warning +#endif //evaluate lightness, contrast } @@ -1485,8 +1489,8 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb if (ciedata) { //only with improccoordinator // Data for J Q M s and C histograms int posl, posc; - float brli = 327.f; - float chsacol = 327.f; + float brli; + float chsacol; float libr; float colch; @@ -1739,7 +1743,7 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb 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(); } @@ -2065,25 +2069,25 @@ filmlike_clip(float *r, float *g, float *b) } } - - - - - - - - -void ImProcFunctions::rgbProc(Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, - int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clToningcurve, LUTf & cl2Toningcurve, - const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn, LUTu &histToneCurve, size_t chunkSize, bool measure) +void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, const LUTf& hltonecurve, const LUTf& shtonecurve, const LUTf& tonecurve, + int sat, const LUTf& rCurve, const LUTf& gCurve, const LUTf& bCurve, float satLimit, float satLimitOpacity, + const ColorGradientCurve& ctColorCurve, const OpacityCurve& ctOpacityCurve, bool opautili, const LUTf& clToningcurve, const LUTf& cl2Toningcurve, + const ToneCurve& customToneCurve1, const ToneCurve& customToneCurve2, const ToneCurve& customToneCurvebw1, const ToneCurve& customToneCurvebw2, + double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf, const DCPProfileApplyState& asIn, + LUTu& histToneCurve, size_t chunkSize, bool measure) { - rgbProc (working, lab, pipetteBuffer, hltonecurve, shtonecurve, tonecurve, sat, rCurve, gCurve, bCurve, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, params->toneCurve.expcomp, params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh, dcpProf, asIn, histToneCurve, chunkSize, measure); + rgbProc(working, lab, pipetteBuffer, hltonecurve, shtonecurve, tonecurve, sat, rCurve, gCurve, bCurve, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, + clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, + params->toneCurve.expcomp, params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh, dcpProf, asIn, histToneCurve, chunkSize, measure); } // Process RGB image and convert to LAB space -void ImProcFunctions::rgbProc(Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, - int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clToningcurve, LUTf & cl2Toningcurve, - const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn, LUTu &histToneCurve, size_t chunkSize, bool measure) +void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, const LUTf& hltonecurve, const LUTf& shtonecurve, const LUTf& tonecurve, + int sat, const LUTf& rCurve, const LUTf& gCurve, const LUTf& bCurve, float satLimit, float satLimitOpacity, + const ColorGradientCurve& ctColorCurve, const OpacityCurve& ctOpacityCurve, bool opautili, const LUTf& clToningcurve, const LUTf& cl2Toningcurve, + const ToneCurve& customToneCurve1, const ToneCurve& customToneCurve2, const ToneCurve& customToneCurvebw1, const ToneCurve& customToneCurvebw2, + double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh, + DCPProfile *dcpProf, const DCPProfileApplyState& asIn, LUTu& histToneCurve, size_t chunkSize, bool measure) { std::unique_ptr stop; @@ -2282,7 +2286,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 @@ -2826,7 +2830,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++) { @@ -2840,8 +2843,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]; @@ -3520,7 +3521,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) @@ -3797,10 +3797,9 @@ void ImProcFunctions::toningsmh(float r, float g, float b, float &ro, float &go, float rlo; //0.4 0.5 float rlm; //1.1 float rlh; //1.1 - float rlob; //for BW old mode if (mode == 0) { //colour - rlo = rlob = strProtect; //0.5 ==> 0.75 + rlo = strProtect; //0.5 ==> 0.75 rlh = 2.2f * strProtect; rlm = 1.5f * strProtect; constexpr float v0 = 0.15f; @@ -3817,7 +3816,6 @@ void ImProcFunctions::toningsmh(float r, float g, float b, float &ro, float &go, } } else { //bw coefficient to preserve same results as before for satlimtopacity = 0.5 (default) rlo = strProtect * 0.8f; //0.4 - rlob = strProtect; //0.5 rlm = strProtect * 2.2f; //1.1 rlh = strProtect * 2.4f; //1.2 @@ -3830,10 +3828,10 @@ 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); @@ -3845,26 +3843,26 @@ 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); @@ -4131,7 +4129,7 @@ void ImProcFunctions::toning2col(float r, float g, float b, float &ro, float &go * @param iplow iphigh [0..1] luminance * @param wp wip 3x3 matrix and inverse conversion rgb XYZ **/ -void ImProcFunctions::labtoning(float r, float g, float b, float &ro, float &go, float &bo, int algm, int metchrom, int twoc, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, LUTf & clToningcurve, LUTf & cl2Toningcurve, float iplow, float iphigh, double wp[3][3], double wip[3][3]) +void ImProcFunctions::labtoning (float r, float g, float b, float &ro, float &go, float &bo, int algm, int metchrom, int twoc, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, const LUTf & clToningcurve, const LUTf & cl2Toningcurve, float iplow, float iphigh, double wp[3][3], double wip[3][3] ) { ro = CLIP(r); go = CLIP(g); @@ -4190,7 +4188,7 @@ void ImProcFunctions::labtoning(float r, float g, float b, float &ro, float &go, } -void ImProcFunctions::luminanceCurve(LabImage* lold, LabImage* lnew, LUTf & curve) +void ImProcFunctions::luminanceCurve (LabImage* lold, LabImage* lnew, const LUTf& curve) { int W = lold->W; @@ -4210,7 +4208,7 @@ void ImProcFunctions::luminanceCurve(LabImage* lold, LabImage* lnew, LUTf & curv -void ImProcFunctions::chromiLuminanceCurve(PipetteBuffer *pipetteBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf & acurve, LUTf & bcurve, LUTf & satcurve, LUTf & lhskcurve, LUTf & clcurve, LUTf & curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histLCurve) +void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW, LabImage* lold, LabImage* lnew, const LUTf& acurve, const LUTf& bcurve, const LUTf& satcurve, const LUTf& lhskcurve, const LUTf& clcurve, LUTf & curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histLCurve) { int W = lold->W; int H = lold->H; @@ -4300,11 +4298,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; @@ -4317,11 +4313,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; @@ -4334,11 +4328,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; @@ -5181,11 +5173,11 @@ void ImProcFunctions::EPDToneMapCIE(CieImage *ncie, float a_w, float c_, int Wid if (!params->epd.enabled) { return; } - +/* if (params->wavelet.enabled && params->wavelet.tmrs != 0) { return; } - +*/ float stren = params->epd.strength; float edgest = params->epd.edgeStopping; float sca = params->epd.scale; @@ -5353,7 +5345,7 @@ void ImProcFunctions::EPDToneMaplocal(int sp, LabImage *lab, LabImage *tmp1, uns //Restore past range, also desaturate a bit per Mantiuk's Color correction for tone mapping. float s = (1.0f + 38.7889f) * powf(Compression, 1.5856f) / (1.0f + 38.7889f * powf(Compression, 1.5856f)); float sat = s + 0.3f * s * satur; - printf("s=%f sat=%f \n", s, sat); + //printf("s=%f sat=%f \n", s, sat); if(sat == 1.f) sat = 1.001f; #ifdef _OPENMP #pragma omp parallel for // removed schedule(dynamic,10) @@ -5386,11 +5378,11 @@ void ImProcFunctions::EPDToneMap(LabImage *lab, unsigned int Iterates, int skip) if (!params->epd.enabled) { return; } - +/* if (params->wavelet.enabled && params->wavelet.tmrs != 0) { return; } - +*/ float stren = params->epd.strength; float edgest = params->epd.edgeStopping; float sca = params->epd.scale; @@ -5504,7 +5496,7 @@ void ImProcFunctions::getAutoExp(const LUTu &histogram, int histcompr, double cl int imax = 65536 >> histcompr; int overex = 0; float sum = 0.f, hisum = 0.f, losum = 0.f; - float ave = 0.f, hidev = 0.f, lodev = 0.f; + float ave = 0.f; //find average luminance histogram.getSumAndAverage(sum, ave); @@ -5532,36 +5524,32 @@ void ImProcFunctions::getAutoExp(const LUTu &histogram, int histcompr, double cl float octile[8] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}, ospread = 0.f; count = 0; - int i = 0; + int j = 0; - for (; i < min((int)ave, imax); i++) { + for (; j < min ((int)ave, imax); ++j) { if (count < 8) { - octile[count] += histogram[i]; + octile[count] += histogram[j]; if (octile[count] > sum / 8.f || (count == 7 && octile[count] > sum / 16.f)) { - octile[count] = xlog(1. + (float)i) / log(2.f); + octile[count] = xlog (1. + j) / log (2.f); count++;// = min(count+1,7); } } - //lodev += SQR(ave-i)*histogram[i]; - lodev += (xlog(ave + 1.f) - xlog((float)i + 1.)) * histogram[i]; - losum += histogram[i]; + losum += histogram[j]; } - for (; i < imax; i++) { + for (; j < imax; ++j) { if (count < 8) { - octile[count] += histogram[i]; + octile[count] += histogram[j]; if (octile[count] > sum / 8.f || (count == 7 && octile[count] > sum / 16.f)) { - octile[count] = xlog(1. + (float)i) / log(2.f); + octile[count] = xlog (1. + j) / log (2.f); count++;// = min(count+1,7); } } - //hidev += SQR(i-ave)*histogram[i]; - hidev += (xlog((float)i + 1.) - xlog(ave + 1.f)) * histogram[i]; - hisum += histogram[i]; + hisum += histogram[j]; } @@ -5734,7 +5722,7 @@ void ImProcFunctions::getAutoExp(const LUTu &histogram, int histcompr, double cl whiteclipg = CurveFactory::igamma2((float)(whiteclipg / 65535.0)) * 65535.0; //need to inverse gamma transform to get correct exposure compensation parameter - //corection with gamma + //correction with gamma black = (int)((65535 * black) / whiteclipg); //expcomp = log(65535.0 / (whiteclipg)) / log(2.0); @@ -5963,7 +5951,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 17eb2642a..23154ecd2 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -14,37 +14,77 @@ * GNU General Public License for more details. * * 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_ +#pragma once + +#include +#include -#include "imagefloat.h" -#include "image16.h" -#include "image8.h" -#include "shmap.h" #include "coord2d.h" -#include "color.h" -#include "labimage.h" -#include "cieimage.h" -#include "LUT.h" -#include "lcp.h" -#include "dcp.h" -#include "curves.h" -#include "cplx_wavelet_dec.h" -#include "pipettebuffer.h" #include "gamutwarning.h" #include "jaggedarray.h" +#include "pipettebuffer.h" +#include "array2D.h" +#include "imagesource.h" +#include +namespace Glib +{ + +class ustring; + +} +template +class LUT; + +using LUTu = LUT; +using LUTf = LUT; + +template +class multi_array2D; namespace rtengine { +class ColorAppearance; +class ColorGradientCurve; +class DCPProfile; +class DCPProfileApplyState; +class FlatCurve; +class FramesMetaData; +class LensCorrection; +class LocCCmaskCurve; +class LocLLmaskCurve; +class LocHHmaskCurve; +class LocwavCurve; +class LocretigainCurve; +class LocretitransCurve; +class LocLHCurve; +class LocHHCurve; +class NoiseCurve; +class OpacityCurve; +class PipetteBuffer; +class ToneCurve; +class WavCurve; +class WavOpacityCurveBY; +class WavOpacityCurveRG; +class WavOpacityCurveW; +class WavOpacityCurveWL; + +class CieImage; +class Image8; +class Imagefloat; +class LabImage; +class wavelet_decomposition; + namespace procparams { class ProcParams; struct DehazeParams; +struct FattalToneMappingParams; +struct ColorManagementParams; struct DirPyrDenoiseParams; struct LocalContrastParams; struct LocallabParams; @@ -62,8 +102,9 @@ class ImProcFunctions { cmsHTRANSFORM monitorTransform; std::unique_ptr gamutWarning; + Cairo::RefPtr locImage; - const ProcParams* params; + const procparams::ProcParams* params; double scale; bool multiThread; @@ -76,131 +117,19 @@ class ImProcFunctions void calcVignettingParams(int oW, int oH, const procparams::VignettingParams& vignetting, double &w2, double &h2, double& maxRadius, double &v, double &b, double &mul); void transformLuminanceOnly(Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH); - void 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); - void transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap); + void 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, bool useOriginalBuffer); + void transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap, bool useOriginalBuffer); - bool needsCA(); - bool needsDistortion(); - bool needsRotation(); - bool needsPerspective(); - bool needsGradient(); - bool needsVignetting(); - bool needsLCP(); - bool needsLensfun(); + bool needsCA() const; + bool needsDistortion() const; + bool needsRotation() const; + bool needsPerspective() const; + bool needsGradient() const; + bool needsVignetting() const; + bool needsLCP() const; + bool needsLensfun() const; // 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 { TYPE_3X3_SOFT, @@ -213,7 +142,7 @@ public: double lumimul[3]; - ImProcFunctions(const ProcParams* iparams, bool imultiThread = true) + explicit ImProcFunctions(const procparams::ProcParams* iparams, bool imultiThread = true) : monitorTransform(nullptr), params(iparams), scale(1), multiThread(imultiThread), lumimul{} {} ~ImProcFunctions(); bool needsLuminanceOnly() @@ -222,19 +151,24 @@ public: } void setScale(double iscale); - bool needsTransform(); - bool needsPCVignetting(); - + bool needsTransform(int oW, int oH, int rawRotationDeg, const FramesMetaData *metadata) const; + bool needsPCVignetting() const; + float calcGradientFactor (const struct grad_params& gp, int x, int y); void firstAnalysis(const Imagefloat* const working, const procparams::ProcParams ¶ms, LUTu & vhist16); void updateColorProfiles(const Glib::ustring& monitorProfile, RenderingIntent monitorIntent, bool softProof, bool gamutCheck); - void rgbProc(Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, - int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, - const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn, LUTu &histToneCurve, size_t chunkSize = 1, bool measure = false); - void rgbProc(Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, - int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, - const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, - double expcomp, int hlcompr, int hlcomprthresh, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn, LUTu &histToneCurve, size_t chunkSize = 1, bool measure = false); - void labtoning(float r, float g, float b, float &ro, float &go, float &bo, int algm, int metchrom, int twoc, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, LUTf & clToningcurve, LUTf & cl2Toningcurve, float iplow, float iphigh, double wp[3][3], double wip[3][3]); + void rgbProc(Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, const LUTf& hltonecurve, const LUTf& shtonecurve, const LUTf& tonecurve, + int sat, const LUTf& rCurve, const LUTf& gCurve, const LUTf& bCurve, float satLimit, float satLimitOpacity, const ColorGradientCurve& ctColorCurve, + const OpacityCurve& ctOpacityCurve, bool opautili, const LUTf& clcurve, const LUTf& cl2curve, const ToneCurve& customToneCurve1, + const ToneCurve& customToneCurve2, const ToneCurve& customToneCurvebw1, const ToneCurve& customToneCurvebw2, + double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf, + const DCPProfileApplyState& asIn, LUTu& histToneCurve, size_t chunkSize = 1, bool measure = false); + void rgbProc(Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, const LUTf& hltonecurve, const LUTf& shtonecurve, const LUTf& tonecurve, + int sat, const LUTf& rCurve, const LUTf& gCurve, const LUTf& bCurve, float satLimit, float satLimitOpacity, const ColorGradientCurve& ctColorCurve, + const OpacityCurve& ctOpacityCurve, bool opautili, const LUTf& clcurve, const LUTf& cl2curve, const ToneCurve& customToneCurve1, + const ToneCurve& customToneCurve2, const ToneCurve& customToneCurvebw1, const ToneCurve& customToneCurvebw2, + double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, + int hlcomprthresh, DCPProfile *dcpProf, const DCPProfileApplyState& asIn, LUTu& histToneCurve, size_t chunkSize = 1, bool measure = false); + void labtoning(float r, float g, float b, float &ro, float &go, float &bo, int algm, int metchrom, int twoc, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, const LUTf & clToningcurve, const LUTf & cl2Toningcurve, float iplow, float iphigh, double wp[3][3], double wip[3][3]); void toning2col(float r, float g, float b, float &ro, float &go, float &bo, float iplow, float iphigh, float rl, float gl, float bl, float rh, float gh, float bh, float SatLow, float SatHigh, float balanS, float balanH, float reducac, int mode, int preser, float strProtect); void toningsmh(float r, float g, float b, float &ro, float &go, float &bo, float RedLow, float GreenLow, float BlueLow, float RedMed, float GreenMed, float BlueMed, float RedHigh, float GreenHigh, float BlueHigh, float reducac, int mode, float strProtect); void toningsmh2(float r, float g, float b, float &ro, float &go, float &bo, float low[3], float satLow, float med[3], float satMed, float high[3], float satHigh, float reducac, int mode, int preser); @@ -244,29 +178,28 @@ public: void retreavergb(float &r, float &g, float &b); void moyeqt(Imagefloat* working, float &moyS, float &eqty); - void luminanceCurve(LabImage* lold, LabImage* lnew, LUTf &curve); - + void luminanceCurve(LabImage* lold, LabImage* lnew, const LUTf &curve); void ciecamloc_02float(int sp, LabImage* lab); - void ciecam_02float(CieImage* ncie, float adap, int pW, int pwb, LabImage* lab, const ProcParams* params, + void ciecam_02float(CieImage* ncie, float adap, int pW, int pwb, LabImage* lab, const procparams::ProcParams* params, const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve, const ColorAppearance & customColCurve3, LUTu &histLCAM, LUTu &histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, float &d, float &dj, float &yb, int rtt, bool showSharpMask = false); - void chromiLuminanceCurve(PipetteBuffer *pipetteBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf &acurve, LUTf &bcurve, LUTf & satcurve, LUTf & satclcurve, LUTf &clcurve, LUTf &curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histLurve); + void chromiLuminanceCurve(PipetteBuffer *pipetteBuffer, int pW, LabImage* lold, LabImage* lnew, const LUTf& acurve, const LUTf& bcurve, const LUTf& satcurve, const LUTf& satclcurve, const LUTf& clcurve, LUTf &curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histLurve); void vibrance(LabImage* lab, const procparams::VibranceParams &vibranceParams, bool highlight, const Glib::ustring &workingProfile); //Jacques' vibrance void softprocess(const LabImage* bufcolorig, array2D &buflight, /* float ** bufchro, float ** buf_a, float ** buf_b, */ float rad, int bfh, int bfw, double epsilmax, double epsilmin, float thres, int sk, bool multiThread); - void softproc(const LabImage* bufcolorig, const LabImage* bufcolfin, float rad, int bfh, int bfw, double epsilmax, double epsilmin, float thres, int sk, bool multiThread); + void softproc(const LabImage* bufcolorig, const LabImage* bufcolfin, float rad, int bfh, int bfw, double epsilmax, double epsilmin, float thres, int sk, bool multiThread, int flag); // void colorCurve (LabImage* lold, LabImage* lnew); void sharpening(LabImage* lab, const procparams::SharpeningParams &sharpenParam, bool showMask = false); void sharpeningcam(CieImage* ncie, float** buffer, bool showMask = false); - void transform(Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, int rawRotationDeg, bool fullImage); - float resizeScale(const ProcParams* params, int fw, int fh, int &imw, int &imh); + void transform(Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, int rawRotationDeg, bool fullImage, bool useOriginalBuffer = false); + float resizeScale(const procparams::ProcParams* params, int fw, int fh, int &imw, int &imh); void lab2monitorRgb(LabImage* lab, Image8* image); void resize(Imagefloat* src, Imagefloat* dst, float dScale); 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 deconvsharpeningloc(float** luminance, float** buffer, int W, int H, float** loctemp, int damp, double radi, int ite, int amo, int contrast, double blurrad); void MLsharpen(LabImage* lab); // Manuel's clarity / sharpening @@ -285,6 +218,7 @@ public: void EPDToneMapResid(float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params& cp, int W_L, int H_L, float max0, float min0); void CompressDR(float *Source, int W_L, int H_L, float Compression, float DetailBoost); + void Compresslevels(float **Source, int W_L, int H_L, float compression, float detailattenuator, float thres, float mean, float maxp, float meanN, float maxN, float madL); void ContrastResid(float * WavCoeffs_L0, struct cont_params &cp, int W_L, int H_L, float max0, float min0); void EPDToneMap(LabImage *lab, unsigned int Iterates = 0, int skip = 1); @@ -298,49 +232,138 @@ public: void idirpyr(LabImage* data_coarse, LabImage* data_fine, int level, LUTf &rangefn_L, LUTf & nrwt_l, LUTf & nrwt_ab, int pitch, int scale, const int luma, const int chroma/*, LUTf & Lcurve, LUTf & abcurve*/); //locallab - void normalize_mean_dt(float *data, const float *ref, size_t size, float mod); - void retinex_pde(float *datain, float * dataout, int bfw, int bfh, float thresh, float multy, float *dE, int show); + void maskcalccol(int call, bool invmask, bool pde, int bfw, int bfh, int xstart, int ystart, int sk, int cx, int cy, LabImage* bufcolorig, LabImage* bufmaskblurcol, LabImage* originalmaskcol, LabImage* original, LabImage* reserved, int inv, struct local_params & lp, + float strumask, bool astool, + const LocCCmaskCurve & locccmasCurve, bool & lcmasutili, + const LocLLmaskCurve & locllmasCurve, bool & llmasutili, + const LocHHmaskCurve & lochhmasCurve, bool &lhmasutili, const LocHHmaskCurve & lochhhmasCurve, bool &lhhmasutili, + bool multiThread, bool enaMask, bool showmaske, bool deltaE, bool modmask, bool zero, bool modif, float chrom, float rad, float lap, float gamma, float slope, float blendm, int shado, float amountcd, float anchorcd, + LUTf & lmasklocalcurve, bool & localmaskutili, + const LocwavCurve & loclmasCurvecolwav, bool & lmasutilicolwav, int level_bl, int level_hl, int level_br, int level_hr, + int shortcu, bool delt, const float hueref, const float chromaref, const float lumaref, + float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope); + + void deltaEforMask(float **rdE, int bfw, int bfh, LabImage* bufcolorig, const float hueref, const float chromaref, const float lumaref, + float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, float balance, float balanceh); + void discrete_laplacian_threshold(float * data_out, const float * data_in, size_t nx, size_t ny, float t); + void rex_poisson_dct(float * data, size_t nx, size_t ny, double m); + void mean_dt(const float * data, size_t size, double * mean_p, double * dt_p); + double *cos_table(size_t size); + + void normalize_mean_dt(float *data, float *ref, size_t size, float mod, float sigm); + void retinex_pde(float *datain, float * dataout, int bfw, int bfh, float thresh, float multy, float *dE, int show, int dEenable, int normalize); void exposure_pde(float *dataor, float *datain, float * dataout, int bfw, int bfh, float thresh, float mod); void fftw_convol_blur(float *input, float *output, int bfw, int bfh, float radius, int fftkern, int algo); void fftw_convol_blur2(float **input2, float **output2, int bfw, int bfh, float radius, int fftkern, int algo); void fftw_tile_blur(int GW, int GH, int tilssize , int max_numblox_W, int min_numblox_W, float **tmp1, int numThreads, double radius); - void MSRLocal(int sp, bool fftw, int lum, LabImage * bufreti, LabImage * bufmask, LabImage * buforig, LabImage * buforigmas, float** luminance, float** templ, const float* const *originalLuminance, const int width, const int height, const procparams::LocallabParams &loc, const int skip, const LocretigainCurve &locRETgainCcurve, const int chrome, const int scall, const float krad, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, - const LocCCmaskretiCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskretiCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskretiCurve & lochhmasretiCurve, bool & lhmasretiutili, int llretiMask, LabImage * transformed, bool retiMasktmap, bool retiMask); - void calc_ref(int sp, LabImage* original, LabImage* transformed, int cx, int cy, int oW, int oH, int sk, double &huerefblur, double &chromarefblur, double &lumarefblur, double &hueref, double &chromaref, double &lumaref, double &sobelref, float &avg); + void maskforretinex(int sp, int before, float ** luminance, float ** out, int W_L, int H_L, int skip, + const LocCCmaskCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool & lhmasretiutili, + int llretiMask, bool retiMasktmap, bool retiMask, float rad, float lap, bool pde, float gamm, float slop, float chro, float blend, + LUTf & lmaskretilocalcurve, bool & localmaskretiutili, + LabImage * bufreti, LabImage * bufmask, LabImage * buforig, LabImage * buforigmas, bool multiThread, + bool delt, const float hueref, const float chromaref, const float lumaref, + float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, float balance, float balanceh, float lumask); + + //3 functions from Alberto Griggio, adapted J.Desmis 2019 + void filmGrain(Imagefloat *rgb, int isogr, int strengr, int scalegr, int bfw, int bfh); + void log_encode(Imagefloat *rgb, struct local_params & lp, float scale, bool multiThread, int bfw, int bfh); + void getAutoLogloc(int sp, ImageSource *imgsrc, float *sourceg, float *blackev, float *whiteev, bool *Autogr, int fw, int fh, float xsta, float xend, float ysta, float yend, int SCALE); + + void MSRLocal(int call, int sp, bool fftw, int lum, float** reducDE, LabImage * bufreti, LabImage * bufmask, LabImage * buforig, LabImage * buforigmas, float** luminance, float** templ, const float* const *originalLuminance, + const int width, const int height, int bfwr, int bfhr, const procparams::LocallabParams &loc, const int skip, const LocretigainCurve &locRETgainCcurve, const LocretitransCurve &locRETtransCcurve, + const int chrome, const int scall, const float krad, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, + const LocCCmaskCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool & lhmasretiutili, int llretiMask, + LUTf & lmaskretilocalcurve, bool & localmaskretiutili, + LabImage * transformed, bool retiMasktmap, bool retiMask, + bool delt, const float hueref, const float chromaref, const float lumaref, + float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, float balance, float balanceh, float lumask); + + + void calc_ref(int sp, LabImage* original, LabImage* transformed, int cx, int cy, int oW, int oH, int sk, double &huerefblur, double &chromarefblur, double &lumarefblur, double &hueref, double &chromaref, double &lumaref, double &sobelref, float &avg, const LocwavCurve & locwavCurveden, bool & locwavdenutili); void copy_ref(LabImage* spotbuffer, LabImage* original, LabImage* transformed, int cx, int cy, int sk, const struct local_params & lp, double &huerefspot, double &chromarefspot, double &lumarefspot); void paste_ref(LabImage* spotbuffer, LabImage* transformed, int cx, int cy, int sk, const struct local_params & lp); - void Lab_Local(int call, int sp, float** shbuffer, LabImage* original, LabImage* transformed, LabImage* reserved, int cx, int cy, int oW, int oH, int sk, const LocretigainCurve & locRETgainCcurve, LUTf & lllocalcurve, bool & locallutili, const LocLHCurve & loclhCurve, const LocHHCurve & lochhCurve, const LocCCmaskCurve & locccmasCurve, bool & lcmasutili, const LocLLmaskCurve & locllmasCurve, bool & llmasutili, const LocHHmaskCurve & lochhmasCurve, bool & lhmasutili, const LocCCmaskexpCurve & locccmasexpCurve, bool &lcmasexputili, const LocLLmaskexpCurve & locllmasexpCurve, bool &llmasexputili, const LocHHmaskexpCurve & lochhmasexpCurve, bool & lhmasexputili, - const LocCCmaskSHCurve & locccmasSHCurve, bool &lcmasSHutili, const LocLLmaskSHCurve & locllmasSHCurve, bool &llmasSHutili, const LocHHmaskSHCurve & lochhmasSHCurve, bool & lhmasSHutili, - const LocCCmaskcbCurve & locccmascbCurve, bool &lcmascbutili, const LocLLmaskcbCurve & locllmascbCurve, bool &llmascbutili, const LocHHmaskcbCurve & lochhmascbCurve, bool & lhmascbutili, - const LocCCmaskretiCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskretiCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskretiCurve & lochhmasretiCurve, bool & lhmasretiutili, - const LocCCmasktmCurve & locccmastmCurve, bool &lcmastmutili, const LocLLmasktmCurve & locllmastmCurve, bool &llmastmutili, const LocHHmasktmCurve & lochhmastmCurve, bool & lhmastmutili, - const LocwavCurve & locwavCurve, - bool &LHutili, bool &HHutili, LUTf & cclocalcurve, bool & localcutili, bool & localexutili, LUTf & exlocalcurve, LUTf & hltonecurveloc, LUTf & shtonecurveloc, LUTf & tonecurveloc, LUTf & lightCurveloc, double & huerefblur, double &chromarefblur, double & lumarefblur, double &hueref, double &chromaref, double &lumaref, double &sobelref, int llColorMask, int llExpMask, int llSHMask, int llcbMask, int llretiMask, int llsoftMask, int lltmMask); + void Lab_Local(int call, int sp, float** shbuffer, LabImage* original, LabImage* transformed, LabImage* reserved, LabImage* lastorig, int cx, int cy, int oW, int oH, int sk, const LocretigainCurve & locRETgainCcurve, const LocretitransCurve &locRETtransCcurve, + LUTf & lllocalcurve, bool & locallutili, + LUTf & cllocalcurve, bool & localclutili, + LUTf & lclocalcurve, bool & locallcutili, + const LocLHCurve & loclhCurve, const LocHHCurve & lochhCurve, + LUTf & lmasklocalcurve, bool & localmaskutili, + LUTf & lmaskexplocalcurve, bool & localmaskexputili, + LUTf & lmaskSHlocalcurve, bool & localmaskSHutili, + LUTf & lmaskviblocalcurve, bool & localmaskvibutili, + LUTf & lmasktmlocalcurve, bool & localmasktmutili, + LUTf & lmaskretilocalcurve, bool & localmaskretiutili, + LUTf & lmaskcblocalcurve, bool & localmaskcbutili, + LUTf & lmaskbllocalcurve, bool & localmaskblutili, + LUTf & lmasklclocalcurve, bool & localmasklcutili, + const LocCCmaskCurve & locccmasCurve, bool & lcmasutili, const LocLLmaskCurve & locllmasCurve, bool & llmasutili, const LocHHmaskCurve & lochhmasCurve, bool & lhmasutili, const LocHHmaskCurve & lochhhmasCurve, bool & lhhmasutili, + const LocCCmaskCurve & locccmasexpCurve, bool &lcmasexputili, const LocLLmaskCurve & locllmasexpCurve, bool &llmasexputili, const LocHHmaskCurve & lochhmasexpCurve, bool & lhmasexputili, + const LocCCmaskCurve & locccmasSHCurve, bool &lcmasSHutili, const LocLLmaskCurve & locllmasSHCurve, bool &llmasSHutili, const LocHHmaskCurve & lochhmasSHCurve, bool & lhmasSHutili, + const LocCCmaskCurve & locccmasvibCurve, bool &lcmasvibutili, const LocLLmaskCurve & locllmasvibCurve, bool &llmasvibutili, const LocHHmaskCurve & lochhmasvibCurve, bool & lhmasvibutili, + const LocCCmaskCurve & locccmascbCurve, bool &lcmascbutili, const LocLLmaskCurve & locllmascbCurve, bool &llmascbutili, const LocHHmaskCurve & lochhmascbCurve, bool & lhmascbutili, + const LocCCmaskCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool & lhmasretiutili, + const LocCCmaskCurve & locccmastmCurve, bool &lcmastmutili, const LocLLmaskCurve & locllmastmCurve, bool &llmastmutili, const LocHHmaskCurve & lochhmastmCurve, bool & lhmastmutili, + const LocCCmaskCurve & locccmasblCurve, bool &lcmasblutili, const LocLLmaskCurve & locllmasblCurve, bool &llmasblutili, const LocHHmaskCurve & lochhmasblCurve, bool & lhmasblutili, + const LocCCmaskCurve & locccmaslcCurve, bool &lcmaslcutili, const LocLLmaskCurve & locllmaslcCurve, bool &llmaslcutili, const LocHHmaskCurve & lochhmaslcCurve, bool & lhmaslcutili, + const LocwavCurve & loclmasCurveblwav, bool & lmasutiliblwav, + const LocwavCurve & loclmasCurvecolwav, bool & lmasutilicolwav, + const LocwavCurve & locwavCurve, bool & locwavutili, + const LocwavCurve & loclevwavCurve, bool & loclevwavutili, + const LocwavCurve & locconwavCurve, bool & locconwavutili, + const LocwavCurve & loccompwavCurve, bool & loccompwavutili, + const LocwavCurve & loccomprewavCurve, bool & loccomprewavutili, + const LocwavCurve & locwavCurveden, bool & locwavdenutili, + const LocwavCurve & locedgwavCurve, bool & locedgwavutili, + bool &LHutili, bool &HHutili, LUTf & cclocalcurve, bool & localcutili, LUTf & rgblocalcurve, bool & localrgbutili, bool & localexutili, LUTf & exlocalcurve, LUTf & hltonecurveloc, LUTf & shtonecurveloc, LUTf & tonecurveloc, LUTf & lightCurveloc, + double & huerefblur, double &chromarefblur, double & lumarefblur, double &hueref, double &chromaref, double &lumaref, double &sobelref, int &lastsav, + int llColorMask, int llColorMaskinv, int llExpMask, int llExpMaskinv, int llSHMask, int llSHMaskinv, int llvibMask, int lllcMask, int llsharMask, int llcbMask, int llretiMask, int llsoftMask, int lltmMask, int llblMask, + float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax); + void addGaNoise(LabImage *lab, LabImage *dst, const float mean, const float variance, const int sk); void BlurNoise_Localold(int call, const struct local_params& lp, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy); - void InverseBlurNoise_Local(const struct local_params& lp, const float hueref, const float chromaref, const float lumaref, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy, int sk); + void InverseBlurNoise_Local(LabImage * originalmask, float **bufchro, const struct local_params& lp, const float hueref, const float chromaref, const float lumaref, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy, int sk); void InverseReti_Local(const struct local_params& lp, const float hueref, const float chromaref, const float lumaref, LabImage* original, LabImage* transformed, const LabImage* const tmp1, int cx, int cy, int chro, int sk); - void BlurNoise_Local(LabImage* tmp1, const float hueref, const float chromaref, const float lumaref, const local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int sk); + void BlurNoise_Local(LabImage* tmp1, LabImage * originalmask, float **bufchro, const float hueref, const float chromaref, const float lumaref, local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int sk); static void strcurv_data(std::string retistr, int *s_datc, int &siz); void blendstruc(int bfw, int bfh, LabImage* bufcolorig, float radius, float stru, array2D & blend2, int sk, bool multiThread); - void transit_shapedetect_retinex(int senstype, LabImage * bufexporig, LabImage * bufmask, LabImage * buforigmas, float **buflight, float **bufchro, const float hueref, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk); - void transit_shapedetect(int senstype, const LabImage *bufexporig, LabImage * originalmask, float **buflight, float **bufchro, float **buf_a_cat, float ** buf_b_cat, float ** bufhh, bool HHutili, const float hueref, const float chromaref, const float lumaref, float sobelref, float meansobel, float ** blend2, const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk); - void exlabLocal(const local_params& lp, int bfh, int bfw, LabImage* bufexporig, LabImage* lab, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, float mean); + void wavcontrast4(struct local_params& lp, float ** tmp, float ** tmpa, float ** tmpb, float contrast, float fatres, float radblur, float radlevblur, int bfw, int bfh, int level_bl, int level_hl, int level_br, int level_hr, int sk, bool numThreads, const LocwavCurve & locwavCurve, bool & locwavutili, bool wavcurve, + const LocwavCurve & loclevwavCurve, bool & loclevwavutili, bool wavcurvelev, + const LocwavCurve & locconwavCurve, bool & locconwavutili, bool wavcurvecon, + const LocwavCurve & loccompwavCurve, bool & loccompwavutili, bool wavcurvecomp, + const LocwavCurve & loccomprewavCurve, bool & loccomprewavutili, bool wavcurvecompre, + const LocwavCurve & locedgwavCurve, bool & locedgwavutili, + float sigm, float offs,int & maxlvl, float fatdet, float fatanch, float chromalev, float chromablu, bool blurlc, bool blurena, bool levelena, bool comprena, bool compreena, float compress, float thres); + + void wavcont(wavelet_decomposition &wdspot, float ****templevel, int level_bl, int maxlvl, + const LocwavCurve & loclevwavCurve, bool & loclevwavutili, + const LocwavCurve & loccompwavCurve, bool & loccompwavutili, + const LocwavCurve & loccomprewavCurve, bool & loccomprewavutili, + float radlevblur, int process, procparams::FattalToneMappingParams &fatParams, float chromablu, float thres); + + void wavcbd(wavelet_decomposition &wdspot, int level_bl, int maxlvl, + const LocwavCurve & locconwavCurve, bool & locconwavutili, float sigm, float offs, float chromalev, int sk); + + void transit_shapedetect2(int call, int senstype, const LabImage * bufexporig, const LabImage * bufexpfin, LabImage * originalmask, const float hueref, const float chromaref, const float lumaref, float sobelref, float meansobel, float ** blend2, struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk); + + void transit_shapedetect_retinex(int call, int senstype, LabImage * bufexporig, LabImage * bufmask, LabImage * buforigmas, float **buflight, float **bufchro, const float hueref, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk); + void transit_shapedetect(int senstype, const LabImage *bufexporig, LabImage * originalmask, float **bufchro, bool HHutili, const float hueref, const float chromaref, const float lumaref, float sobelref, float meansobel, float ** blend2, const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk); + void exlabLocal(local_params& lp, int bfh, int bfw, LabImage* bufexporig, LabImage* lab, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, float mean); void Exclude_Local(float **deltaso, float hueref, float chromaref, float lumaref, float sobelref, float meansobel, const struct local_params & lp, const LabImage * original, LabImage * transformed, const LabImage * rsv, const LabImage * reserv, int cx, int cy, int sk); - void DeNoise_Local(int call, const struct local_params& lp, int levred, float hueref, float lumaref, float chromaref, LabImage* original, LabImage* transformed, LabImage &tmp1, int cx, int cy, int sk); + void DeNoise_Local(int call, struct local_params& lp, LabImage * originalmask, int levred, float hueref, float lumaref, float chromaref, LabImage* original, LabImage* transformed, LabImage &tmp1, int cx, int cy, int sk); + void DeNoise(int call, int del, float * slidL, float * slida, float * slidb, int aut, bool noiscfactiv, struct local_params& lp, LabImage* originalmaskbl, int levred, float huerefblur, float lumarefblur, float chromarefblur, LabImage* original, LabImage* transformed, int cx, int cy, int sk); void fftw_denoise(int GW, int GH, int max_numblox_W, int min_numblox_W, float **tmp1, array2D *Lin, int numThreads, const struct local_params & lp, int chrom); void ColorLight_Local(float moddE, float powdE, int call, LabImage * bufcolorig, LabImage * originalmask, float **buflight, float **bufchro, float **bufchroslid, float ** bufhh, float ** buflightslid, bool &LHutili, bool &HHutili, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, float sobelref, float ** blend2, LUTf & lllocalcurve, const LocLHCurve & loclhCurve, const LocHHCurve & lochhCurve, LUTf & lightCurveloc, const local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int sk); - void InverseColorLight_Local(int sp, int senstype, const struct local_params& lp, LUTf & lightCurveloc, LUTf & hltonecurveloc, LUTf & shtonecurveloc, LUTf & tonecurveloc, LUTf & exlocalcurve, LUTf & cclocalcurve, float adjustr, bool localcutili, LUTf & lllocalcurve, bool locallutili, LabImage* original, LabImage* transformed, int cx, int cy, const float hueref, const float chromaref, const float lumaref, int sk); - void Sharp_Local(int call, float **loctemp, int senstype, const float hueref, const float chromaref, const float lumaref, const local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk); + void InverseColorLight_Local(bool tonequ, bool tonecurv, int sp, int senstype, struct local_params& lp, LabImage * originalmask, LUTf & lightCurveloc, LUTf & hltonecurveloc, LUTf & shtonecurveloc, LUTf & tonecurveloc, LUTf & exlocalcurve, LUTf & cclocalcurve, float adjustr, bool localcutili, LUTf & lllocalcurve, bool locallutili, LabImage* original, LabImage* transformed, int cx, int cy, const float hueref, const float chromaref, const float lumaref, int sk); + void Sharp_Local(int call, float **loctemp, int senstype, const float hueref, const float chromaref, const float lumaref, local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk); // void Sharp_Local(int call, float **loctemp, int senstype, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int sk); - void InverseSharp_Local(float **loctemp, const float hueref, const float lumaref, const float chromaref, const local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int sk); + void InverseSharp_Local(float **loctemp, const float hueref, const float lumaref, const float chromaref, local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int sk); void Tile_calc(int tilesize, int overlap, int kall, int imwidth, int imheight, int &numtiles_W, int &numtiles_H, int &tilewidth, int &tileheight, int &tileWskip, int &tileHskip); @@ -366,28 +389,28 @@ public: void Aver(float * HH_Coeffs, int datalen, float &averagePlus, float &averageNeg, float &max, float &min); void Sigma(float * HH_Coeffs, int datalen, float averagePlus, float averageNeg, float &sigmaPlus, float &sigmaNeg); - void calckoe(float ** WavCoeffs_LL, const struct cont_params& cp, float ** koeLi, int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC = nullptr); - + // void calckoe(float ** WavCoeffs_LL, const struct cont_params& cp, float ** koeLi, int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC = nullptr); + void calckoe(float ** WavCoeffs_LL, float gradw, float tloww, float ** koeLi, int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC = nullptr); void Median_Denoise(float **src, float **dst, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = nullptr); void Median_Denoise(float **src, float **dst, float upperBound, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = nullptr); void RGB_denoise(int kall, Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, float * ch_M, float *max_r, float *max_b, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, const NoiseCurve & noiseLCurve, const NoiseCurve & noiseCCurve, float &nresi, float &highresi); void RGB_denoise_infoGamCurve(const procparams::DirPyrDenoiseParams & dnparams, const bool isRAW, LUTf &gamcurve, float &gam, float &gamthresh, float &gamslope); - void RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false); - void RGBtile_denoise(float * fLblox, int hblproc, float noisevar_Ldetail, float * nbrwt, float * blurbuffer); //for DCT + void RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, bool isRAW, const LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false); + void RGBtile_denoise(float * fLblox, int hblproc, float noisevar_Ldetail); //for DCT void RGBoutput_tile_row(float *bloxrow_L, float ** Ldetail, float ** tilemask_out, int height, int width, int top); - bool WaveletDenoiseAllL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels); - bool WaveletDenoiseAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels); - bool WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels); + bool WaveletDenoiseAllL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels); + bool WaveletDenoiseAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels); + bool WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float *variC, int local, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, int denoiseNestedLevels); - void WaveletDenoiseAll_info(int levwav, wavelet_decomposition &WaveletCoeffs_a, - wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float & minblueaut, int schoice, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, + void WaveletDenoiseAll_info(int levwav, const wavelet_decomposition &WaveletCoeffs_a, + const wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float & minblueaut, int schoice, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb); - bool WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels); - void ShrinkAllL(wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, float *noisevarlum, float * madL, float * vari, int edge); - void ShrinkAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir, + bool WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge, int denoiseNestedLevels); + void ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, float *noisevarlum, float * madL, float * vari, int edge); + void ShrinkAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir, float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, float * madL, float * variC, int local, float * madaab = nullptr, bool madCalculated = false); void ShrinkAll_info(float ** WavCoeffs_a, float ** WavCoeffs_b, int W_ab, int H_ab, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, int schoice, int lvl, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, @@ -399,12 +422,8 @@ public: // pyramid wavelet void cbdl_local_temp(float ** src, float ** loctemp, int srcwidth, int srcheight, const float * mult, float kchro, const double dirpyrThreshold, const float mergeL, const float contres, const float blurcb, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scale, bool multiThread); - void idirpyr_eq_channel_loc(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float multi[6], const float blucb, const double dirpyrThreshold, float ** l_a_h, float ** l_b_c, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scaleprev, bool multiThread); - 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); @@ -415,14 +434,15 @@ public: void Badpixelscam(CieImage * ncie, double radius, int thresh, int mode, float chrom, bool hotbad); void BadpixelsLab(LabImage * lab, double radius, int thresh, float chrom); - void dehaze(Imagefloat *rgb, const DehazeParams &dehazeParams); - void ToneMapFattal02(Imagefloat *rgb); - void localContrast(LabImage *lab, float **destination, const LocalContrastParams &localContrastParams, bool fftwlc, double scale); + void dehaze(Imagefloat *rgb, const procparams::DehazeParams &dehazeParams); + void dehazeloc(Imagefloat *rgb, const procparams::DehazeParams &dehazeParams); + void ToneMapFattal02(Imagefloat *rgb, const procparams::FattalToneMappingParams &fatParams, int detail_level, int Lalone, float **Lum, int WW, int HH, int algo); + void localContrast(LabImage *lab, float **destination, const procparams::LocalContrastParams &localContrastParams, bool fftwlc, double scale); void colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread); // void shadowsHighlights(LabImage *lab); void shadowsHighlights(LabImage *lab, bool ena, int labmode, int hightli, int shado, int rad, int scal, int hltonal, int shtonal); - void softLight(LabImage *lab, const SoftLightParams &softLightParams); + void softLight(LabImage *lab, const procparams::SoftLightParams &softLightParams); void labColorCorrectionRegions(LabImage *lab); Image8* lab2rgb(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool consider_histogram_settings = true); @@ -430,13 +450,13 @@ public: // CieImage *ciec; void workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, const Glib::ustring &profile, double gampos, double slpos, cmsHTRANSFORM &transform, bool normalizeIn = true, bool normalizeOut = true, bool keepTransForm = false) const; - bool transCoord(int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr); - bool transCoord(int W, int H, const std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr); + bool transCoord(int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr) const; + bool transCoord(int W, int H, const std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr) const; static void getAutoExp(const LUTu & histogram, int histcompr, double clip, double& expcomp, int& bright, int& contr, int& black, int& hlcompr, int& hlcomprthresh); static double getAutoDistor(const Glib::ustring& fname, int thumb_size); - double getTransformAutoFill(int oW, int oH, const LensCorrection *pLCPMap = nullptr); + double getTransformAutoFill(int oW, int oH, const LensCorrection *pLCPMap = nullptr) const; void rgb2lab(const Imagefloat &src, LabImage &dst, const Glib::ustring &workingSpace); void lab2rgb(const LabImage &src, Imagefloat &dst, const Glib::ustring &workingSpace); }; + } -#endif diff --git a/rtengine/impulse_denoise.cc b/rtengine/impulse_denoise.cc index 907afc1a1..20229e714 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 * @@ -22,7 +22,7 @@ #include "labimage.h" #include "improcfun.h" #include "cieimage.h" -#include "sleef.c" +#include "sleef.h" #include "opthelper.h" #include "gauss.h" diff --git a/rtengine/init.cc b/rtengine/init.cc index 8d7ee451f..1a00f7ff6 100644 --- a/rtengine/init.cc +++ b/rtengine/init.cc @@ -14,10 +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 . */ #include #include "../rtgui/profilestorecombobox.h" +#include "color.h" #include "rtengine.h" #include "iccstore.h" #include "dcp.h" @@ -42,7 +43,7 @@ const Settings* settings; MyMutex* lcmsMutex = nullptr; MyMutex *fftwMutex = nullptr; -int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir, bool loadAll) +int init (const Settings* s, const Glib::ustring& baseDir, const Glib::ustring& userSettingsDir, bool loadAll) { settings = s; ProcParams::init(); diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc index 7feaf3321..4b72e269d 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,41 +26,84 @@ * * using a guided filter for the "soft matting" of the transmission map * - */ +*/ +#include #include -#include +#include +#include "array2D.h" +#include "color.h" #include "guidedfilter.h" +#include "iccstore.h" +#include "imagefloat.h" #include "improcfun.h" #include "procparams.h" -#include "rt_algo.h" +#include "rescale.h" #include "rt_math.h" +//#define BENCHMARK +#include "StopWatch.h" -extern Options options; +#include "../rtgui/options.h" -namespace rtengine { +namespace rtengine +{ -namespace { +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)); + } + } -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) + 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, 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(); @@ -68,63 +111,108 @@ int get_dark_channel(const array2D &R, const array2D &G, const arr #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 val = RT_INFINITY_F; + 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) { - 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); + 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]); } } - if (clip) { - val = LIM01(val); - } + +#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)); + 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(); + +#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 val = RT_INFINITY_F; + const int pW = min(x + patchsize, W); + + 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]); + } + } + + 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)); +} 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; @@ -138,40 +226,45 @@ float estimate_ambient_light(const array2D &R, const array2D &G, c } } - if (options.rtSettings.verbose) { + if (settings->verbose) { std::cout << "dehaze: computing ambient light from " << patches.size() << " patches" << std::endl; } 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); - const int pH = min(p.second+patchsize, H); - + const int pW = min(p.first + patchsize, W); + const int pH = min(p.second + patchsize, H); + 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; int n = 0; + for (auto &p : patches) { - const int pW = min(p.first+patchsize, W); - const int pH = min(p.second+patchsize, H); - + const int pW = min(p.first + patchsize, W); + const int pH = min(p.second + patchsize, H); + for (int y = p.second; y < pH; ++y) { for (int x = p.first; x < pW; ++x) { float r = R[y][x]; float g = G[y][x]; float b = B[y][x]; + if (r + g + b >= bright_lim) { rr += r; gg += g; @@ -181,6 +274,7 @@ float estimate_ambient_light(const array2D &R, const array2D &G, c } } } + n = std::max(n, 1); ambient[0] = rr / n; ambient[1] = gg / n; @@ -190,7 +284,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(); @@ -208,121 +301,326 @@ void extract_channels(Imagefloat *img, array2D &r, array2D &g, arr } // namespace - void ImProcFunctions::dehaze(Imagefloat *img, const DehazeParams &dehazeParams) { - if (!dehazeParams.enabled) { + if (!dehazeParams.enabled || dehazeParams.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(dehazeParams.strength) / 100.f * 0.9f); - if (options.rtSettings.verbose) { + if (settings->verbose) { std::cout << "dehaze: strength = " << strength << std::endl; } 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); - + + { + 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 (settings->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); - 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); - - if (options.rtSettings.verbose) { + if (settings->verbose) { std::cout << "dehaze: ambient light is " << ambient[0] << ", " << ambient[1] << ", " << ambient[2] << 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; + if (settings->verbose) { + std::cout << "dehaze: max distance is " << maxDistance << std::endl; } - float depth = -float(dehazeParams.depth) / 100.f; - const float t0 = max(1e-3f, std::exp(depth * max_t)); + const float depth = -float(dehazeParams.depth) / 100.f; + const float t0 = max(1e-3f, std::exp(depth * maxDistance)); const float teps = 1e-3f; + + const bool luminance = dehazeParams.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... + 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 + 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 (dehazeParams.showDepthMap) { + 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 { + 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 (dehazeParams.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; + } + } + } +} + + + +void ImProcFunctions::dehazeloc(Imagefloat *img, const DehazeParams &dehazeParams) +{ + //J.Desmis 12 2019 - this version derived from ART, is slower than the main from maximimum 10% - probably use of SSE + //Probably Ingo could solved this problem in some times + BENCHFUN + if (!dehazeParams.enabled || dehazeParams.strength == 0.0) { + return; + } + + + + const float maxChannel = normalize(img, multiThread); + + const int W = img->getWidth(); + const int H = img->getHeight(); + const float strength = LIM01(float(std::abs(dehazeParams.strength)) / 100.f * 0.9f); + const bool add_haze = dehazeParams.strength < 0; + + if (settings->verbose) { + std::cout << "dehaze: strength = " << strength << std::endl; + } + + array2D dark(W, H); + + int patchsize = max(int(5 / scale), 2); + float ambient[3]; + float maxDistance = 0.f; + + { + 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); + + { + 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 (settings->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 (settings->verbose) { + std::cout << "dehaze: ambient light is " + << ambient[0] << ", " << ambient[1] << ", " << ambient[2] + << std::endl; + } + + get_dark_channel(R, G, B, dark, patchsize, ambient, true, multiThread, strength); + } + + + const int radius = patchsize * 4; + constexpr float epsilon = 1e-5f; + + array2D guideB(W, H, img->b.ptrs, ARRAY2D_BYREFERENCE); + guidedFilter(guideB, dark, dark, radius, epsilon, multiThread); + + if (settings->verbose) { + std::cout << "dehaze: max distance is " << maxDistance << std::endl; + } + + const float depth = -float(dehazeParams.depth) / 100.f; + const float teps = 1e-6f; + const float t0 = max(teps, std::exp(depth * maxDistance)); + + const bool luminance = dehazeParams.luminance; + const TMatrix ws = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile); + + 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) { + int x = 0; + for (; x < W; ++x) { // 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) }; // ... 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); - if (dehazeParams.showDepthMap) { - img->r(y, x) = img->g(y, x) = img->b(y, x) = LIM01(1.f - mt); - } 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]; + 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 &ir = img->r(y, x); + float &ig = img->g(y, x); + float &ib = img->b(y, x); + const float mt = max(dark[y][x], t0, tl + teps); + + if (dehazeParams.showDepthMap) { + img->r(y, x) = img->g(y, x) = img->b(y, x) = LIM01(1.f - mt) * maxChannel; + } else if (luminance) { + float Y = Color::rgbLuminance(img->r(y, x), img->g(y, x), img->b(y, x), ws); + float YY = (Y - ambientY) / mt + ambientY; + + if (Y > 1e-5f) { + if (add_haze) { + YY = Y + Y - YY; + } + + float f = YY / Y; + ir = rgb[0] * f; + ig = rgb[1] * f; + ib = rgb[2] * f; + + } + } 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]); + + if (add_haze) { + ir += (ir - r); + ig += (ig - g); + ib += (ib - b); + } else { + ir = r; + ig = g; + ib = b; + } - img->r(y, x) = r; - img->g(y, x) = g; - img->b(y, x) = b; } } } - img->normalizeFloatTo65535(); + restore(img, maxChannel, multiThread); + } } // namespace rtengine diff --git a/rtengine/ipgrain.cc b/rtengine/ipgrain.cc new file mode 100644 index 000000000..b9079606a --- /dev/null +++ b/rtengine/ipgrain.cc @@ -0,0 +1,371 @@ +/* -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Copyright (c) 2018 Alberto Griggio + * Small adaptation to Rawtherapee Locallab October 2019 + * 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 . + */ + +/* film grain emulation. + * Ported from darktable (src/iop/grain.c). Original copyright/license follows + */ +/* + This file is part of darktable, + copyright (c) 2010-2012 Henrik Andersson. + + darktable 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. + + darktable 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 darktable. If not, see . +*/ + +#include "imagefloat.h" +#include "improcfun.h" +#include "rt_math.h" + + +namespace rtengine { + +namespace { + +constexpr float GRAIN_LIGHTNESS_STRENGTH_SCALE = 0.15f; +constexpr float GRAIN_SCALE_FACTOR = 213.2f; + +constexpr int GRAIN_LUT_SIZE = 128; +constexpr float GRAIN_LUT_DELTA_MAX = 2.0f; +constexpr float GRAIN_LUT_DELTA_MIN = 0.0001f; +constexpr float GRAIN_LUT_PAPER_GAMMA = 1.0f; + + +const int grad3[12][3] = { { 1, 1, 0 }, + { -1, 1, 0 }, + { 1, -1, 0 }, + { -1, -1, 0 }, + { 1, 0, 1 }, + { -1, 0, 1 }, + { 1, 0, -1 }, + { -1, 0, -1 }, + { 0, 1, 1 }, + { 0, -1, 1 }, + { 0, 1, -1 }, + { 0, -1, -1 } }; + +const int permutation[] + = { 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, + 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, + 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, + 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, + 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, + 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, + 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, + 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, + 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, + 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, + 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, + 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, + 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 }; + + +class GrainEvaluator { +public: + GrainEvaluator(int offset_x, int offset_y, int full_width, int full_height, double scale): + ox(offset_x), + oy(offset_y), + fw(full_width), + fh(full_height), + scale(scale) + { + simplex_noise_init(); + constexpr float mb = 100.f; + evaluate_grain_lut(mb); + } + + void operator()(int isogr, int strengr, int scalegr, Imagefloat *lab, bool multithread) + { + const double strength = (strengr / 100.0); + const double octaves = 3; + const double wd = std::min(fw, fh); + const double zoom = (1.0 + 8 * (double(isogr) / GRAIN_SCALE_FACTOR) / 100.0) / 800.0; + const double s = std::max(scale / 3.0, 1.0) / (double(std::max(scalegr, 1)) / 100.0); + + const int W = lab->getWidth(); + const int H = lab->getHeight(); + float **lab_L = lab->g.ptrs; + +#ifdef _OPENMP +# pragma omp parallel for if (multithread) +#endif + for (int j = 0; j < H; ++j) { + double wy = oy + j; + double y = wy / wd; + for (int i = 0; i < W; ++i) { + double wx = ox + i; + double x = wx / wd; + double noise = simplex_2d_noise(x, y, octaves, 1.0, zoom) / s; + lab_L[j][i] += lut_lookup(noise * strength * GRAIN_LIGHTNESS_STRENGTH_SCALE, lab_L[j][i] / 32768.f); + } + } + } + +private: + void simplex_noise_init() + { + for(int i = 0; i < 512; i++) perm[i] = permutation[i & 255]; + } + + double dot(const int *g, double x, double y, double z) + { + return g[0] * x + g[1] * y + g[2] * z; + } + + float FASTFLOOR(float x) + { + return (x > 0 ? (int)(x) : (int)(x)-1); + } + + double simplex_noise(double xin, double yin, double zin) + { + double n0, n1, n2, n3; // Noise contributions from the four corners + // Skew the input space to determine which simplex cell we're in + const double F3 = 1.0 / 3.0; + const double s = (xin + yin + zin) * F3; // Very nice and simple skew factor for 3D + const int i = FASTFLOOR(xin + s); + const int j = FASTFLOOR(yin + s); + const int k = FASTFLOOR(zin + s); + const double G3 = 1.0 / 6.0; // Very nice and simple unskew factor, too + const double t = (i + j + k) * G3; + const double X0 = i - t; // Unskew the cell origin back to (x,y,z) space + const double Y0 = j - t; + const double Z0 = k - t; + const double x0 = xin - X0; // The x,y,z distances from the cell origin + const double y0 = yin - Y0; + const double z0 = zin - Z0; + // For the 3D case, the simplex shape is a slightly irregular tetrahedron. + // Determine which simplex we are in. + int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords + int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords + if(x0 >= y0) + { + if(y0 >= z0) + { + i1 = 1; // X Y Z order + j1 = 0; + k1 = 0; + i2 = 1; + j2 = 1; + k2 = 0; + } + else if(x0 >= z0) + { + i1 = 1; // X Z Y order + j1 = 0; + k1 = 0; + i2 = 1; + j2 = 0; + k2 = 1; + } + else + { + i1 = 0; // Z X Y order + j1 = 0; + k1 = 1; + i2 = 1; + j2 = 0; + k2 = 1; + } + } + else // x0. + * along with RawTherapee. If not, see . */ #include "rtengine.h" +#include "image8.h" +#include "imagefloat.h" +#include "labimage.h" #include "improcfun.h" -#include +#include #include "iccstore.h" #include "iccmatrices.h" -#include "../rtgui/options.h" #include "settings.h" -#include "curves.h" #include "alignedbuffer.h" #include "color.h" #include "procparams.h" @@ -33,20 +34,12 @@ namespace rtengine extern void filmlike_clip(float *r, float *g, float *b); -extern const Settings* settings; - namespace { inline void copyAndClampLine(const float *src, unsigned char *dst, const int W) { - for (int j = 0, iy = 0; j < W; ++j) { - float r = src[iy] * MAXVALF; - float g = src[iy+1] * MAXVALF; - float b = src[iy+2] * MAXVALF; - dst[iy] = uint16ToUint8Rounded(CLIP(r)); - dst[iy+1] = uint16ToUint8Rounded(CLIP(g)); - dst[iy+2] = uint16ToUint8Rounded(CLIP(b)); - iy += 3; + for (int j = 0; j < W * 3; ++j) { + dst[j] = uint16ToUint8Rounded(CLIP(src[j] * MAXVALF)); } } @@ -91,8 +84,8 @@ void ImProcFunctions::lab2monitorRgb(LabImage* lab, Image8* image) { if (monitorTransform) { - int W = lab->W; - int H = lab->H; + const int W = lab->W; + const int H = lab->H; unsigned char * data = image->data; // cmsDoTransform is relatively expensive @@ -101,18 +94,19 @@ void ImProcFunctions::lab2monitorRgb(LabImage* lab, Image8* image) #endif { AlignedBuffer pBuf(3 * lab->W); - AlignedBuffer mBuf(3 * lab->W); + AlignedBuffer mBuf; AlignedBuffer gwBuf1; AlignedBuffer gwBuf2; if (gamutWarning) { gwBuf1.resize(3 * lab->W); gwBuf2.resize(3 * lab->W); + mBuf.resize(3 * lab->W); } float *buffer = pBuf.data; - float *outbuffer = mBuf.data; + float *outbuffer = gamutWarning ? mBuf.data : pBuf.data; // make in place transformations when gamutWarning is not needed #ifdef _OPENMP #pragma omp for schedule(dynamic,16) @@ -133,7 +127,7 @@ void ImProcFunctions::lab2monitorRgb(LabImage* lab, Image8* image) buffer[iy++] = rb[j] / 327.68f; } - cmsDoTransform (monitorTransform, buffer, outbuffer, W); + cmsDoTransform(monitorTransform, buffer, outbuffer, W); copyAndClampLine(outbuffer, data + ix, W); if (gamutWarning) { @@ -356,24 +350,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))) } }; @@ -381,7 +370,6 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, if (transform) { hTransform = transform; } else { - double pwr = 1.0 / gampos; double ts = slpos; int five = mul; diff --git a/rtengine/iplabregions.cc b/rtengine/iplabregions.cc index 5945398d2..6526419f5 100644 --- a/rtengine/iplabregions.cc +++ b/rtengine/iplabregions.cc @@ -15,19 +15,21 @@ * GNU General Public License for more details. * * 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 "array2D.h" +#include "color.h" +#include "curves.h" #include "guidedfilter.h" +#include "iccstore.h" +#include "improcfun.h" +#include "labimage.h" #include "procparams.h" +#include "sleef.h" + //#define BENCHMARK #include "StopWatch.h" -#include "sleef.c" namespace { @@ -51,7 +53,8 @@ void fastlin2log(float *x, float factor, float base, int w) } -namespace rtengine { +namespace rtengine +{ void ImProcFunctions::labColorCorrectionRegions(LabImage *lab) { diff --git a/rtengine/iplocalcontrast.cc b/rtengine/iplocalcontrast.cc index cdf463130..f2d82751f 100644 --- a/rtengine/iplocalcontrast.cc +++ b/rtengine/iplocalcontrast.cc @@ -19,25 +19,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 . */ -#ifdef _OPENMP -#include -#endif - #include "array2D.h" #include "gauss.h" +#include "labimage.h" #include "improcfun.h" #include "procparams.h" +#include "settings.h" namespace rtengine { - extern const Settings* settings; - - LocallabParams locallab; ///< Local lab parameters -void ImProcFunctions::localContrast(LabImage *lab, float **destination, const LocalContrastParams &localContrastParams, bool fftwlc, double scale) +void ImProcFunctions::localContrast(LabImage *lab, float **destination, const rtengine::procparams::LocalContrastParams &localContrastParams, bool fftwlc, double scale) { if (!localContrastParams.enabled) { return; @@ -70,7 +65,7 @@ void ImProcFunctions::localContrast(LabImage *lab, float **destination, const Lo } else {//sigma *= sigma kr = sigma; } - // printf("kr=%f \n", kr); + //OPENMP disabled ImProcFunctions::fftw_convol_blur2(lab->L, buf, width, height, kr * sigma, 0, 0); } #ifdef _OPENMP diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index 643ebbfe3..4b297879f 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -3,6 +3,7 @@ * * 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 @@ -23,16 +24,25 @@ #include #include "improcfun.h" +#include "colortemp.h" #include "curves.h" #include "gauss.h" -#include "iccmatrices.h" +#include "iccstore.h" +#include "imagefloat.h" +#include "labimage.h" #include "color.h" #include "rt_math.h" #include "jaggedarray.h" +#include "rt_algo.h" +#include "settings.h" +#include "../rtgui/options.h" + +#include "utils.h" #ifdef _OPENMP #include #endif #include "../rtgui/thresholdselector.h" +#include "imagesource.h" #include "cplx_wavelet_dec.h" #include "ciecam02.h" @@ -42,14 +52,18 @@ #include "guidedfilter.h" #define TS 64 // Tile size -#define offset 25 // shift between tiles +#define offset1 25 // shift between tiles #define fTS ((TS/2+1)) // second dimension of Fourier tiles #define blkrad 1 // radius of block averaging #define offset2 25 // shift between tiles -#define epsilon 0.001f/(TS*TS) //tolerance +#define epsilonw 0.001f/(TS*TS) //tolerance #define MAXSCOPE 1.25f #define MINSCOPE 0.025f +#define mSP 5 //minimum size Spot +#define mDEN 64 //minimum size Spot Denoise +#define mSPsharp 39 //minimum size Spot Sharp due to buildblendmask +#define mSPwav 32 //minimum size Spot Wavelet #define CLIPC(a) LIM(a, -42000.f, 42000.f) // limit a and b to 130 probably enough ? #define CLIPL(x) LIM(x,0.f,40000.f) // limit L to about L=120 probably enough ? @@ -64,6 +78,7 @@ #define CLIP42_35(x) LIM(x, 0.42, 3.5) #define CLIP2_30(x) LIM(x, 0.2, 3.) #define CLIPMAX(x) LIM(x,0.f,500000.f) +#define CLIPdE(x) LIM(x,0.3f,1.f) #pragma GCC diagnostic warning "-Wall" #pragma GCC diagnostic warning "-Wextra" @@ -83,6 +98,8 @@ void calcGammaLut(double gamma, double ts, LUTf &gammaLut) std::swap(pwr, gamm); } +// printf("OK calcgamm\n"); + rtengine::Color::calcGamma(pwr, ts, 0, g_a); // call to calcGamma with selected gamma and slope const double start = gamm2 < 1. ? g_a[2] : g_a[3]; @@ -105,14 +122,12 @@ void calcGammaLut(double gamma, double ts, LUTf &gammaLut) } } } +// localFactor = calcLocalFactorrect(lox, loy, lp.xc, lp.lx, lp.yc, lp.ly, ach, lp.transgrad); float calcLocalFactor(const float lox, const float loy, const float lcx, const float dx, const float lcy, const float dy, const float ach, const float gradient) { //elipse x2/a2 + y2/b2=1 //transition elipsoidal -//x==>lox y==>loy -// a==> dx b==>dy -//printf("grad=%f", gradient); float eps = 0.0001f; float kelip = dx / dy; float belip = sqrt((rtengine::SQR((lox - lcx) / kelip) + rtengine::SQR(loy - lcy))); //determine position ellipse ==> a and b @@ -173,9 +188,6 @@ extern MyMutex *fftwMutex; using namespace procparams; -extern const Settings* settings; - - struct local_params { float yc, xc; float ycbuf, xcbuf; @@ -184,6 +196,8 @@ struct local_params { float dxx, dyy; float iterat; float balance; + float balanceh; + int colorde; int cir; float thr; float stru; @@ -191,6 +205,7 @@ struct local_params { float clarityml; float contresid; float blurcbdl; + bool deltaem; float struco; float strengrid; float struexc; @@ -199,10 +214,42 @@ struct local_params { float chromacol; float gammacol; float slomacol; + float blendmalc; + float radmalc; + float chromalc; float radmaexp; float chromaexp; float gammaexp; float slomaexp; + float strmaexp; + float angmaexp; + float strexp; + float angexp; + float strSH; + float angSH; + float strcol; + float strcolab; + float strcolh; + float angcol; + float strvib; + float strvibab; + float strvibh; + float angvib; + float angwav; + float strwav; + + float strengthw; + float radiusw; + float detailw; + float gradw; + float tloww; + float thigw; + float edgw; + float basew; + + + float anglog; + float strlog; float softradiusexp; float softradiuscol; float softradiuscb; @@ -214,6 +261,11 @@ struct local_params { float chromaSH; float gammaSH; float slomaSH; + float radmavib; + float blendmavib; + float chromavib; + float gammavib; + float slomavib; float radmacb; float blendmacb; float chromacbm; @@ -224,12 +276,22 @@ struct local_params { float chromatm; float gammatm; float slomatm; + + float radmabl; + float blendmabl; + float chromabl; + float gammabl; + float slomabl; + float struexp; float blurexp; float blurcol; + float blurcolmask; + float contcolmask; float blurSH; float ligh; float lowA, lowB, highA, highB; + float lowBmerg, highBmerg, lowAmerg, highAmerg; int shamo, shdamp, shiter, senssha, sensv; float neig; float strng; @@ -239,10 +301,16 @@ struct local_params { double shblurr; double rad; double stren; - int trans; + int it; + int guidb; + float strbl; + float epsb; + float trans; + float feath; float transweak; float transgrad; int dehaze; + int depth; bool inv; bool invex; bool invsh; @@ -260,23 +328,36 @@ struct local_params { int qualcurvemet; int gridmet; int showmaskcolmet; + int showmaskcolmetinv; int showmaskexpmet; + int showmaskexpmetinv; int showmaskSHmet; + int showmaskSHmetinv; + int showmaskvibmet; + int showmasklcmet; + int showmasksharmet; int showmaskcbmet; int showmaskretimet; int showmasksoftmet; int showmasktmmet; + int showmaskblmet; + bool fftbl; float laplacexp; float balanexp; float linear; int expmet; int softmet; int blurmet; + int blmet; + int chromet; + int shmeth; + int medmet; int locmet; float noiself; float noiself0; float noiself2; float noiseldetail; + int detailthr; int noiselequal; float noisechrodetail; float bilat; @@ -284,6 +365,8 @@ struct local_params { float noisecf; float noisecc; float mulloc[6]; + int mullocsh[5]; + int detailsh; float threshol; float chromacb; float strengt; @@ -304,6 +387,8 @@ struct local_params { bool expvib; bool exposena; bool hsena; + bool vibena; + bool logena; bool cut_past; float past; float satur; @@ -315,16 +400,29 @@ struct local_params { double expcomp; float expchroma; int excmet; + int mergemet; + int mergecolMethod; + float opacol; int war; float adjch; int shapmet; + int edgwmet; + int neiwmet; bool enaColorMask; + bool fftColorMask; + bool enaColorMaskinv; bool enaExpMask; + bool enaExpMaskinv; bool enaSHMask; + bool enaSHMaskinv; + bool enavibMask; + bool enalcMask; + bool enasharMask; bool enacbMask; bool enaretiMask; bool enaretiMasktmap; bool enatmMask; + bool enablMask; int highlihs; int shadowhs; int radiushs; @@ -336,6 +434,20 @@ struct local_params { float gammareti; float slomareti; int scalereti; + float sourcegray; + float targetgray; + float blackev; + float whiteev; + float detail; + int sensilog; + bool Autogray; + bool autocompute; + float baselog; + bool wavgradl; + bool edgwena; + bool lip3; + int daubLen; + }; static void SobelCannyLuma(float **sobelL, float **luma, int bfw, int bfh, float radius, bool multiThread = false) @@ -418,7 +530,7 @@ static void SobelCannyLuma(float **sobelL, float **luma, int bfw, int bfh, float -static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locallab, struct local_params& lp, int llColorMask, int llExpMask, int llSHMask, int llcbMask, int llretiMask, int llsoftMask, int lltmMask) +static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locallab, struct local_params& lp, int llColorMask, int llColorMaskinv, int llExpMask, int llExpMaskinv, int llSHMask, int llSHMaskinv, int llvibMask, int lllcMask, int llsharMask, int llcbMask, int llretiMask, int llsoftMask, int lltmMask, int llblMask, const LocwavCurve & locwavCurveden, bool & locwavdenutili) { int w = oW; int h = oH; @@ -432,7 +544,6 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall float strlight = ((float)locallab.spots.at(sp).streng); float strucc = locallab.spots.at(sp).struc; float laplac = ((float)locallab.spots.at(sp).laplace); - float thre = locallab.spots.at(sp).thresh; if (thre > 8.f || thre < 0.f) {//to avoid artifacts if user does not clear cache with new settings. Can be suppressed after @@ -450,6 +561,8 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall double local_dxy = locallab.spots.at(sp).iter / 8000.0; //for proxi = 2==> # 1 pixel float iterati = (float) locallab.spots.at(sp).iter; float balanc = (float) locallab.spots.at(sp).balan; + float balanch = (float) locallab.spots.at(sp).balanh; + int colorde = (int) locallab.spots.at(sp).colorde; if (iterati > 4.f || iterati < 0.2f) {//to avoid artifacts if user does not clear cache with new settings Can be suppressed after iterati = 2.f; @@ -495,27 +608,77 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.balanexp = locallab.spots.at(sp).balanexp; lp.linear = locallab.spots.at(sp).linear; + lp.fftColorMask = locallab.spots.at(sp).fftColorMask; + lp.showmaskcolmet = llColorMask; + lp.showmaskcolmetinv = llColorMaskinv; lp.showmaskexpmet = llExpMask; + lp.showmaskexpmetinv = llExpMaskinv; lp.showmaskSHmet = llSHMask; + lp.showmaskSHmetinv = llSHMaskinv; + lp.showmaskvibmet = llvibMask; + lp.showmasklcmet = lllcMask; + lp.showmasksharmet = llsharMask; lp.showmaskcbmet = llcbMask; lp.showmaskretimet = llretiMask; lp.showmasksoftmet = llsoftMask; lp.showmasktmmet = lltmMask; - // printf("lpshmasktm=%i\n",lp.showmasktmmet); - lp.enaExpMask = locallab.spots.at(sp).enaExpMask && llExpMask == 0 && llColorMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0;// Exposure mask is deactivated if Color & Light mask is visible - lp.enaSHMask = locallab.spots.at(sp).enaSHMask && llSHMask == 0 && llColorMask == 0 && llExpMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0; - lp.enacbMask = locallab.spots.at(sp).enacbMask && llcbMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llretiMask == 0 && lltmMask == 0; - lp.enaretiMask = locallab.spots.at(sp).enaretiMask && llretiMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && lltmMask == 0; - lp.enatmMask = locallab.spots.at(sp).enatmMask && lltmMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0; - // if(lp.enaretiMask) printf("lp.enaretiMasktrue\n"); else printf("lp.enaretiMaskfalse\n"); + lp.showmaskblmet = llblMask; + lp.enaColorMask = locallab.spots.at(sp).enaColorMask && llsoftMask == 0 && llColorMask == 0 && lllcMask == 0 && llsharMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0;// Exposure mask is deactivated if Color & Light mask is visible + lp.enaColorMaskinv = locallab.spots.at(sp).enaColorMask && llColorMaskinv == 0 && llsoftMask == 0 && lllcMask == 0 && llsharMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0;// Exposure mask is deactivated if Color & Light mask is visible + lp.enaExpMask = locallab.spots.at(sp).enaExpMask && llExpMask == 0 && llColorMask == 0 && llsoftMask == 0 && lllcMask == 0 && llsharMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0;// Exposure mask is deactivated if Color & Light mask is visible + lp.enaExpMaskinv = locallab.spots.at(sp).enaExpMask && llExpMaskinv == 0 && llColorMask == 0 && llsoftMask == 0 && lllcMask == 0 && llsharMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0;// Exposure mask is deactivated if Color & Light mask is visible + lp.enaSHMask = locallab.spots.at(sp).enaSHMask && llSHMask == 0 && llColorMask == 0 && llsoftMask == 0 && lllcMask == 0 && llsharMask == 0 && llExpMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0; + lp.enaSHMaskinv = locallab.spots.at(sp).enaSHMask && llSHMaskinv == 0 && lllcMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0; + lp.enacbMask = locallab.spots.at(sp).enacbMask && llcbMask == 0 && lllcMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0; + lp.enaretiMask = locallab.spots.at(sp).enaretiMask && lllcMask == 0 && llsharMask == 0 && llsoftMask == 0 && llretiMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0; + lp.enatmMask = locallab.spots.at(sp).enatmMask && lltmMask == 0 && lllcMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && llblMask == 0 && llvibMask == 0; + lp.enablMask = locallab.spots.at(sp).enablMask && llblMask == 0 && lllcMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llvibMask == 0; + lp.enavibMask = locallab.spots.at(sp).enavibMask && llvibMask == 0 && lllcMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llSHMask == 0; + lp.enalcMask = locallab.spots.at(sp).enalcMask && lllcMask == 0 && llcbMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0; + lp.enasharMask = lllcMask == 0 && llcbMask == 0 && llsharMask == 0 && llsoftMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0; + // printf("llColorMask=%i lllcMask=%i llExpMask=%i llSHMask=%i llcbMask=%i llretiMask=%i lltmMask=%i llblMask=%i llvibMask=%i\n", llColorMask, lllcMask, llExpMask, llSHMask, llcbMask, llretiMask, lltmMask, llblMask, llvibMask); if (locallab.spots.at(sp).softMethod == "soft") { lp.softmet = 0; } else if (locallab.spots.at(sp).softMethod == "reti") { lp.softmet = 1; } + if (locallab.spots.at(sp).blMethod == "blur") { + lp.blmet = 0; + } else if (locallab.spots.at(sp).blMethod == "med") { + lp.blmet = 1; + } else if (locallab.spots.at(sp).blMethod == "guid") { + lp.blmet = 2; + } + + if (locallab.spots.at(sp).chroMethod == "lum") { + lp.chromet = 0; + } else if (locallab.spots.at(sp).chroMethod == "chr") { + lp.chromet = 1; + } else if (locallab.spots.at(sp).chroMethod == "all") { + lp.chromet = 2; + } + + if (locallab.spots.at(sp).shMethod == "std") { + lp.shmeth = 0; + } else if (locallab.spots.at(sp).shMethod == "tone") { + lp.shmeth = 1; + } + + + if (locallab.spots.at(sp).medMethod == "none") { + lp.medmet = -1; + } else if (locallab.spots.at(sp).medMethod == "33") { + lp.medmet = 0; + } else if (locallab.spots.at(sp).medMethod == "55") { + lp.medmet = 1; + } else if (locallab.spots.at(sp).medMethod == "77") { + lp.medmet = 2; + } else if (locallab.spots.at(sp).medMethod == "99") { + lp.medmet = 3; + } if (locallab.spots.at(sp).blurMethod == "norm") { lp.blurmet = 0; @@ -529,20 +692,144 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.excmet = 1; } + if (locallab.spots.at(sp).merMethod == "mone") { + lp.mergemet = 0; + } else if (locallab.spots.at(sp).merMethod == "mtwo") { + lp.mergemet = 1; + } else if (locallab.spots.at(sp).merMethod == "mthr") { + lp.mergemet = 2; + } else if (locallab.spots.at(sp).merMethod == "mfou") { + lp.mergemet = 3; + } else if (locallab.spots.at(sp).merMethod == "mfiv") { + lp.mergemet = 4; + } + + + if (locallab.spots.at(sp).mergecolMethod == "one") { + lp.mergecolMethod = 0; + } else if (locallab.spots.at(sp).mergecolMethod == "two") { + lp.mergecolMethod = 1; + } else if (locallab.spots.at(sp).mergecolMethod == "thr") { + lp.mergecolMethod = 2; + } else if (locallab.spots.at(sp).mergecolMethod == "fou") { + lp.mergecolMethod = 3; + } else if (locallab.spots.at(sp).mergecolMethod == "fiv") { + lp.mergecolMethod = 4; + } else if (locallab.spots.at(sp).mergecolMethod == "six") { + lp.mergecolMethod = 5; + } else if (locallab.spots.at(sp).mergecolMethod == "sev") { + lp.mergecolMethod = 6; + } else if (locallab.spots.at(sp).mergecolMethod == "sev0") { + lp.mergecolMethod = 7; + } else if (locallab.spots.at(sp).mergecolMethod == "sev1") { + lp.mergecolMethod = 8; + } else if (locallab.spots.at(sp).mergecolMethod == "sev2") { + lp.mergecolMethod = 9; + } else if (locallab.spots.at(sp).mergecolMethod == "hei") { + lp.mergecolMethod = 10; + } else if (locallab.spots.at(sp).mergecolMethod == "nin") { + lp.mergecolMethod = 11; + } else if (locallab.spots.at(sp).mergecolMethod == "ten") { + lp.mergecolMethod = 12; + } else if (locallab.spots.at(sp).mergecolMethod == "ele") { + lp.mergecolMethod = 13; + } else if (locallab.spots.at(sp).mergecolMethod == "twe") { + lp.mergecolMethod = 14; + } else if (locallab.spots.at(sp).mergecolMethod == "thi") { + lp.mergecolMethod = 15; + } else if (locallab.spots.at(sp).mergecolMethod == "for") { + lp.mergecolMethod = 16; + } else if (locallab.spots.at(sp).mergecolMethod == "hue") { + lp.mergecolMethod = 17; + } else if (locallab.spots.at(sp).mergecolMethod == "sat") { + lp.mergecolMethod = 18; + } else if (locallab.spots.at(sp).mergecolMethod == "col") { + lp.mergecolMethod = 19; + } else if (locallab.spots.at(sp).mergecolMethod == "lum") { + lp.mergecolMethod = 20; + } + + if (locallab.spots.at(sp).localedgMethod == "fir") { + lp.edgwmet = 0; + } else if (locallab.spots.at(sp).localedgMethod == "sec") { + lp.edgwmet = 1; + } else if (locallab.spots.at(sp).localedgMethod == "thr") { + lp.edgwmet = 2; + } + + if (locallab.spots.at(sp).localneiMethod == "none") { + lp.neiwmet = -1; + lp.lip3 = false; + } else if (locallab.spots.at(sp).localneiMethod == "low") { + lp.neiwmet = 0; + lp.lip3 = true; + } else if (locallab.spots.at(sp).localneiMethod == "high") { + lp.lip3 = true; + lp.neiwmet = 1; + } + + + if (locallab.spots.at(sp).wavMethod == "D2") { + lp.daubLen = 4; + } else if (locallab.spots.at(sp).wavMethod == "D4") { + lp.daubLen = 6; + } else if (locallab.spots.at(sp).wavMethod == "D6") { + lp.daubLen = 8; + } else if (locallab.spots.at(sp).wavMethod == "D10") { + lp.daubLen = 12; + } else if (locallab.spots.at(sp).wavMethod == "D14") { + lp.daubLen = 16; +// } else if(locallab.spots.at(sp).wavMethod == "D20"){ +// lp.daubLen = 22; + } + + + lp.edgwena = locallab.spots.at(sp).wavedg; + + lp.opacol = 0.01f * locallab.spots.at(sp).opacol; + if (locallab.spots.at(sp).shape == "ELI") { lp.shapmet = 0; } else if (locallab.spots.at(sp).shape == "RECT") { lp.shapmet = 1; } - float local_noiself = (float)locallab.spots.at(sp).noiselumf; - float local_noiself0 = (float)locallab.spots.at(sp).noiselumf0; - float local_noiself2 = (float)locallab.spots.at(sp).noiselumf2; - float local_noiselc = (float)locallab.spots.at(sp).noiselumc; + lp.denoiena = locallab.spots.at(sp).expdenoi; + + bool wavcurveden = false; + float local_noiself = 0.f; + float local_noiself0 = 0.f; + float local_noiself2 = 0.f; + float local_noiselc = 0.f; + + if (locwavCurveden && locwavdenutili) { + if (lp.denoiena) { + for (int i = 0; i < 500; i++) { + if (locwavCurveden[i] != 0.) { + wavcurveden = true; + } + } + } + } + + if (wavcurveden) { + if (lp.denoiena) { + local_noiself0 = 150.f * locwavCurveden[0]; + local_noiself = 150.f * locwavCurveden[166]; + local_noiself2 = 150.f * locwavCurveden[323]; + local_noiselc = 100.f * locwavCurveden[500]; + } + } + +// float local_noiself = (float)locallab.spots.at(sp).noiselumf; +// float local_noiself0 = (float)locallab.spots.at(sp).noiselumf0; +// float local_noiself2 = (float)locallab.spots.at(sp).noiselumf2; +// float local_noiselc = (float)locallab.spots.at(sp).noiselumc; float local_noiseldetail = (float)locallab.spots.at(sp).noiselumdetail; int local_noiselequal = locallab.spots.at(sp).noiselequal; float local_noisechrodetail = (float)locallab.spots.at(sp).noisechrodetail; int local_sensiden = locallab.spots.at(sp).sensiden; + float local_detailthr = (float)locallab.spots.at(sp).detailthr; float local_noisecf = ((float)locallab.spots.at(sp).noisechrof) / 10.f; float local_noisecc = ((float)locallab.spots.at(sp).noisechroc) / 10.f; @@ -552,6 +839,12 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall multi[y] = ((float) locallab.spots.at(sp).mult[y]); } + float multish[5]; + + for (int y = 0; y < 5; y++) { + multish[y] = ((float) locallab.spots.at(sp).multsh[y]); + } + float thresho = ((float)locallab.spots.at(sp).threshold); float chromcbdl = (float)locallab.spots.at(sp).chromacbdl; @@ -566,6 +859,7 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall int local_warm = locallab.spots.at(sp).warm; int local_sensih = locallab.spots.at(sp).sensih; int local_dehaze = locallab.spots.at(sp).dehaz; + int local_depth = locallab.spots.at(sp).depth; int local_sensicb = locallab.spots.at(sp).sensicb; float local_clarityml = (float) locallab.spots.at(sp).clarityml; float local_contresid = (float) locallab.spots.at(sp).contresid; @@ -577,7 +871,14 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall float labgridBHighloc = locallab.spots.at(sp).labgridBHigh; float labgridAHighloc = locallab.spots.at(sp).labgridAHigh; float strengthgrid = (float) locallab.spots.at(sp).strengthgrid; + float labgridBLowlocmerg = locallab.spots.at(sp).labgridBLowmerg; + float labgridBHighlocmerg = locallab.spots.at(sp).labgridBHighmerg; + float labgridALowlocmerg = locallab.spots.at(sp).labgridALowmerg; + float labgridAHighlocmerg = locallab.spots.at(sp).labgridAHighmerg; + float blendmasklc = ((float) locallab.spots.at(sp).blendmasklc) / 100.f ; + float radmasklc = ((float) locallab.spots.at(sp).radmasklc); + float chromasklc = ((float) locallab.spots.at(sp).chromasklc); float structcolor = (float) locallab.spots.at(sp).structcol; float blendmaskcolor = ((float) locallab.spots.at(sp).blendmaskcol) / 100.f ; float radmaskcolor = ((float) locallab.spots.at(sp).radmaskcol); @@ -589,6 +890,24 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall float chromaskexpo = ((float) locallab.spots.at(sp).chromaskexp); float gammaskexpo = ((float) locallab.spots.at(sp).gammaskexp); float slomaskexpo = ((float) locallab.spots.at(sp).slomaskexp); + float strmaskexpo = ((float) locallab.spots.at(sp).strmaskexp); + float angmaskexpo = ((float) locallab.spots.at(sp).angmaskexp); + float strexpo = ((float) locallab.spots.at(sp).strexp); + float angexpo = ((float) locallab.spots.at(sp).angexp); + float strSH = ((float) locallab.spots.at(sp).strSH); + float angSH = ((float) locallab.spots.at(sp).angSH); + float strcol = ((float) locallab.spots.at(sp).strcol); + float strcolab = ((float) locallab.spots.at(sp).strcolab); + float strcolh = ((float) locallab.spots.at(sp).strcolh); + float angcol = ((float) locallab.spots.at(sp).angcol); + float strvib = ((float) locallab.spots.at(sp).strvib); + float strvibab = ((float) locallab.spots.at(sp).strvibab); + float strvibh = ((float) locallab.spots.at(sp).strvibh); + float angvib = ((float) locallab.spots.at(sp).angvib); + float strwav = ((float) locallab.spots.at(sp).strwav); + float angwav = ((float) locallab.spots.at(sp).angwav); + float strlog = ((float) locallab.spots.at(sp).strlog); + float anglog = ((float) locallab.spots.at(sp).anglog); float softradiusexpo = ((float) locallab.spots.at(sp).softradiusexp); float softradiuscolor = ((float) locallab.spots.at(sp).softradiuscol); float softradiusreti = ((float) locallab.spots.at(sp).softradiusret); @@ -599,14 +918,25 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall float chromaskSH = ((float) locallab.spots.at(sp).chromaskSH); float gammaskSH = ((float) locallab.spots.at(sp).gammaskSH); float slomaskSH = ((float) locallab.spots.at(sp).slomaskSH); + float blendmaskvib = ((float) locallab.spots.at(sp).blendmaskvib) / 100.f ; + float radmaskvib = ((float) locallab.spots.at(sp).radmaskvib); + float chromaskvib = ((float) locallab.spots.at(sp).chromaskvib); + float gammaskvib = ((float) locallab.spots.at(sp).gammaskvib); + float slomaskvib = ((float) locallab.spots.at(sp).slomaskvib); float structexpo = (float) locallab.spots.at(sp).structexp; float blurexpo = (float) locallab.spots.at(sp).blurexpde; float blurcolor = (float) locallab.spots.at(sp).blurcolde; + float blurcolmask = (float) locallab.spots.at(sp).blurcol; + float contcolmask = (float) locallab.spots.at(sp).contcol; float blurSH = (float) locallab.spots.at(sp).blurSHde; - int local_transit = locallab.spots.at(sp).transit; + float local_transit = locallab.spots.at(sp).transit; + float local_feather = locallab.spots.at(sp).feather; float local_transitweak = (float)locallab.spots.at(sp).transitweak; float local_transitgrad = (float)locallab.spots.at(sp).transitgrad; float radius = (float) locallab.spots.at(sp).radius; + int itera = locallab.spots.at(sp).itera; + int guidbl = locallab.spots.at(sp).guidbl; + float epsbl = (float) locallab.spots.at(sp).epsbl; double sharradius = ((double) locallab.spots.at(sp).sharradius); sharradius = CLIP42_35(sharradius); float lcamount = ((float) locallab.spots.at(sp).lcamount); @@ -654,7 +984,27 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall float chromasktm = ((float) locallab.spots.at(sp).chromasktm); float gammasktm = ((float) locallab.spots.at(sp).gammasktm); float slomasktm = ((float) locallab.spots.at(sp).slomasktm); + bool wavgradl = locallab.spots.at(sp).wavgradl; + float blendmaskbl = ((float) locallab.spots.at(sp).blendmaskbl) / 100.f ; + float radmaskbl = ((float) locallab.spots.at(sp).radmaskbl); + float chromaskbl = ((float) locallab.spots.at(sp).chromaskbl); + float gammaskbl = ((float) locallab.spots.at(sp).gammaskbl); + float slomaskbl = ((float) locallab.spots.at(sp).slomaskbl); + bool fftbl = locallab.spots.at(sp).fftwbl; + + + lp.sourcegray = (float) locallab.spots.at(sp).sourceGray; + lp.targetgray = (float) locallab.spots.at(sp).targetGray; + lp.blackev = (float) locallab.spots.at(sp).blackEv; + lp.whiteev = (float) locallab.spots.at(sp).whiteEv; + lp.detail = locallab.spots.at(sp).detail; + lp.sensilog = locallab.spots.at(sp).sensilog; + lp.Autogray = locallab.spots.at(sp).Autogray; + lp.autocompute = locallab.spots.at(sp).autocompute; + lp.baselog = (float) locallab.spots.at(sp).baselog; + + lp.deltaem = locallab.spots.at(sp).deltae; lp.scalereti = scaleret; lp.cir = circr; lp.actsp = acti; @@ -669,6 +1019,9 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.chro = local_chroma; lp.struco = structcolor; lp.strengrid = strengthgrid; + lp.blendmalc = blendmasklc; + lp.radmalc = radmasklc; + lp.chromalc = chromasklc; lp.blendmacol = blendmaskcolor; lp.radmacol = radmaskcolor; lp.chromacol = chromaskcolor; @@ -678,6 +1031,24 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.chromaexp = chromaskexpo; lp.gammaexp = gammaskexpo; lp.slomaexp = slomaskexpo; + lp.strmaexp = strmaskexpo; + lp.angmaexp = angmaskexpo; + lp.strexp = strexpo; + lp.angexp = angexpo; + lp.strSH = strSH; + lp.angSH = angSH; + lp.strcol = strcol; + lp.strcolab = strcolab; + lp.strcolh = strcolh; + lp.angcol = angcol; + lp.strvib = strvib; + lp.strvibab = strvibab; + lp.strvibh = strvibh; + lp.angvib = angvib; + lp.strwav = strwav; + lp.angwav = angwav; + lp.strlog = strlog; + lp.anglog = anglog; lp.softradiusexp = softradiusexpo; lp.softradiuscol = softradiuscolor; lp.softradiusret = softradiusreti; @@ -690,6 +1061,11 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.chromaSH = chromaskSH; lp.gammaSH = gammaskSH; lp.slomaSH = slomaskSH; + lp.blendmavib = blendmaskvib; + lp.radmavib = radmaskvib; + lp.chromavib = chromaskvib; + lp.gammavib = gammaskvib; + lp.slomavib = slomaskvib; lp.blendmacb = blendmaskcb; lp.radmacb = radmaskcb; lp.chromacbm = chromaskcb; @@ -700,17 +1076,40 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.chromatm = chromasktm; lp.gammatm = gammasktm; lp.slomatm = slomasktm; + lp.wavgradl = wavgradl; + lp.strengthw = ((float) locallab.spots.at(sp).strengthw); + lp.radiusw = ((float) locallab.spots.at(sp).radiusw); + lp.detailw = ((float) locallab.spots.at(sp).detailw); + lp.gradw = ((float) locallab.spots.at(sp).gradw); + lp.tloww = ((float) locallab.spots.at(sp).tloww); + lp.thigw = ((float) locallab.spots.at(sp).thigw); + lp.edgw = ((float) locallab.spots.at(sp).edgw); + lp.basew = ((float) locallab.spots.at(sp).basew); + + lp.blendmabl = blendmaskbl; + lp.radmabl = radmaskbl; + lp.chromabl = chromaskbl; + lp.gammabl = gammaskbl; + lp.slomabl = slomaskbl; + lp.fftbl = fftbl; + lp.it = itera; + lp.guidb = guidbl; + lp.strbl = 0.01f * (float) locallab.spots.at(sp).strbl; + + lp.epsb = epsbl; lp.struexp = structexpo; lp.blurexp = blurexpo; lp.blurcol = blurcolor; + lp.blurcolmask = blurcolmask; + lp.contcolmask = 0.01f * contcolmask; lp.blurSH = blurSH; lp.sens = local_sensi; lp.sensh = local_sensih; lp.dehaze = local_dehaze; + lp.depth = local_depth; lp.senscb = local_sensicb; lp.clarityml = local_clarityml; - //printf("lpclari=%f \n", lp.clarityml); lp.contresid = local_contresid; lp.blurcbdl = local_blurcbdl; lp.cont = local_contrast; @@ -719,6 +1118,10 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.lowB = labgridBLowloc; lp.highB = labgridBHighloc; lp.highA = labgridAHighloc; + lp.lowBmerg = labgridBLowlocmerg; + lp.highBmerg = labgridBHighlocmerg; + lp.lowAmerg = labgridALowlocmerg; + lp.highAmerg = labgridAHighlocmerg; lp.senssf = local_sensisf; lp.strng = strlight; @@ -730,6 +1133,7 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall } lp.trans = local_transit; + lp.feath = local_feather; lp.transweak = local_transitweak; lp.transgrad = local_transitgrad; lp.rad = radius; @@ -756,6 +1160,8 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.shiter = local_shariter; lp.iterat = iterati; lp.balance = balanc; + lp.balanceh = balanch; + lp.colorde = colorde; lp.dxx = w * local_dxy; lp.dyy = h * local_dxy; lp.thr = thre; @@ -764,6 +1170,7 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.noiself0 = local_noiself0; lp.noiself2 = local_noiself2; lp.noiseldetail = local_noiseldetail; + lp.detailthr = local_detailthr; lp.noiselequal = local_noiselequal; lp.noisechrodetail = local_noisechrodetail; lp.noiselc = local_noiselc; @@ -784,23 +1191,31 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.mulloc[y] = CLIP04(multi[y]);//to prevent crash with old pp3 integer } + for (int y = 0; y < 5; y++) { + lp.mullocsh[y] = multish[y]; + } + + lp.logena = locallab.spots.at(sp).explog; + + lp.detailsh = locallab.spots.at(sp).detailSH; lp.threshol = thresho; lp.chromacb = chromcbdl; - lp.colorena = locallab.spots.at(sp).expcolor && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0; // Color & Light tool is deactivated if Exposure mask is visible or SHMask - lp.blurena = locallab.spots.at(sp).expblur; - lp.tonemapena = locallab.spots.at(sp).exptonemap; - lp.retiena = locallab.spots.at(sp).expreti && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && llColorMask == 0; - lp.sharpena = locallab.spots.at(sp).expsharp; - lp.lcena = locallab.spots.at(sp).expcontrast; - lp.sfena = locallab.spots.at(sp).expsoft; - lp.cbdlena = locallab.spots.at(sp).expcbdl && llExpMask == 0 && llSHMask == 0 && llretiMask == 0 && llColorMask == 0 ; - lp.denoiena = locallab.spots.at(sp).expdenoi; lp.expvib = locallab.spots.at(sp).expvibrance; + lp.colorena = locallab.spots.at(sp).expcolor && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && lltmMask == 0 && llvibMask == 0; // Color & Light tool is deactivated if Exposure mask is visible or SHMask + lp.blurena = locallab.spots.at(sp).expblur && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && llColorMask == 0 && lltmMask == 0 && llvibMask == 0; + lp.tonemapena = locallab.spots.at(sp).exptonemap && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && llColorMask == 0 && llvibMask == 0; + lp.retiena = locallab.spots.at(sp).expreti && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llColorMask == 0 && lltmMask == 0 && llvibMask == 0 && llSHMask == 0; + lp.lcena = locallab.spots.at(sp).expcontrast && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && llsharMask == 0 && llColorMask == 0 && lltmMask == 0 && llvibMask == 0 && llSHMask == 0; + lp.cbdlena = locallab.spots.at(sp).expcbdl && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llretiMask == 0 && lllcMask == 0 && llsharMask == 0 && lllcMask == 0 && llColorMask == 0 && lltmMask == 0 && llvibMask == 0; + lp.exposena = locallab.spots.at(sp).expexpose && llColorMask == 0 && llsoftMask == 0 && llSHMask == 0 && lllcMask == 0 && llsharMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llvibMask == 0; // Exposure tool is deactivated if Color & Light mask SHmask is visible + lp.hsena = locallab.spots.at(sp).expshadhigh && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && lltmMask == 0 && llvibMask == 0;// Shadow Highlight tool is deactivated if Color & Light mask or SHmask is visible + lp.vibena = locallab.spots.at(sp).expvibrance && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && llcbMask == 0 && lltmMask == 0 && llSHMask == 0;// vibrance tool is deactivated if Color & Light mask or SHmask is visible + lp.sharpena = locallab.spots.at(sp).expsharp && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llretiMask == 0 && llcbMask == 0 && lltmMask == 0 && llSHMask == 0 && llvibMask == 0; + lp.sfena = locallab.spots.at(sp).expsoft && llColorMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llretiMask == 0 && llcbMask == 0 && lltmMask == 0 && llSHMask == 0 && llvibMask == 0; lp.sensv = local_sensiv; lp.past = chromaPastel; lp.satur = chromaSatur; - lp.exposena = locallab.spots.at(sp).expexpose && llColorMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0; // Exposure tool is deactivated if Color & Light mask SHmask is visible lp.cut_past = cupas; lp.blac = locallab.spots.at(sp).black; lp.shcomp = locallab.spots.at(sp).shcompr; @@ -812,7 +1227,6 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.expchroma = locallab.spots.at(sp).expchroma / 100.; lp.sensex = local_sensiex; lp.war = local_warm; - lp.hsena = locallab.spots.at(sp).expshadhigh && llColorMask == 0 && llExpMask == 0 && llcbMask == 0 && llretiMask == 0 && llcbMask == 0;// Shadow Highlight tool is deactivated if Color & Light mask or SHmask is visible lp.highlihs = highhs; lp.shadowhs = shadhs; lp.radiushs = radhs; @@ -821,13 +1235,14 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.senshs = local_sensihs; lp.ftwlc = fftwlc; lp.ftwreti = fftwreti; + } static void calcTransitionrect(const float lox, const float loy, const float ach, const local_params& lp, int &zone, float &localFactor) { zone = 0; - if (lox >= lp.xc && lox < (lp.xc + lp.lx) && loy >= lp.yc && loy < lp.yc + lp.ly) { + if (lox >= lp.xc && lox < lp.xc + lp.lx && loy >= lp.yc && loy < lp.yc + lp.ly) { if (lox < (lp.xc + lp.lx * ach) && loy < (lp.yc + lp.ly * ach)) { zone = 2; } else { @@ -924,6 +1339,592 @@ static void calcTransition(const float lox, const float loy, const float ach, co } +// Copyright 2018 Alberto Griggio +//J.Desmis 12 2019 - I will try to port a raw process in local adjustements +// I choose this one because, it is "new" +// Perhaps - probably no result, but perhaps ?? + +float find_gray(float source_gray, float target_gray) +{ + // find a base such that log2lin(base, source_gray) = target_gray + // log2lin is (base^source_gray - 1) / (base - 1), so we solve + // + // (base^source_gray - 1) / (base - 1) = target_gray, that is + // + // base^source_gray - 1 - base * target_gray + target_gray = 0 + // + // use a bisection method (maybe later change to Netwon) + + if (source_gray <= 0.f) { + return 0.f; + } + + const auto f = + [ = ](float x) -> float { + return std::pow(x, source_gray) - 1 - target_gray * x + target_gray; + }; + + // first find the interval we are interested in + + float lo = 1.f; + + while (f(lo) <= 0.f) { + lo *= 2.f; + } + + float hi = lo * 2.f; + + while (f(hi) >= 0.f) { + hi *= 2.f; + } + + if (std::isinf(hi)) { + return 0.f; + } + + // now search for a zero + for (int iter = 0; iter < 100; ++iter) { + float mid = lo + (hi - lo) / 2.f; + float v = f(mid); + + if (std::abs(v) < 1e-4f || (hi - lo) / lo <= 1e-4f) { + return mid; + } + + if (v > 0.f) { + lo = mid; + } else { + hi = mid; + } + } + + return 0.f; // not found +} + + +// basic log encoding taken from ACESutil.Lin_to_Log2, from +// https://github.com/ampas/aces-dev +// (as seen on pixls.us) +void ImProcFunctions::log_encode(Imagefloat *rgb, struct local_params & lp, float scale, bool multiThread, int bfw, int bfh) +{ + /* J.Desmis 12 2019 + small adaptations to local adjustements + replace log2 by log(lp.baselog) allows diferentiation between low and high lights + */ + BENCHFUN + const float gray = lp.sourcegray / 100.f; + const float shadows_range = lp.blackev; + const float dynamic_range = lp.whiteev - lp.blackev; + const float noise = pow_F(2.f, -16.f); + const float log2 = xlogf(lp.baselog); + const float b = lp.targetgray > 1 && lp.targetgray < 100 && dynamic_range > 0 ? find_gray(std::abs(lp.blackev) / dynamic_range, lp.targetgray / 100.f) : 0.f; + const float linbase = max(b, 0.f); + TMatrix ws = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile); + + const auto apply = + [ = ](float x, bool scale = true) -> float { + if (scale) + { + x /= 65535.f; + } + + x = max(x, noise); + x = max(x / gray, noise); + x = max((xlogf(x) / log2 - shadows_range) / dynamic_range, noise); + assert(x == x); + + if (linbase > 0.f) + { + x = xlog2lin(x, linbase); + } + + if (scale) + { + return x * 65535.f; + } else + { + return x; + } + }; + printf("sc=%f\n", scale); + const auto norm = + [&](float r, float g, float b) -> float { + return Color::rgbLuminance(r, g, b, ws); + + // other possible alternatives (so far, luminance seems to work + // fine though). See also + // https://discuss.pixls.us/t/finding-a-norm-to-preserve-ratios-across-non-linear-operations + // + // MAX + //return max(r, g, b); + // + // Euclidean + //return std::sqrt(SQR(r) + SQR(g) + SQR(b)); + + // weighted yellow power norm from https://youtu.be/Z0DS7cnAYPk + // float rr = 1.22f * r / 65535.f; + // float gg = 1.20f * g / 65535.f; + // float bb = 0.58f * b / 65535.f; + // float rr4 = SQR(rr) * SQR(rr); + // float gg4 = SQR(gg) * SQR(gg); + // float bb4 = SQR(bb) * SQR(bb); + // float den = (rr4 + gg4 + bb4); + // if (den > 0.f) { + // return 0.8374319f * ((rr4 * rr + gg4 * gg + bb4 * bb) / den) * 65535.f; + // } else { + // return 0.f; + // } + }; + +// const int detail2 = float(max(lp.detail, 0)) / scale + 0.5f; + const float detail = lp.detail; + const int W = rgb->getWidth(), H = rgb->getHeight(); + + if (detail == 0.f) {//no local contrast +#ifdef _OPENMP + # pragma omp parallel for if (multiThread) +#endif + + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + float r = rgb->r(y, x); + float g = rgb->g(y, x); + float b = rgb->b(y, x); + float m = norm(r, g, b); + + if (m > noise) { + float mm = apply(m); + float f = mm / m; + r *= f; + b *= f; + g *= f; + } + + assert(r == r); + assert(g == g); + assert(b == b); + + rgb->r(y, x) = r; + rgb->g(y, x) = g; + rgb->b(y, x) = b; + } + } + } else {//local contrast + + array2D Y(W, H); + { + constexpr float base_posterization = 20.f; + array2D Y2(W, H); + +#ifdef _OPENMP + # pragma omp parallel for if (multiThread) +#endif + + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + Y2[y][x] = norm(rgb->r(y, x), rgb->g(y, x), rgb->b(y, x)) / 65535.f; + float l = xlogf(std::max(Y2[y][x], 1e-9f)); + float ll = round(l * base_posterization) / base_posterization; + Y[y][x] = xexpf(ll); + assert(std::isfinite(Y[y][x])); + } + } + + const float radius = max(max(bfw, W), max(bfh, H)) / 30.f; + const float epsilon = 0.005f; + rtengine::guidedFilter(Y2, Y, Y, radius, epsilon, multiThread); + } + const float blend = detail; + +#ifdef _OPENMP + # pragma omp parallel for if (multiThread) +#endif + + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + float &r = rgb->r(y, x); + float &g = rgb->g(y, x); + float &b = rgb->b(y, x); + float t = Y[y][x]; + float t2; + + if (t > noise && (t2 = norm(r, g, b)) > noise) { + float c = apply(t, false); + float f = c / t; + // float t2 = norm(r, g, b); + float f2 = apply(t2) / t2; + f = intp(blend, f, f2); + assert(std::isfinite(f)); + r *= f; + g *= f; + b *= f; + assert(std::isfinite(r)); + assert(std::isfinite(g)); + assert(std::isfinite(b)); + } + } + } + } + +} + + + +void ImProcFunctions::getAutoLogloc(int sp, ImageSource *imgsrc, float *sourceg, float *blackev, float *whiteev, bool *Autogr, int fw, int fh, float xsta, float xend, float ysta, float yend, int SCALE) +{ + BENCHFUN +//adpatation to local adjustements Jacques Desmis 12 2019 + PreviewProps pp(0, 0, fw, fh, SCALE); + + Imagefloat img(int(fw / SCALE + 0.5), int(fh / SCALE + 0.5)); + ProcParams neutral; +// neutral.exposure.enabled = true; + imgsrc->getImage(imgsrc->getWB(), TR_NONE, &img, pp, params->toneCurve, neutral.raw); + imgsrc->convertColorSpace(&img, params->icm, imgsrc->getWB()); + + float vmin = RT_INFINITY; + float vmax = -RT_INFINITY; + bool always = true; + const float ec = always ? std::pow(2.f, params->toneCurve.expcomp) : 1.f; + + constexpr float noise = 1e-5; + int h = fh / SCALE; + int w = fw / SCALE; + // printf("h=%d w=%d\n", h, w); + // printf("xsta=%f xend=%f ysta=%f yend=%f\n", xsta, xend, ysta, yend); + + + int hsta = ysta * h; + int hend = yend * h; + + int wsta = xsta * w; + int wend = xend * w; + + //printf("h=%d w=%d hsta=%d hend=%d wsta=%d wend=%d\n", h, w, hsta, hend, wsta, wend); + float mean = 0.f; + int nc = 0; + + for (int y = hsta; y < hend; ++y) { + for (int x = wsta; x < wend; ++x) { + float r = img.r(y, x), g = img.g(y, x), b = img.b(y, x); + float m = max(0.f, r, g, b) / 65535.f * ec; + float rgam = Color::gamma_srgb(r / 65535.f); + float ggam = Color::gamma_srgb(g / 65535.f); + float bgam = Color::gamma_srgb(b / 65535.f); + float lum = 0.2126f * rgam + 0.7152f * ggam + 0.0722f * bgam; + mean += lum; + nc++; + + if (m > noise) { + float l = min(r, g, b) / 65535.f * ec; + vmin = min(vmin, l > noise ? l : m); + vmax = max(vmax, m); + } + } + } + + mean = mean / nc; + float yb = 18.f; + + if (mean < 0.15f) { + yb = 3.0f; + } else if (mean < 0.3f) { + yb = 5.0f; + } else if (mean < 0.4f) { + yb = 10.0f; + } else if (mean < 0.45f) { + yb = 15.0f; + } else if (mean < 0.5f) { + yb = 18.0f; + } else if (mean < 0.55f) { + yb = 23.0f; + } else if (mean < 0.6f) { + yb = 30.0f; + } else { + yb = 45.f; + } + + //approximation sourcegray yb source = 0.4 * yb + + + if (vmax > vmin) { + const float log2 = xlogf(2.f); + float dynamic_range = -xlogf(vmin / vmax) / log2; + + if (settings->verbose) { + std::cout << "AutoLog: min = " << vmin << ", max = " << vmax + << ", DR = " << dynamic_range << std::endl; + } + + if (Autogr[sp]) { + double tot = 0.f; + int n = 0; + float gmax = std::min(vmax / 2.f, 0.25f); + float gmin = std::max(vmin * std::pow(2.f, std::max((dynamic_range - 1.f) / 2.f, 1.f)), 0.05f); + + if (settings->verbose) { + std::cout << " gray boundaries: " << gmin << ", " << gmax << std::endl; + } + + for (int y = ysta; y < yend; ++y) { + for (int x = wsta; x < wend; ++x) { + float l = img.g(y, x) / 65535.f; + + if (l >= gmin && l <= gmax) { + tot += l; + ++n; + } + } + } + + if (n > 0) { + sourceg[sp] = tot / n * 100.f; + + if (settings->verbose) { + std::cout << " computed gray point from " << n << " samples: " << sourceg[sp] << std::endl; + } + } else if (settings->verbose) { + sourceg[sp] = 0.4f * yb; + std::cout << " no samples found in range, resorting to Yb gray point value " << sourceg[sp] << std::endl; + } + } + + float gray = float(sourceg[sp]) / 100.f; + whiteev[sp] = xlogf(vmax / gray) / log2; + blackev[sp] = whiteev[sp] - dynamic_range; + } +} + +void tone_eq(array2D &R, array2D &G, array2D &B, const struct local_params & lp, const Glib::ustring &workingProfile, double scale, bool multithread) +// adapted from the tone equalizer of darktable +/* + Copyright 2019 Alberto Griggio + Small adaptation to Local Adjustement 10 2019 Jacques Desmis + This file is part of darktable, + copyright (c) 2018 Aurelien Pierre. + + darktable 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. + + darktable 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 darktable. If not, see . +*/ + +{ + BENCHFUN + + const int W = R.width(); + const int H = R.height(); + array2D Y(W, H); + + const auto log2 = + [](float x) -> float { + static const float l2 = xlogf(2); + return xlogf(x) / l2; + }; + + const auto exp2 = + [](float x) -> float { + return pow_F(2.f, x); + }; + // Build the luma channels: band-pass filters with gaussian windows of + // std 2 EV, spaced by 2 EV + const float centers[12] = { + -18.0f, -16.0f, -14.0f, -12.0f, -10.0f, -8.0f, -6.0f, + -4.0f, -2.0f, 0.0f, 2.0f, 4.0f + }; + + const auto conv = [&](int v, float lo, float hi) -> float { + const float f = v < 0 ? lo : hi; + return exp2(float(v) / 100.f * f); + }; + const float factors[12] = { + conv(lp.mullocsh[0], 2.f, 3.f), // -18 EV + conv(lp.mullocsh[0], 2.f, 3.f), // -16 EV + conv(lp.mullocsh[0], 2.f, 3.f), // -14 EV + conv(lp.mullocsh[0], 2.f, 3.f), // -12 EV + conv(lp.mullocsh[0], 2.f, 3.f), // -10 EV + conv(lp.mullocsh[0], 2.f, 3.f), // -8 EV + conv(lp.mullocsh[1], 2.f, 3.f), // -6 EV + conv(lp.mullocsh[2], 2.5f, 2.5f), // -4 EV + conv(lp.mullocsh[3], 3.f, 2.f), // -2 EV + conv(lp.mullocsh[4], 3.f, 2.f), // 0 EV + conv(lp.mullocsh[4], 3.f, 2.f), // 2 EV + conv(lp.mullocsh[4], 3.f, 2.f) // 4 EV + }; + + TMatrix ws = ICCStore::getInstance()->workingSpaceMatrix(workingProfile); + +#ifdef _OPENMP + # pragma omp parallel for if (multithread) +#endif + + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + Y[y][x] = Color::rgbLuminance(R[y][x], G[y][x], B[y][x], ws); + } + } + + int detail = LIM(lp.detailsh + 5, 0, 5); + int radius = float(detail) / scale + 0.5f; + float epsilon2 = 0.01f + 0.002f * max(detail - 3, 0); + + if (radius > 0) { + rtengine::guidedFilterLog(10.f, Y, radius, epsilon2, multithread); + } + + if (lp.detailsh > 0) { + array2D Y2(W, H); + constexpr float base_epsilon = 0.02f; + constexpr float base_posterization = 5.f; + +#ifdef _OPENMP + # pragma omp parallel for if (multithread) +#endif + + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + float l = LIM(log2(std::max(Y[y][x], 1e-9f)), centers[0], centers[11]); + float ll = round(l * base_posterization) / base_posterization; + Y2[y][x] = Y[y][x]; + Y[y][x] = exp2(ll); + } + } + + radius = 350.f / scale; + epsilon2 = base_epsilon / float(6 - std::min(lp.detailsh, 5)); + rtengine::guidedFilter(Y2, Y, Y, radius, epsilon2, multithread); + } + + const auto gauss = + [](float b, float x) -> float { + return xexpf((-SQR(x - b) / 4.0f)); + }; + + // For every pixel luminance, the sum of the gaussian masks + float w_sum = 0.f; + + for (int i = 0; i < 12; ++i) { + w_sum += gauss(centers[i], 0.f); + } + + const auto process_pixel = + [&](float y) -> float { + // convert to log space + const float luma = max(log2(max(y, 0.f)), -18.0f); + + // build the correction as the sum of the contribution of each + // luminance channel to current pixel + float correction = 0.0f; + + for (int c = 0; c < 12; ++c) + { + correction += gauss(centers[c], luma) * factors[c]; + } + + correction /= w_sum; + + return correction; + }; + + LUTf lut(65536); + + for (int i = 0; i < 65536; ++i) { + float y = float(i) / 65535.f; + float c = process_pixel(y); + lut[i] = c; + } + + +#ifdef __SSE2__ + vfloat vfactors[12]; + vfloat vcenters[12]; + + for (int i = 0; i < 12; ++i) { + vfactors[i] = F2V(factors[i]); + vcenters[i] = F2V(centers[i]); + } + + const auto vgauss = + [](vfloat b, vfloat x) -> vfloat { + static const vfloat fourv = F2V(4.f); + return xexpf((-SQR(x - b) / fourv)); + }; + + vfloat zerov = F2V(0.f); + vfloat vw_sum = F2V(w_sum); + + const vfloat noisev = F2V(-18.f); + const vfloat xlog2v = F2V(xlogf(2.f)); + + const auto vprocess_pixel = + [&](vfloat y) -> vfloat { + const vfloat luma = vmaxf(xlogf(vmaxf(y, zerov)) / xlog2v, noisev); + + vfloat correction = zerov; + + for (int c = 0; c < 12; ++c) + { + correction += vgauss(vcenters[c], luma) * vfactors[c]; + } + + correction /= vw_sum; + + return correction; + }; + + + vfloat v1 = F2V(1.f); + vfloat v65535 = F2V(65535.f); +#endif // __SSE2__ + + +#ifdef _OPENMP + # pragma omp parallel for if (multithread) +#endif + + for (int y = 0; y < H; ++y) { + int x = 0; + + +#ifdef __SSE2__ + + for (; x < W - 3; x += 4) { + vfloat cY = LVFU(Y[y][x]); + vmask m = vmaskf_gt(cY, v1); + vfloat corr; + + if (_mm_movemask_ps((vfloat)m)) { + corr = vprocess_pixel(cY); + } else { + corr = lut[cY * v65535]; + } + + STVF(R[y][x], LVF(R[y][x]) * corr); + STVF(G[y][x], LVF(G[y][x]) * corr); + STVF(B[y][x], LVF(B[y][x]) * corr); + } + +#endif // __SSE2__ + + for (; x < W; ++x) { + float cY = Y[y][x]; + float corr = cY > 1.f ? process_pixel(cY) : lut[cY * 65535.f]; + R[y][x] *= corr; + G[y][x] *= corr; + B[y][x] *= corr; + } + } + +} + void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab) { @@ -1191,38 +2192,120 @@ void ImProcFunctions::ciecamloc_02float(int sp, LabImage* lab) } } -void ImProcFunctions::softproc(const LabImage* bufcolorig, const LabImage* bufcolfin, float rad, int bfh, int bfw, double epsilmax, double epsilmin, float thres, int sk, bool multiThread) +void ImProcFunctions::softproc(const LabImage* bufcolorig, const LabImage* bufcolfin, float rad, int bfh, int bfw, double epsilmax, double epsilmin, float thres, int sk, bool multiThread, int flag) { - if (rad > 0.f) { - array2D ble(bfw, bfh); - array2D guid(bfw, bfh); + if (flag == 0) { + if (rad > 0.f) { + array2D ble(bfw, bfh); + array2D guid(bfw, bfh); + Imagefloat *tmpImage = nullptr; + tmpImage = new Imagefloat(bfw, bfh); + #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel for #endif - for (int ir = 0; ir < bfh; ir++) - for (int jr = 0; jr < bfw; jr++) { - ble[ir][jr] = (bufcolfin->L[ir][jr]) / 32768.f; - guid[ir][jr] = bufcolorig->L[ir][jr] / 32768.f; - } + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { - double aepsil = (epsilmax - epsilmin) / 90.f; - double bepsil = epsilmax - 100.f * aepsil; - double epsil = aepsil * rad + bepsil; + float X, Y, Z; + float L = bufcolorig->L[ir][jr]; + float a = bufcolorig->a[ir][jr]; + float b = bufcolorig->b[ir][jr]; + Color::Lab2XYZ(L, a, b, X, Y, Z); - float blur = 10.f / sk * (thres + 0.8f * rad); - rtengine::guidedFilter(guid, ble, ble, blur, epsil, multiThread, 4); + guid[ir][jr] = Y / 32768.f; + float La = bufcolfin->L[ir][jr]; + float aa = bufcolfin->a[ir][jr]; + float ba = bufcolfin->b[ir][jr]; + Color::Lab2XYZ(La, aa, ba, X, Y, Z); + tmpImage->r(ir, jr) = X; + tmpImage->g(ir, jr) = Y; + tmpImage->b(ir, jr) = Z; + + ble[ir][jr] = Y / 32768.f; + } + + double aepsil = (epsilmax - epsilmin) / 90.f; + double bepsil = epsilmax - 100.f * aepsil; + double epsil = aepsil * 0.1 * rad + bepsil; + + float blur = 10.f / sk * (thres + 0.8f * rad); + rtengine::guidedFilter(guid, ble, ble, blur, epsil, multiThread, 4); #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel for #endif - for (int ir = 0; ir < bfh; ir++) - for (int jr = 0; jr < bfw; jr++) { - bufcolfin->L[ir][jr] = 32768.f * ble[ir][jr]; + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + float X = tmpImage->r(ir, jr); + float Y = 32768.f * ble[ir][jr]; + float Z = tmpImage->b(ir, jr); + float L, a, b; + Color::XYZ2Lab(X, Y, Z, L, a, b); + bufcolfin->L[ir][jr] = L; + } + + delete tmpImage; + } + } else if (flag == 1) { + if (rad > 0.f) { + array2D ble(bfw, bfh); + array2D blechro(bfw, bfh); + array2D hue(bfw, bfh); + array2D guid(bfw, bfh); + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { +// hue[ir][jr] = xatan2f(bufcolfin->b[ir][jr], bufcolfin->a[ir][jr]); +// float chromah = sqrt(SQR(bufcolfin->b[ir][jr]) + SQR(bufcolfin->a[ir][jr])); + + ble[ir][jr] = (bufcolfin->L[ir][jr]) / 32768.f; +// blechro[ir][jr] = chromah / 32768.f; + guid[ir][jr] = bufcolorig->L[ir][jr] / 32768.f; + } + + double aepsil = (epsilmax - epsilmin) / 90.f; + double bepsil = epsilmax - 100.f * aepsil; + double epsil = aepsil * 0.1 * rad + bepsil; + + if (rad != 0.f) { + float blur = rad; + blur = blur < 0.f ? -1.f / blur : 1.f + blur; + // int r1 = max(int(4 / sk * blur + 0.5), 1); + int r2 = max(int(25 / sk * blur + 0.5), 1); + + if (rad < 0.f) { + epsil = 0.0001; + } + + rtengine::guidedFilter(guid, ble, ble, r2, epsil, multiThread); +// rtengine::guidedFilter(guid, blechro, blechro, r1, 0.5 * epsil, multiThread); } + + + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + // float2 sincosval = xsincosf(hue[ir][jr]); + + bufcolfin->L[ir][jr] = 32768.f * ble[ir][jr]; + // bufcolfin->a[ir][jr] = 32768.f * sincosval.y * blechro[ir][jr]; + // bufcolfin->b[ir][jr] = 32768.f * sincosval.x * blechro[ir][jr]; + } + } + } } @@ -1260,7 +2343,6 @@ void ImProcFunctions::softprocess(const LabImage* bufcolorig, array2D &bu float blur = 1.f / sk * (thres + 0.8f * rad); guidedFilter(guidsoft, buflight, buflight, blur, epsil, multiThread, 4); - // guidedFilter(guidsoft, buflight, buflight, rad * 100.f / sk, 0.001, multiThread, 4); #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) @@ -1273,7 +2355,7 @@ void ImProcFunctions::softprocess(const LabImage* bufcolorig, array2D &bu } } -void ImProcFunctions::exlabLocal(const local_params& lp, int bfh, int bfw, LabImage* bufexporig, LabImage* lab, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, float mean) +void ImProcFunctions::exlabLocal(local_params& lp, int bfh, int bfw, LabImage* bufexporig, LabImage* lab, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, float mean) { BENCHFUN //exposure local @@ -1286,6 +2368,13 @@ void ImProcFunctions::exlabLocal(const local_params& lp, int bfh, int bfw, LabIm float linear = lp.linear; float kl = 1.5f; float addcomp = 0.f; + + if (lp.linear > 0.f) { + if (lp.expcomp == 0.f) { + lp.expcomp = 0.01f; + } + } + #ifdef _OPENMP #pragma omp parallel for #endif @@ -1294,7 +2383,7 @@ void ImProcFunctions::exlabLocal(const local_params& lp, int bfh, int bfw, LabIm for (int jr = 0; jr < bfw; jr++) { float L = bufexporig->L[ir][jr]; - if (L < mean && lp.expmet == 1 && lp.expcomp > 0.f && !lp.invex) { + if (L < mean && lp.expmet == 1 && lp.linear > 0.f && lp.laplacexp > 0.1f && !lp.invex) { float Llin = LIM01(L / 32768.f); addcomp = linear * (-kl * Llin + kl);//maximum about 1.5 IL exp_scale = pow(2.0, (lp.expcomp + addcomp)); @@ -1397,6 +2486,18 @@ static void balancedeltaE(float kL, float &kab) kab = abal * kL + bbal; } +static void balancedeltaEH(float kH, float &kch) +{ + float mincurs = 0.3f;//minimum slider balan_ + float maxcurs = 1.7f;//maximum slider balan_ + float maxkab = 1.35;//0.5 * (3 - 0.3) + float minkab = 0.65;//0.5 * (3 - 1.7) + float abal = (maxkab - minkab) / (mincurs - maxcurs); + float bbal = maxkab - mincurs * abal; + kch = abal * kH + bbal; +} + + static void calcreducdE(float dE, float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, float &reducdE) { if (dE > maxdE) { @@ -1424,7 +2525,7 @@ static void calcreducdE(float dE, float maxdE, float mindE, float maxdElim, flo } } } -void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, int levred, float hueref, float lumaref, float chromaref, LabImage* original, LabImage* transformed, LabImage &tmp1, int cx, int cy, int sk) +void ImProcFunctions::DeNoise_Local(int call, struct local_params& lp, LabImage*originalmask, int levred, float hueref, float lumaref, float chromaref, LabImage* original, LabImage* transformed, LabImage &tmp1, int cx, int cy, int sk) { //warning, but I hope used it next // local denoise and impulse @@ -1438,12 +2539,40 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, in const int GW = transformed->W; const int GH = transformed->H; + + if (lp.colorde == 0) { + lp.colorde = -1;//to avoid black + } + + float darklim = 5000.f; + float aadark = -1.f; + float bbdark = darklim; + const float refa = chromaref * cos(hueref); const float refb = chromaref * sin(hueref); + const bool usemaskbl = (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 4); + const bool usemaskall = (usemaskbl); + const bool blshow = ((lp.showmaskblmet == 1 || lp.showmaskblmet == 2)); + const bool previewbl = ((lp.showmaskblmet == 4)); std::unique_ptr origblur(new LabImage(GW, GH)); + std::unique_ptr origblurmask; const float radius = 3.f / sk; + + if (usemaskall) { + origblurmask.reset(new LabImage(GW, GH)); + +#ifdef _OPENMP + #pragma omp parallel if (multiThread) +#endif + { + gaussianBlur(originalmask->L, origblurmask->L, GW, GH, radius); + gaussianBlur(originalmask->a, origblurmask->a, GW, GH, radius); + gaussianBlur(originalmask->b, origblurmask->b, GW, GH, radius); + } + } + #ifdef _OPENMP #pragma omp parallel #endif @@ -1460,6 +2589,7 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, in #pragma omp parallel if (multiThread) #endif { + const LabImage *maskptr = usemaskall ? origblurmask.get() : origblur.get(); const int limscope = 80; const float mindE = 2.f + MINSCOPE * lp.sensden * lp.thr; const float maxdE = 5.f + MAXSCOPE * lp.sensden * (1 + 0.1f * lp.thr); @@ -1494,10 +2624,9 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, in continue; } - float rL = original->L[y][x] / 327.6f; - float dEL = sqrt(0.9f * SQR(refa - origblur->a[y][x] / 327.6f) + 0.9f * SQR(refb - origblur->b[y][x] / 327.8f) + 1.2f * SQR(lumaref - rL)); - float dEa = sqrt(1.2f * SQR(refa - origblur->a[y][x] / 327.6f) + 1.f * SQR(refb - origblur->b[y][x] / 327.8f) + 0.8f * SQR(lumaref - rL)); - float dEb = sqrt(1.f * SQR(refa - origblur->a[y][x] / 327.6f) + 1.2f * SQR(refb - origblur->b[y][x] / 327.8f) + 0.8f * SQR(lumaref - rL)); + float dEL = sqrt(0.9f * SQR(refa - maskptr->a[y][x] / 327.6f) + 0.9f * SQR(refb - maskptr->b[y][x] / 327.8f) + 1.2f * SQR(lumaref - maskptr->L[y][x] / 327.8f)); + float dEa = sqrt(1.2f * SQR(refa - maskptr->a[y][x] / 327.6f) + 1.f * SQR(refb - maskptr->b[y][x] / 327.8f) + 0.8f * SQR(lumaref - maskptr->L[y][x] / 327.8f)); + float dEb = sqrt(1.f * SQR(refa - maskptr->a[y][x] / 327.6f) + 1.2f * SQR(refb - maskptr->b[y][x] / 327.8f) + 0.8f * SQR(lumaref - maskptr->L[y][x] / 327.8f)); float reducdEL = 1.f; float reducdEa = 1.f; @@ -1513,52 +2642,51 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, in } - switch (zone) { - case 1: { // inside transition zone - float difL, difa, difb; + if (zone > 0) { + float difL, difa, difb; - if (call == 2 /*|| call == 1 || call == 3 */) { //simpleprocess - difL = tmp1.L[loy - begy][lox - begx] - original->L[y][x]; - difa = tmp1.a[loy - begy][lox - begx] - original->a[y][x]; - difb = tmp1.b[loy - begy][lox - begx] - original->b[y][x]; - } else { //dcrop - difL = tmp1.L[y][x] - original->L[y][x]; - difa = tmp1.a[y][x] - original->a[y][x]; - difb = tmp1.b[y][x] - original->b[y][x]; + if (call == 2 /*|| call == 1 || call == 3 */) { //simpleprocess + difL = tmp1.L[loy - begy][lox - begx] - original->L[y][x]; + difa = tmp1.a[loy - begy][lox - begx] - original->a[y][x]; + difb = tmp1.b[loy - begy][lox - begx] - original->b[y][x]; + } else { //dcrop + difL = tmp1.L[y][x] - original->L[y][x]; + difa = tmp1.a[y][x] - original->a[y][x]; + difb = tmp1.b[y][x] - original->b[y][x]; - } - - difL *= localFactor * reducdEL; - difa *= localFactor * reducdEa; - difb *= localFactor * reducdEb; - transformed->L[y][x] = CLIP(original->L[y][x] + difL); - transformed->a[y][x] = CLIPC((original->a[y][x] + difa) * factnoise); - transformed->b[y][x] = CLIPC((original->b[y][x] + difb) * factnoise) ; - break; } - case 2: { // inside selection => full effect, no transition - float difL, difa, difb; + difL *= localFactor * reducdEL; + difa *= localFactor * reducdEa; + difb *= localFactor * reducdEb; + transformed->L[y][x] = CLIP(original->L[y][x] + difL); + transformed->a[y][x] = CLIPC((original->a[y][x] + difa) * factnoise); + transformed->b[y][x] = CLIPC((original->b[y][x] + difb) * factnoise) ; + float amplabL = 2.f * lp.colorde; - if (call == 2 /*|| call == 1 || call == 3 */) { //simpleprocess - difL = tmp1.L[loy - begy][lox - begx] - original->L[y][x]; - difa = tmp1.a[loy - begy][lox - begx] - original->a[y][x]; - difb = tmp1.b[loy - begy][lox - begx] - original->b[y][x]; - } else { //dcrop - difL = tmp1.L[y][x] - original->L[y][x]; - difa = tmp1.a[y][x] - original->a[y][x]; - difb = tmp1.b[y][x] - original->b[y][x]; + if (blshow) { + transformed->L[y][x] = CLIP(12000.f + amplabL * difL);// * 10.f empirical to can visualize modifications + transformed->a[y][x] = CLIPC(amplabL * difa);// * 10.f empirical to can visualize modifications + transformed->b[y][x] = CLIPC(amplabL * difb);// * 10.f empirical to can visualize modifications + } else if (previewbl) { + float difbdisp = (reducdEL + reducdEa + reducdEb) * 10000.f * lp.colorde; + if (transformed->L[y][x] < darklim) { //enhance dark luminance as user can see! + float dark = transformed->L[y][x]; + transformed->L[y][x] = dark * aadark + bbdark; } - difL *= reducdEL; - difa *= reducdEa; - difb *= reducdEb; + if (lp.colorde <= 0) { + transformed->a[y][x] = 0.f; + transformed->b[y][x] = difbdisp; + } else { + transformed->a[y][x] = -difbdisp; + transformed->b[y][x] = 0.f; + } - transformed->L[y][x] = CLIP(original->L[y][x] + difL); - transformed->a[y][x] = CLIPC((original->a[y][x] + difa) * factnoise); - transformed->b[y][x] = CLIPC((original->b[y][x] + difb) * factnoise); } + + } } @@ -1566,92 +2694,6 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, in } } -void ImProcFunctions::BlurNoise_Local(LabImage *tmp1, const float hueref, const float chromaref, const float lumaref, const local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) -{ -//local BLUR - BENCHFUN - - const int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); - const int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); - const int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); - const int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); - - const float ach = lp.trans / 100.f; - const int GW = transformed->W; - const int GH = transformed->H; - const float refa = chromaref * cos(hueref) * 327.68f; - const float refb = chromaref * sin(hueref) * 327.68f; - const float refL = lumaref * 327.68f; - - //balance deltaE - float kL = lp.balance; - float kab = 1.f; - balancedeltaE(kL, kab); - kab /= SQR(327.68f); - kL /= SQR(327.68f); - - std::unique_ptr origblur(new LabImage(GW, GH)); - - const float radius = 3.f / sk; -#ifdef _OPENMP - #pragma omp parallel -#endif - { - gaussianBlur(original->L, origblur->L, GW, GH, radius); - gaussianBlur(original->a, origblur->a, GW, GH, radius); - gaussianBlur(original->b, origblur->b, GW, GH, radius); - } - -#ifdef _OPENMP - #pragma omp parallel if (multiThread) -#endif - { - const int limscope = 80; - const float mindE = 4.f + MINSCOPE * lp.sensbn * lp.thr;//best usage ?? with blurnoise - const float maxdE = 5.f + MAXSCOPE * lp.sensbn * (1 + 0.1f * lp.thr); - const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; - const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); - -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) -#endif - - for (int y = ystart; y < yend; y++) { - const int loy = cy + y; - - for (int x = xstart, lox = cx + x; x < xend; x++, lox++) { - int zone = 0; - float localFactor = 1.f; - - if (lp.shapmet == 0) { - calcTransition(lox, loy, ach, lp, zone, localFactor); - } else if (lp.shapmet == 1) { - calcTransitionrect(lox, loy, ach, lp, zone, localFactor); - } - - if (zone == 0) { // outside selection and outside transition zone => no effect, keep original values - continue; - } - - const float dE = sqrt(kab * (SQR(refa - origblur->a[y][x]) + SQR(refb - origblur->b[y][x])) + kL * SQR(refL - origblur->L[y][x])); - - float reducdE; - calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, lp.sensbn, reducdE); - - const float difL = (tmp1->L[y - ystart][x - xstart] - original->L[y][x]) * localFactor * reducdE; - transformed->L[y][x] = CLIP(original->L[y][x] + difL); - - if (!lp.actsp) { - const float difa = (tmp1->a[y - ystart][x - xstart] - original->a[y][x]) * localFactor * reducdE;; - const float difb = (tmp1->b[y - ystart][x - xstart] - original->b[y][x]) * localFactor * reducdE;; - transformed->a[y][x] = CLIPC(original->a[y][x] + difa); - transformed->b[y][x] = CLIPC(original->b[y][x] + difb); - } - } - } - } -} - void ImProcFunctions::InverseReti_Local(const struct local_params & lp, const float hueref, const float chromaref, const float lumaref, LabImage * original, LabImage * transformed, const LabImage * const tmp1, int cx, int cy, int chro, int sk) { // BENCHFUN @@ -1667,7 +2709,10 @@ void ImProcFunctions::InverseReti_Local(const struct local_params & lp, const fl float kab = 1.f; balancedeltaE(kL, kab); - LabImage *origblur = new LabImage(GW, GH); + kab /= SQR(327.68f); + kL /= SQR(327.68f); + + std::unique_ptr origblur(new LabImage(GW, GH)); float radius = 3.f / sk; #ifdef _OPENMP @@ -1772,30 +2817,57 @@ void ImProcFunctions::InverseReti_Local(const struct local_params & lp, const fl } } - delete origblur; } -void ImProcFunctions::InverseBlurNoise_Local(const struct local_params & lp, const float hueref, const float chromaref, const float lumaref, LabImage * original, LabImage * transformed, const LabImage * const tmp1, int cx, int cy, int sk) +void ImProcFunctions::InverseBlurNoise_Local(LabImage * originalmask, float **bufchro, const struct local_params & lp, const float hueref, const float chromaref, const float lumaref, LabImage * original, LabImage * transformed, const LabImage * const tmp1, int cx, int cy, int sk) { // BENCHFUN //inverse local blur and noise float ach = (float)lp.trans / 100.f; int GW = transformed->W; int GH = transformed->H; - float refa = chromaref * cos(hueref); - float refb = chromaref * sin(hueref); + const float refa = chromaref * cos(hueref) * 327.68f; + const float refb = chromaref * sin(hueref) * 327.68f; + const float refL = lumaref * 327.68f; + + + const bool blshow = (lp.showmaskblmet == 1 || lp.showmaskblmet == 2); + const bool previewbl = (lp.showmaskblmet == 4); //balance deltaE float kL = lp.balance; float kab = 1.f; balancedeltaE(kL, kab); + float kH = lp.balanceh; + float kch = 1.f; + balancedeltaEH(kH, kch); + kab /= SQR(327.68f); + kL /= SQR(327.68f); - LabImage *origblur = new LabImage(GW, GH); + std::unique_ptr origblur(new LabImage(GW, GH)); + std::unique_ptr origblurmask; + const bool usemaskbl = (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 4); + const bool usemaskall = usemaskbl; float radius = 3.f / sk; + + if (usemaskall) { + origblurmask.reset(new LabImage(GW, GH)); + +#ifdef _OPENMP + #pragma omp parallel if (multiThread) +#endif + { + gaussianBlur(originalmask->L, origblurmask->L, GW, GH, radius); + gaussianBlur(originalmask->a, origblurmask->a, GW, GH, radius); + gaussianBlur(originalmask->b, origblurmask->b, GW, GH, radius); + } + } + + #ifdef _OPENMP #pragma omp parallel #endif @@ -1809,6 +2881,7 @@ void ImProcFunctions::InverseBlurNoise_Local(const struct local_params & lp, co #pragma omp parallel if (multiThread) #endif { + const LabImage *maskptr = usemaskall ? origblurmask.get() : origblur.get(); const int limscope = 80; const float mindE = 2.f + MINSCOPE * lp.sensbn * lp.thr; const float maxdE = 5.f + MAXSCOPE * lp.sensbn * (1 + 0.1f * lp.thr); @@ -1834,19 +2907,42 @@ void ImProcFunctions::InverseBlurNoise_Local(const struct local_params & lp, co calcTransitionrect(lox, loy, ach, lp, zone, localFactor); } - float rL = origblur->L[y][x] / 327.68f; - float dE = sqrt(kab * SQR(refa - origblur->a[y][x] / 327.68f) + kab * SQR(refb - origblur->b[y][x] / 327.68f) + kL * SQR(lumaref - rL)); + const float clc = (previewbl) ? settings->previewselection * 100.f : bufchro[y][x]; + float abdelta2 = SQR(refa - maskptr->a[y][x]) + SQR(refb - maskptr->b[y][x]); + float chrodelta2 = SQR(sqrt(SQR(maskptr->a[y][x]) + SQR(maskptr->b[y][x])) - (chromaref * 327.68f)); + float huedelta2 = abdelta2 - chrodelta2; + + float dE = sqrt(kab * (kch * chrodelta2 + kH * huedelta2) + kL * SQR(refL - maskptr->L[y][x])); float reducdE; calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, lp.sensbn, reducdE); + const float realstrchdE = reducdE * clc; switch (zone) { + case 0: { // outside selection and outside transition zone => full effect, no transition float difL = tmp1->L[y][x] - original->L[y][x]; transformed->L[y][x] = CLIP(original->L[y][x] + difL * reducdE); + float difa = tmp1->a[y][x] - original->a[y][x]; + float difb = tmp1->b[y][x] - original->b[y][x]; + float flia = 1.f, flib = 1.f; + flia = flib = ((100.f + realstrchdE) / 100.f); + const float chra = tmp1->a[y][x]; + const float chrb = tmp1->b[y][x]; if (!lp.actsp) { - transformed->a[y][x] = CLIPC(tmp1->a[y][x]); - transformed->b[y][x] = CLIPC(tmp1->b[y][x]); + difa = chra * flia - original->a[y][x]; + difb = chrb * flib - original->b[y][x]; + transformed->a[y][x] = CLIPC(original->a[y][x] + difa); + transformed->b[y][x] = CLIPC(original->b[y][x] + difb); + } + + if (blshow) { + transformed->L[y][x] = CLIP(12000.f + difL); + transformed->a[y][x] = CLIPC(difa); + transformed->b[y][x] = CLIPC(difb); + } else if (previewbl) { + transformed->a[y][x] = 0.f; + transformed->b[y][x] = (difb); } break; @@ -1856,18 +2952,33 @@ void ImProcFunctions::InverseBlurNoise_Local(const struct local_params & lp, co float difL = tmp1->L[y][x] - original->L[y][x]; float difa = tmp1->a[y][x] - original->a[y][x]; float difb = tmp1->b[y][x] - original->b[y][x]; + float flia = 1.f, flib = 1.f; + flia = flib = ((100.f + realstrchdE) / 100.f); + const float chra = tmp1->a[y][x]; + const float chrb = tmp1->b[y][x]; float factorx = 1.f - localFactor; difL *= factorx; - difa *= factorx; - difb *= factorx; transformed->L[y][x] = CLIP(original->L[y][x] + difL * reducdE); if (!lp.actsp) { - + difa = chra * flia - original->a[y][x]; + difb = chrb * flib - original->b[y][x]; + difa *= factorx; + difb *= factorx; transformed->a[y][x] = CLIPC(original->a[y][x] + difa); transformed->b[y][x] = CLIPC(original->b[y][x] + difb); + + } + + if (blshow) { + transformed->L[y][x] = CLIP(12000.f + difL); + transformed->a[y][x] = CLIPC(difa); + transformed->b[y][x] = CLIPC(difb); + } else if (previewbl) { + transformed->a[y][x] = 0.f; + transformed->b[y][x] = (difb); } break; @@ -1886,7 +2997,6 @@ void ImProcFunctions::InverseBlurNoise_Local(const struct local_params & lp, co } } } - delete origblur; } static void calclight(float lum, float koef, float &lumnew, const LUTf &lightCurveloc) @@ -1943,10 +3053,167 @@ static void mean_fab(int xstart, int ystart, int bfw, int bfh, LabImage* bufexpo } } +float pow3(float x) +{ + return x * x * x; +} + + +struct grad_params { + bool angle_is_zero, transpose, bright_top; + float ta, yc, xc; + float ys, ys_inv; + float scale, botmul, topmul; + float top_edge_0; + int h; +}; + +void calclocalGradientParams(const struct local_params& lp, struct grad_params& gp, float ystart, float xstart, int bfw, int bfh, int indic) +{ + int w = bfw; + int h = bfh; + float stops = 0.f; + float angs = 0.f; + + if (indic == 0) { + stops = -lp.strmaexp; + angs = lp.angmaexp; + } else if (indic == 1) { + stops = lp.strexp; + angs = lp.angexp; + } else if (indic == 2) { + stops = lp.strSH; + angs = lp.angSH; + } else if (indic == 3) { + stops = lp.strcol; + angs = lp.angcol; + } else if (indic == 4) { + float redu = 1.f; + + if (lp.strcolab > 0.f) { + redu = 0.6f; + } else { + redu = 0.15f; + } + + stops = redu * lp.strcolab; + angs = lp.angcol; + } else if (indic == 5) { + stops = lp.strcolab; + angs = lp.angcol; + } else if (indic == 6) { + stops = lp.strcolh; + angs = lp.angcol; + } else if (indic == 7) { + stops = lp.strvib; + angs = lp.angvib; + } else if (indic == 8) { + float redu = 1.f; + + if (lp.strvibab > 0.f) { + redu = 0.7f; + } else { + redu = 0.5f; + } + + stops = redu * lp.strvibab; + angs = lp.angvib; + } else if (indic == 9) { + stops = lp.strvibh; + angs = lp.angvib; + } else if (indic == 10) { + stops = fabs(lp.strwav); + angs = lp.angwav; + } else if (indic == 11) { + stops = lp.strlog; + angs = lp.anglog; + } + + + double gradient_stops = stops; + double gradient_center_x = LIM01((lp.xc - xstart) / bfw); + double gradient_center_y = LIM01((lp.yc - ystart) / bfh); + double gradient_angle = angs / 180.0 * rtengine::RT_PI; + double varfeath = 0.01 * lp.feath; + + //printf("xstart=%f ysta=%f lpxc=%f lpyc=%f stop=%f bb=%f cc=%f ang=%f ff=%d gg=%d\n", xstart, ystart, lp.xc, lp.yc, gradient_stops, gradient_center_x, gradient_center_y, gradient_angle, w, h); + + // make 0.0 <= gradient_angle < 2 * rtengine::RT_PI + gradient_angle = fmod(gradient_angle, 2 * rtengine::RT_PI); + + if (gradient_angle < 0.0) { + gradient_angle += 2.0 * rtengine::RT_PI; + } + + gp.bright_top = false; + gp.transpose = false; + gp.angle_is_zero = false; + gp.h = h; + double cosgrad = cos(gradient_angle); + + if (fabs(cosgrad) < 0.707) { + // we transpose to avoid division by zero at 90 degrees + // (actually we could transpose only for 90 degrees, but this way we avoid + // division with extremely small numbers + gp.transpose = true; + gradient_angle += 0.5 * rtengine::RT_PI; + double gxc = gradient_center_x; + gradient_center_x = 1.0 - gradient_center_y; + gradient_center_y = gxc; + } + + gradient_angle = fmod(gradient_angle, 2 * rtengine::RT_PI); + + if (gradient_angle > 0.5 * rtengine::RT_PI && gradient_angle < rtengine::RT_PI) { + gradient_angle += rtengine::RT_PI; + gp.bright_top = true; + } else if (gradient_angle >= rtengine::RT_PI && gradient_angle < 1.5 * rtengine::RT_PI) { + gradient_angle -= rtengine::RT_PI; + gp.bright_top = true; + } + + if (fabs(gradient_angle) < 0.001 || fabs(gradient_angle - 2 * rtengine::RT_PI) < 0.001) { + gradient_angle = 0; + gp.angle_is_zero = true; + } + + if (gp.transpose) { + gp.bright_top = !gp.bright_top; + std::swap(w, h); + } + + gp.scale = 1.0 / pow(2, gradient_stops); + + if (gp.bright_top) { + gp.topmul = 1.0; + gp.botmul = gp.scale; + } else { + gp.topmul = gp.scale; + gp.botmul = 1.0; + } + + gp.ta = tan(gradient_angle); + gp.xc = w * gradient_center_x; + gp.yc = h * gradient_center_y; + gp.ys = sqrt((float)h * h + (float)w * w) * (varfeath / cos(gradient_angle)); + gp.ys_inv = 1.0 / gp.ys; + gp.top_edge_0 = gp.yc - gp.ys / 2.0; + + if (gp.ys < 1.0 / h) { + gp.ys_inv = 0; + gp.ys = 0; + } +} void ImProcFunctions::blendstruc(int bfw, int bfh, LabImage* bufcolorig, float radius, float stru, array2D & blend2, int sk, bool multiThread) { SobelCannyLuma(blend2, bufcolorig->L, bfw, bfh, radius, multiThread); + float rm = 20.f / sk; + + if (rm > 0) { + float **mb = blend2; + gaussianBlur(mb, mb, bfw, bfh, rm); + } array2D ble(bfw, bfh); array2D guid(bfw, bfh); @@ -1956,8 +3223,15 @@ void ImProcFunctions::blendstruc(int bfw, int bfh, LabImage* bufcolorig, float r for (int ir = 0; ir < bfh; ir++) { for (int jr = 0; jr < bfw; jr++) { + float X, Y, Z; + float L = bufcolorig->L[ir][jr]; + float a = bufcolorig->a[ir][jr]; + float b = bufcolorig->b[ir][jr]; + Color::Lab2XYZ(L, a, b, X, Y, Z); + + guid[ir][jr] = Y / 32768.f; + blend2[ir][jr] /= 32768.f; - guid[ir][jr] = bufcolorig->L[ir][jr] / 32768.f; } } @@ -1971,15 +3245,15 @@ void ImProcFunctions::blendstruc(int bfw, int bfh, LabImage* bufcolorig, float r for (int ir = 0; ir < bfh; ir++) { for (int jr = 0; jr < bfw; jr++) { - ble[ir][jr] *= 32768.f; + blend2[ir][jr] = 32768.f * ble[ir][jr]; } } - Median_Denoise(ble, blend2, bfw, bfh, Median::TYPE_3X3_STRONG, 1, multiThread); +// Median_Denoise(ble, blend2, bfw, bfh, Median::TYPE_3X3_STRONG, 1, multiThread); } -static void blendmask(const local_params& lp, int xstart, int ystart, int cx, int cy, int bfw, int bfh, LabImage* bufexporig, LabImage* original, LabImage* bufmaskor, LabImage* originalmas, float bl) +static void blendmask(const local_params& lp, int xstart, int ystart, int cx, int cy, int bfw, int bfh, LabImage* bufexporig, LabImage* original, LabImage* bufmaskor, LabImage* originalmas, float bl, int inv) { #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) @@ -2001,44 +3275,131 @@ static void blendmask(const local_params& lp, int xstart, int ystart, int cx, in calcTransitionrect(lox, loy, achm, lp, zone, localFactor); } - if (zone > 0) { - bufexporig->L[y][x] += (bl * bufmaskor->L[y][x]); - bufexporig->a[y][x] *= (1.f + bl * bufmaskor->a[y][x]); - bufexporig->b[y][x] *= (1.f + bl * bufmaskor->b[y][x]); + if (inv == 0) { + if (zone > 0) { + bufexporig->L[y][x] += (bl * bufmaskor->L[y][x]); + bufexporig->a[y][x] *= (1.f + bl * bufmaskor->a[y][x]); + bufexporig->b[y][x] *= (1.f + bl * bufmaskor->b[y][x]); - bufexporig->L[y][x] = CLIP(bufexporig->L[y][x]); - bufexporig->a[y][x] = CLIPC(bufexporig->a[y][x]); - bufexporig->b[y][x] = CLIPC(bufexporig->b[y][x]); + bufexporig->L[y][x] = CLIP(bufexporig->L[y][x]); + bufexporig->a[y][x] = CLIPC(bufexporig->a[y][x]); + bufexporig->b[y][x] = CLIPC(bufexporig->b[y][x]); - originalmas->L[y][x] = CLIP(bufexporig->L[y][x] - bufmaskor->L[y][x]); - originalmas->a[y][x] = CLIPC(bufexporig->a[y][x] * (1.f - bufmaskor->a[y][x])); - originalmas->b[y][x] = CLIPC(bufexporig->b[y][x] * (1.f - bufmaskor->b[y][x])); + originalmas->L[y][x] = CLIP(bufexporig->L[y][x] - bufmaskor->L[y][x]); + originalmas->a[y][x] = CLIPC(bufexporig->a[y][x] * (1.f - bufmaskor->a[y][x])); + originalmas->b[y][x] = CLIPC(bufexporig->b[y][x] * (1.f - bufmaskor->b[y][x])); - switch (zone) { + original->L[y + ystart][x + xstart] += (bl * localFactor * bufmaskor->L[y][x]); + original->a[y + ystart][x + xstart] *= (1.f + bl * localFactor * bufmaskor->a[y][x]); + original->b[y + ystart][x + xstart] *= (1.f + bl * localFactor * bufmaskor->b[y][x]); + original->L[y + ystart][x + xstart] = CLIP(original->L[y + ystart][x + xstart]); + original->a[y + ystart][x + xstart] = CLIPC(original->a[y + ystart][x + xstart]); + original->b[y + ystart][x + xstart] = CLIPC(original->b[y + ystart][x + xstart]); - case 1: { - original->L[y + ystart][x + xstart] += (bl * localFactor * bufmaskor->L[y][x]); - original->a[y + ystart][x + xstart] *= (1.f + bl * localFactor * bufmaskor->a[y][x]); - original->b[y + ystart][x + xstart] *= (1.f + bl * localFactor * bufmaskor->b[y][x]); - original->L[y + ystart][x + xstart] = CLIP(original->L[y + ystart][x + xstart]); - original->a[y + ystart][x + xstart] = CLIPC(original->a[y + ystart][x + xstart]); - original->b[y + ystart][x + xstart] = CLIPC(original->b[y + ystart][x + xstart]); - break; - } + } + } else if (inv == 1) { + localFactor = 1.f - localFactor; - case 2: { + if (zone < 2) { + bufexporig->L[y][x] += (bl * bufmaskor->L[y][x]); + bufexporig->a[y][x] *= (1.f + bl * bufmaskor->a[y][x]); + bufexporig->b[y][x] *= (1.f + bl * bufmaskor->b[y][x]); - original->L[y + ystart][x + xstart] = bufexporig->L[y][x]; - original->a[y + ystart][x + xstart] = bufexporig->a[y][x]; - original->b[y + ystart][x + xstart] = bufexporig->b[y][x]; + bufexporig->L[y][x] = CLIP(bufexporig->L[y][x]); + bufexporig->a[y][x] = CLIPC(bufexporig->a[y][x]); + bufexporig->b[y][x] = CLIPC(bufexporig->b[y][x]); + + originalmas->L[y][x] = CLIP(bufexporig->L[y][x] - bufmaskor->L[y][x]); + originalmas->a[y][x] = CLIPC(bufexporig->a[y][x] * (1.f - bufmaskor->a[y][x])); + originalmas->b[y][x] = CLIPC(bufexporig->b[y][x] * (1.f - bufmaskor->b[y][x])); + + switch (zone) { + case 0: { + original->L[y + ystart][x + xstart] += (bl * bufmaskor->L[y][x]); + original->a[y + ystart][x + xstart] *= (1.f + bl * bufmaskor->a[y][x]); + original->b[y + ystart][x + xstart] *= (1.f + bl * bufmaskor->b[y][x]); + original->L[y + ystart][x + xstart] = CLIP(original->L[y + ystart][x + xstart]); + original->a[y + ystart][x + xstart] = CLIPC(original->a[y + ystart][x + xstart]); + original->b[y + ystart][x + xstart] = CLIPC(original->b[y + ystart][x + xstart]); + break; + } + + case 1: { + original->L[y + ystart][x + xstart] += (bl * localFactor * bufmaskor->L[y][x]); + original->a[y + ystart][x + xstart] *= (1.f + bl * localFactor * bufmaskor->a[y][x]); + original->b[y + ystart][x + xstart] *= (1.f + bl * localFactor * bufmaskor->b[y][x]); + original->L[y + ystart][x + xstart] = CLIP(original->L[y + ystart][x + xstart]); + original->a[y + ystart][x + xstart] = CLIPC(original->a[y + ystart][x + xstart]); + original->b[y + ystart][x + xstart] = CLIPC(original->b[y + ystart][x + xstart]); + } } } + } } } } +void ImProcFunctions::deltaEforMask(float **rdE, int bfw, int bfh, LabImage* bufcolorig, const float hueref, const float chromaref, const float lumaref, + float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, float balance, float balanceh) +{ + const float refa = chromaref * cos(hueref); + const float refb = chromaref * sin(hueref); + const float refL = lumaref; + + float kL = balance; + float kab = 1.f; + float kH = balanceh; + float kch = 1.f; + balancedeltaE(kL, kab); + balancedeltaEH(kH, kch); + + float reducdE = 1.f; +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < bfh; y++) { + for (int x = 0; x < bfw; x++) { + float abdelta2 = SQR(refa - bufcolorig->a[y][x] / 327.68f) + SQR(refb - bufcolorig->b[y][x] / 327.68f); + float chrodelta2 = SQR(sqrt(SQR(bufcolorig->a[y][x] / 327.68f) + SQR(bufcolorig->b[y][x] / 327.68f)) - (chromaref)); + float huedelta2 = abdelta2 - chrodelta2; + + float tempdE = sqrt(kab * (kch * chrodelta2 + kH * huedelta2) + kL * SQR(refL - bufcolorig->L[y][x] / 327.68f)); + + if (tempdE > maxdE) { + reducdE = 0.f; + } else if (tempdE > mindE && tempdE <= maxdE) { + const float ar = 1.f / (mindE - maxdE); + const float br = - ar * maxdE; + reducdE = pow(ar * tempdE + br, iterat); + } else { + reducdE = 1.f; + } + + if (scope > limscope) { + if (tempdE > maxdElim) { + reducdE = 0.f; + } else if (tempdE > mindElim && tempdE <= maxdElim) { + const float arlim = 1.f / (mindElim - maxdElim); + const float brlim = - arlim * maxdElim; + const float reducdElim = pow(arlim * tempdE + brlim, iterat); + const float aalim = (1.f - reducdElim) / 20.f; + const float bblim = 1.f - 100.f * aalim; + reducdE = aalim * scope + bblim; + } else { + reducdE = 1.f; + } + } + +// if(scope == 100) reducdE = 1.f; + rdE[y][x] = reducdE ; + } + } +} + + static void deltaEforLaplace(float *dE, const local_params& lp, int bfw, int bfh, LabImage* bufexporig, const float hueref, const float chromaref, const float lumaref) { @@ -2094,7 +3455,7 @@ static void deltaEforLaplace(float *dE, const local_params& lp, int bfw, int bfh } -static void showmask(const local_params& lp, int xstart, int ystart, int cx, int cy, int bfw, int bfh, LabImage* bufexporig, LabImage* transformed, LabImage* bufmaskorigSH) +static void showmask(int lumask, const local_params& lp, int xstart, int ystart, int cx, int cy, int bfw, int bfh, LabImage* bufexporig, LabImage* transformed, LabImage* bufmaskorigSH, int inv) { #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) @@ -2115,31 +3476,980 @@ static void showmask(const local_params& lp, int xstart, int ystart, int cx, int calcTransitionrect(lox, loy, achm, lp, zone, localFactor); } - if (zone > 0) { - transformed->L[y + ystart][x + xstart] = 6000.f + CLIPLOC(bufmaskorigSH->L[y][x]); - transformed->a[y + ystart][x + xstart] = bufexporig->a[y][x] * bufmaskorigSH->a[y][x]; - transformed->b[y + ystart][x + xstart] = bufexporig->b[y][x] * bufmaskorigSH->b[y][x]; + if (inv == 0) { + if (zone > 0) {//normal + transformed->L[y + ystart][x + xstart] = (lumask * 400.f) + CLIPLOC(bufmaskorigSH->L[y][x]); + transformed->a[y + ystart][x + xstart] = bufexporig->a[y][x] * bufmaskorigSH->a[y][x]; + transformed->b[y + ystart][x + xstart] = bufexporig->b[y][x] * bufmaskorigSH->b[y][x]; + } + } else if (inv == 1) { //inverse + if (zone == 0) { + transformed->L[y + ystart][x + xstart] = (lumask * 400.f) + CLIPLOC(bufmaskorigSH->L[y][x]); + transformed->a[y + ystart][x + xstart] = bufexporig->a[y][x] * bufmaskorigSH->a[y][x]; + transformed->b[y + ystart][x + xstart] = bufexporig->b[y][x] * bufmaskorigSH->b[y][x]; + } } } } } +void ImProcFunctions::discrete_laplacian_threshold(float * data_out, const float * data_in, size_t nx, size_t ny, float t) +{ + BENCHFUN -void ImProcFunctions::InverseSharp_Local(float **loctemp, const float hueref, const float lumaref, const float chromaref, const local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) + size_t i, j; + float *ptr_out; + float diff = 0.f; + /* pointers to the current and neighbour values */ + const float *ptr_in, *ptr_in_xm1, *ptr_in_xp1, *ptr_in_ym1, *ptr_in_yp1; + + if (NULL == data_in || NULL == data_out) { + fprintf(stderr, "a pointer is NULL and should not be so\n"); + abort(); + } + + /* pointers to the data and neighbour values */ + /* + * y-1 + * x-1 ptr x+1 + * y+1 + * <---------------------nx-------> + */ + ptr_in = data_in; + ptr_in_xm1 = data_in - 1; + ptr_in_xp1 = data_in + 1; + ptr_in_ym1 = data_in - nx; + ptr_in_yp1 = data_in + nx; + ptr_out = data_out; + + for (j = 0; j < ny; j++) { + for (i = 0; i < nx; i++) { + *ptr_out = 0.f; + + /* row differences */ + if (0 < i) { + diff = *ptr_in - *ptr_in_xm1; + + if (fabs(diff) > t) { + *ptr_out += diff; + } + } + + if (nx - 1 > i) { + diff = *ptr_in - *ptr_in_xp1; + + if (fabs(diff) > t) { + *ptr_out += diff; + } + } + + /* column differences */ + if (0 < j) { + diff = *ptr_in - *ptr_in_ym1; + + if (fabs(diff) > t) { + *ptr_out += diff; + } + } + + if (ny - 1 > j) { + diff = *ptr_in - *ptr_in_yp1; + + if (fabs(diff) > t) { + *ptr_out += diff; + } + } + + ptr_in++; + ptr_in_xm1++; + ptr_in_xp1++; + ptr_in_ym1++; + ptr_in_yp1++; + ptr_out++; + } + } + +} + +double *ImProcFunctions::cos_table(size_t size) +{ + double *table = NULL; + double pi_size; + size_t i; + + /* allocate the cosinus table */ + if (NULL == (table = (double *) malloc(sizeof(double) * size))) { + fprintf(stderr, "allocation error\n"); + abort(); + } + + /* + * fill the cosinus table, + * table[i] = cos(i Pi / n) for i in [0..n[ + */ + pi_size = rtengine::RT_PI / size; + + for (i = 0; i < size; i++) { + table[i] = cos(pi_size * i); + } + + return table; +} + + +void ImProcFunctions::rex_poisson_dct(float * data, size_t nx, size_t ny, double m) +{ + /* + * Copyright 2009-2011 IPOL Image Processing On Line http://www.ipol.im/ + * + + * @file retinex_pde_lib.c discrete Poisson equation + * @brief laplacian, DFT and Poisson routines + * + * @author Nicolas Limare + * some adaptations for Rawtherapee + */ + BENCHFUN + + double *cosx = NULL, *cosy = NULL; + size_t i; + double m2; + + /* + * get the cosinus tables + * cosx[i] = cos(i Pi / nx) for i in [0..nx[ + * cosy[i] = cos(i Pi / ny) for i in [0..ny[ + */ + + cosx = cos_table(nx); + cosy = cos_table(ny); + + /* + * we will now multiply data[i, j] by + * m / (4 - 2 * cosx[i] - 2 * cosy[j])) + * and set data[0, 0] to 0 + */ + m2 = m / 2.; + /* + * handle the first value, data[0, 0] = 0 + * after that, by construction, we always have + * cosx[] + cosy[] != 2. + */ + data[0] = 0.; + + /* + * continue with all the array: + * i % nx is the position on the x axis (column number) + * i / nx is the position on the y axis (row number) + */ + for (i = 1; i < nx * ny; i++) { + data[i] *= m2 / (2. - cosx[i % nx] - cosy[i / nx]); + } + + free(cosx); + free(cosy); + +} + +void ImProcFunctions::mean_dt(const float * data, size_t size, double * mean_p, double * dt_p) +{ + double mean, dt; + const float *ptr_data; + size_t i; + + mean = 0.; + dt = 0.; + ptr_data = data; + + for (i = 0; i < size; i++) { + mean += *ptr_data; + dt += (*ptr_data) * (*ptr_data); + ptr_data++; + } + + mean /= (double) size; + dt /= (double) size; + dt -= (mean * mean); + dt = sqrt(dt); + + *mean_p = mean; + *dt_p = dt; + +} + +void ImProcFunctions::normalize_mean_dt(float * data, float * ref, size_t size, float mod, float sigm) +{ + /* + * Copyright 2009-2011 IPOL Image Processing On Line http://www.ipol.im/ + * + + * @file retinex_pde_lib.c discrete Poisson equation + * @brief laplacian, DFT and Poisson routines + * + * @author Nicolas Limare + * adapted for Rawtherapee - jacques Desmis july 2019 + */ + + double mean_ref, mean_data, dt_ref, dt_data; + double a, b; + size_t i; + float *ptr_data; + float *ptr_dataold; + + if (NULL == data || NULL == ref) { + fprintf(stderr, "a pointer is NULL and should not be so\n"); + abort(); + } + + /* compute mean and variance of the two arrays */ + mean_dt(ref, size, &mean_ref, &dt_ref); + mean_dt(data, size, &mean_data, &dt_data); + + /* compute the normalization coefficients */ + a = dt_ref / dt_data; + b = mean_ref - a * mean_data; + + /* normalize the array */ + ptr_data = data; + ptr_dataold = ref;//data; + + for (i = 0; i < size; i++) { + *ptr_data = mod * (a * *ptr_data + sigm * b) + (1.f - mod) * *ptr_dataold;//normalize mean and stdv and balance PDE + ptr_data++; + } + +} + +void ImProcFunctions::retinex_pde(float * datain, float * dataout, int bfw, int bfh, float thresh, float multy, float * dE, int show, int dEenable, int normalize) +{ + /* + * Copyright 2009-2011 IPOL Image Processing On Line http://www.ipol.im/ + * + + * @file retinex_pde_lib.c discrete Poisson equation + * @brief laplacian, DFT and Poisson routines + * + * @author Nicolas Limare + * adapted for Rawtherapee by Jacques Desmis 6-2019 + */ + + BENCHFUN +#ifdef _OPENMP + + if (multiThread) { + fftwf_init_threads(); + fftwf_plan_with_nthreads(omp_get_max_threads()); + } + +#endif + fftwf_plan dct_fw, dct_fw04, dct_bw; + float *data_fft, *data_fft04, *data_tmp, *data, *data_tmp04; + float *datashow = nullptr; + + if (show != 0) { + if (NULL == (datashow = (float *) fftwf_malloc(sizeof(float) * bfw * bfh))) { + fprintf(stderr, "allocation error\n"); + abort(); + } + } + + if (NULL == (data_tmp = (float *) fftwf_malloc(sizeof(float) * bfw * bfh))) { + fprintf(stderr, "allocation error\n"); + abort(); + } + + if (NULL == (data_tmp04 = (float *) fftwf_malloc(sizeof(float) * bfw * bfh))) { + fprintf(stderr, "allocation error\n"); + abort(); + } + + //first call to laplacian with plein strength + ImProcFunctions::discrete_laplacian_threshold(data_tmp, datain, bfw, bfh, thresh); + + if (NULL == (data_fft = (float *) fftwf_malloc(sizeof(float) * bfw * bfh))) { + fprintf(stderr, "allocation error\n"); + abort(); + } + + if (show == 1) { + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + datashow[y * bfw + x] = data_tmp[y * bfw + x]; + } + } + } + + //second call to laplacian with 40% strength ==> reduce effect if we are far from ref (deltaE) + ImProcFunctions::discrete_laplacian_threshold(data_tmp04, datain, bfw, bfh, 0.4f * thresh); + + if (NULL == (data_fft04 = (float *) fftwf_malloc(sizeof(float) * bfw * bfh))) { + fprintf(stderr, "allocation error\n"); + abort(); + } + + if (NULL == (data = (float *) fftwf_malloc(sizeof(float) * bfw * bfh))) { + fprintf(stderr, "allocation error\n"); + abort(); + } + + //execute first + dct_fw = fftwf_plan_r2r_2d(bfh, bfw, data_tmp, data_fft, FFTW_REDFT10, FFTW_REDFT10, FFTW_ESTIMATE | FFTW_DESTROY_INPUT); + fftwf_execute(dct_fw); + + //execute second + if (dEenable == 1) { + dct_fw04 = fftwf_plan_r2r_2d(bfh, bfw, data_tmp04, data_fft04, FFTW_REDFT10, FFTW_REDFT10, FFTW_ESTIMATE | FFTW_DESTROY_INPUT); + fftwf_execute(dct_fw04); + } + + if (dEenable == 1) { +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < bfh ; y++) {//mix two fftw Laplacian : plein if dE near ref + for (int x = 0; x < bfw; x++) { + float prov = pow(dE[y * bfw + x], 4.5f); + data_fft[y * bfw + x] = prov * data_fft[y * bfw + x] + (1.f - prov) * data_fft04[y * bfw + x]; + } + } + } + + if (show == 2) { + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + datashow[y * bfw + x] = data_fft[y * bfw + x]; + } + } + } + + fftwf_free(data_fft04); + fftwf_free(data_tmp); + fftwf_free(data_tmp04); + + if (dEenable == 1) { + fftwf_destroy_plan(dct_fw04); + } + + /* solve the Poisson PDE in Fourier space */ + /* 1. / (float) (bfw * bfh)) is the DCT normalisation term, see libfftw */ + ImProcFunctions::rex_poisson_dct(data_fft, bfw, bfh, 1. / (double)(bfw * bfh)); + + if (show == 3) { + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + datashow[y * bfw + x] = data_fft[y * bfw + x]; + } + } + } + + dct_bw = fftwf_plan_r2r_2d(bfh, bfw, data_fft, data, FFTW_REDFT01, FFTW_REDFT01, FFTW_ESTIMATE | FFTW_DESTROY_INPUT); + fftwf_execute(dct_bw); + fftwf_destroy_plan(dct_fw); + fftwf_destroy_plan(dct_bw); + fftwf_free(data_fft); + fftwf_cleanup(); + + if (multiThread) { + fftwf_cleanup_threads(); + } + + if (show != 4 && normalize == 1) { + normalize_mean_dt(data, datain, bfw * bfh, 1.f, 1.f); + } + + if (show == 0 || show == 4) { + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + dataout[y * bfw + x] = CLIPLOC(multy * data[y * bfw + x]); + } + } + } else if (show == 1 || show == 2 || show == 3) { + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + dataout[y * bfw + x] = CLIPLOC(multy * datashow[y * bfw + x]); + } + } + + fftwf_free(datashow); + } + + fftwf_free(data); + +} + +void ImProcFunctions::maskcalccol(int call, bool invmask, bool pde, int bfw, int bfh, int xstart, int ystart, int sk, int cx, int cy, LabImage* bufcolorig, LabImage* bufmaskblurcol, LabImage* originalmaskcol, LabImage* original, LabImage* reserved, int inv, struct local_params & lp, + float strumask, bool astool, + const LocCCmaskCurve & locccmasCurve, bool & lcmasutili, + const LocLLmaskCurve & locllmasCurve, bool & llmasutili, + const LocHHmaskCurve & lochhmasCurve, bool &lhmasutili, const LocHHmaskCurve & lochhhmasCurve, bool &lhhmasutili, + bool multiThread, bool enaMask, bool showmaske, bool deltaE, bool modmask, bool zero, bool modif, float chrom, float rad, float lap, float gamma, float slope, float blendm, int shado, float amountcd, float anchorcd, + LUTf & lmasklocalcurve, bool & localmaskutili, + const LocwavCurve & loclmasCurvecolwav, bool & lmasutilicolwav, int level_bl, int level_hl, int level_br, int level_hr, + int shortcu, bool delt, const float hueref, const float chromaref, const float lumaref, + float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope + ) +{ + array2D ble(bfw, bfh); + array2D blechro(bfw, bfh); + array2D hue(bfw, bfh); + array2D guid(bfw, bfh); + std::unique_ptr bufreserv(new LabImage(bfw, bfh)); + float meanfab, fab; + mean_fab(xstart, ystart, bfw, bfh, bufcolorig, original, fab, meanfab, chrom); + float chromult = 1.f - 0.01f * chrom; + float kinv = 1.f; + float kneg = 1.f; + + if (invmask) { + kinv = 0.f; + kneg = -1.f; + } + + if (deltaE || modmask || enaMask || showmaske) { + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh; y++) { + for (int x = 0; x < bfw; x++) { + bufmaskblurcol->L[y][x] = original->L[y + ystart][x + xstart]; + bufmaskblurcol->a[y][x] = original->a[y + ystart][x + xstart]; + bufmaskblurcol->b[y][x] = original->b[y + ystart][x + xstart]; + bufreserv->L[y][x] = reserved->L[y + ystart][x + xstart]; + bufreserv->a[y][x] = reserved->a[y + ystart][x + xstart]; + bufreserv->b[y][x] = reserved->b[y + ystart][x + xstart]; + } + } + + JaggedArray blendstru(bfw, bfh); + + if (lp.blurcolmask >= 0.25f && strumask == 0.f) { + strumask = 0.1f; // to enable a small mask make FFT good ...why ?? + } + + if (strumask > 0.f) { + float delstrumask = 4.1f - strumask;//4.1 = 2 * max slider strumask + 0.1 + buildBlendMask(bufcolorig->L, blendstru, bfw, bfh, delstrumask); + float radblur = 0.02f * fabs(0.1f * rad);//empirical value + float rm = radblur / sk; + + if (rm > 0) { + float **mb = blendstru; + gaussianBlur(mb, mb, bfw, bfh, rm); + } + + } + + JaggedArray blendblur(bfw, bfh); + + JaggedArray blur(bfw, bfh); + + if (lp.contcolmask > 0.f) { + float contra = lp.contcolmask; + buildBlendMask(bufcolorig->L, blendblur, bfw, bfh, contra); + + + float radblur = 0.25f + 0.002f * fabs(rad);//empirical value + float rm = radblur / sk; + + if (lp.fftColorMask) { + if (rm < 0.3f) { + rm = 0.3f; + } + } + + if (rm > 0) { + float **mb = blendblur; + gaussianBlur(mb, mb, bfw, bfh, rm); + } + + if (lp.blurcolmask >= 0.25f) { + if (!lp.fftColorMask) { // || (lp.fftColorMask && call != 2)) { + printf("call=%i\n", call); + gaussianBlur(bufcolorig->L, blur, bfw, bfh, lp.blurcolmask / sk); + } else { + ImProcFunctions::fftw_convol_blur2(bufcolorig->L, blur, bfw, bfh, lp.blurcolmask / sk, 0, 0); + } + + for (int i = 0; i < bfh; i++) { + for (int j = 0; j < bfw; j++) { + blur[i][j] = intp(blendblur[i][j], bufcolorig->L[i][j], std::max(blur[i][j], 0.0f)); + } + } + } + } + + bool HHmaskcurve = false; + + if (lochhhmasCurve && lhhmasutili) { + for (int i = 0; i < 500; i++) { + if (lochhhmasCurve[i] != 0.5) { + HHmaskcurve = true; + } + } + } + +#ifdef _OPENMP + #pragma omp parallel +#endif + { +#ifdef __SSE2__ + float atan2Buffer[bfw] ALIGNED64; +// float atan2BufferH[bfw] ALIGNED64; +#endif +#ifdef _OPENMP + #pragma omp for schedule(dynamic, 16) +#endif + + for (int ir = 0; ir < bfh; ir++) { +#ifdef __SSE2__ + + if (lochhmasCurve && lhmasutili) { + int i = 0; + + for (; i < bfw - 3; i += 4) { + STVF(atan2Buffer[i], xatan2f(LVFU(bufcolorig->b[ir][i]), LVFU(bufcolorig->a[ir][i]))); + } + + for (; i < bfw; i++) { + atan2Buffer[i] = xatan2f(bufcolorig->b[ir][i], bufcolorig->a[ir][i]); + } + } + +#endif + + for (int jr = 0; jr < bfw; jr++) { + float kmaskL = 0.f; + float kmaskC = 0.f; + float kmaskHL = 0.f; + float kmaskH = 0.f; + float kmasstru = 0.f; + float kmasblur = 0.f; + // float kmaskHH = 0.f; + // float huemah; + // float newhr = 0.f; + // float2 sincosval; + + if (strumask > 0.f && !astool) { + kmasstru = bufcolorig->L[ir][jr] * blendstru[ir][jr]; + } + + if (lp.contcolmask > 0.f) { + + if (lp.blurcolmask >= 0.25f) { + + float prov = intp(blendstru[ir][jr], bufcolorig->L[ir][jr], max(blur[ir][jr], 0.0f)); + kmasblur = bufcolorig->L[ir][jr] - prov ; + + } + } + + if (locllmasCurve && llmasutili) { + kmaskL = 32768.f * LIM01(kinv - kneg * locllmasCurve[(500.f / 32768.f) * bufcolorig->L[ir][jr]]); + + } + + if (!deltaE && locccmasCurve && lcmasutili) { + kmaskC = LIM01(kinv - kneg * locccmasCurve[500.f * (0.0001f + sqrt(SQR(bufcolorig->a[ir][jr]) + SQR(bufcolorig->b[ir][jr])) / fab)]); + } + + if (lochhmasCurve && lhmasutili) { +#ifdef __SSE2__ + const float huema = atan2Buffer[jr]; +#else + const float huema = xatan2f(bufcolorig->b[ir][jr], bufcolorig->a[ir][jr]); +#endif + float h = Color::huelab_to_huehsv2(huema); + h += 1.f / 6.f; + + if (h > 1.f) { + h -= 1.f; + } + + const float valHH = LIM01(kinv - kneg * lochhmasCurve[500.f * h]); + + if (!deltaE) { + kmaskH = valHH; + } + + kmaskHL = 32768.f * valHH; + + + } + + /* + //keep here in case of...but !! + if (lochhhmasCurve && HHmaskcurve) { + + #ifdef __SSE2__ + huemah = atan2BufferH[jr]; + #else + huemah = xatan2f(bufcolorig->b[ir][jr], bufcolorig->a[ir][jr]); + #endif + + float hh = Color::huelab_to_huehsv2(huemah); + hh += 1.f / 6.f; + + if (hh > 1.f) { + hh -= 1.f; + } + + const float val_HH = float (LIM01(((0.5f - lochhhmasCurve[500.f * hh])))); + kmaskHH = 2.f * val_HH; + const float hhro = kmaskHH; + + if (hhro != 0) { + newhr = huemah + hhro; + + if (newhr > rtengine::RT_PI_F) { + newhr -= 2 * rtengine::RT_PI_F; + } else if (newhr < -rtengine::RT_PI_F) { + newhr += 2 * rtengine::RT_PI_F; + } + } + sincosval = xsincosf(newhr); + + } + */ + bufmaskblurcol->L[ir][jr] = CLIPLOC(kmaskL + kmaskHL + kmasstru + kmasblur); +// if(HHmaskcurve) { +// bufmaskblurcol->a[ir][jr] = CLIPC((kmaskC + chromult * kmaskH) * sincosval.y); +// bufmaskblurcol->b[ir][jr] = CLIPC((kmaskC + chromult * kmaskH) * sincosval.x); +// } else { + bufmaskblurcol->a[ir][jr] = CLIPC((kmaskC + chromult * kmaskH)); + bufmaskblurcol->b[ir][jr] = CLIPC((kmaskC + chromult * kmaskH)); +// } + + if (shortcu == 1) { //short circuit all L curve + bufmaskblurcol->L[ir][jr] = 32768.f - bufcolorig->L[ir][jr]; + } + + ble[ir][jr] = bufmaskblurcol->L[ir][jr] / 32768.f; + hue[ir][jr] = xatan2f(bufmaskblurcol->b[ir][jr], bufmaskblurcol->a[ir][jr]); + float chromah = sqrt(SQR(bufmaskblurcol->b[ir][jr]) + SQR(bufmaskblurcol->a[ir][jr])); + + blechro[ir][jr] = chromah / 32768.f;//must be good perhaps more or less, only incidence on LIM blea bleb + float X, Y, Z; + float L = bufcolorig->L[ir][jr]; + float a = bufcolorig->a[ir][jr]; + float b = bufcolorig->b[ir][jr]; + Color::Lab2XYZ(L, a, b, X, Y, Z); + + guid[ir][jr] = Y / 32768.f; + + } + } + } + + std::unique_ptr bufprov(new LabImage(bfw, bfh)); + + bufprov->CopyFrom(bufmaskblurcol); + + + + if (rad != 0.f) { + float blur = rad; + blur = blur < 0.f ? -1.f / blur : 1.f + blur; + int r1 = max(int(4 / sk * blur + 0.5), 1); + int r2 = max(int(25 / sk * blur + 0.5), 1); + + double epsilmax = 0.0005; + double epsilmin = 0.00001; + + double aepsil = (epsilmax - epsilmin) / 90.f; + double bepsil = epsilmax - 100.f * aepsil; + double epsil = aepsil * 0.1 * rad + bepsil; + + if (rad < 0.f) { + epsil = 0.001; + } + + rtengine::guidedFilter(guid, blechro, blechro, r1, epsil, multiThread); + rtengine::guidedFilter(guid, ble, ble, r2, 0.2 * epsil, multiThread); + } + + LUTf lutTonemaskexp(65536); + calcGammaLut(gamma, slope, lutTonemaskexp); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) { + for (int jr = 0; jr < bfw; jr++) { + float2 sincosval = xsincosf(hue[ir][jr]); + bufmaskblurcol->L[ir][jr] = lutTonemaskexp[LIM01(ble[ir][jr]) * 65536.f]; + bufmaskblurcol->a[ir][jr] = 32768.f * sincosval.y * blechro[ir][jr]; + bufmaskblurcol->b[ir][jr] = 32768.f * sincosval.x * blechro[ir][jr]; + } + } + + + if (strumask > 0.f && astool) { + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) { + for (int jr = 0; jr < bfw; jr++) { + bufmaskblurcol->L[ir][jr] *= (1.f + blendstru[ir][jr]); + } + } + + } + + if (lmasklocalcurve && localmaskutili) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + bufmaskblurcol->L[ir][jr] = 0.5f * lmasklocalcurve[2.f * bufmaskblurcol->L[ir][jr]]; + } + } + + if (shado > 0) { + ImProcFunctions::shadowsHighlights(bufmaskblurcol, true, 1, 0, shado, 40, sk, 0, 60); + } + + int wavelet_level = level_br; + + int minwin = min(bfw, bfh); + int maxlevelspot = 9; + + while ((1 << maxlevelspot) >= (minwin * sk) && maxlevelspot > 1) { + --maxlevelspot ; + } + + wavelet_level = min(wavelet_level, maxlevelspot); + int maxlvl; + float contrast = 0.f; + bool wavcurvemask = false; + + if (loclmasCurvecolwav && lmasutilicolwav) { + for (int i = 0; i < 500; i++) { + if (loclmasCurvecolwav[i] != 0.5) { + wavcurvemask = true; + } + } + } + + if (wavcurvemask) { +#ifdef _OPENMP + const int numThreads = omp_get_max_threads(); +#else + const int numThreads = 1; + +#endif + LocwavCurve dummy; + bool loclevwavutili = false; + bool wavcurvelev = false; + bool locconwavutili = false; + bool wavcurvecon = false; + bool loccompwavutili = false; + bool wavcurvecomp = false; + bool loccomprewavutili = false; + bool wavcurvecompre = false; + bool wavcurve = false; + bool locedgwavutili = false; + wavcontrast4(lp, bufmaskblurcol->L, nullptr, nullptr, contrast, 0.f, 0.f, 0.f, bfw, bfh, level_bl, level_hl, level_br, level_hr, sk, numThreads, loclmasCurvecolwav, lmasutilicolwav, wavcurve, dummy, loclevwavutili, wavcurvelev, dummy, locconwavutili, wavcurvecon, dummy, loccompwavutili, wavcurvecomp, dummy, loccomprewavutili, wavcurvecompre, dummy, locedgwavutili, 1.f, 1.f, maxlvl, 0.f, 0.f, 1.f, 1.f, false, false, false, false, false, 0.f, 0.f); + + } + + if (lochhhmasCurve && HHmaskcurve) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + float huemah = xatan2f(bufmaskblurcol->b[ir][jr], bufmaskblurcol->a[ir][jr]); + float chromah = sqrt(SQR(bufmaskblurcol->b[ir][jr]) + SQR(bufmaskblurcol->a[ir][jr])); + + + float hh = Color::huelab_to_huehsv2(huemah); + hh += 1.f / 6.f; + + if (hh > 1.f) { + hh -= 1.f; + } + + const float val_HH = float ((0.5f - lochhhmasCurve[500.f * hh])); + const float hhro = 1.5f * val_HH; + float newhr; + + if (hhro != 0) { + newhr = huemah + hhro;//we add radians and other dim between 0 1.. always radians but addition "false" + + if (newhr > rtengine::RT_PI_F) { + newhr -= 2 * rtengine::RT_PI_F; + } else if (newhr < -rtengine::RT_PI_F) { + newhr += 2 * rtengine::RT_PI_F; + } + } + + float2 sincosval = xsincosf(newhr); + bufmaskblurcol->a[ir][jr] = CLIPC(chromah * sincosval.y); + bufmaskblurcol->b[ir][jr] = CLIPC(chromah * sincosval.x); + + } + } + + if (amountcd > 1.f) { //dynamic range compression for Mask + FattalToneMappingParams fatParams; + fatParams.enabled = true; + fatParams.threshold = 100.f; + fatParams.amount = amountcd; + fatParams.anchor = anchorcd; + int nlev = 1; + Imagefloat *tmpImagefat = nullptr; + tmpImagefat = new Imagefloat(bfw, bfh); + lab2rgb(*bufmaskblurcol, *tmpImagefat, params->icm.workingProfile); + ToneMapFattal02(tmpImagefat, fatParams, nlev, 0, nullptr, 0, 0, 0); + rgb2lab(*tmpImagefat, *bufmaskblurcol, params->icm.workingProfile); + delete tmpImagefat; + } + + if (delt) { + std::unique_ptr> rdEBuffer(new JaggedArray(bfw, bfh)); + float** rdE = *(rdEBuffer.get()); + + deltaEforMask(rdE, bfw, bfh, bufreserv.get(), hueref, chromaref, lumaref, maxdE, mindE, maxdElim, mindElim, iterat, limscope, scope, lp.balance, lp.balanceh); + std::unique_ptr delta(new LabImage(bfw, bfh)); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + delta->L[ir][jr] = bufmaskblurcol->L[ir][jr] - bufprov->L[ir][jr]; + delta->a[ir][jr] = bufmaskblurcol->a[ir][jr] - bufprov->a[ir][jr]; + delta->b[ir][jr] = bufmaskblurcol->b[ir][jr] - bufprov->b[ir][jr]; + + bufmaskblurcol->L[ir][jr] = bufprov->L[ir][jr] + rdE[ir][jr] * delta->L[ir][jr]; + bufmaskblurcol->a[ir][jr] = bufprov->a[ir][jr] + rdE[ir][jr] * delta->a[ir][jr]; + bufmaskblurcol->b[ir][jr] = bufprov->b[ir][jr] + rdE[ir][jr] * delta->b[ir][jr]; + } + + rdEBuffer.reset(); + + } + + struct grad_params gp; + + if (lp.strmaexp != 0.f) { + calclocalGradientParams(lp, gp, ystart, xstart, bfw, bfh, 0); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + double factor = 1.0; + factor = ImProcFunctions::calcGradientFactor(gp, jr, ir); + bufmaskblurcol->L[ir][jr] *= factor; + } + } + + + if (lap > 0.f) { + float *datain = new float[bfh * bfw]; + float *data_tmp = new float[bfh * bfw]; + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < bfh; y++) { + for (int x = 0; x < bfw; x++) { + datain[y * bfw + x] = bufmaskblurcol->L[y][x]; + } + } + + if (!pde) { + ImProcFunctions::discrete_laplacian_threshold(data_tmp, datain, bfw, bfh, 200.f * lap); + } else { + ImProcFunctions::retinex_pde(datain, data_tmp, bfw, bfh, 12.f * lap, 1.f, nullptr, 0, 0, 1); + } + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < bfh; y++) { + for (int x = 0; x < bfw; x++) { + bufmaskblurcol->L[y][x] = data_tmp[y * bfw + x]; + } + } + + delete [] datain; + delete [] data_tmp; + + } + } + + const float radiusb = 1.f / sk; + + if (deltaE || modmask || enaMask || showmaske) { +#ifdef _OPENMP + #pragma omp parallel +#endif + { + gaussianBlur(bufmaskblurcol->L, bufmaskblurcol->L, bfw, bfh, radiusb); + gaussianBlur(bufmaskblurcol->a, bufmaskblurcol->a, bfw, bfh, 1.f + (0.5f * rad) / sk); + gaussianBlur(bufmaskblurcol->b, bufmaskblurcol->b, bfw, bfh, 1.f + (0.5f * rad) / sk); + } + + if (zero || modif || modmask || deltaE || enaMask) { + originalmaskcol->CopyFrom(bufcolorig); + blendmask(lp, xstart, ystart, cx, cy, bfw, bfh, bufcolorig, original, bufmaskblurcol, originalmaskcol, blendm, inv); + } + } +} + +void ImProcFunctions::InverseSharp_Local(float **loctemp, const float hueref, const float lumaref, const float chromaref, local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) { //local sharp // BENCHFUN const float ach = (float)lp.trans / 100.f; int GW = transformed->W; int GH = transformed->H; - float refa = chromaref * cos(hueref); - float refb = chromaref * sin(hueref); + const float refa = chromaref * cos(hueref) * 327.68f; + const float refb = chromaref * sin(hueref) * 327.68f; + const float refL = lumaref * 327.68f; //balance deltaE float kL = lp.balance; float kab = 1.f; + float kH = lp.balanceh; + float kch = 1.f; balancedeltaE(kL, kab); + balancedeltaEH(kH, kch); + kab /= SQR(327.68f); + kL /= SQR(327.68f); + const bool sharshow = (lp.showmasksharmet == 1); + const bool previewshar = (lp.showmasksharmet == 2); - LabImage *origblur = new LabImage(GW, GH); + if (lp.colorde == 0) { + lp.colorde = -1;//to avoid black + } + + float ampli = 1.f + fabs(lp.colorde); + ampli = 2.f + 0.5f * (ampli - 2.f); + + float darklim = 5000.f; + float aadark = -1.f; + float bbdark = darklim; + + std::unique_ptr origblur(new LabImage(GW, GH)); float radius = 3.f / sk; #ifdef _OPENMP @@ -2180,16 +4490,42 @@ void ImProcFunctions::InverseSharp_Local(float **loctemp, const float hueref, co calcTransitionrect(lox, loy, ach, lp, zone, localFactor); } - float rL = origblur->L[y][x] / 327.68f; float reducdE = 0.f; - float dE = sqrt(kab * SQR(refa - origblur->a[y][x] / 327.68f) + kab * SQR(refb - origblur->b[y][x] / 327.68f) + kL * SQR(lumaref - rL)); + float reducview = 0.f; + float abdelta2 = SQR(refa - origblur->a[y][x]) + SQR(refb - origblur->b[y][x]); + float chrodelta2 = SQR(sqrt(SQR(origblur->a[y][x]) + SQR(origblur->b[y][x])) - (chromaref * 327.68f)); + float huedelta2 = abdelta2 - chrodelta2; + float dE = sqrt(kab * (kch * chrodelta2 + kH * huedelta2) + kL * SQR(refL - origblur->L[y][x])); + calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, lp.senssha, reducdE); + reducview = reducdE; switch (zone) { case 0: { // outside selection and outside transition zone => full effect, no transition float difL = loctemp[y][x] - original->L[y][x]; transformed->L[y][x] = CLIP(original->L[y][x] + difL * reducdE); + if (sharshow) { + transformed->a[y][x] = 0.f; + transformed->b[y][x] = ampli * 5.f * difL * reducdE; + } else if (previewshar) { + float difbdisp = reducview * 10000.f * lp.colorde; + + if (transformed->L[y][x] < darklim) { //enhance dark luminance as user can see! + float dark = transformed->L[y][x]; + transformed->L[y][x] = dark * aadark + bbdark; + } + + if (lp.colorde <= 0) { + transformed->a[y][x] = 0.f; + transformed->b[y][x] = difbdisp; + } else { + transformed->a[y][x] = -difbdisp; + transformed->b[y][x] = 0.f; + } + + } + break; } @@ -2200,6 +4536,28 @@ void ImProcFunctions::InverseSharp_Local(float **loctemp, const float hueref, co difL *= factorx; transformed->L[y][x] = CLIP(original->L[y][x] + difL * reducdE); + + if (sharshow) { + transformed->a[y][x] = 0.f; + transformed->b[y][x] = ampli * 5.f * difL * reducdE; + } else if (previewshar) { + float difbdisp = reducview * 10000.f * lp.colorde; + + if (transformed->L[y][x] < darklim) { //enhance dark luminance as user can see! + float dark = transformed->L[y][x]; + transformed->L[y][x] = dark * aadark + bbdark; + } + + if (lp.colorde <= 0) { + transformed->a[y][x] = 0.f; + transformed->b[y][x] = difbdisp; + } else { + transformed->a[y][x] = -difbdisp; + transformed->b[y][x] = 0.f; + } + + } + break; } @@ -2210,23 +4568,40 @@ void ImProcFunctions::InverseSharp_Local(float **loctemp, const float hueref, co } } } - delete origblur; } -void ImProcFunctions::Sharp_Local(int call, float **loctemp, int senstype, const float hueref, const float chromaref, const float lumaref, const local_params &lp, LabImage *original, LabImage *transformed, int cx, int cy, int sk) +void ImProcFunctions::Sharp_Local(int call, float **loctemp, int senstype, const float hueref, const float chromaref, const float lumaref, local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) { BENCHFUN const float ach = lp.trans / 100.f; const float varsens = senstype == 1 ? lp.senslc : lp.senssha; + const bool sharshow = (lp.showmasksharmet == 1); + const bool previewshar = (lp.showmasksharmet == 2); + //balance deltaE //balance deltaE float kL = lp.balance; float kab = 1.f; + float kH = lp.balanceh; + float kch = 1.f; balancedeltaE(kL, kab); + balancedeltaEH(kH, kch); + kab /= SQR(327.68f); kL /= SQR(327.68f); + if (lp.colorde == 0) { + lp.colorde = -1;//to avoid black + } + + float ampli = 1.f + fabs(lp.colorde); + ampli = 2.f + 0.5f * (ampli - 2.f); + + float darklim = 5000.f; + float aadark = -1.f; + float bbdark = darklim; + const int GW = transformed->W; const int GH = transformed->H; @@ -2284,10 +4659,18 @@ void ImProcFunctions::Sharp_Local(int call, float **loctemp, int senstype, const continue; } - const float dE = sqrt(kab * (SQR(refa - origblur->a[y][x]) + SQR(refb - origblur->b[y][x])) + kL * SQR(refL - origblur->L[y][x])); + //deltaE + float abdelta2 = SQR(refa - origblur->a[y][x]) + SQR(refb - origblur->b[y][x]); + float chrodelta2 = SQR(sqrt(SQR(origblur->a[y][x]) + SQR(origblur->b[y][x])) - (chromaref * 327.68f)); + float huedelta2 = abdelta2 - chrodelta2; + + const float dE = sqrt(kab * (kch * chrodelta2 + kH * huedelta2) + kL * SQR(refL - origblur->L[y][x])); + float reducdE = 0.f; + float reducview = 0.f; calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, varsens, reducdE); + reducview = reducdE; reducdE *= localFactor; float difL; @@ -2299,6 +4682,27 @@ void ImProcFunctions::Sharp_Local(int call, float **loctemp, int senstype, const } transformed->L[y][x] = CLIP(original->L[y][x] + difL * reducdE); + + if (sharshow) { + transformed->a[y][x] = 0.f; + transformed->b[y][x] = ampli * 5.f * difL * reducdE; + } else if (previewshar) { + float difbdisp = reducview * 10000.f * lp.colorde; + + if (transformed->L[y][x] < darklim) { //enhance dark luminance as user can see! + float dark = transformed->L[y][x]; + transformed->L[y][x] = dark * aadark + bbdark; + } + + if (lp.colorde <= 0) { + transformed->a[y][x] = 0.f; + transformed->b[y][x] = difbdisp; + } else { + transformed->a[y][x] = -difbdisp; + transformed->b[y][x] = 0.f; + } + + } } } } @@ -2322,11 +4726,15 @@ void ImProcFunctions::Exclude_Local(float **deltaso, float hueref, float chromar const float refa = chromaref * cos(hueref) * 327.68f; const float refb = chromaref * sin(hueref) * 327.68f; - lumaref *= 327.68f; + const float refL = lumaref * 327.68f; + // lumaref *= 327.68f; //balance deltaE float kL = lp.balance; float kab = 1.f; + float kH = lp.balanceh; + float kch = 1.f; balancedeltaE(kL, kab); + balancedeltaEH(kH, kch); kL /= SQR(327.68f); kab /= SQR(327.68f); //sobel @@ -2336,7 +4744,7 @@ void ImProcFunctions::Exclude_Local(float **deltaso, float hueref, float chromar sobelref = log1p(sobelref); - LabImage *origblur = new LabImage(GW, GH); + std::unique_ptr origblur(new LabImage(GW, GH)); const float radius = 3.f / sk; @@ -2357,7 +4765,7 @@ void ImProcFunctions::Exclude_Local(float **deltaso, float hueref, float chromar for (int y = 0; y < transformed->H; y++) { const int loy = cy + y; - const bool isZone0 = loy > lp.yc + lp.ly || loy < lp.yc - lp.lyT; // whole line is zone 0 => we can skip a lot of processing + const bool isZone0 = loy > (lp.yc + lp.ly - 1) || loy < lp.yc - lp.lyT; // // -1 fix issue 5554 if (isZone0) { // outside selection and outside transition zone => no effect, keep original values for (int x = 0; x < transformed->W; x++) { @@ -2369,6 +4777,16 @@ void ImProcFunctions::Exclude_Local(float **deltaso, float hueref, float chromar for (int x = 0; x < transformed->W; x++) { const int lox = cx + x; + const bool isZone0x = lox > (lp.xc + lp.lx - 1) || lox < lp.xc - lp.lxL; // -1 fix issue 5554 + + if (isZone0x) { // outside selection and outside transition zone => no effect, keep original values + for (int x = 0; x < transformed->W; x++) { + transformed->L[y][x] = original->L[y][x]; + } + + continue; + } + const int begx = int (lp.xc - lp.lxL); const int begy = int (lp.yc - lp.lyT); @@ -2410,8 +4828,12 @@ void ImProcFunctions::Exclude_Local(float **deltaso, float hueref, float chromar } } + float abdelta2 = SQR(refa - origblur->a[y][x]) + SQR(refb - origblur->b[y][x]); + float chrodelta2 = SQR(sqrt(SQR(origblur->a[y][x]) + SQR(origblur->b[y][x])) - (chromaref * 327.68f)); + float huedelta2 = abdelta2 - chrodelta2; + const float dE = sqrt(kab * (kch * chrodelta2 + kH * huedelta2) + kL * SQR(refL - origblur->L[y][x])); const float rL = origblur->L[y][x]; - const float dE = sqrt(kab * SQR(refa - origblur->a[y][x]) + kab * SQR(refb - origblur->b[y][x]) + kL * SQR(lumaref - rL)); + float reducdE; calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, varsens, reducdE); @@ -2419,59 +4841,64 @@ void ImProcFunctions::Exclude_Local(float **deltaso, float hueref, float chromar const float affde = reducdE; if (rL > 32.768f) { //to avoid crash with very low gamut in rare cases ex : L=0.01 a=0.5 b=-0.9 - switch (zone) { + if (zone > 0) { - case 1: { // inside transition zone - const float difL = (rsv->L[loy - begy][lox - begx] - original->L[y][x]) * localFactor; - transformed->L[y][x] = CLIP(original->L[y][x] + difL * affsob * affde); + const float difL = (rsv->L[loy - begy][lox - begx] - original->L[y][x]) * localFactor; + transformed->L[y][x] = CLIP(original->L[y][x] + difL * affsob * affde); - const float difa = (rsv->a[loy - begy][lox - begx] - original->a[y][x]) * localFactor; - transformed->a[y][x] = CLIPC(original->a[y][x] + difa * affsob * affde); + const float difa = (rsv->a[loy - begy][lox - begx] - original->a[y][x]) * localFactor; + transformed->a[y][x] = CLIPC(original->a[y][x] + difa * affsob * affde); - const float difb = (rsv->b[loy - begy][lox - begx] - original->b[y][x]) * localFactor; - transformed->b[y][x] = CLIPC(original->b[y][x] + difb * affsob * affde); + const float difb = (rsv->b[loy - begy][lox - begx] - original->b[y][x]) * localFactor; + transformed->b[y][x] = CLIPC(original->b[y][x] + difb * affsob * affde); - break; - - } - - case 2: { // inside selection => full effect, no transition - const float difL = rsv->L[loy - begy][lox - begx] - original->L[y][x]; - transformed->L[y][x] = CLIP(original->L[y][x] + difL * affsob * affde); - - const float difa = rsv->a[loy - begy][lox - begx] - original->a[y][x];; - transformed->a[y][x] = CLIPC(original->a[y][x] + difa * affsob * affde); - - const float difb = rsv->b[loy - begy][lox - begx] - original->b[y][x]; - transformed->b[y][x] = CLIPC(original->b[y][x] + difb * affsob * affde); - } } } } } } - delete origblur; } } -void ImProcFunctions::transit_shapedetect_retinex(int senstype, LabImage * bufexporig, LabImage * bufmask, LabImage * buforigmas, float **buflight, float **bufchro, const float hueref, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) + + +void ImProcFunctions::transit_shapedetect_retinex(int call, int senstype, LabImage * bufexporig, LabImage * bufmask, LabImage * buforigmas, float **buflight, float **bufchro, const float hueref, const float chromaref, const float lumaref, const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) { BENCHFUN { + const int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); + const int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); + const int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); + const int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); + + const float ach = (float)lp.trans / 100.f; const float varsens = lp.sensh; int GW = transformed->W; int GH = transformed->H; - const float refa = chromaref * cos(hueref); - const float refb = chromaref * sin(hueref); + // const float refa = chromaref * cos(hueref); + // const float refb = chromaref * sin(hueref); + + const float refa = chromaref * cos(hueref) * 327.68f; + const float refb = chromaref * sin(hueref) * 327.68f; + const float refL = lumaref * 327.68f; + const bool retishow = ((lp.showmaskretimet == 1 || lp.showmaskretimet == 2)); const bool previewreti = ((lp.showmaskretimet == 4)); //balance deltaE float kL = lp.balance; float kab = 1.f; + float kH = lp.balanceh; + float kch = 1.f; balancedeltaE(kL, kab); + balancedeltaEH(kH, kch); + + kab /= SQR(327.68f); + kL /= SQR(327.68f); + + bool showmas = false ; if (lp.showmaskretimet == 3) @@ -2508,25 +4935,18 @@ void ImProcFunctions::transit_shapedetect_retinex(int senstype, LabImage * bufex const float maxdE = 5.f + MAXSCOPE * varsens * (1 + 0.1f * lp.thr); const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + const float previewint = settings->previewselection; #ifdef _OPENMP #pragma omp for schedule(dynamic,16) #endif - for (int y = 0; y < transformed->H; y++) + for (int y = ystart; y < yend; y++) { const int loy = cy + y; - const bool isZone0 = loy > lp.yc + lp.ly || loy < lp.yc - lp.lyT; // whole line is zone 0 => we can skip a lot of processing - if (isZone0) { // outside selection and outside transition zone => no effect, keep original values - continue; - } - - for (int x = 0; x < transformed->W; x++) { + for (int x = xstart; x < xend; x++) { const int lox = cx + x; - const int begx = int (lp.xc - lp.lxL); - const int begy = int (lp.yc - lp.lyT); - int zone = 0; float localFactor = 1.f; @@ -2543,42 +4963,74 @@ void ImProcFunctions::transit_shapedetect_retinex(int senstype, LabImage * bufex float rL = origblur->L[y][x] / 327.68f; float dE; + float abdelta2 = 0.f; + float chrodelta2 = 0.f; + float huedelta2 = 0.f; if (!usemaskreti) { - dE = sqrt(kab * SQR(refa - origblur->a[y][x] / 327.68f) + kab * SQR(refb - origblur->b[y][x] / 327.68f) + kL * SQR(lumaref - rL)); + abdelta2 = SQR(refa - origblur->a[y][x]) + SQR(refb - origblur->b[y][x]); + chrodelta2 = SQR(sqrt(SQR(origblur->a[y][x]) + SQR(origblur->b[y][x])) - (chromaref * 327.68f)); + huedelta2 = abdelta2 - chrodelta2; + dE = sqrt(kab * (kch * chrodelta2 + kH * huedelta2) + kL * SQR(refL - origblur->L[y][x])); } else { - dE = sqrt(kab * SQR(refa - buforigmas->a[loy - begy][lox - begx] / 327.68f) + kab * SQR(refb - buforigmas->b[loy - begy][lox - begx] / 327.68f) + kL * SQR(lumaref - buforigmas->L[loy - begy][lox - begx] / 327.68f)); + if (call == 2) { + abdelta2 = SQR(refa - buforigmas->a[y - ystart][x - xstart]) + SQR(refb - buforigmas->b[y - ystart][x - xstart]); + chrodelta2 = SQR(sqrt(SQR(buforigmas->a[y - ystart][x - xstart]) + SQR(buforigmas->b[y - ystart][x - xstart])) - (chromaref * 327.68f)); + huedelta2 = abdelta2 - chrodelta2; + dE = sqrt(kab * (kch * chrodelta2 + kH * huedelta2) + kL * SQR(refL - buforigmas->L[y - ystart][x - xstart])); + + } else { + abdelta2 = SQR(refa - buforigmas->a[y][x]) + SQR(refb - buforigmas->b[y][x]); + chrodelta2 = SQR(sqrt(SQR(buforigmas->a[y][x]) + SQR(buforigmas->b[y][x])) - (chromaref * 327.68f)); + huedelta2 = abdelta2 - chrodelta2; + dE = sqrt(kab * (kch * chrodelta2 + kH * huedelta2) + kL * SQR(refL - buforigmas->L[y][x])); + } } - float cli = buflight[loy - begy][lox - begx]; - //float clc = bufchro[loy - begy][lox - begx]; - float clc = previewreti ? settings->previewselection * 100.f : bufchro[loy - begy][lox - begx]; + float cli, clc; + + if (call == 2) { + cli = buflight[y - ystart][x - xstart]; + clc = previewreti ? settings->previewselection * 100.f : bufchro[y - ystart][x - xstart]; + } else { + cli = buflight[y][x]; + clc = previewreti ? settings->previewselection * 100.f : bufchro[y][x]; + + } float reducdE; calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, varsens, reducdE); - // const float realstrdE = reducdE * cli; reducdE /= 100.f; cli *= reducdE; clc *= reducdE; cli *= (1.f + strcli); - // clc *= (1.f + strcli); if (rL > 0.1f) { //to avoid crash with very low gamut in rare cases ex : L=0.01 a=0.5 b=-0.9 if (senstype == 4) {//all except color and light (TODO) and exposure - float lightc = bufexporig->L[loy - begy][lox - begx]; + float lightc; + + if (call == 2) { + lightc = bufexporig->L[y - ystart][x - xstart]; + } else { + lightc = bufexporig->L[y][x]; + } + float fli = 1.f + cli; float diflc = lightc * fli - original->L[y][x]; - // float diflc2 = 328.f * realstrdE; diflc *= localFactor; - // diflc2 *= localFactor; if (!showmas) { transformed->L[y][x] = CLIP(original->L[y][x] + diflc); } else { - transformed->L[y][x] = bufmask->L[loy - begy][lox - begx]; - } ; //bufexporig->L[loy - begy][lox - begx]; + if (call == 2) { + + transformed->L[y][x] = bufmask->L[y - ystart][x - xstart]; + } else { + transformed->L[y][x] = bufmask->L[y][x]; + } + } ; if (retishow) { transformed->L[y][x] = CLIP(12000.f + diflc); @@ -2586,22 +5038,36 @@ void ImProcFunctions::transit_shapedetect_retinex(int senstype, LabImage * bufex } float fliab = 1.f; - const float chra = bufexporig->a[loy - begy][lox - begx]; - const float chrb = bufexporig->b[loy - begy][lox - begx]; + float chra, chrb; + + if (call == 2) { + chra = bufexporig->a[y - ystart][x - xstart]; + chrb = bufexporig->b[y - ystart][x - xstart]; + } else { + chra = bufexporig->a[y][x]; + chrb = bufexporig->b[y][x]; + + } if (senstype == 5) { fliab = 1.f + clc; } const float difa = (chra * fliab - original->a[y][x]) * localFactor; - const float difb = (chrb * fliab - original->b[y][x]) * localFactor; + float difb = (chrb * fliab - original->b[y][x]) * localFactor; transformed->a[y][x] = CLIPC(original->a[y][x] + difa); transformed->b[y][x] = CLIPC(original->b[y][x] + difb); if (showmas) { - transformed->a[y][x] = bufmask->a[loy - begy][lox - begx]; - transformed->b[y][x] = bufmask->b[loy - begy][lox - begx]; + if (call == 2) { + transformed->a[y][x] = bufmask->a[y - ystart][x - xstart]; + transformed->b[y][x] = bufmask->b[y - ystart][x - xstart]; + } else { + transformed->a[y][x] = bufmask->a[y][x]; + transformed->b[y][x] = bufmask->b[y][x]; + + } } if (retishow) { @@ -2611,7 +5077,7 @@ void ImProcFunctions::transit_shapedetect_retinex(int senstype, LabImage * bufex if (previewreti) { transformed->a[y][x] = 0.f; - transformed->b[y][x] = CLIPC(difb); + transformed->b[y][x] = previewint * difb; } } } @@ -2627,7 +5093,7 @@ void ImProcFunctions::transit_shapedetect_retinex(int senstype, LabImage * bufex } -void ImProcFunctions::transit_shapedetect(int senstype, const LabImage *bufexporig, LabImage * originalmask, float **buflight, float **bufchro, float **buf_a_cat, float ** buf_b_cat, float ** bufhh, bool HHutili, const float hueref, const float chromaref, const float lumaref, float sobelref, float meansobel, float ** blend2, const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) +void ImProcFunctions::transit_shapedetect(int senstype, const LabImage * bufexporig, LabImage * originalmask, float **bufchro, bool HHutili, const float hueref, const float chromaref, const float lumaref, float sobelref, float meansobel, float ** blend2, const struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) { BENCHFUN { @@ -2641,33 +5107,18 @@ void ImProcFunctions::transit_shapedetect(int senstype, const LabImage *bufexpor const float ach = lp.trans / 100.f; float varsens = lp.sensex; - if (senstype == 0) //Color and Light - { - varsens = lp.sens; - } else if (senstype == 1) //exposure - { - varsens = lp.sensex; - } else if (senstype == 2) //vibrance - { - varsens = lp.sensv; - } else if (senstype == 3) //soft light - { - varsens = lp.senssf; - } else if (senstype == 6 || senstype == 7) //cbdl + if (senstype == 6 || senstype == 7) //cbdl { varsens = lp.senscb; } else if (senstype == 8) //TM { varsens = lp.senstm; - } else if (senstype == 9) //Shadow highlight - { - varsens = lp.senshs; } else if (senstype == 10) //local contrast { varsens = lp.senslc; } - //sobel + //sobel //keep in case of, not used sobelref /= 100.f; meansobel /= 100.f; @@ -2680,15 +5131,10 @@ void ImProcFunctions::transit_shapedetect(int senstype, const LabImage *bufexpor const float refa = chromaref * cos(hueref) * 327.68f; const float refb = chromaref * sin(hueref) * 327.68f; const float refL = lumaref * 327.68f; + const float previewint = settings->previewselection; - const bool expshow = ((lp.showmaskexpmet == 1 || lp.showmaskexpmet == 2) && senstype == 1); - const bool colshow = ((lp.showmaskcolmet == 1 || lp.showmaskcolmet == 2) && senstype == 0); - const bool SHshow = ((lp.showmaskSHmet == 1 || lp.showmaskSHmet == 2) && senstype == 9); const bool cbshow = ((lp.showmaskcbmet == 1 || lp.showmaskcbmet == 2) && senstype == 6); const bool tmshow = ((lp.showmasktmmet == 1 || lp.showmasktmmet == 2) && senstype == 8); - const bool previewcol = ((lp.showmaskcolmet == 5) && senstype == 0); - const bool previewexp = ((lp.showmaskexpmet == 5) && senstype == 1); - const bool previewSH = ((lp.showmaskSHmet == 4) && senstype == 9); const bool previewcb = ((lp.showmaskcbmet == 4) && senstype == 6); const bool previewtm = ((lp.showmasktmmet == 4) && senstype == 8); @@ -2696,30 +5142,27 @@ void ImProcFunctions::transit_shapedetect(int senstype, const LabImage *bufexpor std::unique_ptr origblurmask; float radius = 3.f / sk; - - if (senstype == 1) - { - radius = (2.f + 0.2f * lp.blurexp) / sk; - } else if (senstype == 0) - { - radius = (2.f + 0.2f * lp.blurcol) / sk; - } else if (senstype == 9) - { - radius = (2.f + 0.2f * lp.blurSH) / sk; - } - + /* + if (senstype == 1) + { + radius = (2.f + 0.2f * lp.blurexp) / sk; + } else if (senstype == 0 || senstype == 100) + { + radius = (2.f + 0.2f * lp.blurcol) / sk; + } else if (senstype == 9) + { + radius = (2.f + 0.2f * lp.blurSH) / sk; + } + */ //balance deltaE float kL = lp.balance; float kab = 1.f; balancedeltaE(kL, kab); kab /= SQR(327.68f); kL /= SQR(327.68f); - const bool usemaskexp = (lp.showmaskexpmet == 2 || lp.enaExpMask || lp.showmaskexpmet == 5) && senstype == 1; - const bool usemaskcol = (lp.showmaskcolmet == 2 || lp.enaColorMask || lp.showmaskcolmet == 5) && senstype == 0; - const bool usemaskSH = (lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 4) && senstype == 9; const bool usemaskcb = (lp.showmaskcbmet == 2 || lp.enacbMask || lp.showmaskcbmet == 4) && senstype == 6; const bool usemasktm = (lp.showmasktmmet == 2 || lp.enatmMask || lp.showmasktmmet == 4) && senstype == 8; - const bool usemaskall = (usemaskSH || usemaskcol || usemaskexp || usemaskcb || usemasktm); + const bool usemaskall = (usemaskcb || usemasktm); if (usemaskall) { @@ -2750,7 +5193,7 @@ void ImProcFunctions::transit_shapedetect(int senstype, const LabImage *bufexpor data[(y - ystart)* bfw + (x - xstart)] = bufexporig->L[y - ystart][x - xstart]; } - normalize_mean_dt(data, datain, bfh * bfw, 1.f); + normalize_mean_dt(data, datain, bfh * bfw, 1.f, 1.f); #ifdef _OPENMP #pragma omp parallel for #endif @@ -2858,7 +5301,7 @@ void ImProcFunctions::transit_shapedetect(int senstype, const LabImage *bufexpor const float rL = origblur->L[y - ystart][x - xstart] / 327.68f; float rsob = 0.f; - if (blend2 && ((senstype == 1 && lp.struexp > 0.f) || (senstype == 0 && lp.struco > 0.f))) { + if (blend2 && ((senstype == 1 && lp.struexp > 0.f) || ((senstype == 0 || senstype == 100) && lp.struco > 0.f))) {//keep in case of, not used const float csob = xlogf(1.f + std::min(blend2[y - ystart][x - xstart] / 100.f, 60.f) + 0.001f); float rs; @@ -2871,293 +5314,75 @@ void ImProcFunctions::transit_shapedetect(int senstype, const LabImage *bufexpor if (rs > 0.f && senstype == 1) { rsob = 1.1f * lp.struexp * rs; - } else if (rs > 0.f && senstype == 0) { + } else if (rs > 0.f && (senstype == 0 || senstype == 100)) { rsob = 1.1f * lp.struco * rs; } } const float dE = rsob + sqrt(kab * (SQR(refa - maskptr->a[y - ystart][x - xstart]) + SQR(refb - maskptr->b[y - ystart][x - xstart])) + kL * SQR(refL - maskptr->L[y - ystart][x - xstart])); - float cla = 0.f; - float clb = 0.f; - - const float cli = buflight[y - ystart][x - xstart]; - const float clc = (previewcol || previewexp || previewSH || previewcb) ? settings->previewselection * 100.f : bufchro[y - ystart][x - xstart]; + const float clc = (previewcb) ? settings->previewselection * 100.f : bufchro[y - ystart][x - xstart]; - if (senstype <= 1) { - cla = buf_a_cat[y - ystart][x - xstart]; - clb = buf_b_cat[y - ystart][x - xstart]; - } float reducdE; calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, varsens, reducdE); - const float realstrdE = reducdE * cli; - const float realstradE = reducdE * cla; - const float realstrbdE = reducdE * clb; const float realstrchdE = reducdE * clc; - /* comment on processus deltaE - * the algo uses 3 different ways to manage deltaE according to the type of intervention - * if we call "applyproc" : the datas produced upstream in bfw, bfh coordinate by the function producing something curves, retinex, exposure, etc. - - * direct : in this case we use directly the datas produced upstream by "applyproc", with only a regulation produce for deltaE by reducdE - * direct : we found in this case "applyproc" modify data with low amplitude : BlurNoise, CBDL, Denoise, Sharp, TM - - * with first use of "buflight" on which is apply "applyproc", in this case we apply realstrdE = reducdE * buflight with a function of type 328.f * realstrdE - * in this case we found "applyproc" which result in direct use on Luminance : Exposure, Color and Light, Shadows highlight, SoftLight, Localcontrast - - * with second use of "buflight" on which is apply "applyproc", in this case we apply realstrdE = reducdE * buflight with a function of type fli = (100.f + realstrdE) / 100.f; - * in this case we found "applyproc" which result in large variations of L : Retinex - - * if you change you must test before - - */ if (rL > 0.1f) { //to avoid crash with very low gamut in rare cases ex : L=0.01 a=0.5 b=-0.9 - switch (zone) { - case 1: { // inside transition zone - float factorx = localFactor; - float diflc = 0.f; - float newhr = 0.f; - float difL = 0.f; - - if (senstype == 2) { - const float lightc = bufexporig->L[y - ystart][x - xstart]; - const float fli = (100.f + realstrdE) / 100.f; - transformed->L[y][x] = CLIP(original->L[y][x] + (lightc * fli - original->L[y][x]) * factorx); - } else if (senstype == 6 || senstype == 8 || senstype == 10) { - difL = (bufexporig->L[y - ystart][x - xstart] - original->L[y][x]) * localFactor * reducdE; - transformed->L[y][x] = CLIP(original->L[y][x] + difL); - } else if (senstype == 1 || senstype == 0 || senstype == 9 || senstype == 3) { - if (HHutili) { - const float hhro = bufhh[y - ystart][x - xstart]; - - if (hhro != 0) { - const float realhhdE = reducdE * hhro; - const float addh = 0.01f * realhhdE * factorx; - newhr = rhue + addh; - - if (newhr > rtengine::RT_PI_F) { - newhr -= 2 * rtengine::RT_PI_F; - } else if (newhr < -rtengine::RT_PI_F) { - newhr += 2 * rtengine::RT_PI_F; - } - } - } - - transformed->L[y][x] = CLIP(original->L[y][x] + 328.f * factorx * realstrdE); - diflc = 328.f * factorx * realstrdE; - } - - if (senstype == 7) { - float difab = bufexporig->L[y - ystart][x - xstart] - sqrt(SQR(original->a[y][x]) + SQR(original->b[y][x])); - float2 sincosval = xsincosf(rhue); - float difa = difab * sincosval.y; - float difb = difab * sincosval.x; - difa *= factorx * (100.f + realstrchdE) / 100.f; - difb *= factorx * (100.f + realstrchdE) / 100.f; - transformed->a[y][x] = CLIPC(original->a[y][x] + difa); - transformed->b[y][x] = CLIPC(original->b[y][x] + difb); - } else { - float flia = 1.f; - float flib = 1.f; - const float chra = bufexporig->a[y - ystart][x - xstart]; - const float chrb = bufexporig->b[y - ystart][x - xstart]; - - if (senstype == 2 || senstype == 3 || senstype == 8 || senstype == 9 || senstype == 6 || senstype == 10) { - - flia = flib = ((100.f + realstrchdE) / 100.f); - } else if (senstype == 1) { - flia = (100.f + realstradE + 100.f * realstrchdE) / 100.f; - flib = (100.f + realstrbdE + 100.f * realstrchdE) / 100.f; - - if (previewcol || previewexp || previewSH) { - flia = (100.f + realstradE + realstrchdE) / 100.f; - flib = (100.f + realstrbdE + realstrchdE) / 100.f; - } - } else if (senstype == 0) { - flia = (100.f + 0.3f * lp.strengrid * realstradE + realstrchdE) / 100.f; - flib = (100.f + 0.3f * lp.strengrid * realstrbdE + realstrchdE) / 100.f; - - if (previewcol || previewexp || previewSH || previewcb) { - flia = (100.f + realstradE + realstrchdE) / 100.f; - flib = (100.f + realstrbdE + realstrchdE) / 100.f; - } - } - - float difa = chra * flia - original->a[y][x]; - float difb = chrb * flib - original->b[y][x]; - difa *= factorx; - difb *= factorx; - - transformed->a[y][x] = CLIPC(original->a[y][x] + difa); - transformed->b[y][x] = CLIPC(original->b[y][x] + difb); - - if (senstype == 0 && HHutili) { - const float tempa = transformed->a[y][x]; - const float tempb = transformed->b[y][x]; - const float hhro = bufhh[y - ystart][x - xstart]; - - if (hhro != 0.f) { - const float chromhr = sqrt(SQR(original->a[y][x] + difa) + SQR(original->b[y][x] + difb)); - float epsia = 0.f; - float epsib = 0.f; - - if (original->a[y][x] == 0.f) { - epsia = 0.001f; - } - - if (original->b[y][x] == 0.f) { - epsib = 0.001f; - } - - const float faca = (original->a[y][x] + difa) / (original->a[y][x] + epsia); - const float facb = (original->b[y][x] + difb) / (original->b[y][x] + epsib); - const float2 sincosval = xsincosf(newhr); - - transformed->a[y][x] = CLIPC(chromhr * sincosval.y * faca) ; - transformed->b[y][x] = CLIPC(chromhr * sincosval.x * facb); - difa = transformed->a[y][x] - tempa; - difb = transformed->b[y][x] - tempb; - } - } - - if (expshow || colshow || SHshow) { - transformed->L[y][x] = CLIP(12000.f + diflc); - transformed->a[y][x] = CLIPC(difa); - transformed->b[y][x] = CLIPC(difb); - } else if (cbshow || tmshow) { - transformed->L[y][x] = CLIP(12000.f + difL); - transformed->a[y][x] = CLIPC(difa); - transformed->b[y][x] = CLIPC(difb); - } else if (previewcol || previewexp || previewSH || previewcb || previewtm) { - transformed->a[y][x] = 0.f; - transformed->b[y][x] = (difb); - } - } - - break; + if (zone > 0) { + float factorx = localFactor; + float difL = 0.f; + if (senstype == 6 || senstype == 8 || senstype == 10) { + difL = (bufexporig->L[y - ystart][x - xstart] - original->L[y][x]) * localFactor * reducdE; + transformed->L[y][x] = CLIP(original->L[y][x] + difL); } - case 2: { // inside selection => full effect, no transition - float diflc = 0.f; - float newhr = 0.f; - float difL = 0.f; + if (senstype == 7) { + float difab = bufexporig->L[y - ystart][x - xstart] - sqrt(SQR(original->a[y][x]) + SQR(original->b[y][x])); + float2 sincosval = xsincosf(rhue); + float difa = difab * sincosval.y; + float difb = difab * sincosval.x; + difa *= factorx * (100.f + realstrchdE) / 100.f; + difb *= factorx * (100.f + realstrchdE) / 100.f; + transformed->a[y][x] = CLIPC(original->a[y][x] + difa); + transformed->b[y][x] = CLIPC(original->b[y][x] + difb); + } else { + float flia = 1.f; + float flib = 1.f; + float chra = bufexporig->a[y - ystart][x - xstart]; + float chrb = bufexporig->b[y - ystart][x - xstart]; - if (senstype == 2) { - const float lightc = bufexporig->L[y - ystart][x - xstart]; - const float fli = (100.f + realstrdE) / 100.f; - transformed->L[y][x] = CLIP(original->L[y][x] + lightc * fli - original->L[y][x]); - } else if (senstype == 6 || senstype == 8 || senstype == 10) { - difL = (bufexporig->L[y - ystart][x - xstart] - original->L[y][x]) * reducdE; - transformed->L[y][x] = CLIP(original->L[y][x] + difL); - } else if (senstype == 1 || senstype == 0 || senstype == 9 || senstype == 3) { - if (HHutili) { - const float hhro = bufhh[y - ystart][x - xstart]; - - if (hhro != 0) { - const float realhhdE = reducdE * hhro; - const float addh = 0.01f * realhhdE; - newhr = rhue + addh; - - if (newhr > rtengine::RT_PI_F) { - newhr -= 2 * rtengine::RT_PI_F; - } else if (newhr < -rtengine::RT_PI_F) { - newhr += 2 * rtengine::RT_PI_F; - } - } - } - - transformed->L[y][x] = CLIP(original->L[y][x] + 328.f * realstrdE);//kch fach - diflc = 328.f * realstrdE; + if (senstype == 3 || senstype == 30 || senstype == 8 || senstype == 6 || senstype == 10) { + flia = flib = ((100.f + realstrchdE) / 100.f); } - if (senstype == 7) {//cbdl chroma - float difab = bufexporig->L[y - ystart][x - xstart] - sqrt(SQR(original->a[y][x]) + SQR(original->b[y][x])); - float2 sincosval = xsincosf(rhue); - float difa = difab * sincosval.y; - float difb = difab * sincosval.x; - difa *= (100.f + realstrchdE) / 100.f; - difb *= (100.f + realstrchdE) / 100.f; - transformed->a[y][x] = CLIPC(original->a[y][x] + difa); - transformed->b[y][x] = CLIPC(original->b[y][x] + difb); - } else { - float flia = 1.f; - float flib = 1.f; - const float chra = bufexporig->a[y - ystart][x - xstart]; - const float chrb = bufexporig->b[y - ystart][x - xstart]; - if (senstype == 2 || senstype == 3 || senstype == 8 || senstype == 9 || senstype == 6 || senstype == 10) { - flia = flib = (100.f + realstrchdE) / 100.f; - } else if (senstype == 1) { - flia = (100.f + realstradE + 100.f * realstrchdE) / 100.f; - flib = (100.f + realstrbdE + 100.f * realstrchdE) / 100.f; + float difa = chra * flia - original->a[y][x]; + float difb = chrb * flib - original->b[y][x]; + difa *= factorx; + difb *= factorx; - if (previewcol || previewexp || previewSH) { - flia = (100.f + realstradE + realstrchdE) / 100.f; - flib = (100.f + realstrbdE + realstrchdE) / 100.f; - } - } else if (senstype == 0) { - flia = (100.f + 0.3f * lp.strengrid * realstradE + realstrchdE) / 100.f; - flib = (100.f + 0.3f * lp.strengrid * realstrbdE + realstrchdE) / 100.f; + transformed->a[y][x] = CLIPC(original->a[y][x] + difa); + transformed->b[y][x] = CLIPC(original->b[y][x] + difb); - if (previewcol || previewexp || previewSH) { - flia = (100.f + realstradE + realstrchdE) / 100.f; - flib = (100.f + realstrbdE + realstrchdE) / 100.f; - } + + if (cbshow || tmshow) { + transformed->L[y][x] = CLIP(12000.f + difL); + transformed->a[y][x] = CLIPC(difa); + transformed->b[y][x] = CLIPC(difb); + } else if (previewcb || previewtm) { + if (fabs(difb) < 500.f) { + difb += difL; } - float difa = chra * flia - original->a[y][x]; - float difb = chrb * flib - original->b[y][x]; - - transformed->a[y][x] = CLIPC(original->a[y][x] + difa); - transformed->b[y][x] = CLIPC(original->b[y][x] + difb); - - if (senstype == 0 && HHutili) { - const float tempa = transformed->a[y][x]; - const float tempb = transformed->b[y][x]; - const float hhro = bufhh[y - ystart][x - xstart]; - - if (hhro != 0.f) { - const float chromhr = sqrt(SQR(original->a[y][x] + difa) + SQR(original->b[y][x] + difb)); - float epsia = 0.f; - float epsib = 0.f; - - if (original->a[y][x] == 0.f) { - epsia = 0.001f; - } - - if (original->b[y][x] == 0.f) { - epsib = 0.001f; - } - - const float faca = (original->a[y][x] + difa) / (original->a[y][x] + epsia); - const float facb = (original->b[y][x] + difb) / (original->b[y][x] + epsib); - - const float2 sincosval = xsincosf(newhr); - transformed->a[y][x] = CLIPC(chromhr * sincosval.y * faca) ; - transformed->b[y][x] = CLIPC(chromhr * sincosval.x * facb); - difa = transformed->a[y][x] - tempa; - difb = transformed->b[y][x] - tempb; - } - } - - if (expshow || colshow || SHshow) { - transformed->L[y][x] = CLIP(12000.f + diflc); - transformed->a[y][x] = CLIPC(difa); - transformed->b[y][x] = CLIPC(difb); - } else if (cbshow || tmshow) { - transformed->L[y][x] = CLIP(12000.f + difL); - transformed->a[y][x] = CLIPC(difa); - transformed->b[y][x] = CLIPC(difb); - } else if (previewcol || previewexp || previewSH || previewcb || previewtm) { - transformed->a[y][x] = 0.f; - transformed->b[y][x] = difb; - } + transformed->a[y][x] = 0.f; + transformed->b[y][x] = previewint * difb; } } + } } } @@ -3166,7 +5391,7 @@ void ImProcFunctions::transit_shapedetect(int senstype, const LabImage *bufexpor } } -void ImProcFunctions::InverseColorLight_Local(int sp, int senstype, const struct local_params & lp, LUTf & lightCurveloc, LUTf & hltonecurveloc, LUTf & shtonecurveloc, LUTf & tonecurveloc, LUTf & exlocalcurve, LUTf & cclocalcurve, float adjustr, bool localcutili, LUTf & lllocalcurve, bool locallutili, LabImage * original, LabImage * transformed, int cx, int cy, const float hueref, const float chromaref, const float lumaref, int sk) +void ImProcFunctions::InverseColorLight_Local(bool tonequ, bool tonecurv, int sp, int senstype, struct local_params & lp, LabImage * originalmask, LUTf & lightCurveloc, LUTf & hltonecurveloc, LUTf & shtonecurveloc, LUTf & tonecurveloc, LUTf & exlocalcurve, LUTf & cclocalcurve, float adjustr, bool localcutili, LUTf & lllocalcurve, bool locallutili, LabImage * original, LabImage * transformed, int cx, int cy, const float hueref, const float chromaref, const float lumaref, int sk) { // BENCHFUN float ach = (float)lp.trans / 100.f; @@ -3190,8 +5415,11 @@ void ImProcFunctions::InverseColorLight_Local(int sp, int senstype, const struct int GW = transformed->W; int GH = transformed->H; - float refa = chromaref * cos(hueref); - float refb = chromaref * sin(hueref); +// float refa = chromaref * cos(hueref); +// float refb = chromaref * sin(hueref); + const float refa = chromaref * cos(hueref) * 327.68f; + const float refb = chromaref * sin(hueref) * 327.68f; + const float refL = lumaref * 327.68f; if (senstype == 2) { // Shadows highlight temp = new LabImage(GW, GH); @@ -3207,9 +5435,44 @@ void ImProcFunctions::InverseColorLight_Local(int sp, int senstype, const struct } } - ImProcFunctions::shadowsHighlights(temp, lp.hsena, 1, lp.highlihs, lp.shadowhs, lp.radiushs, sk, lp.hltonalhs, lp.shtonalhs); + if (lp.shmeth == 0) { + ImProcFunctions::shadowsHighlights(temp, lp.hsena, 1, lp.highlihs, lp.shadowhs, lp.radiushs, sk, lp.hltonalhs, lp.shtonalhs); + } + + if (lp.shmeth == 1) { + int GH = transformed->H; + int GW = transformed->W; + + double scal = (double)(sk); + Imagefloat *tmpImage = nullptr; + tmpImage = new Imagefloat(GW, GH); + lab2rgb(*temp, *tmpImage, params->icm.workingProfile); + + if (tonecurv) { //Tone response curve : does nothing if gamma=2.4 and slope=12.92 ==> gamma sRGB + float gamtone = params->locallab.spots.at(sp).gamSH; + float slotone = params->locallab.spots.at(sp).sloSH; + cmsHTRANSFORM dummy = nullptr; + workingtrc(tmpImage, tmpImage, GW, GH, -5, params->icm.workingProfile, 2.4, 12.92310, dummy, true, false, false); + workingtrc(tmpImage, tmpImage, GW, GH, 5, params->icm.workingProfile, gamtone, slotone, dummy, false, true, true); + } + + if (tonequ) { + tmpImage->normalizeFloatTo1(); + array2D Rtemp(GW, GH, tmpImage->r.ptrs, ARRAY2D_BYREFERENCE); + array2D Gtemp(GW, GH, tmpImage->g.ptrs, ARRAY2D_BYREFERENCE); + array2D Btemp(GW, GH, tmpImage->b.ptrs, ARRAY2D_BYREFERENCE); + tone_eq(Rtemp, Gtemp, Btemp, lp, params->icm.workingProfile, scal, multiThread); + tmpImage->normalizeFloatTo65535(); + } + + rgb2lab(*tmpImage, *temp, params->icm.workingProfile); + + delete tmpImage; + } + } + if (senstype == 1) { //exposure temp = new LabImage(GW, GH); #ifdef _OPENMP @@ -3272,9 +5535,11 @@ void ImProcFunctions::InverseColorLight_Local(int sp, int senstype, const struct } } - if (lp.war != 0) { - ImProcFunctions::ciecamloc_02float(sp, temp); - } + /* + if (lp.war != 0) { + ImProcFunctions::ciecamloc_02float(sp, temp); + } + */ } if (senstype == 0) { //Color and Light curves L C @@ -3331,12 +5596,35 @@ void ImProcFunctions::InverseColorLight_Local(int sp, int senstype, const struct //balance deltaE float kL = lp.balance; float kab = 1.f; + float kH = lp.balanceh; + float kch = 1.f; balancedeltaE(kL, kab); + balancedeltaEH(kH, kch); - LabImage *origblur = new LabImage(GW, GH); + kab /= SQR(327.68f); + kL /= SQR(327.68f); + + std::unique_ptr origblur(new LabImage(GW, GH)); + std::unique_ptr origblurmask; + const bool usemaskcol = (lp.enaColorMaskinv) && senstype == 0; + const bool usemaskexp = (lp.enaExpMaskinv) && senstype == 1; + const bool usemasksh = (lp.enaSHMaskinv) && senstype == 2; + const bool usemaskall = (usemaskcol || usemaskexp || usemasksh); float radius = 3.f / sk; + if (usemaskall) { + origblurmask.reset(new LabImage(GW, GH)); + +#ifdef _OPENMP + #pragma omp parallel if (multiThread) +#endif + { + gaussianBlur(originalmask->L, origblurmask->L, GW, GH, radius); + gaussianBlur(originalmask->a, origblurmask->a, GW, GH, radius); + gaussianBlur(originalmask->b, origblurmask->b, GW, GH, radius); + } + } if (senstype == 1) { radius = (2.f + 0.2f * lp.blurexp) / sk; @@ -3364,6 +5652,7 @@ void ImProcFunctions::InverseColorLight_Local(int sp, int senstype, const struct #pragma omp parallel if (multiThread) #endif { + const LabImage *maskptr = usemaskall ? origblurmask.get() : origblur.get(); const int limscope = 80; const float mindE = 2.f + MINSCOPE * varsens * lp.thr; const float maxdE = 5.f + MAXSCOPE * varsens * (1 + 0.1f * lp.thr); @@ -3395,7 +5684,12 @@ void ImProcFunctions::InverseColorLight_Local(int sp, int senstype, const struct origblur->b[y][x] = 0.01f; } - float dE = sqrt(kab * SQR(refa - origblur->a[y][x] / 327.68f) + kab * SQR(refb - origblur->b[y][x] / 327.68f) + kL * SQR(lumaref - rL)); + //deltaE + float abdelta2 = SQR(refa - maskptr->a[y][x]) + SQR(refb - maskptr->b[y][x]); + float chrodelta2 = SQR(sqrt(SQR(maskptr->a[y][x]) + SQR(maskptr->b[y][x])) - (chromaref * 327.68f)); + float huedelta2 = abdelta2 - chrodelta2; + const float dE = sqrt(kab * (kch * chrodelta2 + kH * huedelta2) + kL * SQR(refL - maskptr->L[y][x])); + float reducdE = 0.f; calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, varsens, reducdE); @@ -3563,7 +5857,6 @@ void ImProcFunctions::InverseColorLight_Local(int sp, int senstype, const struct } } } - delete origblur; if (senstype == 1 || senstype == 2) { delete temp; @@ -3575,12 +5868,12 @@ void ImProcFunctions::InverseColorLight_Local(int sp, int senstype, const struct } -void ImProcFunctions::calc_ref(int sp, LabImage * original, LabImage * transformed, int cx, int cy, int oW, int oH, int sk, double & huerefblur, double & chromarefblur, double & lumarefblur, double & hueref, double & chromaref, double & lumaref, double & sobelref, float &avg) +void ImProcFunctions::calc_ref(int sp, LabImage * original, LabImage * transformed, int cx, int cy, int oW, int oH, int sk, double & huerefblur, double & chromarefblur, double & lumarefblur, double & hueref, double & chromaref, double & lumaref, double & sobelref, float & avg, const LocwavCurve & locwavCurveden, bool & locwavdenutili) { if (params->locallab.enabled) { //always calculate hueref, chromaref, lumaref before others operations use in normal mode for all modules exceprt denoise struct local_params lp; - calcLocalParams(sp, oW, oH, params->locallab, lp, 0, 0, 0, 0, 0, 0, 0); + calcLocalParams(sp, oW, oH, params->locallab, lp, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, locwavCurveden, locwavdenutili); int begy = lp.yc - lp.lyT; int begx = lp.xc - lp.lxL; int yEn = lp.yc + lp.ly; @@ -3808,392 +6101,688 @@ const int fftw_size[] = {18144, 18000, 17920, 17836, 17820, 17640, 17600, 17550, int N_fftwsize = sizeof(fftw_size) / sizeof(fftw_size[0]); -static double *cos_table(size_t size) -{ - double *table = NULL; - double pi_size; - size_t i; - - /* allocate the cosinus table */ - if (NULL == (table = (double *) malloc(sizeof(double) * size))) { - fprintf(stderr, "allocation error\n"); - abort(); - } - - /* - * fill the cosinus table, - * table[i] = cos(i Pi / n) for i in [0..n[ - */ - pi_size = rtengine::RT_PI / size; - - for (i = 0; i < size; i++) { - table[i] = cos(pi_size * i); - } - - return table; -} - -static void mean_dt(const float *data, size_t size, double *mean_p, double *dt_p) -{ - double mean, dt; - const float *ptr_data; - size_t i; - - mean = 0.; - dt = 0.; - ptr_data = data; - - for (i = 0; i < size; i++) { - mean += *ptr_data; - dt += (*ptr_data) * (*ptr_data); - ptr_data++; - } - - mean /= (double) size; - dt /= (double) size; - dt -= (mean * mean); - dt = sqrt(dt); - - *mean_p = mean; - *dt_p = dt; - - return; -} - -void ImProcFunctions::normalize_mean_dt(float *data, const float *ref, size_t size, float mod) +void optfft(int &N_fftwsize, int &bfh, int &bfw, int &bfhr, int &bfwr, bool &reduH, bool &reduW, struct local_params & lp, int &H, int &W, int &xstart, int &ystart, int &xend, int ¥d, int cx, int cy) { /* - * Copyright 2009-2011 IPOL Image Processing On Line http://www.ipol.im/ - * - - * @file retinex_pde_lib.c discrete Poisson equation - * @brief laplacian, DFT and Poisson routines - * - * @author Nicolas Limare - * adapted for Rawtherapee - jacques Desmis july 2019 - */ - - double mean_ref, mean_data, dt_ref, dt_data; - double a, b; - size_t i; - float *ptr_data; - float *ptr_dataold; - - if (NULL == data || NULL == ref) { - fprintf(stderr, "a pointer is NULL and should not be so\n"); - abort(); - } - - /* compute mean and variance of the two arrays */ - mean_dt(ref, size, &mean_ref, &dt_ref); - mean_dt(data, size, &mean_data, &dt_data); - - /* compute the normalization coefficients */ - a = dt_ref / dt_data; - b = mean_ref - a * mean_data; - - /* normalize the array */ - ptr_data = data; - ptr_dataold = data; - - for (i = 0; i < size; i++) { - *ptr_data = mod * (a * *ptr_data + b) + (1.f - mod) * *ptr_dataold;//normalize mean and stdv and balance PDE - ptr_data++; - } - - return; -} - -static float *rex_poisson_dct(float *data, size_t nx, size_t ny, double m) -{ - /* - * Copyright 2009-2011 IPOL Image Processing On Line http://www.ipol.im/ - * - - * @file retinex_pde_lib.c discrete Poisson equation - * @brief laplacian, DFT and Poisson routines - * - * @author Nicolas Limare - * some adaptations for Rawtherapee - */ - BENCHFUN - - double *cosx = NULL, *cosy = NULL; - size_t i; - double m2; - - /* - * get the cosinus tables - * cosx[i] = cos(i Pi / nx) for i in [0..nx[ - * cosy[i] = cos(i Pi / ny) for i in [0..ny[ - */ - cosx = cos_table(nx); - cosy = cos_table(ny); - - /* - * we will now multiply data[i, j] by - * m / (4 - 2 * cosx[i] - 2 * cosy[j])) - * and set data[0, 0] to 0 - */ - m2 = m / 2.; - /* - * handle the first value, data[0, 0] = 0 - * after that, by construction, we always have - * cosx[] + cosy[] != 2. - */ - data[0] = 0.; - - /* - * continue with all the array: - * i % nx is the position on the x axis (column number) - * i / nx is the position on the y axis (row number) - */ - for (i = 1; i < nx * ny; i++) { - data[i] *= m2 / (2. - cosx[i % nx] - cosy[i / nx]); - } - - free(cosx); - free(cosy); - - return data; -} + for (int n=0; n< 17; n++){ + for(int m=0; m < 11; m++) { + for(int l=0; l < 8; l++) { + for(int p=0; p < 6; p++) { + for (int r=0; r < 2; r++){ + int bon = pow(2, n) * pow(3, m) * pow(5, l) * pow(7, p) * pow(13, r); + if(bon >= 18000 && bon < 18200) printf("b=%i", bon); + } + } + } + } + } + */ + int ftsizeH = 1; + int ftsizeW = 1; -static float *discrete_laplacian_threshold(float *data_out, const float *data_in, size_t nx, size_t ny, float t) -{ - BENCHFUN - - size_t i, j; - float *ptr_out; - float diff = 0.f; - /* pointers to the current and neighbour values */ - const float *ptr_in, *ptr_in_xm1, *ptr_in_xp1, *ptr_in_ym1, *ptr_in_yp1; - - if (NULL == data_in || NULL == data_out) { - fprintf(stderr, "a pointer is NULL and should not be so\n"); - abort(); - } - - /* pointers to the data and neighbour values */ - /* - * y-1 - * x-1 ptr x+1 - * y+1 - * <---------------------nx-------> - */ - ptr_in = data_in; - ptr_in_xm1 = data_in - 1; - ptr_in_xp1 = data_in + 1; - ptr_in_ym1 = data_in - nx; - ptr_in_yp1 = data_in + nx; - ptr_out = data_out; - - for (j = 0; j < ny; j++) { - for (i = 0; i < nx; i++) { - *ptr_out = 0.f; - - /* row differences */ - if (0 < i) { - diff = *ptr_in - *ptr_in_xm1; - - if (fabs(diff) > t) { - *ptr_out += diff; - } - } - - if (nx - 1 > i) { - diff = *ptr_in - *ptr_in_xp1; - - if (fabs(diff) > t) { - *ptr_out += diff; - } - } - - /* column differences */ - if (0 < j) { - diff = *ptr_in - *ptr_in_ym1; - - if (fabs(diff) > t) { - *ptr_out += diff; - } - } - - if (ny - 1 > j) { - diff = *ptr_in - *ptr_in_yp1; - - if (fabs(diff) > t) { - *ptr_out += diff; - } - } - - ptr_in++; - ptr_in_xm1++; - ptr_in_xp1++; - ptr_in_ym1++; - ptr_in_yp1++; - ptr_out++; + for (int ft = 0; ft < N_fftwsize; ft++) { //find best values + if (fftw_size[ft] <= bfh) { + ftsizeH = fftw_size[ft]; + break; } } - return data_out; + for (int ft = 0; ft < N_fftwsize; ft++) { + if (fftw_size[ft] <= bfw) { + ftsizeW = fftw_size[ft]; + break; + } + } + + // printf("FTsizeH =%i FTsizeW=%i \n", ftsizeH, ftsizeW); + //optimize with size fftw + if (ystart == 0 && yend < H) { + lp.ly -= (bfh - ftsizeH); + } else if (ystart != 0 && yend == H) { + lp.lyT -= (bfh - ftsizeH); + } else if (ystart != 0 && yend != H) { + if (lp.ly <= lp.lyT) { + lp.lyT -= (bfh - ftsizeH); + } else { + lp.ly -= (bfh - ftsizeH); + } + } else if (ystart == 0 && yend == H) { + bfhr = ftsizeH; + reduH = true; + } + + if (xstart == 0 && xend < W) { + lp.lx -= (bfw - ftsizeW); + } else if (xstart != 0 && xend == W) { + lp.lxL -= (bfw - ftsizeW); + } else if (xstart != 0 && xend != W) { + if (lp.lx <= lp.lxL) { + lp.lxL -= (bfw - ftsizeW); + } else { + lp.lx -= (bfw - ftsizeW); + } + } else if (xstart == 0 && xend == W) { + bfwr = ftsizeW; + reduW = true; + } + + //new values optimized + ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); + yend = std::min(static_cast(lp.yc + lp.ly) - cy, H); + xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); + xend = std::min(static_cast(lp.xc + lp.lx) - cx, W); + bfh = bfhr = yend - ystart; + bfw = bfwr = xend - xstart; + + if (reduH) { + bfhr = ftsizeH; + } + + if (reduW) { + bfwr = ftsizeW; + } + + if (settings->verbose) { + printf("Nyst=%i Nyen=%i lp.yc=%f lp.lyT=%f lp.ly=%f bfh=%i bfhr=%i origH=%i ftsizeH=%i\n", ystart, yend, lp.yc, lp.lyT, lp.ly, bfh, bfhr, H, ftsizeH); + printf("Nxst=%i Nxen=%i lp.xc=%f lp.lxL=%f lp.lx=%f bfw=%i bfwr=%i origW=%i ftsizeW=%i\n", xstart, xend, lp.xc, lp.lxL, lp.lx, bfw, bfwr, W, ftsizeW); + } } -void ImProcFunctions::retinex_pde(float *datain, float * dataout, int bfw, int bfh, float thresh, float multy, float *dE, int show) +void ImProcFunctions::BlurNoise_Local(LabImage *tmp1, LabImage * originalmask, float **bufchro, const float hueref, const float chromaref, const float lumaref, local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) { - /* - * Copyright 2009-2011 IPOL Image Processing On Line http://www.ipol.im/ - * - - * @file retinex_pde_lib.c discrete Poisson equation - * @brief laplacian, DFT and Poisson routines - * - * @author Nicolas Limare - * adapted for Rawtherapee by Jacques Desmis 6-2019 - */ - +//local BLUR BENCHFUN -#ifdef _OPENMP - if (multiThread) { - fftwf_init_threads(); - fftwf_plan_with_nthreads(omp_get_max_threads()); + const int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); + const int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); + const int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); + const int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); + + const float ach = lp.trans / 100.f; + const int GW = transformed->W; + const int GH = transformed->H; + const float refa = chromaref * cos(hueref) * 327.68f; + const float refb = chromaref * sin(hueref) * 327.68f; + const float refL = lumaref * 327.68f; + const bool blshow = ((lp.showmaskblmet == 1 || lp.showmaskblmet == 2)); + const bool previewbl = ((lp.showmaskblmet == 4)); + + //balance deltaE + float kL = lp.balance; + float kab = 1.f; + float kH = lp.balanceh; + float kch = 1.f; + balancedeltaE(kL, kab); + balancedeltaEH(kH, kch); + + kab /= SQR(327.68f); + kL /= SQR(327.68f); + + if (lp.colorde == 0) { + lp.colorde = -1;//to avoid black } -#endif - fftwf_plan dct_fw, dct_fw04, dct_bw; - float *data_fft, *data_fft04, *data_tmp, *data, *data_tmp04; - float *datashow = nullptr; + float ampli = 1.f + fabs(lp.colorde); + ampli = 2.f + 0.5f * (ampli - 2.f); - if (show != 0) { - if (NULL == (datashow = (float *) fftwf_malloc(sizeof(float) * bfw * bfh))) { - fprintf(stderr, "allocation error\n"); - abort(); - } - } + float darklim = 5000.f; + float aadark = -1.f; + float bbdark = darklim; - if (NULL == (data_tmp = (float *) fftwf_malloc(sizeof(float) * bfw * bfh))) { - fprintf(stderr, "allocation error\n"); - abort(); - } + const bool usemaskbl = (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 4); + const bool usemaskall = (usemaskbl); + const float radius = 3.f / sk; + std::unique_ptr origblurmask; - if (NULL == (data_tmp04 = (float *) fftwf_malloc(sizeof(float) * bfw * bfh))) { - fprintf(stderr, "allocation error\n"); - abort(); - } + std::unique_ptr origblur(new LabImage(GW, GH)); - //first call to laplacian with plein strength - (void) discrete_laplacian_threshold(data_tmp, datain, bfw, bfh, thresh); - - if (NULL == (data_fft = (float *) fftwf_malloc(sizeof(float) * bfw * bfh))) { - fprintf(stderr, "allocation error\n"); - abort(); - } - - if (show == 1) { - for (int y = 0; y < bfh ; y++) { - for (int x = 0; x < bfw; x++) { - datashow[y * bfw + x] = data_tmp[y * bfw + x]; - } - } - } - - //second call to laplacian with 40% strength ==> reduce effect if we are far from ref (deltaE) - (void) discrete_laplacian_threshold(data_tmp04, datain, bfw, bfh, 0.4f * thresh); - - if (NULL == (data_fft04 = (float *) fftwf_malloc(sizeof(float) * bfw * bfh))) { - fprintf(stderr, "allocation error\n"); - abort(); - } - - if (NULL == (data = (float *) fftwf_malloc(sizeof(float) * bfw * bfh))) { - fprintf(stderr, "allocation error\n"); - abort(); - } - - //execute first - dct_fw = fftwf_plan_r2r_2d(bfh, bfw, data_tmp, data_fft, FFTW_REDFT10, FFTW_REDFT10, FFTW_ESTIMATE | FFTW_DESTROY_INPUT); - fftwf_execute(dct_fw); - //execute second - dct_fw04 = fftwf_plan_r2r_2d(bfh, bfw, data_tmp04, data_fft04, FFTW_REDFT10, FFTW_REDFT10, FFTW_ESTIMATE | FFTW_DESTROY_INPUT); - fftwf_execute(dct_fw04); + if (usemaskall) { + origblurmask.reset(new LabImage(GW, GH)); #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel if (multiThread) +#endif + { + gaussianBlur(originalmask->L, origblurmask->L, GW, GH, radius); + gaussianBlur(originalmask->a, origblurmask->a, GW, GH, radius); + gaussianBlur(originalmask->b, origblurmask->b, GW, GH, radius); + } + } + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + gaussianBlur(original->L, origblur->L, GW, GH, radius); + gaussianBlur(original->a, origblur->a, GW, GH, radius); + gaussianBlur(original->b, origblur->b, GW, GH, radius); + } + +#ifdef _OPENMP + #pragma omp parallel if (multiThread) +#endif + { + const LabImage *maskptr = usemaskall ? origblurmask.get() : origblur.get(); + const int limscope = 80; + const float mindE = 4.f + MINSCOPE * lp.sensbn * lp.thr;//best usage ?? with blurnoise + const float maxdE = 5.f + MAXSCOPE * lp.sensbn * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) #endif - for (int y = 0; y < bfh ; y++) {//mix two fftw Laplacian : plein if dE near ref - for (int x = 0; x < bfw; x++) { - float prov = pow(dE[y * bfw + x], 4.5f); - data_fft[y * bfw + x] = prov * data_fft[y * bfw + x] + (1.f - prov) * data_fft04[y * bfw + x]; - } - } + for (int y = ystart; y < yend; y++) { + const int loy = cy + y; + + for (int x = xstart, lox = cx + x; x < xend; x++, lox++) { + int zone = 0; + float localFactor = 1.f; + + if (lp.shapmet == 0) { + calcTransition(lox, loy, ach, lp, zone, localFactor); + } else if (lp.shapmet == 1) { + calcTransitionrect(lox, loy, ach, lp, zone, localFactor); + } + + if (zone == 0) { // outside selection and outside transition zone => no effect, keep original values + continue; + } + + + float abdelta2 = SQR(refa - maskptr->a[y][x]) + SQR(refb - maskptr->b[y][x]); + float chrodelta2 = SQR(sqrt(SQR(maskptr->a[y][x]) + SQR(maskptr->b[y][x])) - (chromaref * 327.68f)); + float huedelta2 = abdelta2 - chrodelta2; + const float dE = sqrt(kab * (kch * chrodelta2 + kH * huedelta2) + kL * SQR(refL - maskptr->L[y][x])); + + + float reducdE; + calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, lp.sensbn, reducdE); + const float clc = (previewbl) ? settings->previewselection * 100.f : bufchro[y - ystart][x - xstart]; + const float realstrchdE = reducdE * clc; + float flia = 1.f; + float flib = 1.f; + const float chra = tmp1->a[y - ystart][x - xstart]; + const float chrb = tmp1->b[y - ystart][x - xstart]; + + float difL = (tmp1->L[y - ystart][x - xstart] - original->L[y][x]) * localFactor * reducdE; + transformed->L[y][x] = CLIP(original->L[y][x] + difL); + flia = flib = ((100.f + realstrchdE) / 100.f); + float difa = chra * flia - original->a[y][x]; + float difb = chrb * flib - original->b[y][x]; + difa *= localFactor; + difb *= localFactor; + + if (!lp.actsp) { + transformed->a[y][x] = CLIPC(original->a[y][x] + difa); + transformed->b[y][x] = CLIPC(original->b[y][x] + difb); + } + + float maxdifab = max(fabs(difa), fabs(difb)); + + if ((blshow) && lp.colorde < 0) { //show modifications whith use "b" + // (origshow && lp.colorde < 0) { //original Retinex + transformed->a[y][x] = 0.f; + transformed->b[y][x] = ampli * 8.f * difL * reducdE; + transformed->L[y][x] = CLIP(12000.f + 0.5f * ampli * difL); + + } else if ((blshow) && lp.colorde > 0) {//show modifications whithout use "b" + if (difL < 1000.f) {//if too low to be view use ab + difL += 0.5f * maxdifab; + } + + transformed->L[y][x] = CLIP(12000.f + 0.5f * ampli * difL); + transformed->a[y][x] = CLIPC(ampli * difa); + transformed->b[y][x] = CLIPC(ampli * difb); + } else if (previewbl) {//show deltaE + float difbdisp = reducdE * 10000.f * lp.colorde; + + if (transformed->L[y][x] < darklim) { //enhance dark luminance as user can see! + float dark = transformed->L[y][x]; + transformed->L[y][x] = dark * aadark + bbdark; + } + + if (lp.colorde <= 0) { + transformed->a[y][x] = 0.f; + transformed->b[y][x] = difbdisp; + } else { + transformed->a[y][x] = -difbdisp; + transformed->b[y][x] = 0.f; + } + } - if (show == 2) { - for (int y = 0; y < bfh ; y++) { - for (int x = 0; x < bfw; x++) { - datashow[y * bfw + x] = data_fft[y * bfw + x]; } } } +} - fftwf_free(data_fft04); - fftwf_free(data_tmp); - fftwf_free(data_tmp04); - fftwf_destroy_plan(dct_fw04); - /* solve the Poisson PDE in Fourier space */ - /* 1. / (float) (bfw * bfh)) is the DCT normalisation term, see libfftw */ - (void) rex_poisson_dct(data_fft, bfw, bfh, 1. / (double)(bfw * bfh)); +static void softlig(float &a, float &b, float minc, float maxc) +{ + // as Photoshop + float alpha = 0.5f * (maxc - minc); - if (show == 3) { - for (int y = 0; y < bfh ; y++) { - for (int x = 0; x < bfw; x++) { - datashow[y * bfw + x] = data_fft[y * bfw + x]; - } + if (b <= alpha) { + a = (2.f * a * b) + a * a * (maxc - 2.f * b); + } else { + a = 2.f * a * (maxc - b) + sqrt(LIM(a, 0.f, 2.f)) * (2.f * b - maxc); + } +} + + +static void softlig3(float &a, float &b) +{ + // as w3C + if (b <= 0.5f) { + a = a - (1.f - 2.f * b) * a * (1.f - a); + } else if (((2.f * b) > 1.f) && ((4.f * a) <= 1.f)) { + a = a + ((2.f * b) - 1.f) * (4.f * a * ((4.f * a) + 1.f) * (a - 1.f) + 7.f * a); + } else if (((2.f * b) > 1.f) && ((4.f * a) > 1.f)) { + a = a + ((2.f * a) - 1.f) * (pow(a, 0.5f) - a); + } + +} + + + +static void softlig2(float &a, float &b) +{ + // illusions.hu + a = pow(b, pow(2.f, (2.f * (0.5f - a)))); +} + +static void colburn(float &a, float &b) +{ + // w3C + if (b == 0.f) { + a = 0.f; + } else { + a = 1.f - std::min(1.f, (1.f - a) / b); + } +} + +static void coldodge(float &a, float &b) +{ + // w3C + if (b == 1.f) { + a = 1.f; + } else { + a = std::min(1.f, a / (1.f - b)); + } +} + +static void overlay(float &a, float &b, float minc, float maxc) +{ + float alpha = 0.5f * (maxc - minc); + + if (b <= alpha) { + a = (2.f * a * b); + } else { + a = maxc - 2.f * (1.f - a) * (maxc - b); + } +} + +static void screen(float &a, float &b, float maxc) +{ + a = 1.f - (1.f - a) * (maxc - b); +} + +static void exclusion(float &a, float &b) +{ + a = a + b - 2.f * a * b; +} + +void ImProcFunctions::transit_shapedetect2(int call, int senstype, const LabImage * bufexporig, const LabImage * bufexpfin, LabImage * originalmask, const float hueref, const float chromaref, const float lumaref, float sobelref, float meansobel, float ** blend2, struct local_params & lp, LabImage * original, LabImage * transformed, int cx, int cy, int sk) +{ + //initialize coordonates + int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); + int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); + int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); + int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); + int bfw = xend - xstart; + int bfh = yend - ystart; + + int bfhr = bfh; + int bfwr = bfw; + bool reduH = false; + bool reduW = false; + + if (lp.blurcolmask >= 0.25f && lp.fftColorMask && call == 2) { + optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, reduH, reduW, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy); + } + + bfh = bfhr; + bfw = bfwr; + + //initialize scope + float varsens = lp.sensex;//exposure + + if (senstype == 0) { //Color and light + varsens = lp.sens; + } else if (senstype == 2) { //vibrance + varsens = lp.sensv; + } else if (senstype == 9) { //shadowshighlight + varsens = lp.senshs; + } else if (senstype == 3) { //softlight + varsens = lp.senssf; + } else if (senstype == 30) { //dehaze + varsens = lp.sensh; + } else if (senstype == 8) { //TM + varsens = lp.senstm; + } else if (senstype == 10) { //local contrast + varsens = lp.senslc; + } else if (senstype == 11) { //encoding log + varsens = lp.sensilog; + } + + bool delt = lp.deltaem; + + //sobel + sobelref /= 100.f; + meansobel /= 100.f; + + sobelref = rtengine::min(sobelref, 60.f); + + const bool k = !(sobelref < meansobel && sobelref < lp.stru); //does not always work with noisy images + + sobelref = log1p(sobelref); + + //references Spot + const float refa = chromaref * cos(hueref) * 327.68f; + const float refb = chromaref * sin(hueref) * 327.68f; + const float refL = lumaref * 327.68f; + + //to preview modifications, scope, mask + const bool expshow = ((lp.showmaskexpmet == 1 || lp.showmaskexpmet == 2) && senstype == 1); + const bool vibshow = ((lp.showmaskvibmet == 1 || lp.showmaskvibmet == 2) && senstype == 2); + const bool colshow = ((lp.showmaskcolmet == 1 || lp.showmaskcolmet == 2) && senstype == 0); + const bool SHshow = ((lp.showmaskSHmet == 1 || lp.showmaskSHmet == 2) && senstype == 9); + const bool tmshow = ((lp.showmasktmmet == 1 || lp.showmasktmmet == 2) && senstype == 8); + const bool lcshow = ((lp.showmasklcmet == 1 || lp.showmasklcmet == 2) && senstype == 10); + const bool origshow = ((lp.showmasksoftmet == 5) && senstype == 3 && lp.softmet == 0); + + + const bool previewvib = ((lp.showmaskvibmet == 4) && senstype == 2); + const bool previewexp = ((lp.showmaskexpmet == 5) && senstype == 1); + const bool previewcol = ((lp.showmaskcolmet == 5) && senstype == 0); + const bool previewSH = ((lp.showmaskSHmet == 4) && senstype == 9); + const bool previewtm = ((lp.showmasktmmet == 4) && senstype == 8); + const bool previewlc = ((lp.showmasklcmet == 4) && senstype == 10); + const bool previeworig = ((lp.showmasksoftmet == 6) && senstype == 3 && lp.softmet == 0); + + float radius = 3.f / sk; + + if (senstype == 1) { + radius = (2.f + 0.2f * lp.blurexp) / sk; + } else if (senstype == 1) { + radius = (2.f + 0.2f * lp.blurcol) / sk; + } else if (senstype == 9) { + radius = (2.f + 0.2f * lp.blurSH) / sk; + } + + + std::unique_ptr origblur(new LabImage(bfw, bfh)); + std::unique_ptr origblurmask; + + //balance deltaE + float kL = lp.balance; + float kab = 1.f; + float kH = lp.balanceh; + float kch = 1.f; + balancedeltaE(kL, kab); + balancedeltaEH(kH, kch); + + kab /= SQR(327.68f); + kL /= SQR(327.68f); + + if (lp.colorde == 0) { + lp.colorde = -1;//to avoid black + } + + float ampli = 1.f + fabs(lp.colorde); + ampli = 2.f + 0.5f * (ampli - 2.f); + + float darklim = 5000.f; + float aadark = -1.f; + float bbdark = darklim; + + const bool usemaskvib = (lp.showmaskvibmet == 2 || lp.enavibMask || lp.showmaskvibmet == 4) && senstype == 2; + const bool usemaskexp = (lp.showmaskexpmet == 2 || lp.enaExpMask || lp.showmaskexpmet == 5) && senstype == 1; + const bool usemaskcol = (lp.showmaskcolmet == 2 || lp.enaColorMask || lp.showmaskcolmet == 5) && senstype == 0; + const bool usemaskSH = (lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 4) && senstype == 9; + const bool usemasktm = (lp.showmasktmmet == 2 || lp.enatmMask || lp.showmasktmmet == 4) && senstype == 8; + const bool usemasklc = (lp.showmasklcmet == 2 || lp.enalcMask || lp.showmasklcmet == 4) && senstype == 10; + const bool usemaskall = (usemaskexp || usemaskvib || usemaskcol || usemaskSH || usemasktm || usemasklc); + + //blur a little mask + if (usemaskall) { + origblurmask.reset(new LabImage(bfw, bfh)); + +#ifdef _OPENMP + #pragma omp parallel if (multiThread) +#endif + { + gaussianBlur(originalmask->L, origblurmask->L, bfw, bfh, radius); + gaussianBlur(originalmask->a, origblurmask->a, bfw, bfh, radius); + gaussianBlur(originalmask->b, origblurmask->b, bfw, bfh, radius); } } - dct_bw = fftwf_plan_r2r_2d(bfh, bfw, data_fft, data, FFTW_REDFT01, FFTW_REDFT01, FFTW_ESTIMATE | FFTW_DESTROY_INPUT); - fftwf_execute(dct_bw); - fftwf_destroy_plan(dct_fw); - fftwf_destroy_plan(dct_bw); - fftwf_free(data_fft); - fftwf_cleanup(); - - if (multiThread) { - fftwf_cleanup_threads(); - } - - if (show != 4) { - normalize_mean_dt(data, datain, bfw * bfh, 1.f); - } - - if (show == 0 || show == 4) { + if (lp.equtm && senstype == 8) { //normalize luminance for Tone mapping , at this place we can use for others senstype! + float *datain = new float[bfh * bfw]; + float *data = new float[bfh * bfw]; #ifdef _OPENMP #pragma omp parallel for #endif - for (int y = 0; y < bfh ; y++) { - for (int x = 0; x < bfw; x++) { - dataout[y * bfw + x] = CLIPLOC(multy * data[y * bfw + x]); + for (int y = ystart; y < yend; y++) + for (int x = xstart; x < xend; x++) { + datain[(y - ystart) * bfw + (x - xstart)] = original->L[y][x]; + data[(y - ystart)* bfw + (x - xstart)] = bufexporig->L[y - ystart][x - xstart]; } - } - } else if (show == 1 || show == 2 || show == 3) { - for (int y = 0; y < bfh ; y++) { + + normalize_mean_dt(data, datain, bfh * bfw, 1.f, 1.f); +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = ystart; y < yend; y++) + for (int x = xstart; x < xend; x++) { + bufexporig->L[y - ystart][x - xstart] = data[(y - ystart) * bfw + x - xstart]; + } + + delete [] datain; + delete [] data; + } + +#ifdef _OPENMP + #pragma omp parallel if (multiThread) +#endif + { +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh; y++) { for (int x = 0; x < bfw; x++) { - dataout[y * bfw + x] = CLIPLOC(multy * datashow[y * bfw + x]); + origblur->L[y][x] = original->L[y + ystart][x + xstart]; + origblur->a[y][x] = original->a[y + ystart][x + xstart]; + origblur->b[y][x] = original->b[y + ystart][x + xstart]; } } - fftwf_free(datashow); + gaussianBlur(origblur->L, origblur->L, bfw, bfh, radius); + gaussianBlur(origblur->a, origblur->a, bfw, bfh, radius); + gaussianBlur(origblur->b, origblur->b, bfw, bfh, radius); + + } + //choice between original and mask + const LabImage *maskptr = usemaskexp ? origblurmask.get() : origblur.get(); + + //parameters deltaE + const int limscope = 80; + const float mindE = 2.f + MINSCOPE * varsens * lp.thr; + const float maxdE = 5.f + MAXSCOPE * varsens * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + +#ifdef _OPENMP + #pragma omp parallel if (multiThread) +#endif + { +#ifdef __SSE2__ +// float atan2Buffer[transformed->W] ALIGNED16;//keep in case of +#endif + +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh; y++) { + + const int loy = y + ystart + cy; +#ifdef __SSE2__ + /* //keep in case of + int i = 0; + + for (; i < bfw - 3; i += 4) { + vfloat av = LVFU(maskptr->a[y][i]); + vfloat bv = LVFU(maskptr->b[y][i]); + STVFU(atan2Buffer[i], xatan2f(bv, av)); + } + + for (; i < bfw; i++) { + atan2Buffer[i] = xatan2f(maskptr->b[y][i], maskptr->a[y][i]); + } + */ +#endif + + for (int x = 0; x < bfw; x++) { + const int lox = x + xstart + cx; + int zone = 0; + float localFactor = 1.f; + const float achm = (float)lp.trans / 100.f; + + //claculate transition + if (lp.shapmet == 0) { + calcTransition(lox, loy, achm, lp, zone, localFactor); + } else if (lp.shapmet == 1) { + calcTransitionrect(lox, loy, achm, lp, zone, localFactor); + } + +// float hueh = 0; +#ifdef __SSE2__ +// hueh = atan2Buffer[x]; +#else +// hueh = xatan2f(maskptr->b[y][x], maskptr->a[y][x]); +#endif + + float rsob = 0.f; + + //claculate additive sobel to deltaE + if (blend2 && ((senstype == 1 && lp.struexp > 0.f) || ((senstype == 0) && lp.struco > 0.f))) { + const float csob = xlogf(1.f + std::min(blend2[y][x] / 100.f, 60.f) + 0.001f); + + float rs; + + if (k) { + rs = sobelref / csob; + } else { + rs = csob / sobelref; + } + + if (rs > 0.f && senstype == 1) { + rsob = 1.1f * lp.struexp * rs; + } else if (rs > 0.f && (senstype == 0)) { + rsob = 1.1f * lp.struco * rs; + } + } + + //deltaE + float abdelta2 = SQR(refa - maskptr->a[y][x]) + SQR(refb - maskptr->b[y][x]); + float chrodelta2 = SQR(sqrt(SQR(maskptr->a[y][x]) + SQR(maskptr->b[y][x])) - (chromaref * 327.68f)); + float huedelta2 = abdelta2 - chrodelta2; + + const float dE = rsob + sqrt(kab * (kch * chrodelta2 + kH * huedelta2) + kL * SQR(refL - maskptr->L[y][x])); + float reducdE; + //reduction action with deltaE + calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, varsens, reducdE); + + float cli = (bufexpfin->L[y][x] - bufexporig->L[y][x]); + float cla = (bufexpfin->a[y][x] - bufexporig->a[y][x]); + float clb = (bufexpfin->b[y][x] - bufexporig->b[y][x]); + + if (delt) { + cli = bufexpfin->L[y][x] - original->L[y + ystart][x + xstart]; + cla = bufexpfin->a[y][x] - original->a[y + ystart][x + xstart]; + clb = bufexpfin->b[y][x] - original->b[y + ystart][x + xstart]; + } + + // const float previewint = settings->previewselection; + + const float realstrdE = reducdE * cli; + const float realstradE = reducdE * cla; + const float realstrbdE = reducdE * clb; + + float factorx = localFactor; + float diflc = 0.f; + float difa = 0.f; + float difb = 0.f; + + if (zone > 0) { + //simplified transformed with deltaE and transition + transformed->L[y + ystart][x + xstart] = CLIPLOC(original->L[y + ystart][x + xstart] + factorx * realstrdE); + diflc = factorx * realstrdE; + transformed->a[y + ystart][x + xstart] = CLIPC(original->a[y + ystart][x + xstart] + factorx * realstradE); + difa = factorx * realstradE; + transformed->b[y + ystart][x + xstart] = CLIPC(original->b[y + ystart][x + xstart] + factorx * realstrbdE); + difb = factorx * realstrbdE; + float maxdifab = max(fabs(difa), fabs(difb)); + + if ((expshow || vibshow || colshow || SHshow || tmshow || lcshow || origshow) && lp.colorde < 0) { //show modifications whith use "b" + // (origshow && lp.colorde < 0) { //original Retinex + transformed->a[y + ystart][x + xstart] = 0.f; + transformed->b[y + ystart][x + xstart] = ampli * 8.f * diflc * reducdE; + transformed->L[y + ystart][x + xstart] = CLIP(12000.f + 0.5f * ampli * diflc); + + } else if ((expshow || vibshow || colshow || SHshow || tmshow || lcshow || origshow) && lp.colorde > 0) {//show modifications whithout use "b" + if (diflc < 1000.f) {//if too low to be view use ab + diflc += 0.5f * maxdifab; + } + + transformed->L[y + ystart][x + xstart] = CLIP(12000.f + 0.5f * ampli * diflc); + transformed->a[y + ystart][x + xstart] = CLIPC(ampli * difa); + transformed->b[y + ystart][x + xstart] = CLIPC(ampli * difb); + } else if (previewexp || previewvib || previewcol || previewSH || previewtm || previewlc || previeworig) {//show deltaE + float difbdisp = reducdE * 10000.f * lp.colorde; + + if (transformed->L[y + ystart][x + xstart] < darklim) { //enhance dark luminance as user can see! + float dark = transformed->L[y + ystart][x + xstart]; + transformed->L[y + ystart][x + xstart] = dark * aadark + bbdark; + } + + if (lp.colorde <= 0) { + transformed->a[y + ystart][x + xstart] = 0.f; + transformed->b[y + ystart][x + xstart] = difbdisp; + } else { + transformed->a[y + ystart][x + xstart] = -difbdisp; + transformed->b[y + ystart][x + xstart] = 0.f; + } + } + } + } + } } } -void ImProcFunctions::exposure_pde(float *dataor, float *datain, float * dataout, int bfw, int bfh, float thresh, float mod) + +void ImProcFunctions::exposure_pde(float * dataor, float * datain, float * dataout, int bfw, int bfh, float thresh, float mod) /* Jacques Desmis July 2019 ** adapted from Ipol Copyright 2009-2011 IPOL Image Processing On Line http://www.ipol.im/ */ @@ -4216,7 +6805,7 @@ void ImProcFunctions::exposure_pde(float *dataor, float *datain, float * dataout abort(); } - (void) discrete_laplacian_threshold(data_tmp, datain, bfw, bfh, thresh); + ImProcFunctions::discrete_laplacian_threshold(data_tmp, datain, bfw, bfh, thresh); if (NULL == (data_fft = (float *) fftwf_malloc(sizeof(float) * bfw * bfh))) { fprintf(stderr, "allocation error\n"); @@ -4235,7 +6824,7 @@ void ImProcFunctions::exposure_pde(float *dataor, float *datain, float * dataout /* solve the Poisson PDE in Fourier space */ /* 1. / (float) (bfw * bfh)) is the DCT normalisation term, see libfftw */ - (void) rex_poisson_dct(data_fft, bfw, bfh, 1. / (double)(bfw * bfh)); + ImProcFunctions::rex_poisson_dct(data_fft, bfw, bfh, 1. / (double)(bfw * bfh)); dct_bw = fftwf_plan_r2r_2d(bfh, bfw, data_fft, data, FFTW_REDFT01, FFTW_REDFT01, FFTW_ESTIMATE | FFTW_DESTROY_INPUT); fftwf_execute(dct_bw); @@ -4248,7 +6837,7 @@ void ImProcFunctions::exposure_pde(float *dataor, float *datain, float * dataout fftwf_cleanup_threads(); } - normalize_mean_dt(data, dataor, bfw * bfh, mod); + normalize_mean_dt(data, dataor, bfw * bfh, mod, 1.f); { #ifdef _OPENMP @@ -4261,10 +6850,13 @@ void ImProcFunctions::exposure_pde(float *dataor, float *datain, float * dataout } } } + + fftwf_free(data); + } -void ImProcFunctions::fftw_convol_blur(float *input, float *output, int bfw, int bfh, float radius, int fftkern, int algo) +void ImProcFunctions::fftw_convol_blur(float * input, float * output, int bfw, int bfh, float radius, int fftkern, int algo) { /* ** Jacques Desmis june 2019 - inspired by Copyright 2013 IPOL Image Processing On Line http://www.ipol.im/ @@ -4309,7 +6901,8 @@ void ImProcFunctions::fftw_convol_blur(float *input, float *output, int bfw, int out = (float*) fftwf_malloc(sizeof(float) * (bfw * bfh));//allocate real datas for FFT if (fftkern == 1) { //allocate memory FFT if kernel fft = 1 - kern = new float[bfw * bfh]; + // kern = new float[bfw * bfh]; + kern = (float*) fftwf_malloc(sizeof(float) * (bfw * bfh));//allocate real datas for FFT outkern = (float*) fftwf_malloc(sizeof(float) * (bfw * bfh));//allocate real datas for FFT } @@ -4370,7 +6963,9 @@ void ImProcFunctions::fftw_convol_blur(float *input, float *output, int bfw, int } fftwf_free(outkern); - delete [] kern; + fftwf_free(kern); + + // delete [] kern; } else if (fftkern == 0) {//whithout FFT kernel if (algo == 0) { @@ -4677,6 +7272,1199 @@ void ImProcFunctions::fftw_tile_blur(int GW, int GH, int tilssize, int max_numbl fftwf_cleanup(); } +void ImProcFunctions::wavcbd(wavelet_decomposition &wdspot, int level_bl, int maxlvl, + const LocwavCurve & locconwavCurve, bool & locconwavutili, float sigm, float offs, float chromalev, int sk) +{ + float mean[10]; + float meanN[10]; + float sigma[10]; + float sigmaN[10]; + float MaxP[10]; + float MaxN[10]; + Evaluate2(wdspot, mean, meanN, sigma, sigmaN, MaxP, MaxN); + float beta; + float mea[9]; + + + for (int dir = 1; dir < 4; dir++) { + for (int level = level_bl; level < maxlvl; ++level) { + int W_L = wdspot.level_W(level); + int H_L = wdspot.level_H(level); + + float **wav_L = wdspot.level_coeffs(level); + //offset + float rap = offs * mean[level] - 2.f * sigm * sigma[level]; + + if (rap > 0.f) { + mea[0] = rap; + } else { + mea[0] = mean[level] / 6.f; + } + + rap = offs * mean[level] - sigm * sigma[level]; + + if (rap > 0.f) { + mea[1] = rap; + } else { + mea[1] = mean[level] / 2.f; + } + + mea[2] = offs * mean[level]; // 50% data + mea[3] = offs * mean[level] + sigm * sigma[level] / 2.f; + mea[4] = offs * mean[level] + sigm * sigma[level]; //66% + mea[5] = offs * mean[level] + sigm * 1.2f * sigma[level]; + mea[6] = offs * mean[level] + sigm * 1.5f * sigma[level]; // + mea[7] = offs * mean[level] + sigm * 2.f * sigma[level]; //95% + mea[8] = offs * mean[level] + sigm * 2.5f * sigma[level]; //99% + + if (locconwavCurve && locconwavutili) { + + float cpMul = 200.f * (locconwavCurve[level * 55.5f] - 0.5f); + + if (cpMul > 0.f) { + cpMul *= 3.5f; + } + + cpMul /= sk; + + for (int i = 0; i < W_L * H_L; i++) { + { + float WavCL = fabsf(wav_L[dir][i]); + + //reduction amplification: max action between mean / 2 and mean + sigma + // arbitrary coefficient, we can add a slider !! + if (WavCL < mea[0]) { + beta = 0.6f; //preserve very low contrast (sky...) + } else if (WavCL < mea[1]) { + beta = 0.8f; + } else if (WavCL < mea[2]) { + beta = 1.f; //standard + } else if (WavCL < mea[3]) { + beta = 1.f; + } else if (WavCL < mea[4]) { + beta = 0.8f; //+sigma + } else if (WavCL < mea[5]) { + beta = 0.6f; + } else if (WavCL < mea[6]) { + beta = 0.4f; + } else if (WavCL < mea[7]) { + beta = 0.2f; // + 2 sigma + } else if (WavCL < mea[8]) { + beta = 0.1f; + } else { + beta = 0.0f; + } + } + + float alpha = max((1024.f + 15.f * (float) cpMul * beta) / 1024.f, 0.02f) ; + wav_L[dir][i] *= alpha * chromalev; + } + } + } + } + +} + +void ImProcFunctions::Compresslevels(float **Source, int W_L, int H_L, float compression, float detailattenuator, float thres, float mean, float maxp, float meanN, float maxN, float madL) +{ + //J.Desmis 12-2019 + + float exponent; + + // printf("maxp=%f maxn=%f\n", maxp, maxn); + if (detailattenuator > 0.f && detailattenuator < 0.05f) { + float betemp = expf(-(2.f - detailattenuator + 0.693147f)) - 1.f; //0.69315 = log(2) + exponent = 1.2f * xlogf(-betemp); + exponent /= 20.f; + } else if (detailattenuator >= 0.05f && detailattenuator < 0.25f) { + float betemp = expf(-(2.f - detailattenuator + 0.693147f)) - 1.f; + exponent = 1.2f * xlogf(-betemp); + exponent /= (-75.f * detailattenuator + 23.75f); + } else if (detailattenuator >= 0.25f) { + float betemp = expf(-(2.f - detailattenuator + 0.693147f)) - 1.f; + exponent = 1.2f * xlogf(-betemp); + exponent /= (-2.f * detailattenuator + 5.5f); + } else { + exponent = (compression - 1.0f) / 20.f; + } + + exponent += 1.f; + + + float ap = (thres - 1.f) / (maxp - mean); + float bp = 1.f - ap * mean; + + float a0 = (1.33f * thres - 1.f) / (1.f - mean); + float b0 = 1.f - a0 * mean; + + float apn = (thres - 1.f) / (maxN - meanN); + float bpn = 1.f - apn * meanN; + + float a0n = (1.33f * thres - 1.f) / (1.f - meanN); + float b0n = 1.f - a0n * meanN; + + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + float expone = 1.f; + + if (Source[y][x] >= 0.f) { + + if (Source[y][x] > mean) { + expone = 1.f + (exponent - 1.f) * (ap * Source[y][x] + bp); + } else { + expone = 1.f + (exponent - 1.f) * (a0 * Source[y][x] + b0); + } + + Source[y][x] = xexpf(xlogf(Source[y][x] + 0.05f * madL) * expone); + } else if (Source[y][x] < 0.f) { + if (-Source[y][x] > mean) { + expone = 1.f + (exponent - 1.f) * (apn * -Source[y][x] + bpn); + } else { + expone = 1.f + (exponent - 1.f) * (a0n * -Source[y][x] + b0n); + } + + Source[y][x] = -xexpf(xlogf(-Source[y][x] + 0.05f * madL) * expone); + } + } + } + +} + + +void ImProcFunctions::wavcont(wavelet_decomposition &wdspot, float ****templevel, int level_bl, int maxlvl, + const LocwavCurve & loclevwavCurve, bool & loclevwavutili, + const LocwavCurve & loccompwavCurve, bool & loccompwavutili, + const LocwavCurve & loccomprewavCurve, bool & loccomprewavutili, + float radlevblur, int process, FattalToneMappingParams &fatParams, float chromablu, float thres) +{ + float madL[10][3]; + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int dir = 1; dir < 4; dir++) { + for (int level = level_bl; level < maxlvl; ++level) { + int W_L = wdspot.level_W(level); + int H_L = wdspot.level_H(level); + float **wav_L = wdspot.level_coeffs(level); + madL[level][dir - 1] = Mad(wav_L[dir], W_L * H_L);//evaluate noise by level + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + float val = wav_L[dir][y * W_L + x]; + templevel[dir - 1][level][y][x] = val; + } + } + } + } + + if (process == 1) { //blur + for (int dir = 1; dir < 4; dir++) { + for (int level = level_bl; level < maxlvl; ++level) { + int W_L = wdspot.level_W(level); + int H_L = wdspot.level_H(level); + + if (loclevwavCurve && loclevwavutili) { + + float klev = 0.25f * (loclevwavCurve[level * 55.5f]); + #pragma omp parallel + { + gaussianBlur(templevel[dir - 1][level], templevel[dir - 1][level], W_L, H_L, radlevblur * klev * chromablu); + } + } + } + } + } + + if (process == 2) { //Dynamic compression laplacian - Huge ressources + for (int dir = 1; dir < 4; dir++) { + for (int level = level_bl; level < maxlvl; ++level) { + int W_L = wdspot.level_W(level); + int H_L = wdspot.level_H(level); + + if (loccompwavCurve && loccompwavutili) { + + float klev = (loccompwavCurve[level * 55.5f]); + fatParams.amount = 50.f * klev; + { + ToneMapFattal02(nullptr, fatParams, 3, 1, templevel[dir - 1][level], W_L, H_L, 0); + } + } + } + } + } + + if (process == 3) { //Dynamic compression wavelet + float mean[10]; + float meanN[10]; + float sigma[10]; + float sigmaN[10]; + float MaxP[10]; + float MaxN[10]; + Evaluate2(wdspot, mean, meanN, sigma, sigmaN, MaxP, MaxN); + // printf("levbl=%i maxlvl=%i\n", level_bl, maxlvl); + + for (int dir = 1; dir < 4; dir++) { + for (int level = level_bl; level < maxlvl; ++level) { + int W_L = wdspot.level_W(level); + int H_L = wdspot.level_H(level); + + if (loccomprewavCurve && loccomprewavutili) { + float klev = (loccomprewavCurve[level * 55.5f] - 0.75f); + + if (klev < 0.f) { + klev *= 2.6666f;//compression increase contraste + } else { + klev *= 4.f;//dilatation reduce contraste - detailattenuator + } + + float compression = expf(-klev); + float detailattenuator = klev; + + if (klev < 0.0f) { + detailattenuator = 0.0f; + } + + // float thresref = mean[level]; + // float thresreal = 0.1f * thres * thresref;//small values to take into account noise and artifacts + //printf("mean=%f level=%i\n", mean[level], level); + + Compresslevels(templevel[dir - 1][level], W_L, H_L, compression, detailattenuator, thres, mean[level], MaxP[level], meanN[level], MaxN[level], madL[level][dir - 1]); + } + } + } + } + + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int dir = 1; dir < 4; dir++) { + for (int level = level_bl; level < maxlvl; ++level) { + int W_L = wdspot.level_W(level); + int H_L = wdspot.level_H(level); + float **wav_L = wdspot.level_coeffs(level); + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + wav_L[dir][y * W_L + x] = templevel[dir - 1][level][y][x]; + } + } + } + } + +} + + +void ImProcFunctions::wavcontrast4(struct local_params& lp, float ** tmp, float ** tmpa, float ** tmpb, float contrast, float fatres, float radblur, float radlevblur, int bfw, int bfh, int level_bl, int level_hl, int level_br, int level_hr, int sk, bool numThreads, + const LocwavCurve & locwavCurve, bool & locwavutili, bool wavcurve, const LocwavCurve & loclevwavCurve, bool & loclevwavutili, bool wavcurvelev, + const LocwavCurve & locconwavCurve, bool & locconwavutili, bool wavcurvecon, + const LocwavCurve & loccompwavCurve, bool & loccompwavutili, bool wavcurvecomp, + const LocwavCurve & loccomprewavCurve, bool & loccomprewavutili, bool wavcurvecompre, + const LocwavCurve & locedgwavCurve, bool & locedgwavutili, + float sigm, float offs, int & maxlvl, float fatdet, float fatanch, float chromalev, float chromablu, bool blurlc, bool blurena, bool levelena, bool comprena, bool compreena, float compress, float thres) +{ + wavelet_decomposition *wdspot = new wavelet_decomposition(tmp[0], bfw, bfh, maxlvl, 1, sk, numThreads, lp.daubLen); + + //first decomposition for compress dynamic range positive values and other process + if (wdspot->memoryAllocationFailed) { + return; + } + + struct grad_params gpwav; + + maxlvl = wdspot->maxlevel(); + + int W_Lm = wdspot->level_W(maxlvl - 1); //I assume all decomposition have same W and H + + int H_Lm = wdspot->level_H(maxlvl - 1); + + if (lp.strwav != 0.f && lp.wavgradl) { + array2D factorwav(W_Lm, H_Lm); + calclocalGradientParams(lp, gpwav, 0, 0, W_Lm, H_Lm, 10); + + + for (int y = 0; y < H_Lm; y++) { + for (int x = 0; x < W_Lm; x++) { + float factor = ImProcFunctions::calcGradientFactor(gpwav, x, y); + factorwav[y][x] = factor; + factorwav[y][x] = 1.f - factorwav[y][x]; + + if (lp.strwav < 0.f) { + factorwav[y][x] *= -1.f; + } + } + } + + float mean[10]; + float meanN[10]; + float sigma[10]; + float sigmaN[10]; + float MaxP[10]; + float MaxN[10]; + Evaluate2(*wdspot, mean, meanN, sigma, sigmaN, MaxP, MaxN); + float alowg = 1.f; + float blowg = 0.f; + + if (level_hl != level_bl) { + alowg = 1.f / (level_hl - level_bl); + blowg = -alowg * level_bl; + } + + float ahighg = 1.f; + float bhighg = 0.f; + + if (level_hr != level_br) { + ahighg = 1.f / (level_hr - level_br); + bhighg = -ahighg * level_br; + } + + for (int dir = 1; dir < 4; dir++) { + for (int level = level_bl; level < maxlvl; ++level) { + int W_L = wdspot->level_W(level); + int H_L = wdspot->level_H(level); + float **wav_L = wdspot->level_coeffs(level); + + if (MaxP[level] > 0.f && mean[level] != 0.f && sigma[level] != 0.f) { + float insigma = 0.666f; //SD + float logmax = log(MaxP[level]); //log Max + float rapX = (mean[level] + sigma[level]) / MaxP[level]; //rapport between sD / max + float inx = log(insigma); + float iny = log(rapX); + float rap = inx / iny; //koef + float asig = 0.166f / sigma[level]; + float bsig = 0.5f - asig * mean[level]; + float amean = 0.5f / mean[level]; + +#ifdef _OPENMP + #pragma omp parallel for if (multiThread) +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + + float absciss; + float &val = wav_L[dir][y * W_L + x]; + + if (fabsf(val) >= (mean[level] + sigma[level])) { //for max + float valcour = xlogf(fabsf(val)); + float valc = valcour - logmax; + float vald = valc * rap; + absciss = xexpf(vald); + } else if (fabsf(val) >= mean[level]) { + absciss = asig * fabsf(val) + bsig; + } else { + absciss = amean * fabsf(val); + } + + float klev = 1.f; + + if (level >= level_hl && level <= level_hr) { + klev = 1.f; + } + + if (level_hl != level_bl) { + if (level >= level_bl && level < level_hl) { + klev = alowg * level + blowg; + } + } + + if (level_hr != level_br) { + if (level > level_hr && level <= level_br) { + klev = ahighg * level + bhighg; + } + } + + float kc = 0.5f * klev * factorwav[y][x] * absciss; + float reduceeffect = kc <= 0.f ? 1.f : 1.5f; + + float kinterm = 1.f + reduceeffect * kc; + kinterm = kinterm <= 0.f ? 0.01f : kinterm; + + val *= kinterm; + } + } + } + } + } + + + } + + //declare a and b if need + wavelet_decomposition *wdspota = nullptr; + wavelet_decomposition *wdspotb = nullptr; + + int W_L = wdspot->level_W(0); + int H_L = wdspot->level_H(0); + float *wav_L0 = wdspot->coeff0; + + FattalToneMappingParams fatParams; + fatParams.threshold = fatdet; + fatParams.anchor = fatanch; + + if (fatres > 0.f) { + fatParams.enabled = true; + fatParams.amount = fatres; + array2D bufl(W_L, H_L); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + bufl[y][x] = wav_L0[y * W_L + x]; + } + } + + ToneMapFattal02(nullptr, fatParams, 3, 1, bufl, W_L, H_L, 0); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + wav_L0[y * W_L + x] = bufl[y][x]; + } + } + + } + + + if (radblur > 0.f && blurena) { + array2D bufl(W_L, H_L); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + bufl[y][x] = wav_L0[y * W_L + x]; + } + } + + #pragma omp parallel + { + gaussianBlur(bufl, bufl, W_L, H_L, radblur); + } + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + wav_L0[y * W_L + x] = bufl[y][x]; + } + } + } + + if (compress != 0.f && compreena) { + + float Compression = expf(-compress); + float DetailBoost = compress; + + if (compress < 0.0f) { + DetailBoost = 0.0f; + } + + CompressDR(wav_L0, W_L, H_L, Compression, DetailBoost); + + } + + if (contrast != 0.) { + + double avedbl = 0.0; // use double precision for large summations + +#ifdef _OPENMP + #pragma omp parallel for reduction(+:avedbl) if (multiThread) +#endif + + for (int i = 0; i < W_L * H_L; i++) { + avedbl += wav_L0[i]; + } + + float ave = avedbl / double(W_L * H_L); + + float avg = ave / 32768.f; + avg = LIM01(avg); + double contreal = 0.6 * contrast; + DiagonalCurve resid_contrast({ + DCT_NURBS, + 0, 0, + avg - avg * (0.6 - contreal / 250.0), avg - avg * (0.6 + contreal / 250.0), + avg + (1. - avg) * (0.6 - contreal / 250.0), avg + (1. - avg) * (0.6 + contreal / 250.0), + 1, 1 + }); +#ifdef _OPENMP + #pragma omp parallel for if (multiThread) +#endif + + for (int i = 0; i < W_L * H_L; i++) { + float buf = LIM01(wav_L0[i] / 32768.f); + buf = resid_contrast.getVal(buf); + buf *= 32768.f; + wav_L0[i] = buf; + } + + } + + float alow = 1.f; + float blow = 0.f; + + if (level_hl != level_bl) { + alow = 1.f / (level_hl - level_bl); + blow = -alow * level_bl; + } + + float ahigh = 1.f; + float bhigh = 0.f; + + if (level_hr != level_br) { + ahigh = 1.f / (level_hr - level_br); + bhigh = -ahigh * level_br; + } + + int dir = 3; + int leve = maxlvl; + float ****templevel = nullptr; + + float ****templevela = nullptr; + + float ****templevelb = nullptr; + + + if (wavcurvelev || wavcurvecomp || wavcurvecompre) {//compress dynamic and blur + /* + float mean[10]; + float meanN[10]; + float sigma[10]; + float sigmaN[10]; + float MaxP[10]; + float MaxN[10]; + Evaluate2(*wdspot, mean, meanN, sigma, sigmaN, MaxP, MaxN); + */ + fatParams.enabled = wavcurvecomp; + + templevel = new float***[dir]; + + //allocate memory for 3 DIR n levels, H_L, W_L + for (int d = 0; d < dir; d++) { + templevel[d] = new float**[leve]; + + for (int k = 0; k < leve; k++) { + templevel[d][k] = new float*[H_L]; + + for (int i = 0; i < H_L; i++) { + templevel[d][k][i] = new float[W_L]; + } + } + } + + if (templevel == nullptr) { + fprintf(stderr, "allocation error\n"); + return; + } + + if (wavcurvelev && radlevblur > 0.f && blurena) { + wavcont(*wdspot, templevel, level_bl, maxlvl, loclevwavCurve, loclevwavutili, loccompwavCurve, loccompwavutili, loccomprewavCurve, loccomprewavutili, radlevblur, 1, fatParams, 1.f, 0.f); + } + + if (wavcurvecomp && comprena) { + wavcont(*wdspot, templevel, level_bl, maxlvl, loclevwavCurve, loclevwavutili, loccompwavCurve, loccompwavutili, loccomprewavCurve, loccomprewavutili, radlevblur, 2, fatParams, 1.f, 0.f); + } + + if (wavcurvecompre && compreena) { + wavcont(*wdspot, templevel, level_bl, maxlvl, loclevwavCurve, loclevwavutili, loccompwavCurve, loccompwavutili, loccomprewavCurve, loccomprewavutili, radlevblur, 3, fatParams, 1.f, thres); + } + + //free memory templevel + if (wavcurvelev || wavcurvecomp || wavcurvecompre) { + + + for (int i = 0; i < dir; i++) { + for (int j = 0; j < leve; j++) { + for (int l = 0; l < H_L; l++) { + delete [] templevel[i][j][l]; + } + } + } + + for (int i = 0; i < dir; i++) { + for (int j = 0; j < leve; j++) { + delete [] templevel[i][j]; + } + } + + for (int i = 0; i < dir; i++) { + delete [] templevel[i]; + } + + delete [] templevel; + + + } + } + + if (wavcurvecon && levelena) {//contrast by levels for luminance + wavcbd(*wdspot, level_bl, maxlvl, locconwavCurve, locconwavutili, sigm, offs, 1.f, sk); + } + +//edge sharpness begin + if (lp.edgwena && level_bl == 0 && level_br >= 3 && locedgwavCurve && locedgwavutili && lp.strengthw > 0) { //needs the first levels to work! + float mean[10]; + float meanN[10]; + float sigma[10]; + float sigmaN[10]; + float MaxP[10]; + float MaxN[10]; + Evaluate2(*wdspot, mean, meanN, sigma, sigmaN, MaxP, MaxN); + float edd = 3.f; + float eddlow = 15.f; + float eddlipinfl = 0.005f * lp.edgw + 0.4f; + float eddlipampl = 1.f + lp.basew / 50.f; + int W_L = wdspot->level_W(0);//provisory W_L H_L + int H_L = wdspot->level_H(0); + float *koeLi[12]; + float maxkoeLi[12]; + + float *koeLibuffer = nullptr; + + for (int y = 0; y < 12; y++) { + maxkoeLi[y] = 0.f; //9 + } + + koeLibuffer = new float[12 * H_L * W_L]; //12 + + for (int i = 0; i < 12; i++) { //9 + koeLi[i] = &koeLibuffer[i * W_L * H_L]; + } + + for (int j = 0; j < 12; j++) //9 + for (int i = 0; i < W_L * H_L; i++) { + koeLi[j][i] = 0.f; + } + + float *tmCBuffer = new float[H_L * W_L]; + float *tmC[H_L]; + + for (int i = 0; i < H_L; i++) { + tmC[i] = &tmCBuffer[i * W_L]; + } + + float gradw = lp.gradw; + float tloww = lp.tloww; + +#ifdef _OPENMP + #pragma omp for schedule(dynamic) collapse(2) +#endif + + for (int lvl = 0; lvl < 4; lvl++) { + for (int dir = 1; dir < 4; dir++) { + int W_L = wdspot->level_W(lvl); + int H_L = wdspot->level_H(lvl); + float **wav_L = wdspot->level_coeffs(lvl); + + calckoe(wav_L, gradw, tloww, koeLi, lvl, dir, W_L, H_L, edd, maxkoeLi, tmC); + // return convolution KoeLi and maxkoeLi of level 0 1 2 3 and Dir Horiz, Vert, Diag + } + } + + delete [] tmCBuffer; + float aamp = 1.f + lp.thigw / 100.f; + + for (int lvl = 0; lvl < 4; lvl++) { +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) +#endif + + for (int i = 1; i < H_L - 1; i++) { + for (int j = 1; j < W_L - 1; j++) { + //treatment of koeLi and maxkoeLi + float interm = 0.f; + + if (lp.lip3) {//Sobel Canny algo improve with parameters + // comparison between pixel and neighbours + const auto neigh = lp.neiwmet == 1; + const auto kneigh = neigh ? 28.f : 38.f; + const auto somm = neigh ? 40.f : 50.f; + + for (int dir = 1; dir < 4; dir++) { //neighbours proxi + koeLi[lvl * 3 + dir - 1][i * W_L + j] = (kneigh * koeLi[lvl * 3 + dir - 1][i * W_L + j] + 2.f * koeLi[lvl * 3 + dir - 1][(i - 1) * W_L + j] + 2.f * koeLi[lvl * 3 + dir - 1][(i + 1) * W_L + j] + + 2.f * koeLi[lvl * 3 + dir - 1][i * W_L + j + 1] + 2.f * koeLi[lvl * 3 + dir - 1][i * W_L + j - 1] + koeLi[lvl * 3 + dir - 1][(i - 1) * W_L + j - 1] + + koeLi[lvl * 3 + dir - 1][(i - 1) * W_L + j + 1] + koeLi[lvl * 3 + dir - 1][(i + 1) * W_L + j - 1] + koeLi[lvl * 3 + dir - 1][(i + 1) * W_L + j + 1]) / somm; + } + } + + for (int dir = 1; dir < 4; dir++) { + //here I evaluate combinaison of vert / diag / horiz...we are with multiplicators of the signal + interm += SQR(koeLi[lvl * 3 + dir - 1][i * W_L + j]); + } + + interm = sqrt(interm); + + interm *= 0.57736721f; + float kampli = 1.f; + float eps = 0.0001f; + // I think this double ratio (alph, beta) is better than arctg + + float alph = koeLi[lvl * 3][i * W_L + j] / (koeLi[lvl * 3 + 1][i * W_L + j] + eps); //ratio between horizontal and vertical + float beta = koeLi[lvl * 3 + 2][i * W_L + j] / (koeLi[lvl * 3 + 1][i * W_L + j] + eps); //ratio between diagonal and horizontal + + float alipinfl = (eddlipampl - 1.f) / (1.f - eddlipinfl); + float blipinfl = eddlipampl - alipinfl; + + //alph evaluate the direction of the gradient regularity Lipschitz + // if = 1 we are on an edge + // if 0 we are not + // we can change and use log..or Arctg but why ?? we can change if need ... + //Liamp=1 for eddlipinfl + //liamp > 1 for alp >eddlipinfl and alph < 1 + //Liamp < 1 for alp < eddlipinfl and alph > 0 + if (alph > 1.f) { + alph = 1.f / alph; + } + + if (beta > 1.f) { + beta = 1.f / beta; + } + + //take into account diagonal + //if in same value OK + //if not no edge or reduction + float bet = 1.f; + + //if(cp.lip3) {//enhance algorithm + if (alph > eddlipinfl && beta < 0.85f * eddlipinfl) { //0.85 arbitrary value ==> eliminate from edge if H V D too different + bet = beta; + } + + //} + float AmpLip = 1.f; + + if (alph > eddlipinfl) { + AmpLip = alipinfl * alph + blipinfl; //If beta low reduce kampli + kampli = SQR(bet) * AmpLip * aamp; + } else { + AmpLip = (1.f / eddlipinfl) * SQR(SQR(alph * bet)); //Strong Reduce if beta low + kampli = AmpLip / aamp; + } + + + interm *= kampli; + + if (interm < lp.tloww / eddlow) { + interm = 0.01f; //eliminate too low values + } + + //we can change this part of algo==> not equal but ponderate + koeLi[lvl * 3][i * W_L + j] = koeLi[lvl * 3 + 1][i * W_L + j] = koeLi[lvl * 3 + 2][i * W_L + j] = interm; //new value + //here KoeLi contains values where gradient is high and coef high, and eliminate low values... + } + } + } + + static const float scales[10] = {1.f, 2.f, 4.f, 8.f, 16.f, 32.f, 64.f, 128.f, 256.f, 512.f}; + float scaleskip[10]; + + for (int sc = 0; sc < 10; sc++) { + scaleskip[sc] = scales[sc] / sk; + } + + float rad = ((float)lp.radiusw) / 60.f; //radius ==> not too high value to avoid artifacts + float value = ((float)lp.strengthw) / 8.f; //strength + + if (scaleskip[1] < 1.f) { + float atten01234 = 0.80f; + value *= (atten01234 * scaleskip[1]); //for zoom < 100% reduce strength...I choose level 1...but!! + } + + float edge = 1.f; + float lim0 = 20.f; //arbitrary limit for low radius and level between 2 or 3 to 30 maxi + float repart = (float)lp.detailw; + float brepart; + + if (lp.edgwmet == 0) { + brepart = 3.f; + } + + if (lp.edgwmet == 2) { + brepart = 0.5f; //arbitrary value to increase / decrease repart, between 1 and 0 + } + + float arepart = - (brepart - 1.f) / (lim0 / 60.f); + + if (lp.edgwmet != 1) { + if (rad < lim0 / 60.f) { + repart *= (arepart * rad + brepart); //linear repartition of repart + } + } + + float al0 = 1.f + (repart) / 50.f; + float al10 = 1.0f; //arbitrary value ==> less = take into account high levels + float ak = - (al0 - al10) / 10.f; //10 = maximum levels + float bk = al0; + +#ifdef _OPENMP + #pragma omp for schedule(dynamic) collapse(2) +#endif + + for (int lvl = 0; lvl < maxlvl; lvl++) { + for (int dir = 1; dir < 4; dir++) { + int W_L = wdspot->level_W(lvl); + int H_L = wdspot->level_H(lvl); + float **wav_L = wdspot->level_coeffs(lvl); + float lev = float (lvl); + + float koef = ak * lvl + bk; //modulate for levels : more levels high, more koef low ==> concentrated action on low levels, without or near for high levels + float expkoef = -pow(fabs(rad - lev), koef); //reduce effect for high levels + + if (lp.edgwmet == 2) { + if (rad < lim0 / 60.f && lvl == 0) { + expkoef *= abs(repart); //reduce effect for low values of rad and level=0==> quasi only level 1 is effective + } + } + + if (lp.edgwmet == 0) { + if (rad < lim0 / 60.f && lvl == 1) { + expkoef /= repart; //increase effect for low values of rad and level=1==> quasi only level 0 is effective + } + } + + + //take into account local contrast + float refin = value * exp(expkoef); + float edgePrecalc = 1.f + refin; //estimate edge "pseudo variance" + + + if (MaxP[lvl] > 0.f) { //curve + float insigma = 0.666f; //SD + float logmax = log(MaxP[lvl]); //log Max + float rapX = (mean[lvl] + sigma[lvl]) / MaxP[lvl]; //rapport between sD / max + float inx = log(insigma); + float iny = log(rapX); + float rap = inx / iny; //koef + float asig = 0.166f / sigma[lvl]; + float bsig = 0.5f - asig * mean[lvl]; + float amean = 0.5f / mean[lvl]; + float absciss = 0.f; + float kinterm; + float kmul; + int borderL = 1; + + for (int i = borderL; i < H_L - borderL; i++) { + for (int j = borderL; j < W_L - borderL; j++) { + int k = i * W_L + j; + + + if (lvl < 4) { + edge = 1.f + (edgePrecalc - 1.f) * (koeLi[lvl * 3][k]) / (1.f + 0.9f * maxkoeLi[lvl * 3 + dir - 1]); + } else { + edge = edgePrecalc; + } + + if (fabs(wav_L[dir][k]) >= (mean[lvl] + sigma[lvl])) { //for max + float valcour = log(fabs(wav_L[dir][k])); + float valc = valcour - logmax; + float vald = valc * rap; + absciss = exp(vald); + + } else if (fabs(wav_L[dir][k]) >= mean[lvl] && fabs(wav_L[dir][k]) < (mean[lvl] + sigma[lvl])) { + absciss = asig * fabs(wav_L[dir][k]) + bsig; + } else if (fabs(wav_L[dir][k]) < mean[lvl]) { + absciss = amean * fabs(wav_L[dir][k]); + } + + // Threshold adjuster settings==> approximative for curve + //kmul about average cbrt(3--40 / 10)==>1.5 to 2.5 + //kmul about SD 10--60 / 35 ==> 2 + // kmul about low cbrt((5.f+cp.edg_low)/5.f);==> 1.5 + // kmul about max ==> 9 + // we can change these values + // result is different not best or bad than threshold slider...but similar + float abssd = 4.f; //amplification reference + float bbssd = 2.f; //mini ampli + float maxamp = 2.5f; //maxi ampli at end + float maxampd = 10.f; //maxi ampli at end + float a_abssd = (maxamp - abssd) / 0.333f; + float b_abssd = maxamp - a_abssd; + float da_abssd = (maxampd - abssd) / 0.333f; + float db_abssd = maxampd - da_abssd; + float am = (abssd - bbssd) / 0.666f; + float kmuld = 0.f; + + if (absciss > 0.666f && absciss < 1.f) { + kmul = a_abssd * absciss + b_abssd; //about max ==> kinterm + kmuld = da_abssd * absciss + db_abssd; + } else { + kmul = kmuld = absciss * am + bbssd; + } + + kinterm = 1.f; + float kc = kmul * (locedgwavCurve[absciss * 500.f] - 0.5f); + float kcd = kmuld * (locedgwavCurve[absciss * 500.f] - 0.5f); + + if (kc >= 0.f) { + float reduceeffect = 0.6f; + kinterm = 1.f + reduceeffect * kmul * (locedgwavCurve[absciss * 500.f] - 0.5f); //about 1 to 3 general and big amplification for max (under 0) + } else { + kinterm = 1.f - (SQR(kcd)) / 10.f; + } + + if (kinterm < 0.f) { + kinterm = 0.01f; + } + + edge *= kinterm; + + if (edge < 1.f) { + edge = 1.f; + } + + wav_L[dir][k] *= edge; + } + } + } + } + } + + if (koeLibuffer) { + delete [] koeLibuffer; + } + + } + +//edge sharpness end + + if (locwavCurve && locwavutili && wavcurve) {//simple local contrast in function luminance + float mean[10]; + float meanN[10]; + float sigma[10]; + float sigmaN[10]; + float MaxP[10]; + float MaxN[10]; + Evaluate2(*wdspot, mean, meanN, sigma, sigmaN, MaxP, MaxN); + + for (int dir = 1; dir < 4; dir++) { + for (int level = level_bl; level < maxlvl; ++level) { + int W_L = wdspot->level_W(level); + int H_L = wdspot->level_H(level); + float **wav_L = wdspot->level_coeffs(level); + + // printf("W_L=%i H_L=%i lev=%i\n", W_L, H_L, level); + if (MaxP[level] > 0.f && mean[level] != 0.f && sigma[level] != 0.f) { + float insigma = 0.666f; //SD + float logmax = log(MaxP[level]); //log Max + float rapX = (mean[level] + sigma[level]) / MaxP[level]; //rapport between sD / max + float inx = log(insigma); + float iny = log(rapX); + float rap = inx / iny; //koef + float asig = 0.166f / sigma[level]; + float bsig = 0.5f - asig * mean[level]; + float amean = 0.5f / mean[level]; + +#ifdef _OPENMP + #pragma omp parallel for if (multiThread) +#endif + + for (int i = 0; i < W_L * H_L; i++) { + if (locwavCurve && locwavutili) { + float absciss; + float &val = wav_L[dir][i]; + + if (fabsf(val) >= (mean[level] + sigma[level])) { //for max + float valcour = xlogf(fabsf(val)); + float valc = valcour - logmax; + float vald = valc * rap; + absciss = xexpf(vald); + } else if (fabsf(val) >= mean[level]) { + absciss = asig * fabsf(val) + bsig; + } else { + absciss = amean * fabsf(val); + } + + float klev = 1.f; + + if (level >= level_hl && level <= level_hr) { + klev = 1.f; + } + + if (level_hl != level_bl) { + if (level >= level_bl && level < level_hl) { + klev = alow * level + blow; + } + } + + if (level_hr != level_br) { + if (level > level_hr && level <= level_br) { + klev = ahigh * level + bhigh; + } + } + + float kc = klev * (locwavCurve[absciss * 500.f] - 0.5f); + float reduceeffect = kc <= 0.f ? 1.f : 1.5f; + + float kinterm = 1.f + reduceeffect * kc; + kinterm = kinterm <= 0.f ? 0.01f : kinterm; + + val *= kinterm; + } + } + } + } + } + } + + //reconstruct all for L + wdspot->reconstruct(tmp[0], 1.f); + delete wdspot; + + if (wavcurvecon && (chromalev != 1.f) && levelena) { // a and b if need ) {//contrast by levels for chroma a and b + wdspota = new wavelet_decomposition(tmpa[0], bfw, bfh, maxlvl, 1, sk, numThreads, lp.daubLen); + + if (wdspota->memoryAllocationFailed) { + return; + } + + wavcbd(*wdspota, level_bl, maxlvl, locconwavCurve, locconwavutili, sigm, offs, chromalev, sk); + wdspota->reconstruct(tmpa[0], 1.f); + delete wdspota; + + wdspotb = new wavelet_decomposition(tmpb[0], bfw, bfh, maxlvl, 1, sk, numThreads, lp.daubLen); + + if (wdspotb->memoryAllocationFailed) { + return; + } + + wavcbd(*wdspotb, level_bl, maxlvl, locconwavCurve, locconwavutili, sigm, offs, chromalev, sk); + wdspotb->reconstruct(tmpb[0], 1.f); + delete wdspotb; + + } + + if (wavcurvelev && radlevblur > 0.f && blurena) {//chroma blur if need + if (!blurlc) { + // a + wdspota = new wavelet_decomposition(tmpa[0], bfw, bfh, maxlvl, 1, sk, numThreads, lp.daubLen); + + if (wdspota->memoryAllocationFailed) { + return; + } + + templevela = new float***[dir]; + + for (int d = 0; d < dir; d++) { + templevela[d] = new float**[leve]; + + for (int k = 0; k < leve; k++) { + templevela[d][k] = new float*[H_L]; + + for (int i = 0; i < H_L; i++) { + templevela[d][k][i] = new float[W_L]; + } + } + } + + if (templevela == nullptr) { + fprintf(stderr, "allocation error\n"); + return; + } + + if (wavcurvelev && radlevblur > 0.f) { + wavcont(*wdspota, templevela, level_bl, maxlvl, loclevwavCurve, loclevwavutili, loccompwavCurve, loccompwavutili, loccomprewavCurve, loccomprewavutili, radlevblur, 1, fatParams, chromablu, 0.f); + } + + wdspota->reconstruct(tmpa[0], 1.f); + delete wdspota; + + for (int i = 0; i < dir; i++) { + for (int j = 0; j < leve; j++) { + for (int l = 0; l < H_L; l++) { + delete [] templevela[i][j][l]; + } + } + } + + for (int i = 0; i < dir; i++) { + for (int j = 0; j < leve; j++) { + delete [] templevela[i][j]; + } + } + + for (int i = 0; i < dir; i++) { + delete [] templevela[i]; + } + + delete [] templevela; + + + //b + wdspotb = new wavelet_decomposition(tmpb[0], bfw, bfh, maxlvl, 1, sk, numThreads, lp.daubLen); + + if (wdspotb->memoryAllocationFailed) { + return; + } + + + templevelb = new float***[dir]; + + for (int d = 0; d < dir; d++) { + templevelb[d] = new float**[leve]; + + for (int k = 0; k < leve; k++) { + templevelb[d][k] = new float*[H_L]; + + for (int i = 0; i < H_L; i++) { + templevelb[d][k][i] = new float[W_L]; + } + } + } + + if (templevelb == nullptr) { + fprintf(stderr, "allocation error\n"); + return; + } + + if (wavcurvelev && radlevblur > 0.f) { + wavcont(*wdspotb, templevelb, level_bl, maxlvl, loclevwavCurve, loclevwavutili, loccompwavCurve, loccompwavutili, loccomprewavCurve, loccomprewavutili, radlevblur, 1, fatParams, chromablu, 0.f); + } + + wdspotb->reconstruct(tmpb[0], 1.f); + delete wdspotb; + + for (int i = 0; i < dir; i++) { + for (int j = 0; j < leve; j++) { + for (int l = 0; l < H_L; l++) { + delete [] templevelb[i][j][l]; + } + } + } + + for (int i = 0; i < dir; i++) { + for (int j = 0; j < leve; j++) { + delete [] templevelb[i][j]; + } + } + + for (int i = 0; i < dir; i++) { + delete [] templevelb[i]; + } + + delete [] templevelb; + + + } + } + +} void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_numblox_W, float **tmp1, array2D *Lin, int numThreads, const struct local_params & lp, int chrom) @@ -4691,6 +8479,7 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu float *Lbloxtmp = reinterpret_cast(fftwf_malloc(max_numblox_W * TS * TS * sizeof(float))); float *fLbloxtmp = reinterpret_cast(fftwf_malloc(max_numblox_W * TS * TS * sizeof(float))); + float params_Ldetail = 0.f; int nfwd[2] = {TS, TS}; @@ -4714,8 +8503,8 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu for (int j = 0; j < TS; ++j) { float j1 = abs((j > TS / 2 ? j - TS + 1 : j)); - tilemask_in[i][j] = (vmask * (j1 < border ? SQR(sin((rtengine::RT_PI_F * j1) / (2 * border))) : 1.0f)) + epsilon; - tilemask_out[i][j] = (vmask2 * (j1 < 2 * border ? SQR(sin((rtengine::RT_PI_F * j1) / (2 * border))) : 1.0f)) + epsilon; + tilemask_in[i][j] = (vmask * (j1 < border ? SQR(sin((rtengine::RT_PI_F * j1) / (2 * border))) : 1.0f)) + epsilonw; + tilemask_out[i][j] = (vmask2 * (j1 < 2 * border ? SQR(sin((rtengine::RT_PI_F * j1) / (2 * border))) : 1.0f)) + epsilonw; } } @@ -4726,8 +8515,8 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu - const int numblox_W = ceil((static_cast(GW)) / (offset)) + 2 * blkrad; - const int numblox_H = ceil((static_cast(GH)) / (offset)) + 2 * blkrad; + const int numblox_W = ceil((static_cast(GW)) / (offset1)) + 2 * blkrad; + const int numblox_H = ceil((static_cast(GH)) / (offset1)) + 2 * blkrad; //residual between input and denoised L channel @@ -4751,19 +8540,17 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu #else int subThread = 0; #endif - float blurbuffer[TS * TS] ALIGNED64; float *Lblox = LbloxArray[subThread]; float *fLblox = fLbloxArray[subThread]; - float pBuf[GW + TS + 2 * blkrad * offset] ALIGNED16; - float nbrwt[TS * TS] ALIGNED64; + float pBuf[GW + TS + 2 * blkrad * offset1] ALIGNED16; #ifdef _OPENMP #pragma omp for #endif for (int vblk = 0; vblk < numblox_H; ++vblk) { - int top = (vblk - blkrad) * offset; - float * datarow = pBuf + blkrad * offset; + int top = (vblk - blkrad) * offset1; + float * datarow = pBuf + blkrad * offset1; for (int i = 0; i < TS; ++i) { int row = top + i; @@ -4779,17 +8566,17 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu datarow[j] = ((*Lin)[rr][j] - tmp1[rr][j]); } - for (int j = -blkrad * offset; j < 0; ++j) { + for (int j = -blkrad * offset1; j < 0; ++j) { datarow[j] = datarow[MIN(-j, GW - 1)]; } - for (int j = GW; j < GW + TS + blkrad * offset; ++j) { + for (int j = GW; j < GW + TS + blkrad * offset1; ++j) { datarow[j] = datarow[MAX(0, 2 * GW - 2 - j)]; }//now we have a padded data row //now fill this row of the blocks with Lab high pass data for (int hblk = 0; hblk < numblox_W; ++hblk) { - int left = (hblk - blkrad) * offset; + int left = (hblk - blkrad) * offset1; int indx = (hblk) * TS; //index of block in malloc if (top + i >= 0 && top + i < GH) { @@ -4828,7 +8615,7 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // now process the vblk row of blocks for noise reduction - float params_Ldetail = 0.f; +// float params_Ldetail = 0.f; float noisevar_Ldetail = 1.f; if (chrom == 0) { @@ -4836,7 +8623,8 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu noisevar_Ldetail = SQR(static_cast(SQR(100. - params_Ldetail) + 50.*(100. - params_Ldetail)) * TS * 0.5f); } else if (chrom == 1) { params_Ldetail = min(float(lp.noisechrodetail), 99.9f); - noisevar_Ldetail = 100.f * pow((static_cast(SQR(100. - params_Ldetail) + 50.*(100. - params_Ldetail)) * TS * 0.5f), 2);//to test ??? + // noisevar_Ldetail = 100.f * pow((static_cast(SQR(100. - params_Ldetail) + 50.*(100. - params_Ldetail)) * TS * 0.5f), 2);//to test ??? + noisevar_Ldetail = 100.f * pow((static_cast(SQR(100. - params_Ldetail)) * TS * 0.5f), 2);//to test ??? } // float noisevar_Ldetail = SQR(static_cast(SQR(100. - params_Ldetail) + 50.*(100. - params_Ldetail)) * TS * 0.5f); @@ -4844,7 +8632,8 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu for (int hblk = 0; hblk < numblox_W; ++hblk) { - ImProcFunctions::RGBtile_denoise(fLblox, hblk, noisevar_Ldetail, nbrwt, blurbuffer); + ImProcFunctions::RGBtile_denoise(fLblox, hblk, noisevar_Ldetail); + }//end of horizontal block loop //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -4856,7 +8645,7 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu fftwf_execute_r2r(plan_backward_blox[1], fLblox, Lblox); //for DCT } - int topproc = (vblk - blkrad) * offset; + int topproc = (vblk - blkrad) * offset1; //add row of blocks to output image tile ImProcFunctions::RGBoutput_tile_row(Lblox, Ldetail, tilemask_out, GH, GW, topproc); @@ -4868,6 +8657,35 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% } + //Threshold DCT from Alberto Grigio + const int detail_thresh = lp.detailthr; + array2D mask; + float scalea = 1.f; + + if (detail_thresh > 0) { + mask(GW, GH); + float thr = log2lin(float(detail_thresh) / 200.f, 100.f); + buildBlendMask(tmp1, mask, GW, GH, thr); + float r = 20.f / scalea; + + if (r > 0) { + float **m = mask; + gaussianBlur(m, m, GW, GH, r); + } + + array2D m2(GW, GH); + const float alfa = 0.856f; + const float beta = 1.f + std::sqrt(log2lin(thr, 100.f)); + buildGradientsMask(GW, GH, tmp1, m2, params_Ldetail / 100.f, 7, 3, alfa, beta, multiThread); + + for (int i = 0; i < GH; ++i) { + for (int j = 0; j < GW; ++j) { + mask[i][j] *= m2[i][j]; + } + } + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #ifdef _OPENMP @@ -4876,11 +8694,20 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu for (int i = 0; i < GH; ++i) { for (int j = 0; j < GW; ++j) { + float d = Ldetail[i][j] / totwt[i][j]; + + if (detail_thresh > 0) { + d *= mask[i][j]; + } + //may want to include masking threshold for large hipass data to preserve edges/detail - tmp1[i][j] += Ldetail[i][j] / totwt[i][j]; //note that labdn initially stores the denoised hipass data + tmp1[i][j] += d; } } + mask.free(); +//end Threshold DCT + delete Lin; @@ -4899,44 +8726,1365 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu } -void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * original, LabImage * transformed, LabImage * reserved, int cx, int cy, int oW, int oH, int sk, - const LocretigainCurve & locRETgainCcurve, LUTf & lllocalcurve, bool & locallutili, const LocLHCurve & loclhCurve, const LocHHCurve & lochhCurve, const LocCCmaskCurve & locccmasCurve, bool & lcmasutili, const LocLLmaskCurve & locllmasCurve, bool & llmasutili, const LocHHmaskCurve & lochhmasCurve, bool &lhmasutili, const LocCCmaskexpCurve & locccmasexpCurve, bool &lcmasexputili, const LocLLmaskexpCurve & locllmasexpCurve, bool &llmasexputili, const LocHHmaskexpCurve & lochhmasexpCurve, bool & lhmasexputili, - const LocCCmaskSHCurve & locccmasSHCurve, bool &lcmasSHutili, const LocLLmaskSHCurve & locllmasSHCurve, bool &llmasSHutili, const LocHHmaskSHCurve & lochhmasSHCurve, bool & lhmasSHutili, - const LocCCmaskcbCurve & locccmascbCurve, bool &lcmascbutili, const LocLLmaskcbCurve & locllmascbCurve, bool &llmascbutili, const LocHHmaskcbCurve & lochhmascbCurve, bool & lhmascbutili, - const LocCCmaskretiCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskretiCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskretiCurve & lochhmasretiCurve, bool & lhmasretiutili, - const LocCCmasktmCurve & locccmastmCurve, bool &lcmastmutili, const LocLLmasktmCurve & locllmastmCurve, bool &llmastmutili, const LocHHmasktmCurve & lochhmastmCurve, bool & lhmastmutili, - const LocwavCurve & locwavCurve, - bool & LHutili, bool & HHutili, LUTf & cclocalcurve, bool & localcutili, bool & localexutili, LUTf & exlocalcurve, LUTf & hltonecurveloc, LUTf & shtonecurveloc, LUTf & tonecurveloc, LUTf & lightCurveloc, double & huerefblur, double &chromarefblur, double & lumarefblur, double & hueref, double & chromaref, double & lumaref, double & sobelref, int llColorMask, int llExpMask, int llSHMask, int llcbMask, int llretiMask, int llsoftMask, int lltmMask) +void ImProcFunctions::DeNoise(int call, int del, float * slidL, float * slida, float * slidb, int aut, bool noiscfactiv, struct local_params & lp, LabImage * originalmaskbl, int levred, float huerefblur, float lumarefblur, float chromarefblur, LabImage * original, LabImage * transformed, int cx, int cy, int sk) { - /* comment on processus deltaE - * the algo uses 3 different ways to manage deltaE according to the type of intervention - * if we call "applyproc" : the datas produced upstream in bfw, bfh coordinate by the function producing something curves, retinex, exposure, etc. - * direct : in this case we use directly the datas produced upstream by "applyproc", with only a regulation produce for deltaE by reducdE - * direct : we found in this case "applyproc" modify data with low amplitude : BlurNoise, CBDL, Denoise, Sharp, TM +//local denoise + //all these variables are to prevent use of denoise when non necessary + // but with qualmet = 2 (default for best quality) we must denoise chroma with little values to prevent artifacts due to variations of Hue + // but if user select volontary denoise, it is that choice the good (prioritary) + bool execcolor = (lp.chro != 0.f || lp.ligh != 0.f || lp.cont != 0); // only if one slider ore more is engaged + bool execbdl = (lp.mulloc[0] != 1.f || lp.mulloc[1] != 1.f || lp.mulloc[2] != 1.f || lp.mulloc[3] != 1.f || lp.mulloc[4] != 1.f || lp.mulloc[5] != 1.f) ;//only if user want cbdl + bool execdenoi = noiscfactiv && ((lp.colorena && execcolor) || (lp.tonemapena && lp.strengt != 0.f) || (lp.cbdlena && execbdl) || (lp.sfena && lp.strng > 0.f) || (lp.lcena && lp.lcamount > 0.f) || (lp.sharpena && lp.shrad > 0.42) || (lp.retiena && lp.str > 0.f) || (lp.exposena && lp.expcomp != 0.f) || (lp.expvib && lp.past != 0.f)); - * with first use of "buflight" on which is apply "applyproc", in this case we apply realstrdE = reducdE * buflight with a function of type 328.f * realstrdE - * in this case we found "applyproc" which result in direct use on Luminance : Exposure, Color and Light, Shadows highlight, SoftLight, Local contrast + if (((lp.noiself > 0.f || lp.noiself0 > 0.f || lp.noiself2 > 0.f || lp.noiselc > 0.f || lp.noisecf > 0.f || lp.noisecc > 0.f + || lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4 || aut == 1 || aut == 2) && lp.denoiena) || execdenoi) { // sk == 1 ?? - * with second use of "buflight" on which is apply "applyproc", in this case we apply realstrdE = reducdE * buflight with a function of type fli = (100.f + realstrdE) / 100.f; - * in this case we found "applyproc" which result in large variations of L : Retinex + StopWatch Stop1("locallab Denoise called"); - * if you change you must test before + if (aut == 0) { + MyMutex::MyLock lock(*fftwMutex); + } - */ + if (lp.noisecf >= 0.01f || lp.noisecc >= 0.01f || aut == 1 || aut == 2) { + noiscfactiv = false; + levred = 7; + } + + int GW = transformed->W; + int GH = transformed->H; + + +#ifdef _OPENMP + const int numThreads = omp_get_max_threads(); +#else + const int numThreads = 1; + +#endif + + if (call == 1 && GW >= mDEN && GH >= mDEN) { + + + LabImage tmp1(transformed->W, transformed->H); + LabImage tmp2(transformed->W, transformed->H); + tmp2.clear(); + + array2D *Lin = nullptr; + array2D *Ain = nullptr; + array2D *Bin = nullptr; + + + int GW = transformed->W; + int GH = transformed->H; + int max_numblox_W = ceil((static_cast(GW)) / (offset1)) + 2 * blkrad; + // calculate min size of numblox_W. + int min_numblox_W = ceil((static_cast(GW)) / (offset1)) + 2 * blkrad; + + + for (int ir = 0; ir < GH; ir++) + for (int jr = 0; jr < GW; jr++) { + tmp1.L[ir][jr] = original->L[ir][jr]; + tmp1.a[ir][jr] = original->a[ir][jr]; + tmp1.b[ir][jr] = original->b[ir][jr]; + } + + // int DaubLen = 6; + + int levwavL = levred; + int skip = 1; + + wavelet_decomposition Ldecomp(tmp1.L[0], tmp1.W, tmp1.H, levwavL, 1, skip, numThreads, lp.daubLen); + wavelet_decomposition adecomp(tmp1.a[0], tmp1.W, tmp1.H, levwavL, 1, skip, numThreads, lp.daubLen); + wavelet_decomposition bdecomp(tmp1.b[0], tmp1.W, tmp1.H, levwavL, 1, skip, numThreads, lp.daubLen); + + float madL[8][3]; + int edge = 2; + + if (!Ldecomp.memoryAllocationFailed) { + #pragma omp parallel for collapse(2) schedule(dynamic,1) + + for (int lvl = 0; lvl < levred; lvl++) { + for (int dir = 1; dir < 4; dir++) { + int Wlvl_L = Ldecomp.level_W(lvl); + int Hlvl_L = Ldecomp.level_H(lvl); + + float ** WavCoeffs_L = Ldecomp.level_coeffs(lvl); + + madL[lvl][dir - 1] = SQR(Mad(WavCoeffs_L[dir], Wlvl_L * Hlvl_L)); + } + } + + float vari[levred]; + float mxsl = 0.f; + // float mxsfl = 0.f; + + if (aut == 0) { + if (levred == 7) { + edge = 2; + vari[0] = 8.f * SQR((lp.noiself0 / 125.0) * (1.0 + lp.noiself0 / 25.0)); + vari[1] = 8.f * SQR((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0)); + vari[2] = 8.f * SQR((lp.noiself2 / 125.0) * (1.0 + lp.noiself2 / 25.0)); + + vari[3] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); + vari[4] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); + vari[5] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); + vari[6] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); + } else if (levred == 4) { + edge = 3; + vari[0] = 8.f * SQR((lp.noiself0 / 125.0) * (1.0 + lp.noiself0 / 25.0)); + vari[1] = 8.f * SQR((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0)); + vari[2] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); + vari[3] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); + + } + } else if (aut == 1 || aut == 2) { + edge = 2; + vari[0] = SQR(slidL[0]); + vari[1] = SQR(slidL[1]); + vari[2] = SQR(slidL[2]); + // float maxf01 = max(slidL[0], slidL[1]); + // mxsfl = max(maxf01, slidL[2]); + + vari[3] = SQR(slidL[3]); + vari[4] = SQR(slidL[4]); + vari[5] = SQR(slidL[5]); + vari[6] = SQR(slidL[6]); + float mxslid34 = max(slidL[3], slidL[4]); + float mxslid56 = max(slidL[5], slidL[6]); + mxsl = max(mxslid34, mxslid56); + + } + + { + float kr3 = 0.f; + float kr4 = 0.f; + float kr5 = 0.f; + + if (aut == 0 || aut == 1) { + if ((lp.noiselc < 30.f && aut == 0) || (mxsl < 30.f && aut == 1)) { + kr3 = 0.f; + kr4 = 0.f; + kr5 = 0.f; + } else if ((lp.noiselc < 50.f && aut == 0) || (mxsl < 50.f && aut == 1)) { + kr3 = 0.5f; + kr4 = 0.3f; + kr5 = 0.2f; + } else if ((lp.noiselc < 70.f && aut == 0) || (mxsl < 70.f && aut == 1)) { + kr3 = 0.7f; + kr4 = 0.5f; + kr5 = 0.3f; + } else { + kr3 = 1.f; + kr4 = 1.f; + kr5 = 1.f; + } + } else if (aut == 2) { + kr3 = 1.f; + kr4 = 1.f; + kr5 = 1.f; + } + + vari[0] = max(0.0001f, vari[0]); + vari[1] = max(0.0001f, vari[1]); + vari[2] = max(0.0001f, vari[2]); + vari[3] = max(0.0001f, kr3 * vari[3]); + + if (levred == 7) { + vari[4] = max(0.0001f, kr4 * vari[4]); + vari[5] = max(0.0001f, kr5 * vari[5]); + vari[6] = max(0.0001f, kr5 * vari[6]); + } + + + float* noisevarlum = new float[GH * GW]; + int GW2 = (GW + 1) / 2; + + float nvlh[13] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 0.7f, 0.5f}; //high value + float nvll[13] = {0.1f, 0.15f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.45f, 0.7f, 0.8f, 1.f, 1.f, 1.f}; //low value + + float seuillow = 3000.f;//low + float seuilhigh = 18000.f;//high + int i = 10 - lp.noiselequal; + float ac = (nvlh[i] - nvll[i]) / (seuillow - seuilhigh); + float bc = nvlh[i] - seuillow * ac; + //ac and bc for transition +#ifdef _OPENMP + #pragma omp parallel for + +#endif + + for (int ir = 0; ir < GH; ir++) + for (int jr = 0; jr < GW; jr++) { + float lN = tmp1.L[ir][jr]; + + if (lN < seuillow) { + noisevarlum[(ir >> 1)*GW2 + (jr >> 1)] = nvlh[i]; + } else if (lN < seuilhigh) { + noisevarlum[(ir >> 1)*GW2 + (jr >> 1)] = ac * lN + bc; + } else { + noisevarlum[(ir >> 1)*GW2 + (jr >> 1)] = nvll[i]; + } + } + + if ((lp.noiselc < 0.02f && aut == 0) || (mxsl < 1.f && (aut == 1 || aut == 2))) { + WaveletDenoiseAllL(Ldecomp, noisevarlum, madL, vari, edge, numThreads); + + } else { + + WaveletDenoiseAll_BiShrinkL(Ldecomp, noisevarlum, madL, vari, edge, numThreads); + + WaveletDenoiseAllL(Ldecomp, noisevarlum, madL, vari, edge, numThreads); + + } + + delete[] noisevarlum; + + } + } + + + float variC[levred]; + float variCb[levred]; + + float noisecfr = lp.noisecf; + float noiseccr = lp.noisecc; + + if (lp.adjch > 0.f) { + noisecfr = lp.noisecf * ((100.f + lp.adjch) / 10.f); + noiseccr = lp.noisecc + ((100.f + lp.adjch) / 10.f); + } + + float noisecfb = lp.noisecf; + float noiseccb = lp.noisecc; + + if (lp.adjch < 0.f) { + noisecfb = lp.noisecf * ((100.f - lp.adjch) / 10.f); + noiseccb = lp.noisecc * ((100.f - lp.adjch) / 10.f); + } + + + if (noisecfr < 0.f) { + noisecfr = 0.0001f; + } + + if (noiseccr < 0.f) { + noiseccr = 0.0001f; + } + + if (noisecfb < 0.f) { + noisecfb = 0.0001f; + } + + if (noiseccb < 0.f) { + noiseccb = 0.0001f; + } + + if (!adecomp.memoryAllocationFailed && !bdecomp.memoryAllocationFailed) { + float maxcfine = 0.f; + float maxccoarse = 0.f; + + if (aut == 0) { + if (levred == 7) { + edge = 2; + variC[0] = SQR(noisecfr); + variC[1] = SQR(noisecfr); + variC[2] = SQR(noisecfr); + + variC[3] = SQR(noisecfr); + variC[4] = SQR(noisecfr); + variC[5] = SQR(noiseccr); + variC[6] = SQR(noiseccr); + + variCb[0] = SQR(noisecfb); + variCb[1] = SQR(noisecfb); + variCb[2] = SQR(noisecfb); + + variCb[3] = SQR(noisecfb); + variCb[4] = SQR(noisecfb); + variCb[5] = SQR(noiseccb); + variCb[6] = SQR(noiseccb); + + } else if (levred == 4) { + edge = 3; + variC[0] = SQR(lp.noisecf / 10.0); + variC[1] = SQR(lp.noisecf / 10.0); + variC[2] = SQR(lp.noisecf / 10.0); + variC[3] = SQR(lp.noisecf / 10.0); + + variCb[0] = SQR(lp.noisecf / 10.0); + variCb[1] = SQR(lp.noisecf / 10.0); + variCb[2] = SQR(lp.noisecf / 10.0); + variCb[3] = SQR(lp.noisecf / 10.0); + + } + } else if (aut == 1 || aut == 2) { + edge = 2; + variC[0] = SQR(slida[0]); + variC[1] = SQR(slida[1]); + variC[2] = SQR(slida[2]); + variC[3] = SQR(slida[3]); + variC[4] = SQR(slida[4]); + variC[5] = SQR(slida[5]); + variC[6] = SQR(slida[6]); + float maxc01 = max(slida[0], slida[1]); + float maxc23 = max(slida[2], slida[3]); + float max03 = max(maxc01, maxc23); + float maxrf = max(max03, slida[4]); + float maxrc = max(slida[5], slida[6]); + + variCb[0] = SQR(slidb[0]); + variCb[1] = SQR(slidb[1]); + variCb[2] = SQR(slidb[2]); + variCb[3] = SQR(slidb[3]); + variCb[4] = SQR(slidb[4]); + variCb[5] = SQR(slidb[5]); + variCb[6] = SQR(slidb[6]); + float maxb01 = max(slidb[0], slidb[1]); + float maxb23 = max(slidb[2], slidb[3]); + float maxb03 = max(maxb01, maxb23); + float maxbf = max(maxb03, slidb[4]); + maxcfine = max(maxrf, maxbf); + + float maxbc = max(slidb[5], slidb[6]); + maxccoarse = max(maxrc, maxbc); + + } + + { + float minic = 0.0001f; + + if (noiscfactiv) { + minic = 0.1f;//only for artifact shape detection + } + + float k1 = 0.f; + float k2 = 0.f; + float k3 = 0.f; + + if (aut == 0 || aut == 1) { + if ((lp.noisecf < 0.2f && aut == 0) || (maxcfine < 0.2f && aut == 1)) { + k1 = 0.f; + k2 = 0.f; + k3 = 0.f; + } else if ((lp.noisecf < 0.3f && aut == 0) || (maxcfine < 0.3f && aut == 1)) { + k1 = 0.1f; + k2 = 0.0f; + k3 = 0.f; + } else if ((lp.noisecf < 0.5f && aut == 0) || (maxcfine < 0.5f && aut == 1)) { + k1 = 0.2f; + k2 = 0.1f; + k3 = 0.f; + } else if ((lp.noisecf < 0.8f && aut == 0) || (maxcfine < 0.8f && aut == 1)) { + k1 = 0.3f; + k2 = 0.25f; + k3 = 0.f; + } else if ((lp.noisecf < 1.f && aut == 0) || (maxcfine < 1.f && aut == 1)) { + k1 = 0.4f; + k2 = 0.25f; + k3 = 0.1f; + } else if ((lp.noisecf < 2.f && aut == 0) || (maxcfine < 2.f && aut == 1)) { + k1 = 0.5f; + k2 = 0.3f; + k3 = 0.15f; + } else if ((lp.noisecf < 3.f && aut == 0) || (maxcfine < 3.f && aut == 1)) { + k1 = 0.6f; + k2 = 0.45f; + k3 = 0.3f; + } else if ((lp.noisecf < 4.f && aut == 0) || (maxcfine < 4.f && aut == 1)) { + k1 = 0.7f; + k2 = 0.5f; + k3 = 0.4f; + } else if ((lp.noisecf < 5.f && aut == 0) || (maxcfine < 5.f && aut == 1)) { + k1 = 0.8f; + k2 = 0.6f; + k3 = 0.5f; + } else if ((lp.noisecf < 10.f && aut == 0) || (maxcfine < 10.f && aut == 1)) { + k1 = 0.85f; + k2 = 0.7f; + k3 = 0.6f; + } else if ((lp.noisecf < 20.f && aut == 0) || (maxcfine < 20.f && aut == 1)) { + k1 = 0.9f; + k2 = 0.8f; + k3 = 0.7f; + } else if ((lp.noisecf < 50.f && aut == 0) || (maxcfine < 50.f && aut == 1)) { + k1 = 1.f; + k2 = 1.f; + k3 = 0.9f; + + } else { + k1 = 1.f; + k2 = 1.f; + k3 = 1.f; + } + } else if (aut == 2) { + k1 = 1.f; + k2 = 1.f; + k3 = 1.f; + } + + + variC[0] = max(minic, variC[0]); + variC[1] = max(minic, k1 * variC[1]); + variC[2] = max(minic, k2 * variC[2]); + variC[3] = max(minic, k3 * variC[3]); + + variCb[0] = max(minic, variCb[0]); + variCb[1] = max(minic, k1 * variCb[1]); + variCb[2] = max(minic, k2 * variCb[2]); + variCb[3] = max(minic, k3 * variCb[3]); + + if (levred == 7) { + float k4 = 0.f; + float k5 = 0.f; + float k6 = 0.f; + + if ((lp.noisecc == 0.01f && aut == 0) || (maxccoarse == 0.1f && aut == 1)) { + k4 = 0.f; + k5 = 0.0f; + } else if ((lp.noisecc < 0.2f && aut == 0) || (maxccoarse < 0.2f && aut == 1)) { + k4 = 0.1f; + k5 = 0.0f; + } else if ((lp.noisecc < 0.5f && aut == 0) || (maxccoarse < 0.5f && aut == 1)) { + k4 = 0.15f; + k5 = 0.0f; + } else if ((lp.noisecc < 1.f && aut == 0) || (maxccoarse < 1.f && aut == 1)) { + k4 = 0.15f; + k5 = 0.1f; + } else if ((lp.noisecc < 3.f && aut == 0) || (maxccoarse < 3.f && aut == 1)) { + k4 = 0.3f; + k5 = 0.15f; + } else if ((lp.noisecc < 4.f && aut == 0) || (maxccoarse < 5.f && aut == 1)) { + k4 = 0.6f; + k5 = 0.4f; + } else if ((lp.noisecc < 6.f && aut == 0) || (maxccoarse < 6.f && aut == 1)) { + k4 = 0.8f; + k5 = 0.6f; + } else { + k4 = 1.f; + k5 = 1.f; + } + + variC[4] = max(0.0001f, k4 * variC[4]); + variC[5] = max(0.0001f, k5 * variC[5]); + variCb[4] = max(0.0001f, k4 * variCb[4]); + variCb[5] = max(0.0001f, k5 * variCb[5]); + + if ((lp.noisecc < 4.f && aut == 0) || (maxccoarse < 4.f && aut == 1)) { + k6 = 0.f; + } else if ((lp.noisecc < 5.f && aut == 0) || (maxccoarse < 5.f && aut == 1)) { + k6 = 0.4f; + } else if ((lp.noisecc < 6.f && aut == 0) || (maxccoarse < 6.f && aut == 1)) { + k6 = 0.7f; + } else { + k6 = 1.f; + } + + variC[6] = max(0.0001f, k6 * variC[6]); + variCb[6] = max(0.0001f, k6 * variCb[6]); + + } + + float* noisevarchrom = new float[GH * GW]; + //noisevarchrom in function chroma + int GW2 = (GW + 1) / 2; + float nvch = 0.6f;//high value + float nvcl = 0.1f;//low value + + if ((lp.noisecf > 100.f && aut == 0) || (maxcfine > 100.f && (aut == 1 || aut == 2))) { + nvch = 0.8f; + nvcl = 0.4f; + } + + float seuil = 4000.f;//low + float seuil2 = 15000.f;//high + //ac and bc for transition + float ac = (nvch - nvcl) / (seuil - seuil2); + float bc = nvch - seuil * ac; +#ifdef _OPENMP + #pragma omp parallel for + +#endif + + for (int ir = 0; ir < GH; ir++) + for (int jr = 0; jr < GW; jr++) { + float cN = sqrt(SQR(tmp1.a[ir][jr]) + SQR(tmp1.b[ir][jr])); + + if (cN < seuil) { + noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = nvch; + } else if (cN < seuil2) { + noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = ac * cN + bc; + } else { + noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = nvcl; + } + } + + + float noisevarab_r = 100.f; //SQR(lp.noisecc / 10.0); + + if ((lp.noisecc < 0.02f && aut == 0) || (maxccoarse < 0.1f && (aut == 1 || aut == 2))) { + WaveletDenoiseAllAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads); + WaveletDenoiseAllAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads); + } else { + WaveletDenoiseAll_BiShrinkAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads); + WaveletDenoiseAllAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads); + + WaveletDenoiseAll_BiShrinkAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads); + WaveletDenoiseAllAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads); + } + + delete[] noisevarchrom; + + } + } + + if (!Ldecomp.memoryAllocationFailed) { + Lin = new array2D(GW, GH); +#ifdef _OPENMP + #pragma omp parallel for + +#endif + + for (int i = 0; i < GH; ++i) { + for (int j = 0; j < GW; ++j) { + (*Lin)[i][j] = tmp1.L[i][j]; + } + } + + Ldecomp.reconstruct(tmp1.L[0]); + } + + if (!Ldecomp.memoryAllocationFailed && aut == 0) { + if ((lp.noiself >= 0.01f || lp.noiself0 >= 0.01f || lp.noiself2 >= 0.01f || lp.noiselc >= 0.01f) && levred == 7 && lp.noiseldetail != 100.f) { + fftw_denoise(GW, GH, max_numblox_W, min_numblox_W, tmp1.L, Lin, numThreads, lp, 0); + } + } + + if (!adecomp.memoryAllocationFailed) { + Ain = new array2D(GW, GH); +#ifdef _OPENMP + #pragma omp parallel for + +#endif + + for (int i = 0; i < GH; ++i) { + for (int j = 0; j < GW; ++j) { + (*Ain)[i][j] = tmp1.a[i][j]; + } + } + + adecomp.reconstruct(tmp1.a[0]); + } + + + if (!adecomp.memoryAllocationFailed && aut == 0) { + if ((lp.noisecf >= 0.01f || lp.noisecc >= 0.01f) && levred == 7 && lp.noisechrodetail != 100.f) { + fftw_denoise(GW, GH, max_numblox_W, min_numblox_W, tmp1.a, Ain, numThreads, lp, 1); + } + } + + + if (!bdecomp.memoryAllocationFailed) { + + Bin = new array2D(GW, GH); +#ifdef _OPENMP + #pragma omp parallel for + +#endif + + for (int i = 0; i < GH; ++i) { + for (int j = 0; j < GW; ++j) { + (*Bin)[i][j] = tmp1.b[i][j]; + } + } + + bdecomp.reconstruct(tmp1.b[0]); + } + + + if (!bdecomp.memoryAllocationFailed && aut == 0) { + if ((lp.noisecf >= 0.01f || lp.noisecc >= 0.01f) && levred == 7 && lp.noisechrodetail != 100.f) { + fftw_denoise(GW, GH, max_numblox_W, min_numblox_W, tmp1.b, Bin, numThreads, lp, 1); + } + + } + + DeNoise_Local(call, lp, originalmaskbl, levred, huerefblur, lumarefblur, chromarefblur, original, transformed, tmp1, cx, cy, sk); + + } else if (call == 2) { //simpleprocess + + int bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone + int bfw = int (lp.lx + lp.lxL) + del; + + if (bfh >= mDEN && bfw >= mDEN) { + LabImage bufwv(bfw, bfh); + bufwv.clear(true); + array2D *Lin = nullptr; + array2D *Ain = nullptr; + array2D *Bin = nullptr; + + int max_numblox_W = ceil((static_cast(bfw)) / (offset1)) + 2 * blkrad; + // calculate min size of numblox_W. + int min_numblox_W = ceil((static_cast(bfw)) / (offset1)) + 2 * blkrad; + // these are needed only for creation of the plans and will be freed before entering the parallel loop + + + int begy = lp.yc - lp.lyT; + int begx = lp.xc - lp.lxL; + int yEn = lp.yc + lp.ly; + int xEn = lp.xc + lp.lx; + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < transformed->H ; y++) //{ + for (int x = 0; x < transformed->W; x++) { + int lox = cx + x; + int loy = cy + y; + + if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) { + bufwv.L[loy - begy][lox - begx] = original->L[y][x]; + bufwv.a[loy - begy][lox - begx] = original->a[y][x]; + bufwv.b[loy - begy][lox - begx] = original->b[y][x]; + } + + } + + // int DaubLen = 6; + + int levwavL = levred; + int skip = 1; + wavelet_decomposition Ldecomp(bufwv.L[0], bufwv.W, bufwv.H, levwavL, 1, skip, numThreads, lp.daubLen); + wavelet_decomposition adecomp(bufwv.a[0], bufwv.W, bufwv.H, levwavL, 1, skip, numThreads, lp.daubLen); + wavelet_decomposition bdecomp(bufwv.b[0], bufwv.W, bufwv.H, levwavL, 1, skip, numThreads, lp.daubLen); + float madL[8][3]; + int edge = 2; + + if (!Ldecomp.memoryAllocationFailed) { + #pragma omp parallel for collapse(2) schedule(dynamic,1) + + for (int lvl = 0; lvl < levred; lvl++) { + for (int dir = 1; dir < 4; dir++) { + int Wlvl_L = Ldecomp.level_W(lvl); + int Hlvl_L = Ldecomp.level_H(lvl); + + float ** WavCoeffs_L = Ldecomp.level_coeffs(lvl); + + madL[lvl][dir - 1] = SQR(Mad(WavCoeffs_L[dir], Wlvl_L * Hlvl_L)); + } + } + + float vari[levred]; + float mxsl = 0.f; + // float mxsfl = 0.f; + + if (aut == 0) { + if (levred == 7) { + edge = 2; + vari[0] = 8.f * SQR((lp.noiself0 / 125.0) * (1.0 + lp.noiself0 / 25.0)); + vari[1] = 8.f * SQR((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0)); + vari[2] = 8.f * SQR((lp.noiself2 / 125.0) * (1.0 + lp.noiself2 / 25.0)); + + vari[3] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); + vari[4] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); + vari[5] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); + vari[6] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); + } else if (levred == 4) { + edge = 3; + vari[0] = 8.f * SQR((lp.noiself0 / 125.0) * (1.0 + lp.noiself0 / 25.0)); + vari[1] = 8.f * SQR((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0)); + vari[2] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); + vari[3] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); + + } + } else if (aut == 1 || aut == 2) { + edge = 2; + vari[0] = SQR(slidL[0]); + vari[1] = SQR(slidL[1]); + vari[2] = SQR(slidL[2]); + // float maxf01 = max(slidL[0], slidL[1]); + // mxsfl = max(maxf01, slidL[2]); + + vari[3] = SQR(slidL[3]); + vari[4] = SQR(slidL[4]); + vari[5] = SQR(slidL[5]); + vari[6] = SQR(slidL[6]); + float mxslid34 = max(slidL[3], slidL[4]); + float mxslid56 = max(slidL[5], slidL[6]); + mxsl = max(mxslid34, mxslid56); + + } + + + + // if ((lp.noiself >= 0.1f || lp.noiself0 >= 0.1f || lp.noiself2 >= 0.1f || lp.noiselc >= 0.1f || mxsl >= 0.1f || mxsfl >= 0.1f)) { + { + float kr3 = 0.f; + float kr4 = 0.f; + float kr5 = 0.f; + + if (aut == 0 || aut == 1) { + if ((lp.noiselc < 30.f && aut == 0) || (mxsl < 30.f && aut == 1)) { + kr3 = 0.f; + kr4 = 0.f; + kr5 = 0.f; + } else if ((lp.noiselc < 50.f && aut == 0) || (mxsl < 50.f && aut == 1)) { + kr3 = 0.5f; + kr4 = 0.3f; + kr5 = 0.2f; + } else if ((lp.noiselc < 70.f && aut == 0) || (mxsl < 70.f && aut == 1)) { + kr3 = 0.7f; + kr4 = 0.5f; + kr5 = 0.3f; + } else { + kr3 = 1.f; + kr4 = 1.f; + kr5 = 1.f; + } + } else if (aut == 2) { + kr3 = 1.f; + kr4 = 1.f; + kr5 = 1.f; + + } + + vari[0] = max(0.0001f, vari[0]); + vari[1] = max(0.0001f, vari[1]); + vari[2] = max(0.0001f, vari[2]); + vari[3] = max(0.0001f, kr3 * vari[3]); + + if (levred == 7) { + vari[4] = max(0.0001f, kr4 * vari[4]); + vari[5] = max(0.0001f, kr5 * vari[5]); + vari[6] = max(0.0001f, kr5 * vari[6]); + } + + // float* noisevarlum = nullptr; // we need a dummy to pass it to WaveletDenoiseAllL + float* noisevarlum = new float[bfh * bfw]; + int bfw2 = (bfw + 1) / 2; + + float nvlh[13] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 0.7f, 0.5f}; //high value + float nvll[13] = {0.1f, 0.15f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.45f, 0.7f, 0.8f, 1.f, 1.f, 1.f}; //low value + + float seuillow = 3000.f;//low + float seuilhigh = 18000.f;//high + int i = 10 - lp.noiselequal; + float ac = (nvlh[i] - nvll[i]) / (seuillow - seuilhigh); + float bc = nvlh[i] - seuillow * ac; + //ac and bc for transition +#ifdef _OPENMP + #pragma omp parallel for + +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + float lN = bufwv.L[ir][jr]; + + if (lN < seuillow) { + noisevarlum[(ir >> 1)*bfw2 + (jr >> 1)] = nvlh[i]; + } else if (lN < seuilhigh) { + noisevarlum[(ir >> 1)*bfw2 + (jr >> 1)] = ac * lN + bc; + } else { + noisevarlum[(ir >> 1)*bfw2 + (jr >> 1)] = nvll[i]; + } + } + + + if ((lp.noiselc < 0.02f && aut == 0) || (mxsl < 1.f && (aut == 1 || aut == 2))) { + WaveletDenoiseAllL(Ldecomp, noisevarlum, madL, vari, edge, numThreads); + } else { + WaveletDenoiseAll_BiShrinkL(Ldecomp, noisevarlum, madL, vari, edge, numThreads); + WaveletDenoiseAllL(Ldecomp, noisevarlum, madL, vari, edge, numThreads); + } + + delete [] noisevarlum; + + } + } + + + float variC[levred]; + float variCb[levred]; + + float noisecfr = lp.noisecf; + float noiseccr = lp.noisecc; + + if (lp.adjch > 0.f) { + noisecfr = lp.noisecf * ((100.f + lp.adjch) / 10.f); + noiseccr = lp.noisecc + ((100.f + lp.adjch) / 10.f); + } + + float noisecfb = lp.noisecf; + float noiseccb = lp.noisecc; + + if (lp.adjch < 0.f) { + noisecfb = lp.noisecf * ((100.f - lp.adjch) / 10.f); + noiseccb = lp.noisecc * ((100.f - lp.adjch) / 10.f); + } + + + if (noisecfr < 0.f) { + noisecfr = 0.0001f; + } + + if (noiseccr < 0.f) { + noiseccr = 0.0001f; + } + + if (noisecfb < 0.f) { + noisecfb = 0.0001f; + } + + if (noiseccb < 0.f) { + noiseccb = 0.0001f; + } + + + if (!adecomp.memoryAllocationFailed && !bdecomp.memoryAllocationFailed) { + float maxcfine = 0.f; + float maxccoarse = 0.f; + + if (aut == 0) { + + if (levred == 7) { + edge = 2; + variC[0] = SQR(noisecfr); + variC[1] = SQR(noisecfr); + variC[2] = SQR(noisecfr); + + variC[3] = SQR(noisecfr); + variC[4] = SQR(noisecfr); + variC[5] = SQR(noiseccr); + variC[6] = SQR(noiseccr); + + variCb[0] = SQR(noisecfb); + variCb[1] = SQR(noisecfb); + variCb[2] = SQR(noisecfb); + + variCb[3] = SQR(noisecfb); + variCb[4] = SQR(noisecfb); + variCb[5] = SQR(noiseccb); + variCb[6] = SQR(noiseccb); + + } else if (levred == 4) { + edge = 3; + variC[0] = SQR(lp.noisecf / 10.0); + variC[1] = SQR(lp.noisecf / 10.0); + variC[2] = SQR(lp.noisecf / 10.0); + variC[3] = SQR(lp.noisecf / 10.0); + + variCb[0] = SQR(lp.noisecf / 10.0); + variCb[1] = SQR(lp.noisecf / 10.0); + variCb[2] = SQR(lp.noisecf / 10.0); + variCb[3] = SQR(lp.noisecf / 10.0); + + + } + } else if (aut == 1 || aut == 2) { + edge = 2; + variC[0] = SQR(slida[0]); + variC[1] = SQR(slida[1]); + variC[2] = SQR(slida[2]); + variC[3] = SQR(slida[3]); + variC[4] = SQR(slida[4]); + variC[5] = SQR(slida[5]); + variC[6] = SQR(slida[6]); + float maxc01 = max(slida[0], slida[1]); + float maxc23 = max(slida[2], slida[3]); + float max03 = max(maxc01, maxc23); + float maxrf = max(max03, slida[4]); + float maxrc = max(slida[5], slida[6]); + + variCb[0] = SQR(slidb[0]); + variCb[1] = SQR(slidb[1]); + variCb[2] = SQR(slidb[2]); + variCb[3] = SQR(slidb[3]); + variCb[4] = SQR(slidb[4]); + variCb[5] = SQR(slidb[5]); + variCb[6] = SQR(slidb[6]); + float maxb01 = max(slidb[0], slidb[1]); + float maxb23 = max(slidb[2], slidb[3]); + float maxb03 = max(maxb01, maxb23); + float maxbf = max(maxb03, slidb[4]); + maxcfine = max(maxrf, maxbf); + + float maxbc = max(slidb[5], slidb[6]); + maxccoarse = max(maxrc, maxbc); + + } + + + + // if ((lp.noisecf >= 0.1f || lp.noisecc >= 0.1f || noiscfactiv || maxcfine >= 0.1f || maxccoarse > 0.1f)) { + { + float minic = 0.0001f; + + if (noiscfactiv) { + minic = 0.1f;//only for artifact shape detection + } + + float k1 = 0.f; + float k2 = 0.f; + float k3 = 0.f; + + if (aut == 0 || aut == 1) { + if ((lp.noisecf < 0.2f && aut == 0) || (maxcfine < 0.2f && aut == 1)) { + k1 = 0.f; + k2 = 0.f; + k3 = 0.f; + } else if ((lp.noisecf < 0.3f && aut == 0) || (maxcfine < 0.3f && aut == 1)) { + k1 = 0.1f; + k2 = 0.0f; + k3 = 0.f; + } else if ((lp.noisecf < 0.5f && aut == 0) || (maxcfine < 0.5f && aut == 1)) { + k1 = 0.2f; + k2 = 0.1f; + k3 = 0.f; + } else if ((lp.noisecf < 0.8f && aut == 0) || (maxcfine < 0.8f && aut == 1)) { + k1 = 0.3f; + k2 = 0.25f; + k3 = 0.f; + } else if ((lp.noisecf < 1.f && aut == 0) || (maxcfine < 1.f && aut == 1)) { + k1 = 0.4f; + k2 = 0.25f; + k3 = 0.1f; + } else if ((lp.noisecf < 2.f && aut == 0) || (maxcfine < 2.f && aut == 1)) { + k1 = 0.5f; + k2 = 0.3f; + k3 = 0.15f; + } else if ((lp.noisecf < 3.f && aut == 0) || (maxcfine < 3.f && aut == 1)) { + k1 = 0.6f; + k2 = 0.45f; + k3 = 0.3f; + } else if ((lp.noisecf < 4.f && aut == 0) || (maxcfine < 4.f && aut == 1)) { + k1 = 0.7f; + k2 = 0.5f; + k3 = 0.4f; + } else if ((lp.noisecf < 5.f && aut == 0) || (maxcfine < 5.f && aut == 1)) { + k1 = 0.8f; + k2 = 0.6f; + k3 = 0.5f; + } else if ((lp.noisecf < 10.f && aut == 0) || (maxcfine < 10.f && aut == 1)) { + k1 = 0.85f; + k2 = 0.7f; + k3 = 0.6f; + } else if ((lp.noisecf < 20.f && aut == 0) || (maxcfine < 20.f && aut == 1)) { + k1 = 0.9f; + k2 = 0.8f; + k3 = 0.7f; + } else if ((lp.noisecf < 50.f && aut == 0) || (maxcfine < 50.f && aut == 1)) { + k1 = 1.f; + k2 = 1.f; + k3 = 0.9f; + + } else { + k1 = 1.f; + k2 = 1.f; + k3 = 1.f; + } + } else if (aut == 2) { + k1 = 1.f; + k2 = 1.f; + k3 = 1.f; + } + + variC[0] = max(minic, variC[0]); + variC[1] = max(minic, k1 * variC[1]); + variC[2] = max(minic, k2 * variC[2]); + variC[3] = max(minic, k3 * variC[3]); + + variCb[0] = max(minic, variCb[0]); + variCb[1] = max(minic, k1 * variCb[1]); + variCb[2] = max(minic, k2 * variCb[2]); + variCb[3] = max(minic, k3 * variCb[3]); + + if (levred == 7) { + float k4 = 0.f; + float k5 = 0.f; + float k6 = 0.f; + + if ((lp.noisecc == 0.01f && aut == 0) || (maxccoarse == 0.1f && aut == 1)) { + k4 = 0.f; + k5 = 0.0f; + } else if ((lp.noisecc < 0.2f && aut == 0) || (maxccoarse < 0.2f && aut == 1)) { + k4 = 0.1f; + k5 = 0.0f; + } else if ((lp.noisecc < 0.5f && aut == 0) || (maxccoarse < 0.5f && aut == 1)) { + k4 = 0.15f; + k5 = 0.0f; + } else if ((lp.noisecc < 1.f && aut == 0) || (maxccoarse < 1.f && aut == 1)) { + k4 = 0.15f; + k5 = 0.1f; + } else if ((lp.noisecc < 3.f && aut == 0) || (maxccoarse < 3.f && aut == 1)) { + k4 = 0.3f; + k5 = 0.15f; + } else if ((lp.noisecc < 4.f && aut == 0) || (maxccoarse < 5.f && aut == 1)) { + k4 = 0.6f; + k5 = 0.4f; + } else if ((lp.noisecc < 6.f && aut == 0) || (maxccoarse < 6.f && aut == 1)) { + k4 = 0.8f; + k5 = 0.6f; + } else { + k4 = 1.f; + k5 = 1.f; + } + + + variC[4] = max(0.0001f, k4 * variC[4]); + variC[5] = max(0.0001f, k5 * variC[5]); + variCb[4] = max(0.0001f, k4 * variCb[4]); + variCb[5] = max(0.0001f, k5 * variCb[5]); + + if ((lp.noisecc < 4.f && aut == 0) || (maxccoarse < 4.f && aut == 1)) { + k6 = 0.f; + } else if ((lp.noisecc < 5.f && aut == 0) || (maxccoarse < 5.f && aut == 1)) { + k6 = 0.4f; + } else if ((lp.noisecc < 6.f && aut == 0) || (maxccoarse < 6.f && aut == 1)) { + k6 = 0.7f; + } else { + k6 = 1.f; + } + + variC[6] = max(0.0001f, k6 * variC[6]); + variCb[6] = max(0.0001f, k6 * variCb[6]); + } + + float* noisevarchrom = new float[bfh * bfw]; + int bfw2 = (bfw + 1) / 2; + float nvch = 0.6f;//high value + float nvcl = 0.1f;//low value + + if ((lp.noisecf > 100.f && aut == 0) || (maxcfine > 100.f && (aut == 1 || aut == 2))) { + nvch = 0.8f; + nvcl = 0.4f; + } + + float seuil = 4000.f;//low + float seuil2 = 15000.f;//high + //ac and bc for transition + float ac = (nvch - nvcl) / (seuil - seuil2); + float bc = nvch - seuil * ac; +#ifdef _OPENMP + #pragma omp parallel for + +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + float cN = sqrt(SQR(bufwv.a[ir][jr]) + SQR(bufwv.b[ir][jr])); + + if (cN < seuil) { + noisevarchrom[(ir >> 1)*bfw2 + (jr >> 1)] = nvch; + } else if (cN < seuil2) { + noisevarchrom[(ir >> 1)*bfw2 + (jr >> 1)] = ac * cN + bc; + } else { + noisevarchrom[(ir >> 1)*bfw2 + (jr >> 1)] = nvcl; + } + } + + float noisevarab_r = 100.f; //SQR(lp.noisecc / 10.0); + + if ((lp.noisecc < 0.02f && aut == 0) || (maxccoarse < 0.1f && (aut == 1 || aut == 2))) { + WaveletDenoiseAllAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads); + WaveletDenoiseAllAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads); + } else { + WaveletDenoiseAll_BiShrinkAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads); + WaveletDenoiseAllAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads); + + WaveletDenoiseAll_BiShrinkAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads); + WaveletDenoiseAllAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads); + } + + delete[] noisevarchrom; + } + } + + if (!Ldecomp.memoryAllocationFailed) { + Lin = new array2D(bfw, bfh); + +#ifdef _OPENMP + #pragma omp parallel for + +#endif + + for (int i = 0; i < bfh; ++i) { + for (int j = 0; j < bfw; ++j) { + (*Lin)[i][j] = bufwv.L[i][j]; + } + } + + Ldecomp.reconstruct(bufwv.L[0]); + } + + + if (!Ldecomp.memoryAllocationFailed && aut == 0) { + + + if ((lp.noiself >= 0.01f || lp.noiself0 >= 0.01f || lp.noiself2 >= 0.01f || lp.noiselc >= 0.01f) && levred == 7 && lp.noiseldetail != 100.f) { + fftw_denoise(bfw, bfh, max_numblox_W, min_numblox_W, bufwv.L, Lin, numThreads, lp, 0); + } + } + + + if (!adecomp.memoryAllocationFailed) { + Ain = new array2D(bfw, bfh); +#ifdef _OPENMP + #pragma omp parallel for + +#endif + + for (int i = 0; i < bfh; ++i) { + for (int j = 0; j < bfw; ++j) { + (*Ain)[i][j] = bufwv.a[i][j]; + } + } + + adecomp.reconstruct(bufwv.a[0]); + } + + if (!adecomp.memoryAllocationFailed && aut == 0) { + if ((lp.noisecf >= 0.001f || lp.noisecc >= 0.001f) && levred == 7 && lp.noisechrodetail != 100.f) { + fftw_denoise(bfw, bfh, max_numblox_W, min_numblox_W, bufwv.a, Ain, numThreads, lp, 1); + } + } + + + if (!bdecomp.memoryAllocationFailed) { + Bin = new array2D(bfw, bfh); +#ifdef _OPENMP + #pragma omp parallel for + +#endif + + for (int i = 0; i < bfh; ++i) { + for (int j = 0; j < bfw; ++j) { + (*Bin)[i][j] = bufwv.b[i][j]; + } + } + + bdecomp.reconstruct(bufwv.b[0]); + } + + if (!bdecomp.memoryAllocationFailed && aut == 0) { + if ((lp.noisecf >= 0.001f || lp.noisecc >= 0.001f) && levred == 7 && lp.noisechrodetail != 100.f) { + fftw_denoise(bfw, bfh, max_numblox_W, min_numblox_W, bufwv.b, Bin, numThreads, lp, 1); + } + } + + + DeNoise_Local(call, lp, originalmaskbl, levred, huerefblur, lumarefblur, chromarefblur, original, transformed, bufwv, cx, cy, sk); + } + } + } + +} + +float triangle(float a, float a1, float b) +{ + if (a != b) { + float b1; + float a2 = a1 - a; + + if (b < a) { + b1 = b + a2 * b / a ; + } else { + b1 = b + a2 * (65535.f - b) / (65535.f - a); + } + + return b1; + } + + return a1; +} + +void rgbtone(float & maxval, float & medval, float & minval, LUTf & lutToneCurve) +{ + float minvalold = minval, medvalold = medval, maxvalold = maxval; + + maxval = lutToneCurve[maxvalold]; + minval = lutToneCurve[minvalold]; + medval = minval + ((maxval - minval) * (medvalold - minvalold) / (maxvalold - minvalold)); +} + +void clarimerge(struct local_params& lp, float &mL, float &mC, bool &exec, LabImage *tmpresid, int wavelet_level, int sk, bool numThreads) +{ + if (mL != 0.f && mC == 0.f) { + mC = 0.0001f; + exec = true; + } + + if (mC != 0.f && mL == 0.f) { + mL = 0.0001f; + exec = true; + } + + if (mL != 0.f && mC != 0.f) { + exec = true; + } + + if (mL != 0.f) { + + wavelet_decomposition *wdspotresid = new wavelet_decomposition(tmpresid->L[0], tmpresid->W, tmpresid->H, wavelet_level, 1, sk, numThreads, lp.daubLen); + + if (wdspotresid->memoryAllocationFailed) { + return; + } + + int maxlvlresid = wdspotresid->maxlevel(); + + if (maxlvlresid > 4) {//Clarity + for (int dir = 1; dir < 4; dir++) { + for (int level = 0; level < maxlvlresid; ++level) { + int W_L = wdspotresid->level_W(level); + int H_L = wdspotresid->level_H(level); + float **wav_Lresid = wdspotresid->level_coeffs(level); + + for (int i = 0; i < W_L * H_L; i++) { + wav_Lresid[dir][i] = 0.f; + } + } + } + } else {//Sharp + float *wav_L0resid = wdspotresid->coeff0; + int W_L = wdspotresid->level_W(0); + int H_L = wdspotresid->level_H(0); + + for (int i = 0; i < W_L * H_L; i++) { + wav_L0resid[i] = 0.f; + } + } + + wdspotresid->reconstruct(tmpresid->L[0], 1.f); + delete wdspotresid; + } + + + if (mC != 0.f) { + + wavelet_decomposition *wdspotresida = new wavelet_decomposition(tmpresid->a[0], tmpresid->W, tmpresid->H, wavelet_level, 1, sk, numThreads, lp.daubLen); + + if (wdspotresida->memoryAllocationFailed) { + return; + } + + int maxlvlresid = wdspotresida->maxlevel(); + + if (maxlvlresid > 4) {//Clarity + for (int dir = 1; dir < 4; dir++) { + for (int level = 0; level < maxlvlresid; ++level) { + int W_L = wdspotresida->level_W(level); + int H_L = wdspotresida->level_H(level); + float **wav_Lresida = wdspotresida->level_coeffs(level); + + for (int i = 0; i < W_L * H_L; i++) { + wav_Lresida[dir][i] = 0.f; + } + } + } + } else {//Sharp + float *wav_L0resida = wdspotresida->coeff0; + int W_L = wdspotresida->level_W(0); + int H_L = wdspotresida->level_H(0); + + for (int i = 0; i < W_L * H_L; i++) { + wav_L0resida[i] = 0.f; + } + } + + wdspotresida->reconstruct(tmpresid->a[0], 1.f); + delete wdspotresida; + } + + if (mC != 0.f) { + + wavelet_decomposition *wdspotresidb = new wavelet_decomposition(tmpresid->b[0], tmpresid->W, tmpresid->H, wavelet_level, 1, sk, numThreads, lp.daubLen); + + if (wdspotresidb->memoryAllocationFailed) { + return; + } + + int maxlvlresid = wdspotresidb->maxlevel(); + + if (maxlvlresid > 4) {//Clarity + for (int dir = 1; dir < 4; dir++) { + for (int level = 0; level < maxlvlresid; ++level) { + int W_L = wdspotresidb->level_W(level); + int H_L = wdspotresidb->level_H(level); + float **wav_Lresidb = wdspotresidb->level_coeffs(level); + + for (int i = 0; i < W_L * H_L; i++) { + wav_Lresidb[dir][i] = 0.f; + } + } + } + } else {//Sharp + float *wav_L0residb = wdspotresidb->coeff0; + int W_L = wdspotresidb->level_W(0); + int H_L = wdspotresidb->level_H(0); + + for (int i = 0; i < W_L * H_L; i++) { + wav_L0residb[i] = 0.f; + } + } + + wdspotresidb->reconstruct(tmpresid->b[0], 1.f); + delete wdspotresidb; + } +} + +void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * original, LabImage * transformed, LabImage * reserved, LabImage * lastorig, int cx, int cy, int oW, int oH, int sk, + const LocretigainCurve & locRETgainCcurve, const LocretitransCurve & locRETtransCcurve, + LUTf & lllocalcurve, bool & locallutili, + LUTf & cllocalcurve, bool & localclutili, + LUTf & lclocalcurve, bool & locallcutili, + const LocLHCurve & loclhCurve, const LocHHCurve & lochhCurve, + LUTf & lmasklocalcurve, bool & localmaskutili, + LUTf & lmaskexplocalcurve, bool & localmaskexputili, + LUTf & lmaskSHlocalcurve, bool & localmaskSHutili, + LUTf & lmaskviblocalcurve, bool & localmaskvibutili, + LUTf & lmasktmlocalcurve, bool & localmasktmutili, + LUTf & lmaskretilocalcurve, bool & localmaskretiutili, + LUTf & lmaskcblocalcurve, bool & localmaskcbutili, + LUTf & lmaskbllocalcurve, bool & localmaskblutili, + LUTf & lmasklclocalcurve, bool & localmasklcutili, + const LocCCmaskCurve & locccmasCurve, bool & lcmasutili, const LocLLmaskCurve & locllmasCurve, bool & llmasutili, const LocHHmaskCurve & lochhmasCurve, bool & lhmasutili, const LocHHmaskCurve & lochhhmasCurve, bool & lhhmasutili, + const LocCCmaskCurve & locccmasexpCurve, bool & lcmasexputili, const LocLLmaskCurve & locllmasexpCurve, bool & llmasexputili, const LocHHmaskCurve & lochhmasexpCurve, bool & lhmasexputili, + const LocCCmaskCurve & locccmasSHCurve, bool & lcmasSHutili, const LocLLmaskCurve & locllmasSHCurve, bool & llmasSHutili, const LocHHmaskCurve & lochhmasSHCurve, bool & lhmasSHutili, + const LocCCmaskCurve & locccmasvibCurve, bool & lcmasvibutili, const LocLLmaskCurve & locllmasvibCurve, bool & llmasvibutili, const LocHHmaskCurve & lochhmasvibCurve, bool & lhmasvibutili, + const LocCCmaskCurve & locccmascbCurve, bool & lcmascbutili, const LocLLmaskCurve & locllmascbCurve, bool & llmascbutili, const LocHHmaskCurve & lochhmascbCurve, bool & lhmascbutili, + const LocCCmaskCurve & locccmasretiCurve, bool & lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool & llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool & lhmasretiutili, + const LocCCmaskCurve & locccmastmCurve, bool & lcmastmutili, const LocLLmaskCurve & locllmastmCurve, bool & llmastmutili, const LocHHmaskCurve & lochhmastmCurve, bool & lhmastmutili, + const LocCCmaskCurve & locccmasblCurve, bool & lcmasblutili, const LocLLmaskCurve & locllmasblCurve, bool & llmasblutili, const LocHHmaskCurve & lochhmasblCurve, bool & lhmasblutili, + const LocCCmaskCurve & locccmaslcCurve, bool & lcmaslcutili, const LocLLmaskCurve & locllmaslcCurve, bool & llmaslcutili, const LocHHmaskCurve & lochhmaslcCurve, bool & lhmaslcutili, + const LocwavCurve & loclmasCurveblwav, bool & lmasutiliblwav, + const LocwavCurve & loclmasCurvecolwav, bool & lmasutilicolwav, + const LocwavCurve & locwavCurve, bool & locwavutili, + const LocwavCurve & loclevwavCurve, bool & loclevwavutili, + const LocwavCurve & locconwavCurve, bool & locconwavutili, + const LocwavCurve & loccompwavCurve, bool & loccompwavutili, + const LocwavCurve & loccomprewavCurve, bool & loccomprewavutili, + const LocwavCurve & locwavCurveden, bool & locwavdenutili, + const LocwavCurve & locedgwavCurve, bool & locedgwavutili, + bool & LHutili, bool & HHutili, LUTf & cclocalcurve, bool & localcutili, LUTf & rgblocalcurve, bool & localrgbutili, bool & localexutili, LUTf & exlocalcurve, LUTf & hltonecurveloc, LUTf & shtonecurveloc, LUTf & tonecurveloc, LUTf & lightCurveloc, + double & huerefblur, double & chromarefblur, double & lumarefblur, double & hueref, double & chromaref, double & lumaref, double & sobelref, int &lastsav, + int llColorMask, int llColorMaskinv, int llExpMask, int llExpMaskinv, int llSHMask, int llSHMaskinv, int llvibMask, int lllcMask, int llsharMask, int llcbMask, int llretiMask, int llsoftMask, int lltmMask, int llblMask, + float & minCD, float & maxCD, float & mini, float & maxi, float & Tmean, float & Tsigma, float & Tmin, float & Tmax) +{ //general call of others functions : important return hueref, chromaref, lumaref if (params->locallab.enabled) { BENCHFUN + int complexsoft = options.complexity; #ifdef _DEBUG // init variables to display Munsell corrections MunsellDebugInfo* MunsDebugInfo = new MunsellDebugInfo(); #endif int del = 3; // to avoid crash with [loy - begy] and [lox - begx] and bfh bfw // with gtk2 [loy - begy-1] [lox - begx -1 ] and del = 1 - + int delxy = 0; struct local_params lp; - calcLocalParams(sp, oW, oH, params->locallab, lp, llColorMask, llExpMask, llSHMask, llcbMask, llretiMask, llsoftMask, lltmMask); + calcLocalParams(sp, oW, oH, params->locallab, lp, llColorMask, llColorMaskinv, llExpMask, llExpMaskinv, llSHMask, llSHMaskinv, llvibMask, lllcMask, llsharMask, llcbMask, llretiMask, llsoftMask, lltmMask, llblMask, locwavCurveden, locwavdenutili); const float radius = lp.rad / (sk * 1.4f); //0 to 70 ==> see skip int strred = 1;//(lp.strucc - 1); @@ -4953,6 +10101,8 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o noiscfactiv = false; } +//lastsav for save restore image + lastsav = 0; if (lp.excmet == 1 && call <= 3) {//exclude const int bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone @@ -4968,10 +10118,10 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o #pragma omp parallel for schedule(dynamic,16) #endif - for (int y = std::max(begy - cy, 0); y < std::min(yEn - cy, original->H); y++) { + for (int y = std::max(begy - cy, 0); y < ((std::min(yEn - cy, original->H)) + delxy); y++) { const int loy = cy + y; - for (int x = std::max(begx - cx, 0); x < std::min(xEn - cx, original->W); x++) { + for (int x = std::max(begx - cx, 0); x < ((std::min(xEn - cx, original->W)) + delxy); x++) { const int lox = cx + x; bufsob[loy - begy][lox - begx] = bufreserv.L[loy - begy][lox - begx] = reserved->L[y][x]; @@ -5025,7 +10175,986 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } +//encoding lab at the beginning + if (lp.logena) { + int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); + int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); + int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); + int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); + int bfh = yend - ystart; + int bfw = xend - xstart; + if (bfh >= mSP && bfw >= mSP) { + std::unique_ptr bufexporig(new LabImage(bfw, bfh)); //buffer for data in zone limit + std::unique_ptr bufexpfin(new LabImage(bfw, bfh)); //buffer for data in zone limit + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = ystart; y < yend; y++) { + for (int x = xstart; x < xend; x++) { + bufexporig->L[y - ystart][x - xstart] = original->L[y][x]; + bufexporig->a[y - ystart][x - xstart] = original->a[y][x]; + bufexporig->b[y - ystart][x - xstart] = original->b[y][x]; + } + } + + bufexpfin->CopyFrom(bufexporig.get()); + Imagefloat *tmpImage = nullptr; + tmpImage = new Imagefloat(bfw, bfh); + lab2rgb(*bufexpfin, *tmpImage, params->icm.workingProfile); + log_encode(tmpImage, lp, float (sk), multiThread, bfw, bfh); + + rgb2lab(*tmpImage, *bufexpfin, params->icm.workingProfile); + + delete tmpImage; + + //here begin graduated filter + //first solution "easy" but we can do other with log_encode...to see the results + if (lp.strlog != 0.f) { + struct grad_params gplog; + calclocalGradientParams(lp, gplog, ystart, xstart, bfw, bfh, 11); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + double factor = 1.0; + factor = ImProcFunctions::calcGradientFactor(gplog, jr, ir); + bufexpfin->L[ir][jr] *= factor; + } + } + + + //end graduated + transit_shapedetect2(call, 11, bufexporig.get(), bufexpfin.get(), nullptr, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } + } + } + + + +//Prepare mask for Blur and noise and Denoise + bool denoiz = false; + + if (((lp.noiself > 0.f || lp.noiself0 > 0.f || lp.noiself2 > 0.f || lp.noiselc > 0.f || lp.noisecf > 0.f || lp.noisecc > 0.f || lp.bilat > 0.f) && lp.denoiena)) { + denoiz = true; + } + + bool blurz = false; + bool delt = params->locallab.spots.at(sp).deltae; + bool astool = params->locallab.spots.at(sp).toolbl; + + if (((radius > 1.5 * GAUSS_SKIP) || lp.stren > 0.1 || lp.blmet == 1 || lp.guidb > 1 || lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) && lp.blurena) { + blurz = true; + } + + const int GW = transformed->W; + const int GH = transformed->H; + + LabImage * originalmaskbl = nullptr; + std::unique_ptr bufmaskorigbl; + std::unique_ptr bufmaskblurbl; + std::unique_ptr bufgb; + std::unique_ptr bufprov(new LabImage(GW, GH)); + + if (denoiz || blurz || lp.denoiena || lp.blurena) { + bufgb.reset(new LabImage(GW, GH)); + + if (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) { + bufmaskorigbl.reset(new LabImage(GW, GH)); + bufmaskblurbl.reset(new LabImage(GW, GH)); + originalmaskbl = new LabImage(GW, GH); + } + + array2D ble(GW, GH); + array2D blechro(GW, GH); + array2D hue(GW, GH); + array2D guid(GW, GH); + float meanfab, fab; + mean_fab(0, 0, GW, GH, bufgb.get(), original, fab, meanfab, lp.chromabl); + float chromult = 1.f - 0.01f * lp.chromabl; + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < GH; y++) { + for (int x = 0; x < GW; x++) { + bufgb->L[y][x] = original->L[y][x]; + bufgb->a[y][x] = original->a[y][x]; + bufgb->b[y][x] = original->b[y][x]; + } + } + + float strumask = 0.02f * (float) params->locallab.spots.at(sp).strumaskbl; + JaggedArray blendstru(GW, GH); + + if (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) { + + if (strumask > 0.f) { + float delstrumask = 4.1f - strumask;//4.1 = 2 * max slider strumask + 0.1 + buildBlendMask(bufgb->L, blendstru, GW, GH, delstrumask); + float radblur = 0.02f * 0.1f * fabs(lp.radmabl); + float rm = radblur / sk; + + if (rm > 0) { + float **mb = blendstru; + gaussianBlur(mb, mb, GW, GH, rm); + } + } + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < GH; ir++) { + for (int jr = 0; jr < GW; jr++) { + float kmaskLexp = 0; + float kmaskCH = 0; + float kmasstru = 0.f; + + if (strumask > 0.f && !astool) { + kmasstru = bufgb->L[ir][jr] * blendstru[ir][jr]; + } + + if (locllmasblCurve && llmasblutili) { + float ligh = bufgb->L[ir][jr] / 32768.f; + kmaskLexp = 32768.f * LIM01(1.f - locllmasblCurve[500.f * ligh]); + } + + if (lp.showmaskblmet != 4) { + if (locccmasblCurve && lcmasblutili) { + float chromask = 0.0001f + sqrt(SQR((bufgb->a[ir][jr]) / fab) + SQR((bufgb->b[ir][jr]) / fab)); + kmaskCH = LIM01(1.f - locccmasblCurve[500.f * chromask]); + } + } + + if (lochhmasblCurve && lhmasblutili) { + float huema = xatan2f(bufgb->b[ir][jr], bufgb->a[ir][jr]); + float h = Color::huelab_to_huehsv2(huema); + h += 1.f / 6.f; + + if (h > 1.f) { + h -= 1.f; + } + + float valHH = LIM01(1.f - lochhmasblCurve[500.f * h]); + + if (lp.showmaskblmet != 4) { + kmaskCH += chromult * valHH; + } + + kmaskLexp += 32768.f * valHH; + } + + bufmaskblurbl->L[ir][jr] = CLIPLOC(kmaskLexp + kmasstru); + bufmaskblurbl->a[ir][jr] = kmaskCH; + bufmaskblurbl->b[ir][jr] = kmaskCH; + ble[ir][jr] = bufmaskblurbl->L[ir][jr] / 32768.f; + hue[ir][jr] = xatan2f(bufmaskblurbl->b[ir][jr], bufmaskblurbl->a[ir][jr]); + float chromah = sqrt(SQR(bufmaskblurbl->b[ir][jr]) + SQR(bufmaskblurbl->a[ir][jr])); + blechro[ir][jr] = chromah / 32768.f; + float X, Y, Z; + float L = bufgb->L[ir][jr]; + float a = bufgb->a[ir][jr]; + float b = bufgb->b[ir][jr]; + Color::Lab2XYZ(L, a, b, X, Y, Z); + + guid[ir][jr] = Y / 32768.f; + } + } + + std::unique_ptr bufprov(new LabImage(GW, GH)); + + bufprov->CopyFrom(bufmaskblurbl.get()); + + + if (lp.radmabl != 0.f) { + float blur = lp.radmabl; + blur = blur < 0.f ? -1.f / blur : 1.f + blur; + int r1 = max(int(4 / sk * blur + 0.5), 1); + int r2 = max(int(25 / sk * blur + 0.5), 1); + + double epsilmax = 0.0005; + double epsilmin = 0.00001; + + double aepsil = (epsilmax - epsilmin) / 90.f; + double bepsil = epsilmax - 100.f * aepsil; + double epsil = aepsil * lp.radmabl + bepsil; + + if (lp.radmabl < 0.f) { + epsil = 0.001; + } + + rtengine::guidedFilter(guid, blechro, blechro, r1, epsil, multiThread); + rtengine::guidedFilter(guid, ble, ble, r2, 0.2 * epsil, multiThread); + + // guidedFilter(guid, ble, ble, lp.radmabl * 10.f / sk, 0.001, multiThread, 4); + } + + LUTf lutTonemaskbl(65536); + calcGammaLut(lp.gammabl, lp.slomabl, lutTonemaskbl); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < GH; ir++) + for (int jr = 0; jr < GW; jr++) { + float L_; + float2 sincosval = xsincosf(hue[ir][jr]); + bufmaskblurbl->L[ir][jr] = LIM01(ble[ir][jr]) * 32768.f; + L_ = 2.f * bufmaskblurbl->L[ir][jr]; + bufmaskblurbl->L[ir][jr] = lutTonemaskbl[L_]; + bufmaskblurbl->a[ir][jr] = 32768.f * sincosval.y * blechro[ir][jr]; + bufmaskblurbl->b[ir][jr] = 32768.f * sincosval.x * blechro[ir][jr]; + } + + } + + if (strumask > 0.f && astool && (lp.enablMask || lp.showmaskblmet == 3)) { + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < GH; ir++) { + for (int jr = 0; jr < GW; jr++) { + bufmaskblurbl->L[ir][jr] *= (1.f + blendstru[ir][jr]); + } + } + + } + + if (lmaskbllocalcurve && localmaskblutili && (lp.enablMask || lp.showmaskblmet == 3)) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < GH; ir++) + for (int jr = 0; jr < GW; jr++) { + bufmaskblurbl->L[ir][jr] = 0.5f * lmaskbllocalcurve[2.f * bufmaskblurbl->L[ir][jr]]; + } + } + + int wavelet_level = params->locallab.spots.at(sp).shadmaskbl; + + int minwin = min(GW, GH); + int maxlevelspot = 9; + + while ((1 << maxlevelspot) >= (minwin * sk) && maxlevelspot > 1) { + --maxlevelspot ; + } + + wavelet_level = min(wavelet_level, maxlevelspot); + int maxlvl; + float contrast = 0.f; + bool wavcurvemask = false; + + if (loclmasCurveblwav && lmasutiliblwav && (lp.enablMask || lp.showmaskblmet == 3)) { + for (int i = 0; i < 500; i++) { + if (loclmasCurveblwav[i] != 0.5) { + wavcurvemask = true; + } + } + } + + if (wavcurvemask && (lp.enablMask || lp.showmaskblmet == 3)) { +#ifdef _OPENMP + const int numThreads = omp_get_max_threads(); +#else + const int numThreads = 1; + +#endif + int level_bl = params->locallab.spots.at(sp).csthresholdblur.getBottomLeft(); + int level_hl = params->locallab.spots.at(sp).csthresholdblur.getTopLeft(); + int level_br = params->locallab.spots.at(sp).csthresholdblur.getBottomRight(); + int level_hr = params->locallab.spots.at(sp).csthresholdblur.getTopRight(); + + LocwavCurve dummy; + bool loclevwavutili = false; + bool wavcurvelev = false; + bool locconwavutili = false; + bool wavcurvecon = false; + bool loccompwavutili = false; + bool wavcurvecomp = false; + bool loccomprewavutili = false; + bool locedgwavutili = false; + bool wavcurvecompre = false; + bool wavcurve = false; + wavcontrast4(lp, bufmaskblurbl->L, nullptr, nullptr, contrast, 0.f, 0.f, 0.f, GW, GH, level_bl, level_hl, level_br, level_hr, sk, numThreads, loclmasCurveblwav, lmasutiliblwav, wavcurve, dummy, loclevwavutili, wavcurvelev, dummy, locconwavutili, wavcurvecon, dummy, loccompwavutili, wavcurvecomp, dummy, loccomprewavutili, wavcurvecompre, dummy, locedgwavutili, 1.f, 1.f, maxlvl, 0.f, 0.f, 1.f, 1.f, false, false, false, false, false, 0.f, 0.f); + } + + int shado = params->locallab.spots.at(sp).shadmaskbl; + + if (shado > 0 && (lp.enablMask || lp.showmaskblmet == 3)) { + ImProcFunctions::shadowsHighlights(bufmaskblurbl.get(), true, 1, shado, 0, 40, sk, 50, 0);//50 middle value for highlight tonal width + } + +// deltae Mask with scope +// bool delt = params->locallab.spots.at(sp).deltae; + int sco = params->locallab.spots.at(sp).scopemask; + const int limscope = 80; + const float mindE = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + + //printf("minde=%f maxde=%f, scopee=%i huref=%f lumaref=%f chromaref=%f\n", mindE, maxdE, sco, hueref, lumaref, chromaref); + if (delt && lp.blurmet == 0 && (lp.enablMask || lp.showmaskblmet == 3)) { + std::unique_ptr> rdEBuffer(new JaggedArray(GW, GH)); + float** rdE = *(rdEBuffer.get()); + + deltaEforMask(rdE, GW, GH, bufgb.get(), hueref, chromaref, lumaref, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco, lp.balance, lp.balanceh); + std::unique_ptr delta(new LabImage(GW, GH)); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < GH; ir++) + for (int jr = 0; jr < GW; jr++) { + delta->L[ir][jr] = bufmaskblurbl->L[ir][jr] - bufprov->L[ir][jr]; + delta->a[ir][jr] = bufmaskblurbl->a[ir][jr] - bufprov->a[ir][jr]; + delta->b[ir][jr] = bufmaskblurbl->b[ir][jr] - bufprov->b[ir][jr]; + + bufmaskblurbl->L[ir][jr] = bufprov->L[ir][jr] + rdE[ir][jr] * delta->L[ir][jr]; + bufmaskblurbl->a[ir][jr] = bufprov->a[ir][jr] + rdE[ir][jr] * delta->a[ir][jr]; + bufmaskblurbl->b[ir][jr] = bufprov->b[ir][jr] + rdE[ir][jr] * delta->b[ir][jr]; + } + + rdEBuffer.reset(); + + } + + +// + float lap = params->locallab.spots.at(sp).lapmaskbl; + bool pde = params->locallab.spots.at(sp).laplac; + float lumask = params->locallab.spots.at(sp).lumask; + + if (lap > 0.f && (lp.enablMask || lp.showmaskblmet == 3)) { + float *datain = new float[GH * GW]; + float *data_tmp = new float[GH * GW]; + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < GH; y++) { + for (int x = 0; x < GW; x++) { + datain[y * GW + x] = bufmaskblurbl->L[y][x]; + } + } + + if (!pde) { + ImProcFunctions::discrete_laplacian_threshold(data_tmp, datain, GW, GH, 200.f * lap); + } else { + ImProcFunctions::retinex_pde(datain, data_tmp, GW, GH, 12.f * lap, 1.f, nullptr, 0, 0, 1); + } + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < GH; y++) { + for (int x = 0; x < GW; x++) { + bufmaskblurbl->L[y][x] = data_tmp[y * GW + x]; + } + } + + delete [] datain; + delete [] data_tmp; + + } + + + float radiusb = 1.f / sk; + + if (lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) { + int invers = 0; + + if (lp.blurmet == 0) { + invers = 0; + } else if (lp.blurmet == 1) { + invers = 1; + } + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + gaussianBlur(bufmaskblurbl->L, bufmaskorigbl->L, GW, GH, radiusb); + gaussianBlur(bufmaskblurbl->a, bufmaskorigbl->a, GW, GH, 1.f + (0.005f * lp.radmabl) / sk); + gaussianBlur(bufmaskblurbl->b, bufmaskorigbl->b, GW, GH, 1.f + (0.005f * lp.radmabl) / sk); + } + + if (lp.showmaskblmet == 0 || lp.showmaskblmet == 1 || lp.showmaskblmet == 2 || lp.showmaskblmet == 4 || lp.enablMask) { + blendmask(lp, 0, 0, cx, cy, GW, GH, bufgb.get(), original, bufmaskorigbl.get(), originalmaskbl, lp.blendmabl, invers); + + } else if (lp.showmaskblmet == 3) { + showmask(lumask, lp, 0, 0, cx, cy, GW, GH, bufgb.get(), transformed, bufmaskorigbl.get(), invers); + return; + } + + } + +//end mask + + + + } + + if (((radius > 1.5 * GAUSS_SKIP && lp.rad > 1.6) || lp.stren > 0.1 || lp.blmet == 1 || lp.guidb > 0 || lp.showmaskblmet == 2 || lp.enablMask || lp.showmaskblmet == 3 || lp.showmaskblmet == 4) && lp.blurena) { // radius < GAUSS_SKIP means no gauss, just copy of original image + std::unique_ptr tmp1; + std::unique_ptr tmp2; + int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); + int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); + int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); + int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); + int bfh = yend - ystart; + int bfw = xend - xstart; + int bfhr = bfh; + int bfwr = bfw; + bool reduH = false; + bool reduW = false; + + bool fft = params->locallab.spots.at(sp).fftwbl; + int isogr = params->locallab.spots.at(sp).isogr; + int strengr = params->locallab.spots.at(sp).strengr; + int scalegr = params->locallab.spots.at(sp).scalegr; + + + + if (bfw >= mSP && bfh >= mSP) { + if (lp.blurmet == 0 && (fft || lp.rad > 30.f)) { + optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, reduH, reduW, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy); + } + + JaggedArray bufchroi(GW, GH); + std::unique_ptr bufgbi(new LabImage(GW, GH)); + JaggedArray bufchro(bfw, bfh); + + //here mask is used with plein image for normal and inverse + //if it is possible to optimze with maskcalccol(), I don't to preserv lisibility + if (lp.showmaskblmet == 0 || lp.showmaskblmet == 1 || lp.showmaskblmet == 2 || lp.showmaskblmet == 4 || lp.enablMask) { + + if (lp.blurmet == 0) { + if (bfw > 0 && bfh > 0) { + tmp1.reset(new LabImage(bfw, bfh)); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = ystart; y < yend ; y++) { + for (int x = xstart; x < xend; x++) { + tmp1->L[y - ystart][x - xstart] = original->L[y][x]; + tmp1->a[y - ystart][x - xstart] = original->a[y][x]; + tmp1->b[y - ystart][x - xstart] = original->b[y][x]; + } + } + } + } else if (lp.blurmet == 1) { + tmp1.reset(new LabImage(transformed->W, transformed->H)); + tmp2.reset(new LabImage(transformed->W, transformed->H)); + + for (int y = 0; y < GH ; y++) { + for (int x = 0; x < GW; x++) { + tmp2->L[y][x] = original->L[y][x]; + tmp2->a[y][x] = original->a[y][x]; + tmp2->b[y][x] = original->b[y][x]; + bufgbi->L[y][x] = original->L[y][x]; + bufgbi->a[y][x] = original->a[y][x]; + bufgbi->b[y][x] = original->b[y][x]; + } + } + + } + + + if (lp.blurmet == 0 && lp.blmet == 0 && radius > (1.5 * GAUSS_SKIP) && lp.rad > 1.6) { + if (fft || lp.rad > 30.f) { + if (lp.chromet == 0) { + ImProcFunctions::fftw_convol_blur2(tmp1->L, tmp1->L, bfwr, bfhr, radius, 0, 0); + } else if (lp.chromet == 1) { + ImProcFunctions::fftw_convol_blur2(tmp1->a, tmp1->a, bfwr, bfhr, radius, 0, 0); + ImProcFunctions::fftw_convol_blur2(tmp1->b, tmp1->b, bfwr, bfhr, radius, 0, 0); + } else if (lp.chromet == 2) { + ImProcFunctions::fftw_convol_blur2(tmp1->L, tmp1->L, bfwr, bfhr, radius, 0, 0); + ImProcFunctions::fftw_convol_blur2(tmp1->a, tmp1->a, bfwr, bfhr, radius, 0, 0); + ImProcFunctions::fftw_convol_blur2(tmp1->b, tmp1->b, bfwr, bfhr, radius, 0, 0); + } + } else { + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + if (lp.chromet == 0) + { + + gaussianBlur(tmp1->L, tmp1->L, bfw, bfh, radius); + } + + else if (lp.chromet == 1) + { + gaussianBlur(tmp1->a, tmp1->a, bfw, bfh, radius); + gaussianBlur(tmp1->b, tmp1->b, bfw, bfh, radius); + } else if (lp.chromet == 2) + { + gaussianBlur(tmp1->L, tmp1->L, bfw, bfh, radius); + gaussianBlur(tmp1->a, tmp1->a, bfw, bfh, radius); + gaussianBlur(tmp1->b, tmp1->b, bfw, bfh, radius); + } + + } + } + + } else if (lp.blurmet == 1 && lp.blmet == 0 && radius > (1.5 * GAUSS_SKIP) && lp.rad > 1.6) { + if (fft || lp.rad > 30.f) { + if (lp.chromet == 0) { + ImProcFunctions::fftw_convol_blur2(original->L, tmp1->L, GW, GH, radius, 0, 0); + } + + else if (lp.chromet == 1) { + ImProcFunctions::fftw_convol_blur2(original->a, tmp1->a, GW, GH, radius, 0, 0); + ImProcFunctions::fftw_convol_blur2(original->b, tmp1->b, GW, GH, radius, 0, 0); + } else if (lp.chromet == 2) { + ImProcFunctions::fftw_convol_blur2(original->L, tmp1->L, GW, GH, radius, 0, 0); + ImProcFunctions::fftw_convol_blur2(original->a, tmp1->a, GW, GH, radius, 0, 0); + ImProcFunctions::fftw_convol_blur2(original->b, tmp1->b, GW, GH, radius, 0, 0); + } + + } else { + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + if (lp.chromet == 0) + { + gaussianBlur(original->L, tmp1->L, GW, GH, radius); + } else if (lp.chromet == 1) + + { + gaussianBlur(original->a, tmp1->a, GW, GH, radius); + gaussianBlur(original->b, tmp1->b, GW, GH, radius); + } else if (lp.chromet == 2) + + { + gaussianBlur(original->L, tmp1->L, GW, GH, radius); + gaussianBlur(original->a, tmp1->a, GW, GH, radius); + gaussianBlur(original->b, tmp1->b, GW, GH, radius); + } + + } + } + } + + + //add noise + if (tmp1.get() && lp.stren > 0.1f && lp.blmet == 0) { + float mean = 0.f;//0 best result + float variance = lp.stren ; + addGaNoise(tmp1.get(), tmp1.get(), mean, variance, sk) ; + } + + //add grain + if (lp.blmet == 0 && strengr > 0) { + int wi = bfw; + int he = bfh; + + if (lp.blurmet == 1) { + wi = GW; + he = GH; + } + + if (tmp1.get()) { + Imagefloat *tmpImage = nullptr; + tmpImage = new Imagefloat(wi, he); + + for (int y = 0; y < he ; y++) { + for (int x = 0; x < wi; x++) { + tmpImage->g(y, x) = tmp1->L[y][x]; + tmpImage->r(y, x) = tmp1->a[y][x]; + tmpImage->b(y, x) = tmp1->b[y][x]; + } + } + + + filmGrain(tmpImage, isogr, strengr, scalegr, wi, he); + + for (int y = 0; y < he ; y++) { + for (int x = 0; x < wi; x++) { + tmp1->L[y][x] = tmpImage->g(y, x); + tmp1->a[y][x] = tmpImage->r(y, x); + tmp1->b[y][x] = tmpImage->b(y, x); + } + } + + delete tmpImage; + } + } + + Median medianTypeL = Median::TYPE_3X3_STRONG; + Median medianTypeAB = Median::TYPE_3X3_STRONG; + + if (lp.medmet == 0) { + medianTypeL = medianTypeAB = Median::TYPE_3X3_STRONG; + } else if (lp.medmet == 1) { + medianTypeL = medianTypeAB = Median::TYPE_5X5_STRONG; + } else if (lp.medmet == 2) { + medianTypeL = medianTypeAB = Median::TYPE_7X7; + } else if (lp.medmet == 3) { + medianTypeL = medianTypeAB = Median::TYPE_9X9; + } + + if (lp.blurmet == 0 && lp.blmet == 1 && lp.medmet != -1) { + float** tmL; + int wid = bfw; + int hei = bfh; + tmL = new float*[hei]; + + for (int i = 0; i < hei; ++i) { + tmL[i] = new float[wid]; + } + + if (lp.chromet == 0) { + Median_Denoise(tmp1->L, tmp1->L, bfw, bfh, medianTypeL, lp.it, multiThread, tmL); + } + + else if (lp.chromet == 1) { + Median_Denoise(tmp1->a, tmp1->a, bfw, bfh, medianTypeAB, lp.it, multiThread, tmL); + Median_Denoise(tmp1->b, tmp1->b, bfw, bfh, medianTypeAB, lp.it, multiThread, tmL); + } else if (lp.chromet == 2) { + Median_Denoise(tmp1->L, tmp1->L, bfw, bfh, medianTypeL, lp.it, multiThread, tmL); + Median_Denoise(tmp1->a, tmp1->a, bfw, bfh, medianTypeAB, lp.it, multiThread, tmL); + Median_Denoise(tmp1->b, tmp1->b, bfw, bfh, medianTypeAB, lp.it, multiThread, tmL); + } + + for (int i = 0; i < hei; ++i) { + delete[] tmL[i]; + } + + delete[] tmL; + + } else if (lp.blurmet == 1 && lp.blmet == 1) { + float** tmL; + int wid = GW; + int hei = GH; + tmL = new float*[hei]; + + for (int i = 0; i < hei; ++i) { + tmL[i] = new float[wid]; + } + + if (lp.chromet == 0) { + Median_Denoise(tmp2->L, tmp1->L, GW, GH, medianTypeL, lp.it, multiThread, tmL); + } else if (lp.chromet == 1) { + Median_Denoise(tmp2->a, tmp1->a, GW, GH, medianTypeAB, lp.it, multiThread, tmL); + Median_Denoise(tmp2->b, tmp1->b, GW, GH, medianTypeAB, lp.it, multiThread, tmL); + } else if (lp.chromet == 2) { + Median_Denoise(tmp2->L, tmp1->L, GW, GH, medianTypeL, lp.it, multiThread, tmL); + Median_Denoise(tmp2->a, tmp1->a, GW, GH, medianTypeAB, lp.it, multiThread, tmL); + Median_Denoise(tmp2->b, tmp1->b, GW, GH, medianTypeAB, lp.it, multiThread, tmL); + } + + for (int i = 0; i < hei; ++i) { + delete[] tmL[i]; + } + + delete[] tmL; + } + + if (lp.blurmet == 0 && lp.blmet == 2) { + + if (lp.guidb > 0) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = ystart; y < yend ; y++) { + for (int x = xstart; x < xend; x++) { + tmp1->L[y - ystart][x - xstart] = original->L[y][x]; + tmp1->a[y - ystart][x - xstart] = original->a[y][x]; + tmp1->b[y - ystart][x - xstart] = original->b[y][x]; + bufgb->L[y - ystart][x - xstart] = original->L[y][x]; + } + } + + Imagefloat *tmpImage = nullptr; + tmpImage = new Imagefloat(bfw, bfh); + lab2rgb(*tmp1, *tmpImage, params->icm.workingProfile); + array2D LL(bfw, bfh); + array2D rr(bfw, bfh); + array2D gg(bfw, bfh); + array2D bb(bfw, bfh); + array2D guide(bfw, bfh); + + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + LL[y][x] = tmp1->L[y][x]; + float ll = LL[y][x] / 32768.f; + guide[y][x] = xlin2log(max(ll, 0.f), 10.f); + rr[y][x] = tmpImage->r(y, x); + gg[y][x] = tmpImage->g(y, x); + bb[y][x] = tmpImage->b(y, x); + + } + } + array2D iR(bfw, bfh, rr, 0); + array2D iG(bfw, bfh, gg, 0); + array2D iB(bfw, bfh, bb, 0); + array2D iL(bfw, bfh, LL, 0); + + int r = max(int(lp.guidb / sk), 1); + + const float epsil = 0.001f * std::pow(2, - lp.epsb); + + if (lp.chromet == 0) { + rtengine::guidedFilterLog(guide, 10.f, LL, r, epsil, multiThread); + } else if (lp.chromet == 1) { + rtengine::guidedFilterLog(guide, 10.f, rr, r, epsil, multiThread); + rtengine::guidedFilterLog(guide, 10.f, bb, r, epsil, multiThread); + } else if (lp.chromet == 2) { + rtengine::guidedFilterLog(10.f, gg, r, epsil, multiThread); + rtengine::guidedFilterLog(10.f, rr, r, epsil, multiThread); + rtengine::guidedFilterLog(10.f, bb, r, epsil, multiThread); + } + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + rr[y][x] = intp(lp.strbl, rr[y][x] , iR[y][x]); + gg[y][x] = intp(lp.strbl, gg[y][x] , iG[y][x]); + bb[y][x] = intp(lp.strbl, bb[y][x] , iB[y][x]); + tmpImage->r(y, x) = rr[y][x]; + tmpImage->g(y, x) = gg[y][x]; + tmpImage->b(y, x) = bb[y][x]; + + } + } + + rgb2lab(*tmpImage, *tmp1, params->icm.workingProfile); + + if (lp.chromet == 0) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + LL[y][x] = intp(lp.strbl, LL[y][x] , iL[y][x]); + tmp1->L[y][x] = LL[y][x]; + } + } + } + + delete tmpImage; + } + + } else if (lp.blurmet == 1 && lp.blmet == 2) { + + if (lp.guidb > 0) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < GH ; y++) { + for (int x = 0; x < GW; x++) { + tmp1->L[y][x] = original->L[y][x]; + tmp1->a[y][x] = original->a[y][x]; + tmp1->b[y][x] = original->b[y][x]; + tmp2->L[y][x] = original->L[y][x]; + } + } + + Imagefloat *tmpImage = nullptr; + tmpImage = new Imagefloat(GW, GH); + lab2rgb(*tmp1, *tmpImage, params->icm.workingProfile); + array2D LL(GW, GH); + array2D rr(GW, GH); + array2D gg(GW, GH); + array2D bb(GW, GH); + array2D guide(GW, GH); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < GH ; y++) { + for (int x = 0; x < GW; x++) { + LL[y][x] = tmp1->L[y][x]; + float ll = LL[y][x] / 32768.f; + guide[y][x] = xlin2log(max(ll, 0.f), 10.f); + rr[y][x] = tmpImage->r(y, x); + gg[y][x] = tmpImage->g(y, x); + bb[y][x] = tmpImage->b(y, x); + + } + } + + array2D iR(GW, GH, rr, 0); + array2D iG(GW, GH, gg, 0); + array2D iB(GW, GH, bb, 0); + array2D iL(GW, GH, LL, 0); + + int r = max(int(lp.guidb / sk), 1); + + const float epsil = 0.001f * std::pow(2, - lp.epsb); + + if (lp.chromet == 0) { + rtengine::guidedFilterLog(guide, 10.f, LL, r, epsil, multiThread); + } else if (lp.chromet == 1) { + rtengine::guidedFilterLog(guide, 10.f, rr, r, epsil, multiThread); + rtengine::guidedFilterLog(guide, 10.f, bb, r, epsil, multiThread); + } else if (lp.chromet == 2) { + rtengine::guidedFilterLog(10.f, gg, r, epsil, multiThread); + rtengine::guidedFilterLog(10.f, rr, r, epsil, multiThread); + rtengine::guidedFilterLog(10.f, bb, r, epsil, multiThread); + } + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < GH ; y++) { + for (int x = 0; x < GW; x++) { + rr[y][x] = intp(lp.strbl, rr[y][x] , iR[y][x]); + gg[y][x] = intp(lp.strbl, gg[y][x] , iG[y][x]); + bb[y][x] = intp(lp.strbl, bb[y][x] , iB[y][x]); + tmpImage->r(y, x) = rr[y][x]; + tmpImage->g(y, x) = gg[y][x]; + tmpImage->b(y, x) = bb[y][x]; + + } + } + + rgb2lab(*tmpImage, *tmp1, params->icm.workingProfile); + + if (lp.chromet == 0) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < GH ; y++) { + for (int x = 0; x < GW; x++) { + LL[y][x] = intp(lp.strbl, LL[y][x] , iL[y][x]); + tmp1->L[y][x] = LL[y][x]; + } + } + } + + delete tmpImage; + } + + } + + if (lp.blurmet == 0) { + float minC = sqrt(SQR(tmp1->a[0][0]) + SQR(tmp1->b[0][0])) - sqrt(SQR(bufgb->a[0][0]) + SQR(bufgb->b[0][0])); + float maxC = minC; +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxC) reduction(min:minC) schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) { + for (int jr = 0; jr < bfw; jr++) { + bufchro[ir][jr] = sqrt(SQR(tmp1->a[ir][jr]) + SQR(tmp1->b[ir][jr])) - sqrt(SQR(bufgb->a[ir][jr]) + SQR(bufgb->b[ir][jr])); + minC = rtengine::min(minC, bufchro[ir][jr]); + maxC = rtengine::max(maxC, bufchro[ir][jr]); + } + } + + float coefC = 0.01f * (max(fabs(minC), fabs(maxC))); + + if (coefC == 0.f) { + coefC = 1.f; + } + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < bfh; y++) { + for (int x = 0; x < bfw; x++) { + bufchro[y][x] /= coefC; + } + } + + } else if (lp.blurmet == 1) { + float minC = sqrt(SQR(tmp1->a[0][0]) + SQR(tmp1->b[0][0])) - sqrt(SQR(bufgbi->a[0][0]) + SQR(bufgbi->b[0][0])); + float maxC = minC; +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxC) reduction(min:minC) schedule(dynamic,16) +#endif + + for (int ir = 0; ir < GH; ir++) { + for (int jr = 0; jr < GW; jr++) { + bufchroi[ir][jr] = sqrt(SQR(tmp1->a[ir][jr]) + SQR(tmp1->b[ir][jr])) - sqrt(SQR(bufgbi->a[ir][jr]) + SQR(bufgbi->b[ir][jr])); + minC = rtengine::min(minC, bufchroi[ir][jr]); + maxC = rtengine::max(maxC, bufchroi[ir][jr]); + } + } + + float coefC = 0.01f * (max(fabs(minC), fabs(maxC))); + + if (coefC == 0.f) { + coefC = 1.f; + } + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < GH; y++) { + for (int x = 0; x < GW; x++) { + bufchroi[y][x] /= coefC; + } + } + + } + + if (lp.blurmet == 0) { //blur and noise (center) + + if (tmp1.get()) { + BlurNoise_Local(tmp1.get(), originalmaskbl, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } + } + } else if (lp.blurmet == 1) { + if (tmp1.get()) { + InverseBlurNoise_Local(originalmaskbl, bufchroi, lp, hueref, chromaref, lumaref, original, transformed, tmp1.get(), cx, cy, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } + } + } + + } + } + } //local impulse if ((lp.bilat > 0.f) && lp.denoiena) { @@ -5067,975 +11196,33 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o ImProcFunctions::impulse_nr(bufwv.get(), threshold); } - DeNoise_Local(call, lp, levred, huerefblur, lumarefblur, chromarefblur, original, transformed, *(bufwv.get()), cx, cy, sk); + DeNoise_Local(call, lp, originalmaskbl, levred, huerefblur, lumarefblur, chromarefblur, original, transformed, *(bufwv.get()), cx, cy, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } } //local denoise - //all these variables are to prevent use of denoise when non necessary - // but with qualmet = 2 (default for best quality) we must denoise chroma with little values to prevent artifacts due to variations of Hue - // but if user select volontary denoise, it is that choice the good (prioritary) - bool execcolor = (lp.chro != 0.f || lp.ligh != 0.f || lp.cont != 0); // only if one slider ore more is engaged - bool execbdl = (lp.mulloc[0] != 1.f || lp.mulloc[1] != 1.f || lp.mulloc[2] != 1.f || lp.mulloc[3] != 1.f || lp.mulloc[4] != 1.f || lp.mulloc[5] != 1.f) ;//only if user want cbdl - bool execdenoi = noiscfactiv && ((lp.colorena && execcolor) || (lp.tonemapena && lp.strengt != 0.f) || (lp.cbdlena && execbdl) || (lp.sfena && lp.strng > 0.f) || (lp.lcena && lp.lcamount > 0.f) || (lp.sharpena && lp.shrad > 0.42) || (lp.retiena && lp.str > 0.f) || (lp.exposena && lp.expcomp != 0.f) || (lp.expvib && lp.past != 0.f)); + float slidL[8] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + float slida[8] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + float slidb[8] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + int aut = 0; - if (((lp.noiself > 0.f || lp.noiself0 > 0.f || lp.noiself2 > 0.f || lp.noiselc > 0.f || lp.noisecf > 0.f || lp.noisecc > 0.f) && lp.denoiena) || execdenoi) { // sk == 1 ?? - StopWatch Stop1("locallab Denoise called"); - MyMutex::MyLock lock(*fftwMutex); + if (lp.denoiena) { + DeNoise(call, del, slidL, slida, slidb, aut, noiscfactiv, lp, originalmaskbl, levred, huerefblur, lumarefblur, chromarefblur, original, transformed, cx, cy, sk); - if (lp.noisecf >= 0.1f || lp.noisecc >= 0.1f) { - noiscfactiv = false; - levred = 7; - } - - -#ifdef _OPENMP - const int numThreads = omp_get_max_threads(); -#else - const int numThreads = 1; - -#endif - - if (call == 1) { - - - LabImage tmp1(transformed->W, transformed->H); - LabImage tmp2(transformed->W, transformed->H); - tmp2.clear(); - - array2D *Lin = nullptr; - array2D *Ain = nullptr; - array2D *Bin = nullptr; - - - int GW = transformed->W; - int GH = transformed->H; - int max_numblox_W = ceil((static_cast(GW)) / (offset)) + 2 * blkrad; - // calculate min size of numblox_W. - int min_numblox_W = ceil((static_cast(GW)) / (offset)) + 2 * blkrad; - - - for (int ir = 0; ir < GH; ir++) - for (int jr = 0; jr < GW; jr++) { - tmp1.L[ir][jr] = original->L[ir][jr]; - tmp1.a[ir][jr] = original->a[ir][jr]; - tmp1.b[ir][jr] = original->b[ir][jr]; - } - - int DaubLen = 6; - - int levwavL = levred; - int skip = 1; - - wavelet_decomposition Ldecomp(tmp1.L[0], tmp1.W, tmp1.H, levwavL, 1, skip, numThreads, DaubLen); - wavelet_decomposition adecomp(tmp1.a[0], tmp1.W, tmp1.H, levwavL, 1, skip, numThreads, DaubLen); - wavelet_decomposition bdecomp(tmp1.b[0], tmp1.W, tmp1.H, levwavL, 1, skip, numThreads, DaubLen); - - float madL[8][3]; - int edge = 2; - - if (!Ldecomp.memoryAllocationFailed) { - #pragma omp parallel for collapse(2) schedule(dynamic,1) - - for (int lvl = 0; lvl < levred; lvl++) { - for (int dir = 1; dir < 4; dir++) { - int Wlvl_L = Ldecomp.level_W(lvl); - int Hlvl_L = Ldecomp.level_H(lvl); - - float ** WavCoeffs_L = Ldecomp.level_coeffs(lvl); - - madL[lvl][dir - 1] = SQR(Mad(WavCoeffs_L[dir], Wlvl_L * Hlvl_L)); - } - } - - float vari[levred]; - - if (levred == 7) { - edge = 2; - vari[0] = 8.f * SQR((lp.noiself0 / 125.0) * (1.0 + lp.noiself0 / 25.0)); - vari[1] = 8.f * SQR((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0)); - vari[2] = 8.f * SQR((lp.noiself2 / 125.0) * (1.0 + lp.noiself2 / 25.0)); - - vari[3] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); - vari[4] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); - vari[5] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); - vari[6] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); - } else if (levred == 4) { - edge = 3; - vari[0] = 8.f * SQR((lp.noiself0 / 125.0) * (1.0 + lp.noiself0 / 25.0)); - vari[1] = 8.f * SQR((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0)); - vari[2] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); - vari[3] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); - - } - - if ((lp.noiself >= 0.1f || lp.noiself0 >= 0.1f || lp.noiself2 >= 0.1f || lp.noiselc >= 0.1f)) { - float kr3 = 0.f; - float kr4 = 0.f; - float kr5 = 0.f; - - if (lp.noiselc < 30.f) { - kr3 = 0.f; - kr4 = 0.f; - kr5 = 0.f; - } else if (lp.noiselc < 50.f) { - kr3 = 0.5f; - kr4 = 0.3f; - kr5 = 0.2f; - } else if (lp.noiselc < 70.f) { - kr3 = 0.7f; - kr4 = 0.5f; - kr5 = 0.3f; - } else { - kr3 = 1.f; - kr4 = 1.f; - kr5 = 1.f; - } - - vari[0] = max(0.0001f, vari[0]); - vari[1] = max(0.0001f, vari[1]); - vari[2] = max(0.0001f, vari[2]); - vari[3] = max(0.0001f, kr3 * vari[3]); - - if (levred == 7) { - vari[4] = max(0.0001f, kr4 * vari[4]); - vari[5] = max(0.0001f, kr5 * vari[5]); - vari[6] = max(0.0001f, kr5 * vari[6]); - } - - float* noisevarlum = new float[GH * GW]; - int GW2 = (GW + 1) / 2; - - float nvlh[13] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 0.7f, 0.5f}; //high value - float nvll[13] = {0.1f, 0.15f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.45f, 0.7f, 0.8f, 1.f, 1.f, 1.f}; //low value - - float seuillow = 3000.f;//low - float seuilhigh = 18000.f;//high - int i = 10 - lp.noiselequal; - float ac = (nvlh[i] - nvll[i]) / (seuillow - seuilhigh); - float bc = nvlh[i] - seuillow * ac; - //ac and bc for transition -#ifdef _OPENMP - #pragma omp parallel for - -#endif - - for (int ir = 0; ir < GH; ir++) - for (int jr = 0; jr < GW; jr++) { - float lN = tmp1.L[ir][jr]; - - if (lN < seuillow) { - noisevarlum[(ir >> 1)*GW2 + (jr >> 1)] = nvlh[i]; - } else if (lN < seuilhigh) { - noisevarlum[(ir >> 1)*GW2 + (jr >> 1)] = ac * lN + bc; - } else { - noisevarlum[(ir >> 1)*GW2 + (jr >> 1)] = nvll[i]; - } - } - - - if (lp.noiselc < 1.f) { - WaveletDenoiseAllL(Ldecomp, noisevarlum, madL, vari, edge, numThreads); - } else { - WaveletDenoiseAll_BiShrinkL(Ldecomp, noisevarlum, madL, vari, edge, numThreads); - WaveletDenoiseAllL(Ldecomp, noisevarlum, madL, vari, edge, numThreads); - } - - delete[] noisevarlum; - - } - } - - float variC[levred]; - float variCb[levred]; - - float noisecfr = lp.noisecf; - float noiseccr = lp.noisecc; - - if (lp.adjch > 0.f) { - noisecfr = lp.noisecf * ((100.f + lp.adjch) / 10.f); - noiseccr = lp.noisecc + ((100.f + lp.adjch) / 10.f); - } - - float noisecfb = lp.noisecf; - float noiseccb = lp.noisecc; - - if (lp.adjch < 0.f) { - noisecfb = lp.noisecf * ((100.f - lp.adjch) / 10.f); - noiseccb = lp.noisecc * ((100.f - lp.adjch) / 10.f); - } - - - if (noisecfr < 0.f) { - noisecfr = 0.0001f; - } - - if (noiseccr < 0.f) { - noiseccr = 0.0001f; - } - - if (noisecfb < 0.f) { - noisecfb = 0.0001f; - } - - if (noiseccb < 0.f) { - noiseccb = 0.0001f; - } - - if (!adecomp.memoryAllocationFailed && !bdecomp.memoryAllocationFailed) { - - if (levred == 7) { - edge = 2; - variC[0] = SQR(noisecfr); - variC[1] = SQR(noisecfr); - variC[2] = SQR(noisecfr); - - variC[3] = SQR(noisecfr); - variC[4] = SQR(noisecfr); - variC[5] = SQR(noiseccr); - variC[6] = SQR(noiseccr); - - variCb[0] = SQR(noisecfb); - variCb[1] = SQR(noisecfb); - variCb[2] = SQR(noisecfb); - - variCb[3] = SQR(noisecfb); - variCb[4] = SQR(noisecfb); - variCb[5] = SQR(noiseccb); - variCb[6] = SQR(noiseccb); - - } else if (levred == 4) { - edge = 3; - variC[0] = SQR(lp.noisecf / 10.0); - variC[1] = SQR(lp.noisecf / 10.0); - variC[2] = SQR(lp.noisecf / 10.0); - variC[3] = SQR(lp.noisecf / 10.0); - - variCb[0] = SQR(lp.noisecf / 10.0); - variCb[1] = SQR(lp.noisecf / 10.0); - variCb[2] = SQR(lp.noisecf / 10.0); - variCb[3] = SQR(lp.noisecf / 10.0); - - - } - - if ((lp.noisecf >= 0.1f || lp.noisecc >= 0.1f || noiscfactiv)) { - float minic = 0.0001f; - - if (noiscfactiv) { - minic = 0.1f;//only for artifact shape detection - } - - float k1 = 0.f; - float k2 = 0.f; - float k3 = 0.f; - - if (lp.noisecf < 0.2f) { - k1 = 0.f; - k2 = 0.f; - k3 = 0.f; - } else if (lp.noisecf < 0.3f) { - k1 = 0.1f; - k2 = 0.0f; - k3 = 0.f; - } else if (lp.noisecf < 0.5f) { - k1 = 0.2f; - k2 = 0.1f; - k3 = 0.f; - } else if (lp.noisecf < 0.8f) { - k1 = 0.3f; - k2 = 0.25f; - k3 = 0.f; - } else if (lp.noisecf < 1.f) { - k1 = 0.4f; - k2 = 0.25f; - k3 = 0.1f; - } else if (lp.noisecf < 2.f) { - k1 = 0.5f; - k2 = 0.3f; - k3 = 0.15f; - } else if (lp.noisecf < 3.f) { - k1 = 0.6f; - k2 = 0.45f; - k3 = 0.3f; - } else if (lp.noisecf < 4.f) { - k1 = 0.7f; - k2 = 0.5f; - k3 = 0.4f; - } else if (lp.noisecf < 5.f) { - k1 = 0.8f; - k2 = 0.6f; - k3 = 0.5f; - } else if (lp.noisecf < 10.f) { - k1 = 0.85f; - k2 = 0.7f; - k3 = 0.6f; - } else if (lp.noisecf < 20.f) { - k1 = 0.9f; - k2 = 0.8f; - k3 = 0.7f; - } else if (lp.noisecf < 50.f) { - k1 = 1.f; - k2 = 1.f; - k3 = 0.9f; - - } else { - k1 = 1.f; - k2 = 1.f; - k3 = 1.f; - } - - variC[0] = max(minic, variC[0]); - variC[1] = max(minic, k1 * variC[1]); - variC[2] = max(minic, k2 * variC[2]); - variC[3] = max(minic, k3 * variC[3]); - - variCb[0] = max(minic, variCb[0]); - variCb[1] = max(minic, k1 * variCb[1]); - variCb[2] = max(minic, k2 * variCb[2]); - variCb[3] = max(minic, k3 * variCb[3]); - - if (levred == 7) { - float k4 = 0.f; - float k5 = 0.f; - float k6 = 0.f; - - if (lp.noisecc == 0.1f) { - k4 = 0.f; - k5 = 0.0f; - } else if (lp.noisecc < 0.2f) { - k4 = 0.1f; - k5 = 0.0f; - } else if (lp.noisecc < 0.5f) { - k4 = 0.15f; - k5 = 0.0f; - } else if (lp.noisecc < 1.f) { - k4 = 0.15f; - k5 = 0.1f; - } else if (lp.noisecc < 3.f) { - k4 = 0.3f; - k5 = 0.15f; - } else if (lp.noisecc < 4.f) { - k4 = 0.6f; - k5 = 0.4f; - } else if (lp.noisecc < 6.f) { - k4 = 0.8f; - k5 = 0.6f; - } else { - k4 = 1.f; - k5 = 1.f; - } - - - variC[4] = max(0.0001f, k4 * variC[4]); - variC[5] = max(0.0001f, k5 * variC[5]); - variCb[4] = max(0.0001f, k4 * variCb[4]); - variCb[5] = max(0.0001f, k5 * variCb[5]); - - if (lp.noisecc < 4.f) { - k6 = 0.f; - } else if (lp.noisecc < 5.f) { - k6 = 0.4f; - } else if (lp.noisecc < 6.f) { - k6 = 0.7f; - } else { - k6 = 1.f; - } - - variC[6] = max(0.0001f, k6 * variC[6]); - variCb[6] = max(0.0001f, k6 * variCb[6]); - - } - - float* noisevarchrom = new float[GH * GW]; - //noisevarchrom in function chroma - int GW2 = (GW + 1) / 2; - float nvch = 0.6f;//high value - float nvcl = 0.1f;//low value - - if (lp.noisecf > 100.f) { - nvch = 0.8f; - nvcl = 0.4f; - } - - float seuil = 4000.f;//low - float seuil2 = 15000.f;//high - //ac and bc for transition - float ac = (nvch - nvcl) / (seuil - seuil2); - float bc = nvch - seuil * ac; -#ifdef _OPENMP - #pragma omp parallel for - -#endif - - for (int ir = 0; ir < GH; ir++) - for (int jr = 0; jr < GW; jr++) { - float cN = sqrt(SQR(tmp1.a[ir][jr]) + SQR(tmp1.b[ir][jr])); - - if (cN < seuil) { - noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = nvch; - } else if (cN < seuil2) { - noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = ac * cN + bc; - } else { - noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = nvcl; - } - } - - - float noisevarab_r = 100.f; //SQR(lp.noisecc / 10.0); - - if (lp.noisecc < 0.1f) { - WaveletDenoiseAllAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads); - WaveletDenoiseAllAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads); - } else { - WaveletDenoiseAll_BiShrinkAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads); - WaveletDenoiseAllAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads); - - WaveletDenoiseAll_BiShrinkAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads); - WaveletDenoiseAllAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads); - } - - delete[] noisevarchrom; - - } - } - - if (!Ldecomp.memoryAllocationFailed) { - Lin = new array2D(GW, GH); -#ifdef _OPENMP - #pragma omp parallel for - -#endif - - for (int i = 0; i < GH; ++i) { - for (int j = 0; j < GW; ++j) { - (*Lin)[i][j] = tmp1.L[i][j]; - } - } - - Ldecomp.reconstruct(tmp1.L[0]); - } - - if (!Ldecomp.memoryAllocationFailed) { - if ((lp.noiself >= 0.1f || lp.noiself0 >= 0.1f || lp.noiself2 >= 0.1f || lp.noiselc >= 0.1f) && levred == 7) { - fftw_denoise(GW, GH, max_numblox_W, min_numblox_W, tmp1.L, Lin, numThreads, lp, 0); - } - } - - if (!adecomp.memoryAllocationFailed) { - Ain = new array2D(GW, GH); -#ifdef _OPENMP - #pragma omp parallel for - -#endif - - for (int i = 0; i < GH; ++i) { - for (int j = 0; j < GW; ++j) { - (*Ain)[i][j] = tmp1.a[i][j]; - } - } - - adecomp.reconstruct(tmp1.a[0]); - } - - - if (!adecomp.memoryAllocationFailed) { - if ((lp.noisecf >= 0.1f || lp.noisecc >= 0.1f)) { - if (lp.noisechrodetail > 1000) { //to avoid all utilisation - fftw_denoise(GW, GH, max_numblox_W, min_numblox_W, tmp1.a, Ain, numThreads, lp, 1); - } - } - - - - - } - - - if (!bdecomp.memoryAllocationFailed) { - - Bin = new array2D(GW, GH); -#ifdef _OPENMP - #pragma omp parallel for - -#endif - - for (int i = 0; i < GH; ++i) { - for (int j = 0; j < GW; ++j) { - (*Bin)[i][j] = tmp1.b[i][j]; - } - } - - bdecomp.reconstruct(tmp1.b[0]); - } - - - if (!bdecomp.memoryAllocationFailed) { - if ((lp.noisecf >= 0.1f || lp.noisecc >= 0.1f)) { - if (lp.noisechrodetail > 1000) {//to avoid all utilisation - - fftw_denoise(GW, GH, max_numblox_W, min_numblox_W, tmp1.b, Bin, numThreads, lp, 1); - } - } - - } - - DeNoise_Local(call, lp, levred, huerefblur, lumarefblur, chromarefblur, original, transformed, tmp1, cx, cy, sk); - - } else if (call == 2 /* || call == 1 || call == 3 */) { //simpleprocess - - int bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone - int bfw = int (lp.lx + lp.lxL) + del; - LabImage bufwv(bfw, bfh); - bufwv.clear(true); - array2D *Lin = nullptr; - // array2D *Ain = nullptr; - // array2D *Bin = nullptr; - - int max_numblox_W = ceil((static_cast(bfw)) / (offset)) + 2 * blkrad; - // calculate min size of numblox_W. - int min_numblox_W = ceil((static_cast(bfw)) / (offset)) + 2 * blkrad; - // these are needed only for creation of the plans and will be freed before entering the parallel loop - - - int begy = lp.yc - lp.lyT; - int begx = lp.xc - lp.lxL; - int yEn = lp.yc + lp.ly; - int xEn = lp.xc + lp.lx; - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < transformed->H ; y++) //{ - for (int x = 0; x < transformed->W; x++) { - int lox = cx + x; - int loy = cy + y; - - if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) { - bufwv.L[loy - begy][lox - begx] = original->L[y][x]; - bufwv.a[loy - begy][lox - begx] = original->a[y][x]; - bufwv.b[loy - begy][lox - begx] = original->b[y][x]; - } - - } - - int DaubLen = 6; - - int levwavL = levred; - int skip = 1; - wavelet_decomposition Ldecomp(bufwv.L[0], bufwv.W, bufwv.H, levwavL, 1, skip, numThreads, DaubLen); - wavelet_decomposition adecomp(bufwv.a[0], bufwv.W, bufwv.H, levwavL, 1, skip, numThreads, DaubLen); - wavelet_decomposition bdecomp(bufwv.b[0], bufwv.W, bufwv.H, levwavL, 1, skip, numThreads, DaubLen); - - float madL[8][3]; - int edge = 2; - - if (!Ldecomp.memoryAllocationFailed) { - #pragma omp parallel for collapse(2) schedule(dynamic,1) - - for (int lvl = 0; lvl < levred; lvl++) { - for (int dir = 1; dir < 4; dir++) { - int Wlvl_L = Ldecomp.level_W(lvl); - int Hlvl_L = Ldecomp.level_H(lvl); - - float ** WavCoeffs_L = Ldecomp.level_coeffs(lvl); - - madL[lvl][dir - 1] = SQR(Mad(WavCoeffs_L[dir], Wlvl_L * Hlvl_L)); - } - } - - float vari[levred]; - - if (levred == 7) { - edge = 2; - vari[0] = 8.f * SQR((lp.noiself0 / 125.0) * (1.0 + lp.noiself0 / 25.0)); - vari[1] = 8.f * SQR((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0)); - vari[2] = 8.f * SQR((lp.noiself2 / 125.0) * (1.0 + lp.noiself2 / 25.0)); - - vari[3] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); - vari[4] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); - vari[5] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); - vari[6] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); - } else if (levred == 4) { - edge = 3; - vari[0] = 8.f * SQR((lp.noiself0 / 125.0) * (1.0 + lp.noiself0 / 25.0)); - vari[1] = 8.f * SQR((lp.noiself / 125.0) * (1.0 + lp.noiself / 25.0)); - vari[2] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); - vari[3] = 8.f * SQR((lp.noiselc / 125.0) * (1.0 + lp.noiselc / 25.0)); - - } - - - if ((lp.noiself >= 0.1f || lp.noiself0 >= 0.1f || lp.noiself2 >= 0.1f || lp.noiselc >= 0.1f)) { - float kr3 = 0.f; - float kr4 = 0.f; - float kr5 = 0.f; - - if (lp.noiselc < 30.f) { - kr3 = 0.f; - kr4 = 0.f; - kr5 = 0.f; - } else if (lp.noiselc < 50.f) { - kr3 = 0.5f; - kr4 = 0.3f; - kr5 = 0.2f; - } else if (lp.noiselc < 70.f) { - kr3 = 0.7f; - kr4 = 0.5f; - kr5 = 0.3f; - } else { - kr3 = 1.f; - kr4 = 1.f; - kr5 = 1.f; - } - - vari[0] = max(0.0001f, vari[0]); - vari[1] = max(0.0001f, vari[1]); - vari[2] = max(0.0001f, vari[2]); - vari[3] = max(0.0001f, kr3 * vari[3]); - - if (levred == 7) { - vari[4] = max(0.0001f, kr4 * vari[4]); - vari[5] = max(0.0001f, kr5 * vari[5]); - vari[6] = max(0.0001f, kr5 * vari[6]); - } - - // float* noisevarlum = nullptr; // we need a dummy to pass it to WaveletDenoiseAllL - float* noisevarlum = new float[bfh * bfw]; - int bfw2 = (bfw + 1) / 2; - - float nvlh[13] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 0.7f, 0.5f}; //high value - float nvll[13] = {0.1f, 0.15f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.45f, 0.7f, 0.8f, 1.f, 1.f, 1.f}; //low value - - float seuillow = 3000.f;//low - float seuilhigh = 18000.f;//high - int i = 10 - lp.noiselequal; - float ac = (nvlh[i] - nvll[i]) / (seuillow - seuilhigh); - float bc = nvlh[i] - seuillow * ac; - //ac and bc for transition -#ifdef _OPENMP - #pragma omp parallel for - -#endif - - for (int ir = 0; ir < bfh; ir++) - for (int jr = 0; jr < bfw; jr++) { - float lN = bufwv.L[ir][jr]; - - if (lN < seuillow) { - noisevarlum[(ir >> 1)*bfw2 + (jr >> 1)] = nvlh[i]; - } else if (lN < seuilhigh) { - noisevarlum[(ir >> 1)*bfw2 + (jr >> 1)] = ac * lN + bc; - } else { - noisevarlum[(ir >> 1)*bfw2 + (jr >> 1)] = nvll[i]; - } - } - - if (lp.noiselc < 1.f) { - WaveletDenoiseAllL(Ldecomp, noisevarlum, madL, vari, edge, numThreads); - } else { - WaveletDenoiseAll_BiShrinkL(Ldecomp, noisevarlum, madL, vari, edge, numThreads); - WaveletDenoiseAllL(Ldecomp, noisevarlum, madL, vari, edge, numThreads); - } - - delete [] noisevarlum; - - } - } - - - float variC[levred]; - float variCb[levred]; - - float noisecfr = lp.noisecf; - float noiseccr = lp.noisecc; - - if (lp.adjch > 0.f) { - noisecfr = lp.noisecf * ((100.f + lp.adjch) / 10.f); - noiseccr = lp.noisecc + ((100.f + lp.adjch) / 10.f); - } - - float noisecfb = lp.noisecf; - float noiseccb = lp.noisecc; - - if (lp.adjch < 0.f) { - noisecfb = lp.noisecf * ((100.f - lp.adjch) / 10.f); - noiseccb = lp.noisecc * ((100.f - lp.adjch) / 10.f); - } - - - if (noisecfr < 0.f) { - noisecfr = 0.0001f; - } - - if (noiseccr < 0.f) { - noiseccr = 0.0001f; - } - - if (noisecfb < 0.f) { - noisecfb = 0.0001f; - } - - if (noiseccb < 0.f) { - noiseccb = 0.0001f; - } - - - if (!adecomp.memoryAllocationFailed && !bdecomp.memoryAllocationFailed) { - - if (levred == 7) { - edge = 2; - variC[0] = SQR(noisecfr); - variC[1] = SQR(noisecfr); - variC[2] = SQR(noisecfr); - - variC[3] = SQR(noisecfr); - variC[4] = SQR(noisecfr); - variC[5] = SQR(noiseccr); - variC[6] = SQR(noiseccr); - - variCb[0] = SQR(noisecfb); - variCb[1] = SQR(noisecfb); - variCb[2] = SQR(noisecfb); - - variCb[3] = SQR(noisecfb); - variCb[4] = SQR(noisecfb); - variCb[5] = SQR(noiseccb); - variCb[6] = SQR(noiseccb); - - } else if (levred == 4) { - edge = 3; - variC[0] = SQR(lp.noisecf / 10.0); - variC[1] = SQR(lp.noisecf / 10.0); - variC[2] = SQR(lp.noisecf / 10.0); - variC[3] = SQR(lp.noisecf / 10.0); - - variCb[0] = SQR(lp.noisecf / 10.0); - variCb[1] = SQR(lp.noisecf / 10.0); - variCb[2] = SQR(lp.noisecf / 10.0); - variCb[3] = SQR(lp.noisecf / 10.0); - - - } - - - if ((lp.noisecf >= 0.1f || lp.noisecc >= 0.1f || noiscfactiv)) { - float minic = 0.0001f; - - if (noiscfactiv) { - minic = 0.1f;//only for artifact shape detection - } - - float k1 = 0.f; - float k2 = 0.f; - float k3 = 0.f; - - if (lp.noisecf < 0.2f) { - k1 = 0.f; - k2 = 0.f; - k3 = 0.f; - } else if (lp.noisecf < 0.3f) { - k1 = 0.1f; - k2 = 0.0f; - k3 = 0.f; - } else if (lp.noisecf < 0.5f) { - k1 = 0.2f; - k2 = 0.1f; - k3 = 0.f; - } else if (lp.noisecf < 0.8f) { - k1 = 0.3f; - k2 = 0.25f; - k3 = 0.f; - } else if (lp.noisecf < 1.f) { - k1 = 0.4f; - k2 = 0.25f; - k3 = 0.1f; - } else if (lp.noisecf < 2.f) { - k1 = 0.5f; - k2 = 0.3f; - k3 = 0.15f; - } else if (lp.noisecf < 3.f) { - k1 = 0.6f; - k2 = 0.45f; - k3 = 0.3f; - } else if (lp.noisecf < 4.f) { - k1 = 0.7f; - k2 = 0.5f; - k3 = 0.4f; - } else if (lp.noisecf < 5.f) { - k1 = 0.8f; - k2 = 0.6f; - k3 = 0.5f; - } else if (lp.noisecf < 10.f) { - k1 = 0.85f; - k2 = 0.7f; - k3 = 0.6f; - } else if (lp.noisecf < 20.f) { - k1 = 0.9f; - k2 = 0.8f; - k3 = 0.7f; - } else if (lp.noisecf < 50.f) { - k1 = 1.f; - k2 = 1.f; - k3 = 0.9f; - - } else { - k1 = 1.f; - k2 = 1.f; - k3 = 1.f; - } - - variC[0] = max(minic, variC[0]); - variC[1] = max(minic, k1 * variC[1]); - variC[2] = max(minic, k2 * variC[2]); - variC[3] = max(minic, k3 * variC[3]); - - variCb[0] = max(minic, variCb[0]); - variCb[1] = max(minic, k1 * variCb[1]); - variCb[2] = max(minic, k2 * variCb[2]); - variCb[3] = max(minic, k3 * variCb[3]); - - if (levred == 7) { - float k4 = 0.f; - float k5 = 0.f; - float k6 = 0.f; - - if (lp.noisecc == 0.1f) { - k4 = 0.f; - k5 = 0.0f; - } else if (lp.noisecc < 0.2f) { - k4 = 0.1f; - k5 = 0.0f; - } else if (lp.noisecc < 0.5f) { - k4 = 0.15f; - k5 = 0.0f; - } else if (lp.noisecc < 1.f) { - k4 = 0.15f; - k5 = 0.1f; - } else if (lp.noisecc < 3.f) { - k4 = 0.3f; - k5 = 0.15f; - } else if (lp.noisecc < 4.f) { - k4 = 0.6f; - k5 = 0.4f; - } else if (lp.noisecc < 6.f) { - k4 = 0.8f; - k5 = 0.6f; - } else { - k4 = 1.f; - k5 = 1.f; - } - - - variC[4] = max(0.0001f, k4 * variC[4]); - variC[5] = max(0.0001f, k5 * variC[5]); - variCb[4] = max(0.0001f, k4 * variCb[4]); - variCb[5] = max(0.0001f, k5 * variCb[5]); - - if (lp.noisecc < 4.f) { - k6 = 0.f; - } else if (lp.noisecc < 5.f) { - k6 = 0.4f; - } else if (lp.noisecc < 6.f) { - k6 = 0.7f; - } else { - k6 = 1.f; - } - - variC[6] = max(0.0001f, k6 * variC[6]); - variCb[6] = max(0.0001f, k6 * variCb[6]); - } - - float* noisevarchrom = new float[bfh * bfw]; - int bfw2 = (bfw + 1) / 2; - float nvch = 0.6f;//high value - float nvcl = 0.1f;//low value - - if (lp.noisecf > 100.f) { - nvch = 0.8f; - nvcl = 0.4f; - } - - float seuil = 4000.f;//low - float seuil2 = 15000.f;//high - //ac and bc for transition - float ac = (nvch - nvcl) / (seuil - seuil2); - float bc = nvch - seuil * ac; -#ifdef _OPENMP - #pragma omp parallel for - -#endif - - for (int ir = 0; ir < bfh; ir++) - for (int jr = 0; jr < bfw; jr++) { - float cN = sqrt(SQR(bufwv.a[ir][jr]) + SQR(bufwv.b[ir][jr])); - - if (cN < seuil) { - noisevarchrom[(ir >> 1)*bfw2 + (jr >> 1)] = nvch; - } else if (cN < seuil2) { - noisevarchrom[(ir >> 1)*bfw2 + (jr >> 1)] = ac * cN + bc; - } else { - noisevarchrom[(ir >> 1)*bfw2 + (jr >> 1)] = nvcl; - } - } - - float noisevarab_r = 100.f; //SQR(lp.noisecc / 10.0); - - - if (lp.noisecc < 0.1f) { - WaveletDenoiseAllAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads); - WaveletDenoiseAllAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads); - } else { - WaveletDenoiseAll_BiShrinkAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads); - WaveletDenoiseAllAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, true, false, false, numThreads); - - WaveletDenoiseAll_BiShrinkAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads); - WaveletDenoiseAllAB(Ldecomp, bdecomp, noisevarchrom, madL, variCb, edge, noisevarab_r, true, false, false, numThreads); - } - - delete[] noisevarchrom; - } - } - - if (!Ldecomp.memoryAllocationFailed) { - Lin = new array2D(bfw, bfh); - -#ifdef _OPENMP - #pragma omp parallel for - -#endif - - for (int i = 0; i < bfh; ++i) { - for (int j = 0; j < bfw; ++j) { - (*Lin)[i][j] = bufwv.L[i][j]; - } - } - - Ldecomp.reconstruct(bufwv.L[0]); - } - - - if (!Ldecomp.memoryAllocationFailed) { - - - if ((lp.noiself >= 0.1f || lp.noiself0 >= 0.1f || lp.noiself2 >= 0.1f || lp.noiselc >= 0.1f) && levred == 7) { - fftw_denoise(bfw, bfh, max_numblox_W, min_numblox_W, bufwv.L, Lin, numThreads, lp, 0); - } - } - - - if (!adecomp.memoryAllocationFailed) { - adecomp.reconstruct(bufwv.a[0]); - } - - - if (!bdecomp.memoryAllocationFailed) { - bdecomp.reconstruct(bufwv.b[0]); - } - - DeNoise_Local(call, lp, levred, huerefblur, lumarefblur, chromarefblur, original, transformed, bufwv, cx, cy, sk); + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); } + } + if (denoiz || blurz || lp.denoiena || lp.blurena) { + delete originalmaskbl; } //begin cbdl @@ -6064,13 +11251,6 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o originalmaskcb.reset(new LabImage(bfw, bfh)); } - array2D ble(bfw, bfh); - array2D guid(bfw, bfh); - float meanfab, fab; - - mean_fab(xstart, ystart, bfw, bfh, loctemp.get(), original, fab, meanfab, lp.chromacbm); - // printf("fab=%f lpchro=%f \n", fab, lp.chromacbm); - #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -6081,98 +11261,73 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } } - if (lp.showmaskcbmet == 2 || lp.enacbMask || lp.showmaskcbmet == 3 || lp.showmaskcbmet == 4) { - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < bfh; ir++) { - for (int jr = 0; jr < bfw; jr++) { - float kmaskLexp = 0; - float kmaskCH = 0; - - if (locllmascbCurve && llmascbutili) { - float ligh = loctemp->L[ir][jr] / 32768.f; - kmaskLexp = 32768.f * LIM01(1.f - locllmascbCurve[500.f * ligh]); - } - - if (lp.showmaskcbmet != 4) { - if (locccmascbCurve && lcmascbutili) { - float chromask = 0.0001f + sqrt(SQR((loctemp->a[ir][jr]) / fab) + SQR((loctemp->b[ir][jr]) / fab)); - kmaskCH = LIM01(1.f - locccmascbCurve[500.f * chromask]); - } - } - - if (lochhmascbCurve && lhmascbutili) { - float huema = xatan2f(loctemp->b[ir][jr], loctemp->a[ir][jr]); - float h = Color::huelab_to_huehsv2(huema); - h += 1.f / 6.f; - - if (h > 1.f) { - h -= 1.f; - } - - float valHH = LIM01(1.f - lochhmascbCurve[500.f * h]); - - if (lp.showmaskcbmet != 4) { - kmaskCH += valHH; - } - - kmaskLexp += 32768.f * valHH; - } - - bufmaskblurcb->L[ir][jr] = CLIPLOC(kmaskLexp); - bufmaskblurcb->a[ir][jr] = kmaskCH; - bufmaskblurcb->b[ir][jr] = kmaskCH; - ble[ir][jr] = bufmaskblurcb->L[ir][jr] / 32768.f; - guid[ir][jr] = loctemp->L[ir][jr] / 32768.f; - - } - } - - if (lp.radmacb > 0.f) { - guidedFilter(guid, ble, ble, lp.radmacb * 10.f / sk, 0.001, multiThread, 4); - } - - LUTf lutTonemaskcb(65536); - calcGammaLut(lp.gammacb, lp.slomacb, lutTonemaskcb); - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < bfh; ir++) - for (int jr = 0; jr < bfw; jr++) { - float L_; - bufmaskblurcb->L[ir][jr] = LIM01(ble[ir][jr]) * 32768.f; - L_ = 2.f * bufmaskblurcb->L[ir][jr]; - bufmaskblurcb->L[ir][jr] = lutTonemaskcb[L_]; - } + int inv = 0; + bool showmaske = false; + bool enaMask = false; + bool deltaE = false; + bool modmask = false; + bool zero = false; + bool modif = false; + if (lp.showmaskcbmet == 3) { + showmaske = true; } - float radiusb = 1.f / sk; + if (lp.enacbMask) { + enaMask = true; + } - if (lp.showmaskcbmet == 2 || lp.enacbMask || lp.showmaskcbmet == 3 || lp.showmaskcbmet == 4) { + if (lp.showmaskcbmet == 4) { + deltaE = true; + } -#ifdef _OPENMP - #pragma omp parallel -#endif - { - gaussianBlur(bufmaskblurcb->L, bufmaskorigcb->L, bfw, bfh, radiusb); - gaussianBlur(bufmaskblurcb->a, bufmaskorigcb->a, bfw, bfh, 1.f + (0.5f * lp.radmacb) / sk); - gaussianBlur(bufmaskblurcb->b, bufmaskorigcb->b, bfw, bfh, 1.f + (0.5f * lp.radmacb) / sk); - } + if (lp.showmaskcbmet == 2) { + modmask = true; + } - if (lp.showmaskcbmet == 0 || lp.showmaskcbmet == 1 || lp.showmaskcbmet == 2 || lp.showmaskcbmet == 4 || lp.enacbMask) { + if (lp.showmaskcbmet == 1) { + modif = true; + } - blendmask(lp, xstart, ystart, cx, cy, bfw, bfh, loctemp.get(), original, bufmaskorigcb.get(), originalmaskcb.get(), lp.blendmacb); + if (lp.showmaskcbmet == 0) { + zero = true; + } - } else if (lp.showmaskcbmet == 3) { - showmask(lp, xstart, ystart, cx, cy, bfw, bfh, loctemp.get(), transformed, bufmaskorigcb.get()); - return; - } + float chrom = lp.chromacbm;; + float rad = lp.radmacb; + float gamma = lp.gammacb; + float slope = lp.slomacb; + float blendm = lp.blendmacb; + float lap = params->locallab.spots.at(sp).lapmaskcb; + bool pde = params->locallab.spots.at(sp).laplac; + LocwavCurve dummy; + bool delt = params->locallab.spots.at(sp).deltae; + int sco = params->locallab.spots.at(sp).scopemask; + int lumask = params->locallab.spots.at(sp).lumask; + int shado = 0; + const int limscope = 80; + const float mindE = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + bool lmasutilicolwav = false; + float amountcd = 0.f; + float anchorcd = 50.f; + int shortcu = 0; //lp.mergemet; //params->locallab.spots.at(sp).shortc; + LocHHmaskCurve lochhhmasCurve; + bool lhhmasutili = false; + maskcalccol(call, false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, loctemp.get(), bufmaskorigcb.get(), originalmaskcb.get(), original, reserved, inv, lp, + 0.f, false, + locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, lochhhmasCurve, lhhmasutili, multiThread, + enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, shado, amountcd, anchorcd, lmaskcblocalcurve, localmaskcbutili, dummy, lmasutilicolwav, 1, 1, 5, 5, + shortcu, delt, hueref, chromaref, lumaref, + maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco + ); + + if (lp.showmaskcbmet == 3) { + showmask(lumask, lp, xstart, ystart, cx, cy, bfw, bfh, loctemp.get(), transformed, bufmaskorigcb.get(), 0); + + return; } constexpr float b_l = -5.f; @@ -6204,20 +11359,15 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o lp.mulloc[5] = 1.001f; } - /* - for (int lv = 0; lv < 6; lv++) { - printf("mulloc=%f lv=%i\n", lp.mulloc[lv], lv); - } - */ ImProcFunctions::cbdl_local_temp(bufsh, loctemp->L, bfw, bfh, lp.mulloc, 1.f, lp.threshol, lp.clarityml, lp.contresid, lp.blurcbdl, skinprot, false, b_l, t_l, t_r, b_r, choice, sk, multiThread); if (lp.softradiuscb > 0.f) { - softproc(origcbdl.get(), loctemp.get(), lp.softradiuscb, bfh, bfw, 0.0001, 0.00001, 0.0001f, sk, multiThread); + softproc(origcbdl.get(), loctemp.get(), lp.softradiuscb, bfh, bfw, 0.0001, 0.00001, 0.1f, sk, multiThread, 1); } } - transit_shapedetect(6, loctemp.get(), originalmaskcb.get(), buflight, bufchrom, nullptr, nullptr, nullptr, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); + transit_shapedetect(6, loctemp.get(), originalmaskcb.get(), bufchrom, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); bool nochroma = (lp.showmaskcbmet == 2 || lp.showmaskcbmet == 1); @@ -6246,7 +11396,6 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o for (int lv = 0; lv < 6; lv++) { multc[lv] = rtengine::max((lp.chromacb * ((float) lp.mulloc[lv] - 1.f)) + 1.f, 0.01f); - // printf("multc=%f lev=%i\n", multc[lv], lv); } choice = 1; @@ -6269,6 +11418,10 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o float coefC = 0.01f * (max(fabs(minC), fabs(maxC))); + if (coefC == 0.f) { + coefC = 1.f; + } + @@ -6282,7 +11435,15 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } } - transit_shapedetect(7, loctemp.get(), nullptr, buflight, bufchrom, nullptr, nullptr, nullptr, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); + transit_shapedetect(7, loctemp.get(), nullptr, bufchrom, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); + buflight.free(); + bufsh.free(); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } } } } @@ -6291,77 +11452,9 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o //end cbdl_Local - -//Blur and noise - - if (((radius >= 1.5 * GAUSS_SKIP && lp.rad > 1.) || lp.stren > 0.1) && lp.blurena) { // radius < GAUSS_SKIP means no gauss, just copy of original image - std::unique_ptr tmp1; - - if (call <= 3 && lp.blurmet == 0) { - const int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); - const int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); - const int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); - const int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); - const int bfh = yend - ystart; - const int bfw = xend - xstart; - - if (bfw > 0 && bfh > 0) { - tmp1.reset(new LabImage(bfw, bfh)); -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = ystart; y < yend ; y++) { - for (int x = xstart; x < xend; x++) { - tmp1->L[y - ystart][x - xstart] = original->L[y][x]; - tmp1->a[y - ystart][x - xstart] = original->a[y][x]; - tmp1->b[y - ystart][x - xstart] = original->b[y][x]; - } - } - -#ifdef _OPENMP - #pragma omp parallel -#endif - - { - gaussianBlur(tmp1->L, tmp1->L, bfw, bfh, radius); - gaussianBlur(tmp1->a, tmp1->a, bfw, bfh, radius); - gaussianBlur(tmp1->b, tmp1->b, bfw, bfh, radius); - } - } - } else { - const int GW = transformed->W; - const int GH = transformed->H; - tmp1.reset(new LabImage(transformed->W, transformed->H)); - -#ifdef _OPENMP - #pragma omp parallel -#endif - { - gaussianBlur(original->L, tmp1->L, GW, GH, radius); - gaussianBlur(original->a, tmp1->a, GW, GH, radius); - gaussianBlur(original->b, tmp1->b, GW, GH, radius); - } - } - - if (tmp1.get() && lp.stren > 0.1f) { - float mean = 0.f;//0 best result - float variance = lp.stren ; - addGaNoise(tmp1.get(), tmp1.get(), mean, variance, sk) ; - } - - if (lp.blurmet == 0) { //blur and noise (center) - if (tmp1.get()) { - BlurNoise_Local(tmp1.get(), hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); - } - } else { - InverseBlurNoise_Local(lp, hueref, chromaref, lumaref, original, transformed, tmp1.get(), cx, cy, sk); - } - } - //vibrance - if (lp.expvib && (lp.past != 0.f || lp.satur != 0.f)) { //interior ellipse renforced lightness and chroma //locallutili + if (lp.expvib && (lp.past != 0.f || lp.satur != 0.f || lp.strvib != 0.f || lp.war != 0 || lp.strvibab != 0.f || lp.strvibh != 0.f || lp.showmaskvibmet == 2 || lp.enavibMask || lp.showmaskvibmet == 3 || lp.showmaskvibmet == 4) && lp.vibena) { //interior ellipse renforced lightness and chroma //locallutili if (call <= 3) { //simpleprocess, dcrop, improccoordinator const int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); const int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); @@ -6370,50 +11463,215 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o const int bfh = yend - ystart; const int bfw = xend - xstart; - if (bfw > 0 && bfh > 0) { - JaggedArray buflight(bfw, bfh); - JaggedArray bufl_ab(bfw, bfh); + if (bfw >= mSP && bfh >= mSP) { std::unique_ptr bufexporig(new LabImage(bfw, bfh)); std::unique_ptr bufexpfin(new LabImage(bfw, bfh)); + std::unique_ptr bufmaskorigvib; + std::unique_ptr bufmaskblurvib; + std::unique_ptr originalmaskvib; -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = ystart; y < yend; y++) { - for (int x = xstart; x < xend; x++) { - bufexporig->L[y - ystart][x - xstart] = original->L[y][x]; - bufexporig->a[y - ystart][x - xstart] = original->a[y][x]; - bufexporig->b[y - ystart][x - xstart] = original->b[y][x]; - } + if (lp.showmaskvibmet == 2 || lp.enavibMask || lp.showmaskvibmet == 3 || lp.showmaskvibmet == 4) { + bufmaskorigvib.reset(new LabImage(bfw, bfh)); + bufmaskblurvib.reset(new LabImage(bfw, bfh)); + originalmaskvib.reset(new LabImage(bfw, bfh)); } - VibranceParams vibranceParams; - vibranceParams.enabled = params->locallab.spots.at(sp).expvibrance; - vibranceParams.pastels = params->locallab.spots.at(sp).pastels; - vibranceParams.saturated = params->locallab.spots.at(sp).saturated; - vibranceParams.psthreshold = params->locallab.spots.at(sp).psthreshold; - vibranceParams.protectskins = params->locallab.spots.at(sp).protectskins; - vibranceParams.avoidcolorshift = params->locallab.spots.at(sp).avoidcolorshift; - vibranceParams.pastsattog = params->locallab.spots.at(sp).pastsattog; - vibranceParams.skintonescurve = params->locallab.spots.at(sp).skintonescurve; - - bufexpfin->CopyFrom(bufexporig.get()); - ImProcFunctions::vibrance(bufexpfin.get(), vibranceParams, params->toneCurve.hrenabled, params->icm.workingProfile); - #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif for (int y = 0; y < bfh; y++) { for (int x = 0; x < bfw; x++) { - buflight[y][x] = CLIPRET((bufexpfin->L[y][x] - bufexporig->L[y][x]) / 328.f); - bufl_ab[y][x] = CLIPRET((sqrt(SQR(bufexpfin->a[y][x]) + SQR(bufexpfin->b[y][x])) - sqrt(SQR(bufexporig->a[y][x]) + SQR(bufexporig->b[y][x]))) / 250.f); + bufexporig->L[y][x] = original->L[y + ystart][x + xstart]; } } - bufexpfin.reset(); - transit_shapedetect(2, bufexporig.get(), nullptr, buflight, bufl_ab, nullptr, nullptr, nullptr, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); + int inv = 0; + bool showmaske = false; + bool enaMask = false; + bool deltaE = false; + bool modmask = false; + bool zero = false; + bool modif = false; + + if (lp.showmaskvibmet == 3) { + showmaske = true; + } + + if (lp.enavibMask) { + enaMask = true; + } + + if (lp.showmaskvibmet == 4) { + deltaE = true; + } + + if (lp.showmaskvibmet == 2) { + modmask = true; + } + + if (lp.showmaskvibmet == 1) { + modif = true; + } + + if (lp.showmaskvibmet == 0) { + zero = true; + } + + float chrom = lp.chromavib; + float rad = lp.radmavib; + float gamma = lp.gammavib; + float slope = lp.slomavib; + float blendm = lp.blendmavib; + float lap = params->locallab.spots.at(sp).lapmaskvib; + bool pde = params->locallab.spots.at(sp).laplac; + LocwavCurve dummy; + bool lmasutilicolwav = false; + bool delt = params->locallab.spots.at(sp).deltae; + int sco = params->locallab.spots.at(sp).scopemask; + int shortcu = 0;//lp.mergemet; //params->locallab.spots.at(sp).shortc; + + const int limscope = 80; + const float mindE = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + int shado = 0; + int lumask = params->locallab.spots.at(sp).lumask; + LocHHmaskCurve lochhhmasCurve; + bool lhhmasutili = false; + float amountcd = 0.f; + float anchorcd = 50.f; + + maskcalccol(call, false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufexporig.get(), bufmaskorigvib.get(), originalmaskvib.get(), original, reserved, inv, lp, + 0.f, false, + locccmasvibCurve, lcmasvibutili, locllmasvibCurve, llmasvibutili, lochhmasvibCurve, lhmasvibutili, lochhhmasCurve, lhhmasutili, multiThread, + enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, shado, amountcd, anchorcd, lmaskviblocalcurve, localmaskvibutili, dummy, lmasutilicolwav, 1, 1, 5, 5, + shortcu, delt, hueref, chromaref, lumaref, + maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco + ); + + if (lp.showmaskvibmet == 3) { + showmask(lumask, lp, xstart, ystart, cx, cy, bfw, bfh, bufexporig.get(), transformed, bufmaskorigvib.get(), 0); + + return; + } + + if (lp.showmaskvibmet == 0 || lp.showmaskvibmet == 1 || lp.showmaskvibmet == 2 || lp.showmaskvibmet == 4 || lp.enavibMask) { + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = ystart; y < yend; y++) { + for (int x = xstart; x < xend; x++) { + bufexporig->L[y - ystart][x - xstart] = original->L[y][x]; + bufexporig->a[y - ystart][x - xstart] = original->a[y][x]; + bufexporig->b[y - ystart][x - xstart] = original->b[y][x]; + } + } + + VibranceParams vibranceParams; + vibranceParams.enabled = params->locallab.spots.at(sp).expvibrance; + vibranceParams.pastels = params->locallab.spots.at(sp).pastels; + vibranceParams.saturated = params->locallab.spots.at(sp).saturated; + vibranceParams.psthreshold = params->locallab.spots.at(sp).psthreshold; + vibranceParams.protectskins = params->locallab.spots.at(sp).protectskins; + vibranceParams.avoidcolorshift = params->locallab.spots.at(sp).avoidcolorshift; + vibranceParams.pastsattog = params->locallab.spots.at(sp).pastsattog; + vibranceParams.skintonescurve = params->locallab.spots.at(sp).skintonescurve; + + + bufexpfin->CopyFrom(bufexporig.get()); + + if (lp.strvibh != 0.f) { + struct grad_params gph; + calclocalGradientParams(lp, gph, ystart, xstart, bfw, bfh, 9); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + double factor = 1.0; + factor = ImProcFunctions::calcGradientFactor(gph, jr, ir); + float aa = bufexpfin->a[ir][jr]; + float bb = bufexpfin->b[ir][jr]; + float chrm = sqrt(SQR(aa) + SQR(bb)); + float HH = xatan2f(bb, aa); + + float newhr = 0.f; + float cor = 0.f; + + if (factor < 1.f) { + cor = - 2.5f * (1.f - factor); + } else if (factor > 1.f) { + cor = 0.03f * (factor - 1.f); + } + + newhr = HH + cor; + + if (newhr > rtengine::RT_PI_F) { + newhr -= 2 * rtengine::RT_PI_F; + } else if (newhr < -rtengine::RT_PI_F) { + newhr += 2 * rtengine::RT_PI_F; + } + + float2 sincosval = xsincosf(newhr); + bufexpfin->a[ir][jr] = CLIPC(chrm * sincosval.y); + bufexpfin->b[ir][jr] = CLIPC(chrm * sincosval.x); + } + } + + if (lp.strvib != 0.f) { + struct grad_params gp; + calclocalGradientParams(lp, gp, ystart, xstart, bfw, bfh, 7); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + double factor = 1.0; + factor = ImProcFunctions::calcGradientFactor(gp, jr, ir); + bufexpfin->L[ir][jr] *= factor; + } + } + + if (lp.strvibab != 0.f) { + struct grad_params gpab; + calclocalGradientParams(lp, gpab, ystart, xstart, bfw, bfh, 8); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + double factor = 1.0; + factor = ImProcFunctions::calcGradientFactor(gpab, jr, ir); + bufexpfin->a[ir][jr] *= factor; + bufexpfin->b[ir][jr] *= factor; + } + } + + ImProcFunctions::vibrance(bufexpfin.get(), vibranceParams, params->toneCurve.hrenabled, params->icm.workingProfile); + + if (params->locallab.spots.at(sp).warm != 0) { + ImProcFunctions::ciecamloc_02float(sp, bufexpfin.get()); + } + + + transit_shapedetect2(call, 2, bufexporig.get(), bufexpfin.get(), originalmaskvib.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); + + + } + + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } } } } @@ -6430,25 +11688,29 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o const int bfh = yend - ystart; const int bfw = xend - xstart; - if (bfw > 0 && bfh > 0) { + if (bfw >= mSP && bfh >= mSP) { array2D buflight(bfw, bfh); JaggedArray bufchro(bfw, bfh); std::unique_ptr bufgb(new LabImage(bfw, bfh)); std::unique_ptr tmp1(new LabImage(bfw, bfh)); + std::unique_ptr bufgbm(new LabImage(bfw, bfh)); + std::unique_ptr tmp1m(new LabImage(bfw, bfh)); std::unique_ptr bufmaskorigtm; std::unique_ptr bufmaskblurtm; std::unique_ptr originalmasktm; + // if (lp.showmasktmmet == 0 || lp.showmasktmmet == 2 || lp.enatmMask || lp.showmasktmmet == 3 || lp.showmasktmmet == 4) { if (lp.showmasktmmet == 2 || lp.enatmMask || lp.showmasktmmet == 3 || lp.showmasktmmet == 4) { bufmaskorigtm.reset(new LabImage(bfw, bfh)); bufmaskblurtm.reset(new LabImage(bfw, bfh)); originalmasktm.reset(new LabImage(bfw, bfh)); } - array2D ble(bfw, bfh); - array2D guid(bfw, bfh); - float meanfab, fab; - mean_fab(xstart, ystart, bfw, bfh, bufgb.get(), original, fab, meanfab, lp.chromatm); + int itera = 0; + + if (call == 1) { + // itera = 5; + } #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) @@ -6459,135 +11721,141 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o bufgb->L[y - ystart][x - xstart] = original->L[y][x]; bufgb->a[y - ystart][x - xstart] = original->a[y][x]; bufgb->b[y - ystart][x - xstart] = original->b[y][x]; + bufgbm->L[y - ystart][x - xstart] = original->L[y][x]; + bufgbm->a[y - ystart][x - xstart] = original->a[y][x]; + bufgbm->b[y - ystart][x - xstart] = original->b[y][x]; } } - int itera = 0; + int inv = 0; + bool showmaske = false; + bool enaMask = false; + bool deltaE = false; + bool modmask = false; + bool zero = false; + bool modif = false; - if (call == 1) { - // itera = 5; + if (lp.showmasktmmet == 3) { + showmaske = true; } - if (lp.showmasktmmet == 2 || lp.enatmMask || lp.showmasktmmet == 3 || lp.showmasktmmet == 4) { -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < bfh; ir++) { - for (int jr = 0; jr < bfw; jr++) { - float kmaskLexp = 0; - float kmaskCH = 0; - - if (locllmastmCurve && llmastmutili) { - float ligh = bufgb->L[ir][jr] / 32768.f; - kmaskLexp = 32768.f * LIM01(1.f - locllmastmCurve[500.f * ligh]); - } - - if (lp.showmasktmmet != 4) { - if (locccmastmCurve && lcmastmutili) { - float chromask = 0.0001f + sqrt(SQR((bufgb->a[ir][jr]) / fab) + SQR((bufgb->b[ir][jr]) / fab)); - kmaskCH = LIM01(1.f - locccmastmCurve[500.f * chromask]); - } - } - - if (lochhmastmCurve && lhmastmutili) { - float huema = xatan2f(bufgb->b[ir][jr], bufgb->a[ir][jr]); - float h = Color::huelab_to_huehsv2(huema); - h += 1.f / 6.f; - - if (h > 1.f) { - h -= 1.f; - } - - float valHH = LIM01(1.f - lochhmastmCurve[500.f * h]); - - if (lp.showmasktmmet != 4) { - kmaskCH += valHH; - } - - kmaskLexp += 32768.f * valHH; - } - - bufmaskblurtm->L[ir][jr] = CLIPLOC(kmaskLexp); - bufmaskblurtm->a[ir][jr] = kmaskCH; - bufmaskblurtm->b[ir][jr] = kmaskCH; - ble[ir][jr] = bufmaskblurtm->L[ir][jr] / 32768.f; - guid[ir][jr] = bufgb->L[ir][jr] / 32768.f; - - } - } - - if (lp.radmatm > 0.f) { - guidedFilter(guid, ble, ble, lp.radmatm * 10.f / sk, 0.001, multiThread, 4); - } - - LUTf lutTonemasktm(65536); - calcGammaLut(lp.gammatm, lp.slomatm, lutTonemasktm); - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < bfh; ir++) - for (int jr = 0; jr < bfw; jr++) { - float L_; - bufmaskblurtm->L[ir][jr] = LIM01(ble[ir][jr]) * 32768.f; - L_ = 2.f * bufmaskblurtm->L[ir][jr]; - bufmaskblurtm->L[ir][jr] = lutTonemasktm[L_]; - } - + if (lp.enatmMask) { + enaMask = true; } - float radiusb = 1.f / sk; + if (lp.showmasktmmet == 4) { + deltaE = true; + } - if (lp.showmasktmmet == 2 || lp.enatmMask || lp.showmasktmmet == 3 || lp.showmasktmmet == 4) { + if (lp.showmasktmmet == 2) { + modmask = true; + } - //printf("lp.showmasktmmet=%i\n",lp.showmasktmmet); -#ifdef _OPENMP - #pragma omp parallel -#endif - { - gaussianBlur(bufmaskblurtm->L, bufmaskorigtm->L, bfw, bfh, radiusb); - gaussianBlur(bufmaskblurtm->a, bufmaskorigtm->a, bfw, bfh, 1.f + (0.5f * lp.radmatm) / sk); - gaussianBlur(bufmaskblurtm->b, bufmaskorigtm->b, bfw, bfh, 1.f + (0.5f * lp.radmatm) / sk); - } + if (lp.showmasktmmet == 1) { + modif = true; + } - if (lp.showmasktmmet == 0 || lp.showmasktmmet == 1 || lp.showmasktmmet == 2 || lp.showmasktmmet == 4 || lp.enatmMask) { - blendmask(lp, xstart, ystart, cx, cy, bfw, bfh, bufgb.get(), original, bufmaskorigtm.get(), originalmasktm.get(), lp.blendmatm); + if (lp.showmasktmmet == 0) { + zero = true; + } + + float chrom = lp.chromatm;; + float rad = lp.radmatm; + float gamma = lp.gammatm; + float slope = lp.slomatm; + float blendm = lp.blendmatm; + float lap = params->locallab.spots.at(sp).lapmasktm; + bool pde = params->locallab.spots.at(sp).laplac; + int shortcu = 0; //lp.mergemet;// params->locallab.spots.at(sp).shortc; + int lumask = params->locallab.spots.at(sp).lumask; + + if (!params->locallab.spots.at(sp).enatmMaskaft) { + LocwavCurve dummy; + bool lmasutilicolwav = false; + bool delt = params->locallab.spots.at(sp).deltae; + int sco = params->locallab.spots.at(sp).scopemask; + + const int limscope = 80; + const float mindE = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + int shado = 0; + float amountcd = 0.f; + float anchorcd = 50.f; + LocHHmaskCurve lochhhmasCurve; + bool lhhmasutili = false; + + maskcalccol(call, false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufgbm.get(), bufmaskorigtm.get(), originalmasktm.get(), original, reserved, inv, lp, + 0.f, false, + locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, lochhhmasCurve, lhhmasutili, multiThread, + enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, shado, amountcd, anchorcd, lmasktmlocalcurve, localmasktmutili, dummy, lmasutilicolwav, 1, 1, 5, 5, + shortcu, delt, hueref, chromaref, lumaref, + maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco + ); + + if (lp.showmasktmmet == 3) { + showmask(lumask, lp, xstart, ystart, cx, cy, bfw, bfh, bufgbm.get(), transformed, bufmaskorigtm.get(), 0); - } else if (lp.showmasktmmet == 3) { - showmask(lp, xstart, ystart, cx, cy, bfw, bfh, bufgb.get(), transformed, bufmaskorigtm.get()); return; } } - - if (lp.showmasktmmet == 0 || lp.showmasktmmet == 1 || lp.showmasktmmet == 2 || lp.showmasktmmet == 4 || lp.enatmMask) { - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < bfh ; y++) { - for (int x = 0; x < bfw; x++) { - bufgb->L[y][x] = original->L[y + ystart][x + xstart]; - bufgb->a[y][x] = original->a[y + ystart][x + xstart]; - bufgb->b[y][x] = original->b[y + ystart][x + xstart]; - } - } - + if (lp.showmasktmmet == 0 || lp.showmasktmmet == 1 || lp.showmasktmmet == 2 || lp.showmasktmmet == 4 || lp.showmasktmmet == 3 || lp.enatmMask) { ImProcFunctions::EPDToneMaplocal(sp, bufgb.get(), tmp1.get(), itera, sk);//iterate to 0 calculate with edgstopping, improve result, call=1 dcrop we can put iterate to 5 + tmp1m->CopyFrom(tmp1.get());//save current result + bool enatmMasktmap = params->locallab.spots.at(sp).enatmMaskaft; + + if (enatmMasktmap) { + //calculate new values for original, originalmasktm, bufmaskorigtm...in function of tmp1 + LocwavCurve dummy; + bool lmasutilicolwav = false; + bool delt = params->locallab.spots.at(sp).deltae; + int sco = params->locallab.spots.at(sp).scopemask; + int shortcu = 0;//lp.mergemet; //params->locallab.spots.at(sp).shortc; + int lumask = params->locallab.spots.at(sp).lumask; + + const int limscope = 80; + const float mindE = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + int shado = 0; + float amountcd = 0.f; + float anchorcd = 50.f; + LocHHmaskCurve lochhhmasCurve; + bool lhhmasutili = false; + + maskcalccol(call, false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, tmp1.get(), bufmaskorigtm.get(), originalmasktm.get(), original, reserved, inv, lp, + 0.f, false, + locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, lochhhmasCurve, lhhmasutili, multiThread, + enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, shado, amountcd, anchorcd, lmasktmlocalcurve, localmasktmutili, dummy, lmasutilicolwav, 1, 1, 5, 5, + shortcu, delt, hueref, chromaref, lumaref, + maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco + ); + + if (lp.showmasktmmet == 3) {//dispaly mask + showmask(lumask, lp, xstart, ystart, cx, cy, bfw, bfh, tmp1.get(), transformed, bufmaskorigtm.get(), 0); + + return; + } + + } + + tmp1->CopyFrom(tmp1m.get());//restore current result + + float minL = tmp1->L[0][0] - bufgb->L[0][0]; float maxL = minL; float minC = sqrt(SQR(tmp1->a[0][0]) + SQR(tmp1->b[0][0])) - sqrt(SQR(bufgb->a[0][0]) + SQR(bufgb->b[0][0])); float maxC = minC; #ifdef _OPENMP - #pragma omp parallel for reduction(max:maxL) reduction(min:minL) schedule(dynamic,16) + #pragma omp parallel for reduction(max:maxL) reduction(min:minL) reduction(max:maxC) reduction(min:minC) schedule(dynamic,16) #endif for (int ir = 0; ir < bfh; ir++) { @@ -6604,6 +11872,15 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o float coef = 0.01f * (max(fabs(minL), fabs(maxL))); float coefC = 0.01f * (max(fabs(minC), fabs(maxC))); + if (coef == 0.f) { + coef = 1.f; + } + + if (coefC == 0.f) { + coefC = 1.f; + } + + #ifdef _OPENMP #pragma omp parallel for #endif @@ -6612,29 +11889,20 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o for (int x = 0; x < bfw; x++) { buflight[y][x] /= coef; bufchro[y][x] /= coefC; - // guid[y][x] = (bufgb->L[y][x]) / 32768.f; - // ble[y][x] = (tmp1->L[y][x] - bufgb->L[y][x]) / 32768.f; } } - /* - if (lp.softradiustm > 0.f) { - guidedFilter(guid, ble, ble, 0.1f * lp.softradiustm / sk, 0.0001, multiThread); - // softprocess(bufgb.get(), buflight, lp.softradiustm, bfh, bfw, sk, multiThread); - } + // transit_shapedetect_retinex(call, 4, bufgb.get(),bufmaskorigtm.get(), originalmasktm.get(), buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); + transit_shapedetect2(call, 8, bufgb.get(), tmp1.get(), originalmasktm.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); - #ifdef _OPENMP - #pragma omp parallel for - #endif - - for (int y = 0; y < bfh; y++) { - for (int x = 0; x < bfw; x++) { - tmp1->L[y][x] = 32768.f * LIM01(ble[y][x]) + bufgb->L[y][x]; - } - } - */ + // transit_shapedetect(8, tmp1.get(), originalmasktm.get(), bufchro, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); bufgb.reset(); - transit_shapedetect(8, tmp1.get(), originalmasktm.get(), buflight, bufchro, nullptr, nullptr, nullptr, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } } } } @@ -6644,8 +11912,19 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o //shadow highlight + bool tonequ = false; - if (! lp.invsh && (lp.highlihs > 0.f || lp.shadowhs > 0.f || lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3 || lp.showmaskSHmet == 4) && call < 3 && lp.hsena) { + if (lp.mullocsh[0] != 0 || lp.mullocsh[1] != 0 || lp.mullocsh[2] != 0 || lp.mullocsh[3] != 0 || lp.mullocsh[4] != 0) { + tonequ = true; + } + + bool tonecurv = false; + + if (params->locallab.spots.at(sp).gamSH != 2.4 || params->locallab.spots.at(sp).sloSH != 12.92) { + tonecurv = true; + } + + if (! lp.invsh && (lp.highlihs > 0.f || lp.shadowhs > 0.f || tonequ || tonecurv || lp.strSH != 0.f || lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3 || lp.showmaskSHmet == 4) && call < 3 && lp.hsena) { const int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); const int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); const int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); @@ -6653,7 +11932,11 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o const int bfh = yend - ystart; const int bfw = xend - xstart; - if (bfw > 0 && bfh > 0) { + if (complexsoft == 2) { + lp.shmeth = 1; + } + + if (bfw >= mSP && bfh >= mSP) { std::unique_ptr bufexporig(new LabImage(bfw, bfh)); std::unique_ptr bufexpfin(new LabImage(bfw, bfh)); @@ -6661,8 +11944,6 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o std::unique_ptr bufmaskblurSH; std::unique_ptr originalmaskSH; - JaggedArray buflight(bfw, bfh); - JaggedArray bufl_ab(bfw, bfh); if (call <= 3) { //simpleprocess, dcrop, improccoordinator if (lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3 || lp.showmaskSHmet == 4) { @@ -6671,12 +11952,6 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o originalmaskSH.reset(new LabImage(bfw, bfh)); } - array2D ble(bfw, bfh); - array2D guid(bfw, bfh); - float meanfab, fab; - - mean_fab(xstart, ystart, bfw, bfh, bufexporig.get(), original, fab, meanfab, lp.chromaSH); - #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -6687,99 +11962,76 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } } - if (lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3 || lp.showmaskSHmet == 4) { -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < bfh; ir++) { - for (int jr = 0; jr < bfw; jr++) { - float kmaskLexp = 0; - float kmaskCH = 0; - - if (locllmasSHCurve && llmasSHutili) { - float ligh = bufexporig->L[ir][jr] / 32768.f; - kmaskLexp = 32768.f * LIM01(1.f - locllmasSHCurve[500.f * ligh]); - } - - if (lp.showmaskSHmet != 4) { - if (locccmasSHCurve && lcmasSHutili) { - float chromask = 0.0001f + sqrt(SQR((bufexporig->a[ir][jr]) / fab) + SQR((bufexporig->b[ir][jr]) / fab)); - kmaskCH = LIM01(1.f - locccmasSHCurve[500.f * chromask]); - } - } - - if (lochhmasSHCurve && lhmasSHutili) { - float huema = xatan2f(bufexporig->b[ir][jr], bufexporig->a[ir][jr]); - float h = Color::huelab_to_huehsv2(huema); - h += 1.f / 6.f; - - if (h > 1.f) { - h -= 1.f; - } - - float valHH = LIM01(1.f - lochhmasSHCurve[500.f * h]); - - if (lp.showmaskSHmet != 4) { - kmaskCH += valHH; - } - - kmaskLexp += 32768.f * valHH; - } - - bufmaskblurSH->L[ir][jr] = CLIPLOC(kmaskLexp); - bufmaskblurSH->a[ir][jr] = kmaskCH; - bufmaskblurSH->b[ir][jr] = kmaskCH; - ble[ir][jr] = bufmaskblurSH->L[ir][jr] / 32768.f; - guid[ir][jr] = bufexporig->L[ir][jr] / 32768.f; - - } - } - - if (lp.radmaSH > 0.f) { - guidedFilter(guid, ble, ble, lp.radmaSH * 10.f / sk, 0.001, multiThread, 4); - } - - LUTf lutTonemaskSH(65536); - calcGammaLut(lp.gammaSH, lp.slomaSH, lutTonemaskSH); - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < bfh; ir++) - for (int jr = 0; jr < bfw; jr++) { - float L_; - bufmaskblurSH->L[ir][jr] = LIM01(ble[ir][jr]) * 32768.f; - L_ = 2.f * bufmaskblurSH->L[ir][jr]; - bufmaskblurSH->L[ir][jr] = lutTonemaskSH[L_]; - } + int inv = 0; + bool showmaske = false; + bool enaMask = false; + bool deltaE = false; + bool modmask = false; + bool zero = false; + bool modif = false; + if (lp.showmaskSHmet == 3) { + showmaske = true; } - float radiusb = 1.f / sk; - - if (lp.showmaskSHmet == 2 || lp.enaSHMask || lp.showmaskSHmet == 3 || lp.showmaskSHmet == 4) { - - -#ifdef _OPENMP - #pragma omp parallel -#endif - { - gaussianBlur(bufmaskblurSH->L, bufmaskorigSH->L, bfw, bfh, radiusb); - gaussianBlur(bufmaskblurSH->a, bufmaskorigSH->a, bfw, bfh, 1.f + (0.5f * lp.radmaSH) / sk); - gaussianBlur(bufmaskblurSH->b, bufmaskorigSH->b, bfw, bfh, 1.f + (0.5f * lp.radmaSH) / sk); - } - - if (lp.showmaskSHmet == 0 || lp.showmaskSHmet == 1 || lp.showmaskSHmet == 2 || lp.showmaskSHmet == 4 || lp.enaSHMask) { - blendmask(lp, xstart, ystart, cx, cy, bfw, bfh, bufexporig.get(), original, bufmaskorigSH.get(), originalmaskSH.get(), lp.blendmaSH); - - } else if (lp.showmaskSHmet == 3) { - showmask(lp, xstart, ystart, cx, cy, bfw, bfh, bufexporig.get(), transformed, bufmaskorigSH.get()); - return; - } + if (lp.enaSHMask) { + enaMask = true; } + if (lp.showmaskSHmet == 4) { + deltaE = true; + } + + if (lp.showmaskSHmet == 2) { + modmask = true; + } + + if (lp.showmaskSHmet == 1) { + modif = true; + } + + if (lp.showmaskSHmet == 0) { + zero = true; + } + + float chrom = lp.chromaSH; + float rad = lp.radmaSH; + float gamma = lp.gammaSH; + float slope = lp.slomaSH; + float blendm = lp.blendmaSH; + float lap = params->locallab.spots.at(sp).lapmaskSH; + bool pde = params->locallab.spots.at(sp).laplac; + LocwavCurve dummy; + bool lmasutilicolwav = false; + bool delt = params->locallab.spots.at(sp).deltae; + int sco = params->locallab.spots.at(sp).scopemask; + int shortcu = 0;//lp.mergemet; //params->locallab.spots.at(sp).shortc; + + const int limscope = 80; + const float mindE = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + int shado = 0; + float amountcd = params->locallab.spots.at(sp).fatamountSH; + float anchorcd = params->locallab.spots.at(sp).fatanchorSH; + int lumask = params->locallab.spots.at(sp).lumask; + LocHHmaskCurve lochhhmasCurve; + bool lhhmasutili = false; + + maskcalccol(call, false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufexporig.get(), bufmaskorigSH.get(), originalmaskSH.get(), original, reserved, inv, lp, + 0.f, false, + locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, lochhhmasCurve, lhhmasutili, multiThread, + enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, shado, amountcd, anchorcd, lmaskSHlocalcurve, localmaskSHutili, dummy, lmasutilicolwav, 1, 1, 5, 5, + shortcu, delt, hueref, chromaref, lumaref, + maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco + ); + + if (lp.showmaskSHmet == 3) { + showmask(lumask, lp, xstart, ystart, cx, cy, bfw, bfh, bufexporig.get(), transformed, bufmaskorigSH.get(), 0); + + return; + } if (lp.showmaskSHmet == 0 || lp.showmaskSHmet == 1 || lp.showmaskSHmet == 2 || lp.showmaskSHmet == 4 || lp.enaSHMask) { @@ -6798,27 +12050,159 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } } - ImProcFunctions::shadowsHighlights(bufexpfin.get(), lp.hsena, 1, lp.highlihs, lp.shadowhs, lp.radiushs, sk, lp.hltonalhs, lp.shtonalhs); + if (lp.shmeth == 0) { + ImProcFunctions::shadowsHighlights(bufexpfin.get(), lp.hsena, 1, lp.highlihs, lp.shadowhs, lp.radiushs, sk, lp.hltonalhs, lp.shtonalhs); + } +//gradient + struct grad_params gp; + + if (lp.strSH != 0.f) { + calclocalGradientParams(lp, gp, ystart, xstart, bfw, bfh, 2); #ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int ir = 0; ir < bfh; ir++) { - for (int jr = 0; jr < bfw; jr++) { - buflight[ir][jr] = CLIPRET((bufexpfin->L[ir][jr] - bufexporig->L[ir][jr]) / 328.f); - bufl_ab[ir][jr] = CLIPRET((sqrt(SQR(bufexpfin->a[ir][jr]) + SQR(bufexpfin->b[ir][jr])) - sqrt(SQR(bufexporig->a[ir][jr]) + SQR(bufexporig->b[ir][jr]))) / 250.f); - } + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + double factor = 1.0; + factor = ImProcFunctions::calcGradientFactor(gp, jr, ir); + bufexpfin->L[ir][jr] *= factor; + } } - } - transit_shapedetect(9, bufexpfin.get(), originalmaskSH.get(), buflight, bufl_ab, nullptr, nullptr, nullptr, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); + if (lp.shmeth == 1) { + double scal = (double)(sk); + Imagefloat *tmpImage = nullptr; + tmpImage = new Imagefloat(bfw, bfh); + lab2rgb(*bufexpfin, *tmpImage, params->icm.workingProfile); + + if (tonecurv) { //Tone response curve : does nothing if gamma=2.4 and slope=12.92 ==> gamma sRGB + float gamtone = params->locallab.spots.at(sp).gamSH; + float slotone = params->locallab.spots.at(sp).sloSH; + cmsHTRANSFORM dummy = nullptr; + workingtrc(tmpImage, tmpImage, bfw, bfh, -5, params->icm.workingProfile, 2.4, 12.92310, dummy, true, false, false); + workingtrc(tmpImage, tmpImage, bfw, bfh, 5, params->icm.workingProfile, gamtone, slotone, dummy, false, true, true); + } + + if (tonequ) { + tmpImage->normalizeFloatTo1(); + array2D Rtemp(bfw, bfh, tmpImage->r.ptrs, ARRAY2D_BYREFERENCE); + array2D Gtemp(bfw, bfh, tmpImage->g.ptrs, ARRAY2D_BYREFERENCE); + array2D Btemp(bfw, bfh, tmpImage->b.ptrs, ARRAY2D_BYREFERENCE); + tone_eq(Rtemp, Gtemp, Btemp, lp, params->icm.workingProfile, scal, multiThread); + tmpImage->normalizeFloatTo65535(); + } + + rgb2lab(*tmpImage, *bufexpfin, params->icm.workingProfile); + + delete tmpImage; + } + + } + } + + transit_shapedetect2(call, 9, bufexporig.get(), bufexpfin.get(), originalmaskSH.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); } } - } else if (lp.invsh && (lp.highlihs > 0.f || lp.shadowhs > 0.f) && call < 3 && lp.hsena) { + } else if (lp.invsh && (lp.highlihs > 0.f || lp.shadowhs > 0.f || tonequ || tonecurv || lp.showmaskSHmetinv == 1 || lp.enaSHMaskinv) && call < 3 && lp.hsena) { + std::unique_ptr bufmaskblurcol; + std::unique_ptr originalmaskSH; + std::unique_ptr bufcolorig; + int GW = transformed->W; + int GH = transformed->H; + bufcolorig.reset(new LabImage(GW, GH)); + + if (lp.enaSHMaskinv || lp.showmaskSHmetinv == 1) { + bufmaskblurcol.reset(new LabImage(GW, GH, true)); + originalmaskSH.reset(new LabImage(GW, GH)); + } + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < GH ; y++) { + for (int x = 0; x < GW; x++) { + bufcolorig->L[y][x] = original->L[y][x]; + } + } + + int inv = 1; + bool showmaske = false; + bool enaMask = false; + bool deltaE = false; + bool modmask = false; + bool zero = false; + bool modif = false; + + if (lp.showmaskSHmetinv == 1) { + showmaske = true; + } + + if (lp.enaSHMaskinv) { + enaMask = true; + } + + if (lp.showmaskSHmetinv == 0) { + zero = true; + } + + float chrom = lp.chromaSH; + float rad = lp.radmaSH; + float gamma = lp.gammaSH; + float slope = lp.slomaSH; + float blendm = lp.blendmaSH; + float lap = params->locallab.spots.at(sp).lapmaskSH; + bool pde = params->locallab.spots.at(sp).laplac; + LocwavCurve dummy; + bool lmasutilicolwav = false; + // bool delt = params->locallab.spots.at(sp).deltae; + bool delt = false; + int sco = params->locallab.spots.at(sp).scopemask; + int shortcu = 0;//lp.mergemet; + params->locallab.spots.at(sp).shortc; + + const int limscope = 80;// + const float mindE = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + int shado = 0; + float amountcd = params->locallab.spots.at(sp).fatamountSH; + float anchorcd = params->locallab.spots.at(sp).fatanchorSH; + int lumask = params->locallab.spots.at(sp).lumask; + LocHHmaskCurve lochhhmasCurve; + bool lhhmasutili = false; + + maskcalccol(call, false, pde, GW, GH, 0, 0, sk, cx, cy, bufcolorig.get(), bufmaskblurcol.get(), originalmaskSH.get(), original, reserved, inv, lp, + 0.f, false, + locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, lochhhmasCurve, lhhmasutili, multiThread, + enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, shado, amountcd, anchorcd, lmaskSHlocalcurve, localmaskSHutili, dummy, lmasutilicolwav, 1, 1, 5, 5, + shortcu, delt, hueref, chromaref, lumaref, + maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco + ); + + + if (lp.showmaskSHmetinv == 1) { + showmask(lumask, lp, 0, 0, cx, cy, GW, GH, bufcolorig.get(), transformed, bufmaskblurcol.get(), inv); + + return; + } float adjustr = 2.f; - InverseColorLight_Local(sp, 2, lp, lightCurveloc, hltonecurveloc, shtonecurveloc, tonecurveloc, exlocalcurve, cclocalcurve, adjustr, localcutili, lllocalcurve, locallutili, original, transformed, cx, cy, hueref, chromaref, lumaref, sk); + InverseColorLight_Local(tonequ, tonecurv, sp, 2, lp, originalmaskSH.get(), lightCurveloc, hltonecurveloc, shtonecurveloc, tonecurveloc, exlocalcurve, cclocalcurve, adjustr, localcutili, lllocalcurve, locallutili, original, transformed, cx, cy, hueref, chromaref, lumaref, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } } @@ -6833,104 +12217,20 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); int bfh = yend - ystart; int bfw = xend - xstart; - //vriable for fast FFTW + //variable for fast FFTW int bfhr = bfh; int bfwr = bfw; bool reduH = false; bool reduW = false; - // printf("n_fftw=%i yst=%i yen=%i lp.yc=%f lp.lyT=%f lp.ly=%f bfh=%i origH=%i \n", N_fftwsize, ystart, yend, lp.yc, lp.lyT, lp.ly, bfh, original->H); - // printf("xst= %i xen=%i lp.xc=%f lp.lxL=%f lp.lx=%f bfw=%i origW=%i", xstart, xend, lp.xc, lp.lxL, lp.lx, bfwr, original->W); - if (lp.softmet == 1) { - /* - for (int n=0; n< 17; n++){ - for(int m=0; m < 11; m++) { - for(int l=0; l < 8; l++) { - for(int p=0; p < 6; p++) { - for (int r=0; r < 2; r++){ - int bon = pow(2, n) * pow(3, m) * pow(5, l) * pow(7, p) * pow(13, r); - if(bon >= 18000 && bon < 18200) printf("b=%i", bon); - } - } - } - } - } - */ - int ftsizeH = 1; - int ftsizeW = 1; + if (bfw >= mSP && bfh >= mSP) { - for (int ft = 0; ft < N_fftwsize; ft++) { //find best values - if (fftw_size[ft] <= bfh) { - ftsizeH = fftw_size[ft]; - break; - } + if (lp.softmet == 1) { + optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, reduH, reduW, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy); } - for (int ft = 0; ft < N_fftwsize; ft++) { - if (fftw_size[ft] <= bfw) { - ftsizeW = fftw_size[ft]; - break; - } - } - - // printf("FTsizeH =%i FTsizeW=%i \n", ftsizeH, ftsizeW); - //optimize with size fftw - if (ystart == 0 && yend < original->H) { - lp.ly -= (bfh - ftsizeH); - } else if (ystart != 0 && yend == original->H) { - lp.lyT -= (bfh - ftsizeH); - } else if (ystart != 0 && yend != original->H) { - if (lp.ly <= lp.lyT) { - lp.lyT -= (bfh - ftsizeH); - } else { - lp.ly -= (bfh - ftsizeH); - } - } else if (ystart == 0 && yend == original->H) { - bfhr = ftsizeH; - reduH = true; - } - - if (xstart == 0 && xend < original->W) { - lp.lx -= (bfw - ftsizeW); - } else if (xstart != 0 && xend == original->W) { - lp.lxL -= (bfw - ftsizeW); - } else if (xstart != 0 && xend != original->W) { - if (lp.lx <= lp.lxL) { - lp.lxL -= (bfw - ftsizeW); - } else { - lp.lx -= (bfw - ftsizeW); - } - } else if (xstart == 0 && xend == original->W) { - bfwr = ftsizeW; - reduW = true; - } - - //new values optimized - ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); - yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); - xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); - xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); - bfh = bfhr = yend - ystart; - bfw = bfwr = xend - xstart; - - if (reduH) { - bfhr = ftsizeH; - } - - if (reduW) { - bfwr = ftsizeW; - } - } - - // printf("Nyst=%i Nyen=%i lp.yc=%f lp.lyT=%f lp.ly=%f bfh=%i origH=%i maxH=%i\n", ystart, yend, lp.yc, lp.lyT, lp.ly, bfhr, original->H, maxH); - // printf("Nxst=%i Nxen=%i lp.xc=%f lp.lxL=%f lp.lx=%f bfw=%i origW=%i", xstart, xend, lp.xc, lp.lxL, lp.lx, bfwr, original->W); - - if (bfw > 0 && bfh > 0) { - std::unique_ptr bufexporig(new LabImage(bfw, bfh)); //buffer for data in zone limit - std::unique_ptr bufexpfin(new LabImage(bfw, bfh)); //buffer for data in zone limit - // std::unique_ptr temp(new LabImage(bfw, bfh)); //buffer for data in zone limit - JaggedArray buflight(bfw, bfh); - JaggedArray bufl_ab(bfw, bfh); + std::unique_ptr bufexporig(new LabImage(bfw, bfh)); + std::unique_ptr bufexpfin(new LabImage(bfw, bfh)); #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) @@ -6966,12 +12266,17 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o for (int y = 0; y < bfhr; y++) { for (int x = 0; x < bfwr; x++) { - // datain[y * bfwr + x] = temp->L[y][x] - bufexpfin->L[y][x]; datain[y * bfwr + x] = bufexpfin->L[y][x]; } } - ImProcFunctions::retinex_pde(datain, dataout, bfwr, bfhr, 8.f * lp.strng, 1.f, dE, lp.showmasksoftmet); + int showorig = lp.showmasksoftmet; + + if (lp.showmasksoftmet >= 5) { + showorig = 0; + } + + ImProcFunctions::retinex_pde(datain, dataout, bfwr, bfhr, 8.f * lp.strng, 1.f, dE, showorig, 1, 1); #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -6988,33 +12293,81 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o delete [] dE; } -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif + transit_shapedetect2(call, 3, bufexporig.get(), bufexpfin.get(), nullptr, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); - for (int y = 0; y < bfh; y++) { - for (int x = 0; x < bfw; x++) { - buflight[y][x] = CLIPRET((bufexpfin->L[y][x] - bufexporig->L[y][x]) / 328.f); - bufl_ab[y][x] = CLIPRET((sqrt(SQR(bufexpfin->a[y][x]) + SQR(bufexpfin->b[y][x])) - sqrt(SQR(bufexporig->a[y][x]) + SQR(bufexporig->b[y][x]))) / 250.f); - } + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); } - - bufexpfin.reset(); - transit_shapedetect(3, bufexporig.get(), nullptr, buflight, bufl_ab, nullptr, nullptr, nullptr, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); } } //local contrast bool wavcurve = false; - if (lp.locmet == 1) { - for (int i = 0; i < 500; i++) { - if (locwavCurve[i] != 0.5) { - wavcurve = true; + + if (locwavCurve && locwavutili) { + if (lp.locmet == 1) { + for (int i = 0; i < 500; i++) { + if (locwavCurve[i] != 0.5) { + wavcurve = true; + } } } } - if ((lp.lcamount > 0.f || wavcurve || params->locallab.spots.at(sp).residcont != 0.f) && call < 3 && lp.lcena) { + + bool wavcurvelev = false; + + if (loclevwavCurve && loclevwavutili) { + if (lp.locmet == 1) { + for (int i = 0; i < 500; i++) { + if (loclevwavCurve[i] != 0.) { + wavcurvelev = true; + } + } + } + } + + bool wavcurvecon = false; + + if (locconwavCurve && locconwavutili) { + if (lp.locmet == 1) { + for (int i = 0; i < 500; i++) { + if (locconwavCurve[i] != 0.5) { + wavcurvecon = true; + } + } + } + } + + bool wavcurvecomp = false; + + if (loccompwavCurve && loccompwavutili) { + if (lp.locmet == 1) { + for (int i = 0; i < 500; i++) { + if (loccompwavCurve[i] != 0.) { + wavcurvecomp = true; + } + } + } + } + + bool wavcurvecompre = false; + + if (loccomprewavCurve && loccomprewavutili) { + if (lp.locmet == 1) { + for (int i = 0; i < 500; i++) { + if (loccomprewavCurve[i] != 0.75) { + wavcurvecompre = true; + } + } + } + } + + + if ((lp.lcamount > 0.f || wavcurve || lp.showmasklcmet == 2 || lp.enalcMask || lp.showmasklcmet == 3 || lp.showmasklcmet == 4 || lp.strwav != 0.f || wavcurvelev || wavcurvecon || wavcurvecomp || wavcurvecompre || lp.edgwena || params->locallab.spots.at(sp).residblur > 0.f || params->locallab.spots.at(sp).levelblur > 0.f || params->locallab.spots.at(sp).residcont != 0.f || params->locallab.spots.at(sp).clarilres != 0.f || params->locallab.spots.at(sp).claricres != 0.f) && call < 3 && lp.lcena) { + int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); @@ -7026,79 +12379,32 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o bool reduH = false; bool reduW = false; - if (lp.ftwlc) { - int ftsizeH = 1; - int ftsizeW = 1; +// if (bfw >= mSP && bfh >= mSP) { + if (bfw >= mSPwav && bfh >= mSPwav) {//avoid too small spot for wavelet - for (int ft = 0; ft < N_fftwsize; ft++) { //find best values - if (fftw_size[ft] <= bfh) { - ftsizeH = fftw_size[ft]; - break; - } + + if (lp.ftwlc) { + optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, reduH, reduW, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy); } - for (int ft = 0; ft < N_fftwsize; ft++) { - if (fftw_size[ft] <= bfw) { - ftsizeW = fftw_size[ft]; - break; - } + std::unique_ptr bufmaskblurlc; + std::unique_ptr originalmasklc; + std::unique_ptr bufmaskoriglc; + + if (lp.showmasklcmet == 2 || lp.enalcMask || lp.showmasklcmet == 3 || lp.showmasklcmet == 4) { + bufmaskblurlc.reset(new LabImage(bfw, bfh)); + originalmasklc.reset(new LabImage(bfw, bfh)); + bufmaskoriglc.reset(new LabImage(bfw, bfh)); } - //printf("FTsizeH =%i FTsizeW=%i \n", ftsizeH, ftsizeW); - //optimize with size fftw - if (ystart == 0 && yend < original->H) { - lp.ly -= (bfh - ftsizeH); - } else if (ystart != 0 && yend == original->H) { - lp.lyT -= (bfh - ftsizeH); - } else if (ystart != 0 && yend != original->H) { - if (lp.ly <= lp.lyT) { - lp.lyT -= (bfh - ftsizeH); - } else { - lp.ly -= (bfh - ftsizeH); - } - } else if (ystart == 0 && yend == original->H) { - bfhr = ftsizeH; - reduH = true; - } - - if (xstart == 0 && xend < original->W) { - lp.lx -= (bfw - ftsizeW); - } else if (xstart != 0 && xend == original->W) { - lp.lxL -= (bfw - ftsizeW); - } else if (xstart != 0 && xend != original->W) { - if (lp.lx <= lp.lxL) { - lp.lxL -= (bfw - ftsizeW); - } else { - lp.lx -= (bfw - ftsizeW); - } - } else if (xstart == 0 && xend == original->W) { - bfwr = ftsizeW; - reduW = true; - } - - //new values optimized - ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); - yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); - xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); - xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); - bfh = bfhr = yend - ystart; - bfw = bfwr = xend - xstart; - - if (reduH) { - bfhr = ftsizeH; - } - - if (reduW) { - bfwr = ftsizeW; - } - } - - if (bfw > 0 && bfh > 0) { array2D buflight(bfw, bfh); JaggedArray bufchro(bfw, bfh); std::unique_ptr bufgb(new LabImage(bfw, bfh)); std::unique_ptr tmp1(new LabImage(bfw, bfh)); + std::unique_ptr tmpresid(new LabImage(bfw, bfh)); + std::unique_ptr tmpres(new LabImage(bfw, bfh)); + #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -7111,237 +12417,383 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o tmp1->L[y - ystart][x - xstart] = original->L[y][x]; tmp1->a[y - ystart][x - xstart] = original->a[y][x]; tmp1->b[y - ystart][x - xstart] = original->b[y][x]; + tmpresid->L[y - ystart][x - xstart] = original->L[y][x]; + tmpresid->a[y - ystart][x - xstart] = original->a[y][x]; + tmpresid->b[y - ystart][x - xstart] = original->b[y][x]; + tmpres->L[y - ystart][x - xstart] = original->L[y][x]; + tmpres->a[y - ystart][x - xstart] = original->a[y][x]; + tmpres->b[y - ystart][x - xstart] = original->b[y][x]; } } - if (lp.locmet == 0) { - LocalContrastParams localContrastParams; - LocallabParams locallabparams; - localContrastParams.enabled = true; - localContrastParams.radius = params->locallab.spots.at(sp).lcradius; - localContrastParams.amount = params->locallab.spots.at(sp).lcamount; - localContrastParams.darkness = params->locallab.spots.at(sp).lcdarkness; - localContrastParams.lightness = params->locallab.spots.at(sp).lightness; - bool fftwlc = false; - - if (!lp.ftwlc) { - ImProcFunctions::localContrast(tmp1.get(), tmp1->L, localContrastParams, fftwlc, sk); - } else { - std::unique_ptr tmpfftw(new LabImage(bfwr, bfhr)); #ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int y = 0; y < bfhr; y++) { - for (int x = 0; x < bfwr; x++) { - tmpfftw->L[y][x] = tmp1->L[y][x]; - tmpfftw->a[y][x] = tmp1->a[y][x]; - tmpfftw->b[y][x] = tmp1->b[y][x]; + for (int y = 0; y < bfh; y++) { + for (int x = 0; x < bfw; x++) { + bufgb->L[y][x] = original->L[y + ystart][x + xstart]; + } + } + + int inv = 0; + bool showmaske = false; + bool enaMask = false; + bool deltaE = false; + bool modmask = false; + bool zero = false; + bool modif = false; + + if (lp.showmasklcmet == 3) { + showmaske = true; + } + + if (lp.enalcMask) { + enaMask = true; + } + + if (lp.showmasklcmet == 4) { + deltaE = true; + } + + if (lp.showmasklcmet == 2) { + modmask = true; + } + + if (lp.showmasklcmet == 1) { + modif = true; + } + + if (lp.showmasklcmet == 0) { + zero = true; + } + + + float chrom = lp.chromalc; + float rad = lp.radmalc; + float blendm = lp.blendmalc; + float gamma = 1.f; + float slope = 0.f; + float lap = 0.f; //params->locallab.spots.at(sp).lapmaskexp; + bool pde = false; //params->locallab.spots.at(sp).laplac; + LocwavCurve dummy; + bool lmasutilicolwav = false; + bool delt = params->locallab.spots.at(sp).deltae; + int sco = params->locallab.spots.at(sp).scopemask; + int shado = 0; + int shortcu = 0;//lp.mergemet; //params->locallab.spots.at(sp).shortc; + const int limscope = 80; + const float mindE = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + float amountcd = 0.f; + float anchorcd = 50.f; + int lumask = params->locallab.spots.at(sp).lumask; + LocHHmaskCurve lochhhmasCurve; + bool lhhmasutili = false; + maskcalccol(call, false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufgb.get(), bufmaskoriglc.get(), originalmasklc.get(), original, reserved, inv, lp, + 0.f, false, + locccmaslcCurve, lcmaslcutili, locllmaslcCurve, llmaslcutili, lochhmaslcCurve, lhmaslcutili, lochhhmasCurve, lhhmasutili, multiThread, + enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, shado, amountcd, anchorcd, lmasklclocalcurve, localmasklcutili, dummy, lmasutilicolwav, 1, 1, 5, 5, + shortcu, delt, hueref, chromaref, lumaref, + maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco + ); + + if (lp.showmasklcmet == 3) { + showmask(lumask, lp, xstart, ystart, cx, cy, bfw, bfh, bufgb.get(), transformed, bufmaskoriglc.get(), 0); + + return; + } + + if (lp.showmasklcmet == 0 || lp.showmasklcmet == 1 || lp.showmasklcmet == 2 || lp.showmasklcmet == 4 || lp.enalcMask) { + + if (lp.locmet == 0) { + LocalContrastParams localContrastParams; + LocallabParams locallabparams; + localContrastParams.enabled = true; + localContrastParams.radius = params->locallab.spots.at(sp).lcradius; + localContrastParams.amount = params->locallab.spots.at(sp).lcamount; + localContrastParams.darkness = params->locallab.spots.at(sp).lcdarkness; + localContrastParams.lightness = params->locallab.spots.at(sp).lightness; + bool fftwlc = false; + + if (!lp.ftwlc) { // || (lp.ftwlc && call != 2)) { + ImProcFunctions::localContrast(tmp1.get(), tmp1->L, localContrastParams, fftwlc, sk); + } else { + std::unique_ptr tmpfftw(new LabImage(bfwr, bfhr)); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfhr; y++) { + for (int x = 0; x < bfwr; x++) { + tmpfftw->L[y][x] = tmp1->L[y][x]; + tmpfftw->a[y][x] = tmp1->a[y][x]; + tmpfftw->b[y][x] = tmp1->b[y][x]; + } } - } - fftwlc = true; - ImProcFunctions::localContrast(tmpfftw.get(), tmpfftw->L, localContrastParams, fftwlc, sk); + fftwlc = true; + ImProcFunctions::localContrast(tmpfftw.get(), tmpfftw->L, localContrastParams, fftwlc, sk); #ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int y = 0; y < bfhr; y++) { - for (int x = 0; x < bfwr; x++) { - tmp1->L[y][x] = tmpfftw->L[y][x]; - tmp1->a[y][x] = tmpfftw->a[y][x]; - tmp1->b[y][x] = tmpfftw->b[y][x]; + for (int y = 0; y < bfhr; y++) { + for (int x = 0; x < bfwr; x++) { + tmp1->L[y][x] = tmpfftw->L[y][x]; + tmp1->a[y][x] = tmpfftw->a[y][x]; + tmp1->b[y][x] = tmpfftw->b[y][x]; + } } + + } + } else if (lp.locmet == 1) { //wavelet && sk ==1 + int wavelet_level = 1 + params->locallab.spots.at(sp).csthreshold.getBottomRight();//retriev with +1 maximum wavelet_level + float mL = (float)(params->locallab.spots.at(sp).clarilres / 100.f); + float mC = (float)(params->locallab.spots.at(sp).claricres / 100.f); + float softr = (float)(params->locallab.spots.at(sp).clarisoft); + float mL0 = 0.f; + float mC0 = 0.f; +#ifdef _OPENMP + const int numThreads = omp_get_max_threads(); +#else + const int numThreads = 1; + +#endif + // adap maximum level wavelet to size of RT-spot + int minwin = min(bfw, bfh); + int maxlevelspot = 10;//maximum possible + + // adap maximum level wavelet to size of crop + while ((1 << maxlevelspot) >= (minwin * sk) && maxlevelspot > 1) { + --maxlevelspot ; } - } - } else if (lp.locmet == 1) { //wavelet - - int wavelet_level = params->locallab.spots.at(sp).levelwav; + // printf("minwin=%i maxlevelavant=%i maxlespot=%i\n", minwin, wavelet_level, maxlevelspot); - int minwin = min(bfwr, bfhr); - int maxlevelspot = 9; - // adap maximum level wavelet to size of RT-spot - if (minwin * sk < 1024) { - maxlevelspot = 9; //sampling wavelet 512 - } + wavelet_level = min(wavelet_level, maxlevelspot); + // printf("maxlevel=%i\n", wavelet_level); + bool exec = false; + bool origlc = params->locallab.spots.at(sp).origlc; - if (minwin * sk < 512) { - maxlevelspot = 8; //sampling wavelet 256 - } + if (origlc) {//merge only with original + clarimerge(lp, mL, mC, exec, tmpresid.get(), wavelet_level, sk, numThreads); + } - if (minwin * sk < 256) { - maxlevelspot = 7; //sampling 128 - } + int maxlvl = wavelet_level; + const float contrast = params->locallab.spots.at(sp).residcont; + int level_bl = params->locallab.spots.at(sp).csthreshold.getBottomLeft(); + int level_hl = params->locallab.spots.at(sp).csthreshold.getTopLeft(); + int level_br = params->locallab.spots.at(sp).csthreshold.getBottomRight(); + int level_hr = params->locallab.spots.at(sp).csthreshold.getTopRight(); + const float radblur = (params->locallab.spots.at(sp).residblur) / sk; + const bool blurlc = params->locallab.spots.at(sp).blurlc; + const float radlevblur = (params->locallab.spots.at(sp).levelblur) / sk; + const float sigma = params->locallab.spots.at(sp).sigma; + const float offs = params->locallab.spots.at(sp).offset; + const float fatdet = params->locallab.spots.at(sp).fatdet; + const float fatanch = params->locallab.spots.at(sp).fatanch; + const float fatres = params->locallab.spots.at(sp).fatres; + const float chrol = params->locallab.spots.at(sp).chromalev; + const float chrobl = params->locallab.spots.at(sp).chromablu; + const bool blurena = params->locallab.spots.at(sp).wavblur; + const bool levelena = params->locallab.spots.at(sp).wavcont; + const bool comprena = params->locallab.spots.at(sp).wavcomp; + const bool compreena = params->locallab.spots.at(sp).wavcompre; + const float compress = params->locallab.spots.at(sp).residcomp; + const float thres = params->locallab.spots.at(sp).threswav; - if (minwin * sk < 128) { - maxlevelspot = 6; - } + wavcontrast4(lp, tmp1->L, tmp1->a, tmp1->b, contrast, fatres, radblur, radlevblur, tmp1->W, tmp1->H, level_bl, level_hl, level_br, level_hr, sk, numThreads, locwavCurve, locwavutili, wavcurve, loclevwavCurve, loclevwavutili, wavcurvelev, locconwavCurve, locconwavutili, wavcurvecon, loccompwavCurve, loccompwavutili, wavcurvecomp, loccomprewavCurve, loccomprewavutili, wavcurvecompre, locedgwavCurve, locedgwavutili, sigma, offs, maxlvl, fatdet, fatanch, chrol, chrobl, blurlc, blurena, levelena, comprena, compreena, compress, thres); - if (minwin * sk < 64) { - maxlevelspot = 5; - } + const float satur = params->locallab.spots.at(sp).residchro; - if (minwin * sk < 32) { - maxlevelspot = 4; - } - if (minwin * sk < 16) { - maxlevelspot = 3; - } + if (satur != 0.f || radblur > 0.f) {//blur residual a and satur - if (minwin * sk < 8) { - maxlevelspot = 2; - } + wavelet_decomposition *wdspota = new wavelet_decomposition(tmp1->a[0], tmp1->W, tmp1->H, wavelet_level, 1, sk, numThreads, lp.daubLen); - if (minwin * sk < 4) { - maxlevelspot = 1; - } + if (wdspota->memoryAllocationFailed) { + return; + } - if (minwin * sk < 2) { - maxlevelspot = 0; - } - - wavelet_level = min(wavelet_level, maxlevelspot); - - wavelet_decomposition wdspot(tmp1->data, bfw, bfh, wavelet_level, 1, sk); - if (wdspot.memoryAllocationFailed) { - return; - } - - const float contrast = params->locallab.spots.at(sp).residcont; - int maxlvl = wdspot.maxlevel(); - - if (contrast != 0) { - int W_L = wdspot.level_W(0); - int H_L = wdspot.level_H(0); - float *wav_L0 = wdspot.coeff0; - - double avedbl = 0.0; // use double precision for large summations + float *wav_ab0a = wdspota->coeff0; + // int maxlvla = wdspota->maxlevel(); + int W_La = wdspota->level_W(0); + int H_La = wdspota->level_H(0); + if (radblur > 0.f && !blurlc && blurena) { + array2D bufa(W_La, H_La); #ifdef _OPENMP - #pragma omp parallel for reduction(+:avedbl) if (multiThread) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int i = 0; i < W_L * H_L; i++) { - avedbl += wav_L0[i]; - } + for (int y = 0; y < H_La; y++) { + for (int x = 0; x < W_La; x++) { + bufa[y][x] = wav_ab0a [y * W_La + x]; + } + } - float ave = avedbl / double(W_L * H_L); + #pragma omp parallel + { + gaussianBlur(bufa, bufa, W_La, H_La, radblur); + } - float avg = ave / 32768.f; - avg = LIM01(avg); - double contreal = 0.6 * contrast; - DiagonalCurve resid_contrast({ - DCT_NURBS, - 0, 0, - avg - avg * (0.6 - contreal / 250.0), avg - avg * (0.6 + contreal / 250.0), - avg + (1. - avg) * (0.6 - contreal / 250.0), avg + (1. - avg) * (0.6 + contreal / 250.0), - 1, 1 - }); #ifdef _OPENMP - #pragma omp parallel for if (multiThread) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int i = 0; i < W_L * H_L; i++) { - float buf = LIM01(wav_L0[i] / 32768.f); - buf = resid_contrast.getVal(buf); - buf *= 32768.f; - wav_L0[i] = buf; - } - - } + + for (int y = 0; y < H_La; y++) { + for (int x = 0; x < W_La; x++) { + wav_ab0a[y * W_La + x] = bufa[y][x]; + } + } + + } + + if (satur != 0.f) { +#ifdef _OPENMP + #pragma omp parallel for if (multiThread) +#endif + + for (int i = 0; i < W_La * H_La; i++) { + wav_ab0a[i] *= (1.f + sin(rtengine::RT_PI * (satur / 200.f)));//more progressive than linear + wav_ab0a[i] = CLIPC(wav_ab0a[i]); + } + } + + wdspota->reconstruct(tmp1->a[0], 1.f); + delete wdspota; + + wavelet_decomposition *wdspotb = new wavelet_decomposition(tmp1->b[0], tmp1->W, tmp1->H, wavelet_level, 1, sk, numThreads, lp.daubLen); + + if (wdspotb->memoryAllocationFailed) { + return; + } + + float *wav_ab0b = wdspotb->coeff0; + // int maxlvlb = wdspotb->maxlevel(); + int W_Lb = wdspotb->level_W(0); + int H_Lb = wdspotb->level_H(0); + + if (radblur > 0.f && !blurlc && blurena) { + array2D bufb(W_Lb, H_Lb); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < H_Lb; y++) { + for (int x = 0; x < W_Lb; x++) { + bufb[y][x] = wav_ab0b [y * W_Lb + x]; + } + } + + #pragma omp parallel + { + gaussianBlur(bufb, bufb, W_Lb, H_Lb, radblur); + } - float mean[10]; - float meanN[10]; - float sigma[10]; - float sigmaN[10]; - float MaxP[10]; - float MaxN[10]; - Evaluate2(wdspot, mean, meanN, sigma, sigmaN, MaxP, MaxN); - // printf("mean=%f sig=%f\n", mean[3], sigma[3]); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif - for (int dir = 1; dir < 4; dir++) { - for (int level = 0; level < maxlvl; ++level) { - int W_L = wdspot.level_W(level); - int H_L = wdspot.level_H(level); - float **wav_L = wdspot.level_coeffs(level); + for (int y = 0; y < H_Lb; y++) { + for (int x = 0; x < W_Lb; x++) { + wav_ab0b[y * W_Lb + x] = bufb[y][x]; + } + } - if (MaxP[level] > 0.f && mean[level] != 0.f && sigma[level] != 0.f) { - float insigma = 0.666f; //SD - float logmax = log(MaxP[level]); //log Max - float rapX = (mean[level] + sigma[level]) / MaxP[level]; //rapport between sD / max - float inx = log(insigma); - float iny = log(rapX); - float rap = inx / iny; //koef - float asig = 0.166f / sigma[level]; - float bsig = 0.5f - asig * mean[level]; - float amean = 0.5f / mean[level]; + } + + if (satur != 0.f) { #ifdef _OPENMP #pragma omp parallel for if (multiThread) #endif - for (int i = 0; i < W_L * H_L; i++) { - float absciss; - float &val = wav_L[dir][i]; - if (fabsf(val) >= (mean[level] + sigma[level])) { //for max - float valcour = xlogf(fabsf(val)); - float valc = valcour - logmax; - float vald = valc * rap; - absciss = xexpf(vald); - } else if (fabsf(val) >= mean[level]) { - absciss = asig * fabsf(val) + bsig; - } else { - absciss = amean * fabsf(val); - } - - float kc = locwavCurve[absciss * 500.f] - 0.5f; - float reduceeffect = kc <= 0.f ? 1.f : 1.5f; - - float kinterm = 1.f + reduceeffect * kc; - kinterm = kinterm <= 0.f ? 0.01f : kinterm; - - val *= kinterm; + for (int i = 0; i < W_Lb * H_Lb; i++) { + wav_ab0b[i] *= (1.f + sin(rtengine::RT_PI * (satur / 200.f))); + wav_ab0b[i] = CLIPC(wav_ab0b[i]); } } + + wdspotb->reconstruct(tmp1->b[0], 1.f); + delete wdspotb; + + } + + if (!origlc) {//merge all files + exec = false; +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + +//copy previous calculation in merge possibilities + for (int y = 0; y < bfhr; y++) { + for (int x = 0; x < bfwr; x++) { + tmpresid->L[y][x] = tmp1->L[y][x]; + tmpresid->a[y][x] = tmp1->a[y][x]; + tmpresid->b[y][x] = tmp1->b[y][x]; + } + } + + clarimerge(lp, mL, mC, exec, tmpresid.get(), wavelet_level, sk, numThreads); + } + + float thr = 0.001f; + int flag = 0; + + if (maxlvl <= 4) { + mL0 = 0.f; + mC0 = 0.f; + mL = -1.5f * mL;//increase only for sharpen + mC = -mC; + thr = 1.f; + flag = 0; + + } else if (maxlvl > 4) { + mL0 = mL; + mC0 = mC; + thr = 1.f; + flag = 1; + } else { + mL0 = mL = mC0 = mC = 0.f; + } + + if (exec || compreena) { + bool origl = false; + // origlc = false; + LabImage *mergfile = origl ? tmpres.get() : tmp1.get(); + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int x = 0; x < bfh; x++) + for (int y = 0; y < bfw; y++) { + tmp1->L[x][y] = CLIPLOC((1.f + mL0) * mergfile->L[x][y] - mL * tmpresid->L[x][y]); + tmp1->a[x][y] = CLIPC((1.f + mC0) * mergfile->a[x][y] - mC * tmpresid->a[x][y]); + tmp1->b[x][y] = CLIPC((1.f + mC0) * mergfile->b[x][y] - mC * tmpresid->b[x][y]); + } + + if (softr > 0.f && (compreena || fabs(mL) > 0.001f)) { + softproc(tmpres.get(), tmp1.get(), softr, bfh, bfw, 0.0001, 0.00001, thr, sk, multiThread, flag); + } } } - wdspot.reconstruct(tmp1->data, 1.f); - + transit_shapedetect2(call, 10, bufgb.get(), tmp1.get(), originalmasklc.get(), hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); + tmp1.reset(); } - float minL = tmp1->L[0][0] - bufgb->L[0][0]; - float maxL = minL; -#ifdef _OPENMP - #pragma omp parallel for reduction(max:maxL) reduction(min:minL) schedule(dynamic,16) -#endif - - for (int ir = 0; ir < bfhr; ir++) { - for (int jr = 0; jr < bfwr; jr++) { - buflight[ir][jr] = tmp1->L[ir][jr] - bufgb->L[ir][jr]; - bufchro[ir][jr] = sqrt(SQR(tmp1->a[ir][jr]) + SQR(tmp1->b[ir][jr])) - sqrt(SQR(bufgb->a[ir][jr]) + SQR(bufgb->b[ir][jr])); - minL = rtengine::min(minL, buflight[ir][jr]); - maxL = rtengine::max(maxL, buflight[ir][jr]); - } + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); } - - float coef = 0.01f * (max(fabs(minL), fabs(maxL))); -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < bfhr; y++) { - for (int x = 0; x < bfwr; x++) { - buflight[y][x] /= coef; - } - } - - bufgb.reset(); - transit_shapedetect(10, tmp1.get(), nullptr, buflight, bufchro, nullptr, nullptr, nullptr, false, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); - tmp1.reset(); } } @@ -7351,6 +12803,13 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o JaggedArray loctemp(bfw, bfh); if (call == 2) { //call from simpleprocess + printf("bfw=%i bfh=%i\n", bfw, bfh); + + if (bfw < mSPsharp || bfh < mSPsharp) { + printf("too small RT-spot - minimum size 39 * 39\n"); + return; + } + JaggedArray bufsh(bfw, bfh, true); JaggedArray hbuffer(bfw, bfh); int begy = lp.yc - lp.lyT; @@ -7382,6 +12841,12 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o //sharpen ellipse and transition Sharp_Local(call, loctemp, 0, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } + } else if (lp.invshar && lp.shrad > 0.42 && call < 3 && lp.sharpena && sk == 1) { int GW = original->W; int GH = original->H; @@ -7391,321 +12856,180 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o InverseSharp_Local(loctemp, hueref, lumaref, chromaref, lp, original, transformed, cx, cy, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } } // } //&& lp.retiena - if (lp.str > 0.f && lp.retiena) { + + if (lp.dehaze != 0 && lp.retiena) { + int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); + int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); + int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); + int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); + int bfh = yend - ystart; + int bfw = xend - xstart; + + if (bfh >= mSP && bfw >= mSP) { + std::unique_ptr bufexporig(new LabImage(bfw, bfh)); //buffer for data in zone limit + std::unique_ptr bufexpfin(new LabImage(bfw, bfh)); //buffer for data in zone limit + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = ystart; y < yend; y++) { + for (int x = xstart; x < xend; x++) { + bufexporig->L[y - ystart][x - xstart] = original->L[y][x]; + bufexporig->a[y - ystart][x - xstart] = original->a[y][x]; + bufexporig->b[y - ystart][x - xstart] = original->b[y][x]; + } + } + + bufexpfin->CopyFrom(bufexporig.get()); + //calc dehaze + Imagefloat *tmpImage = nullptr; + + if (lp.dehaze != 0) { + DehazeParams dehazeParams; + dehazeParams.enabled = true; + dehazeParams.strength = lp.dehaze; + dehazeParams.showDepthMap = false; + dehazeParams.depth = lp.depth; + dehazeParams.luminance = params->locallab.spots.at(sp).lumonly; + tmpImage = new Imagefloat(bfw, bfh); + lab2rgb(*bufexpfin, *tmpImage, params->icm.workingProfile); + dehazeloc(tmpImage, dehazeParams); + rgb2lab(*tmpImage, *bufexpfin, params->icm.workingProfile); + + delete tmpImage; + } + + transit_shapedetect2(call, 30, bufexporig.get(), bufexpfin.get(), nullptr, hueref, chromaref, lumaref, sobelref, 0.f, nullptr, lp, original, transformed, cx, cy, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } + } + } + + lp.invret = false;//always disabled inverse RETI too complex todo !! + + if (lp.str >= 0.2f && lp.retiena && call != 2) { int GW = transformed->W; int GH = transformed->H; - LabImage *bufreti = nullptr; LabImage *bufmask = nullptr; LabImage *buforig = nullptr; LabImage *buforigmas = nullptr; - int bfh = int (lp.ly + lp.lyT) + del; //bfw bfh real size of square zone - int bfw = int (lp.lx + lp.lxL) + del; - // printf("before bfh=%i bfw=%i\n", bfh, bfw); - if (lp.ftwreti) { - int ftsizeH = 1; - int ftsizeW = 1; + if (GW >= mSP && GH >= mSP) - for (int ft = 0; ft < N_fftwsize; ft++) { //find best values for FFTW - if (fftw_size[ft] <= bfh) { - ftsizeH = fftw_size[ft]; - break; + { + + array2D buflight(GW, GH); + JaggedArray bufchro(GW, GH); + + int Hd, Wd; + Hd = GH; + Wd = GW; + + if (!lp.invret && call != 2) { + + Hd = GH; + Wd = GW; + bufreti = new LabImage(GW, GH); + bufmask = new LabImage(GW, GH); + + if (!lp.enaretiMasktmap && lp.enaretiMask) { + buforig = new LabImage(GW, GH); + buforigmas = new LabImage(GW, GH); } - } - - for (int ft = 0; ft < N_fftwsize; ft++) { - if (fftw_size[ft] <= bfw) { - ftsizeW = fftw_size[ft]; - break; - } - } - - int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); - int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); - int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); - int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); - - if (ystart == 0 && yend < original->H) { - lp.ly -= (bfh - ftsizeH); - } else if (ystart != 0 && yend == original->H) { - lp.lyT -= (bfh - ftsizeH); - } else if (ystart != 0 && yend != original->H) { - if (lp.ly <= lp.lyT) { - lp.lyT -= (bfh - ftsizeH); - } else { - lp.ly -= (bfh - ftsizeH); - } - } - - if (xstart == 0 && xend < original->W) { - lp.lx -= (bfw - ftsizeW); - } else if (xstart != 0 && xend == original->W) { - lp.lxL -= (bfw - ftsizeW); - } else if (xstart != 0 && xend != original->W) { - if (lp.lx <= lp.lxL) { - lp.lxL -= (bfw - ftsizeW); - } else { - lp.lx -= (bfw - ftsizeW); - } - } - - //new size bfw, bfh not optimized if spot H > high or spot W > width ==> TODO - bfh = int (lp.ly + lp.lyT) + del; - bfw = int (lp.lx + lp.lxL) + del; - //printf("after bfh=%i bfw=%i fftwH=%i fftww=%i\n", bfh, bfw, ftsizeH, ftsizeW); - - } - - array2D buflight(bfw, bfh); - JaggedArray bufchro(bfw, bfh); - - int Hd, Wd; - Hd = GH; - Wd = GW; - - if (!lp.invret && call <= 3) { - - Hd = bfh; - Wd = bfw; - bufreti = new LabImage(bfw, bfh); - bufmask = new LabImage(bfw, bfh); - - if (!lp.enaretiMasktmap && lp.enaretiMask) { - buforig = new LabImage(bfw, bfh); - buforigmas = new LabImage(bfw, bfh); - } #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel for #endif - for (int ir = 0; ir < bfh; ir++) //fill with 0 - for (int jr = 0; jr < bfw; jr++) { - bufreti->L[ir][jr] = 0.f; - bufreti->a[ir][jr] = 0.f; - bufreti->b[ir][jr] = 0.f; - buflight[ir][jr] = 0.f; - bufchro[ir][jr] = 0.f; - } - - int begy = lp.yc - lp.lyT; - int begx = lp.xc - lp.lxL; - int yEn = lp.yc + lp.ly; - int xEn = lp.xc + lp.lx; + for (int ir = 0; ir < GH; ir++) //fill with 0 + for (int jr = 0; jr < GW; jr++) { + bufreti->L[ir][jr] = 0.f; + bufreti->a[ir][jr] = 0.f; + bufreti->b[ir][jr] = 0.f; + buflight[ir][jr] = 0.f; + bufchro[ir][jr] = 0.f; + } #ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int y = 0; y < transformed->H ; y++) //{ - for (int x = 0; x < transformed->W; x++) { - int lox = cx + x; - int loy = cy + y; - - if (lox >= begx && lox < xEn && loy >= begy && loy < yEn) { - bufreti->L[loy - begy][lox - begx] = original->L[y][x]; - bufreti->a[loy - begy][lox - begx] = original->a[y][x]; - bufreti->b[loy - begy][lox - begx] = original->b[y][x]; - bufmask->L[loy - begy][lox - begx] = original->L[y][x]; - bufmask->a[loy - begy][lox - begx] = original->a[y][x]; - bufmask->b[loy - begy][lox - begx] = original->b[y][x]; + for (int y = 0; y < transformed->H ; y++) //{ + for (int x = 0; x < transformed->W; x++) { + bufreti->L[y][x] = original->L[y][x]; + bufreti->a[y][x] = original->a[y][x]; + bufreti->b[y][x] = original->b[y][x]; + bufmask->L[y][x] = original->L[y][x]; + bufmask->a[y][x] = original->a[y][x]; + bufmask->b[y][x] = original->b[y][x]; if (!lp.enaretiMasktmap && lp.enaretiMask) { - buforig->L[loy - begy][lox - begx] = original->L[y][x]; - buforig->a[loy - begy][lox - begx] = original->a[y][x]; - buforig->b[loy - begy][lox - begx] = original->b[y][x]; + buforig->L[y][x] = original->L[y][x]; + buforig->a[y][x] = original->a[y][x]; + buforig->b[y][x] = original->b[y][x]; } + } - } - - //calc dehaze - Imagefloat *tmpImage = nullptr; - - if (lp.dehaze > 0) { - const float depthcombi = 0.3f * params->locallab.spots.at(sp).neigh + 0.15f * (500.f - params->locallab.spots.at(sp).vart); - DehazeParams dehazeParams; - dehazeParams.enabled = true; - dehazeParams.strength = 0.9f * lp.dehaze + 0.3f * lp.str; - dehazeParams.showDepthMap = false; - dehazeParams.depth = LIM(depthcombi, 0.f, 100.f); - - tmpImage = new Imagefloat(bfw, bfh); - lab2rgb(*bufreti, *tmpImage, params->icm.workingProfile); - dehaze(tmpImage, dehazeParams); - rgb2lab(*tmpImage, *bufreti, params->icm.workingProfile); - - delete tmpImage; } - } - float *orig[Hd] ALIGNED16; - float *origBuffer = new float[Hd * Wd]; + float raddE = params->locallab.spots.at(sp).softradiusret; - for (int i = 0; i < Hd; i++) { - orig[i] = &origBuffer[i * Wd]; - } - - float *orig1[Hd] ALIGNED16; - float *origBuffer1 = new float[Hd * Wd]; - - for (int i = 0; i < Hd; i++) { - orig1[i] = &origBuffer1[i * Wd]; - } - - - - LabImage *tmpl = nullptr; - - if (!lp.invret && call <= 3) { + //calc dE and reduction to use in MSR to reduce artifacts + const int limscope = 80; + const float mindE = 4.f + MINSCOPE * lp.sensh * lp.thr; + const float maxdE = 5.f + MAXSCOPE * lp.sensh * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + const float refa = chromaref * cos(hueref); + const float refb = chromaref * sin(hueref); + std::unique_ptr> reducDEBuffer(new JaggedArray(Wd, Hd)); + float** reducDE = *(reducDEBuffer.get()); + float ade = 0.01f * raddE; + float bde = 100.f - raddE; + float sensibefore = ade * lp.sensh + bde;//we can change sensitivity 0.1 90 or 0.3 70 or 0.4 60 #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif - for (int ir = 0; ir < Hd; ir += 1) - for (int jr = 0; jr < Wd; jr += 1) { - orig[ir][jr] = bufreti->L[ir][jr]; - orig1[ir][jr] = bufreti->L[ir][jr]; + for (int y = 0; y < transformed->H ; y++) + for (int x = 0; x < transformed->W; x++) { + float dE = sqrt(SQR(refa - bufreti->a[y][x] / 327.68f) + SQR(refb - bufreti->b[y][x] / 327.68f) + SQR(lumaref - bufreti->b[y][x] / 327.68f)); + float reducdE; + calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sensibefore, reducdE); + reducDE[y][x] = CLIPdE(reducdE); + } - tmpl = new LabImage(Wd, Hd); + std::unique_ptr> origBuffer(new JaggedArray(Wd, Hd)); + float** orig = *(origBuffer.get()); - } else { - - Imagefloat *tmpImage = nullptr; - bufreti = new LabImage(Wd, Hd); - - if (lp.dehaze > 0) { - const float depthcombi = 0.3f * params->locallab.spots.at(sp).neigh + 0.15f * (500.f - params->locallab.spots.at(sp).vart); - DehazeParams dehazeParams; - dehazeParams.enabled = true; - dehazeParams.strength = 0.9f * lp.dehaze + 0.3f * lp.str; - dehazeParams.showDepthMap = false; - dehazeParams.depth = LIM(depthcombi, 0.f, 100.f); - - tmpImage = new Imagefloat(Wd, Hd); - lab2rgb(*original, *tmpImage, params->icm.workingProfile); - dehaze(tmpImage, dehazeParams); - rgb2lab(*tmpImage, *bufreti, params->icm.workingProfile); - - delete tmpImage; -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < Hd; ir += 1) { - for (int jr = 0; jr < Wd; jr += 1) { - orig[ir][jr] = original->L[ir][jr]; - orig1[ir][jr] = bufreti->L[ir][jr]; - } - } - - delete bufreti; - bufreti = nullptr; - } else { - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < Hd; ir += 1) { - for (int jr = 0; jr < Wd; jr += 1) { - orig[ir][jr] = original->L[ir][jr]; - orig1[ir][jr] = transformed->L[ir][jr]; - } - } - } - - tmpl = new LabImage(transformed->W, transformed->H); - } - - float minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax; - bool fftw = lp.ftwreti; - ImProcFunctions::MSRLocal(sp, fftw, 1, bufreti, bufmask, buforig, buforigmas, orig, tmpl->L, orig1, Wd, Hd, params->locallab, sk, locRETgainCcurve, 0, 4, 1.f, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax, - locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, llretiMask, transformed, lp.enaretiMasktmap, lp.enaretiMask); + std::unique_ptr> origBuffer1(new JaggedArray(Wd, Hd)); + float** orig1 = *(origBuffer1.get()); -#ifdef _OPENMP - #pragma omp parallel for -#endif - for (int ir = 0; ir < Hd; ir += 1) - for (int jr = 0; jr < Wd; jr += 1) { - tmpl->L[ir][jr] = orig[ir][jr]; - } + LabImage *tmpl = nullptr; - if (lp.equret) { //equilibrate luminance before / after MSR - float *datain = new float[Hd * Wd]; - float *data = new float[Hd * Wd]; -#ifdef _OPENMP - #pragma omp parallel for -#endif + if (!lp.invret && call != 2) { - for (int ir = 0; ir < Hd; ir += 1) - for (int jr = 0; jr < Wd; jr += 1) { - datain[ir * Wd + jr] = orig1[ir][jr]; - data[ir * Wd + jr] = orig[ir][jr]; - } - - normalize_mean_dt(data, datain, Hd * Wd, 1.f); -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int ir = 0; ir < Hd; ir += 1) - for (int jr = 0; jr < Wd; jr += 1) { - tmpl->L[ir][jr] = data[ir * Wd + jr]; - } - - delete [] datain; - delete [] data; - } - - if (!lp.invret) { - float minL = tmpl->L[0][0] - bufreti->L[0][0]; - float maxL = minL; -#ifdef _OPENMP - #pragma omp parallel for reduction(min:minL) reduction(max:maxL) schedule(dynamic,16) -#endif - - for (int ir = 0; ir < Hd; ir++) { - for (int jr = 0; jr < Wd; jr++) { - buflight[ir][jr] = tmpl->L[ir][jr] - bufreti->L[ir][jr]; - minL = rtengine::min(minL, buflight[ir][jr]); - maxL = rtengine::max(maxL, buflight[ir][jr]); - } - } - - float coef = 0.01f * (max(fabs(minL), fabs(maxL))); - - - for (int ir = 0; ir < Hd; ir++) { - for (int jr = 0; jr < Wd; jr++) { - buflight[ir][jr] /= coef; - } - } - - /* - if (lp.softradiusret > 0.f && lp.scalereti != 1) { - // softprocess(bufreti, buflight, lp.softradiusret, Hd, Wd, sk, 0.01, 0.001, 0.0001f, multiThread); - //softproc(bufreti, tmpl, lp.softradiusret, bfh, bfw, 0.0001, 0.00001, 0.0001f, sk, multiThread); - } - */ - transit_shapedetect_retinex(4, bufreti, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); - - } else { - InverseReti_Local(lp, hueref, chromaref, lumaref, original, transformed, tmpl, cx, cy, 0, sk); - } - - if (params->locallab.spots.at(sp).chrrt > 0) { - - if (!lp.invret && call <= 3) { #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) @@ -7713,104 +13037,372 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o for (int ir = 0; ir < Hd; ir += 1) for (int jr = 0; jr < Wd; jr += 1) { - - orig[ir][jr] = sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr])); - orig1[ir][jr] = sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr])); + orig[ir][jr] = bufreti->L[ir][jr]; + orig1[ir][jr] = bufreti->L[ir][jr]; } + tmpl = new LabImage(Wd, Hd); + } else { - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < GH; ir += 1) - for (int jr = 0; jr < GW; jr += 1) { - orig[ir][jr] = sqrt(SQR(original->a[ir][jr]) + SQR(original->b[ir][jr])); - orig1[ir][jr] = sqrt(SQR(transformed->a[ir][jr]) + SQR(transformed->b[ir][jr])); - } + // } - float maxChro = orig1[0][0]; + // float minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax; + bool fftw = lp.ftwreti; + //fftw = false; + //for Retinex Mask are incorporated in MSR + bool delt = params->locallab.spots.at(sp).deltae; + int sco = params->locallab.spots.at(sp).scopemask; + float lumask = params->locallab.spots.at(sp).lumask; + + const int limscope2 = 80; + const float mindE2 = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE2 = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim2 = 2.f + MINSCOPE * limscope2 * lp.thr; + const float maxdElim2 = 5.f + MAXSCOPE * limscope2 * (1 + 0.1f * lp.thr); + ImProcFunctions::MSRLocal(call, sp, fftw, 1, reducDE, bufreti, bufmask, buforig, buforigmas, orig, tmpl->L, orig1, + Wd, Hd, Wd, Hd, params->locallab, sk, locRETgainCcurve, locRETtransCcurve, 0, 4, 1.f, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax, + locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, llretiMask, + lmaskretilocalcurve, localmaskretiutili, + transformed, lp.enaretiMasktmap, lp.enaretiMask, + delt, hueref, chromaref, lumaref, + maxdE2, mindE2, maxdElim2, mindElim2, lp.iterat, limscope2, sco, lp.balance, lp.balanceh, lumask); #ifdef _OPENMP - #pragma omp parallel for reduction(max:maxChro) schedule(dynamic,16) + #pragma omp parallel for #endif - for (int ir = 0; ir < Hd; ir++) { - for (int jr = 0; jr < Wd; jr++) { - maxChro = rtengine::max(maxChro, orig1[ir][jr]); + for (int ir = 0; ir < Hd; ir += 1) + for (int jr = 0; jr < Wd; jr += 1) { + tmpl->L[ir][jr] = orig[ir][jr]; } - } - - float divchro = maxChro; - - //first step change saturation whithout Retinex ==> gain of time and memory - float satreal = lp.str * params->locallab.spots.at(sp).chrrt / 100.f; - - if (params->locallab.spots.at(sp).chrrt <= 0.2f) { - satreal /= 10.f; - } - - DiagonalCurve reti_satur({ - DCT_NURBS, - 0, 0, - 0.2, 0.2 + satreal / 250.0, - 0.6, min(1.0, 0.6 + satreal / 250.0), - 1, 1 - }); - bool fftw = false; - - if (params->locallab.spots.at(sp).chrrt > 40.f) { //second step active Retinex Chroma - ImProcFunctions::MSRLocal(sp, fftw, 0, bufreti, bufmask, buforig, buforigmas, orig, tmpl->L, orig1, Wd, Hd, params->locallab, sk, locRETgainCcurve, 1, 4, 0.8f, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax, - locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, llretiMask, transformed, lp.enaretiMasktmap, lp.enaretiMask); - } - - if (!lp.invret && call <= 3) { + if (lp.equret) { //equilibrate luminance before / after MSR + float *datain = new float[Hd * Wd]; + float *data = new float[Hd * Wd]; #ifdef _OPENMP #pragma omp parallel for #endif for (int ir = 0; ir < Hd; ir += 1) for (int jr = 0; jr < Wd; jr += 1) { - const float Chprov = orig1[ir][jr]; - float2 sincosval; - sincosval.y = Chprov == 0.0f ? 1.f : bufreti->a[ir][jr] / Chprov; - sincosval.x = Chprov == 0.0f ? 0.f : bufreti->b[ir][jr] / Chprov; - - if (params->locallab.spots.at(sp).chrrt <= 40.f) { //first step - float buf = LIM01(orig[ir][jr] / divchro); - buf = reti_satur.getVal(buf); - buf *= divchro; - orig[ir][jr] = buf; - } - - tmpl->a[ir][jr] = orig[ir][jr] * sincosval.y; - tmpl->b[ir][jr] = orig[ir][jr] * sincosval.x; + datain[ir * Wd + jr] = orig1[ir][jr]; + data[ir * Wd + jr] = orig[ir][jr]; } - float minC = sqrt(SQR(tmpl->a[0][0]) + SQR(tmpl->b[0][0])) - orig1[0][0]; - float maxC = minC; + normalize_mean_dt(data, datain, Hd * Wd, 1.f, 1.f); #ifdef _OPENMP - #pragma omp parallel for reduction(min:minC) reduction(max:maxC) schedule(dynamic,16) + #pragma omp parallel for +#endif + + for (int ir = 0; ir < Hd; ir += 1) + for (int jr = 0; jr < Wd; jr += 1) { + tmpl->L[ir][jr] = data[ir * Wd + jr]; + } + + delete [] datain; + delete [] data; + } + + + if (!lp.invret) { + float minL = tmpl->L[0][0] - bufreti->L[0][0]; + float maxL = minL; +#ifdef _OPENMP + #pragma omp parallel for reduction(min:minL) reduction(max:maxL) schedule(dynamic,16) #endif for (int ir = 0; ir < Hd; ir++) { for (int jr = 0; jr < Wd; jr++) { - bufchro[ir][jr] = sqrt(SQR(tmpl->a[ir][jr]) + SQR(tmpl->b[ir][jr])) - orig1[ir][jr]; - minC = rtengine::min(minC, bufchro[ir][jr]); - maxC = rtengine::max(maxC, bufchro[ir][jr]); + buflight[ir][jr] = tmpl->L[ir][jr] - bufreti->L[ir][jr]; + minL = rtengine::min(minL, buflight[ir][jr]); + maxL = rtengine::max(maxL, buflight[ir][jr]); } } - const float coefC = 0.01f * (max(fabs(minC), fabs(maxC))); + float coef = 0.01f * (max(fabs(minL), fabs(maxL))); + for (int ir = 0; ir < Hd; ir++) { for (int jr = 0; jr < Wd; jr++) { - bufchro[ir][jr] /= coefC; + buflight[ir][jr] /= coef; } } + + transit_shapedetect_retinex(call, 4, bufreti, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } + } else { + // + } + + + if (params->locallab.spots.at(sp).chrrt > 0) { + + if (!lp.invret && call == 1) { + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < Hd; ir += 1) + for (int jr = 0; jr < Wd; jr += 1) { + + orig[ir][jr] = sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr])); + orig1[ir][jr] = sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr])); + } + + } else { + + } + + float maxChro = orig1[0][0]; +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxChro) schedule(dynamic,16) +#endif + + for (int ir = 0; ir < Hd; ir++) { + for (int jr = 0; jr < Wd; jr++) { + maxChro = rtengine::max(maxChro, orig1[ir][jr]); + } + } + + float divchro = maxChro; + + //first step change saturation whithout Retinex ==> gain of time and memory + float satreal = lp.str * params->locallab.spots.at(sp).chrrt / 100.f; + + if (params->locallab.spots.at(sp).chrrt <= 0.2f) { + satreal /= 10.f; + } + + DiagonalCurve reti_satur({ + DCT_NURBS, + 0, 0, + 0.2, 0.2 + satreal / 250.0, + 0.6, min(1.0, 0.6 + satreal / 250.0), + 1, 1 + }); + + if (!lp.invret && call == 1) { + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ir = 0; ir < Hd; ir += 1) + for (int jr = 0; jr < Wd; jr += 1) { + const float Chprov = orig1[ir][jr]; + float2 sincosval; + sincosval.y = Chprov == 0.0f ? 1.f : bufreti->a[ir][jr] / Chprov; + sincosval.x = Chprov == 0.0f ? 0.f : bufreti->b[ir][jr] / Chprov; + + if (params->locallab.spots.at(sp).chrrt <= 100.f) { //first step + float buf = LIM01(orig[ir][jr] / divchro); + buf = reti_satur.getVal(buf); + buf *= divchro; + orig[ir][jr] = buf; + } + + tmpl->a[ir][jr] = orig[ir][jr] * sincosval.y; + tmpl->b[ir][jr] = orig[ir][jr] * sincosval.x; + } + + float minC = sqrt(SQR(tmpl->a[0][0]) + SQR(tmpl->b[0][0])) - orig1[0][0]; + float maxC = minC; +#ifdef _OPENMP + #pragma omp parallel for reduction(min:minC) reduction(max:maxC) schedule(dynamic,16) +#endif + + for (int ir = 0; ir < Hd; ir++) { + for (int jr = 0; jr < Wd; jr++) { + bufchro[ir][jr] = sqrt(SQR(tmpl->a[ir][jr]) + SQR(tmpl->b[ir][jr])) - orig1[ir][jr]; + minC = rtengine::min(minC, bufchro[ir][jr]); + maxC = rtengine::max(maxC, bufchro[ir][jr]); + } + } + + float coefC = 0.01f * (max(fabs(minC), fabs(maxC))); + + if (coefC == 0.f) { + coefC = 1.f; + } + + for (int ir = 0; ir < Hd; ir++) { + for (int jr = 0; jr < Wd; jr++) { + bufchro[ir][jr] /= coefC; + } + } + } else { + // + } + + + if (!lp.invret) { + transit_shapedetect_retinex(call, 5, tmpl, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } + } else { + // + } + + } + + delete tmpl; + reducDEBuffer.reset(); + origBuffer.reset(); + origBuffer1.reset(); + + if (bufmask) { + delete bufmask; + } + + if (!lp.enaretiMasktmap && lp.enaretiMask) { + if (buforig) { + delete buforig; + } + + if (buforigmas) { + delete buforigmas; + } + } + + if (bufreti) { + delete bufreti; + } + + } + } + + + + if (lp.str >= 0.2f && lp.retiena && call == 2) { + int GW = transformed->W; + int GH = transformed->H; + int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); + int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); + int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); + int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); + int bfh = yend - ystart; + int bfw = xend - xstart; + + LabImage *bufreti = nullptr; + LabImage *bufmask = nullptr; + LabImage *buforig = nullptr; + LabImage *buforigmas = nullptr; + int bfhr = bfh; + int bfwr = bfw; + bool reduH = false; + bool reduW = false; + + if (bfw >= mSP && bfh > mSP) { + + if (lp.ftwreti) { + optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, reduH, reduW, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy); + } + + array2D buflight(bfw, bfh); + JaggedArray bufchro(bfw, bfh); + + int Hd, Wd; + Hd = GH; + Wd = GW; + + if (!lp.invret && call == 2) { + + Hd = bfh; + Wd = bfw; + bufreti = new LabImage(bfw, bfh); + bufmask = new LabImage(bfw, bfh); + + if (!lp.enaretiMasktmap && lp.enaretiMask) { + buforig = new LabImage(bfw, bfh); + buforigmas = new LabImage(bfw, bfh); + } + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ir = 0; ir < bfh; ir++) //fill with 0 + for (int jr = 0; jr < bfw; jr++) { + bufreti->L[ir][jr] = 0.f; + bufreti->a[ir][jr] = 0.f; + bufreti->b[ir][jr] = 0.f; + buflight[ir][jr] = 0.f; + bufchro[ir][jr] = 0.f; + } + + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = ystart; y < yend; y++) { + for (int x = xstart; x < xend; x++) { + bufreti->L[y - ystart][x - xstart] = original->L[y][x]; + bufreti->a[y - ystart][x - xstart] = original->a[y][x]; + bufreti->b[y - ystart][x - xstart] = original->b[y][x]; + bufmask->L[y - ystart][x - xstart] = original->L[y][x]; + bufmask->a[y - ystart][x - xstart] = original->a[y][x]; + bufmask->b[y - ystart][x - xstart] = original->b[y][x]; + + if (!lp.enaretiMasktmap && lp.enaretiMask) { + buforig->L[y - ystart][x - xstart] = original->L[y][x]; + buforig->a[y - ystart][x - xstart] = original->a[y][x]; + buforig->b[y - ystart][x - xstart] = original->b[y][x]; + } + } + } + } + + float raddE = params->locallab.spots.at(sp).softradiusret; + + //calc dE and reduction to use in MSR to reduce artifacts + const int limscope = 80; + const float mindE = 4.f + MINSCOPE * lp.sensh * lp.thr; + const float maxdE = 5.f + MAXSCOPE * lp.sensh * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + const float refa = chromaref * cos(hueref); + const float refb = chromaref * sin(hueref); + + std::unique_ptr> reducDEBuffer(new JaggedArray(Wd, Hd)); + float** reducDE = *(reducDEBuffer.get()); + float ade = 0.01f * raddE; + float bde = 100.f - raddE; + float sensibefore = ade * lp.sensh + bde;//we can change sensitivity 0.1 90 or 0.3 70 or 0.4 60 +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = ystart; y < yend ; y++) + for (int x = xstart; x < xend; x++) { + float dE = sqrt(SQR(refa - bufreti->a[y - ystart][x - xstart] / 327.68f) + SQR(refb - bufreti->b[y - ystart][x - xstart] / 327.68f) + SQR(lumaref - bufreti->b[y - ystart][x - xstart] / 327.68f)); + float reducdE; + calcreducdE(dE, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sensibefore, reducdE); + reducDE[y - ystart][x - xstart] = CLIPdE(reducdE); + + } + + std::unique_ptr> origBuffer(new JaggedArray(Wd, Hd)); + float** orig = *(origBuffer.get()); + + std::unique_ptr> origBuffer1(new JaggedArray(Wd, Hd)); + float** orig1 = *(origBuffer1.get()); + + LabImage *tmpl = nullptr; + + if (!lp.invret && call == 2) { + #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) @@ -7818,50 +13410,267 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o for (int ir = 0; ir < Hd; ir += 1) for (int jr = 0; jr < Wd; jr += 1) { - float Chprov = orig1[ir][jr]; - float2 sincosval; - sincosval.y = Chprov == 0.0f ? 1.f : transformed->a[ir][jr] / Chprov; - sincosval.x = Chprov == 0.0f ? 0.f : transformed->b[ir][jr] / Chprov; - tmpl->a[ir][jr] = orig[ir][jr] * sincosval.y; - tmpl->b[ir][jr] = orig[ir][jr] * sincosval.x; - + orig[ir][jr] = bufreti->L[ir][jr]; + orig1[ir][jr] = bufreti->L[ir][jr]; } + + tmpl = new LabImage(Wd, Hd); + + } else { + // } + // float minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax; + bool fftw = lp.ftwreti; + //for Retinex Mask are incorporated in MSR + bool delt = params->locallab.spots.at(sp).deltae; + int sco = params->locallab.spots.at(sp).scopemask; + float lumask = params->locallab.spots.at(sp).lumask; + + const int limscope2 = 80; + const float mindE2 = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE2 = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim2 = 2.f + MINSCOPE * limscope2 * lp.thr; + const float maxdElim2 = 5.f + MAXSCOPE * limscope2 * (1 + 0.1f * lp.thr); + + ImProcFunctions::MSRLocal(call, sp, fftw, 1, reducDE, bufreti, bufmask, buforig, buforigmas, orig, tmpl->L, orig1, + Wd, Hd, bfwr, bfhr, params->locallab, sk, locRETgainCcurve, locRETtransCcurve, 0, 4, 1.f, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax, + locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, llretiMask, + lmaskretilocalcurve, localmaskretiutili, + transformed, lp.enaretiMasktmap, lp.enaretiMask, + delt, hueref, chromaref, lumaref, + maxdE2, mindE2, maxdElim2, mindElim2, lp.iterat, limscope2, sco, lp.balance, lp.balanceh, lumask); + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ir = 0; ir < Hd; ir += 1) + for (int jr = 0; jr < Wd; jr += 1) { + tmpl->L[ir][jr] = orig[ir][jr]; + } + + + if (lp.equret) { //equilibrate luminance before / after MSR + float *datain = new float[Hd * Wd]; + float *data = new float[Hd * Wd]; +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ir = 0; ir < Hd; ir += 1) + for (int jr = 0; jr < Wd; jr += 1) { + datain[ir * Wd + jr] = orig1[ir][jr]; + data[ir * Wd + jr] = orig[ir][jr]; + } + + normalize_mean_dt(data, datain, Hd * Wd, 1.f, 1.f); +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ir = 0; ir < Hd; ir += 1) + for (int jr = 0; jr < Wd; jr += 1) { + tmpl->L[ir][jr] = data[ir * Wd + jr]; + } + + delete [] datain; + delete [] data; + } + + if (!lp.invret) { - transit_shapedetect_retinex(5, tmpl, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); + float minL = tmpl->L[0][0] - bufreti->L[0][0]; + float maxL = minL; +#ifdef _OPENMP + #pragma omp parallel for reduction(min:minL) reduction(max:maxL) schedule(dynamic,16) +#endif + + for (int ir = 0; ir < Hd; ir++) { + for (int jr = 0; jr < Wd; jr++) { + buflight[ir][jr] = tmpl->L[ir][jr] - bufreti->L[ir][jr]; + minL = rtengine::min(minL, buflight[ir][jr]); + maxL = rtengine::max(maxL, buflight[ir][jr]); + } + } + + float coef = 0.01f * (max(fabs(minL), fabs(maxL))); + + if (coef == 0.f) { + coef = 1.f; + } + + + for (int ir = 0; ir < Hd; ir++) { + for (int jr = 0; jr < Wd; jr++) { + buflight[ir][jr] /= coef; + } + } + + + + transit_shapedetect_retinex(call, 4, bufreti, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } + } else { - InverseReti_Local(lp, hueref, chromaref, lumaref, original, transformed, tmpl, cx, cy, 1, sk); + // } - } + if (params->locallab.spots.at(sp).chrrt > 0) { - delete tmpl; - delete [] origBuffer; - delete [] origBuffer1; + if (!lp.invret && call == 2) { - if (bufmask) { - delete bufmask; - } +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < Hd; ir += 1) + for (int jr = 0; jr < Wd; jr += 1) { + + orig[ir][jr] = sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr])); + orig1[ir][jr] = sqrt(SQR(bufreti->a[ir][jr]) + SQR(bufreti->b[ir][jr])); + } + + } else { + // + } + + float maxChro = orig1[0][0]; +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxChro) schedule(dynamic,16) +#endif + + for (int ir = 0; ir < Hd; ir++) { + for (int jr = 0; jr < Wd; jr++) { + maxChro = rtengine::max(maxChro, orig1[ir][jr]); + } + } + + float divchro = maxChro; + + //first step change saturation whithout Retinex ==> gain of time and memory + float satreal = lp.str * params->locallab.spots.at(sp).chrrt / 100.f; + + if (params->locallab.spots.at(sp).chrrt <= 0.2f) { + satreal /= 10.f; + } + + DiagonalCurve reti_satur({ + DCT_NURBS, + 0, 0, + 0.2, 0.2 + satreal / 250.0, + 0.6, min(1.0, 0.6 + satreal / 250.0), + 1, 1 + }); + + if (!lp.invret && call == 2) { + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ir = 0; ir < Hd; ir += 1) + for (int jr = 0; jr < Wd; jr += 1) { + const float Chprov = orig1[ir][jr]; + float2 sincosval; + sincosval.y = Chprov == 0.0f ? 1.f : bufreti->a[ir][jr] / Chprov; + sincosval.x = Chprov == 0.0f ? 0.f : bufreti->b[ir][jr] / Chprov; + + if (params->locallab.spots.at(sp).chrrt <= 40.f) { //first step + float buf = LIM01(orig[ir][jr] / divchro); + buf = reti_satur.getVal(buf); + buf *= divchro; + orig[ir][jr] = buf; + } + + tmpl->a[ir][jr] = orig[ir][jr] * sincosval.y; + tmpl->b[ir][jr] = orig[ir][jr] * sincosval.x; + } + + float minC = sqrt(SQR(tmpl->a[0][0]) + SQR(tmpl->b[0][0])) - orig1[0][0]; + float maxC = minC; +#ifdef _OPENMP + #pragma omp parallel for reduction(min:minC) reduction(max:maxC) schedule(dynamic,16) +#endif + + for (int ir = 0; ir < Hd; ir++) { + for (int jr = 0; jr < Wd; jr++) { + bufchro[ir][jr] = sqrt(SQR(tmpl->a[ir][jr]) + SQR(tmpl->b[ir][jr])) - orig1[ir][jr]; + minC = rtengine::min(minC, bufchro[ir][jr]); + maxC = rtengine::max(maxC, bufchro[ir][jr]); + } + } + + float coefC = 0.01f * (max(fabs(minC), fabs(maxC))); + + if (coefC == 0.f) { + coefC = 1.f; + } + + for (int ir = 0; ir < Hd; ir++) { + for (int jr = 0; jr < Wd; jr++) { + bufchro[ir][jr] /= coefC; + } + } + } else { + // + } + + + if (!lp.invret) { + transit_shapedetect_retinex(call, 5, tmpl, bufmask, buforigmas, buflight, bufchro, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } + } else { + // + } - if (!lp.enaretiMasktmap && lp.enaretiMask) { - if (buforig) { - delete buforig; } - if (buforigmas) { - delete buforigmas; - } - } + delete tmpl; + origBuffer.reset(); + origBuffer1.reset(); + reducDEBuffer.reset(); - if (bufreti) { - delete bufreti; + if (bufmask) { + delete bufmask; + } + + if (!lp.enaretiMasktmap && lp.enaretiMask) { + if (buforig) { + delete buforig; + } + + if (buforigmas) { + delete buforigmas; + } + } + + if (bufreti) { + delete bufreti; + } } } + bool enablefat = false; - if (!lp.invex && (lp.exposena && (lp.expcomp != 0.f || lp.war != 0 || lp.showmaskexpmet == 2 || lp.enaExpMask || lp.showmaskexpmet == 3 || lp.showmaskexpmet == 4 || lp.showmaskexpmet == 5 || (exlocalcurve && localexutili)))) { //interior ellipse renforced lightness and chroma //locallutili + if (params->locallab.spots.at(sp).fatamount > 1.f) { + enablefat = true;; + } + + bool execex = (lp.exposena && (lp.expcomp != 0.f || lp.blac != 0 || lp.laplacexp > 0.1f || lp.strexp != 0.f || enablefat || lp.showmaskexpmet == 2 || lp.enaExpMask || lp.showmaskexpmet == 3 || lp.showmaskexpmet == 4 || lp.showmaskexpmet == 5 || (exlocalcurve && localexutili))); + + if (!lp.invex && execex) { int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); @@ -7874,84 +13683,23 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o bool reduH = false; bool reduW = false; - if (lp.expmet == 1) { - int ftsizeH = 1; - int ftsizeW = 1; - - for (int ft = 0; ft < N_fftwsize; ft++) { //find best values - if (fftw_size[ft] <= bfh) { - ftsizeH = fftw_size[ft]; - break; - } - } - - for (int ft = 0; ft < N_fftwsize; ft++) { - if (fftw_size[ft] <= bfw) { - ftsizeW = fftw_size[ft]; - break; - } - } - - // printf("FTsizeH =%i FTsizeW=%i \n", ftsizeH, ftsizeW); - //optimize with size fftw - if (ystart == 0 && yend < original->H) { - lp.ly -= (bfh - ftsizeH); - } else if (ystart != 0 && yend == original->H) { - lp.lyT -= (bfh - ftsizeH); - } else if (ystart != 0 && yend != original->H) { - if (lp.ly <= lp.lyT) { - lp.lyT -= (bfh - ftsizeH); - } else { - lp.ly -= (bfh - ftsizeH); - } - } else if (ystart == 0 && yend == original->H) { - bfhr = ftsizeH; - reduH = true; - } - - if (xstart == 0 && xend < original->W) { - lp.lx -= (bfw - ftsizeW); - } else if (xstart != 0 && xend == original->W) { - lp.lxL -= (bfw - ftsizeW); - } else if (xstart != 0 && xend != original->W) { - if (lp.lx <= lp.lxL) { - lp.lxL -= (bfw - ftsizeW); - } else { - lp.lx -= (bfw - ftsizeW); - } - } else if (xstart == 0 && xend == original->W) { - bfwr = ftsizeW; - reduW = true; - } - - //new values optimized - ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); - yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); - xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); - xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); - bfh = bfhr = yend - ystart; - bfw = bfwr = xend - xstart; - - if (reduH) { - bfhr = ftsizeH; - } - - if (reduW) { - bfwr = ftsizeW; - } + if (complexsoft == 2) { + lp.expmet = 1; + lp.laplacexp = 0.f; } - if (bfw > 0 && bfh > 0) { + if (bfw >= mSP && bfh >= mSP) { + + if (lp.expmet == 1) { + optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, reduH, reduW, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy); + } + std::unique_ptr bufexporig(new LabImage(bfw, bfh)); std::unique_ptr bufexpfin(new LabImage(bfw, bfh)); + std::unique_ptr bufmaskblurexp; std::unique_ptr originalmaskexp; - - array2D buflight(bfw, bfh); - JaggedArray bufl_ab(bfw, bfh); - JaggedArray buf_a_cat(bfw, bfh); - JaggedArray buf_b_cat(bfw, bfh); array2D blend2; if (call <= 3) { //simpleprocess, dcrop, improccoordinator @@ -8009,17 +13757,6 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } } - std::unique_ptr> ble; - std::unique_ptr> guid; - - if (lp.showmaskexpmet == 2 || lp.enaExpMask || lp.showmaskexpmet == 3 || lp.showmaskexpmet == 5) { - ble.reset(new array2D(bfw, bfh)); - guid.reset(new array2D(bfw, bfh)); - } - - float meanfab, fab; - - mean_fab(xstart, ystart, bfw, bfh, bufexporig.get(), original, fab, meanfab, lp.chromaexp); float meanorig = 0.f; for (int ir = 0; ir < bfh; ir++) @@ -8029,94 +13766,75 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o meanorig /= (bfh * bfw); - // meanorig /= 32768.f; - // printf("meanor=%f \n", meanorig); - if (lp.showmaskexpmet == 2 || lp.enaExpMask || lp.showmaskexpmet == 3 || lp.showmaskexpmet == 5) { -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif + int inv = 0; + bool showmaske = false; + bool enaMask = false; + bool deltaE = false; + bool modmask = false; + bool zero = false; + bool modif = false; - for (int ir = 0; ir < bfh; ir++) - for (int jr = 0; jr < bfw; jr++) { - float kmaskLexp = 0.f; - float kmaskC = 0.f; - float kmaskHL = 0.f; - float kmaskH = 0.f; + if (lp.showmaskexpmet == 3) { + showmaske = true; + } + if (lp.enaExpMask) { + enaMask = true; + } - if (locllmasexpCurve && llmasexputili) { - const float ligh = bufexporig->L[ir][jr] / 32768.f; - kmaskLexp = 32768.f * LIM01(1.f - locllmasexpCurve[500.f * ligh]); - } + if (lp.showmaskexpmet == 5) { + deltaE = true; + } - if (lp.showmaskexpmet != 5) { - if (locccmasexpCurve && lcmasexputili) { - const float chromaskr = 0.0001f + sqrt(SQR((bufexporig->a[ir][jr])) + SQR((bufexporig->b[ir][jr]))) / fab; - kmaskC = LIM01(1.f - locccmasexpCurve[500.f * chromaskr]); - } - } + if (lp.showmaskexpmet == 2) { + modmask = true; + } - if (lochhmasexpCurve && lhmasexputili) { - const float huema = xatan2f(bufexporig->b[ir][jr], bufexporig->a[ir][jr]); - float h = Color::huelab_to_huehsv2(huema); - h += 1.f / 6.f; + if (lp.showmaskexpmet == 1) { + modif = true; + } - if (h > 1.f) { - h -= 1.f; - } + if (lp.showmaskexpmet == 0) { + zero = true; + } - const float valHH = LIM01(1.f - lochhmasexpCurve[500.f * h]); + float chrom = lp.chromaexp; + float rad = lp.radmaexp; + float gamma = lp.gammaexp; + float slope = lp.slomaexp; + float blendm = lp.blendmaexp; + float lap = params->locallab.spots.at(sp).lapmaskexp; + bool pde = params->locallab.spots.at(sp).laplac; + LocwavCurve dummy; + bool lmasutilicolwav = false; + bool delt = params->locallab.spots.at(sp).deltae; + int sco = params->locallab.spots.at(sp).scopemask; + int shado = 0; + int shortcu = 0;//lp.mergemet; //params->locallab.spots.at(sp).shortc; - if (lp.showmaskexpmet != 5) { - kmaskH = valHH; - } + const int limscope = 80; + const float mindE = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + float amountcd = 0.f; + float anchorcd = 50.f; + int lumask = params->locallab.spots.at(sp).lumask; + LocHHmaskCurve lochhhmasCurve; + bool lhhmasutili = false; - kmaskHL = 32768.f * valHH; - } + maskcalccol(call, false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufexporig.get(), bufmaskblurexp.get(), originalmaskexp.get(), original, reserved, inv, lp, + 0.f, false, + locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, lochhhmasCurve, lhhmasutili, multiThread, + enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, shado, amountcd, anchorcd, lmaskexplocalcurve, localmaskexputili, dummy, lmasutilicolwav, 1, 1, 5, 5, + shortcu, delt, hueref, chromaref, lumaref, + maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco + ); - bufmaskblurexp->a[ir][jr] = kmaskC + kmaskH; - bufmaskblurexp->b[ir][jr] = kmaskC + kmaskH; - (*ble)[ir][jr] = LIM01(CLIPLOC(kmaskLexp + kmaskHL) / 32768.f); - (*guid)[ir][jr] = LIM01(bufexporig->L[ir][jr] / 32768.f); - } + if (lp.showmaskexpmet == 3) { + showmask(lumask, lp, xstart, ystart, cx, cy, bfw, bfh, bufexporig.get(), transformed, bufmaskblurexp.get(), 0); - if (lp.radmaexp > 0.f) { - guidedFilter(*guid, *ble, *ble, lp.radmaexp * 10.f / sk, 0.001, multiThread, 4); - } - - LUTf lutTonemask(65536); - calcGammaLut(lp.gammaexp, lp.slomaexp, lutTonemask); - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < bfh; ir++) { - for (int jr = 0; jr < bfw; jr++) { - const float L_ = 2.f * LIM01((*ble)[ir][jr]) * 32768.f; - bufmaskblurexp->L[ir][jr] = lutTonemask[L_]; - } - } - - const float radiusb = 1.f / sk; - -#ifdef _OPENMP - #pragma omp parallel -#endif - { - gaussianBlur(bufmaskblurexp->L, bufmaskblurexp->L, bfw, bfh, radiusb); - gaussianBlur(bufmaskblurexp->a, bufmaskblurexp->a, bfw, bfh, 1.f + (0.5f * lp.radmaexp) / sk); - gaussianBlur(bufmaskblurexp->b, bufmaskblurexp->b, bfw, bfh, 1.f + (0.5f * lp.radmaexp) / sk); - } - - - if (lp.showmaskexpmet == 0 || lp.showmaskexpmet == 1 || lp.showmaskexpmet == 2 /* || lp.showmaskexpmet == 4 */ || lp.showmaskexpmet == 5 || lp.enaExpMask) { - blendmask(lp, xstart, ystart, cx, cy, bfw, bfh, bufexporig.get(), original, bufmaskblurexp.get(), originalmaskexp.get(), lp.blendmaexp); - - } else if (lp.showmaskexpmet == 3) { - showmask(lp, xstart, ystart, cx, cy, bfw, bfh, bufexporig.get(), transformed, bufmaskblurexp.get()); - return; - } + return; } if (lp.showmaskexpmet == 4) { @@ -8149,7 +13867,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } if (lp.expcomp == 0.f) { - lp.expcomp = 0.1f; // to enabled + lp.expcomp = 0.011f; // to enabled } ImProcFunctions::exlabLocal(lp, bfh, bfw, bufexpfin.get(), bufexpfin.get(), hltonecurveloc, shtonecurveloc, tonecurveloc, meanorig); @@ -8160,106 +13878,311 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o ImProcFunctions::exlabLocal(lp, bfh, bfw, bufexporig.get(), bufexpfin.get(), hltonecurveloc, shtonecurveloc, tonecurveloc, meanorig); } +//gradient + struct grad_params gp; + + if (lp.strexp != 0.f) { + calclocalGradientParams(lp, gp, ystart, xstart, bfw, bfh, 1); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + double factor = 1.0; + factor = ImProcFunctions::calcGradientFactor(gp, jr, ir); + bufexpfin->L[ir][jr] *= factor; + } + } + + + //exposure_pde if (lp.expmet == 1) { - MyMutex::MyLock lock(*fftwMutex); - float *datain = new float[bfwr * bfhr]; - float *dataout = new float[bfwr * bfhr]; - float *dataor = new float[bfwr * bfhr]; + Imagefloat *tmpImagefat = nullptr; + + if (enablefat) { + float *datain = new float[bfwr * bfhr]; + float *dataout = new float[bfwr * bfhr]; #ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int y = 0; y < bfhr; y++) { - for (int x = 0; x < bfwr; x++) { - datain[y * bfwr + x] = bufexpfin->L[y][x]; - dataor[y * bfwr + x] = bufexpfin->L[y][x]; + for (int y = 0; y < bfhr; y++) { + for (int x = 0; x < bfwr; x++) { + float L = bufexpfin->L[y][x]; + datain[y * bfwr + x] = L; + } } - } - //call PDE equation - with Laplacian threshold - ImProcFunctions::exposure_pde(dataor, datain, dataout, bfwr, bfhr, 12.f * lp.laplacexp, lp.balanexp); + FattalToneMappingParams fatParams; + fatParams.enabled = true; + fatParams.threshold = params->locallab.spots.at(sp).fatdetail; + fatParams.amount = params->locallab.spots.at(sp).fatamount; + fatParams.anchor = 50.f; //params->locallab.spots.at(sp).fatanchor; + float sigm = params->locallab.spots.at(sp).fatlevel; + float mean = params->locallab.spots.at(sp).fatanchor; + tmpImagefat = new Imagefloat(bfwr, bfhr); + lab2rgb(*bufexpfin, *tmpImagefat, params->icm.workingProfile); + ToneMapFattal02(tmpImagefat, fatParams, 3, 0, nullptr, 0, 0, 1);//last parameter = 1 ==>ART algorithm + rgb2lab(*tmpImagefat, *bufexpfin, params->icm.workingProfile); + delete tmpImagefat; #ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int y = 0; y < bfhr; y++) { - for (int x = 0; x < bfwr; x++) { - bufexpfin->L[y][x] = dataout[y * bfwr + x] ; + for (int y = 0; y < bfhr; y++) { + for (int x = 0; x < bfwr; x++) { + float L = bufexpfin->L[y][x]; + dataout[y * bfwr + x] = L; + } } + + normalize_mean_dt(dataout, datain, bfwr * bfhr, mean, sigm); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfhr; y++) { + for (int x = 0; x < bfwr; x++) { + bufexpfin->L[y][x] = dataout[y * bfwr + x]; + } + } + + + delete [] datain; + delete [] dataout; } - delete [] datain; - delete [] dataout; - delete [] dataor; + + if (lp.laplacexp > 0.1f) { + MyMutex::MyLock lock(*fftwMutex); + float *datain = new float[bfwr * bfhr]; + float *dataout = new float[bfwr * bfhr]; + float *dataor = new float[bfwr * bfhr]; + float gam = params->locallab.spots.at(sp).gamm; + float igam = 1.f / gam; + + + if (params->locallab.spots.at(sp).exnoiseMethod == "med" || params->locallab.spots.at(sp).exnoiseMethod == "medhi") { + + + if (lp.blac < -100.f && lp.linear > 0.01f) { + Median med = Median:: TYPE_3X3_SOFT; + float evnoise = lp.blac - lp.linear * 2000.f; + + if (params->locallab.spots.at(sp).exnoiseMethod == "med") { + evnoise *= 0.4f; + } + + //soft denoise, user must use Local Denoise to best result + if (evnoise < - 18000.f) { + med = Median::TYPE_5X5_STRONG; + } else if (evnoise < - 15000.f) { + med = Median::TYPE_5X5_SOFT; + } else if (evnoise < - 10000.f) { + med = Median::TYPE_3X3_STRONG; + } else { + med = Median:: TYPE_3X3_SOFT; + } + + Median_Denoise(bufexpfin->L, bufexpfin->L, bfwr, bfhr, med, 1, multiThread); + Median_Denoise(bufexpfin->a, bufexpfin->a, bfwr, bfhr, Median::TYPE_3X3_SOFT, 1, multiThread); + Median_Denoise(bufexpfin->b, bufexpfin->b, bfwr, bfhr, Median::TYPE_3X3_SOFT, 1, multiThread); + + } + + } + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfhr; y++) { + for (int x = 0; x < bfwr; x++) { + float L = LIM01(bufexpfin->L[y][x] / 32768.f);//change gamma for Laplacian + + L = pow(L, gam); + L *= 32768.f; + datain[y * bfwr + x] = L; + dataor[y * bfwr + x] = L; + } + } + + //call PDE equation - with Laplacian threshold + ImProcFunctions::exposure_pde(dataor, datain, dataout, bfwr, bfhr, 12.f * lp.laplacexp, lp.balanexp); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfhr; y++) { + for (int x = 0; x < bfwr; x++) { + float Y = dataout[y * bfwr + x] / 32768.f;//inverse Laplacian gamma + Y = pow(Y, igam); + Y *= 32768.f; + bufexpfin->L[y][x] = Y; + } + } + + delete [] datain; + delete [] dataout; + delete [] dataor; + } } + //shadows with ipshadowshighlight - if (lp.shadex > 0) { - ImProcFunctions::shadowsHighlights(bufexpfin.get(), true, 1, 0, lp.shadex, 40, sk, 0, lp.shcomp); - } - - //cat02 - if (params->locallab.spots.at(sp).warm != 0) { - ImProcFunctions::ciecamloc_02float(sp, bufexpfin.get()); - } - - - constexpr float ampli = 70.f; - const float ch = (1.f + 0.02f * lp.expchroma); - const float chprosl = ch <= 1.f ? 99.f * ch - 99.f : CLIPCHRO(ampli * ch - ampli); - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < bfh; ir++) { - for (int jr = 0; jr < bfw; jr++) { - const float epsi = bufexporig->L[ir][jr] == 0.f ? 0.001f : 0.f; - const float rapexp = bufexpfin->L[ir][jr] / (bufexporig->L[ir][jr] + epsi); - - if (rapexp >= 1.f) { - bufl_ab[ir][jr] = chprosl * rapexp; - } else { - bufl_ab[ir][jr] = chprosl * rapexp; - } + if ((lp.expcomp != 0.f && lp.expcomp != 0.01f) || (exlocalcurve && localexutili)) { + if (lp.shadex > 0) { + ImProcFunctions::shadowsHighlights(bufexpfin.get(), true, 1, 0, lp.shadex, 40, sk, 0, lp.shcomp); } } - if (lp.softradiusexp > 0.f) { - softproc(bufexporig.get(), bufexpfin.get(), lp.softradiusexp, bfh, bfw, 0.0001, 0.00001, 0.0001f, sk, multiThread); - // softprocess(bufexporig.get(), buflight, lp.softradiusexp, bfh, bfw, sk, multiThread); + /* + //cat02 + if (params->locallab.spots.at(sp).warm != 0) { + ImProcFunctions::ciecamloc_02float(sp, bufexpfin.get()); + } + */ + /* + constexpr float ampli = 70.f; + float ch = 0.f; + float chprosl = 0.f; + + if ((lp.expcomp != 0.f && lp.expcomp != 0.01f) || (exlocalcurve && localexutili)) { + ch = (1.f + 0.02f * lp.expchroma); + chprosl = ch <= 1.f ? 99.f * ch - 99.f : CLIPCHRO(ampli * ch - ampli); + } + + #ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) + #endif + + for (int ir = 0; ir < bfh; ir++) { + for (int jr = 0; jr < bfw; jr++) { + const float epsi = bufexporig->L[ir][jr] == 0.f ? 0.001f : 0.f; + const float rapexp = bufexpfin->L[ir][jr] / (bufexporig->L[ir][jr] + epsi); + + if (rapexp >= 1.f) { + bufl_ab[ir][jr] = chprosl * rapexp; + } else { + bufl_ab[ir][jr] = chprosl * rapexp; + } + } + } + */ + if (lp.softradiusexp > 0.f && lp.expmet == 0) { + softproc(bufexporig.get(), bufexpfin.get(), lp.softradiusexp, bfh, bfw, 0.0001, 0.00001, 0.1f, sk, multiThread, 1); } -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif + transit_shapedetect2(call, 1, bufexporig.get(), bufexpfin.get(), originalmaskexp.get(), hueref, chromaref, lumaref, sobelref, meansob, blend2, lp, original, transformed, cx, cy, sk); - for (int ir = 0; ir < bfh; ir++) - for (int jr = 0; jr < bfw; jr++) { - buflight[ir][jr] = CLIPRET((bufexpfin->L[ir][jr] - bufexporig->L[ir][jr]) / 328.f); - buf_a_cat[ir][jr] = CLIPRET((bufexpfin->a[ir][jr] - bufexporig->a[ir][jr]) / 328.f); - buf_b_cat[ir][jr] = CLIPRET((bufexpfin->b[ir][jr] - bufexporig->b[ir][jr]) / 328.f); - } - - if (lp.softradiusexp > 0.f) { - // softprocess(bufexporig.get(), buflight, lp.softradiusexp, bfh, bfw, sk, multiThread); - } } - bufexpfin.reset(); - transit_shapedetect(1, bufexporig.get(), originalmaskexp.get(), buflight, bufl_ab, buf_a_cat, buf_b_cat, nullptr, false, hueref, chromaref, lumaref, sobelref, meansob, blend2, lp, original, transformed, cx, cy, sk); - bufexporig.reset(); + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } } } } - //inverse - else if (lp.invex && (lp.expcomp != 0.0 || lp.war != 0 || (exlocalcurve && localexutili)) && lp.exposena) { + + else if (lp.invex && (lp.expcomp != 0.0 || lp.laplacexp > 0.1f || params->locallab.spots.at(sp).fatamount > 1.f || (exlocalcurve && localexutili) || lp.enaExpMaskinv || lp.showmaskexpmetinv == 1) && lp.exposena) { float adjustr = 2.f; - InverseColorLight_Local(sp, 1, lp, lightCurveloc, hltonecurveloc, shtonecurveloc, tonecurveloc, exlocalcurve, cclocalcurve, adjustr, localcutili, lllocalcurve, locallutili, original, transformed, cx, cy, hueref, chromaref, lumaref, sk); + std::unique_ptr bufmaskblurexp; + std::unique_ptr originalmaskexp; + std::unique_ptr bufexporig; + int GW = transformed->W; + int GH = transformed->H; + bufexporig.reset(new LabImage(GW, GH)); + + if (lp.enaExpMaskinv || lp.showmaskexpmetinv == 1) { + bufmaskblurexp.reset(new LabImage(GW, GH, true)); + originalmaskexp.reset(new LabImage(GW, GH)); + } + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < GH ; y++) { + for (int x = 0; x < GW; x++) { + bufexporig->L[y][x] = original->L[y][x]; + } + } + + int inv = 1; + bool showmaske = false; + bool enaMask = false; + bool deltaE = false; + bool modmask = false; + bool zero = false; + bool modif = false; + + if (lp.showmaskexpmetinv == 1) { + showmaske = true; + } + + if (lp.enaExpMaskinv) { + enaMask = true; + } + + if (lp.showmaskexpmetinv == 0) { + zero = true; + } + + float chrom = lp.chromaexp; + float rad = lp.radmaexp; + float gamma = lp.gammaexp; + float slope = lp.slomaexp; + float blendm = lp.blendmaexp; + float lap = params->locallab.spots.at(sp).lapmaskexp; + bool pde = params->locallab.spots.at(sp).laplac; + LocwavCurve dummy; + bool lmasutilicolwav = false; + // bool delt = params->locallab.spots.at(sp).deltae; + bool delt = false; + int sco = params->locallab.spots.at(sp).scopemask; + int shado = 0; + int shortcu = 0;//lp.mergemet; //params->locallab.spots.at(sp).shortc; + int lumask = params->locallab.spots.at(sp).lumask; + + const int limscope = 80; + const float mindE = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + float amountcd = 0.f; + float anchorcd = 50.f; + LocHHmaskCurve lochhhmasCurve; + bool lhhmasutili = false; + + maskcalccol(call, false, pde, GW, GH, 0, 0, sk, cx, cy, bufexporig.get(), bufmaskblurexp.get(), originalmaskexp.get(), original, reserved, inv, lp, + 0.f, false, + locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, lochhhmasCurve, lhhmasutili, multiThread, + enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, shado, amountcd, anchorcd, lmaskexplocalcurve, localmaskexputili, dummy, lmasutilicolwav, 1, 1, 5, 5, + shortcu, delt, hueref, chromaref, lumaref, + maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco + ); + + if (lp.showmaskexpmetinv == 1) { + showmask(lumask, lp, 0, 0, cx, cy, GW, GH, bufexporig.get(), transformed, bufmaskblurexp.get(), inv); + + return; + } + + InverseColorLight_Local(false, false, sp, 1, lp, originalmaskexp.get(), lightCurveloc, hltonecurveloc, shtonecurveloc, tonecurveloc, exlocalcurve, cclocalcurve, adjustr, localcutili, lllocalcurve, locallutili, original, transformed, cx, cy, hueref, chromaref, lumaref, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } + } @@ -8273,7 +14196,14 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o float b_base = lp.lowB / scaling; bool ctoning = (a_scale != 0.f || b_scale != 0.f || a_base != 0.f || b_base != 0.f); - if (!lp.inv && (lp.chro != 0 || lp.ligh != 0.f || lp.cont != 0 || ctoning || lp.qualcurvemet != 0 || lp.showmaskcolmet == 2 || lp.enaColorMask || lp.showmaskcolmet == 3 || lp.showmaskcolmet == 4 || lp.showmaskcolmet == 5) && lp.colorena) { // || lllocalcurve)) { //interior ellipse renforced lightness and chroma //locallutili + float a_scalemerg = (lp.highAmerg - lp.lowAmerg) / factor / scaling; + float a_basemerg = lp.lowAmerg / scaling; + float b_scalemerg = (lp.highBmerg - lp.lowBmerg) / factor / scaling; + float b_basemerg = lp.lowBmerg / scaling; + bool ctoningmerg = (a_scalemerg != 0.f || b_scalemerg != 0.f || a_basemerg != 0.f || b_basemerg != 0.f); + bool nottransit = false; + + if (!lp.inv && (lp.chro != 0 || lp.ligh != 0.f || lp.cont != 0 || ctoning || lp.mergemet > 0 || lp.strcol != 0.f || lp.strcolab != 0.f || lp.qualcurvemet != 0 || lp.showmaskcolmet == 2 || lp.enaColorMask || lp.showmaskcolmet == 3 || lp.showmaskcolmet == 4 || lp.showmaskcolmet == 5) && lp.colorena) { // || lllocalcurve)) { //interior ellipse renforced lightness and chroma //locallutili /* //test for fftw blur with tiles fftw_tile_blur....not good we can see tiles - very long time int GW = original->W; @@ -8349,26 +14279,46 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o */ - const int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); - const int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); - const int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); - const int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); - const int bfh = yend - ystart; - const int bfw = xend - xstart; + int ystart = std::max(static_cast(lp.yc - lp.lyT) - cy, 0); + int yend = std::min(static_cast(lp.yc + lp.ly) - cy, original->H); + int xstart = std::max(static_cast(lp.xc - lp.lxL) - cx, 0); + int xend = std::min(static_cast(lp.xc + lp.lx) - cx, original->W); + int bfh = yend - ystart; + int bfw = xend - xstart; + bool HHcurve = false; + bool usergb = false; + bool spez = params->locallab.spots.at(sp).special; + int bfhr = bfh; + int bfwr = bfw; + bool reduH = false; + bool reduW = false; + // printf("bfw=%i bfh=%i lpx=%f lpy=%f lpxL=%f lpYT=%f\n", bfw, bfh, lp.lx, lp.ly, lp.lxL, lp.lyT); + + if (bfw >= mSP && bfh >= mSP) { + + if (lp.blurcolmask >= 0.25f && lp.fftColorMask && call == 2) { + optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, reduH, reduW, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy); + } + + //printf("bfwred=%i bfhred=%i lpx=%f lpy=%f lpxL=%f lpYT=%f\n", bfwr, bfhr, lp.lx, lp.ly, lp.lxL, lp.lyT); + + bfh = bfhr; + bfw = bfwr; - if (bfw > 0 && bfh > 0) { std::unique_ptr bufcolorig; std::unique_ptr bufcolfin; std::unique_ptr bufmaskblurcol; std::unique_ptr originalmaskcol; + std::unique_ptr bufcolreserv; + std::unique_ptr buftemp; - array2D buflight(bfw, bfh, true); - JaggedArray bufchro(bfw, bfh, true); - JaggedArray bufhh(bfw, bfh, true); +// array2D buflight(bfw, bfh, true); +// JaggedArray bufchro(bfw, bfh, true); +// JaggedArray bufhh(bfw, bfh, true); array2D blend2; - JaggedArray buf_a(bfw, bfh, true); - JaggedArray buf_b(bfw, bfh, true); +// JaggedArray buf_a(bfw, bfh, true); +// JaggedArray buf_b(bfw, bfh, true); float adjustr = 1.0f; @@ -8393,6 +14343,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o float meansob = 0.f; bufcolorig.reset(new LabImage(bfw, bfh)); bufcolfin.reset(new LabImage(bfw, bfh)); + buftemp.reset(new LabImage(bfw, bfh)); if (lp.showmaskcolmet == 2 || lp.enaColorMask || lp.showmaskcolmet == 3 || lp.showmaskcolmet == 5) { bufmaskblurcol.reset(new LabImage(bfw, bfh, true)); @@ -8406,14 +14357,21 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o for (int y = 0; y < bfh ; y++) { for (int x = 0; x < bfw; x++) { bufcolorig->L[y][x] = original->L[y + ystart][x + xstart]; + bufcolorig->a[y][x] = original->a[y + ystart][x + xstart]; + bufcolorig->b[y][x] = original->b[y + ystart][x + xstart]; bufcolfin->L[y][x] = original->L[y + ystart][x + xstart]; + bufcolfin->a[y][x] = original->a[y + ystart][x + xstart]; + bufcolfin->b[y][x] = original->b[y + ystart][x + xstart]; + buftemp->L[y][x] = original->L[y + ystart][x + xstart]; + buftemp->a[y][x] = original->a[y + ystart][x + xstart]; + buftemp->b[y][x] = original->b[y + ystart][x + xstart]; } } const int spotSi = std::max(1 + 2 * max(1, lp.cir / sk), 5); - const bool blend = bfw > 2 * spotSi && bfh > 2 * spotSi && lp.struco > 0.f; + const bool blends = bfw > 2 * spotSi && bfh > 2 * spotSi && lp.struco > 0.f; - if (blend) { + if (blends) { blend2(bfw, bfh); ImProcFunctions::blendstruc(bfw, bfh, bufcolorig.get(), 3.f / (sk * 1.4f), 0.5f * lp.struco, blend2, sk, multiThread); @@ -8424,206 +14382,397 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o for (int y = ystart; y < yend ; y++) { for (int x = xstart; x < xend; x++) { - transformed->L[y][x] = blend2[y - ystart][x - xstart]; - transformed->a[y][x] = 0.f; - transformed->b[y][x] = 0.f; + const int lox = cx + x; + const int loy = cy + y; + int zone = 0; + float localFactor = 1.f; + const float achm = lp.trans / 100.f; + + if (lp.shapmet == 0) { + calcTransition(lox, loy, achm, lp, zone, localFactor); + } else if (lp.shapmet == 1) { + calcTransitionrect(lox, loy, achm, lp, zone, localFactor); + } + + if (zone > 0) { + transformed->L[y][x] = CLIP(blend2[y - ystart][x - xstart]); + transformed->a[y][x] = 0.f; + transformed->b[y][x] = 0.f; + } } } return; } + } - array2D ble(bfw, bfh); - array2D guid(bfw, bfh); - float meanfab, fab; + int inv = 0; + bool showmaske = false; + bool enaMask = false; + bool deltaE = false; + bool modmask = false; + bool zero = false; + bool modif = false; - mean_fab(xstart, ystart, bfw, bfh, bufcolorig.get(), original, fab, meanfab, lp.chromacol); - - if (lp.showmaskcolmet == 2 || lp.enaColorMask || lp.showmaskcolmet == 3 || lp.showmaskcolmet == 5) { - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < bfh; y++) { - for (int x = 0; x < bfw; x++) { - bufmaskblurcol->L[y][x] = original->L[y + ystart][x + xstart]; - bufmaskblurcol->a[y][x] = original->a[y + ystart][x + xstart]; - bufmaskblurcol->b[y][x] = original->b[y + ystart][x + xstart]; - } - } - -#ifdef _OPENMP - #pragma omp parallel -#endif - { -#ifdef __SSE2__ - float atan2Buffer[bfw] ALIGNED64; -#endif -#ifdef _OPENMP - #pragma omp for schedule(dynamic, 16) -#endif - - for (int ir = 0; ir < bfh; ir++) { -#ifdef __SSE2__ - - if (lochhmasCurve && lhmasutili) { - int i = 0; - - for (; i < bfw - 3; i += 4) { - STVF(atan2Buffer[i], xatan2f(LVFU(bufcolorig->b[ir][i]), LVFU(bufcolorig->a[ir][i]))); - } - - for (; i < bfw; i++) { - atan2Buffer[i] = xatan2f(bufcolorig->b[ir][i], bufcolorig->a[ir][i]); - } - } - -#endif - - for (int jr = 0; jr < bfw; jr++) { - float kmaskL = 0.f; - float kmaskC = 0.f; - float kmaskHL = 0.f; - float kmaskH = 0.f; - - if (locllmasCurve && llmasutili) { - kmaskL = 32768.f * LIM01(1.f - locllmasCurve[(500.f / 32768.f) * bufcolorig->L[ir][jr]]); - } - - if (lp.showmaskcolmet != 5 && locccmasCurve && lcmasutili) { - kmaskC = LIM01(1.f - locccmasCurve[500.f * (0.0001f + sqrt(SQR(bufcolorig->a[ir][jr]) + SQR(bufcolorig->b[ir][jr])) / fab)]); - } - - if (lochhmasCurve && lhmasutili) { -#ifdef __SSE2__ - const float huema = atan2Buffer[jr]; -#else - const float huema = xatan2f(bufcolorig->b[ir][jr], bufcolorig->a[ir][jr]); -#endif - float h = Color::huelab_to_huehsv2(huema); - h += 1.f / 6.f; - - if (h > 1.f) { - h -= 1.f; - } - - const float valHH = LIM01(1.f - lochhmasCurve[500.f * h]); - - if (lp.showmaskcolmet != 5) { - kmaskH = valHH; - } - - kmaskHL = 32768.f * valHH; - } - - bufmaskblurcol->L[ir][jr] = CLIPLOC(kmaskL + kmaskHL); - bufmaskblurcol->a[ir][jr] = CLIPC(kmaskC + kmaskH); - bufmaskblurcol->b[ir][jr] = CLIPC(kmaskC + kmaskH); - ble[ir][jr] = bufmaskblurcol->L[ir][jr] / 32768.f; - guid[ir][jr] = bufcolorig->L[ir][jr] / 32768.f; - } - } - } - - if (lp.radmacol > 0.f) { - guidedFilter(guid, ble, ble, lp.radmacol * 10.f / sk, 0.001, multiThread, 4); - } - - LUTf lutTonemaskexp(65536); - calcGammaLut(lp.gammacol, lp.slomacol, lutTonemaskexp); - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < bfh; ir++) { - for (int jr = 0; jr < bfw; jr++) { - bufmaskblurcol->L[ir][jr] = lutTonemaskexp[LIM01(ble[ir][jr]) * 65536.f]; - } - } + if (lp.showmaskcolmet == 3) { + showmaske = true; } - const float radiusb = 1.f / sk; - - if (lp.showmaskcolmet == 2 || lp.enaColorMask || lp.showmaskcolmet == 3 || lp.showmaskcolmet == 5) { -#ifdef _OPENMP - #pragma omp parallel -#endif - { - gaussianBlur(bufmaskblurcol->L, bufmaskblurcol->L, bfw, bfh, radiusb); - gaussianBlur(bufmaskblurcol->a, bufmaskblurcol->a, bfw, bfh, 1.f + (0.5f * lp.radmacol) / sk); - gaussianBlur(bufmaskblurcol->b, bufmaskblurcol->b, bfw, bfh, 1.f + (0.5f * lp.radmacol) / sk); - } - - if (lp.showmaskcolmet == 0 || lp.showmaskcolmet == 1 || lp.showmaskcolmet == 2 || lp.showmaskcolmet == 4 || lp.showmaskcolmet == 5 || lp.enaColorMask) { - originalmaskcol->CopyFrom(transformed); - blendmask(lp, xstart, ystart, cx, cy, bfw, bfh, bufcolorig.get(), original, bufmaskblurcol.get(), originalmaskcol.get(), lp.blendmacol); - } else if (lp.showmaskcolmet == 3) { - showmask(lp, xstart, ystart, cx, cy, bfw, bfh, bufcolorig.get(), transformed, bufmaskblurcol.get()); - - return; - - } + if (lp.enaColorMask) { + enaMask = true; } + if (lp.showmaskcolmet == 5) { + deltaE = true; + } + + if (lp.showmaskcolmet == 2) { + modmask = true; + } + + if (lp.showmaskcolmet == 1) { + modif = true; + } + + if (lp.showmaskcolmet == 0) { + zero = true; + } + + float chrom = lp.chromacol; + float rad = lp.radmacol; + float gamma = lp.gammacol; + float slope = lp.slomacol; + float blendm = lp.blendmacol; + float lap = params->locallab.spots.at(sp).lapmaskcol; + bool pde = params->locallab.spots.at(sp).laplac; + int shado = params->locallab.spots.at(sp).shadmaskcol; + bool delt = params->locallab.spots.at(sp).deltae; + bool astool = params->locallab.spots.at(sp).toolcol; + int sco = params->locallab.spots.at(sp).scopemask; + int level_bl = params->locallab.spots.at(sp).csthresholdcol.getBottomLeft(); + int level_hl = params->locallab.spots.at(sp).csthresholdcol.getTopLeft(); + int level_br = params->locallab.spots.at(sp).csthresholdcol.getBottomRight(); + int level_hr = params->locallab.spots.at(sp).csthresholdcol.getTopRight(); + int shortcu = lp.mergemet; //params->locallab.spots.at(sp).shortc; + int lumask = params->locallab.spots.at(sp).lumask; + float strumask = 0.02f * (float) params->locallab.spots.at(sp).strumaskcol; + float conthr = 0.01f * params->locallab.spots.at(sp).conthrcol; + int tonemod = 0; + float mercol = params->locallab.spots.at(sp).mercol; + float merlucol = params->locallab.spots.at(sp).merlucol; + + if (params->locallab.spots.at(sp).toneMethod == "one") { + tonemod = 0; + } else if (params->locallab.spots.at(sp).toneMethod == "two") { + tonemod = 1; + } else if (params->locallab.spots.at(sp).toneMethod == "thr") { + tonemod = 2; + } else if (params->locallab.spots.at(sp).toneMethod == "fou") { + tonemod = 3; + } + + const int limscope = 80; + const float mindE = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + float amountcd = 0.f; + float anchorcd = 50.f; + +// if (lp.mergemet != 2) { + maskcalccol(call, false, pde, bfw, bfh, xstart, ystart, sk, cx, cy, bufcolorig.get(), bufmaskblurcol.get(), originalmaskcol.get(), original, reserved, inv, lp, + strumask, astool, + locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, lochhhmasCurve, lhhmasutili, multiThread, + enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, shado, amountcd, anchorcd, lmasklocalcurve, localmaskutili, loclmasCurvecolwav, lmasutilicolwav, + level_bl, level_hl, level_br, level_hr, + shortcu, delt, hueref, chromaref, lumaref, + maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco + ); + + if (lp.showmaskcolmet == 3) { + showmask(lumask, lp, xstart, ystart, cx, cy, bfw, bfh, bufcolorig.get(), transformed, bufmaskblurcol.get(), 0); + + return; + } + +// } + if (lp.showmaskcolmet == 4) { return; } if (lp.showmaskcolmet == 0 || lp.showmaskcolmet == 1 || lp.showmaskcolmet == 2 || lp.showmaskcolmet == 5 || lp.enaColorMask) { - float chprosl = 1.f; - if (lp.chro != 0.f) { - const float ch = (1.f + 0.01f * lp.chro) ; + //RGB Curves - if (ch <= 1.f) { - chprosl = 99.f * ch - 99.f; - } else { - constexpr float ampli = 70.f; - chprosl = CLIPCHRO(ampli * ch - ampli); + if (rgblocalcurve && localrgbutili && lp.qualcurvemet != 0) { + usergb = true; + + Imagefloat *tmpImage = nullptr; + tmpImage = new Imagefloat(bfw, bfh); + + float *rtemp = new float[bfw * bfh]; + float *gtemp = new float[bfw * bfh]; + float *btemp = new float[bfw * bfh]; + + lab2rgb(*buftemp, *tmpImage, params->icm.workingProfile); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh; y++) + for (int x = 0; x < bfw; x++) { + rtemp[y * bfw + x] = tmpImage->r(y, x); + gtemp[y * bfw + x] = tmpImage->g(y, x); + btemp[y * bfw + x] = tmpImage->b(y, x); + + assert(rgblocalcurve); + + //std + if (tonemod == 0) { + curves::setLutVal(rgblocalcurve, rtemp[y * bfw + x], gtemp[y * bfw + x], btemp[y * bfw + x]); + } else { + float r = CLIP(rtemp[y * bfw + x]); + float g = CLIP(gtemp[y * bfw + x]); + float b = CLIP(btemp[y * bfw + x]); + + //weightstd + if (tonemod == 1) { + float r1 = rgblocalcurve[r]; + float g1 = triangle(r, r1, g); + float b1 = triangle(r, r1, b); + + float g2 = rgblocalcurve[g]; + float r2 = triangle(g, g2, r); + float b2 = triangle(g, g2, b); + + float b3 = rgblocalcurve[b]; + float r3 = triangle(b, b3, r); + float g3 = triangle(b, b3, g); + r = CLIP(r1 * 0.50f + r2 * 0.25f + r3 * 0.25f); + g = CLIP (g1 * 0.25f + g2 * 0.50f + g3 * 0.25f); + b = CLIP (b1 * 0.25f + b2 * 0.25f + b3 * 0.50f); + } + + + //Luminance + if (tonemod == 2) { + float currLuminance = r * 0.2126729f + g * 0.7151521f + b * 0.0721750f; + + const float newLuminance = rgblocalcurve[currLuminance]; + currLuminance = currLuminance == 0.f ? 0.00001f : currLuminance; + const float coef = newLuminance / currLuminance; + r = LIM (r * coef, 0.f, 65535.f); + g = LIM (g * coef, 0.f, 65535.f); + b = LIM (b * coef, 0.f, 65535.f); + } + + //Film like Adobe + if (tonemod == 3) { + + if (r >= g) { + if (g > b) { + rgbtone(r, g, b, rgblocalcurve); // Case 1: r >= g > b + } else if (b > r) { + rgbtone(b, r, g, rgblocalcurve); // Case 2: b > r >= g + } else if (b > g) { + rgbtone(r, b, g, rgblocalcurve); // Case 3: r >= b > g + } else { // Case 4: r == g == b + r = rgblocalcurve[r]; + g = rgblocalcurve[g]; + b = g; + } + } else { + if (r >= b) { + rgbtone(g, r, b, rgblocalcurve); // Case 5: g > r >= b + } else if (b > g) { + rgbtone(b, g, r, rgblocalcurve); // Case 6: b > g > r + } else { + rgbtone(g, b, r, rgblocalcurve); // Case 7: g >= b > r + } + } + } + + + setUnlessOOG(rtemp[y * bfw + x], gtemp[y * bfw + x], btemp[y * bfw + x], r, g, b); + } + + + tmpImage->r(y, x) = rtemp[y * bfw + x]; + tmpImage->g(y, x) = gtemp[y * bfw + x]; + tmpImage->b(y, x) = btemp[y * bfw + x]; + } + + rgb2lab(*tmpImage, *buftemp, params->icm.workingProfile); + + delete tmpImage; + delete [] rtemp; + delete [] gtemp; + delete [] btemp; + // end rgb curves + } + + + + if (usergb && spez) {//special use of rgb curves ex : negative +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh; y++) { + const int loy = y + ystart + cy; + + for (int x = 0; x < bfw; x++) { + const int lox = x + xstart + cx; + int zone = 0; + float localFactor = 1.f; + const float achm = (float)lp.trans / 100.f; + + if (lp.shapmet == 0) { + calcTransition(lox, loy, achm, lp, zone, localFactor); + } else if (lp.shapmet == 1) { + calcTransitionrect(lox, loy, achm, lp, zone, localFactor); + } + + if (zone > 0) { + transformed->L[y + ystart][x + xstart] = buftemp->L[y][x] * localFactor + (1.f - localFactor) * original->L[y + ystart][x + xstart]; + transformed->a[y + ystart][x + xstart] = buftemp->a[y][x] * localFactor + (1.f - localFactor) * original->a[y + ystart][x + xstart]; + transformed->b[y + ystart][x + xstart] = buftemp->b[y][x] * localFactor + (1.f - localFactor) * original->b[y + ystart][x + xstart]; + } + } + } + + } + + + //others curves + + const LabImage *origptr = usergb ? buftemp.get() : bufcolorig.get(); + + bool execcolor = false; + + if (localcutili || HHutili || locallutili || lp.ligh != 0.f || lp.cont != 0 || lp.chro != 0 || LHutili || ctoning) { + execcolor = true; + } + + + if (lochhCurve && HHutili) { + for (int i = 0; i < 500; i++) { + if (lochhCurve[i] != 0.5) { + HHcurve = true; + } } } + float kd = 1.f;//correction to ctoning + kd = 10.f * 0.01f * lp.strengrid; + + //chroma slider with curve instead of linear + float satreal = lp.chro; + + DiagonalCurve color_satur({ + DCT_NURBS, + 0, 0, + 0.2, 0.2 + satreal / 250.0, + 0.6, min(1.0, 0.6 + satreal / 250.0), + 1, 1 + }); + + DiagonalCurve color_saturmoins({ + DCT_NURBS, + 0, 0, + 0.1 - satreal / 150., 0.1, + min(1.0, 0.7 - satreal / 300.), 0.7, + 1, 1 + }); + #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif for (int ir = 0; ir < bfh; ir++) for (int jr = 0; jr < bfw; jr++) { - float bufcolcalca = bufcolorig->a[ir][jr]; - float bufcolcalcb = bufcolorig->b[ir][jr]; - float bufcolcalcL = bufcolorig->L[ir][jr]; + float bufcolcalca = origptr->a[ir][jr]; + float bufcolcalcb = origptr->b[ir][jr]; + float bufcolcalcL = origptr->L[ir][jr]; - float chprocu = 1.f; + if (lp.chro != 0.f) {//slider chroma with curve DCT_NURBS + const float Chprov = sqrt(SQR(bufcolcalca) + SQR(bufcolcalcb)); + float chp = Chprov; + float2 sincosval; + sincosval.y = Chprov == 0.0f ? 1.f : bufcolcalca / Chprov; + sincosval.x = Chprov == 0.0f ? 0.f : bufcolcalcb / Chprov; + + if (lp.chro > 0.f) { + float buf = LIM01(chp / 35000.f);//35000 must be globaly good, more than 32768...anf les than !! to avoid calculation min max + buf = color_satur.getVal(buf); + buf *= 35000.f; + chp = buf; + } else { + float buf = LIM01(chp / 35000.f); + buf = color_saturmoins.getVal(buf); + buf *= 35000.f; + chp = buf; + } + + if (lp.chro == -100.f) { + chp = 0.f; + } + + bufcolcalca = chp * sincosval.y; + bufcolcalcb = chp * sincosval.x; + // const float ch = (1.f + 0.01f * lp.chro) ;//whithout curve + // bufcolcalca *= ch; + // bufcolcalcb *= ch; + } if (cclocalcurve && lp.qualcurvemet != 0 && localcutili) { // C=f(C) curve const float chromat = sqrt(SQR(bufcolcalca) + SQR(bufcolcalcb)); const float ch = cclocalcurve[chromat * adjustr] / ((chromat + 0.00001f) * adjustr); //ch between 0 and 0 50 or more - constexpr float ampli = 25.f; - chprocu = CLIPCHRO(ampli * ch - ampli); + bufcolcalca *= ch; + bufcolcalcb *= ch; } - bufchro[ir][jr] = chprosl + chprocu; + if (cllocalcurve && lp.qualcurvemet != 0 && localclutili) { // C=f(L) curve + float chromaCfactor = (cllocalcurve[bufcolcalcL * 2.f]) / (bufcolcalcL * 2.f); + bufcolcalca *= chromaCfactor; + bufcolcalcb *= chromaCfactor; + } - if (lochhCurve && HHutili && lp.qualcurvemet != 0) { + if (lclocalcurve && lp.qualcurvemet != 0 && locallcutili) { // L=f(C) curve + const float chromat = sqrt(SQR(bufcolcalca) + SQR(bufcolcalcb)); + float Lc = lclocalcurve[chromat * adjustr] / ((chromat + 0.00001f) * adjustr); + + if (Lc > 1.f) { + Lc = (Lc - 1.0f) * 0.1f + 1.0f; //reduct action + } else { + Lc = (Lc - 1.0f) * 0.3f + 1.0f; + } + + bufcolcalcL *= Lc; + } + + if (lochhCurve && HHcurve && lp.qualcurvemet != 0 && !ctoning) { // H=f(H) + const float chromat = sqrt(SQR(bufcolcalca) + SQR(bufcolcalcb)); const float hhforcurv = xatan2f(bufcolcalcb, bufcolcalca); - const float valparam = float ((lochhCurve[500.f * Color::huelab_to_huehsv2(hhforcurv)] - 0.5f)); //get H=f(H) 1.7 optimisation ! - bufhh[ir][jr] = CLIPRET(200.f * valparam); + const float valparam = float ((lochhCurve[500.f * Color::huelab_to_huehsv2(hhforcurv)] - 0.5f)); //get H=f(H) + float2 sincosval = xsincosf(valparam); + bufcolcalca = chromat * sincosval.y; + bufcolcalcb = chromat * sincosval.x; } - if (lp.ligh != 0.f || lp.cont != 0) { - calclight(bufcolcalcL, lp.ligh, bufcolcalcL, lightCurveloc); //replace L-curve + if (lp.ligh != 0.f || lp.cont != 0) {//slider luminance or slider contrast with curve + calclight(bufcolcalcL, lp.ligh, bufcolcalcL, lightCurveloc); } - if (lllocalcurve && locallutili && lp.qualcurvemet != 0) {// L=f(L) curve enhanced + if (lllocalcurve && locallutili && lp.qualcurvemet != 0) {// L=f(L) curve bufcolcalcL = 0.5f * lllocalcurve[bufcolcalcL * 2.f]; } - if (loclhCurve && LHutili && lp.qualcurvemet != 0) { + if (loclhCurve && LHutili && lp.qualcurvemet != 0) {//L=f(H) curve const float rhue = xatan2f(bufcolcalcb, bufcolcalca); float l_r = bufcolcalcL / 32768.f; //Luminance Lab in 0..1 const float valparam = loclhCurve[500.f * Color::huelab_to_huehsv2(rhue)] - 0.5f; //get l_r=f(H) @@ -8640,13 +14789,13 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } - if (ctoning) { + if (ctoning) {//color toning and direct change color if (lp.gridmet == 0) { - bufcolcalca += bufcolcalcL * a_scale + a_base; - bufcolcalcb += bufcolcalcL * b_scale + b_base; + bufcolcalca += kd * bufcolcalcL * a_scale + a_base; + bufcolcalcb += kd * bufcolcalcL * b_scale + b_base; } else if (lp.gridmet == 1) { - bufcolcalca += scaledirect * a_scale; - bufcolcalcb += scaledirect * b_scale; + bufcolcalca += kd * scaledirect * a_scale; + bufcolcalcb += kd * scaledirect * b_scale; } bufcolcalca = CLIPC(bufcolcalca); @@ -8654,43 +14803,905 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o } - // buflight[ir][jr] = CLIPRET((bufcolcalcL - bufcolorig->L[ir][jr]) / 328.f); - buf_a[ir][jr] = CLIPRET((bufcolcalca - bufcolorig->a[ir][jr]) / 328.f);; - buf_b[ir][jr] = CLIPRET((bufcolcalcb - bufcolorig->b[ir][jr]) / 328.f);; bufcolfin->L[ir][jr] = bufcolcalcL; - + bufcolfin->a[ir][jr] = bufcolcalca; + bufcolfin->b[ir][jr] = bufcolcalcb; } - if (lp.softradiuscol > 0.f) { - softproc(bufcolorig.get(), bufcolfin.get(), lp.softradiuscol, bfh, bfw, 0.0001, 0.00001, 0.0001f, sk, multiThread); - // softprocess(bufcolorig.get(), buflight, lp.softradiuscol, bfh, bfw, sk, multiThread); + + if (HHcurve && ctoning) {//not use ctoning and H(H) simultaneous but priority to ctoning + HHcurve = false; } + if (!execcolor) {//if we don't use color and light sliders, curves except RGB #ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int ir = 0; ir < bfh; ir++) - for (int jr = 0; jr < bfw; jr++) { - buflight[ir][jr] = CLIPRET((bufcolfin->L[ir][jr] - bufcolorig->L[ir][jr]) / 328.f); + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + bufcolfin->L[ir][jr] = origptr->L[ir][jr]; + bufcolfin->a[ir][jr] = origptr->a[ir][jr]; + bufcolfin->b[ir][jr] = origptr->b[ir][jr]; + } + } + + if (lp.mergemet >= 2) { //merge result with original + nottransit = true; + bufcolreserv.reset(new LabImage(bfw, bfh)); + JaggedArray lumreserv(bfw, bfh); + std::unique_ptr bufreser; + bufreser.reset(new LabImage(bfw, bfh)); + + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + lumreserv[y][x] = 32768.f - reserved->L[y + ystart][x + xstart]; + bufreser->L[y][x] = reserved->L[y + ystart][x + xstart]; + bufreser->a[y][x] = reserved->a[y + ystart][x + xstart]; + bufreser->b[y][x] = reserved->b[y + ystart][x + xstart]; + + if (lp.mergemet == 2) { + bufcolreserv->L[y][x] = reserved->L[y + ystart][x + xstart]; + bufcolreserv->a[y][x] = reserved->a[y + ystart][x + xstart]; + bufcolreserv->b[y][x] = reserved->b[y + ystart][x + xstart]; + } else if (lp.mergemet == 3) { + bufcolreserv->L[y][x] = lastorig->L[y + ystart][x + xstart]; + bufcolreserv->a[y][x] = lastorig->a[y + ystart][x + xstart]; + bufcolreserv->b[y][x] = lastorig->b[y + ystart][x + xstart]; + } else if (lp.mergemet == 4) { + if (ctoningmerg) { + bufcolreserv->L[y][x] = merlucol * 327.68f; + bufcolreserv->a[y][x] = 9.f * scaledirect * a_scalemerg; + bufcolreserv->b[y][x] = 9.f * scaledirect * b_scalemerg; + } + } + } } +// test for write text with Cairo November 2019 + /* + //test for write text , it compile... but does nothing + // why ?? is arial or Purisa found (I tried others) or I missed something or poke ?? or tmImageorig or ?? + + locImage = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, bfw, bfh); + Cairo::RefPtr cr = Cairo::Context::create(locImage); + cr->set_source_rgb(0.9, 0.9, 0.9);//white + cr->paint(); + cr->select_font_face("Purisa", Cairo::FontSlant::FONT_SLANT_NORMAL, Cairo::FontWeight::FONT_WEIGHT_BOLD); + cr->set_font_size(50); + cr->set_source_rgb(0.3, 0.3, 0.3);//grey + + cr->move_to(0, 0); + cr->show_text("Coucou"); + Imagefloat *tmpImageorig = nullptr; + tmpImageorig = new Imagefloat(bfw, bfh); + lab2rgb(*bufcolreserv, *tmpImageorig, params->icm.workingProfile); + // tmpImageorig->normalizeFloatTo1(); + locImage->flush(); + unsigned char *locData = locImage->get_data(); + + for (int y = 0; y < bfh ; y++) { + + for (int x = 0; x < bfw; x++) { + unsigned char *dst = locData + (y * bfw + x) * 4;//why 4 ? + // printf("dst=%d ", *dst); + double r = tmpImageorig->r(y, x); + double g = tmpImageorig->g(y, x); + double b = tmpImageorig->b(y, x); + + //perhaps that or whithout 255 or ?? + *(dst++) = (unsigned char)(r); + tmpImageorig->r(y, x) = 255.f * *dst; + *(dst++) = (unsigned char)(g); + tmpImageorig->g(y, x) = 255.f * *dst; + *(dst++) = (unsigned char)(b); + tmpImageorig->b(y, x) = 255.f * *dst; + + //perhaps ?? + // rtengine::poke01_d(dst, r, g, b); + // tmpImageorig->r(y, x) = *(dst++); + // tmpImageorig->g(y, x) = *(dst++); + // tmpImageorig->b(y, x) = *(dst++); + + } + } + + locImage->mark_dirty(); + + // tmpImageorig->normalizeFloatTo65535(); + rgb2lab(*tmpImageorig, *bufcolreserv, params->icm.workingProfile); + delete tmpImageorig; + */ + + if (lp.strcol != 0.f) { + struct grad_params gp; + calclocalGradientParams(lp, gp, ystart, xstart, bfw, bfh, 3); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + double factor = 1.0; + factor = ImProcFunctions::calcGradientFactor(gp, jr, ir); + bufcolfin->L[ir][jr] *= factor; + } + } + + if (lp.strcolab != 0.f) { + struct grad_params gpab; + calclocalGradientParams(lp, gpab, ystart, xstart, bfw, bfh, 4); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + double factor = 1.0; + factor = ImProcFunctions::calcGradientFactor(gpab, jr, ir); + bufcolfin->a[ir][jr] *= factor; + bufcolfin->b[ir][jr] *= factor; + } + } + + if (lp.strcolh != 0.f) { + struct grad_params gph; + calclocalGradientParams(lp, gph, ystart, xstart, bfw, bfh, 6); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + double factor = 1.0; + factor = ImProcFunctions::calcGradientFactor(gph, jr, ir); + float aa = bufcolfin->a[ir][jr]; + float bb = bufcolfin->b[ir][jr]; + float chrm = sqrt(SQR(aa) + SQR(bb)); + float HH = xatan2f(bb, aa); + + float newhr = 0.f; + float cor = 0.f; + + if (factor < 1.f) { + cor = - 2.5f * (1.f - factor); + } else if (factor > 1.f) { + cor = 0.03f * (factor - 1.f); + } + + newhr = HH + cor; + + if (newhr > rtengine::RT_PI_F) { + newhr -= 2 * rtengine::RT_PI_F; + } else if (newhr < -rtengine::RT_PI_F) { + newhr += 2 * rtengine::RT_PI_F; + } + + float2 sincosval = xsincosf(newhr); + bufcolfin->a[ir][jr] = CLIPC(chrm * sincosval.y); + bufcolfin->b[ir][jr] = CLIPC(chrm * sincosval.x); + } + } + + JaggedArray blend(bfw, bfh); + buildBlendMask(lumreserv, blend, bfw, bfh, conthr); + float rm = 20.f / sk; + + if (rm > 0) { + float **mb = blend; + gaussianBlur(mb, mb, bfw, bfh, rm); + } + + std::unique_ptr> rdEBuffer(new JaggedArray(bfw, bfh)); + float** rdE = *(rdEBuffer.get()); + + deltaEforMask(rdE, bfw, bfh, bufreser.get(), hueref, chromaref, lumaref, maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, mercol, lp.balance, lp.balanceh); + + if (lp.mergecolMethod == 0) { //normal + + if (lp.mergemet == 4) { + bufprov.reset(new LabImage(bfw, bfh)); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + rdE[y][x] *= SQR(rdE[y][x]); + bufprov->L[y][x] = (1.f - rdE[y][x]) * bufcolfin->L[y][x] + (rdE[y][x]) * bufcolreserv->L[y][x]; + bufprov->a[y][x] = (1.f - rdE[y][x]) * bufcolfin->a[y][x] + (rdE[y][x]) * bufcolreserv->a[y][x]; + bufprov->b[y][x] = (1.f - rdE[y][x]) * bufcolfin->b[y][x] + (rdE[y][x]) * bufcolreserv->b[y][x]; + + bufcolfin->L[y][x] = (1.f - lp.opacol) * bufcolfin->L[y][x] + (lp.opacol) * bufprov->L[y][x]; + bufcolfin->a[y][x] = (1.f - lp.opacol) * bufcolfin->a[y][x] + (lp.opacol) * bufprov->a[y][x]; + bufcolfin->b[y][x] = (1.f - lp.opacol) * bufcolfin->b[y][x] + (lp.opacol) * bufprov->b[y][x]; + } + } + } else { + bufprov.reset(new LabImage(bfw, bfh)); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + bufprov->L[y][x] = (rdE[y][x]) * bufcolfin->L[y][x] + (1.f - rdE[y][x]) * bufcolreserv->L[y][x]; + bufprov->a[y][x] = (rdE[y][x]) * bufcolfin->a[y][x] + (1.f - rdE[y][x]) * bufcolreserv->a[y][x]; + bufprov->b[y][x] = (rdE[y][x]) * bufcolfin->b[y][x] + (1.f - rdE[y][x]) * bufcolreserv->b[y][x]; + + bufcolfin->L[y][x] = (lp.opacol) * bufprov->L[y][x] + (1.f - lp.opacol) * bufcolreserv->L[y][x]; + bufcolfin->a[y][x] = (lp.opacol) * bufprov->a[y][x] + (1.f - lp.opacol) * bufcolreserv->a[y][x]; + bufcolfin->b[y][x] = (lp.opacol) * bufprov->b[y][x] + (1.f - lp.opacol) * bufcolreserv->b[y][x]; + } + } + + } + + + if (conthr > 0.f && lp.mergemet != 4) { + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + bufcolfin->L[y][x] = intp((blend[y][x]), bufcolfin->L[y][x], bufreser->L[y][x]); + bufcolfin->a[y][x] = intp((blend[y][x]), bufcolfin->a[y][x], bufreser->a[y][x]); + bufcolfin->b[y][x] = intp((blend[y][x]), bufcolfin->b[y][x], bufreser->b[y][x]); + } + } + } + } + + + if (lp.mergecolMethod > 16) { //hue sat chroma luma + std::unique_ptr buftemp; + buftemp.reset(new LabImage(bfw, bfh)); + bufprov.reset(new LabImage(bfw, bfh)); + + if (lp.mergemet == 4) { + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + rdE[y][x] *= SQR(rdE[y][x]); + bufprov->L[y][x] = (1.f - rdE[y][x]) * bufcolfin->L[y][x] + (rdE[y][x]) * bufcolreserv->L[y][x]; + bufprov->a[y][x] = (1.f - rdE[y][x]) * bufcolfin->a[y][x] + (rdE[y][x]) * bufcolreserv->a[y][x]; + bufprov->b[y][x] = (1.f - rdE[y][x]) * bufcolfin->b[y][x] + (rdE[y][x]) * bufcolreserv->b[y][x]; + } + } + } else { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + bufprov->L[y][x] = (rdE[y][x]) * bufcolfin->L[y][x] + (1.f - rdE[y][x]) * bufcolreserv->L[y][x]; + bufprov->a[y][x] = (rdE[y][x]) * bufcolfin->a[y][x] + (1.f - rdE[y][x]) * bufcolreserv->a[y][x]; + bufprov->b[y][x] = (rdE[y][x]) * bufcolfin->b[y][x] + (1.f - rdE[y][x]) * bufcolreserv->b[y][x]; + } + } + } + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float huefin = xatan2f(bufprov->b[y][x], bufprov->a[y][x]); + float hueres = xatan2f(bufcolreserv->b[y][x], bufcolreserv->a[y][x]); + float chrofin = sqrt(SQR(bufprov->a[y][x]) + SQR(bufprov->b[y][x])); + float chrores = sqrt(SQR(bufcolreserv->a[y][x]) + SQR(bufcolreserv->b[y][x])); + float lumfin = bufprov->L[y][x]; + float lumres = bufcolreserv->L[y][x]; + + if (lp.mergecolMethod == 17) { + float2 sincosval1 = xsincosf(huefin); + buftemp->a[y][x] = chrores * sincosval1.y; + buftemp->b[y][x] = chrores * sincosval1.x; + buftemp->L[y][x] = lumres; + } else if (lp.mergecolMethod == 18) { + float2 sincosval2 = xsincosf(hueres); + buftemp->a[y][x] = chrofin * sincosval2.y; + buftemp->b[y][x] = chrofin * sincosval2.x; + buftemp->L[y][x] = lumres; + } else if (lp.mergecolMethod == 19) { + float2 sincosval3 = xsincosf(huefin); + buftemp->a[y][x] = chrofin * sincosval3.y; + buftemp->b[y][x] = chrofin * sincosval3.x; + buftemp->L[y][x] = lumres; + } else if (lp.mergecolMethod == 20) { + float2 sincosval4 = xsincosf(hueres); + buftemp->a[y][x] = chrores * sincosval4.y; + buftemp->b[y][x] = chrores * sincosval4.x; + buftemp->L[y][x] = lumfin; + } + + if (lp.mergemet == 4) { + bufcolfin->L[y][x] = (1.f - lp.opacol) * bufcolfin->L[y][x] + (lp.opacol) * bufprov->L[y][x]; + bufcolfin->a[y][x] = (1.f - lp.opacol) * bufcolfin->a[y][x] + (lp.opacol) * bufprov->a[y][x]; + bufcolfin->b[y][x] = (1.f - lp.opacol) * bufcolfin->b[y][x] + (lp.opacol) * bufprov->b[y][x]; + } else { + bufcolfin->L[y][x] = (lp.opacol) * bufprov->L[y][x] + (1.f - lp.opacol) * bufcolreserv->L[y][x]; + bufcolfin->a[y][x] = (lp.opacol) * bufprov->a[y][x] + (1.f - lp.opacol) * bufcolreserv->a[y][x]; + bufcolfin->b[y][x] = (lp.opacol) * bufprov->b[y][x] + (1.f - lp.opacol) * bufcolreserv->b[y][x]; + } + } + } + + if (conthr > 0.f && lp.mergemet != 4) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + bufcolfin->L[y][x] = intp(blend[y][x], bufcolfin->L[y][x], bufcolreserv->L[y][x]); + bufcolfin->a[y][x] = intp(blend[y][x], bufcolfin->a[y][x], bufcolreserv->a[y][x]); + bufcolfin->b[y][x] = intp(blend[y][x], bufcolfin->b[y][x], bufcolreserv->b[y][x]); + } + } + } + + + } + + + if (lp.mergecolMethod > 0 && lp.mergecolMethod <= 16) { + //first deltaE +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + bufcolfin->L[y][x] = (rdE[y][x]) * bufcolfin->L[y][x] + (1.f - rdE[y][x]) * bufcolreserv->L[y][x]; + bufcolfin->a[y][x] = (rdE[y][x]) * bufcolfin->a[y][x] + (1.f - rdE[y][x]) * bufcolreserv->a[y][x]; + bufcolfin->b[y][x] = (rdE[y][x]) * bufcolfin->b[y][x] + (1.f - rdE[y][x]) * bufcolreserv->b[y][x]; + } + } + + //prepare RGB values in 0 1(or more)for current image and reserved + Imagefloat *tmpImageorig = nullptr; + tmpImageorig = new Imagefloat(bfw, bfh); + lab2rgb(*bufcolfin, *tmpImageorig, params->icm.workingProfile); + tmpImageorig->normalizeFloatTo1(); + + Imagefloat *tmpImagereserv = nullptr; + tmpImagereserv = new Imagefloat(bfw, bfh); + lab2rgb(*bufcolreserv, *tmpImagereserv, params->icm.workingProfile); + tmpImagereserv->normalizeFloatTo1(); + + float minR = tmpImagereserv->r(0, 0); + float maxR = minR; +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxR) reduction(min:minR) schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) { + for (int jr = 0; jr < bfw; jr++) { + minR = rtengine::min(minR, tmpImagereserv->r(ir, jr)); + maxR = rtengine::max(maxR, tmpImagereserv->r(ir, jr)); + } + } + + float minG = tmpImagereserv->g(0, 0); + float maxG = minG; +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxG) reduction(min:minG) schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) { + for (int jr = 0; jr < bfw; jr++) { + minG = rtengine::min(minG, tmpImagereserv->g(ir, jr)); + maxG = rtengine::max(maxG, tmpImagereserv->g(ir, jr)); + } + } + + float minB = tmpImagereserv->b(0, 0); + float maxB = minB; +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxB) reduction(min:minB) schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) { + for (int jr = 0; jr < bfw; jr++) { + minB = rtengine::min(minB, tmpImagereserv->b(ir, jr)); + maxB = rtengine::max(maxB, tmpImagereserv->b(ir, jr)); + } + } + + + + //various combinaison substrct, multiply, difference, etc + if (lp.mergecolMethod == 1) { //substract +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) {//LIM(x 0 2) 2 arbitral value but limit... + for (int x = 0; x < bfw; x++) { + tmpImageorig->r(y, x) = lp.opacol * ((tmpImageorig->r(y, x) - tmpImagereserv->r(y, x))) + (1.f - lp.opacol) * tmpImageorig->r(y, x); + tmpImageorig->g(y, x) = lp.opacol * ((tmpImageorig->g(y, x) - tmpImagereserv->g(y, x))) + (1.f - lp.opacol) * tmpImageorig->g(y, x); + tmpImageorig->b(y, x) = lp.opacol * ((tmpImageorig->b(y, x) - tmpImagereserv->b(y, x))) + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 2) { //difference +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + tmpImageorig->r(y, x) = lp.opacol * (fabs(tmpImageorig->r(y, x) - tmpImagereserv->r(y, x))) + (1.f - lp.opacol) * tmpImageorig->r(y, x); + tmpImageorig->g(y, x) = lp.opacol * (fabs(tmpImageorig->g(y, x) - tmpImagereserv->g(y, x))) + (1.f - lp.opacol) * tmpImageorig->g(y, x); + tmpImageorig->b(y, x) = lp.opacol * (fabs(tmpImageorig->b(y, x) - tmpImagereserv->b(y, x))) + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 3) { //multiply +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + tmpImageorig->r(y, x) = lp.opacol * tmpImageorig->r(y, x) * tmpImagereserv->r(y, x) + (1.f - lp.opacol) * tmpImageorig->r(y, x); + tmpImageorig->g(y, x) = lp.opacol * tmpImageorig->g(y, x) * tmpImagereserv->g(y, x) + (1.f - lp.opacol) * tmpImageorig->g(y, x); + tmpImageorig->b(y, x) = lp.opacol * tmpImageorig->b(y, x) * tmpImagereserv->b(y, x) + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 4) { //addition +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + tmpImageorig->r(y, x) = lp.opacol * (tmpImageorig->r(y, x) + tmpImagereserv->r(y, x)) + (1.f - lp.opacol) * tmpImageorig->r(y, x); + tmpImageorig->g(y, x) = lp.opacol * (tmpImageorig->g(y, x) + tmpImagereserv->g(y, x)) + (1.f - lp.opacol) * tmpImageorig->g(y, x); + tmpImageorig->b(y, x) = lp.opacol * (tmpImageorig->b(y, x) + tmpImagereserv->b(y, x)) + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 5) { //divide +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + tmpImageorig->r(y, x) = lp.opacol * (tmpImageorig->r(y, x) / (tmpImagereserv->r(y, x) + 0.00001f)) + (1.f - lp.opacol) * tmpImageorig->r(y, x); + tmpImageorig->g(y, x) = lp.opacol * (tmpImageorig->g(y, x) / (tmpImagereserv->g(y, x) + 0.00001f)) + (1.f - lp.opacol) * tmpImageorig->g(y, x); + tmpImageorig->b(y, x) = lp.opacol * (tmpImageorig->b(y, x) / (tmpImagereserv->b(y, x) + 0.00001f)) + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 6) { //soft light as Photoshop +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float a = tmpImageorig->r(y, x); + float b = tmpImagereserv->r(y, x); + softlig(a, b, minR, maxR); + tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); + a = tmpImageorig->g(y, x); + b = tmpImagereserv->g(y, x); + softlig(a, b, minG, maxG); + tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); + a = tmpImageorig->b(y, x); + b = tmpImagereserv->b(y, x); + softlig(a, b, minB, maxB); + tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 7) { //soft light as illusions.hu +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float a = LIM01(tmpImageorig->r(y, x)); + float b = tmpImagereserv->r(y, x); + softlig2(a, b); + tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); + a = LIM01(tmpImageorig->g(y, x)); + b = tmpImagereserv->g(y, x); + softlig2(a, b); + tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); + a = LIM01(tmpImageorig->b(y, x)); + b = tmpImagereserv->b(y, x); + softlig2(a, b); + tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 8) { //soft light as W3C +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float a = LIM01(tmpImageorig->r(y, x)); + float b = tmpImagereserv->r(y, x); + softlig3(a, b); + tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); + a = LIM01(tmpImageorig->g(y, x)); + b = tmpImagereserv->g(y, x); + softlig3(a, b); + tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); + a = LIM01(tmpImageorig->b(y, x)); + b = tmpImagereserv->b(y, x); + softlig3(a, b); + tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 9) { //hard light overlay (float &b, float &a) +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float a = tmpImageorig->r(y, x); + float b = tmpImagereserv->r(y, x); + overlay(b, a, minR, maxR); + tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); + a = tmpImageorig->g(y, x); + b = tmpImagereserv->g(y, x); + overlay(b, a, minG, maxG); + tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); + a = tmpImageorig->b(y, x); + b = tmpImagereserv->b(y, x); + overlay(b, a, minB, maxB); + tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 10) { //overlay overlay(float &a, float &b) +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float a = tmpImageorig->r(y, x); + float b = tmpImagereserv->r(y, x); + overlay(a, b, minR, maxR); + tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); + a = tmpImageorig->g(y, x); + b = tmpImagereserv->g(y, x); + overlay(a, b, minG, maxG); + tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); + a = tmpImageorig->b(y, x); + b = tmpImagereserv->b(y, x); + overlay(a, b, minB, maxB); + tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 11) { //screen screen (float &a, float &b) +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float a = tmpImageorig->r(y, x); + float b = tmpImagereserv->r(y, x); + screen(a, b, maxR); + tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); + a = tmpImageorig->g(y, x); + b = tmpImagereserv->g(y, x); + screen(a, b, maxG); + tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); + a = tmpImageorig->b(y, x); + b = tmpImagereserv->b(y, x); + screen(a, b, maxB); + tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 12) { //darken only +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + tmpImageorig->r(y, x) = lp.opacol * std::min(tmpImageorig->r(y, x), tmpImagereserv->r(y, x)) + (1.f - lp.opacol) * tmpImageorig->r(y, x); + tmpImageorig->g(y, x) = lp.opacol * std::min(tmpImageorig->g(y, x), tmpImagereserv->g(y, x)) + (1.f - lp.opacol) * tmpImageorig->g(y, x); + tmpImageorig->b(y, x) = lp.opacol * std::min(tmpImageorig->b(y, x), tmpImagereserv->b(y, x)) + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 13) { //lighten only +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + tmpImageorig->r(y, x) = lp.opacol * std::max(tmpImageorig->r(y, x), tmpImagereserv->r(y, x)) + (1.f - lp.opacol) * tmpImageorig->r(y, x); + tmpImageorig->g(y, x) = lp.opacol * std::max(tmpImageorig->g(y, x), tmpImagereserv->g(y, x)) + (1.f - lp.opacol) * tmpImageorig->g(y, x); + tmpImageorig->b(y, x) = lp.opacol * std::max(tmpImageorig->b(y, x), tmpImagereserv->b(y, x)) + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 14) { //exclusion exclusion (float &a, float &b) +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float a = tmpImageorig->r(y, x); + float b = tmpImagereserv->r(y, x); + exclusion(a, b); + tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); + a = tmpImageorig->g(y, x); + b = tmpImagereserv->g(y, x); + exclusion(a, b); + tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); + a = tmpImageorig->b(y, x); + b = tmpImagereserv->b(y, x); + exclusion(a, b); + tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + + } else if (lp.mergecolMethod == 15) { //Color burn +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float a = LIM01(tmpImageorig->r(y, x)); + float b = LIM01(tmpImagereserv->r(y, x)); + colburn(a, b); + tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); + a = LIM01(tmpImageorig->g(y, x)); + b = LIM01(tmpImagereserv->g(y, x)); + colburn(a, b); + tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); + a = LIM01(tmpImageorig->b(y, x)); + b = LIM01(tmpImagereserv->b(y, x)); + colburn(a, b); + tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 16) { //Color dodge +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float a = LIM01(tmpImageorig->r(y, x)); + float b = LIM01(tmpImagereserv->r(y, x)); + coldodge(a, b); + tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); + a = LIM01(tmpImageorig->g(y, x)); + b = LIM01(tmpImagereserv->g(y, x)); + coldodge(a, b); + tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); + a = LIM01(tmpImageorig->b(y, x)); + b = LIM01(tmpImagereserv->b(y, x)); + coldodge(a, b); + tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } + + tmpImageorig->normalizeFloatTo65535(); + rgb2lab(*tmpImageorig, *bufcolfin, params->icm.workingProfile); + + delete tmpImageorig; + delete tmpImagereserv; + + if (conthr > 0.f && lp.mergemet != 4) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + bufcolfin->L[y][x] = intp(blend[y][x], bufcolfin->L[y][x], bufcolreserv->L[y][x]); + bufcolfin->a[y][x] = intp(blend[y][x], bufcolfin->a[y][x], bufcolreserv->a[y][x]); + bufcolfin->b[y][x] = intp(blend[y][x], bufcolfin->b[y][x], bufcolreserv->b[y][x]); + } + } + } + + bool fordiff = false; + + if (lp.mergecolMethod == 2 && fordiff) {//display differences whithout deltaE...in case of generally disabled +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh; y++) { + const int loy = y + ystart + cy; + + for (int x = 0; x < bfw; x++) { + const int lox = x + xstart + cx; + int zone = 0; + float localFactor = 1.f; + const float achm = (float)lp.trans / 100.f; + + if (lp.shapmet == 0) { + calcTransition(lox, loy, achm, lp, zone, localFactor); + } else if (lp.shapmet == 1) { + calcTransitionrect(lox, loy, achm, lp, zone, localFactor); + } + + if (zone > 0) {//normal + transformed->L[y + ystart][x + xstart] = bufcolfin->L[y][x]; + transformed->a[y + ystart][x + xstart] = bufcolfin->a[y][x]; + transformed->b[y + ystart][x + xstart] = bufcolfin->b[y][x]; + } + } + } + + return; + } + + + } + + if (lp.softradiuscol > 0.f) { + softproc(bufcolreserv.get(), bufcolfin.get(), lp.softradiuscol, bfh, bfw, 0.0001, 0.00001, 0.1f, sk, multiThread, 1); + } + + + + if (nottransit) { + //new 9 december 2019 + transit_shapedetect2(call, 0, bufcolreserv.get(), bufcolfin.get(), originalmaskcol.get(), hueref, chromaref, lumaref, sobelref, meansob, blend2, lp, original, transformed, cx, cy, sk); + /* + Befor 12 2019 + //special only transition + //may be we can add preview... + #ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) + #endif + + for (int y = 0; y < bfh; y++) { + const int loy = y + ystart + cy; + + for (int x = 0; x < bfw; x++) { + const int lox = x + xstart + cx; + int zone = 0; + float localFactor = 1.f; + const float achm = (float)lp.trans / 100.f; + + if (lp.shapmet == 0) { + calcTransition(lox, loy, achm, lp, zone, localFactor); + } else if (lp.shapmet == 1) { + calcTransitionrect(lox, loy, achm, lp, zone, localFactor); + } + + if (zone > 0) { + transformed->L[y + ystart][x + xstart] = bufcolfin->L[y][x] * localFactor + (1.f - localFactor) * reserved->L[y + ystart][x + xstart]; + transformed->a[y + ystart][x + xstart] = bufcolfin->a[y][x] * localFactor + (1.f - localFactor) * reserved->a[y + ystart][x + xstart]; + transformed->b[y + ystart][x + xstart] = bufcolfin->b[y][x] * localFactor + (1.f - localFactor) * reserved->b[y + ystart][x + xstart]; + } + } + } + + */ + } + + + } + + + if (!nottransit) { +//gradient + + if (lp.strcol != 0.f) { + struct grad_params gp; + calclocalGradientParams(lp, gp, ystart, xstart, bfw, bfh, 3); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + double factor = 1.0; + factor = ImProcFunctions::calcGradientFactor(gp, jr, ir); + bufcolfin->L[ir][jr] *= factor; + } + } + + if (lp.strcolab != 0.f) { + struct grad_params gpab; + calclocalGradientParams(lp, gpab, ystart, xstart, bfw, bfh, 5); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + double factor = 1.0; + factor = ImProcFunctions::calcGradientFactor(gpab, jr, ir); + bufcolfin->a[ir][jr] *= factor; + bufcolfin->b[ir][jr] *= factor; + } + } + + if (lp.strcolh != 0.f) { + struct grad_params gph; + calclocalGradientParams(lp, gph, ystart, xstart, bfw, bfh, 6); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + double factor = 1.0; + factor = ImProcFunctions::calcGradientFactor(gph, jr, ir); + float aa = bufcolfin->a[ir][jr]; + float bb = bufcolfin->b[ir][jr]; + float chrm = sqrt(SQR(aa) + SQR(bb)); + float HH = xatan2f(bb, aa); + + float newhr = 0.f; + float cor = 0.f; + + if (factor < 1.f) { + cor = - 2.5f * (1.f - factor); + } else if (factor > 1.f) { + cor = 0.03f * (factor - 1.f); + } + + newhr = HH + cor; + + if (newhr > rtengine::RT_PI_F) { + newhr -= 2 * rtengine::RT_PI_F; + } else if (newhr < -rtengine::RT_PI_F) { + newhr += 2 * rtengine::RT_PI_F; + } + + float2 sincosval = xsincosf(newhr); + bufcolfin->a[ir][jr] = CLIPC(chrm * sincosval.y); + bufcolfin->b[ir][jr] = CLIPC(chrm * sincosval.x); + } + } + + + if (lp.softradiuscol > 0.f) { + softproc(bufcolorig.get(), bufcolfin.get(), lp.softradiuscol, bfh, bfw, 0.0001, 0.00001, 0.1f, sk, multiThread, 1); + } + + transit_shapedetect2(call, 0, bufcolorig.get(), bufcolfin.get(), originalmaskcol.get(), hueref, chromaref, lumaref, sobelref, meansob, blend2, lp, original, transformed, cx, cy, sk); + + } + } - float **temp = nullptr; - - if (blend) { - temp = blend2; + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); } - transit_shapedetect(0, bufcolorig.get(), originalmaskcol.get(), buflight, bufchro, buf_a, buf_b, bufhh, HHutili, hueref, chromaref, lumaref, sobelref, meansob, temp, lp, original, transformed, cx, cy, sk); - } } } //inverse - else if (lp.inv && (lp.chro != 0 || lp.ligh != 0 || exlocalcurve) && lp.colorena) { + else if (lp.inv && (lp.chro != 0 || lp.ligh != 0 || exlocalcurve || lp.showmaskcolmetinv == 0 || lp.enaColorMaskinv) && lp.colorena) { float adjustr = 1.0f; //adapt chroma to working profile @@ -8710,7 +15721,102 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o adjustr = 1.8f; } - InverseColorLight_Local(sp, 0, lp, lightCurveloc, hltonecurveloc, shtonecurveloc, tonecurveloc, exlocalcurve, cclocalcurve, adjustr, localcutili, lllocalcurve, locallutili, original, transformed, cx, cy, hueref, chromaref, lumaref, sk); + std::unique_ptr bufmaskblurcol; + std::unique_ptr originalmaskcol; + std::unique_ptr bufcolorig; + int GW = transformed->W; + int GH = transformed->H; + bufcolorig.reset(new LabImage(GW, GH)); + + if (lp.enaColorMaskinv || lp.showmaskcolmetinv == 1) { + bufmaskblurcol.reset(new LabImage(GW, GH, true)); + originalmaskcol.reset(new LabImage(GW, GH)); + } + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < GH ; y++) { + for (int x = 0; x < GW; x++) { + bufcolorig->L[y][x] = original->L[y][x]; + } + } + + int inv = 1; + bool showmaske = false; + bool enaMask = false; + bool deltaE = false; + bool modmask = false; + bool zero = false; + bool modif = false; + + if (lp.showmaskcolmetinv == 1) { + showmaske = true; + } + + if (lp.enaColorMaskinv) { + enaMask = true; + } + + if (lp.showmaskcolmetinv == 0) { + zero = true; + } + + float chrom = lp.chromacol; + float rad = lp.radmacol; + float gamma = lp.gammacol; + float slope = lp.slomacol; + float blendm = lp.blendmacol; + float lap = params->locallab.spots.at(sp).lapmaskcol; + bool pde = params->locallab.spots.at(sp).laplac; + int shado = params->locallab.spots.at(sp).shadmaskcol; + int level_bl = params->locallab.spots.at(sp).csthresholdcol.getBottomLeft(); + int level_hl = params->locallab.spots.at(sp).csthresholdcol.getTopLeft(); + int level_br = params->locallab.spots.at(sp).csthresholdcol.getBottomRight(); + int level_hr = params->locallab.spots.at(sp).csthresholdcol.getTopRight(); + // bool delt = params->locallab.spots.at(sp).deltae; + bool delt = false; + bool astool = params->locallab.spots.at(sp).toolcol; + int sco = params->locallab.spots.at(sp).scopemask; + int shortcu = lp.mergemet; //params->locallab.spots.at(sp).shortc; + int lumask = params->locallab.spots.at(sp).lumask; + float strumask = 0.02f * (float) params->locallab.spots.at(sp).strumaskcol; + + const int limscope = 80; + const float mindE = 2.f + MINSCOPE * sco * lp.thr; + const float maxdE = 5.f + MAXSCOPE * sco * (1 + 0.1f * lp.thr); + const float mindElim = 2.f + MINSCOPE * limscope * lp.thr; + const float maxdElim = 5.f + MAXSCOPE * limscope * (1 + 0.1f * lp.thr); + float amountcd = 0.f; + float anchorcd = 50.f; + + maskcalccol(call, false, pde, GW, GH, 0, 0, sk, cx, cy, bufcolorig.get(), bufmaskblurcol.get(), originalmaskcol.get(), original, reserved, inv, lp, + strumask, astool, + locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, lochhhmasCurve, lhhmasutili, multiThread, + enaMask, showmaske, deltaE, modmask, zero, modif, chrom, rad, lap, gamma, slope, blendm, shado, amountcd, anchorcd, lmasklocalcurve, localmaskutili, loclmasCurvecolwav, lmasutilicolwav, + level_bl, level_hl, level_br, level_hr, + shortcu, delt, hueref, chromaref, lumaref, + maxdE, mindE, maxdElim, mindElim, lp.iterat, limscope, sco + ); + + + if (lp.showmaskcolmetinv == 1) { + showmask(lumask, lp, 0, 0, cx, cy, GW, GH, bufcolorig.get(), transformed, bufmaskblurcol.get(), inv); + + return; + } + + if (lp.showmaskcolmetinv == 0 || lp.enaColorMaskinv) { + InverseColorLight_Local(false, false, sp, 0, lp, originalmaskcol.get(), lightCurveloc, hltonecurveloc, shtonecurveloc, tonecurveloc, exlocalcurve, cclocalcurve, adjustr, localcutili, lllocalcurve, locallutili, original, transformed, cx, cy, hueref, chromaref, lumaref, sk); + + if (params->locallab.spots.at(sp).recurs) { + original->CopyFrom(transformed); + float avge; + calc_ref(sp, original, transformed, 0, 0, original->W, original->H, sk, huerefblur, chromarefblur, lumarefblur, hueref, chromaref, lumaref, sobelref, avge, locwavCurveden, locwavdenutili); + } + + } } // Gamut and Munsell control - very important do not desactivated to avoid crash diff --git a/rtengine/ipresize.cc b/rtengine/ipresize.cc index 823beb23e..b9e234b63 100644 --- a/rtengine/ipresize.cc +++ b/rtengine/ipresize.cc @@ -14,16 +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 . */ #include "improcfun.h" #include "alignedbuffer.h" +#include "imagefloat.h" +#include "labimage.h" #include "opthelper.h" #include "rt_math.h" #include "procparams.h" -#include "sleef.c" +#include "sleef.h" //#define PROFILE @@ -186,8 +188,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 +270,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 d1a37ca5c..6bc9834e3 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 @@ -41,24 +41,28 @@ #include #include +#include "color.h" +#include "curves.h" #include "gauss.h" #include "improcfun.h" +#include "labimage.h" #include "median.h" #include "opthelper.h" #include "procparams.h" #include "rawimagesource.h" #include "rtengine.h" +#include "shmap.h" +#define BENCHMARK #include "StopWatch.h" #include "guidedfilter.h" #define clipretinex( val, minv, maxv ) (( val = (val < minv ? minv : val ) ) > maxv ? maxv : val ) #define CLIPLOC(x) LIM(x,0.f,32767.f) #define CLIPC(a) LIM(a, -42000.f, 42000.f) // limit a and b to 130 probably enough ? -#define CLIPMAX(x) LIM(x,0.f,500000.f) namespace { - + void calcGammaLut(double gamma, double ts, LUTf &gammaLut) { double pwr = 1.0 / gamma; @@ -93,7 +97,6 @@ void calcGammaLut(double gamma, double ts, LUTf &gammaLut) } } - void retinex_scales(float* scales, int nscales, int mode, int s, float high) { if (s < 3) { @@ -180,363 +183,430 @@ void mean_stddv2(float **dst, float &mean, float &stddv, int W_L, int H_L, float namespace rtengine { -extern const Settings* settings; - -void RawImageSource::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 RawImageSource::MSR(float** luminance, float** originalLuminance, float **exLuminance, const LUTf& mapcurve, bool mapcontlutili, int width, int height, const procparams::RetinexParams &deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax) { + BENCHFUN - if (deh.enabled) {//enabled - float maxtr, mintr; - constexpr float eps = 2.f; - bool useHsl = deh.retinexcolorspace == "HSLLOG"; - bool useHslLin = deh.retinexcolorspace == "HSLLIN"; - float offse = (float) deh.offs; //def = 0 not use - int iter = deh.iter; - int gradient = deh.scal; - int scal = 3;//disabled scal - int nei = (int)(2.8f * deh.neigh); //def = 220 - float vart = (float)deh.vart / 100.f;//variance - float gradvart = (float)deh.grad; - float gradstr = (float)deh.grads; - float strength = (float) deh.str / 100.f; // Blend with original L channel data - float limD = (float) deh.limd; - limD = pow(limD, 1.7f); //about 2500 enough - limD *= useHslLin ? 10.f : 1.f; - float ilimD = 1.f / limD; - float hig = ((float) deh.highl) / 100.f; - scal = deh.skal; + if (!deh.enabled) { + return; + } - int H_L = height; - int W_L = width; + constexpr float eps = 2.f; + const bool useHsl = deh.retinexcolorspace == "HSLLOG"; + const bool useHslLin = deh.retinexcolorspace == "HSLLIN"; + const float offse = deh.offs; //def = 0 not use + const int iter = deh.iter; + const int gradient = deh.scal; + int scal = deh.skal; + const int nei = 2.8f * deh.neigh; //def = 220 + const float vart = deh.vart / 100.f;//variance + const float gradvart = deh.grad; + const float gradstr = deh.grads; + const float strength = deh.str / 100.f; // Blend with original L channel data + float limD = deh.limd; + limD = pow(limD, 1.7f);//about 2500 enough + limD *= useHslLin ? 10.f : 1.f; + const float ilimD = 1.f / limD; + const float hig = deh.highl / 100.f; - float *tran[H_L] ALIGNED16; - float *tranBuffer = nullptr; + const int H_L = height; + const int W_L = width; - constexpr float elogt = 2.71828f; - bool lhutili = false; + constexpr float elogt = 2.71828f; + bool lhutili = false; - FlatCurve* shcurve = new FlatCurve(deh.lhcurve); //curve L=f(H) + FlatCurve* shcurve = new FlatCurve(deh.lhcurve); //curve L=f(H) - if (!shcurve || shcurve->isIdentity()) { - if (shcurve) { - delete shcurve; - shcurve = nullptr; - } - } else { - lhutili = true; + if (!shcurve || shcurve->isIdentity()) { + if (shcurve) { + delete shcurve; + shcurve = nullptr; } + } else { + lhutili = true; + } - bool higplus = false ; - int moderetinex = 2; // default to 2 ( deh.retinexMethod == "high" ) + bool higplus = false ; + int moderetinex = 2; // default to 2 ( deh.retinexMethod == "high" ) - if (deh.retinexMethod == "highliplus") { - higplus = true; - moderetinex = 3; - } else if (deh.retinexMethod == "uni") { - moderetinex = 0; - } else if (deh.retinexMethod == "low") { - moderetinex = 1; - } else { /*if (deh.retinexMethod == "highli") */ - moderetinex = 3; - } + if (deh.retinexMethod == "highliplus") { + higplus = true; + moderetinex = 3; + } else if (deh.retinexMethod == "uni") { + moderetinex = 0; + } else if (deh.retinexMethod == "low") { + moderetinex = 1; + } else { /*if (deh.retinexMethod == "highli") */ + moderetinex = 3; + } - constexpr float aahi = 49.f / 99.f; ////reduce sensibility 50% - constexpr float bbhi = 1.f - aahi; + constexpr float aahi = 49.f / 99.f; ////reduce sensibility 50% + constexpr float bbhi = 1.f - aahi; + float high = bbhi + aahi * (float) deh.highl; - for (int it = 1; it < iter + 1; it++) { //iter nb max of iterations - float high = bbhi + aahi * (float) deh.highl; + for (int it = 1; it < iter + 1; it++) { //iter nb max of iterations + float grad = 1.f; + float sc = scal; - float grad = 1.f; - float sc = scal; - - if (gradient == 0) { - grad = 1.f; - sc = 3.f; - } else if (gradient == 1) { - grad = 0.25f * it + 0.75f; - sc = -0.5f * it + 4.5f; - } else if (gradient == 2) { - grad = 0.5f * it + 0.5f; - sc = -0.75f * it + 5.75f; - } else if (gradient == 3) { - grad = 0.666f * it + 0.333f; - sc = -0.75f * it + 5.75f; - } else if (gradient == 4) { - grad = 0.8f * it + 0.2f; - sc = -0.75f * it + 5.75f; - } else if (gradient == 5) { - if (moderetinex != 3) { - grad = 2.5f * it - 1.5f; - } else { - float aa = (11.f * high - 1.f) / 4.f; - float bb = 1.f - aa; - grad = aa * it + bb; - } - - sc = -0.75f * it + 5.75f; - } else if (gradient == 6) { - if (moderetinex != 3) { - grad = 5.f * it - 4.f; - } else { - float aa = (21.f * high - 1.f) / 4.f; - float bb = 1.f - aa; - grad = aa * it + bb; - } - - sc = -0.75f * it + 5.75f; - } - - else if (gradient == -1) { - grad = -0.125f * it + 1.125f; - sc = 3.f; - } - - if (iter == 1) { - sc = scal; + if (gradient == 0) { + grad = 1.f; + sc = 3.f; + } else if (gradient == 1) { + grad = 0.25f * it + 0.75f; + sc = -0.5f * it + 4.5f; + } else if (gradient == 2) { + grad = 0.5f * it + 0.5f; + sc = -0.75f * it + 5.75f; + } else if (gradient == 3) { + grad = 0.666f * it + 0.333f; + sc = -0.75f * it + 5.75f; + } else if (gradient == 4) { + grad = 0.8f * it + 0.2f; + sc = -0.75f * it + 5.75f; + } else if (gradient == 5) { + if (moderetinex != 3) { + grad = 2.5f * it - 1.5f; } else { - //adjust sc in function of choice of scale by user if iterations - if (scal < 3) { - sc -= 1; + float aa = (11.f * high - 1.f) / 4.f; + float bb = 1.f - aa; + grad = aa * it + bb; + } - if (sc < 1.f) { //avoid 0 - sc = 1.f; - } + sc = -0.75f * it + 5.75f; + } else if (gradient == 6) { + if (moderetinex != 3) { + grad = 5.f * it - 4.f; + } else { + float aa = (21.f * high - 1.f) / 4.f; + float bb = 1.f - aa; + grad = aa * it + bb; + } + + sc = -0.75f * it + 5.75f; + } else if (gradient == -1) { + grad = -0.125f * it + 1.125f; + sc = 3.f; + } + + if (iter == 1) { + sc = scal; + } else { + //adjust sc in function of choice of scale by user if iterations + if (scal < 3) { + sc -= 1; + + if (sc < 1.f) {//avoid 0 + sc = 1.f; } + } else if (scal > 4) { + sc += 1; + } + } - if (scal > 4) { - sc += 1; + float varx = vart; + float limdx = limD; + float ilimdx = ilimD; + + if (gradvart != 0) { + if (gradvart == 1) { + varx = vart * (-0.125f * it + 1.125f); + limdx = limD * (-0.125f * it + 1.125f); + ilimdx = 1.f / limdx; + } else if (gradvart == 2) { + varx = vart * (-0.2f * it + 1.2f); + limdx = limD * (-0.2f * it + 1.2f); + ilimdx = 1.f / limdx; + } else if (gradvart == -1) { + varx = vart * (0.125f * it + 0.875f); + limdx = limD * (0.125f * it + 0.875f); + ilimdx = 1.f / limdx; + } else if (gradvart == -2) { + varx = vart * (0.4f * it + 0.6f); + limdx = limD * (0.4f * it + 0.6f); + ilimdx = 1.f / limdx; + } + } + + scal = round(sc); + float ks = 1.f; + + if (gradstr != 0) { + if (gradstr == 1) { + if (it <= 3) { + ks = -0.3f * it + 1.6f; + } else { + ks = 0.5f; + } + } else if (gradstr == 2) { + if (it <= 3) { + ks = -0.6f * it + 2.2f; + } else { + ks = 0.3f; + } + } else if (gradstr == -1) { + if (it <= 3) { + ks = 0.2f * it + 0.6f; + } else { + ks = 1.2f; + } + } else if (gradstr == -2) { + if (it <= 3) { + ks = 0.4f * it + 0.2f; + } else { + ks = 1.5f; } } + } - float varx = vart; - float limdx = limD; - float ilimdx = ilimD; + const float strengthx = ks * strength; - if (gradvart != 0) { - if (gradvart == 1) { - varx = vart * (-0.125f * it + 1.125f); - limdx = limD * (-0.125f * it + 1.125f); - ilimdx = 1.f / limdx; - } else if (gradvart == 2) { - varx = vart * (-0.2f * it + 1.2f); - limdx = limD * (-0.2f * it + 1.2f); - ilimdx = 1.f / limdx; - } else if (gradvart == -1) { - varx = vart * (0.125f * it + 0.875f); - limdx = limD * (0.125f * it + 0.875f); - ilimdx = 1.f / limdx; - } else if (gradvart == -2) { - varx = vart * (0.4f * it + 0.6f); - limdx = limD * (0.4f * it + 0.6f); - ilimdx = 1.f / limdx; - } - } + constexpr auto maxRetinexScales = 8; + float RetinexScales[maxRetinexScales]; - scal = round(sc); - float ks = 1.f; + retinex_scales(RetinexScales, scal, moderetinex, nei / grad, high); - if (gradstr != 0) { - if (gradstr == 1) { - if (it <= 3) { - ks = -0.3f * it + 1.6f; - } else { - ks = 0.5f; - } - } else if (gradstr == 2) { - if (it <= 3) { - ks = -0.6f * it + 2.2f; - } else { - ks = 0.3f; - } - } else if (gradstr == -1) { - if (it <= 3) { - ks = 0.2f * it + 0.6f; - } else { - ks = 1.2f; - } - } else if (gradstr == -2) { - if (it <= 3) { - ks = 0.4f * it + 0.2f; - } else { - ks = 1.5f; - } - } - } + const int shHighlights = deh.highlights; + const int shShadows = deh.shadows; - float strengthx = ks * strength; + int mapmet = 0; - constexpr auto maxRetinexScales = 8; - float RetinexScales[maxRetinexScales]; + if (deh.mapMethod == "map") { + mapmet = 2; + } else if (deh.mapMethod == "mapT") { + mapmet = 3; + } else if (deh.mapMethod == "gaus") { + mapmet = 4; + } - retinex_scales(RetinexScales, scal, moderetinex, nei / grad, high); + const double shradius = mapmet == 4 ? (double) deh.radius : 40.; - float *src[H_L] ALIGNED16; - float *srcBuffer = new float[H_L * W_L]; + int viewmet = 0; - for (int i = 0; i < H_L; i++) { - src[i] = &srcBuffer[i * W_L]; - } + if (deh.viewMethod == "mask") { + viewmet = 1; + } else if (deh.viewMethod == "tran") { + viewmet = 2; + } else if (deh.viewMethod == "tran2") { + viewmet = 3; + } else if (deh.viewMethod == "unsharp") { + viewmet = 4; + } - int h_th = 0, s_th = 0; - - int shHighlights = deh.highlights; - int shShadows = deh.shadows; - - int mapmet = 0; - - if (deh.mapMethod == "map") { - mapmet = 2; - } else if (deh.mapMethod == "mapT") { - mapmet = 3; - } else if (deh.mapMethod == "gaus") { - mapmet = 4; - } - - const double shradius = mapmet == 4 ? (double) deh.radius : 40.; - - int viewmet = 0; - - if (deh.viewMethod == "mask") { - viewmet = 1; - } else if (deh.viewMethod == "tran") { - viewmet = 2; - } else if (deh.viewMethod == "tran2") { - viewmet = 3; - } else if (deh.viewMethod == "unsharp") { - viewmet = 4; - } + std::unique_ptr> srcBuffer(new JaggedArray(W_L, H_L)); + float** src = *(srcBuffer.get()); #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel for #endif - for (int i = 0; i < H_L; i++) - for (int j = 0; j < W_L; j++) { - src[i][j] = luminance[i][j] + eps; - luminance[i][j] = 0.f; - } - - float *out[H_L] ALIGNED16; - float *outBuffer = new float[H_L * W_L]; - - for (int i = 0; i < H_L; i++) { - out[i] = &outBuffer[i * W_L]; + for (int i = 0; i < H_L; i++) + for (int j = 0; j < W_L; j++) { + src[i][j] = luminance[i][j] + eps; + luminance[i][j] = 0.f; } - if (viewmet == 3 || viewmet == 2) { - tranBuffer = new float[H_L * W_L]; + JaggedArray out(W_L, H_L); + JaggedArray& tran = out; // tran and out can safely use the same buffer - for (int i = 0; i < H_L; i++) { - tran[i] = &tranBuffer[i * W_L]; - } - } + const float logBetaGain = xlogf(16384.f); + float pond = logBetaGain / (float) scal; - const float logBetaGain = xlogf(16384.f); - float pond = logBetaGain / (float) scal; + if (!useHslLin) { + pond /= log(elogt); + } - if (!useHslLin) { - pond /= log(elogt); - } + std::unique_ptr shmap; - auto shmap = ((mapmet == 2 || mapmet == 3 || mapmet == 4) && it == 1) ? new SHMap(W_L, H_L) : nullptr; + if (((mapmet == 2 || mapmet == 3 || mapmet == 4) && it == 1)) { + shmap.reset(new SHMap(W_L, H_L)); + } - float *buffer = new float[W_L * H_L];; + std::unique_ptr buffer; - for (int scale = scal - 1; scale >= 0; scale--) { -#ifdef _OPENMP - #pragma omp parallel -#endif - { - if (scale == scal - 1) - { - gaussianBlur(src, out, W_L, H_L, RetinexScales[scale], buffer); - } else // reuse result of last iteration - { - // out was modified in last iteration => restore it - if ((((mapmet == 2 && scale > 1) || mapmet == 3 || mapmet == 4) || (mapmet > 0 && mapcontlutili)) && it == 1) { -#ifdef _OPENMP - #pragma omp for -#endif + if (mapmet > 0) { + buffer.reset(new float[W_L * H_L]); + } - for (int i = 0; i < H_L; i++) { - for (int j = 0; j < W_L; j++) { - out[i][j] = buffer[i * W_L + j]; - } - } - } - - gaussianBlur(out, out, W_L, H_L, sqrtf(SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])), buffer); - } - - if ((((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) || (mapmet > 0 && mapcontlutili)) && it == 1 && scale > 0) - { - // out will be modified => store it for use in next iteration. We even don't need a new buffer because 'buffer' is free after gaussianBlur :) -#ifdef _OPENMP - #pragma omp for -#endif - - for (int i = 0; i < H_L; i++) { - for (int j = 0; j < W_L; j++) { - buffer[i * W_L + j] = out[i][j]; - } - } - } - } - - if (((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) && it == 1) { - shmap->updateL(out, shradius, true, 1); - h_th = shmap->max_f - deh.htonalwidth * (shmap->max_f - shmap->avg) / 100; - s_th = deh.stonalwidth * (shmap->avg - shmap->min_f) / 100; - } - -#ifdef __SSE2__ - vfloat pondv = F2V(pond); - vfloat limMinv = F2V(ilimdx); - vfloat limMaxv = F2V(limdx); - -#endif - - if (mapmet > 0 && mapcontlutili && it == 1) { - // TODO: When rgbcurvespeedup branch is merged into master we can simplify the code by - // 1) in rawimagesource.retinexPrepareCurves() insert - // mapcurve *= 0.5f; - // after - // CurveFactory::mapcurve (mapcontlutili, retinexParams.mapcurve, mapcurve, 1, lhist16RETI, histLRETI); - // 2) remove the division by 2.f from the code 7 lines below this line + for (int scale = scal - 1; scale >= 0; --scale) { + if (scale == scal - 1) { + gaussianBlur(src, out, W_L, H_L, RetinexScales[scale], true); + } else { // reuse result of last iteration + // out was modified in last iteration => restore it + if ((((mapmet == 2 && scale > 1) || mapmet == 3 || mapmet == 4) || (mapmet > 0 && mapcontlutili)) && it == 1) { #ifdef _OPENMP #pragma omp parallel for #endif for (int i = 0; i < H_L; i++) { for (int j = 0; j < W_L; j++) { - out[i][j] = mapcurve[2.f * out[i][j]] / 2.f; + out[i][j] = buffer[i * W_L + j]; } } - } - if (((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) && it == 1) { - float hWeight = (100.f - shHighlights) / 100.f; - float sWeight = (100.f - shShadows) / 100.f; + gaussianBlur(out, out, W_L, H_L, sqrtf(SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])), true); + } + + if ((((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) || (mapmet > 0 && mapcontlutili)) && it == 1 && scale > 0) { + // out will be modified => store it for use in next iteration. #ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for #endif - for (int i = 0; i < H_L; i++) { - for (int j = 0; j < W_L; j++) { - float mapval = 1.f + shmap->map[i][j]; - float factor = 1.f; + for (int i = 0; i < H_L; i++) { + for (int j = 0; j < W_L; j++) { + buffer[i * W_L + j] = out[i][j]; + } + } + } - if (mapval > h_th) { - factor = (h_th + hWeight * (mapval - h_th)) / mapval; - } else if (mapval < s_th) { - factor = (s_th - sWeight * (s_th - mapval)) / mapval; - } + int h_th = 0; + int s_th = 0; - out[i][j] *= factor; + if (((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) && it == 1) { + shmap->updateL(out, shradius, true, 1); + h_th = shmap->max_f - deh.htonalwidth * (shmap->max_f - shmap->avg) / 100; + s_th = deh.stonalwidth * (shmap->avg - shmap->min_f) / 100; + } + if (mapmet > 0 && mapcontlutili && it == 1) { +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H_L; i++) { + for (int j = 0; j < W_L; j++) { + out[i][j] = mapcurve[2.f * out[i][j]]; + } + } + + } + + if (((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) && it == 1) { + const float hWeight = (100.f - shHighlights) / 100.f; + const float sWeight = (100.f - shShadows) / 100.f; +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int i = 0; i < H_L; i++) { + for (int j = 0; j < W_L; j++) { + const float mapval = 1.f + shmap->map[i][j]; + float factor; + + if (mapval > h_th) { + factor = (h_th + hWeight * (mapval - h_th)) / mapval; + } else if (mapval < s_th) { + factor = (s_th - sWeight * (s_th - mapval)) / mapval; + } else { + factor = 1.f; } + + out[i][j] *= factor; + } + } + } + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H_L; i++) { + int j = 0; + +#ifdef __SSE2__ + const vfloat pondv = F2V(pond); + const vfloat limMinv = F2V(ilimdx); + const vfloat limMaxv = F2V(limdx); + + if (useHslLin) { + for (; j < W_L - 3; j += 4) { + STVFU(luminance[i][j], LVFU(luminance[i][j]) + pondv * vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv)); + } + } else { + for (; j < W_L - 3; j += 4) { + STVFU(luminance[i][j], LVFU(luminance[i][j]) + pondv * xlogf(vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv))); + } + } + +#endif + + if (useHslLin) { + for (; j < W_L; j++) { + luminance[i][j] += pond * LIM(src[i][j] / out[i][j], ilimdx, limdx); + } + } else { + for (; j < W_L; j++) { + luminance[i][j] += pond * xlogf(LIM(src[i][j] / out[i][j], ilimdx, limdx)); // /logt ? + } + } + } + } + + srcBuffer.reset(); + + float mean = 0.f; + float stddv = 0.f; + // I call mean_stddv2 instead of mean_stddv ==> logBetaGain + + float maxtr, mintr; + mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr); + //printf("mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", mean, stddv, delta, maxtr, mintr); + + //mean_stddv( luminance, mean, stddv, W_L, H_L, logBetaGain, maxtr, mintr); + if (dehatransmissionCurve && mean != 0.f && stddv != 0.f) { //if curve + float asig = 0.166666f / stddv; + float bsig = 0.5f - asig * mean; + float amax = 0.333333f / (maxtr - mean - stddv); + float bmax = 1.f - amax * maxtr; + float amin = 0.333333f / (mean - stddv - mintr); + float bmin = -amin * mintr; + + asig *= 500.f; + bsig *= 500.f; + amax *= 500.f; + bmax *= 500.f; + amin *= 500.f; + bmin *= 500.f; + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int i = 0; i < H_L; i++) { + for (int j = 0; j < W_L; j++) { //for mintr to maxtr evalate absciss in function of original transmission + float absciss; + + if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) { + absciss = asig * luminance[i][j] + bsig; + } else if (luminance[i][j] >= mean) { + absciss = amax * luminance[i][j] + bmax; + } else { /*if(luminance[i][j] <= mean - stddv)*/ + absciss = amin * luminance[i][j] + bmin; + } + + //TODO : move multiplication by 4.f and subtraction of 1.f inside the curve + luminance[i][j] *= (-1.f + 4.f * dehatransmissionCurve[absciss]); //new transmission + + if (viewmet == 3 || viewmet == 2) { + tran[i][j] = luminance[i][j]; + } + } + } + + // median filter on transmission ==> reduce artifacts + if (deh.medianmap && it == 1) { //only one time + JaggedArray tmL(W_L, H_L); + constexpr int borderL = 1; + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = borderL; i < H_L - borderL; i++) { + for (int j = borderL; j < W_L - borderL; j++) { + tmL[i][j] = median(luminance[i][j], luminance[i - 1][j], luminance[i + 1][j], luminance[i][j + 1], luminance[i][j - 1], luminance[i - 1][j - 1], luminance[i - 1][j + 1], luminance[i + 1][j - 1], luminance[i + 1][j + 1]); //3x3 } } @@ -544,55 +614,831 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e #pragma omp parallel for #endif - for (int i = 0; i < H_L; i++) { - int j = 0; + for (int i = borderL; i < H_L - borderL; i++) { + for (int j = borderL; j < W_L - borderL; j++) { + luminance[i][j] = tmL[i][j]; + } + } + } -#ifdef __SSE2__ + // I call mean_stddv2 instead of mean_stddv ==> logBetaGain + //mean_stddv( luminance, mean, stddv, W_L, H_L, 1.f, maxtr, mintr); + mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr); + } - if (useHslLin) { - for (; j < W_L - 3; j += 4) { - _mm_storeu_ps(&luminance[i][j], LVFU(luminance[i][j]) + pondv * (vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv))); + constexpr float epsil = 0.1f; + + mini = mean - varx * stddv; + + if (mini < mintr) { + mini = mintr + epsil; + } + + maxi = mean + varx * stddv; + + if (maxi > maxtr) { + maxi = maxtr - epsil; + } + + float delta = maxi - mini; + //printf("maxi=%f mini=%f mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", maxi, mini, mean, stddv, delta, maxtr, mintr); + + if (!delta) { + delta = 1.0f; + } + + // coeff for auto "transmission" with 2 sigma #95% data + const float aza = 16300.f / (2.f * stddv); + const float azb = -aza * (mean - 2.f * stddv); + const float bza = 16300.f / (2.f * stddv); + const float bzb = 16300.f - bza * (mean); + +//prepare work for curve gain +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H_L; i++) { + for (int j = 0; j < W_L; j++) { + luminance[i][j] = luminance[i][j] - mini; + } + } + + mean = 0.f; + stddv = 0.f; + // I call mean_stddv2 instead of mean_stddv ==> logBetaGain + + mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr); + float asig = 0.f, bsig = 0.f, amax = 0.f, bmax = 0.f, amin = 0.f, bmin = 0.f; + + if (dehagaintransmissionCurve && mean != 0.f && stddv != 0.f) { //if curve + asig = 0.166666f / stddv; + bsig = 0.5f - asig * mean; + amax = 0.333333f / (maxtr - mean - stddv); + bmax = 1.f - amax * maxtr; + amin = 0.333333f / (mean - stddv - mintr); + bmin = -amin * mintr; + + asig *= 500.f; + bsig *= 500.f; + amax *= 500.f; + bmax *= 500.f; + amin *= 500.f; + bmin *= 500.f; + } + + const float cdfactor = 32768.f / delta; + maxCD = -9999999.f; + minCD = 9999999.f; + +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxCD) reduction(min:minCD) schedule(dynamic, 16) +#endif + + for (int i = 0; i < H_L; i ++) { + for (int j = 0; j < W_L; j++) { + float gan; + + if (dehagaintransmissionCurve && mean != 0.f && stddv != 0.f) { + float absciss; + + if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) { + absciss = asig * luminance[i][j] + bsig; + } else if (luminance[i][j] >= mean) { + absciss = amax * luminance[i][j] + bmax; + } else { /*if(luminance[i][j] <= mean - stddv)*/ + absciss = amin * luminance[i][j] + bmin; + } + + + // float cd = cdfactor * ( luminance[i][j] - mini ) + offse; + // TODO : move multiplication by 2.f inside the curve + gan = 2.f * dehagaintransmissionCurve[absciss]; //new gain function transmission + } else { + gan = 0.5f; + } + + const float cd = gan * cdfactor * luminance[i][j] + offse; + + maxCD = cd > maxCD ? cd : maxCD; + minCD = cd < minCD ? cd : minCD; + + float str = strengthx; + + if (lhutili && it == 1) { // S=f(H) + { + const float HH = exLuminance[i][j]; + float valparam; + + if (useHsl || useHslLin) { + valparam = shcurve->getVal(HH) - 0.5f; + } else { + valparam = shcurve->getVal(Color::huelab_to_huehsv2(HH)) - 0.5f; } + + str *= (1.f + 2.f * valparam); + } + } + + if (higplus && exLuminance[i][j] > 65535.f * hig) { + str *= hig; + } + + if (viewmet == 0) { + luminance[i][j] = intp(str, LIM(cd, 0.f, 32768.f), originalLuminance[i][j]); + } else if (viewmet == 1) { + luminance[i][j] = out[i][j]; + } else if (viewmet == 4) { + luminance[i][j] = originalLuminance[i][j] + str * (originalLuminance[i][j] - out[i][j]);//unsharp + } else if (viewmet == 2) { + if (tran[i][j] <= mean) { + luminance[i][j] = azb + aza * tran[i][j]; //auto values } else { - for (; j < W_L - 3; j += 4) { - _mm_storeu_ps(&luminance[i][j], LVFU(luminance[i][j]) + pondv * xlogf(vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv))); + luminance[i][j] = bzb + bza * tran[i][j]; + } + } else { /*if (viewmet == 3) */ + luminance[i][j] = 1000.f + tran[i][j] * 700.f; //arbitrary values to help display log values which are between -20 to + 30 - usage values -4 + 5 + } + + } + } + + Tmean = mean; + Tsigma = stddv; + Tmin = mintr; + Tmax = maxtr; + + if (shcurve) { + delete shcurve; + shcurve = nullptr; + } + } +} + + +void ImProcFunctions::maskforretinex(int sp, int before, float ** luminance, float ** out, int W_L, int H_L, int skip, + const LocCCmaskCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool & lhmasretiutili, + int llretiMask, bool retiMasktmap, bool retiMask, float rad, float lap, bool pde, float gamm, float slop, float chro, float blend, + LUTf & lmaskretilocalcurve, bool & localmaskretiutili, + LabImage * bufreti, LabImage * bufmask, LabImage * buforig, LabImage * buforigmas, bool multiThread, + bool delt, const float hueref, const float chromaref, const float lumaref, + float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, float balance, float balanceh, float lumask) +{ + array2D loctemp(W_L, H_L); + array2D ble(W_L, H_L); + array2D blechro(W_L, H_L); + array2D hue(W_L, H_L); + array2D guid(W_L, H_L); + std::unique_ptr bufmaskblurreti; + bufmaskblurreti.reset(new LabImage(W_L, H_L)); + std::unique_ptr bufmaskorigreti; + bufmaskorigreti.reset(new LabImage(W_L, H_L)); + std::unique_ptr bufprov; + bufprov.reset(new LabImage(W_L, H_L)); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + if (before == 1 && retiMasktmap) { + loctemp[y][x] = LIM(luminance[y][x], 0.f, 32768.f); + } else if (before == 0 && retiMasktmap) { + loctemp[y][x] = out[y][x]; + } else { + loctemp[y][x] = bufreti->L[y][x]; + } + } + } + + float chromult = 1.f - 0.01f * chro; +//fab + float fab = 50.f; + float meanfab = 0.f; + const int nbfab = W_L * H_L; + + double sumab = 0.0; + +#ifdef _OPENMP + #pragma omp parallel for reduction(+:sumab) +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + sumab += fabs(bufreti->a[y][x]); + sumab += fabs(bufreti->b[y][x]); + } + } + + meanfab = sumab / (2.f * nbfab); + double som = 0.0; + +#ifdef _OPENMP + #pragma omp parallel for reduction(+:som) +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + som += SQR(fabs(bufreti->a[y][x]) - meanfab) + SQR(fabs(bufreti->b[y][x]) - meanfab); + } + } + const float multsigma = (chro >= 0.f ? 0.035f : 0.018f) * chro + 1.f; + const float stddv = sqrt(som / nbfab); + fab = meanfab + multsigma * stddv; + + if (fab <= 0.f) { + fab = 50.f; + } +//end fab + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < H_L; ir++) { + for (int jr = 0; jr < W_L; jr++) { + float kmaskLexp = 0; + float kmaskCH = 0; + + if (locllmasretiCurve && llmasretiutili) { + float ligh = loctemp[ir][jr] / 32768.f; + kmaskLexp = 32768.f * LIM01(1.f - locllmasretiCurve[500.f * ligh]); + + } + + + if (locllmasretiCurve && llmasretiutili && retiMasktmap) { + } + + if (llretiMask != 4) { + if (locccmasretiCurve && lcmasretiutili) { + float chromask = 0.0001f + sqrt(SQR((bufreti->a[ir][jr]) / fab) + SQR((bufreti->b[ir][jr]) / fab)); + kmaskCH = LIM01(1.f - locccmasretiCurve[500.f * chromask]); + } + } + + if (lochhmasretiCurve && lhmasretiutili) { + float huema = xatan2f(bufreti->b[ir][jr], bufreti->a[ir][jr]); + float h = Color::huelab_to_huehsv2(huema); + h += 1.f / 6.f; + + if (h > 1.f) { + h -= 1.f; + } + + float valHH = LIM01(1.f - lochhmasretiCurve[500.f * h]); + + if (llretiMask != 4) { + kmaskCH += chromult * valHH; + } + + kmaskLexp += 32768.f * valHH; + } + + bufmaskblurreti->L[ir][jr] = kmaskLexp; + bufmaskblurreti->a[ir][jr] = kmaskCH; + bufmaskblurreti->b[ir][jr] = kmaskCH; + ble[ir][jr] = bufmaskblurreti->L[ir][jr] / 32768.f; + hue[ir][jr] = xatan2f(bufmaskblurreti->b[ir][jr], bufmaskblurreti->a[ir][jr]); + float chromah = sqrt(SQR(bufmaskblurreti->b[ir][jr]) + SQR(bufmaskblurreti->a[ir][jr])); + blechro[ir][jr] = chromah / 32768.f; + guid[ir][jr] = bufreti->L[ir][jr] / 32768.f; + bufprov->L[ir][jr] = bufmaskblurreti->L[ir][jr]; + bufprov->a[ir][jr] = bufmaskblurreti->a[ir][jr]; + bufprov->b[ir][jr] = bufmaskblurreti->b[ir][jr]; + + } + } + + if (rad != 0.f) { +// guidedFilter(guid, ble, ble, rad * 10.f / skip, 0.001, multiThread, 4); + float blur = rad; + blur = blur < 0.f ? -1.f / blur : 1.f + blur; + int r1 = max(int(4 / skip * blur + 0.5), 1); + int r2 = max(int(25 / skip * blur + 0.5), 1); + + double epsilmax = 0.0005; + double epsilmin = 0.00001; + + double aepsil = (epsilmax - epsilmin) / 90.f; + double bepsil = epsilmax - 100.f * aepsil; + double epsil = aepsil * 0.1 * rad + bepsil; + if (rad < 0.f) { + epsil = 0.001; + } + rtengine::guidedFilter(guid, blechro, blechro, r1, epsil, multiThread); + rtengine::guidedFilter(guid, ble, ble, r2, 0.2 * epsil, multiThread); + + } + + LUTf lutTonemaskreti(65536); + calcGammaLut(gamm, slop, lutTonemaskreti); + float radiusb = 1.f / skip; + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < H_L; ir++) + for (int jr = 0; jr < W_L; jr++) { + float L_; + float2 sincosval = xsincosf(hue[ir][jr]); + bufmaskblurreti->L[ir][jr] = LIM01(ble[ir][jr]) * 32768.f; + L_ = 2.f * bufmaskblurreti->L[ir][jr]; + bufmaskblurreti->L[ir][jr] = lutTonemaskreti[L_]; + bufmaskblurreti->a[ir][jr] = 32768.f * sincosval.y * blechro[ir][jr]; + bufmaskblurreti->b[ir][jr] = 32768.f * sincosval.x * blechro[ir][jr]; + } + + if (lmaskretilocalcurve && localmaskretiutili) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < H_L; ir++) + for (int jr = 0; jr < W_L; jr++) { + bufmaskblurreti->L[ir][jr] = 0.5f * lmaskretilocalcurve[2.f * bufmaskblurreti->L[ir][jr]]; + } + } + + + if (delt) { + float *rdE[H_L] ALIGNED16; + float *rdEBuffer = new float[H_L * W_L]; + + for (int i = 0; i < H_L; i++) { + rdE[i] = &rdEBuffer[i * W_L]; + } + + deltaEforMask(rdE, W_L, H_L, bufreti, hueref, chromaref, lumaref, maxdE, mindE, maxdElim, mindElim, iterat, limscope, scope, balance, balanceh); + // printf("rde1=%f rde2=%f\n", rdE[1][1], rdE[100][100]); + std::unique_ptr delta(new LabImage(W_L, H_L)); +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int ir = 0; ir < H_L; ir++) + for (int jr = 0; jr < W_L; jr++) { + delta->L[ir][jr] = bufmaskblurreti->L[ir][jr] - bufprov->L[ir][jr]; + delta->a[ir][jr] = bufmaskblurreti->a[ir][jr] - bufprov->a[ir][jr]; + delta->b[ir][jr] = bufmaskblurreti->b[ir][jr] - bufprov->b[ir][jr]; + + bufmaskblurreti->L[ir][jr] = bufprov->L[ir][jr] + rdE[ir][jr] * delta->L[ir][jr]; + bufmaskblurreti->a[ir][jr] = bufprov->a[ir][jr] + rdE[ir][jr] * delta->a[ir][jr]; + bufmaskblurreti->b[ir][jr] = bufprov->b[ir][jr] + rdE[ir][jr] * delta->b[ir][jr]; + } + + delete [] rdEBuffer; + + } + + + if (lap > 0.f) { + float *datain = new float[H_L * W_L]; + float *data_tmp = new float[H_L * W_L]; + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + datain[y * W_L + x] = bufmaskblurreti->L[y][x]; + } + } + + if (!pde) { + ImProcFunctions::discrete_laplacian_threshold(data_tmp, datain, W_L, H_L, 200.f * lap); + } else { + ImProcFunctions::retinex_pde(datain, data_tmp, W_L, H_L, 12.f * lap, 1.f, nullptr, 0, 0, 1); + } + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + bufmaskblurreti->L[y][x] = data_tmp[y * W_L + x]; + } + } + + delete [] datain; + delete [] data_tmp; + + } + +//blend +#ifdef _OPENMP + #pragma omp parallel +#endif + { + gaussianBlur(bufmaskblurreti->L, bufmaskorigreti->L, W_L, H_L, radiusb); + gaussianBlur(bufmaskblurreti->a, bufmaskorigreti->a, W_L, H_L, 1.f + (0.5f * rad) / skip); + gaussianBlur(bufmaskblurreti->b, bufmaskorigreti->b, W_L, H_L, 1.f + (0.5f * rad) / skip); + } + + float modr = 0.01f * (float) blend; + + if (llretiMask != 3 && retiMask) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + if (before == 0 && retiMasktmap) { + out[y][x] += fabs(modr) * bufmaskorigreti->L[y][x]; + out[y][x] = LIM(out[y][x], 0.f, 100000.f); + } else { + bufreti->L[y][x] += bufmaskorigreti->L[y][x] * modr; + bufreti->L[y][x] = CLIPLOC(bufreti->L[y][x]); + + } + + bufreti->a[y][x] *= (1.f + bufmaskorigreti->a[y][x] * modr * (1.f + 0.01f * chro)); + bufreti->b[y][x] *= (1.f + bufmaskorigreti->b[y][x] * modr * (1.f + 0.01f * chro)); + bufreti->a[y][x] = CLIPC(bufreti->a[y][x]); + bufreti->b[y][x] = CLIPC(bufreti->b[y][x]); + } + } + + + } + + if (!retiMasktmap && retiMask) { //new original blur mask for deltaE +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + + buforig->L[y][x] += (modr * bufmaskorigreti->L[y][x]); + buforig->a[y][x] *= (1.f + modr * bufmaskorigreti->a[y][x]); + buforig->b[y][x] *= (1.f + modr * bufmaskorigreti->b[y][x]); + + buforig->L[y][x] = CLIP(buforig->L[y][x]); + buforig->a[y][x] = CLIPC(buforig->a[y][x]); + buforig->b[y][x] = CLIPC(buforig->b[y][x]); + + buforig->L[y][x] = CLIP(buforig->L[y][x] - bufmaskorigreti->L[y][x]); + buforig->a[y][x] = CLIPC(buforig->a[y][x] * (1.f - bufmaskorigreti->a[y][x])); + buforig->b[y][x] = CLIPC(buforig->b[y][x] * (1.f - bufmaskorigreti->b[y][x])); + } + } + + float radius = 3.f / skip; + +#ifdef _OPENMP + #pragma omp parallel if (multiThread) +#endif + { + gaussianBlur(buforig->L, buforigmas->L, W_L, H_L, radius); + gaussianBlur(buforig->a, buforigmas->a, W_L, H_L, radius); + gaussianBlur(buforig->b, buforigmas->b, W_L, H_L, radius); + } + + } + + + if (llretiMask == 3) { + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < H_L; y++) { + for (int x = 0; x < W_L; x++) { + bufmask->L[y][x] = (lumask * 400.f) + CLIPLOC(bufmaskorigreti->L[y][x]); + bufmask->a[y][x] = CLIPC(bufreti->a[y][x] * bufmaskorigreti->a[y][x]); + bufmask->b[y][x] = CLIPC(bufreti->b[y][x] * bufmaskorigreti->b[y][x]); + } + } + } + +} + + + +void ImProcFunctions::MSRLocal(int call, int sp, bool fftw, int lum, float** reducDE, LabImage * bufreti, LabImage * bufmask, LabImage * buforig, LabImage * buforigmas, float** luminance, float** templ, const float* const *originalLuminance, + const int width, const int height, int bfwr, int bfhr, const procparams::LocallabParams &loc, const int skip, const LocretigainCurve &locRETgainCcurve, const LocretitransCurve &locRETtransCcurve, + const int chrome, const int scall, const float krad, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, + const LocCCmaskCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskCurve & lochhmasretiCurve, bool & lhmasretiutili, int llretiMask, + LUTf & lmaskretilocalcurve, bool & localmaskretiutili, + LabImage * transformed, bool retiMasktmap, bool retiMask, + bool delt, const float hueref, const float chromaref, const float lumaref, + float maxdE, float mindE, float maxdElim, float mindElim, float iterat, float limscope, int scope, float balance, float balanceh, float lumask) + +{ + BENCHFUN + bool py = true; + + if (py) {//enabled + float mean, stddv, maxtr, mintr; + float delta; + constexpr float eps = 2.f; + bool useHslLin = false; + const float offse = loc.spots.at(sp).offs; + const float chrT = (float)(loc.spots.at(sp).chrrt) / 100.f; + const int scal = (loc.spots.at(sp).scalereti); + float vart = loc.spots.at(sp).vart / 100.f;//variance + const float strength = loc.spots.at(sp).str / 100.f; // Blend with original L channel data + const float dar = loc.spots.at(sp).darkness; + const float lig = loc.spots.at(sp).lightnessreti; + float value = pow(strength, 0.4f); + float value_1 = pow(strength, 0.3f); + bool logli = loc.spots.at(sp).loglin; + float limD = loc.spots.at(sp).limd;//10.f + limD = pow(limD, 1.7f); //about 2500 enough + float ilimD = 1.f / limD; + float threslum = loc.spots.at(sp).limd; + const float elogt = 2.71828f; + + if (!logli) { + useHslLin = true; + } + + //empirical skip evaluation : very difficult because quasi all parameters interfere + //to test on several images + int nei = (int)(krad * loc.spots.at(sp).neigh); + // printf("neigh=%i\n", nei); + //several test to find good values ???!!! + //very difficult to do because 4 factor are correlate with skip and cannot been solved easily + // size of spots + // radius - neigh + // scal + // variance vart + //not too bad proposition + float divsca = 1.f; + + if (scal >= 3) { + divsca = sqrt(scal / 3.f); + } + + if (skip >= 4) { + //nei = (int)(0.1f * nei + 2.f); //not too bad + nei = (int)(nei / (1.5f * skip)) / divsca; + vart *= sqrt(skip); + } else if (skip > 1 && skip < 4) { + //nei = (int)(0.3f * nei + 2.f); + nei = (int)(nei / skip) / divsca; + vart *= sqrt(skip); + } + + int moderetinex = 0; + + if (loc.spots.at(sp).retinexMethod == "uni") { + moderetinex = 0; + } else if (loc.spots.at(sp).retinexMethod == "low") { + moderetinex = 1; + } else if (loc.spots.at(sp).retinexMethod == "high") { + moderetinex = 2; + } + + const float high = 0.f; // Dummy to pass to retinex_scales(...) + + constexpr auto maxRetinexScales = 10; + float RetinexScales[maxRetinexScales]; + + retinex_scales(RetinexScales, scal, moderetinex, nei, high); + + + const int H_L = height; + const int W_L = width; + std::unique_ptr> srcBuffer(new JaggedArray(W_L, H_L)); + float** src = *(srcBuffer.get()); + + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H_L; i++) + for (int j = 0; j < W_L; j++) { + src[i][j] = luminance[i][j] + eps; + luminance[i][j] = 0.f; + } + + JaggedArray out(W_L, H_L); + + float clipt = loc.spots.at(sp).cliptm; + + const float logBetaGain = xlogf(16384.f); + float pond = logBetaGain / (float) scal; + + if (!useHslLin) { + pond /= log(elogt); + } + + float kr = 1.f;//on FFTW + float kg = 1.f;//on Gaussianblur + std::unique_ptr buffer; + buffer.reset(new float[W_L * H_L]); + + for (int scale = scal - 1; scale >= 0; --scale) { + // printf("retscale=%f scale=%i \n", mulradiusfftw * RetinexScales[scale], scale); + //emprical adjustement between FFTW radius and Gaussainblur + //under 50 ==> 10.f + // 400 ==> 1.f + float sigm = 1.f; + + if (settings->fftwsigma == false) { //empirical formula + sigm = RetinexScales[scale]; + float ak = -9.f / 350.f; + float bk = 10.f - 50.f * ak; + kr = ak * sigm + bk; + + if (sigm < 50.f) { + kr = 10.f; + } + + //above 400 at 5000 ==> 20.f + if (sigm > 400.f) { //increase ==> 5000 + float ka = 19.f / 4600.f; + float kb = 1.f - 400 * ka; + kr = ka * sigm + kb; + float kga = -0.14f / 4600.f;//decrease + float kgb = 1.f - 400.f * kga; + kg = kga * sigm + kgb; + + if (sigm > 5000.f) { + kr = ka * 5000.f + kb; + kg = kga * 5000.f + kgb; + } + + } + } else {//sigma *= sigma + kg = 1.f; + kr = sigm; + } + printf("call=%i\n", call); + if (!fftw) { // || (fftw && call != 2)) { + if (scale == scal - 1) { + gaussianBlur(src, out, W_L, H_L, kg * RetinexScales[scale], true); + } else { // reuse result of last iteration + // out was modified in last iteration => restore it + gaussianBlur(out, out, W_L, H_L, sqrtf(SQR(kg * RetinexScales[scale]) - SQR(kg * RetinexScales[scale + 1])), true); + } + } else { + if (scale == scal - 1) { + if (settings->fftwsigma == false) { //empirical formula + ImProcFunctions::fftw_convol_blur2(src, out, bfwr, bfhr, (kr * RetinexScales[scale]), 0, 0); + } else { + ImProcFunctions::fftw_convol_blur2(src, out, bfwr, bfhr, (SQR(RetinexScales[scale])), 0, 0); + } + } else { // reuse result of last iteration + // out was modified in last iteration => restore it + if (settings->fftwsigma == false) { //empirical formula + ImProcFunctions::fftw_convol_blur2(out, out, bfwr, bfhr, sqrtf(SQR(kr * RetinexScales[scale]) - SQR(kr * RetinexScales[scale + 1])), 0, 0); + } else { + ImProcFunctions::fftw_convol_blur2(out, out, bfwr, bfhr, (SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])), 0, 0); + } + } + } + + if (scale == 1) { //equalize last scale with darkness and lightness of course acts on TM! + if (dar != 1.f || lig != 1.f) { + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < H_L; ++y) { + for (int x = 0; x < W_L; ++x) { + float buf = (src[y][x] - out[y][x]) * value; + buf *= (buf > 0.f) ? lig : dar; + out[y][x] = LIM(out[y][x] + buf, -100000.f, 100000.f); } } + } + + } + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H_L; i++) { + int j = 0; + +#ifdef __SSE2__ + const vfloat pondv = F2V(pond); + const vfloat limMinv = F2V(ilimD); + const vfloat limMaxv = F2V(limD); + + if (useHslLin) { + for (; j < W_L - 3; j += 4) { + STVFU(luminance[i][j], LVFU(luminance[i][j]) + pondv * vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv)); + } + } else { + for (; j < W_L - 3; j += 4) { + STVFU(luminance[i][j], LVFU(luminance[i][j]) + pondv * xlogf(vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv))); + } + } #endif - if (useHslLin) { - for (; j < W_L; j++) { - luminance[i][j] += pond * (LIM(src[i][j] / out[i][j], ilimdx, limdx)); - } - } else { - for (; j < W_L; j++) { - luminance[i][j] += pond * xlogf(LIM(src[i][j] / out[i][j], ilimdx, limdx)); // /logt ? - } + if (useHslLin) { + for (; j < W_L; j++) { + luminance[i][j] += pond * (LIM(src[i][j] / out[i][j], ilimD, limD)); + } + } else { + for (; j < W_L; j++) { + luminance[i][j] += pond * xlogf(LIM(src[i][j] / out[i][j], ilimD, limD)); } } } - if (mapmet > 1) { - if (shmap) { - delete shmap; + } + +// srcBuffer.reset(); + + + if (scal == 1) {//only if user select scal = 1 + + float kval = 1.f; +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int y = 0; y < H_L; ++y) { + for (int x = 0; x < W_L; ++x) { + float threslow = threslum * 163.f; + + if (src[y][x] < threslow) { + kval = src[y][x] / threslow; + } } } - shmap = nullptr; - delete [] buffer; - delete [] srcBuffer; +#ifdef _OPENMP + #pragma omp parallel for +#endif - float mean = 0.f; - float stddv = 0.f; - // I call mean_stddv2 instead of mean_stddv ==> logBetaGain + for (int y = 0; y < H_L; ++y) { + for (int x = 0; x < W_L; ++x) { + float buf = (src[y][x] - out[y][x]) * value_1; + buf *= (buf > 0.f) ? lig : dar; + luminance[y][x] = LIM(src[y][x] + (1.f + kval) * buf, -32768.f, 32768.f); + } + } + + double avg = 0.f; + int ng = 0; + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H_L; i++) { + for (int j = 0; j < W_L; j++) { + avg += luminance[i][j]; + ng++; + } + } + + avg /= ng; + avg /= 32768.f; + avg = LIM01(avg); + float contreal = 0.5f * vart; + DiagonalCurve reti_contrast({ + DCT_NURBS, + 0, 0, + avg - avg * (0.6 - contreal / 250.0), avg - avg * (0.6 + contreal / 250.0), + avg + (1 - avg) * (0.6 - contreal / 250.0), avg + (1 - avg) * (0.6 + contreal / 250.0), + 1, 1 + }); + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H_L; i++) + for (int j = 0; j < W_L; j++) { + float buf = LIM01(luminance[i][j] / 32768.f); + buf = reti_contrast.getVal(buf); + buf *= 32768.f; + luminance[i][j] = buf; + } + + } + + srcBuffer.reset(); + + float str = strength * (chrome == 0 ? 1.f : 0.8f * (chrT - 0.4f)); + const float maxclip = (chrome == 0 ? 32768.f : 50000.f); + + if (scal != 1) { + mean = 0.f; + stddv = 0.f; mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr); - //printf("mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", mean, stddv, delta, maxtr, mintr); + // printf("mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", mean, stddv, delta, maxtr, mintr); - //mean_stddv( luminance, mean, stddv, W_L, H_L, logBetaGain, maxtr, mintr); - if (dehatransmissionCurve && mean != 0.f && stddv != 0.f) { //if curve + if (locRETtransCcurve && mean != 0.f && stddv != 0.f) { //if curve float asig = 0.166666f / stddv; float bsig = 0.5f - asig * mean; float amax = 0.333333f / (maxtr - mean - stddv); @@ -627,848 +1473,15 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e } //TODO : move multiplication by 4.f and subtraction of 1.f inside the curve - luminance[i][j] *= (-1.f + 4.f * dehatransmissionCurve[absciss]); //new transmission + luminance[i][j] *= (-1.f + 4.f * locRETtransCcurve[absciss]); //new transmission - if (viewmet == 3 || viewmet == 2) { - tran[i][j] = luminance[i][j]; - } } } - - // median filter on transmission ==> reduce artifacts - if (deh.medianmap && it == 1) { //only one time - int wid = W_L; - int hei = H_L; - float *tmL[hei] ALIGNED16; - float *tmLBuffer = new float[wid * hei]; - int borderL = 1; - - for (int i = 0; i < hei; i++) { - tmL[i] = &tmLBuffer[i * wid]; - } - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = borderL; i < hei - borderL; i++) { - for (int j = borderL; j < wid - borderL; j++) { - tmL[i][j] = median(luminance[i][j], luminance[i - 1][j], luminance[i + 1][j], luminance[i][j + 1], luminance[i][j - 1], luminance[i - 1][j - 1], luminance[i - 1][j + 1], luminance[i + 1][j - 1], luminance[i + 1][j + 1]); //3x3 - } - } - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = borderL; i < hei - borderL; i++) { - for (int j = borderL; j < wid - borderL; j++) { - luminance[i][j] = tmL[i][j]; - } - } - - delete [] tmLBuffer; - - } - - // I call mean_stddv2 instead of mean_stddv ==> logBetaGain - //mean_stddv( luminance, mean, stddv, W_L, H_L, 1.f, maxtr, mintr); - mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr); - - } - - float epsil = 0.1f; - - mini = mean - varx * stddv; - - if (mini < mintr) { - mini = mintr + epsil; - } - - maxi = mean + varx * stddv; - - if (maxi > maxtr) { - maxi = maxtr - epsil; - } - - float delta = maxi - mini; - //printf("maxi=%f mini=%f mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", maxi, mini, mean, stddv, delta, maxtr, mintr); - - if (!delta) { - delta = 1.0f; - } - - float cdfactor = 32768.f / delta; - maxCD = -9999999.f; - minCD = 9999999.f; - // coeff for auto "transmission" with 2 sigma #95% data - float aza = 16300.f / (2.f * stddv); - float azb = -aza * (mean - 2.f * stddv); - float bza = 16300.f / (2.f * stddv); - float bzb = 16300.f - bza * (mean); - -//prepare work for curve gain -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = 0; i < H_L; i++) { - for (int j = 0; j < W_L; j++) { - luminance[i][j] = luminance[i][j] - mini; - } } mean = 0.f; stddv = 0.f; - // I call mean_stddv2 instead of mean_stddv ==> logBetaGain - - mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr); - float asig = 0.f, bsig = 0.f, amax = 0.f, bmax = 0.f, amin = 0.f, bmin = 0.f; - - if (dehagaintransmissionCurve && mean != 0.f && stddv != 0.f) { //if curve - asig = 0.166666f / stddv; - bsig = 0.5f - asig * mean; - amax = 0.333333f / (maxtr - mean - stddv); - bmax = 1.f - amax * maxtr; - amin = 0.333333f / (mean - stddv - mintr); - bmin = -amin * mintr; - - asig *= 500.f; - bsig *= 500.f; - amax *= 500.f; - bmax *= 500.f; - amin *= 500.f; - bmin *= 500.f; - } - -#ifdef _OPENMP - #pragma omp parallel -#endif - { - float cdmax = -999999.f, cdmin = 999999.f; -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) nowait -#endif - - for (int i = 0; i < H_L; i ++) - for (int j = 0; j < W_L; j++) { - float gan; - - if (dehagaintransmissionCurve && mean != 0.f && stddv != 0.f) { - float absciss; - - if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) { - absciss = asig * luminance[i][j] + bsig; - } else if (luminance[i][j] >= mean) { - absciss = amax * luminance[i][j] + bmax; - } else { /*if(luminance[i][j] <= mean - stddv)*/ - absciss = amin * luminance[i][j] + bmin; - } - - - // float cd = cdfactor * ( luminance[i][j] - mini ) + offse; - // TODO : move multiplication by 2.f inside the curve - gan = 2.f * (dehagaintransmissionCurve[absciss]); //new gain function transmission - } else { - gan = 0.5f; - } - - float cd = gan * cdfactor * (luminance[i][j]) + offse; - - cdmax = cd > cdmax ? cd : cdmax; - cdmin = cd < cdmin ? cd : cdmin; - - float str = strengthx; - - if (lhutili && it == 1) { // S=f(H) - { - float HH = exLuminance[i][j]; - float valparam; - - if (useHsl || useHslLin) { - valparam = float ((shcurve->getVal(HH) - 0.5f)); - } else { - valparam = float ((shcurve->getVal(Color::huelab_to_huehsv2(HH)) - 0.5f)); - } - - str *= (1.f + 2.f * valparam); - } - } - - if (higplus && exLuminance[i][j] > 65535.f * hig) { - str *= hig; - } - - if (viewmet == 0) { - luminance[i][j] = intp(str, clipretinex(cd, 0.f, 32768.f), originalLuminance[i][j]); - } else if (viewmet == 1) { - luminance[i][j] = out[i][j]; - } else if (viewmet == 4) { - luminance[i][j] = originalLuminance[i][j] + str * (originalLuminance[i][j] - out[i][j]);//unsharp - } else if (viewmet == 2) { - if (tran[i][j] <= mean) { - luminance[i][j] = azb + aza * tran[i][j]; //auto values - } else { - luminance[i][j] = bzb + bza * tran[i][j]; - } - } else { /*if(viewmet == 3) */ - luminance[i][j] = 1000.f + tran[i][j] * 700.f; //arbitrary values to help display log values which are between -20 to + 30 - usage values -4 + 5 - } - - } - -#ifdef _OPENMP - #pragma omp critical -#endif - { - maxCD = maxCD > cdmax ? maxCD : cdmax; - minCD = minCD < cdmin ? minCD : cdmin; - } - - } - - delete [] outBuffer; - outBuffer = nullptr; - //printf("cdmin=%f cdmax=%f\n",minCD, maxCD); - Tmean = mean; - Tsigma = stddv; - Tmin = mintr; - Tmax = maxtr; - - if (shcurve) { - delete shcurve; - shcurve = nullptr; - } - } - - if (tranBuffer) { - delete [] tranBuffer; - } - - } -} - -void ImProcFunctions::MSRLocal(int sp, bool fftw, int lum, LabImage * bufreti, LabImage * bufmask, LabImage * buforig, LabImage * buforigmas, float** luminance, float** templ, const float* const *originalLuminance, const int width, const int height, const LocallabParams &loc, const int skip, const LocretigainCurve &locRETgainCcurve, const int chrome, const int scall, const float krad, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, - const LocCCmaskretiCurve & locccmasretiCurve, bool &lcmasretiutili, const LocLLmaskretiCurve & locllmasretiCurve, bool &llmasretiutili, const LocHHmaskretiCurve & lochhmasretiCurve, bool & lhmasretiutili, int llretiMask, LabImage * transformed, bool retiMasktmap, bool retiMask) -{ - BENCHFUN - bool py = true; - - if (py) {//enabled - float mean, stddv, maxtr, mintr; - float delta; - constexpr float eps = 2.f; - bool useHslLin = false; - const float offse = 0.f; //loc.offs; - const float chrT = (float)(loc.spots.at(sp).chrrt) / 100.f; - const int scal = (loc.spots.at(sp).scalereti); - float vart = loc.spots.at(sp).vart / 100.f;//variance - const float strength = loc.spots.at(sp).str / 100.f; // Blend with original L channel data - const float dar = loc.spots.at(sp).darkness; - const float lig = loc.spots.at(sp).lightnessreti; - float value = pow(strength, 0.4f); - float value_1 = pow(strength, 0.3f); - - float limD = loc.spots.at(sp).limd;//10.f - limD = pow(limD, 1.7f); //about 2500 enough - float ilimD = 1.f / limD; - float threslum = loc.spots.at(sp).limd; - const float elogt = 2.71828f; - - if (scal < 3) { - useHslLin = true; - } - - //empirical skip evaluation : very difficult because quasi all parameters interfere - //to test on several images - int nei = (int)(krad * loc.spots.at(sp).neigh); - // printf("neigh=%i\n", nei); - //several test to find good values ???!!! - //very difficult to do because 4 factor are correlate with skip and cannot been solved easily - // size of spots - // radius - neigh - // scal - // variance vart - //not too bad proposition - float divsca = 1.f; - if(scal >=3) divsca = sqrt(scal / 3.f); - - if (skip >= 4) { - //nei = (int)(0.1f * nei + 2.f); //not too bad - nei = (int)(nei / (1.5f * skip))/ divsca; - vart *= sqrt(skip); - } else if (skip > 1 && skip < 4) { - //nei = (int)(0.3f * nei + 2.f); - nei = (int)(nei / skip) / divsca; - vart *= sqrt(skip); - } - - int moderetinex = 0; - - if (loc.spots.at(sp).retinexMethod == "uni") { - moderetinex = 0; - } else if (loc.spots.at(sp).retinexMethod == "low") { - moderetinex = 1; - } else { - if (loc.spots.at(sp).retinexMethod == "high") { - moderetinex = 2; - } - } - - const float high = 0.f; // Dummy to pass to retinex_scales(...) - - constexpr auto maxRetinexScales = 10; - float RetinexScales[maxRetinexScales]; - - retinex_scales(RetinexScales, scal, moderetinex, nei, high); - - - const int H_L = height; - const int W_L = width; - - // array2D src(W_L, H_L); - // array2D out(W_L, H_L); - - float *src[H_L] ALIGNED16; - float *srcBuffer = new float[H_L * W_L]; - - for (int i = 0; i < H_L; i++) { - src[i] = &srcBuffer[i * W_L]; - } - - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = 0; i < H_L; i++) - for (int j = 0; j < W_L; j++) { - src[i][j] = luminance[i][j] + eps; - luminance[i][j] = 0.f; - } - - float *out[H_L] ALIGNED16; - float *outBuffer = new float[H_L * W_L]; - - for (int i = 0; i < H_L; i++) { - out[i] = &outBuffer[i * W_L]; - } - - const float logBetaGain = xlogf(16384.f); - float pond = logBetaGain / (float) scal; - - if (!useHslLin) { - pond /= log(elogt); - } - - float *buffer = new float[W_L * H_L]; - float kr = 1.f;//on FFTW - float kg = 1.f;//on Gaussianblur - for (int scale = scal - 1; scale >= 0; scale--) { - // printf("retscale=%f scale=%i \n", mulradiusfftw * RetinexScales[scale], scale); - //emprical adjustement between FFTW radius and Gaussainblur - //under 50 ==> 10.f - // 400 ==> 1.f - float sigm = 1.f; - if(settings->fftwsigma == false) {//empirical formula - sigm = RetinexScales[scale]; - float ak = -9.f / 350.f; - float bk = 10.f - 50.f * ak; - kr = ak * sigm + bk; - if(sigm < 50.f) kr = 10.f; - //above 400 at 5000 ==> 20.f - if(sigm > 400.f) {//increase ==> 5000 - float ka = 19.f / 4600.f; - float kb = 1.f - 400 * ka; - kr = ka * sigm + kb; - float kga = -0.14f / 4600.f;//decrease - float kgb = 1.f - 400.f * kga; - kg = kga * sigm + kgb; - if(sigm > 5000.f) { - kr = ka * 5000.f + kb; - kg = kga * 5000.f + kgb; - } - - } - } else {//sigma *= sigma - kg = 1.f; - kr = sigm; - } - if(!fftw) { -#ifdef _OPENMP - #pragma omp parallel //disabled with FFTW -#endif - { - - if (scale == scal - 1) - { - gaussianBlur(src, out, W_L, H_L, kg * RetinexScales[scale], buffer); - } else // reuse result of last iteration - { - // out was modified in last iteration => restore it - gaussianBlur(out, out, W_L, H_L, sqrtf(SQR(kg * RetinexScales[scale]) - SQR(kg * RetinexScales[scale + 1])), buffer); - } - } - } else { - if (scale == scal - 1) - { - if(settings->fftwsigma == false) {//empirical formula - ImProcFunctions::fftw_convol_blur2(src, out, W_L, H_L, (kr * RetinexScales[scale]), 0, 0); - } else { - ImProcFunctions::fftw_convol_blur2(src, out, W_L, H_L, (SQR(RetinexScales[scale])), 0, 0); - } - } else // reuse result of last iteration - { - // out was modified in last iteration => restore it - if(settings->fftwsigma == false) {//empirical formula - ImProcFunctions::fftw_convol_blur2(out, out, W_L, H_L,sqrtf(SQR(kr * RetinexScales[scale]) - SQR(kr * RetinexScales[scale + 1])), 0, 0); - } else { - ImProcFunctions::fftw_convol_blur2(out, out, W_L, H_L,(SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])), 0, 0); - } - } - } - if (scale == 1) { //equalize last scale with darkness and lightness - - if (dar != 1.f || lig != 1.f) { -// float value = pow(strength, 0.4f); - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int y = 0; y < H_L; ++y) { - for (int x = 0; x < W_L; ++x) { - float buf = (src[y][x] - out[y][x]) * value; - buf *= (buf > 0.f) ? lig : dar; - out[y][x] = LIM(out[y][x] + buf, 0.f, 100000.f); - } - } - } - } - - if (lum == 1 && scale == 1 && (llretiMask == 3 || llretiMask == 0 || llretiMask == 2 || llretiMask == 4)) { //only mask with luminance on last scale - array2D loctemp(W_L, H_L); - array2D ble(W_L, H_L); - array2D guid(W_L, H_L); - std::unique_ptr bufmaskblurreti; - bufmaskblurreti.reset(new LabImage(W_L, H_L)); - std::unique_ptr bufmaskorigreti; - bufmaskorigreti.reset(new LabImage(W_L, H_L)); -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < H_L; y++) { - for (int x = 0; x < W_L; x++) { - if (retiMasktmap) { - loctemp[y][x] = out[y][x]; - } else { - loctemp[y][x] = bufreti->L[y][x]; - } - } - } - - float fab = 4000.f;//value must be good in most cases - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < H_L; ir++) { - for (int jr = 0; jr < W_L; jr++) { - float kmaskLexp = 0; - float kmaskCH = 0; - - if (locllmasretiCurve && llmasretiutili) { - float ligh = loctemp[ir][jr] / 32768.f; - kmaskLexp = 32768.f * LIM01(1.f - locllmasretiCurve[500.f * ligh]); - } - - - if (locllmasretiCurve && llmasretiutili && retiMasktmap) { - } - - if (llretiMask != 4) { - if (locccmasretiCurve && lcmasretiutili) { - float chromask = 0.0001f + sqrt(SQR((bufreti->a[ir][jr]) / fab) + SQR((bufreti->b[ir][jr]) / fab)); - kmaskCH = LIM01(1.f - locccmasretiCurve[500.f * chromask]); - } - } - - if (lochhmasretiCurve && lhmasretiutili) { - float huema = xatan2f(bufreti->b[ir][jr], bufreti->a[ir][jr]); - float h = Color::huelab_to_huehsv2(huema); - h += 1.f / 6.f; - - if (h > 1.f) { - h -= 1.f; - } - - float valHH = LIM01(1.f - lochhmasretiCurve[500.f * h]); - - if (llretiMask != 4) { - kmaskCH += valHH; - } - - kmaskLexp += 32768.f * valHH; - } - - // printf("km=%f ",kmaskLexp); - bufmaskblurreti->L[ir][jr] = kmaskLexp; - bufmaskblurreti->a[ir][jr] = kmaskCH; - bufmaskblurreti->b[ir][jr] = kmaskCH; - ble[ir][jr] = bufmaskblurreti->L[ir][jr] / 32768.f; - guid[ir][jr] = bufreti->L[ir][jr] / 32768.f; - - } - } - - if (loc.spots.at(sp).radmaskreti > 0.f) { - guidedFilter(guid, ble, ble, loc.spots.at(sp).radmaskreti * 10.f / skip, 0.001, multiThread, 4); - } - - LUTf lutTonemaskreti(65536); - calcGammaLut(loc.spots.at(sp).gammaskreti, loc.spots.at(sp).slomaskreti, lutTonemaskreti); - float radiusb = 1.f / skip; - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int ir = 0; ir < H_L; ir++) - for (int jr = 0; jr < W_L; jr++) { - float L_; - bufmaskblurreti->L[ir][jr] = LIM01(ble[ir][jr]) * 32768.f; - L_ = 2.f * bufmaskblurreti->L[ir][jr]; - bufmaskblurreti->L[ir][jr] = lutTonemaskreti[L_]; - } - -//blend -#ifdef _OPENMP - #pragma omp parallel -#endif - { - gaussianBlur(bufmaskblurreti->L, bufmaskorigreti->L, W_L, H_L, radiusb); - gaussianBlur(bufmaskblurreti->a, bufmaskorigreti->a, W_L, H_L, 1.f + (0.5f * loc.spots.at(sp).radmaskreti) / skip); - gaussianBlur(bufmaskblurreti->b, bufmaskorigreti->b, W_L, H_L, 1.f + (0.5f * loc.spots.at(sp).radmaskreti) / skip); - } - - float modr = 0.01f * (float) loc.spots.at(sp).blendmaskreti; - - if (llretiMask != 3 && retiMask) { -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < H_L; y++) { - for (int x = 0; x < W_L; x++) { - if (retiMasktmap) { - out[y][x] += fabs(modr) * bufmaskorigreti->L[y][x]; - out[y][x] = LIM(out[y][x], 0.f, 100000.f); - } else { - bufreti->L[y][x] += bufmaskorigreti->L[y][x] * modr; - bufreti->L[y][x] = CLIPLOC(bufreti->L[y][x]); - - } - - bufreti->a[y][x] *= (1.f + bufmaskorigreti->a[y][x] * modr * (1.f + 0.01f * loc.spots.at(sp).chromaskreti)); - bufreti->b[y][x] *= (1.f + bufmaskorigreti->b[y][x] * modr * (1.f + 0.01f * loc.spots.at(sp).chromaskreti)); - bufreti->a[y][x] = CLIPC(bufreti->a[y][x]); - bufreti->b[y][x] = CLIPC(bufreti->b[y][x]); - } - } - } - - if (!retiMasktmap && retiMask) { //new original blur mask for deltaE -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < H_L; y++) { - for (int x = 0; x < W_L; x++) { - - buforig->L[y][x] += (modr * bufmaskorigreti->L[y][x]); - buforig->a[y][x] *= (1.f + modr * bufmaskorigreti->a[y][x]); - buforig->b[y][x] *= (1.f + modr * bufmaskorigreti->b[y][x]); - - buforig->L[y][x] = CLIP(buforig->L[y][x]); - buforig->a[y][x] = CLIPC(buforig->a[y][x]); - buforig->b[y][x] = CLIPC(buforig->b[y][x]); - - buforig->L[y][x] = CLIP(buforig->L[y][x] - bufmaskorigreti->L[y][x]); - buforig->a[y][x] = CLIPC(buforig->a[y][x] * (1.f - bufmaskorigreti->a[y][x])); - buforig->b[y][x] = CLIPC(buforig->b[y][x] * (1.f - bufmaskorigreti->b[y][x])); - } - } - - float radius = 3.f / skip; - -#ifdef _OPENMP - #pragma omp parallel if (multiThread) -#endif - { - gaussianBlur(buforig->L, buforigmas->L, W_L, H_L, radius); - gaussianBlur(buforig->a, buforigmas->a, W_L, H_L, radius); - gaussianBlur(buforig->b, buforigmas->b, W_L, H_L, radius); - } - - } - - if (llretiMask == 3) { - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < H_L; y++) { - for (int x = 0; x < W_L; x++) { - bufmask->L[y][x] = 6000.f + CLIPLOC(bufmaskorigreti->L[y][x]); - bufmask->a[y][x] = CLIPC(bufreti->a[y][x] * bufmaskorigreti->a[y][x]); - bufmask->b[y][x] = CLIPC(bufreti->b[y][x] * bufmaskorigreti->b[y][x]); - } - } - - } - } - - - -#ifdef __SSE2__ - vfloat pondv = F2V(pond); - vfloat limMinv = F2V(ilimD); - vfloat limMaxv = F2V(limD); -#endif -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = 0; i < H_L; i++) { - int j = 0; - -#ifdef __SSE2__ - - if (useHslLin) { //keep in case of ?? - for (; j < W_L - 3; j += 4) { - _mm_storeu_ps(&luminance[i][j], LVFU(luminance[i][j]) + pondv * (vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv))); - } - } else { - for (; j < W_L - 3; j += 4) { - _mm_storeu_ps(&luminance[i][j], LVFU(luminance[i][j]) + pondv * xlogf(vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv))); - } - } - -#endif - - if (useHslLin) { - for (; j < W_L; j++) { - luminance[i][j] += pond * (LIM(src[i][j] / out[i][j], ilimD, limD)); - } - } else { - for (; j < W_L; j++) { - luminance[i][j] += pond * xlogf(LIM(src[i][j] / out[i][j], ilimD, limD)); - } - } - } - - } - - if (scal != 1) { - float mintran = luminance[0][0]; - float maxtran = mintran; - -#ifdef _OPENMP - #pragma omp parallel for reduction(min:mintran) reduction(max:maxtran) schedule(dynamic,16) -#endif - - for (int ir = 0; ir < H_L; ir++) { - for (int jr = 0; jr < W_L; jr++) { - mintran = rtengine::min(luminance[ir][jr], mintran); - maxtran = rtengine::max(luminance[ir][jr], maxtran); - } - } - - float deltatran = maxtran - mintran; - -// printf("minT=%f maxT=%f delt=%f \n", mintran, maxtran, deltatran); -//here add GuidFilter for transmission map - array2D ble(W_L, H_L); - array2D guid(W_L, H_L); -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = 0; i < H_L; i ++) - for (int j = 0; j < W_L; j++) { - guid[i][j] = src[i][j] / 32768.f; - ble[i][j] = (luminance[i][j] + mintran) / deltatran; - } - - double epsilmax = 1e-5; - double epsilmin = 1e-6; - float radi = loc.spots.at(sp).softradiusret; - - if (loc.spots.at(sp).softradiusret > 0.f) { - double aepsil = (epsilmax - epsilmin) / 90.f; - double bepsil = epsilmax - 100.f * aepsil; - double epsil = aepsil * radi + bepsil; - - float blur = 10.f / skip * (0.00001f + 0.8f * radi); - rtengine::guidedFilter(guid, ble, ble, blur, epsil, multiThread, 4); - - } - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = 0; i < H_L; i ++) - for (int j = 0; j < W_L; j++) { - luminance[i][j] = ble[i][j] * deltatran + mintran; - } - ble(0,0); - guid(0,0); - } - - - if (scal == 1) { //use only local contrast - float kval = 1.f; -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int y = 0; y < H_L; ++y) { - for (int x = 0; x < W_L; ++x) { - float threslow = threslum * 163.f; - - if (src[y][x] < threslow) { - kval = src[y][x] / threslow; - } - } - } - - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int y = 0; y < H_L; ++y) { - for (int x = 0; x < W_L; ++x) { - float buf = (src[y][x] - out[y][x]) * value_1; - buf *= (buf > 0.f) ? lig : dar; - luminance[y][x] = LIM(src[y][x] + (1.f + kval) * buf, 0.f, 32768.f); - } - } - - double avg = 0.f; - int ng = 0; - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = 0; i < H_L; i++) { - for (int j = 0; j < W_L; j++) { - avg += luminance[i][j]; - ng++; - } - } - - avg /= ng; - avg /= 32768.f; - avg = LIM01(avg); - float contreal = 20.f * vart; - DiagonalCurve reti_contrast({ - DCT_NURBS, - 0, 0, - avg - avg * (0.6 - contreal / 250.0), avg - avg * (0.6 + contreal / 250.0), - avg + (1 - avg) * (0.6 - contreal / 250.0), avg + (1 - avg) * (0.6 + contreal / 250.0), - 1, 1 - }); - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = 0; i < H_L; i++) - for (int j = 0; j < W_L; j++) { - float buf = LIM01(luminance[i][j] / 32768.f); - buf = reti_contrast.getVal(buf); - buf *= 32768.f; - luminance[i][j] = buf; - } - } - - if (scal == 1) { - float mintran = luminance[0][0]; - float maxtran = mintran; - -#ifdef _OPENMP - #pragma omp parallel for reduction(min:mintran) reduction(max:maxtran) schedule(dynamic,16) -#endif - - for (int ir = 0; ir < H_L; ir++) { - for (int jr = 0; jr < W_L; jr++) { - mintran = rtengine::min(luminance[ir][jr], mintran); - maxtran = rtengine::max(luminance[ir][jr], maxtran); - } - } - - float deltatran = maxtran - mintran; - array2D ble(W_L, H_L); - array2D guid(W_L, H_L); -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = 0; i < H_L; i ++) - for (int j = 0; j < W_L; j++) { - guid[i][j] = src[i][j] / 32768.f; - ble[i][j] = (luminance[i][j] + mintran) / deltatran; - } - - double epsilmax = 1e-3; - double epsilmin = 1e-4; - float radi = loc.spots.at(sp).softradiusret; - - if (loc.spots.at(sp).softradiusret > 0.f) { - double aepsil = (epsilmax - epsilmin) / 90.f; - double bepsil = epsilmax - 100.f * aepsil; - double epsil = aepsil * radi + bepsil; - - float blur = 10.f / skip * (0.001f + 0.1f * radi); - rtengine::guidedFilter(guid, ble, ble, blur, epsil, multiThread, 4); - - } - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = 0; i < H_L; i ++) - for (int j = 0; j < W_L; j++) { - luminance[i][j] = ble[i][j] * deltatran + mintran; - } - ble(0,0); - guid(0,0); - - } - delete [] buffer; -// src(0,0); -// out(0,0); - delete [] outBuffer; - outBuffer = nullptr; - delete [] srcBuffer; - srcBuffer = nullptr; - - float str = strength * (chrome == 0 ? 1.f : 0.8f * (chrT - 0.4f)); - const float maxclip = (chrome == 0 ? 32768.f : 50000.f); - - if (scal != 1) { - mean = 0.f; - stddv = 0.f; - - mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr); - // printf("mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", mean, stddv, delta, maxtr, mintr); + mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr);//new calculation of mean... float epsil = 0.1f; @@ -1485,13 +1498,21 @@ void ImProcFunctions::MSRLocal(int sp, bool fftw, int lum, LabImage * bufreti, L } delta = maxi - mini; - // printf("maxi=%f mini=%f mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", maxi, mini, mean, stddv, delta, maxtr, mintr); + // printf("maxi=%f mini=%f mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", maxi, mini, mean, stddv, delta, maxtr, mintr); if (!delta) { delta = 1.0f; } - float cdfactor = 32768.f / delta; + + float *copylum[H_L] ALIGNED16; + float *copylumBuffer = new float[H_L * W_L]; + + for (int i = 0; i < H_L; i++) { + copylum[i] = ©lumBuffer[i * W_L]; + } + + float cdfactor = (clipt * 32768.f) / delta; maxCD = -9999999.f; minCD = 9999999.f; //prepare work for curve gain @@ -1507,9 +1528,10 @@ void ImProcFunctions::MSRLocal(int sp, bool fftw, int lum, LabImage * bufreti, L mean = 0.f; stddv = 0.f; - // I call mean_stddv2 instead of mean_stddv ==> logBetaGain mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr); +// printf("meanun=%f stdun=%f maxtr=%f mintr=%f\n", mean, stddv, maxtr, mintr); + float asig = 0.f, bsig = 0.f, amax = 0.f, bmax = 0.f, amin = 0.f, bmin = 0.f; const bool hasRetGainCurve = locRETgainCcurve && mean != 0.f && stddv != 0.f; @@ -1529,7 +1551,7 @@ void ImProcFunctions::MSRLocal(int sp, bool fftw, int lum, LabImage * bufreti, L bmin *= 500.f; cdfactor *= 2.f; } - + #ifdef _OPENMP #pragma omp parallel @@ -1545,7 +1567,7 @@ void ImProcFunctions::MSRLocal(int sp, bool fftw, int lum, LabImage * bufreti, L for (int i = 0; i < H_L; i ++) for (int j = 0; j < W_L; j++) { - + if (hasRetGainCurve) { float absciss; @@ -1559,12 +1581,14 @@ void ImProcFunctions::MSRLocal(int sp, bool fftw, int lum, LabImage * bufreti, L gan = locRETgainCcurve[absciss]; //new gain function transmission } - + + //but we don't update mean stddv for display only... + copylum[i][j] = gan * luminance[i][j];//update datas for display float cd = gan * cdfactor * luminance[i][j] + offse; cdmax = cd > cdmax ? cd : cdmax; cdmin = cd < cdmin ? cd : cdmin; - luminance[i][j] = CLIPMAX(LIM(cd, 0.f, maxclip) * str + (1.f - str) * originalLuminance[i][j]); + luminance[i][j] = intp(str * reducDE[i][j], clipretinex(cd, 0.f, maxclip), originalLuminance[i][j]); } @@ -1577,7 +1601,14 @@ void ImProcFunctions::MSRLocal(int sp, bool fftw, int lum, LabImage * bufreti, L minCD = minCD < cdmin ? minCD : cdmin; } } + mean = 0.f; + stddv = 0.f; + mean_stddv2(copylum, mean, stddv, W_L, H_L, maxtr, mintr); + delete [] copylumBuffer; + copylumBuffer = nullptr; + +// printf("mean=%f std=%f maxtr=%f mintr=%f\n", mean, stddv, maxtr, mintr); } else { #ifdef _OPENMP @@ -1592,6 +1623,28 @@ void ImProcFunctions::MSRLocal(int sp, bool fftw, int lum, LabImage * bufreti, L } + float rad = loc.spots.at(sp).radmaskreti; + float slop = loc.spots.at(sp).slomaskreti; + float gamm = loc.spots.at(sp).gammaskreti; + float blend = loc.spots.at(sp).blendmaskreti; + float chro = loc.spots.at(sp).chromaskreti; + float lap = loc.spots.at(sp).lapmaskreti; + bool pde = params->locallab.spots.at(sp).laplac; + + if (lum == 1 && (llretiMask == 3 || llretiMask == 0 || llretiMask == 2 || llretiMask == 4)) { //only mask with luminance on last scale + int before = 1; + maskforretinex(sp, before, luminance, nullptr, W_L, H_L, skip, + locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, llretiMask, retiMasktmap, retiMask, + rad, lap, pde, gamm, slop, chro, blend, + lmaskretilocalcurve, localmaskretiutili, + bufreti, bufmask, buforig, buforigmas, multiThread, + delt, hueref, chromaref, lumaref, + maxdE, mindE, maxdElim, mindElim, iterat, limscope, scope, balance, balanceh, lumask + ); + } + + //mask does not interfered with datas displayed + Tmean = mean; Tsigma = stddv; Tmin = mintr; diff --git a/rtengine/ipshadowshighlights.cc b/rtengine/ipshadowshighlights.cc index cfe5a1e4d..fd2ab3db4 100644 --- a/rtengine/ipshadowshighlights.cc +++ b/rtengine/ipshadowshighlights.cc @@ -15,16 +15,21 @@ * GNU General Public License for more details. * * 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" +#include "array2D.h" +#include "color.h" +#include "curves.h" #include "gauss.h" #include "guidedfilter.h" +#include "iccstore.h" +#include "labimage.h" #include "opthelper.h" #include "procparams.h" -#include "sleef.c" +#include "sleef.h" namespace rtengine { //modifications to pass parameters needs by locallab, to avoid 2 functions - no change in process - J.Desmis march 2019 @@ -105,10 +110,10 @@ void ImProcFunctions::shadowsHighlights(LabImage *lab, bool ena, int labmode, in #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 @@ -118,10 +123,10 @@ void ImProcFunctions::shadowsHighlights(LabImage *lab, bool ena, int labmode, in 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; } @@ -132,8 +137,8 @@ void ImProcFunctions::shadowsHighlights(LabImage *lab, bool ena, int labmode, in #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 @@ -143,8 +148,8 @@ void ImProcFunctions::shadowsHighlights(LabImage *lab, bool ena, int labmode, in 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 4ec41fb82..9292fb7bd 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -14,25 +14,30 @@ * GNU General Public License for more details. * * 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" -#include "gauss.h" #include "bilateral2.h" +#include "cieimage.h" +#include "gauss.h" +#include "improcfun.h" #include "jaggedarray.h" -#include "rt_math.h" -#include "procparams.h" -#include "sleef.c" +#include "labimage.h" #include "opthelper.h" +#include "procparams.h" +#include "rt_algo.h" +#include "rt_math.h" +#include "settings.h" +#include "sleef.h" + //#define BENCHMARK #include "StopWatch.h" -#include "rt_algo.h" + using namespace std; namespace { -void sharpenHaloCtrl (float** luminance, float** blurmap, float** base, float** blend, int W, int H, const SharpeningParams &sharpenParam) +void sharpenHaloCtrl (float** luminance, float** blurmap, float** base, float** blend, int W, int H, const procparams::SharpeningParams &sharpenParam) { const float scale = (100.f - sharpenParam.halocontrol_amount) * 0.01f; @@ -156,9 +161,7 @@ void dcdamping (float** aI, float** aO, float damping, int W, int H) 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 procparams::SharpeningParams &sharpenParam, double Scale) { if (sharpenParam.deconvamount == 0 && sharpenParam.blurradius < 0.25f) { return; @@ -175,10 +178,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 +200,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 @@ -211,13 +210,13 @@ BENCHFUN for (int k = 0; k < sharpenParam.deconviter; k++) { if (!needdamp) { // apply gaussian blur and divide luminance by result of gaussian blur - gaussianBlur(tmpI, tmp, W, H, sigma, nullptr, GAUSS_DIV, luminance); + gaussianBlur(tmpI, tmp, W, H, sigma, false, GAUSS_DIV, luminance); } else { // apply gaussian blur + damping gaussianBlur(tmpI, tmp, W, H, sigma); dcdamping(tmp, luminance, damping, W, H); } - gaussianBlur(tmp, tmpI, W, H, sigma, nullptr, GAUSS_MULT); + gaussianBlur(tmp, tmpI, W, H, sigma, false, GAUSS_MULT); } // end for #ifdef _OPENMP @@ -308,14 +307,15 @@ void ImProcFunctions::deconvsharpeningloc (float** luminance, float** tmp, int W for (int k = 0; k < itera; k++) { if (!needdamp) { // apply gaussian blur and divide luminance by result of gaussian blur - gaussianBlur (tmpI, tmp, W, H, sigma, nullptr, GAUSS_DIV, luminance); + // gaussianBlur (tmpI, tmp, W, H, sigma, nullptr, GAUSS_DIV, luminance); + gaussianBlur(tmpI, tmp, W, H, sigma, false, GAUSS_DIV, luminance); } else { // apply gaussian blur + damping gaussianBlur (tmpI, tmp, W, H, sigma); dcdamping (tmp, luminance, damping, W, H); } - gaussianBlur (tmp, tmpI, W, H, sigma, nullptr, GAUSS_MULT); + gaussianBlur (tmp, tmpI, W, H, sigma, false, GAUSS_MULT); } // end for @@ -345,10 +345,7 @@ void ImProcFunctions::deconvsharpeningloc (float** luminance, float** tmp, int W } - - - -void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpenParam, bool showMask) +void ImProcFunctions::sharpening (LabImage* lab, const procparams::SharpeningParams &sharpenParam, bool showMask) { if ((!sharpenParam.enabled) || sharpenParam.amount < 1 || lab->W < 8 || lab->H < 8) { @@ -357,11 +354,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); + 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 @@ -377,7 +375,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 @@ -393,11 +391,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) { @@ -989,11 +982,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 @@ -1006,9 +999,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; } @@ -1024,11 +1016,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 ada1563cd..7df44702e 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,131 @@ * GNU General Public License for more details. * * 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 "color.h" +#include "iccstore.h" #include "improcfun.h" +#include "labimage.h" #include "procparams.h" -namespace rtengine { +namespace rtengine +{ -namespace { +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; } - } // namespace +#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 -void ImProcFunctions::softLight(LabImage *lab, const SoftLightParams &softLightParams) +//} // namespace + +void ImProcFunctions::softLight(LabImage *lab, const rtengine::procparams::SoftLightParams &softLightParams) { if (!softLightParams.enabled || !softLightParams.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 = softLightParams.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 = softLightParams.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 +} \ No newline at end of file diff --git a/rtengine/iptcpairs.h b/rtengine/iptcpairs.h index e0b34180f..af45d7d38 100644 --- a/rtengine/iptcpairs.h +++ b/rtengine/iptcpairs.h @@ -14,11 +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 _IPTCPAIRS_ -#define _IPTCPAIRS_ - +#pragma once struct IptcPair { IptcTag tag; @@ -44,6 +42,3 @@ const IptcPair strTags[] = { {IPTC_TAG_ORIG_TRANS_REF, 32, "TransReference"}, {IPTC_TAG_DATE_CREATED, 8, "DateCreated"} }; - -#endif - diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index beca624a8..a9a84ea3f 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -14,19 +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 . */ -#include "rtengine.h" -#include "improcfun.h" -#include "procparams.h" -#ifdef _OPENMP -#include -#endif -#include "mytime.h" -#include "rt_math.h" -#include "sleef.c" -#include "rtlensfun.h" +#include +#include "imagefloat.h" +#include "improcfun.h" + +#include "procparams.h" +#include "rt_math.h" +#include "rtengine.h" +#include "rtlensfun.h" +#include "sleef.h" using namespace std; @@ -87,6 +86,245 @@ float normn (float a, float b, int n) } } +void logEncode(rtengine::Imagefloat *src, rtengine::Imagefloat *dest, bool multiThread) { + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) if(multiThread) +#endif + + for (int y = 0; y < src->getHeight(); ++y) { + int x = 0; +#ifdef __SSE2__ + for (; x < src->getWidth() - 3; x += 4) { + STVFU(dest->r(y, x), xlogf1(LVFU(src->r(y, x)))); + STVFU(dest->g(y, x), xlogf1(LVFU(src->g(y, x)))); + STVFU(dest->b(y, x), xlogf1(LVFU(src->b(y, x)))); + } +#endif + for (; x < src->getWidth(); ++x) { + dest->r(y, x) = xlogf1(src->r(y, x)); + dest->g(y, x) = xlogf1(src->g(y, x)); + dest->b(y, x) = xlogf1(src->b(y, x)); + } + } +} + +#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); +} + +inline void interpolateTransformCubicLog(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)); + const vfloat tempv = _mm_setr_ps(vhadd(weight * rv), vhadd(weight * gv), vhadd(weight * bv), 0.f); + const vfloat resultv = xexpf(tempv); + r = mul * resultv[0]; + g = mul * resultv[1]; + b = mul * resultv[2]; +} +#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); +} + +inline void interpolateTransformCubicLog(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 * xexpf(rv[0] * w0Hor + rv[1] * w1Hor + rv[2] * w2Hor + rv[3] * w3Hor); + g = mul * xexpf(gv[0] * w0Hor + gv[1] * w1Hor + gv[2] * w2Hor + gv[3] * w3Hor); + b = mul * xexpf(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); +} + +inline void interpolateTransformChannelsCubicLog(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 * xexpf(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); +} + +inline void interpolateTransformChannelsCubicLog(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 * xexpf(cv[0] * w0Hor + cv[1] * w1Hor + cv[2] * w2Hor + cv[3] * w3Hor); +} +#endif } @@ -97,7 +335,7 @@ namespace rtengine #define CLIPTOC(a,b,c,d) ((a)>=(b)?((a)<=(c)?(a):(d=true,(c))):(d=true,(b))) bool ImProcFunctions::transCoord (int W, int H, const std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef, - const LensCorrection *pLCPMap) + const LensCorrection *pLCPMap) const { bool clipped = false; @@ -113,7 +351,7 @@ bool ImProcFunctions::transCoord (int W, int H, const std::vector &src, blue.push_back (Coord2D (src[i].x, src[i].y)); } - return clipped; + return false; } double oW = W, oH = H; @@ -199,7 +437,7 @@ bool ImProcFunctions::transCoord (int W, int H, const std::vector &src, } // Transform all corners and critical sidelines of an image -bool ImProcFunctions::transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef, const LensCorrection *pLCPMap) +bool ImProcFunctions::transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef, const LensCorrection *pLCPMap) const { const int DivisionsPerBorder = 32; @@ -298,7 +536,7 @@ bool ImProcFunctions::transCoord (int W, int H, int x, int y, int w, int h, int& void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, - int rawRotationDeg, bool fullImage) + int rawRotationDeg, bool fullImage, bool useOriginalBuffer) { double focalLen = metadata->getFocalLen(); double focalLen35mm = metadata->getFocalLen35mm(); @@ -308,7 +546,7 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, std::unique_ptr pLCPMap; if (needsLensfun()) { - pLCPMap = LFDatabase::findModifier(params->lensProf, metadata, oW, oH, params->coarse, rawRotationDeg); + pLCPMap = LFDatabase::getInstance()->findModifier(params->lensProf, metadata, oW, oH, params->coarse, rawRotationDeg); } else if (needsLCP()) { // don't check focal length to allow distortion correction for lenses without chip const std::shared_ptr pLCPProf = LCPStore::getInstance()->getProfile (params->lensProf.lcpFile); @@ -346,10 +584,10 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, dest = tmpimg.get(); } } - transformGeneral(highQuality, original, dest, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap.get()); + transformGeneral(highQuality, original, dest, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap.get(), useOriginalBuffer); if (highQuality && dest != transformed) { - transformLCPCAOnly(dest, transformed, cx, cy, pLCPMap.get()); + transformLCPCAOnly(dest, transformed, cx, cy, pLCPMap.get(), useOriginalBuffer); } } } @@ -435,12 +673,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); @@ -466,7 +699,7 @@ static void calcGradientParams (int oW, int oH, const GradientParams& gradient, } } -static float calcGradientFactor (const struct grad_params& gp, int x, int y) +float ImProcFunctions::calcGradientFactor (const struct grad_params& gp, int x, int y) { if (gp.angle_is_zero) { int gy = gp.transpose ? x : y; @@ -743,90 +976,109 @@ 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) +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, bool useOriginalBuffer) { - // 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(); - double w2 = (double) oW / 2.0 - 0.5; - double h2 = (double) oH / 2.0 - 0.5; + // set up stuff, depending on the mode we are + 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(); + + 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 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 bool useLog = params->commonTrans.method == "log" && highQuality; + const double centerFactorx = cx - w2; + const double centerFactory = cy - h2; + + std::unique_ptr tempLog; + if (useLog) { + if (!useOriginalBuffer) { + tempLog.reset(new Imagefloat(original->getWidth(), original->getHeight())); + logEncode(original, tempLog.get(), multiThread); + original = tempLog.get(); + } else { + logEncode(original, original, multiThread); + } + } + + const std::array chOrig = { + original->r.ptrs, + original->g.ptrs, + original->b.ptrs + }; -#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 +1087,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 +1101,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 +1121,81 @@ 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); - } 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); + 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); + } else if (!useLog) { + if (enableCA) { + interpolateTransformChannelsCubic(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], vignmul); + } else { + interpolateTransformCubic(original, xc - 1, yc - 1, Dx, Dy, transformed->r(y, x), transformed->g(y, x), transformed->b(y, x), vignmul); + } } else { - interpolateTransformCubic (original, xc - 1, yc - 1, Dx, Dy, & (transformed->r (y, x)), & (transformed->g (y, x)), & (transformed->b (y, x)), vignmul); + if (enableCA) { + interpolateTransformChannelsCubicLog(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], vignmul); + } else { + interpolateTransformCubicLog(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); + if (useLog) { + if (enableCA) { + chTrans[c][y][x] = vignmul * xexpf(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 * xexpf(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 * xexpf(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 * xexpf(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 { - 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); + 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); + } } } } else { @@ -944,9 +1203,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; } } } @@ -955,19 +1214,24 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I } -void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap) +void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap, bool useOriginalBuffer) { assert(pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable()); + const bool useLog = params->commonTrans.method == "log"; - float** chOrig[3]; - chOrig[0] = original->r.ptrs; - chOrig[1] = original->g.ptrs; - chOrig[2] = original->b.ptrs; + float** chTrans[3] = {transformed->r.ptrs, transformed->g.ptrs, transformed->b.ptrs}; - float** chTrans[3]; - chTrans[0] = transformed->r.ptrs; - chTrans[1] = transformed->g.ptrs; - chTrans[2] = transformed->b.ptrs; + std::unique_ptr tempLog; + if (useLog) { + if (!useOriginalBuffer) { + tempLog.reset(new Imagefloat(original->getWidth(), original->getHeight())); + logEncode(original, tempLog.get(), multiThread); + original = tempLog.get(); + } else { + logEncode(original, original, multiThread); + } + } + float** chOrig[3] = {original->r.ptrs, original->g.ptrs, original->b.ptrs}; #ifdef _OPENMP #pragma omp parallel for if (multiThread) @@ -993,15 +1257,22 @@ 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); + if (!useLog) { + interpolateTransformChannelsCubic(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], 1.0); + } else { + interpolateTransformChannelsCubicLog(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); 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); - - chTrans[c][y][x] = (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); + if (!useLog) { + chTrans[c][y][x] = (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 { + chTrans[c][y][x] = xexpf(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 { // not valid (source pixel x,y not inside source image, etc.) @@ -1013,7 +1284,7 @@ void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *trans } -double ImProcFunctions::getTransformAutoFill (int oW, int oH, const LensCorrection *pLCPMap) +double ImProcFunctions::getTransformAutoFill (int oW, int oH, const LensCorrection *pLCPMap) const { if (!needsCA() && !needsDistortion() && !needsRotation() && !needsPerspective() && (!params->lensProf.useDist || pLCPMap == nullptr)) { return 1; @@ -1037,54 +1308,59 @@ double ImProcFunctions::getTransformAutoFill (int oW, int oH, const LensCorrecti return scaleL; } -bool ImProcFunctions::needsCA () +bool ImProcFunctions::needsCA () const { return fabs (params->cacorrection.red) > 1e-15 || fabs (params->cacorrection.blue) > 1e-15; } -bool ImProcFunctions::needsDistortion () +bool ImProcFunctions::needsDistortion () const { return fabs (params->distortion.amount) > 1e-15; } -bool ImProcFunctions::needsRotation () +bool ImProcFunctions::needsRotation () const { return fabs (params->rotate.degree) > 1e-15; } -bool ImProcFunctions::needsPerspective () +bool ImProcFunctions::needsPerspective () const { return params->perspective.horizontal || params->perspective.vertical; } -bool ImProcFunctions::needsGradient () +bool ImProcFunctions::needsGradient () const { return params->gradient.enabled && fabs (params->gradient.strength) > 1e-15; } -bool ImProcFunctions::needsPCVignetting () +bool ImProcFunctions::needsPCVignetting () const { return params->pcvignette.enabled && fabs (params->pcvignette.strength) > 1e-15; } -bool ImProcFunctions::needsVignetting () +bool ImProcFunctions::needsVignetting () const { return params->vignetting.amount; } -bool ImProcFunctions::needsLCP () +bool ImProcFunctions::needsLCP () const { return params->lensProf.useLcp(); } -bool ImProcFunctions::needsLensfun() +bool ImProcFunctions::needsLensfun() const { return params->lensProf.useLensfun(); } -bool ImProcFunctions::needsTransform () +bool ImProcFunctions::needsTransform (int oW, int oH, int rawRotationDeg, const FramesMetaData *metadata) const { - return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsPCVignetting () || needsVignetting () || needsLCP() || needsLensfun(); + bool needsLf = needsLensfun(); + if (needsLf) { + std::unique_ptr pLCPMap = LFDatabase::getInstance()->findModifier(params->lensProf, metadata, oW, oH, params->coarse, rawRotationDeg); + needsLf = pLCPMap.get(); + } + return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsPCVignetting () || needsVignetting () || needsLCP() || needsLf; } diff --git a/rtengine/ipvibrance.cc b/rtengine/ipvibrance.cc index 390944040..e081a696b 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" @@ -23,16 +23,11 @@ #include "rtengine.h" #include "improcfun.h" #include "iccstore.h" -#include "mytime.h" -#include "../rtgui/thresholdselector.h" +#include "labimage.h" #include "curves.h" #include "color.h" #include "procparams.h" #include "StopWatch.h" -#ifdef _OPENMP -#include -#endif - using namespace std; @@ -149,6 +144,7 @@ void ImProcFunctions::vibrance (LabImage* lab, const procparams::VibranceParams if (skinCurveIsSet) { fillCurveArrayVib (dcurve, skin_curve); skin_curve /= ask; +// skin_curve *= 2.f; } if (dcurve) { diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index 43f4611ba..6c73844dc 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 @@ -28,19 +28,21 @@ #include "../rtgui/threadutils.h" -#include "rtengine.h" -#include "improcfun.h" -#include "LUT.h" #include "array2D.h" -#include "boxblur.h" -#include "rt_math.h" -#include "mytime.h" -#include "sleef.c" -#include "opthelper.h" -#include "median.h" +#include "color.h" +#include "curves.h" #include "EdgePreservingDecomposition.h" #include "iccstore.h" +#include "improcfun.h" +#include "labimage.h" +#include "LUT.h" +#include "median.h" +#include "opthelper.h" #include "procparams.h" +#include "rt_math.h" +#include "rtengine.h" +#include "sleef.h" +#include "../rtgui/options.h" #ifdef _OPENMP #include @@ -48,19 +50,9 @@ #include "cplx_wavelet_dec.h" -#define TS 64 // Tile size -#define offset 25 // shift between tiles -#define fTS ((TS/2+1)) // second dimension of Fourier tiles -#define blkrad 1 // radius of block averaging - -#define epsilon 0.001f/(TS*TS) //tolerance - - namespace rtengine { -extern const Settings* settings; - struct cont_params { float mul[10]; int chrom; @@ -918,6 +910,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const float* noisevarlum = nullptr; // we need a dummy to pass it to WaveletDenoiseAllL WaveletDenoiseAllL (*Ldecomp, noisevarlum, madL, vari, edge, 1); + } //Flat curve for Contrast=f(H) in levels @@ -1195,7 +1188,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const b = 327.68f * Chprov * sincosv.x; //aply Munsell } else {//general case L = labco->L[i1][j1]; - const float Lin = labco->L[i1][j1]; + const float Lin = std::max(0.f, L); if (wavclCurve && cp.finena) { labco->L[i1][j1] = (0.5f * Lin + 1.5f * wavclCurve[Lin]) / 2.f; //apply contrast curve @@ -1432,15 +1425,15 @@ void ImProcFunctions::CompressDR(float *Source, int W_L, int H_L, float Compress float exponent; if (DetailBoost > 0.f && DetailBoost < 0.05f ) { - float betemp = expf (- (2.f - DetailBoost + 0.694f)) - 1.f; //0.694 = log(2) + float betemp = expf (- (2.f - DetailBoost + 0.693147f)) - 1.f; //0.693147 = log(2) exponent = 1.2f * xlogf( -betemp); exponent /= 20.f; } else if (DetailBoost >= 0.05f && DetailBoost < 0.25f ) { - float betemp = expf (- (2.f - DetailBoost + 0.694f)) - 1.f; //0.694 = log(2) + float betemp = expf (- (2.f - DetailBoost + 0.693147f)) - 1.f; exponent = 1.2f * xlogf( -betemp); exponent /= (-75.f * DetailBoost + 23.75f); } else if (DetailBoost >= 0.25f) { - float betemp = expf (- (2.f - DetailBoost + 0.694f)) - 1.f; //0.694 = log(2) + float betemp = expf (- (2.f - DetailBoost + 0.693147f)) - 1.f; exponent = 1.2f * xlogf( -betemp); exponent /= (-2.f * DetailBoost + 5.5f); } else { @@ -1448,6 +1441,7 @@ void ImProcFunctions::CompressDR(float *Source, int W_L, int H_L, float Compress } exponent += 1.f; + const float eps = 0.0001f; // now calculate Source = pow(Source, exponent) #ifdef __SSE2__ @@ -1456,17 +1450,19 @@ void ImProcFunctions::CompressDR(float *Source, int W_L, int H_L, float Compress #endif { vfloat exponentv = F2V(exponent); + __m128 epsv = _mm_set1_ps( eps ); + #ifdef _OPENMP #pragma omp for #endif for (int i = 0; i < n - 3; i += 4) { - STVFU(Source[i], xexpf(xlogf(LVFU(Source[i])) * exponentv)); + STVFU(Source[i], xexpf(xlogf(LVFU(Source[i]) + epsv) * exponentv)); } } for (int i = n - (n % 4); i < n; i++) { - Source[i] = xexpf(xlogf(Source[i]) * exponent); + Source[i] = xexpf(xlogf(Source[i] + eps) * exponent); } #else @@ -1812,6 +1808,8 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * for (int i = 0; i < H_L; i++) { tmC[i] = &tmCBuffer[i * W_L]; } + float gradw = cp.eddet; + float tloww = cp.eddetthr; #ifdef _OPENMP #pragma omp for schedule(dynamic) collapse(2) @@ -1823,7 +1821,8 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * int H_L = WaveletCoeffs_L.level_H (lvl); float ** WavCoeffs_LL = WaveletCoeffs_L.level_coeffs (lvl); - calckoe (WavCoeffs_LL, cp, koeLi, lvl , dir, W_L, H_L, edd, maxkoeLi, tmC); + calckoe (WavCoeffs_LL, gradw, tloww, koeLi, lvl , dir, W_L, H_L, edd, maxkoeLi, tmC); +// calckoe (WavCoeffs_LL, cp, koeLi, lvl , dir, W_L, H_L, edd, maxkoeLi, tmC); // return convolution KoeLi and maxkoeLi of level 0 1 2 3 and Dir Horiz, Vert, Diag } } @@ -2175,12 +2174,11 @@ void ImProcFunctions::WaveletcontAllAB (LabImage * labco, float ** varhue, float //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void ImProcFunctions::calckoe (float ** WavCoeffs_LL, const struct cont_params& cp, float *koeLi[12], int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC) +void ImProcFunctions::calckoe (float ** WavCoeffs_LL, float gradw, float tloww, float *koeLi[12], int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC) { int borderL = 2; -// printf("cpedth=%f\n",cp.eddetthr); - if (cp.eddetthr < 30.f) { + if (tloww < 30.f) { borderL = 1; // I calculate coefficients with r size matrix 3x3 r=1 ; 5x5 r=2; 7x7 r=3 @@ -2204,7 +2202,7 @@ void ImProcFunctions::calckoe (float ** WavCoeffs_LL, const struct cont_params& } } - } else if (cp.eddetthr >= 30.f && cp.eddetthr < 50.f) { + } else if (tloww < 50.f) { borderL = 1; for (int i = 1; i < H_L - 1; i++) { //sigma=0.85 @@ -2220,7 +2218,7 @@ void ImProcFunctions::calckoe (float ** WavCoeffs_LL, const struct cont_params& } - else if (cp.eddetthr >= 50.f && cp.eddetthr < 75.f) { + else if (tloww < 75.f) { borderL = 1; for (int i = 1; i < H_L - 1; i++) { @@ -2232,10 +2230,9 @@ void ImProcFunctions::calckoe (float ** WavCoeffs_LL, const struct cont_params& } } - else if (cp.eddetthr >= 75.f) { + else { borderL = 2; - //if(cp.lip3 && level > 1) { if (level > 1) { // do not activate 5x5 if level 0 or 1 for (int i = 2; i < H_L - 2; i++) { @@ -2254,7 +2251,7 @@ void ImProcFunctions::calckoe (float ** WavCoeffs_LL, const struct cont_params& // 4 9 12 9 4 // 2 4 5 4 2 // divi 159 - if (cp.eddetthr < 85.f) { //sigma=1.1 + if (tloww < 85.f) { //sigma=1.1 tmC[i][j] = (15.f * WavCoeffs_LL[dir][i * W_L + j] + 10.f * WavCoeffs_LL[dir][ (i - 1) * W_L + j] + 10.f * WavCoeffs_LL[dir][ (i + 1) * W_L + j] + 10.f * WavCoeffs_LL[dir][i * W_L + j + 1] + 10.f * WavCoeffs_LL[dir][i * W_L + j - 1] + 7.f * WavCoeffs_LL[dir][ (i - 1) * W_L + j - 1] + 7.f * WavCoeffs_LL[dir][ (i - 1) * W_L + j + 1] + 7.f * WavCoeffs_LL[dir][ (i + 1) * W_L + j - 1] + 7.f * WavCoeffs_LL[dir][ (i + 1) * W_L + j + 1] @@ -2302,8 +2299,8 @@ void ImProcFunctions::calckoe (float ** WavCoeffs_LL, const struct cont_params& float thr = 40.f; //avoid artifact eg. noise...to test float thr2 = 1.5f * edd; //edd can be modified in option ed_detect - thr2 += cp.eddet / 30.f; //to test - float diffFactor = (cp.eddet / 100.f); + thr2 += gradw / 30.f; //to test + float diffFactor = (gradw / 100.f); for (int i = 0; i < H_L; i++ ) { for (int j = 0; j < W_L; j++) { @@ -2514,6 +2511,7 @@ void ImProcFunctions::ContAllL (float *koeLi[12], float *maxkoeLi, bool lipschit float maxkoe = 0.f; if (!lipschitz) { + koe = new float [H_L * W_L]; for (int i = 0; i < W_L * H_L; i++) { @@ -3343,7 +3341,6 @@ void ImProcFunctions::ContAllAB (LabImage * labco, int maxlvl, float ** varhue, } if (cp.bam && cp.diag) { -//printf("OK Chroma\n"); if (cp.opaW && cp.BAmet == 2) { int iteration = cp.ite; int itplus = 7 + iteration; 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/jdatasrc.cc b/rtengine/jdatasrc.cc index 8c04a14a2..e461b60f5 100644 --- a/rtengine/jdatasrc.cc +++ b/rtengine/jdatasrc.cc @@ -25,11 +25,6 @@ #define JFREAD(file,buf,sizeofbuf) \ ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) -#define JFWRITE(file,buf,sizeofbuf) \ - ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) - - - /* Expanded data source object for stdio input */ namespace diff --git a/rtengine/jpeg.h b/rtengine/jpeg.h index 99baecc5a..9b1f45f1d 100644 --- a/rtengine/jpeg.h +++ b/rtengine/jpeg.h @@ -1,5 +1,4 @@ -#ifndef _RT_JPEG_H -#define _RT_JPEG_H +#pragma once #include @@ -29,6 +28,3 @@ typedef struct { #ifdef __cplusplus } #endif - - -#endif diff --git a/rtengine/klt/selectGoodFeatures.cc b/rtengine/klt/selectGoodFeatures.cc index 20e67fb2e..ccd7681db 100644 --- a/rtengine/klt/selectGoodFeatures.cc +++ b/rtengine/klt/selectGoodFeatures.cc @@ -9,7 +9,6 @@ #include /* fflush() */ #include /* memset() */ #include /* fsqrt() */ -#define fsqrt(X) sqrt(X) /* Our includes */ #include "base.h" diff --git a/rtengine/labimage.cc b/rtengine/labimage.cc index 733565ef1..ef54bf862 100644 --- a/rtengine/labimage.cc +++ b/rtengine/labimage.cc @@ -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 . */ -#include #include #include "labimage.h" diff --git a/rtengine/labimage.h b/rtengine/labimage.h index f9a1142cc..6f394645d 100644 --- a/rtengine/labimage.h +++ b/rtengine/labimage.h @@ -14,15 +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 . */ -#ifndef _LABIMAGE_H_ -#define _LABIMAGE_H_ +#pragma once + +#include namespace rtengine { -class LabImage +class LabImage final { private: void allocLab(size_t w, size_t h); @@ -46,4 +47,3 @@ public: }; } -#endif diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index 7156f17e2..c80a126f5 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -14,30 +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 . */ #include +#include #include +#include +#include #include #ifdef WIN32 #include -#include #endif #include "lcp.h" +#include "opthelper.h" #include "procparams.h" +#include "rt_math.h" #include "settings.h" - -namespace rtengine -{ - -extern const Settings* settings; - -} +#include "utils.h" class rtengine::LCPProfile::LCPPersModel { @@ -234,8 +232,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 +246,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 +360,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; @@ -985,7 +982,7 @@ rtengine::LCPMapper::LCPMapper( bool useCADistP, int fullWidth, int fullHeight, - const CoarseTransformParams& coarse, + const procparams::CoarseTransformParams& coarse, int rawRotationDeg ) : enableCA(false), @@ -1138,6 +1135,17 @@ void rtengine::LCPMapper::correctCA(double& x, double& y, int cx, int cy, int ch y -= cy; } +void rtengine::LCPMapper::processVignette(int width, int height, float** rawData) const +{ +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < height; ++y) { + processVignetteLine(width, y, rawData[y]); + } +} + void rtengine::LCPMapper::processVignetteLine(int width, int y, float* line) const { // No need for swapXY, since vignette is in RAW and always before rotation @@ -1176,6 +1184,17 @@ void rtengine::LCPMapper::processVignetteLine(int width, int y, float* line) con } } +void rtengine::LCPMapper::processVignette3Channels(int width, int height, float** rawData) const +{ +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < height; ++y) { + processVignetteLine3Channels(width, y, rawData[y]); + } +} + void rtengine::LCPMapper::processVignetteLine3Channels(int width, int y, float* line) const { // No need for swapXY, since vignette is in RAW and always before rotation diff --git a/rtengine/lcp.h b/rtengine/lcp.h index 2d9707907..2e36fe113 100644 --- a/rtengine/lcp.h +++ b/rtengine/lcp.h @@ -14,27 +14,33 @@ * GNU General Public License for more details. * * 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 -#include #include #include #include -#include +#include #include #include "cache.h" -#include "imagefloat.h" -#include "opthelper.h" namespace rtengine { +namespace procparams +{ + +class ProcParams; + +struct CoarseTransformParams; + +} + enum class LCPCorrectionMode { VIGNETTE, DISTORTION, @@ -165,8 +171,8 @@ public: virtual void correctDistortion(double &x, double &y, int cx, int cy, double scale) const = 0; virtual bool isCACorrectionAvailable() const = 0; virtual void correctCA(double &x, double &y, int cx, int cy, int channel) const = 0; - virtual void processVignetteLine(int width, int y, float *line) const = 0; - virtual void processVignetteLine3Channels(int width, int y, float *line) const = 0; + virtual void processVignette(int width, int height, float** rawData) const = 0; + virtual void processVignette3Channels(int width, int height, float** rawData) const = 0; }; @@ -185,7 +191,7 @@ public: bool useCADistP, int fullWidth, int fullHeight, - const CoarseTransformParams& coarse, + const procparams::CoarseTransformParams& coarse, int rawRotationDeg ); @@ -193,8 +199,8 @@ public: void correctDistortion(double &x, double &y, int cx, int cy, double scale) const override; // MUST be the first stage bool isCACorrectionAvailable() const override; void correctCA(double& x, double& y, int cx, int cy, int channel) const override; - void processVignetteLine(int width, int y, float* line) const override; - void processVignetteLine3Channels(int width, int y, float* line) const override; + void processVignette(int width, int height, float** rawData) const override; + void processVignette3Channels(int width, int height, float** rawData) const override; private: bool enableCA; // is the mapper capable if CA correction? @@ -203,6 +209,9 @@ private: LCPModelCommon mc; LCPModelCommon chrom[3]; // in order RedGreen/Green/BlueGreen bool isFisheye; + + void processVignetteLine(int width, int y, float* line) const; + void processVignetteLine3Channels(int width, int y, float* line) const; }; } diff --git a/rtengine/lmmse_demosaic.cc b/rtengine/lmmse_demosaic.cc new file mode 100644 index 000000000..f4af1b801 --- /dev/null +++ b/rtengine/lmmse_demosaic.cc @@ -0,0 +1,818 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2019 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 + +#include "rawimagesource.h" +#include "rt_math.h" +#include "color.h" +#include "../rtgui/multilangmgr.h" +#include "sleef.h" +#include "opthelper.h" +#include "median.h" + +using namespace std; + +namespace rtengine +{ + +// LSMME demosaicing algorithm +// L. Zhang and X. Wu, +// Color demozaicing via directional Linear Minimum Mean Square-error Estimation, +// IEEE Trans. on Image Processing, vol. 14, pp. 2167-2178, +// Dec. 2005. +// Adapted to RawTherapee by Jacques Desmis 3/2013 +// Improved speed and reduced memory consumption by Ingo Weyrich 2/2015 +// TODO Tiles to reduce memory consumption +void RawImageSource::lmmse_interpolate_omp(int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations) +{ + const int width = winw, height = winh; + const int ba = 10; + const int rr1 = height + 2 * ba; + const int cc1 = width + 2 * ba; + const int w1 = cc1; + const int w2 = 2 * w1; + const int w3 = 3 * w1; + const int w4 = 4 * w1; + float h0, h1, h2, h3, h4, hs; + h0 = 1.0f; + h1 = exp( -1.0f / 8.0f); + h2 = exp( -4.0f / 8.0f); + h3 = exp( -9.0f / 8.0f); + h4 = exp(-16.0f / 8.0f); + hs = h0 + 2.0f * (h1 + h2 + h3 + h4); + h0 /= hs; + h1 /= hs; + h2 /= hs; + h3 /= hs; + h4 /= hs; + int passref = 0; + int iter = 0; + + if (iterations <= 4) { + iter = iterations - 1; + passref = 0; + } else if (iterations <= 6) { + iter = 3; + passref = iterations - 4; + } else if (iterations <= 8) { + iter = 3; + passref = iterations - 6; + } + + bool applyGamma = true; + + if (iterations == 0) { + applyGamma = false; + iter = 0; + } else { + applyGamma = true; + } + + float *rix[5]; + float *qix[5]; + float *buffer = (float *)calloc(static_cast(rr1) * cc1 * 5 * sizeof(float), 1); + + if (buffer == nullptr) { // allocation of big block of memory failed, try to get 5 smaller ones + printf("lmmse_interpolate_omp: allocation of big memory block failed, try to get 5 smaller ones now...\n"); + bool allocationFailed = false; + + for (int i = 0; i < 5; i++) { + qix[i] = (float *)calloc(static_cast(rr1) * cc1 * sizeof(float), 1); + + if (!qix[i]) { // allocation of at least one small block failed + allocationFailed = true; + } + } + + if (allocationFailed) { // fall back to igv_interpolate + printf("lmmse_interpolate_omp: allocation of 5 small memory blocks failed, falling back to igv_interpolate...\n"); + + for (int i = 0; i < 5; i++) { // free the already allocated buffers + if (qix[i]) { + free(qix[i]); + } + } + + igv_interpolate(winw, winh); + return; + } + } else { + qix[0] = buffer; + + for (int i = 1; i < 5; i++) { + qix[i] = qix[i - 1] + rr1 * cc1; + } + } + + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), M("TP_RAW_LMMSE"))); + plistener->setProgress (0.0); + } + + + LUTf *gamtab; + + if (applyGamma) { + gamtab = &(Color::gammatab_24_17a); + } else { + gamtab = new LUTf(65536, LUT_CLIP_BELOW); + gamtab->makeIdentity(65535.f); + } + + +#ifdef _OPENMP + #pragma omp parallel private(rix) +#endif + { +#ifdef _OPENMP + #pragma omp for +#endif + + for (int rrr = ba; rrr < rr1 - ba; rrr++) { + for (int ccc = ba, row = rrr - ba; ccc < cc1 - ba; ccc++) { + int col = ccc - ba; + float *rix = qix[4] + rrr * cc1 + ccc; + rix[0] = (*gamtab)[rawData[row][col]]; + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.1); + } + } + + // G-R(B) +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) +#endif + + for (int rr = 2; rr < rr1 - 2; rr++) { + // G-R(B) at R(B) location + for (int cc = 2 + (FC(rr, 2) & 1); cc < cc1 - 2; cc += 2) { + rix[4] = qix[4] + rr * cc1 + cc; + float v0 = 0.0625f * (rix[4][-w1 - 1] + rix[4][-w1 + 1] + rix[4][w1 - 1] + rix[4][w1 + 1]) + 0.25f * (rix[4][0]); + // horizontal + rix[0] = qix[0] + rr * cc1 + cc; + rix[0][0] = -0.25f * (rix[4][ -2] + rix[4][ 2]) + xdiv2f(rix[4][ -1] + rix[4][0] + rix[4][ 1]); + float Y = v0 + xdiv2f(rix[0][0]); + + if (rix[4][0] > 1.75f * Y) { + rix[0][0] = median(rix[0][0], rix[4][ -1], rix[4][ 1]); + } else { + rix[0][0] = LIM(rix[0][0], 0.0f, 1.0f); + } + + rix[0][0] -= rix[4][0]; + // vertical + rix[1] = qix[1] + rr * cc1 + cc; + rix[1][0] = -0.25f * (rix[4][-w2] + rix[4][w2]) + xdiv2f(rix[4][-w1] + rix[4][0] + rix[4][w1]); + Y = v0 + xdiv2f(rix[1][0]); + + if (rix[4][0] > 1.75f * Y) { + rix[1][0] = median(rix[1][0], rix[4][-w1], rix[4][w1]); + } else { + rix[1][0] = LIM(rix[1][0], 0.0f, 1.0f); + } + + rix[1][0] -= rix[4][0]; + } + + // G-R(B) at G location + for (int ccc = 2 + (FC(rr, 3) & 1); ccc < cc1 - 2; ccc += 2) { + rix[0] = qix[0] + rr * cc1 + ccc; + rix[1] = qix[1] + rr * cc1 + ccc; + rix[4] = qix[4] + rr * cc1 + ccc; + rix[0][0] = 0.25f * (rix[4][ -2] + rix[4][ 2]) - xdiv2f(rix[4][ -1] + rix[4][0] + rix[4][ 1]); + rix[1][0] = 0.25f * (rix[4][-w2] + rix[4][w2]) - xdiv2f(rix[4][-w1] + rix[4][0] + rix[4][w1]); + rix[0][0] = LIM(rix[0][0], -1.0f, 0.0f) + rix[4][0]; + rix[1][0] = LIM(rix[1][0], -1.0f, 0.0f) + rix[4][0]; + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.2); + } + } + + + // apply low pass filter on differential colors +#ifdef _OPENMP + #pragma omp for +#endif + + for (int rr = 4; rr < rr1 - 4; rr++) + for (int cc = 4; cc < cc1 - 4; cc++) { + rix[0] = qix[0] + rr * cc1 + cc; + rix[2] = qix[2] + rr * cc1 + cc; + rix[2][0] = h0 * rix[0][0] + h1 * (rix[0][ -1] + rix[0][ 1]) + h2 * (rix[0][ -2] + rix[0][ 2]) + h3 * (rix[0][ -3] + rix[0][ 3]) + h4 * (rix[0][ -4] + rix[0][ 4]); + rix[1] = qix[1] + rr * cc1 + cc; + rix[3] = qix[3] + rr * cc1 + cc; + rix[3][0] = h0 * rix[1][0] + h1 * (rix[1][-w1] + rix[1][w1]) + h2 * (rix[1][-w2] + rix[1][w2]) + h3 * (rix[1][-w3] + rix[1][w3]) + h4 * (rix[1][-w4] + rix[1][w4]); + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.3); + } + } + + // interpolate G-R(B) at R(B) +#ifdef _OPENMP + #pragma omp for +#endif + + for (int rr = 4; rr < rr1 - 4; rr++) { + int cc = 4 + (FC(rr, 4) & 1); +#ifdef __SSE2__ + vfloat p1v, p2v, p3v, p4v, p5v, p6v, p7v, p8v, p9v, muv, vxv, vnv, xhv, vhv, xvv, vvv; + vfloat epsv = F2V(1e-7); + vfloat ninev = F2V(9.f); + + for (; cc < cc1 - 10; cc += 8) { + rix[0] = qix[0] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + rix[2] = qix[2] + rr * cc1 + cc; + rix[3] = qix[3] + rr * cc1 + cc; + rix[4] = qix[4] + rr * cc1 + cc; + // horizontal + p1v = LC2VFU(rix[2][-4]); + p2v = LC2VFU(rix[2][-3]); + p3v = LC2VFU(rix[2][-2]); + p4v = LC2VFU(rix[2][-1]); + p5v = LC2VFU(rix[2][ 0]); + p6v = LC2VFU(rix[2][ 1]); + p7v = LC2VFU(rix[2][ 2]); + p8v = LC2VFU(rix[2][ 3]); + p9v = LC2VFU(rix[2][ 4]); + muv = (p1v + p2v + p3v + p4v + p5v + p6v + p7v + p8v + p9v) / ninev; + vxv = epsv + SQRV(p1v - muv) + SQRV(p2v - muv) + SQRV(p3v - muv) + SQRV(p4v - muv) + SQRV(p5v - muv) + SQRV(p6v - muv) + SQRV(p7v - muv) + SQRV(p8v - muv) + SQRV(p9v - muv); + p1v -= LC2VFU(rix[0][-4]); + p2v -= LC2VFU(rix[0][-3]); + p3v -= LC2VFU(rix[0][-2]); + p4v -= LC2VFU(rix[0][-1]); + p5v -= LC2VFU(rix[0][ 0]); + p6v -= LC2VFU(rix[0][ 1]); + p7v -= LC2VFU(rix[0][ 2]); + p8v -= LC2VFU(rix[0][ 3]); + p9v -= LC2VFU(rix[0][ 4]); + vnv = epsv + SQRV(p1v) + SQRV(p2v) + SQRV(p3v) + SQRV(p4v) + SQRV(p5v) + SQRV(p6v) + SQRV(p7v) + SQRV(p8v) + SQRV(p9v); + xhv = (LC2VFU(rix[0][0]) * vxv + LC2VFU(rix[2][0]) * vnv) / (vxv + vnv); + vhv = vxv * vnv / (vxv + vnv); + + // vertical + p1v = LC2VFU(rix[3][-w4]); + p2v = LC2VFU(rix[3][-w3]); + p3v = LC2VFU(rix[3][-w2]); + p4v = LC2VFU(rix[3][-w1]); + p5v = LC2VFU(rix[3][ 0]); + p6v = LC2VFU(rix[3][ w1]); + p7v = LC2VFU(rix[3][ w2]); + p8v = LC2VFU(rix[3][ w3]); + p9v = LC2VFU(rix[3][ w4]); + muv = (p1v + p2v + p3v + p4v + p5v + p6v + p7v + p8v + p9v) / ninev; + vxv = epsv + SQRV(p1v - muv) + SQRV(p2v - muv) + SQRV(p3v - muv) + SQRV(p4v - muv) + SQRV(p5v - muv) + SQRV(p6v - muv) + SQRV(p7v - muv) + SQRV(p8v - muv) + SQRV(p9v - muv); + p1v -= LC2VFU(rix[1][-w4]); + p2v -= LC2VFU(rix[1][-w3]); + p3v -= LC2VFU(rix[1][-w2]); + p4v -= LC2VFU(rix[1][-w1]); + p5v -= LC2VFU(rix[1][ 0]); + p6v -= LC2VFU(rix[1][ w1]); + p7v -= LC2VFU(rix[1][ w2]); + p8v -= LC2VFU(rix[1][ w3]); + p9v -= LC2VFU(rix[1][ w4]); + vnv = epsv + SQRV(p1v) + SQRV(p2v) + SQRV(p3v) + SQRV(p4v) + SQRV(p5v) + SQRV(p6v) + SQRV(p7v) + SQRV(p8v) + SQRV(p9v); + xvv = (LC2VFU(rix[1][0]) * vxv + LC2VFU(rix[3][0]) * vnv) / (vxv + vnv); + vvv = vxv * vnv / (vxv + vnv); + // interpolated G-R(B) + muv = (xhv * vvv + xvv * vhv) / (vhv + vvv); + STC2VFU(rix[4][0], muv); + } + +#endif + + for (; cc < cc1 - 4; cc += 2) { + rix[0] = qix[0] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + rix[2] = qix[2] + rr * cc1 + cc; + rix[3] = qix[3] + rr * cc1 + cc; + rix[4] = qix[4] + rr * cc1 + cc; + // horizontal + float p1 = rix[2][-4]; + float p2 = rix[2][-3]; + float p3 = rix[2][-2]; + float p4 = rix[2][-1]; + float p5 = rix[2][ 0]; + float p6 = rix[2][ 1]; + float p7 = rix[2][ 2]; + float p8 = rix[2][ 3]; + float p9 = rix[2][ 4]; + float mu = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) / 9.f; + float vx = 1e-7 + SQR(p1 - mu) + SQR(p2 - mu) + SQR(p3 - mu) + SQR(p4 - mu) + SQR(p5 - mu) + SQR(p6 - mu) + SQR(p7 - mu) + SQR(p8 - mu) + SQR(p9 - mu); + p1 -= rix[0][-4]; + p2 -= rix[0][-3]; + p3 -= rix[0][-2]; + p4 -= rix[0][-1]; + p5 -= rix[0][ 0]; + p6 -= rix[0][ 1]; + p7 -= rix[0][ 2]; + p8 -= rix[0][ 3]; + p9 -= rix[0][ 4]; + float vn = 1e-7 + SQR(p1) + SQR(p2) + SQR(p3) + SQR(p4) + SQR(p5) + SQR(p6) + SQR(p7) + SQR(p8) + SQR(p9); + float xh = (rix[0][0] * vx + rix[2][0] * vn) / (vx + vn); + float vh = vx * vn / (vx + vn); + + // vertical + p1 = rix[3][-w4]; + p2 = rix[3][-w3]; + p3 = rix[3][-w2]; + p4 = rix[3][-w1]; + p5 = rix[3][ 0]; + p6 = rix[3][ w1]; + p7 = rix[3][ w2]; + p8 = rix[3][ w3]; + p9 = rix[3][ w4]; + mu = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) / 9.f; + vx = 1e-7 + SQR(p1 - mu) + SQR(p2 - mu) + SQR(p3 - mu) + SQR(p4 - mu) + SQR(p5 - mu) + SQR(p6 - mu) + SQR(p7 - mu) + SQR(p8 - mu) + SQR(p9 - mu); + p1 -= rix[1][-w4]; + p2 -= rix[1][-w3]; + p3 -= rix[1][-w2]; + p4 -= rix[1][-w1]; + p5 -= rix[1][ 0]; + p6 -= rix[1][ w1]; + p7 -= rix[1][ w2]; + p8 -= rix[1][ w3]; + p9 -= rix[1][ w4]; + vn = 1e-7 + SQR(p1) + SQR(p2) + SQR(p3) + SQR(p4) + SQR(p5) + SQR(p6) + SQR(p7) + SQR(p8) + SQR(p9); + float xv = (rix[1][0] * vx + rix[3][0] * vn) / (vx + vn); + float vv = vx * vn / (vx + vn); + // interpolated G-R(B) + rix[4][0] = (xh * vv + xv * vh) / (vh + vv); + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.4); + } + } + + // copy CFA values +#ifdef _OPENMP + #pragma omp for +#endif + + for (int rr = 0; rr < rr1; rr++) + for (int cc = 0, row = rr - ba; cc < cc1; cc++) { + int col = cc - ba; + int c = FC(rr, cc); + rix[c] = qix[c] + rr * cc1 + cc; + + if ((row >= 0) & (row < height) & (col >= 0) & (col < width)) { + rix[c][0] = (*gamtab)[rawData[row][col]]; + } else { + rix[c][0] = 0.f; + } + + if (c != 1) { + rix[1] = qix[1] + rr * cc1 + cc; + rix[4] = qix[4] + rr * cc1 + cc; + rix[1][0] = rix[c][0] + rix[4][0]; + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.5); + } + } + + // bilinear interpolation for R/B + // interpolate R/B at G location +#ifdef _OPENMP + #pragma omp for +#endif + + for (int rr = 1; rr < rr1 - 1; rr++) + for (int cc = 1 + (FC(rr, 2) & 1), c = FC(rr, cc + 1); cc < cc1 - 1; cc += 2) { + rix[c] = qix[c] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + rix[c][0] = rix[1][0] + xdiv2f(rix[c][ -1] - rix[1][ -1] + rix[c][ 1] - rix[1][ 1]); + c = 2 - c; + rix[c] = qix[c] + rr * cc1 + cc; + rix[c][0] = rix[1][0] + xdiv2f(rix[c][-w1] - rix[1][-w1] + rix[c][w1] - rix[1][w1]); + c = 2 - c; + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.6); + } + } + + // interpolate R/B at B/R location +#ifdef _OPENMP + #pragma omp for +#endif + + for (int rr = 1; rr < rr1 - 1; rr++) + for (int cc = 1 + (FC(rr, 1) & 1), c = 2 - FC(rr, cc); cc < cc1 - 1; cc += 2) { + rix[c] = qix[c] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + rix[c][0] = rix[1][0] + 0.25f * (rix[c][-w1] - rix[1][-w1] + rix[c][ -1] - rix[1][ -1] + rix[c][ 1] - rix[1][ 1] + rix[c][ w1] - rix[1][ w1]); + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.7); + } + } + + }// End of parallelization 1 + + // median filter/ + for (int pass = 0; pass < iter; pass++) { + // Apply 3x3 median filter + // Compute median(R-G) and median(B-G) + +#ifdef _OPENMP + #pragma omp parallel for private(rix) +#endif + + for (int rr = 1; rr < rr1 - 1; rr++) { + for (int c = 0; c < 3; c += 2) { + int d = c + 3 - (c == 0 ? 0 : 1); + int cc = 1; +#ifdef __SSE2__ + + for (; cc < cc1 - 4; cc += 4) { + rix[d] = qix[d] + rr * cc1 + cc; + rix[c] = qix[c] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + // Assign 3x3 differential color values + const std::array p = { + LVFU(rix[c][-w1 - 1]) - LVFU(rix[1][-w1 - 1]), + LVFU(rix[c][-w1]) - LVFU(rix[1][-w1]), + LVFU(rix[c][-w1 + 1]) - LVFU(rix[1][-w1 + 1]), + LVFU(rix[c][ -1]) - LVFU(rix[1][ -1]), + LVFU(rix[c][ 0]) - LVFU(rix[1][ 0]), + LVFU(rix[c][ 1]) - LVFU(rix[1][ 1]), + LVFU(rix[c][ w1 - 1]) - LVFU(rix[1][ w1 - 1]), + LVFU(rix[c][ w1]) - LVFU(rix[1][ w1]), + LVFU(rix[c][ w1 + 1]) - LVFU(rix[1][ w1 + 1]) + }; + _mm_storeu_ps(&rix[d][0], median(p)); + } + +#endif + + for (; cc < cc1 - 1; cc++) { + rix[d] = qix[d] + rr * cc1 + cc; + rix[c] = qix[c] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + // Assign 3x3 differential color values + const std::array p = { + rix[c][-w1 - 1] - rix[1][-w1 - 1], + rix[c][-w1] - rix[1][-w1], + rix[c][-w1 + 1] - rix[1][-w1 + 1], + rix[c][ -1] - rix[1][ -1], + rix[c][ 0] - rix[1][ 0], + rix[c][ 1] - rix[1][ 1], + rix[c][ w1 - 1] - rix[1][ w1 - 1], + rix[c][ w1] - rix[1][ w1], + rix[c][ w1 + 1] - rix[1][ w1 + 1] + }; + rix[d][0] = median(p); + } + } + } + + // red/blue at GREEN pixel locations & red/blue and green at BLUE/RED pixel locations +#ifdef _OPENMP + #pragma omp parallel for private (rix) +#endif + + for (int rr = 0; rr < rr1; rr++) { + rix[0] = qix[0] + rr * cc1; + rix[1] = qix[1] + rr * cc1; + rix[2] = qix[2] + rr * cc1; + rix[3] = qix[3] + rr * cc1; + rix[4] = qix[4] + rr * cc1; + int c0 = FC(rr, 0); + int c1 = FC(rr, 1); + + if (c0 == 1) { + c1 = 2 - c1; + int d = c1 + 3 - (c1 == 0 ? 0 : 1); + int cc; + + for (cc = 0; cc < cc1 - 1; cc += 2) { + rix[0][0] = rix[1][0] + rix[3][0]; + rix[2][0] = rix[1][0] + rix[4][0]; + rix[0]++; + rix[1]++; + rix[2]++; + rix[3]++; + rix[4]++; + rix[c1][0] = rix[1][0] + rix[d][0]; + rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); + rix[0]++; + rix[1]++; + rix[2]++; + rix[3]++; + rix[4]++; + } + + if (cc < cc1) { // remaining pixel, only if width is odd + rix[0][0] = rix[1][0] + rix[3][0]; + rix[2][0] = rix[1][0] + rix[4][0]; + } + } else { + c0 = 2 - c0; + int d = c0 + 3 - (c0 == 0 ? 0 : 1); + int cc; + + for (cc = 0; cc < cc1 - 1; cc += 2) { + rix[c0][0] = rix[1][0] + rix[d][0]; + rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); + rix[0]++; + rix[1]++; + rix[2]++; + rix[3]++; + rix[4]++; + rix[0][0] = rix[1][0] + rix[3][0]; + rix[2][0] = rix[1][0] + rix[4][0]; + rix[0]++; + rix[1]++; + rix[2]++; + rix[3]++; + rix[4]++; + } + + if (cc < cc1) { // remaining pixel, only if width is odd + rix[c0][0] = rix[1][0] + rix[d][0]; + rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); + } + } + } + } + + if (plistener) { + plistener->setProgress (0.8); + } + + if (applyGamma) { + gamtab = &(Color::igammatab_24_17); + } else { + gamtab->makeIdentity(); + } + + array2D* rgb[3]; + rgb[0] = &red; + rgb[1] = &green; + rgb[2] = &blue; + + // copy result back to image matrix +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int row = 0; row < height; row++) { + for (int col = 0, rr = row + ba; col < width; col++) { + int cc = col + ba; + int c = FC(row, col); + + for (int ii = 0; ii < 3; ii++) + if (ii != c) { + float *rix = qix[ii] + rr * cc1 + cc; + (*(rgb[ii]))[row][col] = std::max(0.f, (*gamtab)[65535.f * rix[0]]); + } else { + (*(rgb[ii]))[row][col] = CLIP(rawData[row][col]); + } + } + } + + if (plistener) { + plistener->setProgress (1.0); + } + + if (buffer) { + free(buffer); + } else + for (int i = 0; i < 5; i++) { + free(qix[i]); + } + + if (!applyGamma) { + delete gamtab; + } + + if (iterations > 4) { + refinement(passref); + } + +} + +void RawImageSource::refinement(int PassCount) +{ + int width = W; + int height = H; + int w1 = width; + int w2 = 2 * w1; + + if (plistener) { + plistener->setProgressStr(M("TP_RAW_DMETHOD_PROGRESSBAR_REFINE")); + } + + array2D *rgb[3]; + rgb[0] = &red; + rgb[1] = &green; + rgb[2] = &blue; + + for (int b = 0; b < PassCount; b++) { + if (plistener) { + plistener->setProgress((float)b / PassCount); + } + + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + float *pix[3]; + + /* Reinforce interpolated green pixels on RED/BLUE pixel locations */ +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 2; row < height - 2; row++) { + int col = 2 + (FC(row, 2) & 1); + int c = FC(row, col); +#ifdef __SSE2__ + vfloat dLv, dRv, dUv, dDv, v0v; + vfloat onev = F2V(1.f); + vfloat zd5v = F2V(0.5f); + + for (; col < width - 8; col += 8) { + int indx = row * width + col; + pix[c] = (float*)(*rgb[c]) + indx; + pix[1] = (float*)(*rgb[1]) + indx; + dLv = onev / (onev + vabsf(LC2VFU(pix[c][ -2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); + dRv = onev / (onev + vabsf(LC2VFU(pix[c][ 2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); + dUv = onev / (onev + vabsf(LC2VFU(pix[c][-w2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); + dDv = onev / (onev + vabsf(LC2VFU(pix[c][ w2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); + v0v = vmaxf(ZEROV, LC2VFU(pix[c][0]) + zd5v + ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); + STC2VFU(pix[1][0], v0v); + } + +#endif + + for (; col < width - 2; col += 2) { + int indx = row * width + col; + pix[c] = (float*)(*rgb[c]) + indx; + pix[1] = (float*)(*rgb[1]) + indx; + float dL = 1.f / (1.f + fabsf(pix[c][ -2] - pix[c][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); + float dR = 1.f / (1.f + fabsf(pix[c][ 2] - pix[c][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); + float dU = 1.f / (1.f + fabsf(pix[c][-w2] - pix[c][0]) + fabsf(pix[1][w1] - pix[1][-w1])); + float dD = 1.f / (1.f + fabsf(pix[c][ w2] - pix[c][0]) + fabsf(pix[1][w1] - pix[1][-w1])); + float v0 = (pix[c][0] + 0.5f + ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); + pix[1][0] = std::max(0.f, v0); + } + } + + /* Reinforce interpolated red/blue pixels on GREEN pixel locations */ +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 2; row < height - 2; row++) { + int col = 2 + (FC(row, 3) & 1); + int c = FC(row, col + 1); +#ifdef __SSE2__ + vfloat dLv, dRv, dUv, dDv, v0v; + vfloat onev = F2V(1.f); + vfloat zd5v = F2V(0.5f); + + for (; col < width - 8; col += 8) { + int indx = row * width + col; + pix[1] = (float*)(*rgb[1]) + indx; + + for (int i = 0; i < 2; c = 2 - c, i++) { + pix[c] = (float*)(*rgb[c]) + indx; + dLv = onev / (onev + vabsf(LC2VFU(pix[1][ -2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][ 1]) - LC2VFU(pix[c][ -1]))); + dRv = onev / (onev + vabsf(LC2VFU(pix[1][ 2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][ 1]) - LC2VFU(pix[c][ -1]))); + dUv = onev / (onev + vabsf(LC2VFU(pix[1][-w2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][w1]) - LC2VFU(pix[c][-w1]))); + dDv = onev / (onev + vabsf(LC2VFU(pix[1][ w2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][w1]) - LC2VFU(pix[c][-w1]))); + v0v = vmaxf(ZEROV, LC2VFU(pix[1][0]) + zd5v - ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); + STC2VFU(pix[c][0], v0v); + } + } + +#endif + + for (; col < width - 2; col += 2) { + int indx = row * width + col; + pix[1] = (float*)(*rgb[1]) + indx; + + for (int i = 0; i < 2; c = 2 - c, i++) { + pix[c] = (float*)(*rgb[c]) + indx; + float dL = 1.f / (1.f + fabsf(pix[1][ -2] - pix[1][0]) + fabsf(pix[c][ 1] - pix[c][ -1])); + float dR = 1.f / (1.f + fabsf(pix[1][ 2] - pix[1][0]) + fabsf(pix[c][ 1] - pix[c][ -1])); + float dU = 1.f / (1.f + fabsf(pix[1][-w2] - pix[1][0]) + fabsf(pix[c][w1] - pix[c][-w1])); + float dD = 1.f / (1.f + fabsf(pix[1][ w2] - pix[1][0]) + fabsf(pix[c][w1] - pix[c][-w1])); + float v0 = (pix[1][0] + 0.5f - ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); + pix[c][0] = std::max(0.f, v0); + } + } + } + + /* Reinforce integrated red/blue pixels on BLUE/RED pixel locations */ +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 2; row < height - 2; row++) { + int col = 2 + (FC(row, 2) & 1); + int c = 2 - FC(row, col); +#ifdef __SSE2__ + vfloat dLv, dRv, dUv, dDv, v0v; + vfloat onev = F2V(1.f); + vfloat zd5v = F2V(0.5f); + + for (; col < width - 8; col += 8) { + int indx = row * width + col; + pix[0] = (float*)(*rgb[0]) + indx; + pix[1] = (float*)(*rgb[1]) + indx; + pix[2] = (float*)(*rgb[2]) + indx; + int d = 2 - c; + dLv = onev / (onev + vabsf(LC2VFU(pix[d][ -2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); + dRv = onev / (onev + vabsf(LC2VFU(pix[d][ 2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); + dUv = onev / (onev + vabsf(LC2VFU(pix[d][-w2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); + dDv = onev / (onev + vabsf(LC2VFU(pix[d][ w2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); + v0v = vmaxf(ZEROV, LC2VFU(pix[1][0]) + zd5v - ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); + STC2VFU(pix[c][0], v0v); + } + +#endif + + for (; col < width - 2; col += 2) { + int indx = row * width + col; + pix[0] = (float*)(*rgb[0]) + indx; + pix[1] = (float*)(*rgb[1]) + indx; + pix[2] = (float*)(*rgb[2]) + indx; + int d = 2 - c; + float dL = 1.f / (1.f + fabsf(pix[d][ -2] - pix[d][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); + float dR = 1.f / (1.f + fabsf(pix[d][ 2] - pix[d][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); + float dU = 1.f / (1.f + fabsf(pix[d][-w2] - pix[d][0]) + fabsf(pix[1][w1] - pix[1][-w1])); + float dD = 1.f / (1.f + fabsf(pix[d][ w2] - pix[d][0]) + fabsf(pix[1][w1] - pix[1][-w1])); + float v0 = (pix[1][0] + 0.5f - ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); + pix[c][0] = std::max(0.f, v0); + } + } + } // end parallel + } +} +#ifdef __SSE2__ +#undef CLIPV +#endif + +} /* namespace */ 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..842766dcf 100644 --- a/rtengine/myfile.cc +++ b/rtengine/myfile.cc @@ -14,12 +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 . */ #include "myfile.h" #include -#include - +#include "rtengine.h" // get mmap() sorted out #ifdef MYFILE_MMAP diff --git a/rtengine/myfile.h b/rtengine/myfile.h index e4609c697..423edea9a 100644 --- a/rtengine/myfile.h +++ b/rtengine/myfile.h @@ -14,15 +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 _MYFILE_ -#define _MYFILE_ +#pragma once -#include #include #include -#include "rtengine.h" + +#include + +#include "opthelper.h" + +namespace rtengine +{ + +class ProgressListener; + +} + struct IMFILE { int fd; ssize_t pos; @@ -47,28 +56,26 @@ IMFILE* fopen (const char* fname); IMFILE* gfopen (const char* fname); IMFILE* fopen (unsigned* buf, int size); void fclose (IMFILE* f); -inline int ftell (IMFILE* f) +inline long ftell (IMFILE* f) { - return f->pos; } inline int feof (IMFILE* f) { - return f->eof; } -inline void fseek (IMFILE* f, int p, int how) +inline void fseek (IMFILE* f, long p, int how) { - int fpos = f->pos; + ssize_t fpos = f->pos; if (how == SEEK_SET) { f->pos = p; } else if (how == SEEK_CUR) { f->pos += p; } else if (how == SEEK_END) { - if(p <= 0 && -p <= f->size) { + if (p <= 0 && -p <= f->size) { f->pos = f->size + p; } return; @@ -134,6 +141,3 @@ inline unsigned char* fdata(int offset, IMFILE* f) int fscanf (IMFILE* f, const char* s ...); char* fgets (char* s, int n, IMFILE* f); - -#endif - diff --git a/rtengine/mytime.h b/rtengine/mytime.h index f73d563d2..787fefcc3 100644 --- a/rtengine/mytime.h +++ b/rtengine/mytime.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 _MYTIME_ -#define _MYTIME_ +#pragma once #ifdef WIN32 -#include +#include #elif defined __APPLE__ #include #else @@ -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..f431c0ec9 100644 --- a/rtengine/opthelper.h +++ b/rtengine/opthelper.h @@ -15,30 +15,27 @@ // 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 . // //////////////////////////////////////////////////////////////// +#pragma once -#ifndef OPTHELPER_H - #define OPTHELPER_H +#define pow_F(a,b) (xexpf(b*xlogf(a))) - #define pow_F(a,b) (xexpf(b*xlogf(a))) - - #ifdef __SSE2__ - #include "sleefsseavx.c" - #endif - - #ifdef __GNUC__ - #define RESTRICT __restrict__ - #define LIKELY(x) __builtin_expect (!!(x), 1) - #define UNLIKELY(x) __builtin_expect (!!(x), 0) - #define ALIGNED64 __attribute__ ((aligned (64))) - #define ALIGNED16 __attribute__ ((aligned (16))) - #else - #define RESTRICT - #define LIKELY(x) (x) - #define UNLIKELY(x) (x) - #define ALIGNED64 - #define ALIGNED16 - #endif +#ifdef __SSE2__ + #include "sleefsseavx.h" +#endif + +#ifdef __GNUC__ + #define RESTRICT __restrict__ + #define LIKELY(x) __builtin_expect (!!(x), 1) + #define UNLIKELY(x) __builtin_expect (!!(x), 0) + #define ALIGNED64 __attribute__ ((aligned (64))) + #define ALIGNED16 __attribute__ ((aligned (16))) +#else + #define RESTRICT + #define LIKELY(x) (x) + #define UNLIKELY(x) (x) + #define ALIGNED64 + #define ALIGNED16 #endif diff --git a/rtengine/panasonic_decoders.cc b/rtengine/panasonic_decoders.cc new file mode 100644 index 000000000..bbbfb7c20 --- /dev/null +++ b/rtengine/panasonic_decoders.cc @@ -0,0 +1,278 @@ +/* + * This file is part of RawTherapee. + * + * 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 "dcraw.h" + +// Code adapted from libraw +/* -*- C++ -*- + * Copyright 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). + +*/ + +unsigned DCraw::pana_bits_t::operator() (int nbits, unsigned *bytes) +{ + int byte; + + if (!nbits && !bytes) { + return vbits=0; + } + if (!vbits) { + fread (buf+load_flags, 1, 0x4000-load_flags, ifp); + fread (buf, 1, load_flags, ifp); + } + if (encoding == 5) { + for (byte = 0; byte < 16; byte++) + { + bytes[byte] = buf[vbits++]; + vbits &= 0x3FFF; + } + return 0; + } else { + vbits = (vbits - nbits) & 0x1ffff; + byte = vbits >> 3 ^ 0x3ff0; + return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits); + } +} + +class pana_cs6_page_decoder +{ + unsigned int pixelbuffer[14], lastoffset, maxoffset; + unsigned char current, *buffer; +public: + pana_cs6_page_decoder(unsigned char *_buffer, unsigned int bsize) + : pixelbuffer{}, lastoffset(0), maxoffset(bsize), current(0), buffer(_buffer) + { + } + void read_page(); // will throw IO error if not enough space in buffer + unsigned int nextpixel() + { + return current < 14 ? pixelbuffer[current++] : 0; + } +}; + +#define wbuffer(i) ((unsigned short)buffer[lastoffset + 15 - i]) + +void pana_cs6_page_decoder::read_page() +{ + if (!buffer || (maxoffset - lastoffset < 16)) + ; + pixelbuffer[0] = (wbuffer(0) << 6) | (wbuffer(1) >> 2); // 14 bit + pixelbuffer[1] = (((wbuffer(1) & 0x3) << 12) | (wbuffer(2) << 4) | (wbuffer(3) >> 4)) & 0x3fff; + pixelbuffer[2] = (wbuffer(3) >> 2) & 0x3; + pixelbuffer[3] = ((wbuffer(3) & 0x3) << 8) | wbuffer(4); + pixelbuffer[4] = (wbuffer(5) << 2) | (wbuffer(6) >> 6); + pixelbuffer[5] = ((wbuffer(6) & 0x3f) << 4) | (wbuffer(7) >> 4); + pixelbuffer[6] = (wbuffer(7) >> 2) & 0x3; + pixelbuffer[7] = ((wbuffer(7) & 0x3) << 8) | wbuffer(8); + pixelbuffer[8] = ((wbuffer(9) << 2) & 0x3fc) | (wbuffer(10) >> 6); + pixelbuffer[9] = ((wbuffer(10) << 4) | (wbuffer(11) >> 4)) & 0x3ff; + pixelbuffer[10] = (wbuffer(11) >> 2) & 0x3; + pixelbuffer[11] = ((wbuffer(11) & 0x3) << 8) | wbuffer(12); + pixelbuffer[12] = (((wbuffer(13) << 2) & 0x3fc) | wbuffer(14) >> 6) & 0x3ff; + pixelbuffer[13] = ((wbuffer(14) << 4) | (wbuffer(15) >> 4)) & 0x3ff; + current = 0; + lastoffset += 16; +} +#undef wbuffer + +void DCraw::panasonic_load_raw() +{ + int enc_blck_size = RT_pana_info.bpp == 12 ? 10 : 9; + if (RT_pana_info.encoding == 5) { + pana_bits_t pana_bits(ifp, load_flags, RT_pana_info.encoding); + pana_bits(0, 0); + unsigned bytes[16] = {}; + for (int row = 0; row < raw_height; ++row) { + ushort* raw_block_data = raw_image + row * raw_width; + + for (int col = 0; col < raw_width; col += enc_blck_size) { + pana_bits(0, bytes); + + if (RT_pana_info.bpp == 12) { + raw_block_data[col] = ((bytes[1] & 0xF) << 8) + bytes[0]; + raw_block_data[col + 1] = 16 * bytes[2] + (bytes[1] >> 4); + raw_block_data[col + 2] = ((bytes[4] & 0xF) << 8) + bytes[3]; + raw_block_data[col + 3] = 16 * bytes[5] + (bytes[4] >> 4); + raw_block_data[col + 4] = ((bytes[7] & 0xF) << 8) + bytes[6]; + raw_block_data[col + 5] = 16 * bytes[8] + (bytes[7] >> 4); + raw_block_data[col + 6] = ((bytes[10] & 0xF) << 8) + bytes[9]; + raw_block_data[col + 7] = 16 * bytes[11] + (bytes[10] >> 4); + raw_block_data[col + 8] = ((bytes[13] & 0xF) << 8) + bytes[12]; + raw_block_data[col + 9] = 16 * bytes[14] + (bytes[13] >> 4); + } + else if (RT_pana_info.bpp == 14) { + raw_block_data[col] = bytes[0] + ((bytes[1] & 0x3F) << 8); + raw_block_data[col + 1] = (bytes[1] >> 6) + 4 * (bytes[2]) + ((bytes[3] & 0xF) << 10); + raw_block_data[col + 2] = (bytes[3] >> 4) + 16 * (bytes[4]) + ((bytes[5] & 3) << 12); + raw_block_data[col + 3] = ((bytes[5] & 0xFC) >> 2) + (bytes[6] << 6); + raw_block_data[col + 4] = bytes[7] + ((bytes[8] & 0x3F) << 8); + raw_block_data[col + 5] = (bytes[8] >> 6) + 4 * bytes[9] + ((bytes[10] & 0xF) << 10); + raw_block_data[col + 6] = (bytes[10] >> 4) + 16 * bytes[11] + ((bytes[12] & 3) << 12); + raw_block_data[col + 7] = ((bytes[12] & 0xFC) >> 2) + (bytes[13] << 6); + raw_block_data[col + 8] = bytes[14] + ((bytes[15] & 0x3F) << 8); + } + } + } + } else if (RT_pana_info.encoding == 6) { + panasonicC6_load_raw(); + } else if (RT_pana_info.encoding == 7) { + panasonicC7_load_raw(); + } else { + pana_bits_t pana_bits(ifp, load_flags, RT_pana_info.encoding); + pana_bits(0, 0); + int sh = 0, pred[2], nonz[2]; + for (int row = 0; row < height; ++row) { + for (int col = 0; col < raw_width; ++col) { + int i; + if ((i = col % 14) == 0) { + pred[0] = pred[1] = nonz[0] = nonz[1] = 0; + } + if (i % 3 == 2) { + sh = 4 >> (3 - pana_bits(2)); + } + if (nonz[i & 1]) { + int j; + if ((j = pana_bits(8))) { + if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4) { + pred[i & 1] &= ~(-1 << sh); + } + pred[i & 1] += j << sh; + } + } else if ((nonz[i & 1] = pana_bits(8)) || i > 11) { + pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4); + } + if ((raw_image[(row)*raw_width+(col)] = pred[col & 1]) > 4098 && col < width) { + derror(); + } + } + } + } +} + +void DCraw::panasonicC6_load_raw() +{ + constexpr int rowstep = 16; + const int blocksperrow = raw_width / 11; + const int rowbytes = blocksperrow * 16; + unsigned char *iobuf = (unsigned char *)malloc(rowbytes * rowstep); + merror(iobuf, "panasonicC6_load_raw()"); + + for (int row = 0; row < raw_height - rowstep + 1; row += rowstep) { + const int rowstoread = MIN(rowstep, raw_height - row); + fread(iobuf, rowbytes, rowstoread, ifp); + pana_cs6_page_decoder page(iobuf, rowbytes * rowstoread); + for (int crow = 0, col = 0; crow < rowstoread; ++crow, col = 0) { + unsigned short *rowptr = &raw_image[(row + crow) * raw_width]; + for (int rblock = 0; rblock < blocksperrow; rblock++) { + page.read_page(); + unsigned oddeven[2] = {0, 0}, nonzero[2] = {0, 0}; + unsigned pmul = 0, pixel_base = 0; + for (int pix = 0; pix < 11; ++pix) { + if (pix % 3 == 2) { + unsigned base = page.nextpixel(); + if (base > 3) { + derror(); + } + if (base == 3) { + base = 4; + } + pixel_base = 0x200 << base; + pmul = 1 << base; + } + unsigned epixel = page.nextpixel(); + if (oddeven[pix % 2]) { + epixel *= pmul; + if (pixel_base < 0x2000 && nonzero[pix % 2] > pixel_base) { + epixel += nonzero[pix % 2] - pixel_base; + } + nonzero[pix % 2] = epixel; + } else { + oddeven[pix % 2] = epixel; + if (epixel) { + nonzero[pix % 2] = epixel; + } else { + epixel = nonzero[pix % 2]; + } + } + const unsigned spix = epixel - 0xf; + if (spix <= 0xffff) { + rowptr[col++] = spix & 0xffff; + } else { + epixel = (((signed int)(epixel + 0x7ffffff1)) >> 0x1f); + rowptr[col++] = epixel & 0x3fff; + } + } + } + } + } + free(iobuf); + tiff_bps = RT_pana_info.bpp; +} + +void DCraw::panasonicC7_load_raw() +{ + constexpr int rowstep = 16; + const int pixperblock = RT_pana_info.bpp == 14 ? 9 : 10; + const int rowbytes = raw_width / pixperblock * 16; + + unsigned char *iobuf = (unsigned char *)malloc(rowbytes * rowstep); + merror(iobuf, "panasonicC7_load_raw()"); + for (int row = 0; row < raw_height - rowstep + 1; row += rowstep) { + const int rowstoread = MIN(rowstep, raw_height - row); + fread (iobuf, rowbytes, rowstoread, ifp); + unsigned char *bytes = iobuf; + for (int crow = 0; crow < rowstoread; crow++) { + ushort *rowptr = &raw_image[(row + crow) * raw_width]; + for (int col = 0; col < raw_width - pixperblock + 1; col += pixperblock, bytes += 16) { + if (RT_pana_info.bpp == 14) { + rowptr[col] = bytes[0] + ((bytes[1] & 0x3F) << 8); + rowptr[col + 1] = (bytes[1] >> 6) + 4 * (bytes[2]) + ((bytes[3] & 0xF) << 10); + rowptr[col + 2] = (bytes[3] >> 4) + 16 * (bytes[4]) + ((bytes[5] & 3) << 12); + rowptr[col + 3] = ((bytes[5] & 0xFC) >> 2) + (bytes[6] << 6); + rowptr[col + 4] = bytes[7] + ((bytes[8] & 0x3F) << 8); + rowptr[col + 5] = (bytes[8] >> 6) + 4 * bytes[9] + ((bytes[10] & 0xF) << 10); + rowptr[col + 6] = (bytes[10] >> 4) + 16 * bytes[11] + ((bytes[12] & 3) << 12); + rowptr[col + 7] = ((bytes[12] & 0xFC) >> 2) + (bytes[13] << 6); + rowptr[col + 8] = bytes[14] + ((bytes[15] & 0x3F) << 8); + } else if (RT_pana_info.bpp == 12) { // have not seen in the wild yet + rowptr[col] = ((bytes[1] & 0xF) << 8) + bytes[0]; + rowptr[col + 1] = 16 * bytes[2] + (bytes[1] >> 4); + rowptr[col + 2] = ((bytes[4] & 0xF) << 8) + bytes[3]; + rowptr[col + 3] = 16 * bytes[5] + (bytes[4] >> 4); + rowptr[col + 4] = ((bytes[7] & 0xF) << 8) + bytes[6]; + rowptr[col + 5] = 16 * bytes[8] + (bytes[7] >> 4); + rowptr[col + 6] = ((bytes[10] & 0xF) << 8) + bytes[9]; + rowptr[col + 7] = 16 * bytes[11] + (bytes[10] >> 4); + rowptr[col + 8] = ((bytes[13] & 0xF) << 8) + bytes[12]; + rowptr[col + 9] = 16 * bytes[14] + (bytes[13] >> 4); + } + } + } + } + free(iobuf); + tiff_bps = RT_pana_info.bpp; +} diff --git a/rtengine/pdaflinesfilter.cc b/rtengine/pdaflinesfilter.cc index 0c5b2d786..1eddbc1ea 100644 --- a/rtengine/pdaflinesfilter.cc +++ b/rtengine/pdaflinesfilter.cc @@ -15,20 +15,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 "pdaflinesfilter.h" -#include "settings.h" #include + #include "camconst.h" +#include "pdaflinesfilter.h" +#include "pixelsmap.h" +#include "rawimage.h" +#include "settings.h" -namespace rtengine { +namespace rtengine +{ -extern const Settings *settings; - - -namespace { +namespace +{ class PDAFGreenEqulibrateThreshold: public RawImageSource::GreenEqulibrateThreshold { static constexpr float BASE_THRESHOLD = 0.5f; @@ -166,8 +168,6 @@ private: } // namespace - - PDAFLinesFilter::PDAFLinesFilter(RawImage *ri): ri_(ri), W_(ri->get_width()), @@ -206,7 +206,7 @@ std::unique_ptr PDAFLinesFilter::lineD } -int PDAFLinesFilter::markLine(array2D &rawData, PixelsMap &bpMap, int y) +int PDAFLinesFilter::markLine(const array2D &rawData, PixelsMap &bpMap, int y) { rowmap_.clear(); rowmap_.resize((W_+1)/2, false); @@ -258,7 +258,7 @@ int PDAFLinesFilter::markLine(array2D &rawData, PixelsMap &bpMap, int y) } -int PDAFLinesFilter::mark(array2D &rawData, PixelsMap &bpMap) +int PDAFLinesFilter::mark(const array2D &rawData, PixelsMap &bpMap) { if (pattern_.empty()) { diff --git a/rtengine/pdaflinesfilter.h b/rtengine/pdaflinesfilter.h index b1f7bf650..707eb9371 100644 --- a/rtengine/pdaflinesfilter.h +++ b/rtengine/pdaflinesfilter.h @@ -15,27 +15,33 @@ * GNU General Public License for more details. * * 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 -namespace rtengine { +#include "noncopyable.h" +#include "rawimagesource.h" -class PDAFLinesFilter { +namespace rtengine +{ + +class RawImage; + +class PDAFLinesFilter: public rtengine::NonCopyable +{ public: explicit PDAFLinesFilter(RawImage *ri); ~PDAFLinesFilter(); - int mark(array2D &rawData, PixelsMap &bpMap); + int mark(const array2D &rawData, PixelsMap &bpMap); RawImageSource::GreenEqulibrateThreshold &greenEqThreshold(); std::unique_ptr lineDenoiseRowBlender(); private: - int markLine(array2D &rawData, PixelsMap &bpMap, int y); + int markLine(const array2D& rawData, PixelsMap &bpMap, int y); RawImage *ri_; int W_; diff --git a/rtengine/pipettebuffer.cc b/rtengine/pipettebuffer.cc index 34a52a5c0..11cf50ae9 100644 --- a/rtengine/pipettebuffer.cc +++ b/rtengine/pipettebuffer.cc @@ -14,12 +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 "pipettebuffer.h" #include "imagefloat.h" +#include "labimage.h" #include "../rtgui/editcallbacks.h" @@ -176,9 +177,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..6f017a196 100644 --- a/rtengine/pipettebuffer.h +++ b/rtengine/pipettebuffer.h @@ -14,12 +14,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 . */ #pragma once -#include "array2D.h" -#include "coord.h" #include "iimage.h" class EditDataProvider; @@ -31,6 +29,7 @@ namespace rtengine { class Imagefloat; +class LabImage; /// @brief Structure that contains information about and pointers to the Edit buffer class PipetteBuffer diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc index b31ff62c9..2e98b7b22 100644 --- a/rtengine/pixelshift.cc +++ b/rtengine/pixelshift.cc @@ -16,21 +16,32 @@ // 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 "rawimagesource.h" -#include "../rtgui/multilangmgr.h" -#include "procparams.h" +#include + +#include "array2D.h" #include "gauss.h" #include "median.h" +#include "procparams.h" +#include "rawimagesource.h" +#include "sleef.h" +#include "../rtgui/multilangmgr.h" +#include "../rtgui/options.h" + //#define BENCHMARK #include "StopWatch.h" + namespace { +unsigned fc(const unsigned int cfa[2][2], int r, int c) { + return cfa[r & 1][c & 1]; +} + float greenDiff(float a, float b, float stddevFactor, float eperIso, float nreadIso, float prnu) { // calculate the difference between two green samples @@ -107,9 +118,9 @@ void xorMasks(int xStart, int xEnd, int yStart, int yEnd, const array2D } } -void floodFill4Impl(int y, int x, int xStart, int xEnd, int yStart, int yEnd, array2D &mask, std::stack, std::vector>> &coordStack) +void floodFill4Impl(int yin, int xin, int xStart, int xEnd, int yStart, int yEnd, array2D &mask, std::stack, std::vector>> &coordStack) { - coordStack.emplace(x, y); + coordStack.emplace(xin, yin); while(!coordStack.empty()) { auto coord = coordStack.top(); @@ -295,7 +306,7 @@ void calcFrameBrightnessFactor(unsigned int frame, uint32_t datalen, LUTu *histo using namespace std; using namespace rtengine; -void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RAWParams &rawParamsIn, unsigned int frame, const std::string &make, const std::string &model, float rawWpCorrection) +void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const procparams::RAWParams &rawParamsIn, unsigned int frame, const std::string &make, const std::string &model, float rawWpCorrection) { BENCHFUN if(numFrames != 4) { // fallback for non pixelshift files @@ -303,19 +314,20 @@ BENCHFUN return; } - RAWParams::BayerSensor bayerParams = rawParamsIn.bayersensor; + procparams::RAWParams::BayerSensor bayerParams = rawParamsIn.bayersensor; bool motionDetection = true; - if(bayerParams.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::PSMotionCorrectionMethod::AUTO) { + if(bayerParams.pixelShiftMotionCorrectionMethod == procparams::RAWParams::BayerSensor::PSMotionCorrectionMethod::AUTO) { bool pixelShiftEqualBright = bayerParams.pixelShiftEqualBright; bayerParams.setPixelShiftDefaults(); bayerParams.pixelShiftEqualBright = pixelShiftEqualBright; - } else if(bayerParams.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::PSMotionCorrectionMethod::OFF) { + } else if(bayerParams.pixelShiftMotionCorrectionMethod == procparams::RAWParams::BayerSensor::PSMotionCorrectionMethod::OFF) { motionDetection = false; bayerParams.pixelShiftShowMotion = false; } + const unsigned int cfarray[2][2] = {{FC(0,0), FC(0,1)}, {FC(1,0), FC(1,1)}}; const bool showMotion = bayerParams.pixelShiftShowMotion; const bool showOnlyMask = bayerParams.pixelShiftShowMotionMaskOnly && showMotion; const float smoothFactor = 1.0 - bayerParams.pixelShiftSmoothFactor; @@ -323,9 +335,11 @@ BENCHFUN if(motionDetection) { if(!showOnlyMask) { if(bayerParams.pixelShiftMedian) { // We need the demosaiced frames for motion correction - if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::LMMSE)) { + if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(procparams::RAWParams::BayerSensor::PSDemosaicMethod::LMMSE)) { lmmse_interpolate_omp(winw, winh, *(rawDataFrames[0]), red, green, blue, bayerParams.lmmse_iterations); - } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::AMAZEVNG4)) { + } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(procparams::RAWParams::BayerSensor::PSDemosaicMethod::AMAZEVNG4)) { + dual_demosaic_RT (true, rawParamsIn, winw, winh, *(rawDataFrames[0]), red, green, blue, bayerParams.dualDemosaicContrast, true); + } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(procparams::RAWParams::BayerSensor::PSDemosaicMethod::RCDVNG4)) { dual_demosaic_RT (true, rawParamsIn, winw, winh, *(rawDataFrames[0]), red, green, blue, bayerParams.dualDemosaicContrast, true); } else { amaze_demosaic_RT(winx, winy, winw, winh, *(rawDataFrames[0]), red, green, blue, options.chunkSizeAMAZE, options.measure); @@ -335,9 +349,11 @@ BENCHFUN multi_array2D blueTmp(winw, winh); for(int i = 0; i < 3; i++) { - if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::LMMSE)) { + if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(procparams::RAWParams::BayerSensor::PSDemosaicMethod::LMMSE)) { lmmse_interpolate_omp(winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i], bayerParams.lmmse_iterations); - } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::AMAZEVNG4)) { + } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(procparams::RAWParams::BayerSensor::PSDemosaicMethod::AMAZEVNG4)) { + dual_demosaic_RT (true, rawParamsIn, winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i], bayerParams.dualDemosaicContrast, true); + } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(procparams::RAWParams::BayerSensor::PSDemosaicMethod::RCDVNG4)) { dual_demosaic_RT (true, rawParamsIn, winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i], bayerParams.dualDemosaicContrast, true); } else { amaze_demosaic_RT(winx, winy, winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i], options.chunkSizeAMAZE, options.measure); @@ -362,11 +378,15 @@ BENCHFUN } } } else { - if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::LMMSE)) { + if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(procparams::RAWParams::BayerSensor::PSDemosaicMethod::LMMSE)) { lmmse_interpolate_omp(winw, winh, rawData, red, green, blue, bayerParams.lmmse_iterations); - } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::AMAZEVNG4)) { - RAWParams rawParamsTmp = rawParamsIn; - rawParamsTmp.bayersensor.method = RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZEVNG4); + } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(procparams::RAWParams::BayerSensor::PSDemosaicMethod::AMAZEVNG4)) { + procparams::RAWParams rawParamsTmp = rawParamsIn; + rawParamsTmp.bayersensor.method = procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEVNG4); + dual_demosaic_RT (true, rawParamsTmp, winw, winh, rawData, red, green, blue, bayerParams.dualDemosaicContrast, true); + } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(procparams::RAWParams::BayerSensor::PSDemosaicMethod::RCDVNG4)) { + procparams::RAWParams rawParamsTmp = rawParamsIn; + rawParamsTmp.bayersensor.method = procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCDVNG4); dual_demosaic_RT (true, rawParamsTmp, winw, winh, rawData, red, green, blue, bayerParams.dualDemosaicContrast, true); } else { amaze_demosaic_RT(winx, winy, winw, winh, rawData, red, green, blue, options.chunkSizeAMAZE, options.measure); @@ -634,11 +654,11 @@ BENCHFUN for(int i = winy + 1; i < winh - 1; ++i) { int j = winx + 1; - int c = FC(i, j); + int c = fc(cfarray, i, j); - bool bluerow = (c + FC(i, j + 1)) == 3; + bool bluerow = (c + fc(cfarray, i, j + 1)) == 3; - for(int j = winx + 1, offset = FC(i, j) & 1; j < winw - 1; ++j, offset ^= 1) { + for(int j = winx + 1, offset = fc(cfarray, i, j) & 1; j < winw - 1; ++j, offset ^= 1) { (*histogreenThr[1 - offset])[(*rawDataFrames[1 - offset])[i - offset + 1][j]]++; (*histogreenThr[3 - offset])[(*rawDataFrames[3 - offset])[i + offset][j + 1]]++; @@ -719,9 +739,9 @@ BENCHFUN }; int ng = 0; int j = winx + 1; - int c = FC(i, j); + int c = fc(cfarray, i, j); - if((c + FC(i, j + 1)) == 3) { + if((c + fc(cfarray, i, j + 1)) == 3) { // row with blue pixels => swap destination pointers for non green pixels std::swap(nonGreenDest0, nonGreenDest1); ng ^= 1; @@ -776,7 +796,7 @@ BENCHFUN for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) { // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop - unsigned int offset = FC(i, winx + border - offsX) & 1; + unsigned int offset = fc(cfarray, i, winx + border - offsX) & 1; for(int j = winx + border - offsX; j < winw - (border + offsX); ++j, offset ^= 1) { psMask[i][j] = noMotion; @@ -912,7 +932,7 @@ BENCHFUN float *blueDest = blue[i + offsY]; // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop - unsigned int offset = FC(i, winx + border - offsX) & 1; + unsigned int offset = fc(cfarray, i, winx + border - offsX) & 1; for(int j = winx + border - offsX; j < winw - (border + offsX); ++j, offset ^= 1) { if(showOnlyMask) { @@ -962,9 +982,9 @@ BENCHFUN float *nonGreenDest1 = blue[i]; int ng = 0; int j = winx + 1; - int c = FC(i, j); + int c = fc(cfarray, i, j); - if((c + FC(i, j + 1)) == 3) { + if((c + fc(cfarray, i, j + 1)) == 3) { // row with blue pixels => swap destination pointers for non green pixels std::swap(nonGreenDest0, nonGreenDest1); ng ^= 1; 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 e62a1adea..de1603f1c 100644 --- a/rtengine/previewimage.cc +++ b/rtengine/previewimage.cc @@ -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 . */ #include "previewimage.h" +#include "color.h" #include "iimage.h" #include "iimage.h" #include "procparams.h" diff --git a/rtengine/previewimage.h b/rtengine/previewimage.h index 26b9a85d2..2143509a3 100644 --- a/rtengine/previewimage.h +++ b/rtengine/previewimage.h @@ -14,14 +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 _PREVIEWIMAGE_ -#define _PREVIEWIMAGE_ +#pragma once + -#include #include +namespace Glib +{ + +class ustring; + +} + namespace rtengine { @@ -52,5 +58,3 @@ public: }; } - -#endif 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..9c3846958 100644 --- a/rtengine/processingjob.h +++ b/rtengine/processingjob.h @@ -14,18 +14,17 @@ * GNU General Public License for more details. * * 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_ +#pragma once -#include "rtengine.h" #include "procparams.h" +#include "rtengine.h" namespace rtengine { -class ProcessingJobImpl : public ProcessingJob +class ProcessingJobImpl final : public ProcessingJob { public: @@ -55,5 +54,3 @@ public: }; } - -#endif diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 6abf34d6d..2101275e8 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -14,17 +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 __PROCEVENT__ -#define __PROCEVENT__ +#pragma once namespace rtengine { - - - // Aligned so the first entry starts on line 30 enum ProcEventCode { EvPhotoLoaded = 0, @@ -520,8 +516,8 @@ enum ProcEventCode { EvWBEnabled = 490, EvRGBEnabled = 491, EvLEnabled = 492, -// EvPixelShiftOneGreen = 493, can be reused - EvLocallabSpotCreated = 494, + EvPdShrEnabled = 493, + EvPdShrMaskToggled = 494, EvLocallabSpotDeleted = 495, EvLocallabSpotSelected = 496, EvLocallabSpotName = 497, @@ -726,7 +722,7 @@ enum ProcEventCode { Evlocallabequiltm = 696, Evlocallabfftwlc = 697, Evlocallabfftwreti = 698, -// EvlocallabshowmasksoftMethod = 699, + // EvlocallabshowmasksoftMethod = 699, Evlocallabshadex = 700, EvlocallabexpMethod = 701, Evlocallablaplacexp = 702, @@ -741,53 +737,247 @@ enum ProcEventCode { Evlocallabchromasktm = 711, Evlocallabgammasktm = 712, Evlocallabslomasktm = 713, -// EvlocallabshowmasktmMethod = 714, + // EvlocallabshowmasktmMethod = 714, EvlocallablocalcontMethod = 715, EvlocallabwavCurve = 716, Evlocallablevelwav = 717, - Evlocallabresidcont = 718, + Evlocallabresidcont = 718, + EvlocallabCCmaskblshape = 719, + EvlocallabLLmaskblshape = 720, + EvlocallabHHmaskblshape = 721, + EvLocallabEnablMask = 722, + // EvlocallabshowmaskblMethod = 723, + Evlocallabblendmaskbl = 724, + Evlocallabradmaskbl = 725, + Evlocallabchromaskbl = 726, + Evlocallabgammaskbl = 727, + Evlocallabslomaskbl = 728, + EvlocallabblMethod = 729, + EvlocallabmedMethod = 730, + Evlocallabitera = 731, + Evlocallabguidbl = 732, + Evlocallabepsbl = 733, + // EvlocallabshowmaskcolMethodinv = 734, + // EvlocallabshowmaskexpMethodinv = 735, + // EvlocallabshowmaskSHMethodinv = 736, + Evlocallabclarilres = 737, + Evlocallabclarisoft = 738, + Evlocallabclaricres = 739, + Evlocallabresidchro = 740, + Evlocallabgamm = 741, + Evlocallabfatamount = 742, + Evlocallabfatdetail = 743, + Evlocallabfatanchor = 744, + Evlocallabfatlevel = 745, + EvLocallabSpotCreated = 746, + EvlocallabexnoiseMethod = 747, + Evlocallabdepth = 748, + Evlocallabloglin = 749, + Evlocallablumonly = 750, + Evlocallaboffs = 751, + EvlocallabCTtransCurve = 752, + Evlocallabcliptm = 753, + EvLocallabEnatmMaskaft = 754, + EvLocallabEnaExpMaskaft = 755, + Evlocallablapmasktm = 756, + Evlocallablapmaskreti = 757, + Evlocallablapmaskexp = 758, + Evlocallablapmaskcol = 759, + EvlocallablapmaskSH = 760, + Evlocallablapmaskcb = 761, + Evlocallablapmaskbl = 762, + Evlocallablaplac = 763, + Evlocallabdetailthr = 764, + Evlocallabfftwbl = 765, + Evlocallabisogr = 766, + Evlocallabstrengr = 767, + Evlocallabscalegr = 768, + EvlocallabLmaskshape = 769, + EvlocallabLmaskexpshape = 770, + EvlocallabLmaskSHshape = 771, + EvlocallabLmasktmshape = 772, + EvlocallabLmaskretishape = 773, + EvlocallabLmaskcbshape = 774, + EvlocallabLmaskblshape = 775, + EvlocallabLLmaskblshapewav = 776, + Evlocallabshadmaskbl = 777, + EvlocallabLLmaskcolshapewav = 778, + Evlocallabshadmaskcol = 779, + EvlocallabcsThreshold = 780, + EvlocallabcsThresholdblur = 781, + EvlocallabcsThresholdcol = 782, + Evlocallabdeltae = 783, + EvLocallabSpotscopemask = 784, + EvlocallabshMethod = 785, + EvlocallabEqualizersh = 786, + EvlocallabdetailSH = 787, + EvlocallabfatamountSH = 788, + EvlocallabfatanchorSH = 789, + Evlocallabshortc = 790, + EvLocallabSpotlumask = 791, + EvlocallabgamSH = 792, + EvlocallabsloSH = 793, + Evlocallabsavrest = 794, + Evlocallabrecurs = 795, + EvLocallabmergecolMethod = 796, + Evlocallabopacol = 797, + Evlocallabrgbshape = 798, + EvLocallabtoneMethod = 799, + EvLocallabspecial = 800, + Evlocallabconthrcol = 801, + EvLocallabmerMethod = 802, + Evlocallabstrumaskcol = 803, + Evlocallabstrumaskbl = 804, + EvLocallabtoolcol = 805, + Evlocallabtoolbl = 806, + EvlocallabHHhmaskshape = 807, + EvlocallabCCmaskvibshape = 808, + EvlocallabLLmaskvibshape = 809, + EvlocallabHHmaskvibshape = 810, + // EvlocallabshowmaskvibMethod = 811, + EvLocallabEnavibMask = 812, + Evlocallabblendmaskvi = 813, + Evlocallabradmaskvib = 814, + Evlocallabchromaskvib = 815, + Evlocallabgammaskvib = 816, + Evlocallabslomaskvib = 817, + Evlocallablapmaskvib = 818, + EvlocallabLmaskvibshape = 819, + EvLocallabLabGridmergValue = 820, + Evlocallabmercol = 821, + Evlocallabmerlucol = 822, + Evlocallabstrmaskexp = 823, + Evlocallabangmaskexp = 824, + Evlocallabstrexp = 825, + Evlocallabangexp = 826, + EvlocallabstrSH = 827, + EvlocallabangSH = 828, + Evlocallabstrcol = 829, + Evlocallabangcol = 830, + Evlocallabstrcolab = 831, + EvLocallabSpotfeather = 832, + Evlocallabstrcolh = 833, + Evlocallabstrvib = 834, + Evlocallabangvib = 835, + Evlocallabstrvibab = 836, + Evlocallabstrvibh = 837, + EvLocallabSpotcomplexMethod = 838, + Evlocallabclshape = 839, + Evlocallablcshape = 840, + Evlocallabblurcol = 841, + Evlocallabcontcol = 842, + EvLocallabfftColorMask = 843, + EvLocenalog = 844, + EvLocallabAuto = 845, + EvlocallabsourceGray = 846, + EvlocallabsourceGrayAuto = 847, + EvlocallabAutogray = 848, + EvlocallabblackEv = 849, + EvlocallabwhiteEv = 850, + EvlocallabtargetGray = 851, + Evlocallabdetail = 852, + Evlocallabsensilog = 853, + Evlocallabfullimage = 854, + Evlocallabbaselog = 855, + Evlocallabresidblur = 856, + Evlocallabblurlc = 857, + Evlocallablevelblur = 858, + EvlocallabwavCurvelev = 859, + EvlocallabwavCurvecon = 860, + Evlocallabsigma = 861, + Evlocallaboriglc = 862, + Evlocallabfatdet = 863, + Evlocallabfatanch = 864, + EvlocallabwavCurvecomp = 865, + Evlocallabfatres = 866, + EvLocallabSpotbalanh = 867, + EvlocallabwavCurveden = 868, + EvlocallabHHmasklcshape = 869, + EvlocallabCCmasklcshape = 870, + EvlocallabLLmasklcshape = 871, + EvLocallabEnalcMask = 872, + // EvlocallabshowmasklcMethod = 873, + Evlocallabblendmasklc = 874, + Evlocallabradmasklc = 875, + Evlocallabchromasklc = 876, + EvlocallabLmasklcshape = 877, + Evlocallabchromalev = 878, + Evlocallabchromablu = 879, + Evlocallaboffset = 880, + Evlocallabwavblur = 881, + Evlocallabwavcont = 882, + Evlocallabwavcomp = 883, + Evlocallabwavcompre = 884, + EvlocallabwavCurvecompre = 885, + Evlocallabresidcomp = 886, + Evlocallabthreswav = 887, + Evlocallabstrwav = 888, + Evlocallabangwav = 889, + Evlocallabwavgradl = 890, + Evlocallabstrlog = 891, + Evlocallabanglog = 892, + EvLocallabSpotcolorde = 893, + // EvlocallabshowmasksharMethod = 894, + Evlocallabshowreset = 895, + Evlocallabstrengthw = 896, + Evlocallabradiusw = 897, + Evlocallabdetailw = 898, + Evlocallabgradw = 899, + Evlocallabtloww = 900, + Evlocallabthigw = 901, + EvlocallabwavCurveedg = 902, + EvlocallablocaledgMethod = 903, + Evlocallabwavedg = 904, + Evlocallabedgw = 905, + Evlocallabbasew = 906, + EvlocallablocalneiMethod = 907, + Evlocallabwaveshow = 908, + EvLocallabSpotwavMethod = 909, + EvlocallabchroMethod = 910, + Evlocallabstrbl = 911, + NUMOFEVENTS }; - class ProcEvent { public: ProcEvent(): code_(0) {} ProcEvent(ProcEventCode code): code_(code) {} explicit ProcEvent(int code): code_(code) {} - operator int() const { return code_; } + operator int() const + { + return code_; + } private: int code_; }; -inline bool operator==(ProcEvent a, ProcEvent b) +inline bool operator ==(ProcEvent a, ProcEvent b) { return int(a) == int(b); } -inline bool operator==(ProcEvent a, ProcEventCode b) +inline bool operator ==(ProcEvent a, ProcEventCode b) { return int(a) == int(b); } -inline bool operator==(ProcEventCode a, ProcEvent b) +inline bool operator ==(ProcEventCode a, ProcEvent b) { return int(a) == int(b); } -inline bool operator!=(ProcEvent a, ProcEvent b) +inline bool operator !=(ProcEvent a, ProcEvent b) { return int(a) != int(b); } -inline bool operator!=(ProcEvent a, ProcEventCode b) +inline bool operator !=(ProcEvent a, ProcEventCode b) { return int(a) != int(b); } -inline bool operator!=(ProcEventCode a, ProcEvent b) +inline bool operator !=(ProcEventCode a, ProcEvent b) { return int(a) != int(b); } } -#endif - diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index d91385171..7a817050d 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 @@ -22,9 +22,14 @@ #include #include +#include +#include +#include +#include "color.h" #include "curves.h" #include "procparams.h" +#include "utils.h" #include "../rtgui/multilangmgr.h" #include "../rtgui/options.h" @@ -65,7 +70,7 @@ Glib::ustring relativePathIfInside(const Glib::ustring &procparams_fname, bool f 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); @@ -330,6 +335,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 @@ -1079,7 +1107,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), @@ -1102,9 +1132,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 @@ -1122,6 +1154,36 @@ bool SharpeningParams::operator !=(const SharpeningParams& other) const return !(*this == other); } +CaptureSharpeningParams::CaptureSharpeningParams() : + enabled(false), + autoContrast(true), + autoRadius(true), + contrast(10.0), + deconvradius(0.75), + deconvradiusOffset(0.0), + deconviter(20), + deconvitercheck(true) +{ +} + +bool CaptureSharpeningParams::operator ==(const CaptureSharpeningParams& other) const +{ + return + enabled == other.enabled + && contrast == other.contrast + && autoContrast == other.autoContrast + && autoRadius == other.autoRadius + && deconvradius == other.deconvradius + && deconvitercheck == other.deconvitercheck + && deconvradiusOffset == other.deconvradiusOffset + && deconviter == other.deconviter; +} + +bool CaptureSharpeningParams::operator !=(const CaptureSharpeningParams& other) const +{ + return !(*this == other); +} + SharpenEdgeParams::SharpenEdgeParams() : enabled(false), passes(2), @@ -1210,6 +1272,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 @@ -1655,13 +1732,14 @@ bool CoarseTransformParams::operator !=(const CoarseTransformParams& other) cons } CommonTransformParams::CommonTransformParams() : + method("log"), autofill(true) { } bool CommonTransformParams::operator ==(const CommonTransformParams& other) const { - return autofill == other.autofill; + return method == other.method && autofill == other.autofill; } bool CommonTransformParams::operator !=(const CommonTransformParams& other) const @@ -2340,6 +2418,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : isvisible(true), shape("ELI"), spotMethod("norm"), + wavMethod("D4"), sensiexclu(12), structexclu(0), struc(4.0), @@ -2352,13 +2431,24 @@ LocallabParams::LocallabSpot::LocallabSpot() : centerY(0), circrad(18), qualityMethod("enh"), - transit(60), + complexMethod("mod"), + transit(60.), + feather(25.), thresh(2.0), iter(2.0), balan(1.0), + balanh(1.0), + colorde(5.0), transitweak(1.0), transitgrad(0.0), avoid(false), + recurs(false), + laplac(false), + deltae(true), + shortc(false), + savrest(false), + scopemask(60), + lumask(10), // Color & Light visicolor(false), expcolor(false), @@ -2370,27 +2460,57 @@ LocallabParams::LocallabSpot::LocallabSpot() : labgridBLow(0.0), labgridAHigh(0.0), labgridBHigh(0.0), + labgridALowmerg(0.0), + labgridBLowmerg(0.0), + labgridAHighmerg(-3500.0), + labgridBHighmerg(-4600.0), strengthgrid(30), sensi(15), structcol(0), + strcol(0.), + strcolab(0.), + strcolh(0.), + angcol(0.), blurcolde(5), + blurcol(0.2), + contcol(0.), blendmaskcol(0), - radmaskcol(10.0), + radmaskcol(0.0), chromaskcol(0.0), gammaskcol(1.0), slomaskcol(0.0), + shadmaskcol(0), + strumaskcol(0.), + lapmaskcol(0.0), qualitycurveMethod("none"), gridMethod("one"), - llcurve(DEF_COLOR_LCURVE), - cccurve(DEF_COLOR_LCURVE), - LHcurve(DEF_COLOR_HCURVE), - HHcurve(DEF_COLOR_HCURVE), + merMethod("mone"), + toneMethod("fou"), + mergecolMethod("one"), + llcurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, + lccurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, + cccurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, + clcurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, + rgbcurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, + LHcurve{(double)FCT_MinMaxCPoints, 0.0, 0.50, 0.35, 0.35, 0.166, 0.50, 0.35, 0.35, 0.333, 0.50, 0.35, 0.35, 0.50, 0.50, 0.35, 0.35, 0.666, 0.50, 0.35, 0.35, 0.833, 0.50, 0.35, 0.35}, + HHcurve{(double)FCT_MinMaxCPoints, 0.0, 0.50, 0.35, 0.35, 0.166, 0.50, 0.35, 0.35, 0.333, 0.50, 0.35, 0.35, 0.50, 0.50, 0.35, 0.35, 0.666, 0.50, 0.35, 0.35, 0.833, 0.50, 0.35, 0.35}, invers(false), + special(false), + toolcol(true), enaColorMask(false), - CCmaskcurve(DEF_MASK_CURVE), - LLmaskcurve(DEF_MASK_CURVE), - HHmaskcurve(DEF_MASK_CURVE), + fftColorMask(false), + CCmaskcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.00, 1.0, 0.35, 0.35}, + LLmaskcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.00, 1.0, 0.35, 0.35}, + HHmaskcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.00, 1.0, 0.35, 0.35}, + HHhmaskcurve{(double)FCT_MinMaxCPoints, 0.0, 0.5, 0.35, 0.35, 0.50, 0.5, 0.35, 0.35, 1.00, 0.5, 0.35, 0.35}, softradiuscol(0.0), + opacol(60.0), + mercol(18.0), + merlucol(32.0), + conthrcol(0.0), + Lmaskcurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, + LLmaskcolcurvewav{(double)FCT_MinMaxCPoints, 0.0, 0.5, 0.35, 0.35, 1., 0.5, 0.35, 0.35}, + csthresholdcol(0, 0, 6, 5, false), // Exposure visiexpose(false), expexpose(false), @@ -2401,29 +2521,43 @@ LocallabParams::LocallabSpot::LocallabSpot() : shadex(0), shcompr(50), expchroma(30), - warm(0), sensiex(15), structexp(0), blurexpde(5), - excurve(DEF_EXP_CURVE), + strexp(0.), + angexp(0.), + excurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, inversex(false), enaExpMask(false), - CCmaskexpcurve(DEF_MASK_CURVE), - LLmaskexpcurve(DEF_MASK_CURVE), - HHmaskexpcurve(DEF_MASK_CURVE), + enaExpMaskaft(false), + CCmaskexpcurve{(double)FCT_MinMaxCPoints,0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + LLmaskexpcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + HHmaskexpcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, blendmaskexp(0), - radmaskexp(10.0), + radmaskexp(0.0), chromaskexp(0.0), gammaskexp(1.0), slomaskexp(0.0), + lapmaskexp(0.0), + strmaskexp(0.0), + angmaskexp(0.0), softradiusexp(0.0), + Lmaskexpcurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, expMethod("std"), - laplacexp(20.0), - balanexp(0.8), - linear(0.0), + exnoiseMethod("none"), + laplacexp(0.0), + balanexp(1.0), + linear(0.3), + gamm(0.4), + fatamount(1.0), + fatdetail(40.0), + fatanchor(1.0), + fatlevel(1.), // Shadow highlight visishadhigh(false), expshadhigh(false), + shMethod("std"), + multsh{0, 0, 0, 0, 0}, highlights(0), h_tonalwidth(70), shadows(0), @@ -2431,27 +2565,52 @@ LocallabParams::LocallabSpot::LocallabSpot() : sh_radius(40), sensihs(15), enaSHMask(false), - CCmaskSHcurve(DEF_MASK_CURVE), - LLmaskSHcurve(DEF_MASK_CURVE), - HHmaskSHcurve(DEF_MASK_CURVE), + CCmaskSHcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + LLmaskSHcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + HHmaskSHcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, blendmaskSH(0), - radmaskSH(10.0), + radmaskSH(0.0), blurSHde(5), + strSH(0.), + angSH(0.), inverssh(false), chromaskSH(0.0), gammaskSH(1.0), slomaskSH(0.0), + lapmaskSH(0.0), + detailSH(0), + LmaskSHcurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, + fatamountSH(1.0), + fatanchorSH(50.0), + gamSH(2.4), + sloSH(12.92), // Vibrance visivibrance(false), expvibrance(false), saturated(0), pastels(0), + warm(0), psthreshold({0, 75, false}), protectskins(false), avoidcolorshift(true), pastsattog(true), sensiv(15), skintonescurve{(double)DCT_Linear}, + CCmaskvibcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35 }, + LLmaskvibcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + HHmaskvibcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + enavibMask(false), + blendmaskvib(0), + radmaskvib(0.0), + chromaskvib(0.0), + gammaskvib(1.0), + slomaskvib(0.0), + lapmaskvib(0.0), + strvib(0.0), + strvibab(0.0), + strvibh(0.0), + angvib(0.0), + Lmaskvibcurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, // Soft Light visisoft(false), expsoft(false), @@ -2462,62 +2621,100 @@ LocallabParams::LocallabSpot::LocallabSpot() : // Blur & Noise visiblur(false), expblur(false), - radius(1.0), + radius(1.5), strength(0), sensibn(40), + itera(1), + guidbl(0), + strbl(50), + isogr(400), + strengr(0), + scalegr(100), + epsbl(0), + blMethod("guid"), + chroMethod("lum"), blurMethod("norm"), - activlum(false), + medMethod("33"), + activlum(true), + CCmaskblcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + LLmaskblcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + HHmaskblcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + enablMask(false), + fftwbl(false), + toolbl(false), + blendmaskbl(0), + radmaskbl(0.0), + chromaskbl(0.0), + gammaskbl(1.0), + slomaskbl(0.0), + lapmaskbl(0.0), + shadmaskbl(0), + strumaskbl(0.), + Lmaskblcurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, + LLmaskblcurvewav{(double)FCT_MinMaxCPoints, 0.0, 0.5, 0.35, 0.35, 1., 0.5, 0.35, 0.35}, + csthresholdblur(0, 0, 6, 5, false), // Tone Mapping visitonemap(false), exptonemap(false), stren(0.5), gamma(1.0), - estop(0.5), - scaltm(4.0), + estop(1.4), + scaltm(1.0), rewei(0), satur(0.), sensitm(19), softradiustm(0.0), amount(95.), equiltm(true), - CCmasktmcurve(DEF_MASK_CURVE), - LLmasktmcurve(DEF_MASK_CURVE), - HHmasktmcurve(DEF_MASK_CURVE), + CCmasktmcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + LLmasktmcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + HHmasktmcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, enatmMask(false), + enatmMaskaft(false), blendmasktm(0), - radmasktm(10.0), + radmasktm(0.0), chromasktm(0.0), gammasktm(1.0), slomasktm(0.0), + lapmasktm(0.0), + Lmasktmcurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, // Retinex visireti(false), expreti(false), retinexMethod("high"), - str(0.0), + str(0.2), chrrt(0.0), - neigh(200.), - vart(70.), + neigh(50.0), + vart(150.0), + offs(0.0), dehaz(0), - sensih(30), - localTgaincurve(DEF_RET_CURVE), + depth(25), + sensih(60), + localTgaincurve{(double)FCT_MinMaxCPoints, 0.0, 0.12, 0.35, 0.35, 0.70, 0.50, 0.35, 0.35, 1.00, 0.12, 0.35, 0.35}, + localTtranscurve{(double)FCT_MinMaxCPoints, 0.0, 0.50, 0.35, 0.35, 0.5, 0.5, 0.35, 0.35, 1.00, 0.50, 0.35, 0.35}, inversret(false), equilret(true), - softradiusret(0.0), - CCmaskreticurve(DEF_MASK_CURVE), - LLmaskreticurve(DEF_MASK_CURVE), - HHmaskreticurve(DEF_MASK_CURVE), + loglin(false), + lumonly(false), + softradiusret(40.0), + CCmaskreticurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + LLmaskreticurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + HHmaskreticurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, enaretiMask(false), - enaretiMasktmap(false), + enaretiMasktmap(true), blendmaskreti(0), - radmaskreti(10.0), + radmaskreti(0.0), chromaskreti(0.0), gammaskreti(1.0), slomaskreti(0.0), - scalereti(3.0), - darkness(1.0), + lapmaskreti(0.0), + scalereti(2.0), + darkness(2.0), lightnessreti(1.0), limd(8.0), + cliptm(1.0), fftwreti(false), + Lmaskreticurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, // Sharpening visisharp(false), expsharp(false), @@ -2538,10 +2735,60 @@ LocallabParams::LocallabSpot::LocallabSpot() : lclightness(1.0), levelwav(4), residcont(0.0), - sensilc(19), + residblur(0.0), + levelblur(0.0), + residchro(0.0), + residcomp(0.0), + sigma(1.0), + offset(1.0), + threswav(1.4), + chromalev(1.0), + chromablu(1.0), + fatdet(40.0), + fatanch(50.0), + fatres(0.0), + clarilres(0.0), + claricres(0.0), + clarisoft(1.0), + strwav(0.0), + angwav(0.0), + strengthw(0.0), + radiusw(15.0), + detailw(10.0), + gradw(90.0), + tloww(20.0), + thigw(0.0), + edgw(60.0), + basew(10.0), + sensilc(30), fftwlc(false), + blurlc(true), + wavblur(false), + wavedg(false), + waveshow(false), + wavcont(false), + wavcomp(false), + wavgradl(false), + wavcompre(false), + origlc(false), localcontMethod("loc"), - locwavcurve(DEF_LC_CURVE), + localedgMethod("thr"), + localneiMethod("low"), + locwavcurve{(double)FCT_MinMaxCPoints, 0.0, 0.5, 0.35, 0.35, 1., 0.5, 0.35, 0.35}, + csthreshold(0, 0, 6, 6, false), + loclevwavcurve{(double)FCT_MinMaxCPoints, 0.0, 0.0, 0.0, 0.35, 0.5, 0., 0.35, 0.35, 1.0, 0.0, 0.35, 0.35}, + locconwavcurve{(double)FCT_MinMaxCPoints, 0.0, 0.5, 0.35, 0.35, 1., 0.5, 0.35, 0.35}, + loccompwavcurve{(double)FCT_MinMaxCPoints, 0.0, 0.0, 0.0, 0.35, 0.5, 0., 0.35, 0.35, 1.0, 0.0, 0.35, 0.35}, + loccomprewavcurve{(double)FCT_MinMaxCPoints, 0.0, 0.75, 0.35, 0.35, 1., 0.75, 0.35, 0.35}, + locedgwavcurve{(double)FCT_MinMaxCPoints, 0.0, 0.25, 0.35, 0.35, 0.50, 0.75, 0.35, 0.35, 0.90, 0.0, 0.35, 0.35}, + CCmasklccurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35 }, + LLmasklccurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + HHmasklccurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + enalcMask(false), + blendmasklc(0), + radmasklc(0.0), + chromasklc(0.0), + Lmasklccurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, // Contrast by detail levels visicbdl(false), expcbdl(false), @@ -2554,29 +2801,48 @@ LocallabParams::LocallabSpot::LocallabSpot() : blurcbdl(0.), softradiuscb(0.0), enacbMask(false), - CCmaskcbcurve(DEF_MASK_CURVE), - LLmaskcbcurve(DEF_MASK_CURVE), - HHmaskcbcurve(DEF_MASK_CURVE), + CCmaskcbcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + LLmaskcbcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + HHmaskcbcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, blendmaskcb(0), - radmaskcb(10.0), + radmaskcb(0.0), chromaskcb(0.0), gammaskcb(1.0), slomaskcb(0.0), + lapmaskcb(0.0), + Lmaskcbcurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, // Denoise visidenoi(false), expdenoi(false), - noiselumf(0), - noiselumf0(0), - noiselumf2(0), - noiselumc(0), - noiselumdetail(0), + noiselumf(0.), + noiselumf0(0.), + noiselumf2(0.), + noiselumc(0.), + noiselumdetail(0.), noiselequal(7), - noisechrof(0), - noisechroc(0), - noisechrodetail(0), + noisechrof(0.), + noisechroc(0.), + noisechrodetail(0.), adjblur(0), bilateral(0), - sensiden(20) + sensiden(20), + detailthr(0), + locwavcurveden{(double)FCT_MinMaxCPoints, 0.0, 0.0, 0.0, 0.35, 0.5, 0., 0.35, 0.35, 1.0, 0.0, 0.35, 0.35}, + // Log encoding + visilog(false), + explog(false), + autocompute(false), + sourceGray(10.), + targetGray(18.), + Autogray(true), + fullimage(true), + blackEv(-5.0), + whiteEv(10.0), + detail(0.6), + sensilog(50), + baselog(2.), + strlog(0.0), + anglog(0.0) { } @@ -2588,6 +2854,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && isvisible == other.isvisible && shape == other.shape && spotMethod == other.spotMethod + && wavMethod == other.wavMethod && sensiexclu == other.sensiexclu && structexclu == other.structexclu && struc == other.struc @@ -2600,13 +2867,24 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && centerY == other.centerY && circrad == other.circrad && qualityMethod == other.qualityMethod + && complexMethod == other.complexMethod && transit == other.transit + && feather == other.feather && thresh == other.thresh && iter == other.iter && balan == other.balan + && balanh == other.balanh + && colorde == other.colorde && transitweak == other.transitweak && transitgrad == other.transitgrad && avoid == other.avoid + && recurs == other.recurs + && laplac == other.laplac + && deltae == other.deltae + && shortc == other.shortc + && savrest == other.savrest + && scopemask == other.scopemask + && lumask == other.lumask // Color & Light && visicolor == other.visicolor && expcolor == other.expcolor @@ -2618,27 +2896,57 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && labgridBLow == other.labgridBLow && labgridAHigh == other.labgridAHigh && labgridBHigh == other.labgridBHigh + && labgridALowmerg == other.labgridALowmerg + && labgridBLowmerg == other.labgridBLowmerg + && labgridAHighmerg == other.labgridAHighmerg + && labgridBHighmerg == other.labgridBHighmerg && strengthgrid == other.strengthgrid && sensi == other.sensi && structcol == other.structcol + && strcol == other.strcol + && strcolab == other.strcolab + && strcolh == other.strcolh + && angcol == other.angcol + && blurcolde == other.blurcolde + && blurcol == other.blurcol + && contcol == other.contcol && blendmaskcol == other.blendmaskcol && radmaskcol == other.radmaskcol && chromaskcol == other.chromaskcol && gammaskcol == other.gammaskcol && slomaskcol == other.slomaskcol + && shadmaskcol == other.shadmaskcol + && strumaskcol == other.strumaskcol + && lapmaskcol == other.lapmaskcol && qualitycurveMethod == other.qualitycurveMethod && gridMethod == other.gridMethod + && merMethod == other.merMethod + && toneMethod == other.toneMethod + && mergecolMethod == other.mergecolMethod && llcurve == other.llcurve + && lccurve == other.lccurve && cccurve == other.cccurve + && clcurve == other.clcurve + && rgbcurve == other.rgbcurve && LHcurve == other.LHcurve && HHcurve == other.HHcurve && invers == other.invers + && special == other.special + && toolcol == other.toolcol && enaColorMask == other.enaColorMask + && fftColorMask == other.fftColorMask && CCmaskcurve == other.CCmaskcurve && LLmaskcurve == other.LLmaskcurve && HHmaskcurve == other.HHmaskcurve - && blurcolde == other.blurcolde + && HHhmaskcurve == other.HHhmaskcurve && softradiuscol == other.softradiuscol + && opacol == other.opacol + && mercol == other.mercol + && merlucol == other.merlucol + && conthrcol == other.conthrcol + && Lmaskcurve == other.Lmaskcurve + && LLmaskcolcurvewav == other.LLmaskcolcurvewav + && csthresholdcol == other.csthresholdcol // Exposure && visiexpose == other.visiexpose && expexpose == other.expexpose @@ -2649,13 +2957,15 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && shadex == other.shadex && shcompr == other.shcompr && expchroma == other.expchroma - && warm == other.warm && sensiex == other.sensiex && structexp == other.structexp && blurexpde == other.blurexpde + && strexp == other.strexp + && angexp == other.angexp && excurve == other.excurve && inversex == other.inversex && enaExpMask == other.enaExpMask + && enaExpMaskaft == other.enaExpMaskaft && CCmaskexpcurve == other.CCmaskexpcurve && LLmaskexpcurve == other.LLmaskexpcurve && HHmaskexpcurve == other.HHmaskexpcurve @@ -2664,14 +2974,35 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && chromaskexp == other.chromaskexp && gammaskexp == other.gammaskexp && slomaskexp == other.slomaskexp + && lapmaskexp == other.lapmaskexp + && strmaskexp == other.strmaskexp + && angmaskexp == other.angmaskexp && softradiusexp == other.softradiusexp + && Lmaskexpcurve == other.Lmaskexpcurve && expMethod == other.expMethod + && exnoiseMethod == other.exnoiseMethod && laplacexp == other.laplacexp && balanexp == other.balanexp && linear == other.linear + && gamm == other.gamm + && fatamount == other.fatamount + && fatdetail == other.fatdetail + && fatanchor == other.fatanchor + && fatlevel == other.fatlevel // Shadow highlight && visishadhigh == other.visishadhigh && expshadhigh == other.expshadhigh + && shMethod == other.shMethod + && [this, &other]()->bool { + for (int i = 0; i < 5; i++) + { + if (multsh[i] != other.multsh[i]) { + return false; + } + } + + return true; + }() && highlights == other.highlights && h_tonalwidth == other.h_tonalwidth && shadows == other.shadows @@ -2685,21 +3016,46 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && blendmaskSH == other.blendmaskSH && radmaskSH == other.radmaskSH && blurSHde == other.blurSHde + && strSH == other.strSH + && angSH == other.angSH && inverssh == other.inverssh && chromaskSH == other.chromaskSH && gammaskSH == other.gammaskSH && slomaskSH == other.slomaskSH + && lapmaskSH == other.lapmaskSH + && detailSH == other.detailSH + && LmaskSHcurve == other.LmaskSHcurve + && fatamountSH == other.fatamountSH + && fatanchorSH == other.fatanchorSH + && gamSH == other.gamSH + && sloSH == other.sloSH // Vibrance && visivibrance == other.visivibrance && expvibrance == other.expvibrance && saturated == other.saturated && pastels == other.pastels + && warm == other.warm && psthreshold == other.psthreshold && protectskins == other.protectskins && avoidcolorshift == other.avoidcolorshift && pastsattog == other.pastsattog && sensiv == other.sensiv && skintonescurve == other.skintonescurve + && CCmaskvibcurve == other.CCmaskvibcurve + && LLmaskvibcurve == other.LLmaskvibcurve + && HHmaskvibcurve == other.HHmaskvibcurve + && enavibMask == other.enavibMask + && blendmaskvib == other.blendmaskvib + && radmaskvib == other.radmaskvib + && chromaskvib == other.chromaskvib + && gammaskvib == other.gammaskvib + && slomaskvib == other.slomaskvib + && lapmaskvib == other.lapmaskvib + && strvib == other.strvib + && strvibab == other.strvibab + && strvibh == other.strvibh + && angvib == other.angvib + && Lmaskvibcurve == other.Lmaskvibcurve // Soft Light && visisoft == other.visisoft && expsoft == other.expsoft @@ -2713,8 +3069,35 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && radius == other.radius && strength == other.strength && sensibn == other.sensibn + && itera == other.itera + && guidbl == other.guidbl + && strbl == other.strbl + && isogr == other.isogr + && strengr == other.strengr + && scalegr == other.scalegr + && epsbl == other.epsbl + && blMethod == other.blMethod + && chroMethod == other.chroMethod && blurMethod == other.blurMethod + && medMethod == other.medMethod && activlum == other.activlum + && CCmaskblcurve == other.CCmaskblcurve + && LLmaskblcurve == other.LLmaskblcurve + && HHmaskblcurve == other.HHmaskblcurve + && enablMask == other.enablMask + && fftwbl == other.fftwbl + && toolbl == other.toolbl + && blendmaskbl == other.blendmaskbl + && radmaskbl == other.radmaskbl + && chromaskbl == other.chromaskbl + && gammaskbl == other.gammaskbl + && slomaskbl == other.slomaskbl + && lapmaskbl == other.lapmaskbl + && shadmaskbl == other.shadmaskbl + && strumaskbl == other.strumaskbl + && Lmaskblcurve == other.Lmaskblcurve + && LLmaskblcurvewav == other.LLmaskblcurvewav + && csthresholdblur == other.csthresholdblur // Tone Mapping && visitonemap == other.visitonemap && exptonemap == other.exptonemap @@ -2732,11 +3115,14 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && LLmasktmcurve == other.LLmasktmcurve && HHmasktmcurve == other.HHmasktmcurve && enatmMask == other.enatmMask + && enatmMaskaft == other.enatmMaskaft && blendmasktm == other.blendmasktm && radmasktm == other.radmasktm && chromasktm == other.chromasktm && gammasktm == other.gammasktm && slomasktm == other.slomasktm + && lapmasktm == other.lapmasktm + && Lmasktmcurve == other.Lmasktmcurve // Retinex && visireti == other.visireti && expreti == other.expreti @@ -2745,11 +3131,16 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && chrrt == other.chrrt && neigh == other.neigh && vart == other.vart + && offs == other.offs && dehaz == other.dehaz + && depth == other.depth && sensih == other.sensih && localTgaincurve == other.localTgaincurve + && localTtranscurve == other.localTtranscurve && inversret == other.inversret && equilret == other.equilret + && loglin == other.loglin + && lumonly == other.lumonly && softradiusret == other.softradiusret && CCmaskreticurve == other.CCmaskreticurve && LLmaskreticurve == other.LLmaskreticurve @@ -2761,11 +3152,14 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && chromaskreti == other.chromaskreti && gammaskreti == other.gammaskreti && slomaskreti == other.slomaskreti + && lapmaskreti == other.lapmaskreti && scalereti == other.scalereti && darkness == other.darkness && lightnessreti == other.lightnessreti && limd == other.limd + && cliptm == other.cliptm && fftwreti == other.fftwreti + && Lmaskreticurve == other.Lmaskreticurve // Sharpening && visisharp == other.visisharp && expsharp == other.expsharp @@ -2786,10 +3180,60 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && lclightness == other.lclightness && levelwav == other.levelwav && residcont == other.residcont + && residblur == other.residblur + && levelblur == other.levelblur + && residchro == other.residchro + && residcomp == other.residcomp + && sigma == other.sigma + && offset == other.offset + && threswav == other.threswav + && chromalev == other.chromalev + && chromablu == other.chromablu + && fatdet == other.fatdet + && fatanch == other.fatanch + && fatres == other.fatres + && clarilres == other.clarilres + && claricres == other.claricres + && clarisoft == other.clarisoft + && strwav == other.strwav + && angwav == other.angwav + && strengthw == other.strengthw + && radiusw == other.radiusw + && detailw == other.detailw + && gradw == other.gradw + && tloww == other.tloww + && thigw == other.thigw + && edgw == other.edgw + && basew == other.basew && sensilc == other.sensilc && fftwlc == other.fftwlc + && blurlc == other.blurlc + && wavblur == other.wavblur + && wavedg == other.wavedg + && waveshow == other.waveshow + && wavcont == other.wavcont + && wavcomp == other.wavcomp + && wavgradl == other.wavgradl + && wavcompre == other.wavcompre + && origlc == other.origlc && localcontMethod == other.localcontMethod + && localedgMethod == other.localedgMethod + && localneiMethod == other.localneiMethod && locwavcurve == other.locwavcurve + && csthreshold == other.csthreshold + && loclevwavcurve == other.loclevwavcurve + && locconwavcurve == other.locconwavcurve + && loccompwavcurve == other.loccompwavcurve + && loccomprewavcurve == other.loccomprewavcurve + && locedgwavcurve == other.locedgwavcurve + && CCmasklccurve == other.CCmasklccurve + && LLmasklccurve == other.LLmasklccurve + && HHmasklccurve == other.HHmasklccurve + && enalcMask == other.enalcMask + && blendmasklc == other.blendmasklc + && radmasklc == other.radmasklc + && chromasklc == other.chromasklc + && Lmasklccurve == other.Lmasklccurve // Constrast by detail levels && visicbdl == other.visicbdl && expcbdl == other.expcbdl @@ -2819,6 +3263,8 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && chromaskcb == other.chromaskcb && gammaskcb == other.gammaskcb && slomaskcb == other.slomaskcb + && lapmaskcb == other.lapmaskcb + && Lmaskcbcurve == other.Lmaskcbcurve // Denoise && visidenoi == other.visidenoi && expdenoi == other.expdenoi @@ -2833,7 +3279,24 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && noisechrodetail == other.noisechrodetail && adjblur == other.adjblur && bilateral == other.bilateral - && sensiden == other.sensiden; + && sensiden == other.sensiden + && detailthr == other.detailthr + && locwavcurveden == other.locwavcurveden + // Log encoding + && visilog == other.visilog + && explog == other.explog + && autocompute == other.autocompute + && sourceGray == other.sourceGray + && targetGray == other.targetGray + && Autogray == other.Autogray + && fullimage == other.fullimage + && blackEv == other.blackEv + && whiteEv == other.whiteEv + && detail == other.detail + && sensilog == other.sensilog + && baselog == other.baselog + && strlog == other.strlog + && anglog == other.anglog; } bool LocallabParams::LocallabSpot::operator !=(const LocallabSpot& other) const @@ -2844,12 +3307,6 @@ bool LocallabParams::LocallabSpot::operator !=(const LocallabSpot& other) const const double LocallabParams::LABGRIDL_CORR_MAX = 12800.; const double LocallabParams::LABGRIDL_CORR_SCALE = 3.276; const double LocallabParams::LABGRIDL_DIRECT_SCALE = 41950.; -const std::vector LocallabParams::DEF_MASK_CURVE = {(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}; -const std::vector LocallabParams::DEF_COLOR_LCURVE = {(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}; -const std::vector LocallabParams::DEF_COLOR_HCURVE = {(double)FCT_MinMaxCPoints, 0.0, 0.50, 0.35, 0.35, 0.166, 0.50, 0.35, 0.35, 0.333, 0.50, 0.35, 0.35, 0.50, 0.50, 0.35, 0.35, 0.666, 0.50, 0.35, 0.35, 0.833, 0.50, 0.35, 0.35}; -const std::vector LocallabParams::DEF_EXP_CURVE = {(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}; -const std::vector LocallabParams::DEF_RET_CURVE = {(double)FCT_MinMaxCPoints, 0.0, 0.12, 0.35, 0.35, 0.70, 0.50, 0.35, 0.35, 1.00, 0.12, 0.35, 0.35}; -const std::vector LocallabParams::DEF_LC_CURVE = {(double)FCT_MinMaxCPoints, 0.0, 0.5, 0.35, 0.35, 1., 0.5, 0.35, 0.35}; LocallabParams::LocallabParams() : enabled(false), @@ -2986,7 +3443,8 @@ DehazeParams::DehazeParams() : enabled(false), strength(50), showDepthMap(false), - depth(25) + depth(25), + luminance(false) { } @@ -2996,7 +3454,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 @@ -3132,6 +3591,7 @@ const std::vector& RAWParams::BayerSensor::getPSDemosaicMethodStrin static const std::vector method_strings { "amaze", "amazevng4", + "rcdvng4", "lmmse" }; return method_strings; @@ -3326,6 +3786,8 @@ void ProcParams::setDefaults() prsharpening.deconviter = 100; prsharpening.deconvdamping = 0; + pdsharpening = {}; + vibrance = {}; wb = {}; @@ -3705,6 +4167,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); @@ -3778,6 +4241,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->coarse.vflip, "Coarse Transformation", "VerticalFlip", coarse.vflip, keyFile); // Common properties for transformations + saveToKeyfile(!pedited || pedited->commonTrans.method, "Common Properties for Transformations", "Method", commonTrans.method, keyFile); saveToKeyfile(!pedited || pedited->commonTrans.autofill, "Common Properties for Transformations", "AutoFill", commonTrans.autofill, keyFile); // Rotation @@ -3820,6 +4284,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).isvisible, "Locallab", "Isvisible_" + std::to_string(i), spot.isvisible, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).shape, "Locallab", "Shape_" + std::to_string(i), spot.shape, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).spotMethod, "Locallab", "SpotMethod_" + std::to_string(i), spot.spotMethod, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).wavMethod, "Locallab", "WavMethod_" + std::to_string(i), spot.wavMethod, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sensiexclu, "Locallab", "SensiExclu_" + std::to_string(i), spot.sensiexclu, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).structexclu, "Locallab", "StructExclu_" + std::to_string(i), spot.structexclu, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).struc, "Locallab", "Struc_" + std::to_string(i), spot.struc, keyFile); @@ -3832,13 +4297,24 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).centerY, "Locallab", "CenterY_" + std::to_string(i), spot.centerY, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).circrad, "Locallab", "Circrad_" + std::to_string(i), spot.circrad, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).qualityMethod, "Locallab", "QualityMethod_" + std::to_string(i), spot.qualityMethod, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).complexMethod, "Locallab", "ComplexMethod_" + std::to_string(i), spot.complexMethod, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).transit, "Locallab", "Transit_" + std::to_string(i), spot.transit, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).feather, "Locallab", "Feather_" + std::to_string(i), spot.feather, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).thresh, "Locallab", "Thresh_" + std::to_string(i), spot.thresh, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).iter, "Locallab", "Iter_" + std::to_string(i), spot.iter, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).balan, "Locallab", "Balan_" + std::to_string(i), spot.balan, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).balanh, "Locallab", "Balanh_" + std::to_string(i), spot.balanh, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).colorde, "Locallab", "Colorde_" + std::to_string(i), spot.colorde, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).transitweak, "Locallab", "Transitweak_" + std::to_string(i), spot.transitweak, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).transitgrad, "Locallab", "Transitgrad_" + std::to_string(i), spot.transitgrad, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).avoid, "Locallab", "Avoid_" + std::to_string(i), spot.avoid, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).recurs, "Locallab", "Recurs_" + std::to_string(i), spot.recurs, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).laplac, "Locallab", "Laplac_" + std::to_string(i), spot.laplac, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).deltae, "Locallab", "Deltae_" + std::to_string(i), spot.deltae, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).shortc, "Locallab", "Shortc_" + std::to_string(i), spot.shortc, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).savrest, "Locallab", "Savrest_" + std::to_string(i), spot.savrest, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).scopemask, "Locallab", "Scopemask_" + std::to_string(i), spot.scopemask, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lumask, "Locallab", "Lumask_" + std::to_string(i), spot.lumask, keyFile); // Color & Light if ((!pedited || pedited->locallab.spots.at(i).visicolor) && spot.visicolor) { saveToKeyfile(!pedited || pedited->locallab.spots.at(i).expcolor, "Locallab", "Expcolor_" + std::to_string(i), spot.expcolor, keyFile); @@ -3850,27 +4326,56 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).labgridBLow, "Locallab", "labgridBLow_" + std::to_string(i), spot.labgridBLow, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).labgridAHigh, "Locallab", "labgridAHigh_" + std::to_string(i), spot.labgridAHigh, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).labgridBHigh, "Locallab", "labgridBHigh_" + std::to_string(i), spot.labgridBHigh, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).labgridALowmerg, "Locallab", "labgridALowmerg_" + std::to_string(i), spot.labgridALowmerg, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).labgridBLowmerg, "Locallab", "labgridBLowmerg_" + std::to_string(i), spot.labgridBLowmerg, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).labgridAHighmerg, "Locallab", "labgridAHighmerg_" + std::to_string(i), spot.labgridAHighmerg, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).labgridBHighmerg, "Locallab", "labgridBHighmerg_" + std::to_string(i), spot.labgridBHighmerg, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strengthgrid, "Locallab", "Strengthgrid_" + std::to_string(i), spot.strengthgrid, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sensi, "Locallab", "Sensi_" + std::to_string(i), spot.sensi, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).structcol, "Locallab", "Structcol_" + std::to_string(i), spot.structcol, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strcol, "Locallab", "Strcol_" + std::to_string(i), spot.strcol, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strcolab, "Locallab", "Strcolab_" + std::to_string(i), spot.strcolab, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strcolh, "Locallab", "Strcolh_" + std::to_string(i), spot.strcolh, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).angcol, "Locallab", "Angcol_" + std::to_string(i), spot.angcol, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blurcolde, "Locallab", "Blurcolde_" + std::to_string(i), spot.blurcolde, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).contcol, "Locallab", "Contcol_" + std::to_string(i), spot.contcol, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blendmaskcol, "Locallab", "Blendmaskcol_" + std::to_string(i), spot.blendmaskcol, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).radmaskcol, "Locallab", "Radmaskcol_" + std::to_string(i), spot.radmaskcol, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chromaskcol, "Locallab", "Chromaskcol_" + std::to_string(i), spot.chromaskcol, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).gammaskcol, "Locallab", "Gammaskcol_" + std::to_string(i), spot.gammaskcol, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).slomaskcol, "Locallab", "Slomaskcol_" + std::to_string(i), spot.slomaskcol, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).shadmaskcol, "Locallab", "shadmaskcol_" + std::to_string(i), spot.shadmaskcol, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strumaskcol, "Locallab", "strumaskcol_" + std::to_string(i), spot.strumaskcol, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lapmaskcol, "Locallab", "Lapmaskcol_" + std::to_string(i), spot.lapmaskcol, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).qualitycurveMethod, "Locallab", "QualityCurveMethod_" + std::to_string(i), spot.qualitycurveMethod, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).gridMethod, "Locallab", "gridMethod_" + std::to_string(i), spot.gridMethod, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).merMethod, "Locallab", "Merg_Method_" + std::to_string(i), spot.merMethod, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).toneMethod, "Locallab", "ToneMethod_" + std::to_string(i), spot.toneMethod, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).mergecolMethod, "Locallab", "mergecolMethod_" + std::to_string(i), spot.mergecolMethod, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).llcurve, "Locallab", "LLCurve_" + std::to_string(i), spot.llcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lccurve, "Locallab", "LCCurve_" + std::to_string(i), spot.lccurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).cccurve, "Locallab", "CCCurve_" + std::to_string(i), spot.cccurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).clcurve, "Locallab", "CLCurve_" + std::to_string(i), spot.clcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).rgbcurve, "Locallab", "RGBCurve_" + std::to_string(i), spot.rgbcurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).LHcurve, "Locallab", "LHCurve_" + std::to_string(i), spot.LHcurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).HHcurve, "Locallab", "HHCurve_" + std::to_string(i), spot.HHcurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).invers, "Locallab", "Invers_" + std::to_string(i), spot.invers, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).special, "Locallab", "Special_" + std::to_string(i), spot.special, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).toolcol, "Locallab", "Toolcol_" + std::to_string(i), spot.toolcol, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).enaColorMask, "Locallab", "EnaColorMask_" + std::to_string(i), spot.enaColorMask, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fftColorMask, "Locallab", "FftColorMask_" + std::to_string(i), spot.fftColorMask, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).CCmaskcurve, "Locallab", "CCmaskCurve_" + std::to_string(i), spot.CCmaskcurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).LLmaskcurve, "Locallab", "LLmaskCurve_" + std::to_string(i), spot.LLmaskcurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).HHmaskcurve, "Locallab", "HHmaskCurve_" + std::to_string(i), spot.HHmaskcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).HHhmaskcurve, "Locallab", "HHhmaskCurve_" + std::to_string(i), spot.HHhmaskcurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).softradiuscol, "Locallab", "Softradiuscol_" + std::to_string(i), spot.softradiuscol, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).opacol, "Locallab", "Opacol_" + std::to_string(i), spot.opacol, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).mercol, "Locallab", "Mercol_" + std::to_string(i), spot.mercol, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).merlucol, "Locallab", "Merlucol_" + std::to_string(i), spot.merlucol, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).conthrcol, "Locallab", "Conthrcol_" + std::to_string(i), spot.conthrcol, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).Lmaskcurve, "Locallab", "LmaskCurve_" + std::to_string(i), spot.Lmaskcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).LLmaskcolcurvewav, "Locallab", "LLmaskcolCurvewav_" + std::to_string(i), spot.LLmaskcolcurvewav, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).csthresholdcol, "Locallab", "CSThresholdcol_" + std::to_string(i), spot.csthresholdcol.toVector(), keyFile); } // Exposure if ((!pedited || pedited->locallab.spots.at(i).visiexpose) && spot.visiexpose) { @@ -3882,13 +4387,15 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).shadex, "Locallab", "Shadex_" + std::to_string(i), spot.shadex, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).shcompr, "Locallab", "Shcompr_" + std::to_string(i), spot.shcompr, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).expchroma, "Locallab", "Expchroma_" + std::to_string(i), spot.expchroma, keyFile); - saveToKeyfile(!pedited || pedited->locallab.spots.at(i).warm, "Locallab", "Warm_" + std::to_string(i), spot.warm, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sensiex, "Locallab", "Sensiex_" + std::to_string(i), spot.sensiex, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).structexp, "Locallab", "Structexp_" + std::to_string(i), spot.structexp, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blurexpde, "Locallab", "Blurexpde_" + std::to_string(i), spot.blurexpde, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strexp, "Locallab", "Strexp_" + std::to_string(i), spot.strexp, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).angexp, "Locallab", "Angexp_" + std::to_string(i), spot.angexp, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).excurve, "Locallab", "ExCurve_" + std::to_string(i), spot.excurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).inversex, "Locallab", "Inversex_" + std::to_string(i), spot.inversex, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).enaExpMask, "Locallab", "EnaExpMask_" + std::to_string(i), spot.enaExpMask, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).enaExpMaskaft, "Locallab", "EnaExpMaskaft_" + std::to_string(i), spot.enaExpMaskaft, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).CCmaskexpcurve, "Locallab", "CCmaskexpCurve_" + std::to_string(i), spot.CCmaskexpcurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).LLmaskexpcurve, "Locallab", "LLmaskexpCurve_" + std::to_string(i), spot.LLmaskexpcurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).HHmaskexpcurve, "Locallab", "HHmaskexpCurve_" + std::to_string(i), spot.HHmaskexpcurve, keyFile); @@ -3897,15 +4404,31 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chromaskexp, "Locallab", "Chromaskexp_" + std::to_string(i), spot.chromaskexp, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).gammaskexp, "Locallab", "Gammaskexp_" + std::to_string(i), spot.gammaskexp, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).slomaskexp, "Locallab", "Slomaskexp_" + std::to_string(i), spot.slomaskexp, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lapmaskexp, "Locallab", "Lapmaskexp_" + std::to_string(i), spot.lapmaskexp, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strmaskexp, "Locallab", "Strmaskexp_" + std::to_string(i), spot.strmaskexp, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).angmaskexp, "Locallab", "Angmaskexp_" + std::to_string(i), spot.angmaskexp, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).softradiusexp, "Locallab", "Softradiusexp_" + std::to_string(i), spot.softradiusexp, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).Lmaskexpcurve, "Locallab", "LmaskexpCurve_" + std::to_string(i), spot.Lmaskexpcurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).expMethod, "Locallab", "ExpMethod_" + std::to_string(i), spot.expMethod, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).exnoiseMethod, "Locallab", "ExnoiseMethod_" + std::to_string(i), spot.exnoiseMethod, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).laplacexp, "Locallab", "Laplacexp_" + std::to_string(i), spot.laplacexp, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).balanexp, "Locallab", "Balanexp_" + std::to_string(i), spot.balanexp, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).linear, "Locallab", "Linearexp_" + std::to_string(i), spot.linear, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).gamm, "Locallab", "Gamm_" + std::to_string(i), spot.gamm, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fatamount, "Locallab", "Fatamount_" + std::to_string(i), spot.fatamount, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fatdetail, "Locallab", "Fatdetail_" + std::to_string(i), spot.fatdetail, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fatanchor, "Locallab", "Fatanchor_" + std::to_string(i), spot.fatanchor, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fatlevel, "Locallab", "Fatlevel_" + std::to_string(i), spot.fatlevel, keyFile); } // Shadow highlight if ((!pedited || pedited->locallab.spots.at(i).visishadhigh) && spot.visishadhigh) { saveToKeyfile(!pedited || pedited->locallab.spots.at(i).expshadhigh, "Locallab", "Expshadhigh_" + std::to_string(i), spot.expshadhigh, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).shMethod, "Locallab", "ShMethod_" + std::to_string(i), spot.shMethod, keyFile); + + for (int j = 0; j < 5; j++) { + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).multsh[j], "Locallab", "Multsh" + std::to_string(j) + "_" + std::to_string(i), spot.multsh[j], keyFile); + } + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).highlights, "Locallab", "highlights_" + std::to_string(i), spot.highlights, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).h_tonalwidth, "Locallab", "h_tonalwidth_" + std::to_string(i), spot.h_tonalwidth, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).shadows, "Locallab", "shadows_" + std::to_string(i), spot.shadows, keyFile); @@ -3919,22 +4442,46 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blendmaskSH, "Locallab", "BlendmaskSH_" + std::to_string(i), spot.blendmaskSH, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).radmaskSH, "Locallab", "RadmaskSH_" + std::to_string(i), spot.radmaskSH, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blurSHde, "Locallab", "BlurSHde_" + std::to_string(i), spot.blurSHde, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strSH, "Locallab", "StrSH_" + std::to_string(i), spot.strSH, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).angSH, "Locallab", "AngSH_" + std::to_string(i), spot.angSH, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).inverssh, "Locallab", "Inverssh_" + std::to_string(i), spot.inverssh, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chromaskSH, "Locallab", "ChromaskSH_" + std::to_string(i), spot.chromaskSH, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).gammaskSH, "Locallab", "GammaskSH_" + std::to_string(i), spot.gammaskSH, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).slomaskSH, "Locallab", "SlomaskSH_" + std::to_string(i), spot.slomaskSH, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).detailSH, "Locallab", "DetailSH_" + std::to_string(i), spot.detailSH, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).LmaskSHcurve, "Locallab", "LmaskSHCurve_" + std::to_string(i), spot.LmaskSHcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fatamountSH, "Locallab", "FatamountSH_" + std::to_string(i), spot.fatamountSH, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fatanchorSH, "Locallab", "FatanchorSH_" + std::to_string(i), spot.fatanchorSH, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).gamSH, "Locallab", "GamSH_" + std::to_string(i), spot.gamSH, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sloSH, "Locallab", "SloSH_" + std::to_string(i), spot.sloSH, keyFile); } // Vibrance if ((!pedited || pedited->locallab.spots.at(i).visivibrance) && spot.visivibrance) { saveToKeyfile(!pedited || pedited->locallab.spots.at(i).expvibrance, "Locallab", "Expvibrance_" + std::to_string(i), spot.expvibrance, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).saturated, "Locallab", "Saturated_" + std::to_string(i), spot.saturated, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).pastels, "Locallab", "Pastels_" + std::to_string(i), spot.pastels, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).warm, "Locallab", "Warm_" + std::to_string(i), spot.warm, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).psthreshold, "Locallab", "PSThreshold_" + std::to_string(i), spot.psthreshold.toVector(), keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).protectskins, "Locallab", "ProtectSkins_" + std::to_string(i), spot.protectskins, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).avoidcolorshift, "Locallab", "AvoidColorShift_" + std::to_string(i), spot.avoidcolorshift, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).pastsattog, "Locallab", "PastSatTog_" + std::to_string(i), spot.pastsattog, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sensiv, "Locallab", "Sensiv_" + std::to_string(i), spot.sensiv, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).skintonescurve, "Locallab", "SkinTonesCurve_" + std::to_string(i), spot.skintonescurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).CCmaskvibcurve, "Locallab", "CCmaskvibCurve_" + std::to_string(i), spot.CCmaskvibcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).LLmaskvibcurve, "Locallab", "LLmaskvibCurve_" + std::to_string(i), spot.LLmaskvibcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).HHmaskvibcurve, "Locallab", "HHmaskvibCurve_" + std::to_string(i), spot.HHmaskvibcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).enavibMask, "Locallab", "EnavibMask_" + std::to_string(i), spot.enavibMask, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blendmaskvib, "Locallab", "Blendmaskvib_" + std::to_string(i), spot.blendmaskvib, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).radmaskvib, "Locallab", "Radmaskvib_" + std::to_string(i), spot.radmaskvib, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chromaskvib, "Locallab", "Chromaskvib_" + std::to_string(i), spot.chromaskvib, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).gammaskvib, "Locallab", "Gammaskvib_" + std::to_string(i), spot.gammaskvib, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).slomaskvib, "Locallab", "Slomaskvib_" + std::to_string(i), spot.slomaskvib, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lapmaskvib, "Locallab", "Lapmaskvib_" + std::to_string(i), spot.lapmaskvib, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strvib, "Locallab", "Strvib_" + std::to_string(i), spot.strvib, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strvibab, "Locallab", "Strvibab_" + std::to_string(i), spot.strvibab, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strvibh, "Locallab", "Strvibh_" + std::to_string(i), spot.strvibh, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).angvib, "Locallab", "Angvib_" + std::to_string(i), spot.angvib, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).Lmaskvibcurve, "Locallab", "LmaskvibCurve_" + std::to_string(i), spot.Lmaskvibcurve, keyFile); } // Soft Light if ((!pedited || pedited->locallab.spots.at(i).visisoft) && spot.visisoft) { @@ -3950,8 +4497,35 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).radius, "Locallab", "Radius_" + std::to_string(i), spot.radius, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strength, "Locallab", "Strength_" + std::to_string(i), spot.strength, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sensibn, "Locallab", "Sensibn_" + std::to_string(i), spot.sensibn, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).itera, "Locallab", "Iteramed_" + std::to_string(i), spot.itera, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).guidbl, "Locallab", "Guidbl_" + std::to_string(i), spot.guidbl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strbl, "Locallab", "Strbl_" + std::to_string(i), spot.strbl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).isogr, "Locallab", "Isogr_" + std::to_string(i), spot.isogr, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strengr, "Locallab", "Strengr_" + std::to_string(i), spot.strengr, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).scalegr, "Locallab", "Scalegr_" + std::to_string(i), spot.scalegr, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).epsbl, "Locallab", "Epsbl_" + std::to_string(i), spot.epsbl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blMethod, "Locallab", "BlMethod_" + std::to_string(i), spot.blMethod, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chroMethod, "Locallab", "ChroMethod_" + std::to_string(i), spot.chroMethod, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blurMethod, "Locallab", "BlurMethod_" + std::to_string(i), spot.blurMethod, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).medMethod, "Locallab", "MedMethod_" + std::to_string(i), spot.medMethod, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).activlum, "Locallab", "activlum_" + std::to_string(i), spot.activlum, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).CCmaskblcurve, "Locallab", "CCmaskblCurve_" + std::to_string(i), spot.CCmaskblcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).LLmaskblcurve, "Locallab", "LLmaskblCurve_" + std::to_string(i), spot.LLmaskblcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).HHmaskblcurve, "Locallab", "HHmaskblCurve_" + std::to_string(i), spot.HHmaskblcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).enablMask, "Locallab", "EnablMask_" + std::to_string(i), spot.enablMask, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fftwbl, "Locallab", "Fftwbl_" + std::to_string(i), spot.fftwbl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).toolbl, "Locallab", "Toolbl_" + std::to_string(i), spot.toolbl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blendmaskbl, "Locallab", "Blendmaskbl_" + std::to_string(i), spot.blendmaskbl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).radmaskbl, "Locallab", "Radmaskbl_" + std::to_string(i), spot.radmaskbl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chromaskbl, "Locallab", "Chromaskbl_" + std::to_string(i), spot.chromaskbl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).gammaskbl, "Locallab", "Gammaskbl_" + std::to_string(i), spot.gammaskbl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).slomaskbl, "Locallab", "Slomaskbl_" + std::to_string(i), spot.slomaskbl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lapmaskbl, "Locallab", "Lapmaskbl_" + std::to_string(i), spot.lapmaskbl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).shadmaskbl, "Locallab", "shadmaskbl_" + std::to_string(i), spot.shadmaskbl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strumaskbl, "Locallab", "strumaskbl_" + std::to_string(i), spot.strumaskbl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).Lmaskblcurve, "Locallab", "LmaskblCurve_" + std::to_string(i), spot.Lmaskblcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).LLmaskblcurvewav, "Locallab", "LLmaskblCurvewav_" + std::to_string(i), spot.LLmaskblcurvewav, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).csthresholdblur, "Locallab", "CSThresholdblur_" + std::to_string(i), spot.csthresholdblur.toVector(), keyFile); } // Tone Mapping if ((!pedited || pedited->locallab.spots.at(i).visitonemap) && spot.visitonemap) { @@ -3970,11 +4544,14 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).LLmasktmcurve, "Locallab", "LLmasktmCurve_" + std::to_string(i), spot.LLmasktmcurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).HHmasktmcurve, "Locallab", "HHmasktmCurve_" + std::to_string(i), spot.HHmasktmcurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).enatmMask, "Locallab", "EnatmMask_" + std::to_string(i), spot.enatmMask, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).enatmMaskaft, "Locallab", "EnatmMaskaft_" + std::to_string(i), spot.enatmMaskaft, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blendmasktm, "Locallab", "Blendmasktm_" + std::to_string(i), spot.blendmasktm, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).radmasktm, "Locallab", "Radmasktm_" + std::to_string(i), spot.radmasktm, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chromasktm, "Locallab", "Chromasktm_" + std::to_string(i), spot.chromasktm, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).gammasktm, "Locallab", "Gammasktm_" + std::to_string(i), spot.gammasktm, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).slomasktm, "Locallab", "Slomasktm_" + std::to_string(i), spot.slomasktm, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lapmasktm, "Locallab", "Lapmasktm_" + std::to_string(i), spot.lapmasktm, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).Lmasktmcurve, "Locallab", "LmasktmCurve_" + std::to_string(i), spot.Lmasktmcurve, keyFile); } // Retinex if ((!pedited || pedited->locallab.spots.at(i).visireti) && spot.visireti) { @@ -3984,11 +4561,16 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chrrt, "Locallab", "Chrrt_" + std::to_string(i), spot.chrrt, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).neigh, "Locallab", "Neigh_" + std::to_string(i), spot.neigh, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).vart, "Locallab", "Vart_" + std::to_string(i), spot.vart, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).offs, "Locallab", "Offs_" + std::to_string(i), spot.offs, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).dehaz, "Locallab", "Dehaz_" + std::to_string(i), spot.dehaz, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).depth, "Locallab", "Depth_" + std::to_string(i), spot.depth, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sensih, "Locallab", "Sensih_" + std::to_string(i), spot.sensih, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).localTgaincurve, "Locallab", "TgainCurve_" + std::to_string(i), spot.localTgaincurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).localTtranscurve, "Locallab", "TtransCurve_" + std::to_string(i), spot.localTtranscurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).inversret, "Locallab", "Inversret_" + std::to_string(i), spot.inversret, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).equilret, "Locallab", "Equilret_" + std::to_string(i), spot.equilret, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).loglin, "Locallab", "Loglin_" + std::to_string(i), spot.loglin, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lumonly, "Locallab", "Lumonly_" + std::to_string(i), spot.lumonly, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).softradiusret, "Locallab", "Softradiusret_" + std::to_string(i), spot.softradiusret, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).CCmaskreticurve, "Locallab", "CCmaskretiCurve_" + std::to_string(i), spot.CCmaskreticurve, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).LLmaskreticurve, "Locallab", "LLmaskretiCurve_" + std::to_string(i), spot.LLmaskreticurve, keyFile); @@ -4000,11 +4582,14 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chromaskreti, "Locallab", "Chromaskreti_" + std::to_string(i), spot.chromaskreti, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).gammaskreti, "Locallab", "Gammaskreti_" + std::to_string(i), spot.gammaskreti, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).slomaskreti, "Locallab", "Slomaskreti_" + std::to_string(i), spot.slomaskreti, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lapmaskreti, "Locallab", "Lapmaskreti_" + std::to_string(i), spot.lapmaskreti, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).scalereti, "Locallab", "Scalereti_" + std::to_string(i), spot.scalereti, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).darkness, "Locallab", "Darkness_" + std::to_string(i), spot.darkness, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lightnessreti, "Locallab", "Lightnessreti_" + std::to_string(i), spot.lightnessreti, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).limd, "Locallab", "Limd_" + std::to_string(i), spot.limd, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).cliptm, "Locallab", "Cliptm_" + std::to_string(i), spot.cliptm, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fftwreti, "Locallab", "Fftwreti_" + std::to_string(i), spot.fftwreti, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).Lmaskreticurve, "Locallab", "LmaskretiCurve_" + std::to_string(i), spot.Lmaskreticurve, keyFile); } // Sharpening if ((!pedited || pedited->locallab.spots.at(i).visisharp) && spot.visisharp) { @@ -4027,10 +4612,60 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lclightness, "Locallab", "Lclightness_" + std::to_string(i), spot.lclightness, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).levelwav, "Locallab", "Levelwav_" + std::to_string(i), spot.levelwav, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).residcont, "Locallab", "Residcont_" + std::to_string(i), spot.residcont, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).residblur, "Locallab", "Residblur_" + std::to_string(i), spot.residblur, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).levelblur, "Locallab", "Levelblur_" + std::to_string(i), spot.levelblur, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).residchro, "Locallab", "Residchro_" + std::to_string(i), spot.residchro, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).residcomp, "Locallab", "Residcomp_" + std::to_string(i), spot.residcomp, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sigma, "Locallab", "Sigma_" + std::to_string(i), spot.sigma, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).offset, "Locallab", "Offset_" + std::to_string(i), spot.offset, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).threswav, "Locallab", "Threswav_" + std::to_string(i), spot.threswav, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chromalev, "Locallab", "Chromalev_" + std::to_string(i), spot.chromalev, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chromablu, "Locallab", "Chromablu_" + std::to_string(i), spot.chromablu, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fatdet, "Locallab", "Fatdet_" + std::to_string(i), spot.fatdet, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fatanch, "Locallab", "Fatanch_" + std::to_string(i), spot.fatanch, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fatres, "Locallab", "Fatres_" + std::to_string(i), spot.fatres, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).clarilres, "Locallab", "ClariLres_" + std::to_string(i), spot.clarilres, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).claricres, "Locallab", "ClariCres_" + std::to_string(i), spot.claricres, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).clarisoft, "Locallab", "Clarisoft_" + std::to_string(i), spot.clarisoft, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strwav, "Locallab", "Strwav_" + std::to_string(i), spot.strwav, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).angwav, "Locallab", "Angwav_" + std::to_string(i), spot.angwav, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strengthw, "Locallab", "Strengthw_" + std::to_string(i), spot.strengthw, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).radiusw, "Locallab", "Radiusw_" + std::to_string(i), spot.radiusw, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).detailw, "Locallab", "Detailw_" + std::to_string(i), spot.detailw, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).gradw, "Locallab", "Gradw_" + std::to_string(i), spot.gradw, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).tloww, "Locallab", "Tloww_" + std::to_string(i), spot.tloww, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).thigw, "Locallab", "Thigw_" + std::to_string(i), spot.thigw, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).edgw, "Locallab", "Edgw_" + std::to_string(i), spot.edgw, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).basew, "Locallab", "Basew_" + std::to_string(i), spot.basew, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sensilc, "Locallab", "Sensilc_" + std::to_string(i), spot.sensilc, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fftwlc, "Locallab", "Fftwlc_" + std::to_string(i), spot.fftwlc, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blurlc, "Locallab", "Blurlc_" + std::to_string(i), spot.blurlc, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).wavblur, "Locallab", "Wavblur_" + std::to_string(i), spot.wavblur, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).wavedg, "Locallab", "Wavedg_" + std::to_string(i), spot.wavedg, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).waveshow, "Locallab", "Waveshow_" + std::to_string(i), spot.waveshow, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).wavcont, "Locallab", "Wavcont_" + std::to_string(i), spot.wavcont, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).wavcomp, "Locallab", "Wavcomp_" + std::to_string(i), spot.wavcomp, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).wavgradl, "Locallab", "Wavgradl_" + std::to_string(i), spot.wavgradl, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).wavcompre, "Locallab", "Wavcompre_" + std::to_string(i), spot.wavcompre, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).origlc, "Locallab", "Origlc_" + std::to_string(i), spot.origlc, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).localcontMethod, "Locallab", "localcontMethod_" + std::to_string(i), spot.localcontMethod, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).localedgMethod, "Locallab", "localedgMethod_" + std::to_string(i), spot.localedgMethod, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).localneiMethod, "Locallab", "localneiMethod_" + std::to_string(i), spot.localneiMethod, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).locwavcurve, "Locallab", "LocwavCurve_" + std::to_string(i), spot.locwavcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).csthreshold, "Locallab", "CSThreshold_" + std::to_string(i), spot.csthreshold.toVector(), keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).loclevwavcurve, "Locallab", "LoclevwavCurve_" + std::to_string(i), spot.loclevwavcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).locconwavcurve, "Locallab", "LocconwavCurve_" + std::to_string(i), spot.locconwavcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).loccompwavcurve, "Locallab", "LoccompwavCurve_" + std::to_string(i), spot.loccompwavcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).loccomprewavcurve, "Locallab", "LoccomprewavCurve_" + std::to_string(i), spot.loccomprewavcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).locedgwavcurve, "Locallab", "LocedgwavCurve_" + std::to_string(i), spot.locedgwavcurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).CCmasklccurve, "Locallab", "CCmasklcCurve_" + std::to_string(i), spot.CCmasklccurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).LLmasklccurve, "Locallab", "LLmasklcCurve_" + std::to_string(i), spot.LLmasklccurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).HHmasklccurve, "Locallab", "HHmasklcCurve_" + std::to_string(i), spot.HHmasklccurve, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).enalcMask, "Locallab", "EnalcMask_" + std::to_string(i), spot.enalcMask, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blendmasklc, "Locallab", "Blendmasklc_" + std::to_string(i), spot.blendmasklc, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).radmasklc, "Locallab", "Radmasklc_" + std::to_string(i), spot.radmasklc, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chromasklc, "Locallab", "Chromasklc_" + std::to_string(i), spot.chromasklc, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).Lmasklccurve, "Locallab", "LmasklcCurve_" + std::to_string(i), spot.Lmasklccurve, keyFile); } // Contrast by detail levels if ((!pedited || pedited->locallab.spots.at(i).visicbdl) && spot.visicbdl) { @@ -4056,6 +4691,8 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).chromaskcb, "Locallab", "Chromaskcb_" + std::to_string(i), spot.chromaskcb, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).gammaskcb, "Locallab", "Gammaskcb_" + std::to_string(i), spot.gammaskcb, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).slomaskcb, "Locallab", "Slomaskcb_" + std::to_string(i), spot.slomaskcb, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).lapmaskcb, "Locallab", "Lapmaskcb_" + std::to_string(i), spot.lapmaskcb, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).Lmaskcbcurve, "Locallab", "LmaskcbCurve_" + std::to_string(i), spot.Lmaskcbcurve, keyFile); } // Denoise if ((!pedited || pedited->locallab.spots.at(i).visidenoi) && spot.visidenoi) { @@ -4072,6 +4709,24 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.spots.at(i).adjblur, "Locallab", "Adjblur_" + std::to_string(i), spot.adjblur, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).bilateral, "Locallab", "Bilateral_" + std::to_string(i), spot.bilateral, keyFile); saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sensiden, "Locallab", "Sensiden_" + std::to_string(i), spot.sensiden, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).detailthr, "Locallab", "Detailthr_" + std::to_string(i), spot.detailthr, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).locwavcurveden, "Locallab", "LocwavCurveden_" + std::to_string(i), spot.locwavcurveden, keyFile); + } + // Log encoding + if ((!pedited || pedited->locallab.spots.at(i).visilog) && spot.visilog) { + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).explog, "Locallab", "Explog_" + std::to_string(i), spot.explog, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).autocompute, "Locallab", "Autocompute_" + std::to_string(i), spot.autocompute, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sourceGray, "Locallab", "SourceGray_" + std::to_string(i), spot.sourceGray, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).targetGray, "Locallab", "TargetGray_" + std::to_string(i), spot.targetGray, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).Autogray, "Locallab", "Autogray_" + std::to_string(i), spot.Autogray, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).fullimage, "Locallab", "Fullimage_" + std::to_string(i), spot.fullimage, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).blackEv, "Locallab", "BlackEv_" + std::to_string(i), spot.blackEv, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).whiteEv, "Locallab", "WhiteEv_" + std::to_string(i), spot.whiteEv, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).detail, "Locallab", "Detail_" + std::to_string(i), spot.detail, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).sensilog, "Locallab", "Sensilog_" + std::to_string(i), spot.sensilog, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).baselog, "Locallab", "Baselog_" + std::to_string(i), spot.baselog, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).strlog, "Locallab", "Strlog_" + std::to_string(i), spot.strlog, keyFile); + saveToKeyfile(!pedited || pedited->locallab.spots.at(i).anglog, "Locallab", "Anglog_" + std::to_string(i), spot.anglog, keyFile); } } } @@ -4103,6 +4758,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.deconvradius, "PostDemosaicSharpening", "DeconvRadius", pdsharpening.deconvradius, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.deconvradiusOffset, "PostDemosaicSharpening", "DeconvRadiusOffset", pdsharpening.deconvradiusOffset, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.deconvitercheck, "PostDemosaicSharpening", "DeconvIterCheck", pdsharpening.deconvitercheck, 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); @@ -5075,6 +5740,11 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) } if (keyFile.has_group("Common Properties for Transformations")) { + if (keyFile.has_key("Common Properties for Transformations", "Method")) { + assignFromKeyfile(keyFile, "Common Properties for Transformations", "Method", pedited, commonTrans.method, pedited->commonTrans.method); + } else { + commonTrans.method = "lin"; + } assignFromKeyfile(keyFile, "Common Properties for Transformations", "AutoFill", pedited, commonTrans.autofill, pedited->commonTrans.autofill); } @@ -5165,10 +5835,11 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Isvisible_" + std::to_string(i), pedited, spot.isvisible, spotEdited.isvisible); assignFromKeyfile(keyFile, "Locallab", "Shape_" + std::to_string(i), pedited, spot.shape, spotEdited.shape); assignFromKeyfile(keyFile, "Locallab", "SpotMethod_" + std::to_string(i), pedited, spot.spotMethod, spotEdited.spotMethod); - assignFromKeyfile(keyFile, "Locallab", "ShapeMethod_" + std::to_string(i), pedited, spot.shapeMethod, spotEdited.shapeMethod); + assignFromKeyfile(keyFile, "Locallab", "wavMethod_" + std::to_string(i), pedited, spot.wavMethod, spotEdited.wavMethod); assignFromKeyfile(keyFile, "Locallab", "SensiExclu_" + std::to_string(i), pedited, spot.sensiexclu, spotEdited.sensiexclu); assignFromKeyfile(keyFile, "Locallab", "StructExclu_" + std::to_string(i), pedited, spot.structexclu, spotEdited.structexclu); assignFromKeyfile(keyFile, "Locallab", "Struc_" + std::to_string(i), pedited, spot.struc, spotEdited.struc); + assignFromKeyfile(keyFile, "Locallab", "ShapeMethod_" + std::to_string(i), pedited, spot.shapeMethod, spotEdited.shapeMethod); assignFromKeyfile(keyFile, "Locallab", "LocX_" + std::to_string(i), pedited, spot.locX, spotEdited.locX); assignFromKeyfile(keyFile, "Locallab", "LocXL_" + std::to_string(i), pedited, spot.locXL, spotEdited.locXL); assignFromKeyfile(keyFile, "Locallab", "LocY_" + std::to_string(i), pedited, spot.locY, spotEdited.locY); @@ -5177,13 +5848,24 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "CenterY_" + std::to_string(i), pedited, spot.centerY, spotEdited.centerY); assignFromKeyfile(keyFile, "Locallab", "Circrad_" + std::to_string(i), pedited, spot.circrad, spotEdited.circrad); assignFromKeyfile(keyFile, "Locallab", "QualityMethod_" + std::to_string(i), pedited, spot.qualityMethod, spotEdited.qualityMethod); + assignFromKeyfile(keyFile, "Locallab", "ComplexMethod_" + std::to_string(i), pedited, spot.complexMethod, spotEdited.complexMethod); assignFromKeyfile(keyFile, "Locallab", "Transit_" + std::to_string(i), pedited, spot.transit, spotEdited.transit); + assignFromKeyfile(keyFile, "Locallab", "Feather_" + std::to_string(i), pedited, spot.feather, spotEdited.feather); assignFromKeyfile(keyFile, "Locallab", "Thresh_" + std::to_string(i), pedited, spot.thresh, spotEdited.thresh); assignFromKeyfile(keyFile, "Locallab", "Iter_" + std::to_string(i), pedited, spot.iter, spotEdited.iter); assignFromKeyfile(keyFile, "Locallab", "Balan_" + std::to_string(i), pedited, spot.balan, spotEdited.balan); + assignFromKeyfile(keyFile, "Locallab", "Balanh_" + std::to_string(i), pedited, spot.balanh, spotEdited.balanh); + assignFromKeyfile(keyFile, "Locallab", "Colorde_" + std::to_string(i), pedited, spot.colorde, spotEdited.colorde); assignFromKeyfile(keyFile, "Locallab", "Transitweak_" + std::to_string(i), pedited, spot.transitweak, spotEdited.transitweak); assignFromKeyfile(keyFile, "Locallab", "Transitgrad_" + std::to_string(i), pedited, spot.transitgrad, spotEdited.transitgrad); assignFromKeyfile(keyFile, "Locallab", "Avoid_" + std::to_string(i), pedited, spot.avoid, spotEdited.avoid); + assignFromKeyfile(keyFile, "Locallab", "Recurs_" + std::to_string(i), pedited, spot.recurs, spotEdited.recurs); + assignFromKeyfile(keyFile, "Locallab", "Laplac_" + std::to_string(i), pedited, spot.laplac, spotEdited.laplac); + assignFromKeyfile(keyFile, "Locallab", "Deltae_" + std::to_string(i), pedited, spot.deltae, spotEdited.deltae); + assignFromKeyfile(keyFile, "Locallab", "Shortc_" + std::to_string(i), pedited, spot.shortc, spotEdited.shortc); + assignFromKeyfile(keyFile, "Locallab", "Savrest_" + std::to_string(i), pedited, spot.savrest, spotEdited.savrest); + assignFromKeyfile(keyFile, "Locallab", "Scopemask_" + std::to_string(i), pedited, spot.scopemask, spotEdited.scopemask); + assignFromKeyfile(keyFile, "Locallab", "Lumask_" + std::to_string(i), pedited, spot.lumask, spotEdited.lumask); // Color & Light spot.visicolor = assignFromKeyfile(keyFile, "Locallab", "Expcolor_" + std::to_string(i), pedited, spot.expcolor, spotEdited.expcolor); @@ -5199,27 +5881,67 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "labgridBLow_" + std::to_string(i), pedited, spot.labgridBLow, spotEdited.labgridBLow); assignFromKeyfile(keyFile, "Locallab", "labgridAHigh_" + std::to_string(i), pedited, spot.labgridAHigh, spotEdited.labgridAHigh); assignFromKeyfile(keyFile, "Locallab", "labgridBHigh_" + std::to_string(i), pedited, spot.labgridBHigh, spotEdited.labgridBHigh); + assignFromKeyfile(keyFile, "Locallab", "labgridALowmerg_" + std::to_string(i), pedited, spot.labgridALowmerg, spotEdited.labgridALowmerg); + assignFromKeyfile(keyFile, "Locallab", "labgridBLowmerg_" + std::to_string(i), pedited, spot.labgridBLowmerg, spotEdited.labgridBLowmerg); + assignFromKeyfile(keyFile, "Locallab", "labgridAHighmerg_" + std::to_string(i), pedited, spot.labgridAHighmerg, spotEdited.labgridAHighmerg); + assignFromKeyfile(keyFile, "Locallab", "labgridBHighmerg_" + std::to_string(i), pedited, spot.labgridBHighmerg, spotEdited.labgridBHighmerg); assignFromKeyfile(keyFile, "Locallab", "Strengthgrid_" + std::to_string(i), pedited, spot.strengthgrid, spotEdited.strengthgrid); assignFromKeyfile(keyFile, "Locallab", "Sensi_" + std::to_string(i), pedited, spot.sensi, spotEdited.sensi); assignFromKeyfile(keyFile, "Locallab", "Structcol_" + std::to_string(i), pedited, spot.structcol, spotEdited.structcol); + assignFromKeyfile(keyFile, "Locallab", "Strcol_" + std::to_string(i), pedited, spot.strcol, spotEdited.strcol); + assignFromKeyfile(keyFile, "Locallab", "Strcolab_" + std::to_string(i), pedited, spot.strcolab, spotEdited.strcolab); + assignFromKeyfile(keyFile, "Locallab", "Strcolh_" + std::to_string(i), pedited, spot.strcolh, spotEdited.strcolh); + assignFromKeyfile(keyFile, "Locallab", "Angcol_" + std::to_string(i), pedited, spot.angcol, spotEdited.angcol); assignFromKeyfile(keyFile, "Locallab", "Blurcolde_" + std::to_string(i), pedited, spot.blurcolde, spotEdited.blurcolde); + assignFromKeyfile(keyFile, "Locallab", "Blurcol_" + std::to_string(i), pedited, spot.blurcol, spotEdited.blurcol); + assignFromKeyfile(keyFile, "Locallab", "Contcol_" + std::to_string(i), pedited, spot.contcol, spotEdited.contcol); assignFromKeyfile(keyFile, "Locallab", "Blendmaskcol_" + std::to_string(i), pedited, spot.blendmaskcol, spotEdited.blendmaskcol); assignFromKeyfile(keyFile, "Locallab", "Radmaskcol_" + std::to_string(i), pedited, spot.radmaskcol, spotEdited.radmaskcol); assignFromKeyfile(keyFile, "Locallab", "Chromaskcol_" + std::to_string(i), pedited, spot.chromaskcol, spotEdited.chromaskcol); assignFromKeyfile(keyFile, "Locallab", "Gammaskcol_" + std::to_string(i), pedited, spot.gammaskcol, spotEdited.gammaskcol); assignFromKeyfile(keyFile, "Locallab", "Slomaskcol_" + std::to_string(i), pedited, spot.slomaskcol, spotEdited.slomaskcol); + assignFromKeyfile(keyFile, "Locallab", "shadmaskcol_" + std::to_string(i), pedited, spot.shadmaskcol, spotEdited.shadmaskcol); + assignFromKeyfile(keyFile, "Locallab", "strumaskcol_" + std::to_string(i), pedited, spot.strumaskcol, spotEdited.strumaskcol); + assignFromKeyfile(keyFile, "Locallab", "Lapmaskcol_" + std::to_string(i), pedited, spot.lapmaskcol, spotEdited.lapmaskcol); assignFromKeyfile(keyFile, "Locallab", "QualityCurveMethod_" + std::to_string(i), pedited, spot.qualitycurveMethod, spotEdited.qualitycurveMethod); assignFromKeyfile(keyFile, "Locallab", "gridMethod_" + std::to_string(i), pedited, spot.gridMethod, spotEdited.gridMethod); + assignFromKeyfile(keyFile, "Locallab", "Merg_Method_" + std::to_string(i), pedited, spot.merMethod, spotEdited.merMethod); + assignFromKeyfile(keyFile, "Locallab", "ToneMethod_" + std::to_string(i), pedited, spot.toneMethod, spotEdited.toneMethod); + assignFromKeyfile(keyFile, "Locallab", "mergecolMethod_" + std::to_string(i), pedited, spot.mergecolMethod, spotEdited.mergecolMethod); assignFromKeyfile(keyFile, "Locallab", "LLCurve_" + std::to_string(i), pedited, spot.llcurve, spotEdited.llcurve); + assignFromKeyfile(keyFile, "Locallab", "LCCurve_" + std::to_string(i), pedited, spot.lccurve, spotEdited.lccurve); assignFromKeyfile(keyFile, "Locallab", "CCCurve_" + std::to_string(i), pedited, spot.cccurve, spotEdited.cccurve); + assignFromKeyfile(keyFile, "Locallab", "CLCurve_" + std::to_string(i), pedited, spot.clcurve, spotEdited.clcurve); + assignFromKeyfile(keyFile, "Locallab", "RGBCurve_" + std::to_string(i), pedited, spot.rgbcurve, spotEdited.rgbcurve); assignFromKeyfile(keyFile, "Locallab", "LHCurve_" + std::to_string(i), pedited, spot.LHcurve, spotEdited.LHcurve); assignFromKeyfile(keyFile, "Locallab", "HHCurve_" + std::to_string(i), pedited, spot.HHcurve, spotEdited.HHcurve); assignFromKeyfile(keyFile, "Locallab", "Invers_" + std::to_string(i), pedited, spot.invers, spotEdited.invers); + assignFromKeyfile(keyFile, "Locallab", "Special_" + std::to_string(i), pedited, spot.special, spotEdited.special); + assignFromKeyfile(keyFile, "Locallab", "Toolcol_" + std::to_string(i), pedited, spot.toolcol, spotEdited.toolcol); assignFromKeyfile(keyFile, "Locallab", "EnaColorMask_" + std::to_string(i), pedited, spot.enaColorMask, spotEdited.enaColorMask); + assignFromKeyfile(keyFile, "Locallab", "FftColorMask_" + std::to_string(i), pedited, spot.fftColorMask, spotEdited.fftColorMask); assignFromKeyfile(keyFile, "Locallab", "CCmaskCurve_" + std::to_string(i), pedited, spot.CCmaskcurve, spotEdited.CCmaskcurve); assignFromKeyfile(keyFile, "Locallab", "LLmaskCurve_" + std::to_string(i), pedited, spot.LLmaskcurve, spotEdited.LLmaskcurve); assignFromKeyfile(keyFile, "Locallab", "HHmaskCurve_" + std::to_string(i), pedited, spot.HHmaskcurve, spotEdited.HHmaskcurve); + assignFromKeyfile(keyFile, "Locallab", "HHhmaskCurve_" + std::to_string(i), pedited, spot.HHhmaskcurve, spotEdited.HHhmaskcurve); assignFromKeyfile(keyFile, "Locallab", "Softradiuscol_" + std::to_string(i), pedited, spot.softradiuscol, spotEdited.softradiuscol); + assignFromKeyfile(keyFile, "Locallab", "Opacol_" + std::to_string(i), pedited, spot.opacol, spotEdited.opacol); + assignFromKeyfile(keyFile, "Locallab", "Mercol_" + std::to_string(i), pedited, spot.mercol, spotEdited.mercol); + assignFromKeyfile(keyFile, "Locallab", "Merlucol_" + std::to_string(i), pedited, spot.merlucol, spotEdited.merlucol); + assignFromKeyfile(keyFile, "Locallab", "Conthrcol_" + std::to_string(i), pedited, spot.conthrcol, spotEdited.conthrcol); + assignFromKeyfile(keyFile, "Locallab", "LmaskCurve_" + std::to_string(i), pedited, spot.Lmaskcurve, spotEdited.Lmaskcurve); + assignFromKeyfile(keyFile, "Locallab", "LLmaskcolCurvewav_" + std::to_string(i), pedited, spot.LLmaskcolcurvewav, spotEdited.LLmaskcolcurvewav); + + if (keyFile.has_key("Locallab", "CSThresholdcol_" + std::to_string(i))) { + const std::vector thresh = keyFile.get_integer_list("Locallab", "CSThresholdcol_" + std::to_string(i)); + + if (thresh.size() >= 4) { + spot.csthresholdcol.setValues(thresh[0], thresh[1], min(thresh[2], 10), min(thresh[3], 10)); + } + + spotEdited.csthresholdcol = true; + } + // Exposure spot.visiexpose = assignFromKeyfile(keyFile, "Locallab", "Expexpose_" + std::to_string(i), pedited, spot.expexpose, spotEdited.expexpose); @@ -5234,13 +5956,15 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Shadex_" + std::to_string(i), pedited, spot.shadex, spotEdited.shadex); assignFromKeyfile(keyFile, "Locallab", "Shcompr_" + std::to_string(i), pedited, spot.shcompr, spotEdited.shcompr); assignFromKeyfile(keyFile, "Locallab", "Expchroma_" + std::to_string(i), pedited, spot.expchroma, spotEdited.expchroma); - assignFromKeyfile(keyFile, "Locallab", "Warm_" + std::to_string(i), pedited, spot.warm, spotEdited.warm); assignFromKeyfile(keyFile, "Locallab", "Sensiex_" + std::to_string(i), pedited, spot.sensiex, spotEdited.sensiex); assignFromKeyfile(keyFile, "Locallab", "Structexp_" + std::to_string(i), pedited, spot.structexp, spotEdited.structexp); assignFromKeyfile(keyFile, "Locallab", "Blurexpde_" + std::to_string(i), pedited, spot.blurexpde, spotEdited.blurexpde); + assignFromKeyfile(keyFile, "Locallab", "Strexp_" + std::to_string(i), pedited, spot.strexp, spotEdited.strexp); + assignFromKeyfile(keyFile, "Locallab", "Angexp_" + std::to_string(i), pedited, spot.angexp, spotEdited.angexp); assignFromKeyfile(keyFile, "Locallab", "ExCurve_" + std::to_string(i), pedited, spot.excurve, spotEdited.excurve); assignFromKeyfile(keyFile, "Locallab", "Inversex_" + std::to_string(i), pedited, spot.inversex, spotEdited.inversex); assignFromKeyfile(keyFile, "Locallab", "EnaExpMask_" + std::to_string(i), pedited, spot.enaExpMask, spotEdited.enaExpMask); + assignFromKeyfile(keyFile, "Locallab", "EnaExpMaskaft_" + std::to_string(i), pedited, spot.enaExpMaskaft, spotEdited.enaExpMaskaft); assignFromKeyfile(keyFile, "Locallab", "CCmaskexpCurve_" + std::to_string(i), pedited, spot.CCmaskexpcurve, spotEdited.CCmaskexpcurve); assignFromKeyfile(keyFile, "Locallab", "LLmaskexpCurve_" + std::to_string(i), pedited, spot.LLmaskexpcurve, spotEdited.LLmaskexpcurve); assignFromKeyfile(keyFile, "Locallab", "HHmaskexpCurve_" + std::to_string(i), pedited, spot.HHmaskexpcurve, spotEdited.HHmaskexpcurve); @@ -5249,11 +5973,21 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Chromaskexp_" + std::to_string(i), pedited, spot.chromaskexp, spotEdited.chromaskexp); assignFromKeyfile(keyFile, "Locallab", "Gammaskexp_" + std::to_string(i), pedited, spot.gammaskexp, spotEdited.gammaskexp); assignFromKeyfile(keyFile, "Locallab", "Slomaskexp_" + std::to_string(i), pedited, spot.slomaskexp, spotEdited.slomaskexp); + assignFromKeyfile(keyFile, "Locallab", "Lapmaskexp_" + std::to_string(i), pedited, spot.lapmaskexp, spotEdited.lapmaskexp); + assignFromKeyfile(keyFile, "Locallab", "Strmaskexp_" + std::to_string(i), pedited, spot.strmaskexp, spotEdited.strmaskexp); + assignFromKeyfile(keyFile, "Locallab", "Angmaskexp_" + std::to_string(i), pedited, spot.angmaskexp, spotEdited.angmaskexp); assignFromKeyfile(keyFile, "Locallab", "Softradiusexp_" + std::to_string(i), pedited, spot.softradiusexp, spotEdited.softradiusexp); + assignFromKeyfile(keyFile, "Locallab", "LmaskexpCurve_" + std::to_string(i), pedited, spot.Lmaskexpcurve, spotEdited.Lmaskexpcurve); assignFromKeyfile(keyFile, "Locallab", "ExpMethod_" + std::to_string(i), pedited, spot.expMethod, spotEdited.expMethod); + assignFromKeyfile(keyFile, "Locallab", "ExnoiseMethod_" + std::to_string(i), pedited, spot.exnoiseMethod, spotEdited.exnoiseMethod); assignFromKeyfile(keyFile, "Locallab", "Laplacexp_" + std::to_string(i), pedited, spot.laplacexp, spotEdited.laplacexp); assignFromKeyfile(keyFile, "Locallab", "Balanexp_" + std::to_string(i), pedited, spot.balanexp, spotEdited.balanexp); assignFromKeyfile(keyFile, "Locallab", "Linearexp_" + std::to_string(i), pedited, spot.linear, spotEdited.linear); + assignFromKeyfile(keyFile, "Locallab", "Gamm_" + std::to_string(i), pedited, spot.gamm, spotEdited.gamm); + assignFromKeyfile(keyFile, "Locallab", "Fatamount_" + std::to_string(i), pedited, spot.fatamount, spotEdited.fatamount); + assignFromKeyfile(keyFile, "Locallab", "Fatdetail_" + std::to_string(i), pedited, spot.fatdetail, spotEdited.fatdetail); + assignFromKeyfile(keyFile, "Locallab", "Fatanchor_" + std::to_string(i), pedited, spot.fatanchor, spotEdited.fatanchor); + assignFromKeyfile(keyFile, "Locallab", "Fatlevel_" + std::to_string(i), pedited, spot.fatlevel, spotEdited.fatlevel); // Shadow highlight spot.visishadhigh = assignFromKeyfile(keyFile, "Locallab", "Expshadhigh_" + std::to_string(i), pedited, spot.expshadhigh, spotEdited.expshadhigh); @@ -5261,6 +5995,13 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) spotEdited.visishadhigh = true; } + assignFromKeyfile(keyFile, "Locallab", "ShMethod_" + std::to_string(i), pedited, spot.shMethod, spotEdited.shMethod); + + for (int j = 0; j < 5; j ++) { + assignFromKeyfile(keyFile, "Locallab", "Multsh" + std::to_string(j) + "_" + std::to_string(i), pedited, spot.multsh[j], spotEdited.multsh[j]); + } + + assignFromKeyfile(keyFile, "Locallab", "Expshadhigh_" + std::to_string(i), pedited, spot.expshadhigh, spotEdited.expshadhigh); assignFromKeyfile(keyFile, "Locallab", "highlights_" + std::to_string(i), pedited, spot.highlights, spotEdited.highlights); assignFromKeyfile(keyFile, "Locallab", "h_tonalwidth_" + std::to_string(i), pedited, spot.h_tonalwidth, spotEdited.h_tonalwidth); assignFromKeyfile(keyFile, "Locallab", "shadows_" + std::to_string(i), pedited, spot.shadows, spotEdited.shadows); @@ -5274,10 +6015,19 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "BlendmaskSH_" + std::to_string(i), pedited, spot.blendmaskSH, spotEdited.blendmaskSH); assignFromKeyfile(keyFile, "Locallab", "RadmaskSH_" + std::to_string(i), pedited, spot.radmaskSH, spotEdited.radmaskSH); assignFromKeyfile(keyFile, "Locallab", "BlurSHde_" + std::to_string(i), pedited, spot.blurSHde, spotEdited.blurSHde); + assignFromKeyfile(keyFile, "Locallab", "StrSH_" + std::to_string(i), pedited, spot.strSH, spotEdited.strSH); + assignFromKeyfile(keyFile, "Locallab", "AngSH_" + std::to_string(i), pedited, spot.angSH, spotEdited.angSH); assignFromKeyfile(keyFile, "Locallab", "Inverssh_" + std::to_string(i), pedited, spot.inverssh, spotEdited.inverssh); assignFromKeyfile(keyFile, "Locallab", "ChromaskSH_" + std::to_string(i), pedited, spot.chromaskSH, spotEdited.chromaskSH); assignFromKeyfile(keyFile, "Locallab", "GammaskSH_" + std::to_string(i), pedited, spot.gammaskSH, spotEdited.gammaskSH); assignFromKeyfile(keyFile, "Locallab", "SlomaskSH_" + std::to_string(i), pedited, spot.slomaskSH, spotEdited.slomaskSH); + assignFromKeyfile(keyFile, "Locallab", "LapmaskSH_" + std::to_string(i), pedited, spot.lapmaskSH, spotEdited.lapmaskSH); + assignFromKeyfile(keyFile, "Locallab", "DetailSH_" + std::to_string(i), pedited, spot.detailSH, spotEdited.detailSH); + assignFromKeyfile(keyFile, "Locallab", "LmaskSHCurve_" + std::to_string(i), pedited, spot.LmaskSHcurve, spotEdited.LmaskSHcurve); + assignFromKeyfile(keyFile, "Locallab", "FatamountSH_" + std::to_string(i), pedited, spot.fatamountSH, spotEdited.fatamountSH); + assignFromKeyfile(keyFile, "Locallab", "FatanchorSH_" + std::to_string(i), pedited, spot.fatanchorSH, spotEdited.fatanchorSH); + assignFromKeyfile(keyFile, "Locallab", "GamSH_" + std::to_string(i), pedited, spot.gamSH, spotEdited.gamSH); + assignFromKeyfile(keyFile, "Locallab", "SloSH_" + std::to_string(i), pedited, spot.sloSH, spotEdited.sloSH); // Vibrance spot.visivibrance = assignFromKeyfile(keyFile, "Locallab", "Expvibrance_" + std::to_string(i), pedited, spot.expvibrance, spotEdited.expvibrance); @@ -5287,6 +6037,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Saturated_" + std::to_string(i), pedited, spot.saturated, spotEdited.saturated); assignFromKeyfile(keyFile, "Locallab", "Pastels_" + std::to_string(i), pedited, spot.pastels, spotEdited.pastels); + assignFromKeyfile(keyFile, "Locallab", "Warm_" + std::to_string(i), pedited, spot.warm, spotEdited.warm); if (keyFile.has_key("Locallab", "PSThreshold_" + std::to_string(i))) { const std::vector thresh = keyFile.get_integer_list("Locallab", "PSThreshold_" + std::to_string(i)); @@ -5295,9 +6046,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) spot.psthreshold.setValues(thresh[0], thresh[1]); } - if (pedited) { - spotEdited.psthreshold = true; - } + spotEdited.psthreshold = true; } assignFromKeyfile(keyFile, "Locallab", "ProtectSkins_" + std::to_string(i), pedited, spot.protectskins, spotEdited.protectskins); @@ -5305,6 +6054,21 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "PastSatTog_" + std::to_string(i), pedited, spot.pastsattog, spotEdited.pastsattog); assignFromKeyfile(keyFile, "Locallab", "Sensiv_" + std::to_string(i), pedited, spot.sensiv, spotEdited.sensiv); assignFromKeyfile(keyFile, "Locallab", "SkinTonesCurve_" + std::to_string(i), pedited, spot.skintonescurve, spotEdited.skintonescurve); + assignFromKeyfile(keyFile, "Locallab", "CCmaskvibCurve_" + std::to_string(i), pedited, spot.CCmaskvibcurve, spotEdited.CCmaskvibcurve); + assignFromKeyfile(keyFile, "Locallab", "LLmaskvibCurve_" + std::to_string(i), pedited, spot.LLmaskvibcurve, spotEdited.LLmaskvibcurve); + assignFromKeyfile(keyFile, "Locallab", "HHmaskvibCurve_" + std::to_string(i), pedited, spot.HHmaskvibcurve, spotEdited.HHmaskvibcurve); + assignFromKeyfile(keyFile, "Locallab", "EnavibMask_" + std::to_string(i), pedited, spot.enavibMask, spotEdited.enavibMask); + assignFromKeyfile(keyFile, "Locallab", "Blendmaskvib_" + std::to_string(i), pedited, spot.blendmaskvib, spotEdited.blendmaskvib); + assignFromKeyfile(keyFile, "Locallab", "Radmaskvib_" + std::to_string(i), pedited, spot.radmaskvib, spotEdited.radmaskvib); + assignFromKeyfile(keyFile, "Locallab", "Chromaskvib_" + std::to_string(i), pedited, spot.chromaskvib, spotEdited.chromaskvib); + assignFromKeyfile(keyFile, "Locallab", "Gammaskvib_" + std::to_string(i), pedited, spot.gammaskvib, spotEdited.gammaskvib); + assignFromKeyfile(keyFile, "Locallab", "Slomaskvib_" + std::to_string(i), pedited, spot.slomaskvib, spotEdited.slomaskvib); + assignFromKeyfile(keyFile, "Locallab", "Lapmaskvib_" + std::to_string(i), pedited, spot.lapmaskvib, spotEdited.lapmaskvib); + assignFromKeyfile(keyFile, "Locallab", "Strvib_" + std::to_string(i), pedited, spot.strvib, spotEdited.strvib); + assignFromKeyfile(keyFile, "Locallab", "Strvibab_" + std::to_string(i), pedited, spot.strvibab, spotEdited.strvibab); + assignFromKeyfile(keyFile, "Locallab", "Strvibh_" + std::to_string(i), pedited, spot.strvibh, spotEdited.strvibh); + assignFromKeyfile(keyFile, "Locallab", "Angvib_" + std::to_string(i), pedited, spot.angvib, spotEdited.angvib); + assignFromKeyfile(keyFile, "Locallab", "LmaskvibCurve_" + std::to_string(i), pedited, spot.Lmaskvibcurve, spotEdited.Lmaskvibcurve); // Soft Light spot.visisoft = assignFromKeyfile(keyFile, "Locallab", "Expsoft_" + std::to_string(i), pedited, spot.expsoft, spotEdited.expsoft); @@ -5326,8 +6090,44 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Radius_" + std::to_string(i), pedited, spot.radius, spotEdited.radius); assignFromKeyfile(keyFile, "Locallab", "Strength_" + std::to_string(i), pedited, spot.strength, spotEdited.strength); assignFromKeyfile(keyFile, "Locallab", "Sensibn_" + std::to_string(i), pedited, spot.sensibn, spotEdited.sensibn); + assignFromKeyfile(keyFile, "Locallab", "Iteramed_" + std::to_string(i), pedited, spot.itera, spotEdited.itera); + assignFromKeyfile(keyFile, "Locallab", "Guidbl_" + std::to_string(i), pedited, spot.guidbl, spotEdited.guidbl); + assignFromKeyfile(keyFile, "Locallab", "Strbl_" + std::to_string(i), pedited, spot.strbl, spotEdited.strbl); + assignFromKeyfile(keyFile, "Locallab", "Isogr_" + std::to_string(i), pedited, spot.isogr, spotEdited.isogr); + assignFromKeyfile(keyFile, "Locallab", "Strengr_" + std::to_string(i), pedited, spot.strengr, spotEdited.strengr); + assignFromKeyfile(keyFile, "Locallab", "Scalegr_" + std::to_string(i), pedited, spot.scalegr, spotEdited.scalegr); + assignFromKeyfile(keyFile, "Locallab", "Epsbl_" + std::to_string(i), pedited, spot.epsbl, spotEdited.epsbl); + assignFromKeyfile(keyFile, "Locallab", "BlMethod_" + std::to_string(i), pedited, spot.blMethod, spotEdited.blMethod); + assignFromKeyfile(keyFile, "Locallab", "ChroMethod_" + std::to_string(i), pedited, spot.chroMethod, spotEdited.chroMethod); assignFromKeyfile(keyFile, "Locallab", "BlurMethod_" + std::to_string(i), pedited, spot.blurMethod, spotEdited.blurMethod); + assignFromKeyfile(keyFile, "Locallab", "MedMethod_" + std::to_string(i), pedited, spot.medMethod, spotEdited.medMethod); assignFromKeyfile(keyFile, "Locallab", "activlum_" + std::to_string(i), pedited, spot.activlum, spotEdited.activlum); + assignFromKeyfile(keyFile, "Locallab", "CCmaskblCurve_" + std::to_string(i), pedited, spot.CCmaskblcurve, spotEdited.CCmaskblcurve); + assignFromKeyfile(keyFile, "Locallab", "LLmaskblCurve_" + std::to_string(i), pedited, spot.LLmaskblcurve, spotEdited.LLmaskblcurve); + assignFromKeyfile(keyFile, "Locallab", "HHmaskblCurve_" + std::to_string(i), pedited, spot.HHmaskblcurve, spotEdited.HHmaskblcurve); + assignFromKeyfile(keyFile, "Locallab", "EnablMask_" + std::to_string(i), pedited, spot.enablMask, spotEdited.enablMask); + assignFromKeyfile(keyFile, "Locallab", "Fftwbl_" + std::to_string(i), pedited, spot.fftwbl, spotEdited.fftwbl); + assignFromKeyfile(keyFile, "Locallab", "Toolbl_" + std::to_string(i), pedited, spot.toolbl, spotEdited.toolbl); + assignFromKeyfile(keyFile, "Locallab", "Blendmaskbl_" + std::to_string(i), pedited, spot.blendmaskbl, spotEdited.blendmaskbl); + assignFromKeyfile(keyFile, "Locallab", "Radmaskbl_" + std::to_string(i), pedited, spot.radmaskbl, spotEdited.radmaskbl); + assignFromKeyfile(keyFile, "Locallab", "Chromaskbl_" + std::to_string(i), pedited, spot.chromaskbl, spotEdited.chromaskbl); + assignFromKeyfile(keyFile, "Locallab", "Gammaskbl_" + std::to_string(i), pedited, spot.gammaskbl, spotEdited.gammaskbl); + assignFromKeyfile(keyFile, "Locallab", "Slomaskbl_" + std::to_string(i), pedited, spot.slomaskbl, spotEdited.slomaskbl); + assignFromKeyfile(keyFile, "Locallab", "Lapmaskbl_" + std::to_string(i), pedited, spot.lapmaskbl, spotEdited.lapmaskbl); + assignFromKeyfile(keyFile, "Locallab", "shadmaskbl_" + std::to_string(i), pedited, spot.shadmaskbl, spotEdited.shadmaskbl); + assignFromKeyfile(keyFile, "Locallab", "strumaskbl_" + std::to_string(i), pedited, spot.strumaskbl, spotEdited.strumaskbl); + assignFromKeyfile(keyFile, "Locallab", "LmaskblCurve_" + std::to_string(i), pedited, spot.Lmaskblcurve, spotEdited.Lmaskblcurve); + assignFromKeyfile(keyFile, "Locallab", "LLmaskblCurvewav_" + std::to_string(i), pedited, spot.LLmaskblcurvewav, spotEdited.LLmaskblcurvewav); + + if (keyFile.has_key("Locallab", "CSThresholdblur_" + std::to_string(i))) { + const std::vector thresh = keyFile.get_integer_list("Locallab", "CSThresholdblur_" + std::to_string(i)); + + if (thresh.size() >= 4) { + spot.csthresholdblur.setValues(thresh[0], thresh[1], min(thresh[2], 10), min(thresh[3], 10)); + } + + spotEdited.csthresholdblur = true; + } // Tone Mapping spot.visitonemap = assignFromKeyfile(keyFile, "Locallab", "Exptonemap_" + std::to_string(i), pedited, spot.exptonemap, spotEdited.exptonemap); @@ -5349,11 +6149,14 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "LLmasktmCurve_" + std::to_string(i), pedited, spot.LLmasktmcurve, spotEdited.LLmasktmcurve); assignFromKeyfile(keyFile, "Locallab", "HHmasktmCurve_" + std::to_string(i), pedited, spot.HHmasktmcurve, spotEdited.HHmasktmcurve); assignFromKeyfile(keyFile, "Locallab", "EnatmMask_" + std::to_string(i), pedited, spot.enatmMask, spotEdited.enatmMask); + assignFromKeyfile(keyFile, "Locallab", "EnatmMaskaft_" + std::to_string(i), pedited, spot.enatmMaskaft, spotEdited.enatmMaskaft); assignFromKeyfile(keyFile, "Locallab", "Blendmasktm_" + std::to_string(i), pedited, spot.blendmasktm, spotEdited.blendmasktm); assignFromKeyfile(keyFile, "Locallab", "Radmasktm_" + std::to_string(i), pedited, spot.radmasktm, spotEdited.radmasktm); assignFromKeyfile(keyFile, "Locallab", "Chromasktm_" + std::to_string(i), pedited, spot.chromasktm, spotEdited.chromasktm); assignFromKeyfile(keyFile, "Locallab", "Gammasktm_" + std::to_string(i), pedited, spot.gammasktm, spotEdited.gammasktm); assignFromKeyfile(keyFile, "Locallab", "Slomasktm_" + std::to_string(i), pedited, spot.slomasktm, spotEdited.slomasktm); + assignFromKeyfile(keyFile, "Locallab", "Lapmasktm_" + std::to_string(i), pedited, spot.lapmasktm, spotEdited.lapmasktm); + assignFromKeyfile(keyFile, "Locallab", "LmasktmCurve_" + std::to_string(i), pedited, spot.Lmasktmcurve, spotEdited.Lmasktmcurve); // Retinex spot.visireti = assignFromKeyfile(keyFile, "Locallab", "Expreti_" + std::to_string(i), pedited, spot.expreti, spotEdited.expreti); @@ -5366,11 +6169,16 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Chrrt_" + std::to_string(i), pedited, spot.chrrt, spotEdited.chrrt); assignFromKeyfile(keyFile, "Locallab", "Neigh_" + std::to_string(i), pedited, spot.neigh, spotEdited.neigh); assignFromKeyfile(keyFile, "Locallab", "Vart_" + std::to_string(i), pedited, spot.vart, spotEdited.vart); + assignFromKeyfile(keyFile, "Locallab", "Offs_" + std::to_string(i), pedited, spot.offs, spotEdited.offs); assignFromKeyfile(keyFile, "Locallab", "Dehaz_" + std::to_string(i), pedited, spot.dehaz, spotEdited.dehaz); + assignFromKeyfile(keyFile, "Locallab", "Depth_" + std::to_string(i), pedited, spot.depth, spotEdited.depth); assignFromKeyfile(keyFile, "Locallab", "Sensih_" + std::to_string(i), pedited, spot.sensih, spotEdited.sensih); assignFromKeyfile(keyFile, "Locallab", "TgainCurve_" + std::to_string(i), pedited, spot.localTgaincurve, spotEdited.localTgaincurve); + assignFromKeyfile(keyFile, "Locallab", "TtransCurve_" + std::to_string(i), pedited, spot.localTtranscurve, spotEdited.localTtranscurve); assignFromKeyfile(keyFile, "Locallab", "Inversret_" + std::to_string(i), pedited, spot.inversret, spotEdited.inversret); assignFromKeyfile(keyFile, "Locallab", "Equilret_" + std::to_string(i), pedited, spot.equilret, spotEdited.equilret); + assignFromKeyfile(keyFile, "Locallab", "Loglin_" + std::to_string(i), pedited, spot.loglin, spotEdited.loglin); + assignFromKeyfile(keyFile, "Locallab", "Lumonly_" + std::to_string(i), pedited, spot.lumonly, spotEdited.lumonly); assignFromKeyfile(keyFile, "Locallab", "Softradiusret_" + std::to_string(i), pedited, spot.softradiusret, spotEdited.softradiusret); assignFromKeyfile(keyFile, "Locallab", "CCmaskretiCurve_" + std::to_string(i), pedited, spot.CCmaskreticurve, spotEdited.CCmaskreticurve); assignFromKeyfile(keyFile, "Locallab", "LLmaskretiCurve_" + std::to_string(i), pedited, spot.LLmaskreticurve, spotEdited.LLmaskreticurve); @@ -5382,11 +6190,14 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Chromaskreti_" + std::to_string(i), pedited, spot.chromaskreti, spotEdited.chromaskreti); assignFromKeyfile(keyFile, "Locallab", "Gammaskreti_" + std::to_string(i), pedited, spot.gammaskreti, spotEdited.gammaskreti); assignFromKeyfile(keyFile, "Locallab", "Slomaskreti_" + std::to_string(i), pedited, spot.slomaskreti, spotEdited.slomaskreti); + assignFromKeyfile(keyFile, "Locallab", "Lapmaskreti_" + std::to_string(i), pedited, spot.lapmaskreti, spotEdited.lapmaskreti); assignFromKeyfile(keyFile, "Locallab", "Scalereti_" + std::to_string(i), pedited, spot.scalereti, spotEdited.scalereti); assignFromKeyfile(keyFile, "Locallab", "Darkness_" + std::to_string(i), pedited, spot.darkness, spotEdited.darkness); assignFromKeyfile(keyFile, "Locallab", "Lightnessreti_" + std::to_string(i), pedited, spot.lightnessreti, spotEdited.lightnessreti); assignFromKeyfile(keyFile, "Locallab", "Limd_" + std::to_string(i), pedited, spot.limd, spotEdited.limd); + assignFromKeyfile(keyFile, "Locallab", "Cliptm_" + std::to_string(i), pedited, spot.cliptm, spotEdited.cliptm); assignFromKeyfile(keyFile, "Locallab", "Fftwreti_" + std::to_string(i), pedited, spot.fftwreti, spotEdited.fftwreti); + assignFromKeyfile(keyFile, "Locallab", "LmaskretiCurve_" + std::to_string(i), pedited, spot.Lmaskreticurve, spotEdited.Lmaskreticurve); // Sharpening spot.visisharp = assignFromKeyfile(keyFile, "Locallab", "Expsharp_" + std::to_string(i), pedited, spot.expsharp, spotEdited.expsharp); @@ -5415,10 +6226,73 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Lclightness_" + std::to_string(i), pedited, spot.lclightness, spotEdited.lclightness); assignFromKeyfile(keyFile, "Locallab", "Levelwav_" + std::to_string(i), pedited, spot.levelwav, spotEdited.levelwav); assignFromKeyfile(keyFile, "Locallab", "Residcont_" + std::to_string(i), pedited, spot.residcont, spotEdited.residcont); + assignFromKeyfile(keyFile, "Locallab", "Residblur_" + std::to_string(i), pedited, spot.residblur, spotEdited.residblur); + assignFromKeyfile(keyFile, "Locallab", "Levelblur_" + std::to_string(i), pedited, spot.levelblur, spotEdited.levelblur); + assignFromKeyfile(keyFile, "Locallab", "Residchro_" + std::to_string(i), pedited, spot.residchro, spotEdited.residchro); + assignFromKeyfile(keyFile, "Locallab", "Residcomp_" + std::to_string(i), pedited, spot.residcomp, spotEdited.residcomp); + assignFromKeyfile(keyFile, "Locallab", "Sigma_" + std::to_string(i), pedited, spot.sigma, spotEdited.sigma); + assignFromKeyfile(keyFile, "Locallab", "Offset_" + std::to_string(i), pedited, spot.offset, spotEdited.offset); + assignFromKeyfile(keyFile, "Locallab", "Threswav_" + std::to_string(i), pedited, spot.threswav, spotEdited.threswav); + assignFromKeyfile(keyFile, "Locallab", "Chromalev_" + std::to_string(i), pedited, spot.chromalev, spotEdited.chromalev); + assignFromKeyfile(keyFile, "Locallab", "Chromablu_" + std::to_string(i), pedited, spot.chromablu, spotEdited.chromablu); + assignFromKeyfile(keyFile, "Locallab", "Fatdet_" + std::to_string(i), pedited, spot.fatdet, spotEdited.fatdet); + assignFromKeyfile(keyFile, "Locallab", "Fatanch_" + std::to_string(i), pedited, spot.fatanch, spotEdited.fatanch); + assignFromKeyfile(keyFile, "Locallab", "Fatres_" + std::to_string(i), pedited, spot.fatres, spotEdited.fatres); + assignFromKeyfile(keyFile, "Locallab", "ClariLres_" + std::to_string(i), pedited, spot.clarilres, spotEdited.clarilres); + assignFromKeyfile(keyFile, "Locallab", "ClariCres_" + std::to_string(i), pedited, spot.claricres, spotEdited.claricres); + assignFromKeyfile(keyFile, "Locallab", "Clarisoft_" + std::to_string(i), pedited, spot.clarisoft, spotEdited.clarisoft); + assignFromKeyfile(keyFile, "Locallab", "Strwav_" + std::to_string(i), pedited, spot.strwav, spotEdited.strwav); + assignFromKeyfile(keyFile, "Locallab", "Angwav_" + std::to_string(i), pedited, spot.angwav, spotEdited.angwav); + assignFromKeyfile(keyFile, "Locallab", "Strengthw_" + std::to_string(i), pedited, spot.strengthw, spotEdited.strengthw); + assignFromKeyfile(keyFile, "Locallab", "Radiusw_" + std::to_string(i), pedited, spot.radiusw, spotEdited.radiusw); + assignFromKeyfile(keyFile, "Locallab", "Detailw_" + std::to_string(i), pedited, spot.detailw, spotEdited.detailw); + assignFromKeyfile(keyFile, "Locallab", "Gradw_" + std::to_string(i), pedited, spot.gradw, spotEdited.gradw); + assignFromKeyfile(keyFile, "Locallab", "Tloww_" + std::to_string(i), pedited, spot.tloww, spotEdited.tloww); + assignFromKeyfile(keyFile, "Locallab", "Thigw_" + std::to_string(i), pedited, spot.thigw, spotEdited.thigw); + assignFromKeyfile(keyFile, "Locallab", "Edgw_" + std::to_string(i), pedited, spot.edgw, spotEdited.edgw); + assignFromKeyfile(keyFile, "Locallab", "Basew_" + std::to_string(i), pedited, spot.basew, spotEdited.basew); assignFromKeyfile(keyFile, "Locallab", "Sensilc_" + std::to_string(i), pedited, spot.sensilc, spotEdited.sensilc); assignFromKeyfile(keyFile, "Locallab", "Fftwlc_" + std::to_string(i), pedited, spot.fftwlc, spotEdited.fftwlc); + assignFromKeyfile(keyFile, "Locallab", "Blurlc_" + std::to_string(i), pedited, spot.blurlc, spotEdited.blurlc); + assignFromKeyfile(keyFile, "Locallab", "Wavblur_" + std::to_string(i), pedited, spot.wavblur, spotEdited.wavblur); + assignFromKeyfile(keyFile, "Locallab", "Wavedg_" + std::to_string(i), pedited, spot.wavedg, spotEdited.wavedg); + assignFromKeyfile(keyFile, "Locallab", "Waveshow_" + std::to_string(i), pedited, spot.waveshow, spotEdited.waveshow); + assignFromKeyfile(keyFile, "Locallab", "Wavcont_" + std::to_string(i), pedited, spot.wavcont, spotEdited.wavcont); + assignFromKeyfile(keyFile, "Locallab", "Wavcomp_" + std::to_string(i), pedited, spot.wavcomp, spotEdited.wavcomp); + assignFromKeyfile(keyFile, "Locallab", "Wavgradl_" + std::to_string(i), pedited, spot.wavgradl, spotEdited.wavgradl); + assignFromKeyfile(keyFile, "Locallab", "Wavcompre_" + std::to_string(i), pedited, spot.wavcompre, spotEdited.wavcompre); + assignFromKeyfile(keyFile, "Locallab", "Origlc_" + std::to_string(i), pedited, spot.origlc, spotEdited.origlc); assignFromKeyfile(keyFile, "Locallab", "localcontMethod_" + std::to_string(i), pedited, spot.localcontMethod, spotEdited.localcontMethod); + assignFromKeyfile(keyFile, "Locallab", "localedgMethod_" + std::to_string(i), pedited, spot.localedgMethod, spotEdited.localedgMethod); + assignFromKeyfile(keyFile, "Locallab", "localneiMethod_" + std::to_string(i), pedited, spot.localneiMethod, spotEdited.localneiMethod); assignFromKeyfile(keyFile, "Locallab", "LocwavCurve_" + std::to_string(i), pedited, spot.locwavcurve, spotEdited.locwavcurve); + + + assignFromKeyfile(keyFile, "Locallab", "LoclevwavCurve_" + std::to_string(i), pedited, spot.loclevwavcurve, spotEdited.loclevwavcurve); + assignFromKeyfile(keyFile, "Locallab", "LocconwavCurve_" + std::to_string(i), pedited, spot.locconwavcurve, spotEdited.locconwavcurve); + assignFromKeyfile(keyFile, "Locallab", "LoccompwavCurve_" + std::to_string(i), pedited, spot.loccompwavcurve, spotEdited.loccompwavcurve); + assignFromKeyfile(keyFile, "Locallab", "LoccomprewavCurve_" + std::to_string(i), pedited, spot.loccomprewavcurve, spotEdited.loccomprewavcurve); + assignFromKeyfile(keyFile, "Locallab", "LocedgwavCurve_" + std::to_string(i), pedited, spot.locedgwavcurve, spotEdited.locedgwavcurve); + + if (keyFile.has_key("Locallab", "CSThreshold_" + std::to_string(i))) { + + const std::vector thresh = keyFile.get_integer_list("Locallab", "CSThreshold_" + std::to_string(i)); + + if (thresh.size() >= 4) { + spot.csthreshold.setValues(thresh[0], thresh[1], min(thresh[2], 10), min(thresh[3], 10)); + } + + spotEdited.csthreshold = true; + } + + assignFromKeyfile(keyFile, "Locallab", "CCmasklcCurve_" + std::to_string(i), pedited, spot.CCmasklccurve, spotEdited.CCmasklccurve); + assignFromKeyfile(keyFile, "Locallab", "LLmasklcCurve_" + std::to_string(i), pedited, spot.LLmasklccurve, spotEdited.LLmasklccurve); + assignFromKeyfile(keyFile, "Locallab", "HHmasklcCurve_" + std::to_string(i), pedited, spot.HHmasklccurve, spotEdited.HHmasklccurve); + assignFromKeyfile(keyFile, "Locallab", "EnalcMask_" + std::to_string(i), pedited, spot.enalcMask, spotEdited.enalcMask); + assignFromKeyfile(keyFile, "Locallab", "Blendmasklc_" + std::to_string(i), pedited, spot.blendmasklc, spotEdited.blendmasklc); + assignFromKeyfile(keyFile, "Locallab", "Radmasklc_" + std::to_string(i), pedited, spot.radmasklc, spotEdited.radmasklc); + assignFromKeyfile(keyFile, "Locallab", "Chromasklc_" + std::to_string(i), pedited, spot.chromasklc, spotEdited.chromasklc); + assignFromKeyfile(keyFile, "Locallab", "LmasklcCurve_" + std::to_string(i), pedited, spot.Lmasklccurve, spotEdited.Lmasklccurve); // Contrast by detail levels spot.visicbdl = assignFromKeyfile(keyFile, "Locallab", "Expcbdl_" + std::to_string(i), pedited, spot.expcbdl, spotEdited.expcbdl); @@ -5446,6 +6320,8 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Chromaskcb_" + std::to_string(i), pedited, spot.chromaskcb, spotEdited.chromaskcb); assignFromKeyfile(keyFile, "Locallab", "Gammaskcb_" + std::to_string(i), pedited, spot.gammaskcb, spotEdited.gammaskcb); assignFromKeyfile(keyFile, "Locallab", "Slomaskcb_" + std::to_string(i), pedited, spot.slomaskcb, spotEdited.slomaskcb); + assignFromKeyfile(keyFile, "Locallab", "Lapmaskcb_" + std::to_string(i), pedited, spot.lapmaskcb, spotEdited.lapmaskcb); + assignFromKeyfile(keyFile, "Locallab", "LmaskcbCurve_" + std::to_string(i), pedited, spot.Lmaskcbcurve, spotEdited.Lmaskcbcurve); // Denoise spot.visidenoi = assignFromKeyfile(keyFile, "Locallab", "Expdenoi_" + std::to_string(i), pedited, spot.expdenoi, spotEdited.expdenoi); @@ -5465,6 +6341,27 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Adjblur_" + std::to_string(i), pedited, spot.adjblur, spotEdited.adjblur); assignFromKeyfile(keyFile, "Locallab", "Bilateral_" + std::to_string(i), pedited, spot.bilateral, spotEdited.bilateral); assignFromKeyfile(keyFile, "Locallab", "Sensiden_" + std::to_string(i), pedited, spot.sensiden, spotEdited.sensiden); + assignFromKeyfile(keyFile, "Locallab", "Detailthr_" + std::to_string(i), pedited, spot.detailthr, spotEdited.detailthr); + assignFromKeyfile(keyFile, "Locallab", "LocwavCurveden_" + std::to_string(i), pedited, spot.locwavcurveden, spotEdited.locwavcurveden); + // Log encoding + spot.visilog = assignFromKeyfile(keyFile, "Locallab", "Explog_" + std::to_string(i), pedited, spot.explog, spotEdited.explog); + + if (spot.visilog) { + spotEdited.visilog = true; + } + + assignFromKeyfile(keyFile, "Locallab", "Autocompute_" + std::to_string(i), pedited, spot.autocompute, spotEdited.autocompute); + assignFromKeyfile(keyFile, "Locallab", "SourceGray_" + std::to_string(i), pedited, spot.sourceGray, spotEdited.sourceGray); + assignFromKeyfile(keyFile, "Locallab", "TargetGray_" + std::to_string(i), pedited, spot.targetGray, spotEdited.targetGray); + assignFromKeyfile(keyFile, "Locallab", "AutoGray_" + std::to_string(i), pedited, spot.Autogray, spotEdited.Autogray); + assignFromKeyfile(keyFile, "Locallab", "Fullimage_" + std::to_string(i), pedited, spot.fullimage, spotEdited.fullimage); + assignFromKeyfile(keyFile, "Locallab", "BlackEv_" + std::to_string(i), pedited, spot.blackEv, spotEdited.blackEv); + assignFromKeyfile(keyFile, "Locallab", "WhiteEv_" + std::to_string(i), pedited, spot.whiteEv, spotEdited.whiteEv); + assignFromKeyfile(keyFile, "Locallab", "Detail_" + std::to_string(i), pedited, spot.detail, spotEdited.detail); + assignFromKeyfile(keyFile, "Locallab", "Sensilog_" + std::to_string(i), pedited, spot.sensilog, spotEdited.sensilog); + assignFromKeyfile(keyFile, "Locallab", "Baselog_" + std::to_string(i), pedited, spot.baselog, spotEdited.baselog); + assignFromKeyfile(keyFile, "Locallab", "Strlog_" + std::to_string(i), pedited, spot.strlog, spotEdited.strlog); + assignFromKeyfile(keyFile, "Locallab", "Anglog_" + std::to_string(i), pedited, spot.anglog, spotEdited.anglog); // Append LocallabSpot and LocallabParamsEdited locallab.spots.push_back(spot); @@ -5516,6 +6413,17 @@ 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", "DeconvRadius", pedited, pdsharpening.deconvradius, pedited->pdsharpening.deconvradius); + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "DeconvRadiusOffset", pedited, pdsharpening.deconvradiusOffset, pedited->pdsharpening.deconvradiusOffset); + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "DeconvIterCheck", pedited, pdsharpening.deconvitercheck, pedited->pdsharpening.deconvitercheck); + 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); @@ -5926,6 +6834,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")) { diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 796cdf6dc..aa4bfa7d3 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -14,16 +14,17 @@ * GNU General Public License for more details. * * 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 #include +#include #include #include -#include +#include #include #include "noncopyable.h" @@ -301,6 +302,7 @@ struct ToneCurveParams { ToneCurveParams(); + bool isPanningRelatedChange(const ToneCurveParams& other) const; bool operator ==(const ToneCurveParams& other) const; bool operator !=(const ToneCurveParams& other) const; @@ -510,7 +512,9 @@ struct ColorToningParams { struct SharpeningParams { bool enabled; double contrast; + bool autoContrast; double blurradius; + double gamma; double radius; int amount; Threshold threshold; @@ -558,6 +562,22 @@ struct SharpenMicroParams { bool operator !=(const SharpenMicroParams& other) const; }; +struct CaptureSharpeningParams { + bool enabled; + bool autoContrast; + bool autoRadius; + double contrast; + double deconvradius; + double deconvradiusOffset; + int deconviter; + bool deconvitercheck; + + CaptureSharpeningParams(); + + bool operator ==(const CaptureSharpeningParams& other) const; + bool operator !=(const CaptureSharpeningParams& other) const; +}; + /** * Parameters of the vibrance */ @@ -616,6 +636,7 @@ struct WBParams { WBParams(); + bool isPanningRelatedChange(const WBParams& other) const; bool operator ==(const WBParams& other) const; bool operator !=(const WBParams& other) const; @@ -835,6 +856,7 @@ struct CoarseTransformParams { * Common transformation parameters */ struct CommonTransformParams { + Glib::ustring method; bool autofill; CommonTransformParams(); @@ -939,6 +961,7 @@ struct LocallabParams { bool isvisible; Glib::ustring shape; // ELI, RECT Glib::ustring spotMethod; // norm, exc + Glib::ustring wavMethod; // D2, D4, D6, D10, D14 int sensiexclu; int structexclu; double struc; @@ -951,13 +974,24 @@ struct LocallabParams { int centerY; int circrad; Glib::ustring qualityMethod; // none, std, enh, enhsup, contr, sob2 - int transit; + Glib::ustring complexMethod; // sim, mod, all + double transit; + double feather; double thresh; double iter; double balan; + double balanh; + double colorde; double transitweak; double transitgrad; bool avoid; + bool recurs; + bool laplac; + bool deltae; + bool shortc; + bool savrest; + int scopemask; + int lumask; // Color & Light bool visicolor; bool expcolor; @@ -969,31 +1003,60 @@ struct LocallabParams { double labgridBLow; double labgridAHigh; double labgridBHigh; + double labgridALowmerg; + double labgridBLowmerg; + double labgridAHighmerg; + double labgridBHighmerg; int strengthgrid; int sensi; int structcol; + double strcol; + double strcolab; + double strcolh; + double angcol; int blurcolde; + double blurcol; + double contcol; int blendmaskcol; double radmaskcol; double chromaskcol; double gammaskcol; double slomaskcol; - Glib::ustring qualitycurveMethod; - Glib::ustring gridMethod; + int shadmaskcol; + double strumaskcol; + double lapmaskcol; + Glib::ustring qualitycurveMethod; // none, std + Glib::ustring gridMethod; // one, two + Glib::ustring merMethod; // mone, mtwo, mthr, mfou, mfiv + Glib::ustring toneMethod; // one, two, thr, fou + Glib::ustring mergecolMethod; // one, two, thr, fou, fiv, six, sev, sev0, sev1, sev2, hei, nin, ten, ele, twe, thi, for, hue, sat, col, lum std::vector llcurve; + std::vector lccurve; std::vector cccurve; + std::vector clcurve; + std::vector rgbcurve; std::vector LHcurve; std::vector HHcurve; bool invers; + bool special; + bool toolcol; bool enaColorMask; + bool fftColorMask; std::vector CCmaskcurve; std::vector LLmaskcurve; std::vector HHmaskcurve; + std::vector HHhmaskcurve; double softradiuscol; + double opacol; + double mercol; + double merlucol; + double conthrcol; + std::vector Lmaskcurve; + std::vector LLmaskcolcurvewav; + Threshold csthresholdcol; // Exposure bool visiexpose; bool expexpose; - // int expcomp; double expcomp; int hlcompr; int hlcomprthresh; @@ -1001,13 +1064,15 @@ struct LocallabParams { int shadex; int shcompr; int expchroma; - int warm; int sensiex; int structexp; int blurexpde; + double strexp; + double angexp; std::vector excurve; bool inversex; bool enaExpMask; + bool enaExpMaskaft; std::vector CCmaskexpcurve; std::vector LLmaskexpcurve; std::vector HHmaskexpcurve; @@ -1016,14 +1081,26 @@ struct LocallabParams { double chromaskexp; double gammaskexp; double slomaskexp; + double lapmaskexp; + double strmaskexp; + double angmaskexp; double softradiusexp; - Glib::ustring expMethod; + std::vector Lmaskexpcurve; + Glib::ustring expMethod; // std, pde + Glib::ustring exnoiseMethod; // none, med, medhi double laplacexp; double balanexp; double linear; + double gamm; + double fatamount; + double fatdetail; + double fatanchor; + double fatlevel; // Shadow highlight bool visishadhigh; bool expshadhigh; + Glib::ustring shMethod; // std, tone + int multsh[5]; int highlights; int h_tonalwidth; int shadows; @@ -1037,36 +1114,88 @@ struct LocallabParams { int blendmaskSH; double radmaskSH; int blurSHde; + double strSH; + double angSH; bool inverssh; double chromaskSH; double gammaskSH; double slomaskSH; + double lapmaskSH; + int detailSH; + std::vector LmaskSHcurve; + double fatamountSH; + double fatanchorSH; + double gamSH; + double sloSH; // Vibrance bool visivibrance; bool expvibrance; int saturated; int pastels; + int warm; Threshold psthreshold; bool protectskins; bool avoidcolorshift; bool pastsattog; int sensiv; std::vector skintonescurve; + std::vector CCmaskvibcurve; + std::vector LLmaskvibcurve; + std::vector HHmaskvibcurve; + bool enavibMask; + int blendmaskvib; + double radmaskvib; + double chromaskvib; + double gammaskvib; + double slomaskvib; + double lapmaskvib; + double strvib; + double strvibab; + double strvibh; + double angvib; + std::vector Lmaskvibcurve; // Soft Light bool visisoft; bool expsoft; int streng; int sensisf; double laplace; - Glib::ustring softMethod; + Glib::ustring softMethod; // soft, reti // Blur & Noise bool visiblur; bool expblur; double radius; int strength; int sensibn; - Glib::ustring blurMethod; + int itera; + int guidbl; + int strbl; + int isogr; + int strengr; + int scalegr; + int epsbl; + Glib::ustring blMethod; // blur, med, guid + Glib::ustring chroMethod; // lum, chr, all + Glib::ustring blurMethod; // norm, inv + Glib::ustring medMethod; // none, 33, 55, 77, 99 bool activlum; + std::vector CCmaskblcurve; + std::vector LLmaskblcurve; + std::vector HHmaskblcurve; + bool enablMask; + bool fftwbl; + bool toolbl; + int blendmaskbl; + double radmaskbl; + double chromaskbl; + double gammaskbl; + double slomaskbl; + double lapmaskbl; + int shadmaskbl; + double strumaskbl; + std::vector Lmaskblcurve; + std::vector LLmaskblcurvewav; + Threshold csthresholdblur; // Tone Mapping bool visitonemap; bool exptonemap; @@ -1084,24 +1213,32 @@ struct LocallabParams { std::vector LLmasktmcurve; std::vector HHmasktmcurve; bool enatmMask; + bool enatmMaskaft; int blendmasktm; double radmasktm; double chromasktm; double gammasktm; double slomasktm; + double lapmasktm; + std::vector Lmasktmcurve; // Retinex bool visireti; bool expreti; - Glib::ustring retinexMethod; + Glib::ustring retinexMethod; // low, uni, high double str; double chrrt; double neigh; double vart; + double offs; int dehaz; + int depth; int sensih; std::vector localTgaincurve; + std::vector localTtranscurve; bool inversret; bool equilret; + bool loglin; + bool lumonly; double softradiusret; std::vector CCmaskreticurve; std::vector LLmaskreticurve; @@ -1113,11 +1250,14 @@ struct LocallabParams { double chromaskreti; double gammaskreti; double slomaskreti; + double lapmaskreti; double scalereti; double darkness; double lightnessreti; double limd; + double cliptm; bool fftwreti; + std::vector Lmaskreticurve; // Sharpening bool visisharp; bool expsharp; @@ -1138,10 +1278,60 @@ struct LocallabParams { double lclightness; int levelwav; double residcont; + double residblur; + double levelblur; + double residchro; + double residcomp; + double sigma; + double offset; + double threswav; + double chromalev; + double chromablu; + double fatdet; + double fatanch; + double fatres; + double clarilres; + double claricres; + double clarisoft; + double strwav; + double angwav; + double strengthw; + double radiusw; + double detailw; + double gradw; + double tloww; + double thigw; + double edgw; + double basew; int sensilc; bool fftwlc; - Glib::ustring localcontMethod; + bool blurlc; + bool wavblur; + bool wavedg; + bool waveshow; + bool wavcont; + bool wavcomp; + bool wavgradl; + bool wavcompre; + bool origlc; + Glib::ustring localcontMethod; // loc, wav + Glib::ustring localedgMethod; // fir, sec, thr + Glib::ustring localneiMethod; // none, low, high std::vector locwavcurve; + Threshold csthreshold; + std::vector loclevwavcurve; + std::vector locconwavcurve; + std::vector loccompwavcurve; + std::vector loccomprewavcurve; + std::vector locedgwavcurve; + std::vector CCmasklccurve; + std::vector LLmasklccurve; + std::vector HHmasklccurve; + bool enalcMask; + int blendmasklc; + double radmasklc; + double chromasklc; + std::vector Lmasklccurve; // Contrast by detail levels bool visicbdl; bool expcbdl; @@ -1162,21 +1352,40 @@ struct LocallabParams { double chromaskcb; double gammaskcb; double slomaskcb; + double lapmaskcb; + std::vector Lmaskcbcurve; // Denoise bool visidenoi; bool expdenoi; - int noiselumf; - int noiselumf0; - int noiselumf2; - int noiselumc; - int noiselumdetail; + double noiselumf; + double noiselumf0; + double noiselumf2; + double noiselumc; + double noiselumdetail; int noiselequal; - int noisechrof; - int noisechroc; - int noisechrodetail; + double noisechrof; + double noisechroc; + double noisechrodetail; int adjblur; int bilateral; int sensiden; + int detailthr; + std::vector locwavcurveden; + // Log encoding + bool visilog; + bool explog; + bool autocompute; + double sourceGray; + double targetGray; + bool Autogray; + bool fullimage; + double blackEv; + double whiteEv; + double detail; + int sensilog; + double baselog; + double strlog; + double anglog; LocallabSpot(); @@ -1187,12 +1396,6 @@ struct LocallabParams { static const double LABGRIDL_CORR_MAX; static const double LABGRIDL_CORR_SCALE; static const double LABGRIDL_DIRECT_SCALE; - static const std::vector DEF_MASK_CURVE; - static const std::vector DEF_COLOR_LCURVE; - static const std::vector DEF_COLOR_HCURVE; - static const std::vector DEF_EXP_CURVE; - static const std::vector DEF_RET_CURVE; - static const std::vector DEF_LC_CURVE; bool enabled; int selspot; @@ -1617,6 +1820,7 @@ struct DehazeParams { int strength; bool showDepthMap; int depth; + bool luminance; DehazeParams(); @@ -1660,6 +1864,7 @@ struct RAWParams { enum class PSDemosaicMethod { AMAZE, AMAZEVNG4, + RCDVNG4, LMMSE }; @@ -1820,6 +2025,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 @@ -1929,8 +2135,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..7d937e736 100644 --- a/rtengine/profilestore.cc +++ b/rtengine/profilestore.cc @@ -14,8 +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 +#include + #include "profilestore.h" #include "dynamicprofile.h" @@ -156,7 +160,7 @@ void ProfileStore::_parseProfiles () if (findEntryFromFullPathU (options.defProfRaw) == nullptr) { options.setDefProfRawMissing (true); - if (options.rtSettings.verbose) { + if (settings->verbose) { printf ("WARNING: Default profile \"%s\" for raw images not found!\n", options.defProfRaw.c_str()); } } @@ -164,7 +168,7 @@ void ProfileStore::_parseProfiles () if (findEntryFromFullPathU (options.defProfImg) == nullptr) { options.setDefProfImgMissing (true); - if (options.rtSettings.verbose) { + if (settings->verbose) { printf ("WARNING: Default profile \"%s\" for standard images not found!\n", options.defProfImg.c_str()); } } @@ -216,7 +220,7 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath if (lastdot != Glib::ustring::npos && lastdot == currDir.length() - 4 && currDir.substr (lastdot).casefold() == paramFileExtension) { // file found - if ( options.rtSettings.verbose ) { + if (settings->verbose) { printf ("Processing file %s...", fname.c_str()); } @@ -229,7 +233,7 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath if (!res && pProf->pparams->ppVersion >= 220) { fileFound = true; - if ( options.rtSettings.verbose ) { + if (settings->verbose) { printf ("OK\n"); } @@ -240,7 +244,7 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath // map the partial profile partProfiles[filePSE] = pProf; //partProfiles.insert( std::pair (filePSE, pProf) ); - } else if ( options.rtSettings.verbose ) { + } else if (settings->verbose) { printf ("failed!\n"); } } @@ -261,12 +265,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 +458,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); @@ -518,7 +522,7 @@ PartialProfile *ProfileStore::loadDynamicProfile (const FramesMetaData *im) for (auto rule : dynamicRules) { if (rule.matches (im)) { - if (options.rtSettings.verbose) { + if (settings->verbose) { printf ("found matching profile %s\n", rule.profilepath.c_str()); } @@ -535,7 +539,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..460facb72 100644 --- a/rtengine/profilestore.h +++ b/rtengine/profilestore.h @@ -14,18 +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 _PROFILESTORE_ -#define _PROFILESTORE_ +#pragma once #include #include -#include -#include "rtengine.h" -#include "noncopyable.h" +#include + #include "dynamicprofile.h" +#include "noncopyable.h" +#include "../rtgui/threadutils.h" // forward decl namespace rtengine @@ -34,6 +34,8 @@ namespace rtengine namespace procparams { +class ProcParams; + class AutoPartialProfile; class PartialProfile; @@ -185,7 +187,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 +195,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; } @@ -211,5 +213,3 @@ public: void dumpFolderList(); }; - -#endif diff --git a/rtengine/rawflatfield.cc b/rtengine/rawflatfield.cc new file mode 100644 index 000000000..cbc5e6bd6 --- /dev/null +++ b/rtengine/rawflatfield.cc @@ -0,0 +1,536 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2019 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 +#include +#include + +#include "rawimagesource.h" +#include "procparams.h" +#include "rawimage.h" +//#define BENCHMARK +//#include "StopWatch.h" +#include "opthelper.h" + +namespace { + +void cfaboxblur(const float* const * riFlatFile, float* cfablur, int boxH, int boxW, int H, int W) +{ + if (boxW < 0 || boxH < 0 || (boxW == 0 && boxH == 0)) { // nothing to blur or negative values + memcpy(cfablur, riFlatFile[0], static_cast(W) * H * sizeof(float)); + return; + } + + std::unique_ptr tmpBuffer; + float *cfatmp = cfablur; + + + if (boxH > 0 && boxW > 0) { + // we need a temporary buffer if we have to blur both directions + tmpBuffer.reset(new float [H * W]); + cfatmp = tmpBuffer.get(); + } + + // if boxW == 0 we can skip the horizontal blur and process the vertical blur from riFlatFile to cfablur without using a temporary buffer + const float* srcVertical = boxW == 0 ? riFlatFile[0] : cfatmp; + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + + if (boxW > 0) { + //box blur cfa image; box size = BS + //horizontal blur +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 0; row < H; ++row) { + int len = boxW / 2 + 1; + cfatmp[row * W] = riFlatFile[row][0] / len; + cfatmp[row * W + 1] = riFlatFile[row][1] / len; + + for (int j = 2; j <= boxW; j += 2) { + cfatmp[row * W] += riFlatFile[row][j] / len; + cfatmp[row * W + 1] += riFlatFile[row][j + 1] / len; + } + + for (int col = 2; col <= boxW; col += 2) { + cfatmp[row * W + col] = (cfatmp[row * W + col - 2] * len + riFlatFile[row][boxW + col]) / (len + 1); + cfatmp[row * W + col + 1] = (cfatmp[row * W + col - 1] * len + riFlatFile[row][boxW + col + 1]) / (len + 1); + len ++; + } + + const float rlen = 1.f / len; + for (int col = boxW + 2; col < W - boxW; col++) { + cfatmp[row * W + col] = cfatmp[row * W + col - 2] + (riFlatFile[row][boxW + col] - cfatmp[row * W + col - boxW - 2]) * rlen; + } + + for (int col = W - boxW; col < W; col += 2) { + cfatmp[row * W + col] = (cfatmp[row * W + col - 2] * len - cfatmp[row * W + col - boxW - 2]) / (len - 1); + + if (col + 1 < W) { + cfatmp[row * W + col + 1] = (cfatmp[row * W + col - 1] * len - cfatmp[row * W + col - boxW - 1]) / (len - 1); + } + + len --; + } + } + } + + if (boxH > 0) { + //vertical blur +#ifdef __SSE2__ + const vfloat leninitv = F2V(boxH / 2 + 1); + const vfloat onev = F2V(1.f); +#ifdef _OPENMP + #pragma omp for nowait +#endif + + for (int col = 0; col < W - 7; col += 8) { + vfloat lenv = leninitv; + vfloat temp1v = LVFU(srcVertical[col]) / lenv; + vfloat temp2v = LVFU(srcVertical[W + col]) / lenv; + vfloat temp3v = LVFU(srcVertical[col + 4]) / lenv; + vfloat temp4v = LVFU(srcVertical[W + col + 4]) / lenv; + + for (int i = 2; i < boxH + 2; i += 2) { + temp1v += LVFU(srcVertical[i * W + col]) / lenv; + temp2v += LVFU(srcVertical[(i + 1) * W + col]) / lenv; + temp3v += LVFU(srcVertical[i * W + col + 4]) / lenv; + temp4v += LVFU(srcVertical[(i + 1) * W + col + 4]) / lenv; + } + + STVFU(cfablur[col], temp1v); + STVFU(cfablur[W + col], temp2v); + STVFU(cfablur[col + 4], temp3v); + STVFU(cfablur[W + col + 4], temp4v); + + int row; + for (row = 2; row < boxH + 2; row += 2) { + const vfloat lenp1v = lenv + onev; + temp1v = (temp1v * lenv + LVFU(srcVertical[(row + boxH) * W + col])) / lenp1v; + temp2v = (temp2v * lenv + LVFU(srcVertical[(row + boxH + 1) * W + col])) / lenp1v; + temp3v = (temp3v * lenv + LVFU(srcVertical[(row + boxH) * W + col + 4])) / lenp1v; + temp4v = (temp4v * lenv + LVFU(srcVertical[(row + boxH + 1) * W + col + 4])) / lenp1v; + STVFU(cfablur[row * W + col], temp1v); + STVFU(cfablur[(row + 1) * W + col], temp2v); + STVFU(cfablur[row * W + col + 4], temp3v); + STVFU(cfablur[(row + 1) * W + col + 4], temp4v); + lenv = lenp1v; + } + + for (; row < H - boxH - 1; row += 2) { + temp1v = temp1v + (LVFU(srcVertical[(row + boxH) * W + col]) - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenv; + temp2v = temp2v + (LVFU(srcVertical[(row + 1 + boxH) * W + col]) - LVFU(srcVertical[(row + 1 - boxH - 2) * W + col])) / lenv; + temp3v = temp3v + (LVFU(srcVertical[(row + boxH) * W + col + 4]) - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenv; + temp4v = temp4v + (LVFU(srcVertical[(row + 1 + boxH) * W + col + 4]) - LVFU(srcVertical[(row + 1 - boxH - 2) * W + col + 4])) / lenv; + STVFU(cfablur[row * W + col], temp1v); + STVFU(cfablur[(row + 1) * W + col], temp2v); + STVFU(cfablur[row * W + col + 4], temp3v); + STVFU(cfablur[(row + 1) * W + col + 4], temp4v); + } + + if (row < H - boxH) { + temp1v = temp1v + (LVFU(srcVertical[(row + boxH) * W + col]) - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenv; + temp3v = temp3v + (LVFU(srcVertical[(row + boxH) * W + col + 4]) - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenv; + STVFU(cfablur[row * W + col], temp1v); + STVFU(cfablur[row * W + col + 4], temp3v); + vfloat swapv = temp1v; + temp1v = temp2v; + temp2v = swapv; + swapv = temp3v; + temp3v = temp4v; + temp4v = swapv; + ++row; + } + + for (; row < H - 1; row += 2) { + const vfloat lenm1v = lenv - onev; + temp1v = (temp1v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenm1v; + temp2v = (temp2v * lenv - LVFU(srcVertical[(row - boxH - 1) * W + col])) / lenm1v; + temp3v = (temp3v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenm1v; + temp4v = (temp4v * lenv - LVFU(srcVertical[(row - boxH - 1) * W + col + 4])) / lenm1v; + STVFU(cfablur[row * W + col], temp1v); + STVFU(cfablur[(row + 1) * W + col], temp2v); + STVFU(cfablur[row * W + col + 4], temp3v); + STVFU(cfablur[(row + 1) * W + col + 4], temp4v); + lenv = lenm1v; + } + + if (row < H) { + vfloat lenm1v = lenv - onev; + temp1v = (temp1v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenm1v; + temp3v = (temp3v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenm1v; + STVFU(cfablur[row * W + col], temp1v); + STVFU(cfablur[row * W + col + 4], temp3v); + } + + } + +#ifdef _OPENMP + #pragma omp single +#endif + + for (int col = W - (W % 8); col < W; ++col) { + int len = boxH / 2 + 1; + cfablur[col] = srcVertical[col] / len; + cfablur[W + col] = srcVertical[W + col] / len; + + for (int i = 2; i < boxH + 2; i += 2) { + cfablur[col] += srcVertical[i * W + col] / len; + cfablur[W + col] += srcVertical[(i + 1) * W + col] / len; + } + + for (int row = 2; row < boxH + 2; row += 2) { + cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len + srcVertical[(row + boxH) * W + col]) / (len + 1); + cfablur[(row + 1) * W + col] = (cfablur[(row - 1) * W + col] * len + srcVertical[(row + boxH + 1) * W + col]) / (len + 1); + ++len; + } + + for (int row = boxH + 2; row < H - boxH; ++row) { + cfablur[row * W + col] = cfablur[(row - 2) * W + col] + (srcVertical[(row + boxH) * W + col] - srcVertical[(row - boxH - 2) * W + col]) / len; + } + + for (int row = H - boxH; row < H; row += 2) { + cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len - srcVertical[(row - boxH - 2) * W + col]) / (len - 1); + + if (row + 1 < H) { + cfablur[(row + 1) * W + col] = (cfablur[(row - 1) * W + col] * len - srcVertical[(row - boxH - 1) * W + col]) / (len - 1); + } + --len; + } + } + +#else +#ifdef _OPENMP + #pragma omp for +#endif + + for (int col = 0; col < W; ++col) { + int len = boxH / 2 + 1; + cfablur[col] = srcVertical[col] / len; + cfablur[W + col] = srcVertical[W + col] / len; + + for (int i = 2; i < boxH + 2; i += 2) { + cfablur[col] += srcVertical[i * W + col] / len; + cfablur[W + col] += srcVertical[(i + 1) * W + col] / len; + } + + for (int row = 2; row < boxH + 2; row += 2) { + cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len + srcVertical[(row + boxH) * W + col]) / (len + 1); + cfablur[(row + 1) * W + col] = (cfablur[(row - 1) * W + col] * len + srcVertical[(row + boxH + 1) * W + col]) / (len + 1); + ++len; + } + + for (int row = boxH + 2; row < H - boxH; ++row) { + cfablur[row * W + col] = cfablur[(row - 2) * W + col] + (srcVertical[(row + boxH) * W + col] - srcVertical[(row - boxH - 2) * W + col]) / len; + } + + for (int row = H - boxH; row < H; row += 2) { + cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len - srcVertical[(row - boxH - 2) * W + col]) / (len - 1); + + if (row + 1 < H) { + cfablur[(row + 1) * W + col] = (cfablur[(row - 1) * W + col] * len - srcVertical[(row - boxH - 1) * W + col]) / (len - 1); + } + --len; + } + } +#endif + } + } +} + +} + +namespace rtengine +{ + +void RawImageSource::processFlatField(const procparams::RAWParams &raw, const RawImage *riFlatFile, const float black[4]) +{ +// BENCHFUN + std::unique_ptr cfablur(new float[H * W]); + + const int BS = raw.ff_BlurRadius + (raw.ff_BlurRadius & 1); + + if (raw.ff_BlurType == procparams::RAWParams::getFlatFieldBlurTypeString(procparams::RAWParams::FlatFieldBlurType::V)) { + cfaboxblur(riFlatFile->data, cfablur.get(), 2 * BS, 0, H, W); + } else if (raw.ff_BlurType == procparams::RAWParams::getFlatFieldBlurTypeString(procparams::RAWParams::FlatFieldBlurType::H)) { + cfaboxblur(riFlatFile->data, cfablur.get(), 0, 2 * BS, H, W); + } else if (raw.ff_BlurType == procparams::RAWParams::getFlatFieldBlurTypeString(procparams::RAWParams::FlatFieldBlurType::VH)) { + //slightly more complicated blur if trying to correct both vertical and horizontal anomalies + cfaboxblur(riFlatFile->data, cfablur.get(), BS, BS, H, W); //first do area blur to correct vignette + } else { //(raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::area_ff)) + cfaboxblur(riFlatFile->data, cfablur.get(), BS, BS, H, W); + } + + if (ri->getSensorType() == ST_BAYER || ri->get_colors() == 1) { + float refcolor[2][2]; + + // find center values by channel + for (int m = 0; m < 2; ++m) + for (int n = 0; n < 2; ++n) { + const int row = 2 * (H >> 2) + m; + const int col = 2 * (W >> 2) + n; + const int c = ri->get_colors() != 1 ? FC(row, col) : 0; + const int c4 = ri->get_colors() != 1 ? ((c == 1 && !(row & 1)) ? 3 : c) : 0; + refcolor[m][n] = std::max(0.0f, cfablur[row * W + col] - black[c4]); + } + + float limitFactor = 1.f; + + if (raw.ff_AutoClipControl) { + bool clippedBefore = false; + for (int m = 0; m < 2 && !clippedBefore; ++m) { + for (int n = 0; n < 2 && !clippedBefore; ++n) { + float maxval = 0.f; + const int c = ri->get_colors() != 1 ? FC(m, n) : 0; + const int c4 = ri->get_colors() != 1 ? ((c == 1 && !(m & 1)) ? 3 : c) : 0; + const float clipVal = ri->get_white(c4); +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxval) schedule(dynamic, 16) +#endif + for (int row = 0; row < H - m; row += 2) { + for (int col = 0; col < W - n && !clippedBefore; col += 2) { + const float rawVal = rawData[row + m][col + n]; + if (rawVal >= clipVal) { + clippedBefore = true; + break; + } + const float tempval = (rawVal - black[c4]) * (refcolor[m][n] / std::max(1e-5f, cfablur[(row + m) * W + col + n] - black[c4])); + maxval = std::max(maxval, tempval); + } + } + + // now we have the max value for the channel + // if it clips, calculate factor to avoid clipping + if (maxval + black[c4] >= ri->get_white(c4)) { + if (!clippedBefore) { + limitFactor = std::min(limitFactor, ri->get_white(c4) / (maxval + black[c4])); + } else { + limitFactor = 1.f; + } + } + } + } + flatFieldAutoClipValue = (1.f - limitFactor) * 100.f; // this value can be used to set the clip control slider in gui + } else { + limitFactor = std::max((100 - raw.ff_clipControl) / 100.f, 0.01f); + } + + for (int m = 0; m < 2; ++m) + for (int n = 0; n < 2; ++n) { + refcolor[m][n] *= limitFactor; + } + + unsigned int c[2][2] {}; + unsigned int c4[2][2] {}; + if (ri->get_colors() != 1) { + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 2; ++j) { + c[i][j] = FC(i, j); + } + } + c4[0][0] = (c[0][0] == 1) ? 3 : c[0][0]; + c4[0][1] = (c[0][1] == 1) ? 3 : c[0][1]; + c4[1][0] = c[1][0]; + c4[1][1] = c[1][1]; + } + + constexpr float minValue = 1.f; // if the pixel value in the flat field is less or equal this value, no correction will be applied. + +#ifdef __SSE2__ + const vfloat refcolorv[2] = {_mm_set_ps(refcolor[0][1], refcolor[0][0], refcolor[0][1], refcolor[0][0]), + _mm_set_ps(refcolor[1][1], refcolor[1][0], refcolor[1][1], refcolor[1][0]) + }; + const vfloat blackv[2] = {_mm_set_ps(black[c4[0][1]], black[c4[0][0]], black[c4[0][1]], black[c4[0][0]]), + _mm_set_ps(black[c4[1][1]], black[c4[1][0]], black[c4[1][1]], black[c4[1][0]]) + }; + + const vfloat onev = F2V(1.f); + const vfloat minValuev = F2V(minValue); +#endif +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int row = 0; row < H; ++row) { + int col = 0; +#ifdef __SSE2__ + const vfloat rowBlackv = blackv[row & 1]; + const vfloat rowRefcolorv = refcolorv[row & 1]; + + for (; col < W - 3; col += 4) { + const vfloat blurv = LVFU(cfablur[row * W + col]) - rowBlackv; + vfloat vignettecorrv = rowRefcolorv / blurv; + vignettecorrv = vself(vmaskf_le(blurv, minValuev), onev, vignettecorrv); + const vfloat valv = LVFU(rawData[row][col]) - rowBlackv; + STVFU(rawData[row][col], valv * vignettecorrv + rowBlackv); + } + +#endif + + for (; col < W; ++col) { + const float blur = cfablur[row * W + col] - black[c4[row & 1][col & 1]]; + const float vignettecorr = blur <= minValue ? 1.f : refcolor[row & 1][col & 1] / blur; + rawData[row][col] = (rawData[row][col] - black[c4[row & 1][col & 1]]) * vignettecorr + black[c4[row & 1][col & 1]]; + } + } + } else if (ri->getSensorType() == ST_FUJI_XTRANS) { + float refcolor[3] = {0.f}; + int cCount[3] = {0}; + + // find center average values by channel + for (int m = -3; m < 3; ++m) + for (int n = -3; n < 3; ++n) { + const int row = 2 * (H >> 2) + m; + const int col = 2 * (W >> 2) + n; + const int c = riFlatFile->XTRANSFC(row, col); + refcolor[c] += std::max(0.0f, cfablur[row * W + col] - black[c]); + cCount[c] ++; + } + + for (int c = 0; c < 3; ++c) { + refcolor[c] = refcolor[c] / cCount[c]; + } + + float limitFactor = 1.f; + + if (raw.ff_AutoClipControl) { + // determine maximum calculated value to avoid clipping + bool clippedBefore = false; + const float clipVal = ri->get_white(0); + float maxval = 0.f; + // xtrans files have only one black level actually, so we can simplify the code a bit +#ifdef _OPENMP + #pragma omp parallel for reduction(max:maxval) schedule(dynamic,16) +#endif + for (int row = 0; row < H; ++row) { + for (int col = 0; col < W && !clippedBefore; ++col) { + const float rawVal = rawData[row][col]; + if (rawVal >= clipVal) { + clippedBefore = true; + break; + } + const float tempval = (rawVal - black[0]) * (refcolor[ri->XTRANSFC(row, col)] / std::max(1e-5f, cfablur[(row) * W + col] - black[0])); + maxval = std::max(maxval, tempval); + } + } + + // there's only one white level for xtrans + if (!clippedBefore && maxval + black[0] > ri->get_white(0)) { + limitFactor = ri->get_white(0) / (maxval + black[0]); + flatFieldAutoClipValue = (1.f - limitFactor) * 100.f; // this value can be used to set the clip control slider in gui + } + } else { + limitFactor = std::max((float)(100 - raw.ff_clipControl) / 100.f, 0.01f); + } + + + for (int c = 0; c < 3; ++c) { + refcolor[c] *= limitFactor; + } + + constexpr float minValue = 1.f; // if the pixel value in the flat field is less or equal this value, no correction will be applied. + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int row = 0; row < H; ++row) { + for (int col = 0; col < W; ++col) { + const int c = ri->XTRANSFC(row, col); + const float blur = cfablur[(row) * W + col] - black[c]; + const float vignettecorr = blur <= minValue ? 1.f : refcolor[c] / blur; + rawData[row][col] = (rawData[row][col] - black[c]) * vignettecorr + black[c]; + } + } + } + + if (raw.ff_BlurType == procparams::RAWParams::getFlatFieldBlurTypeString(procparams::RAWParams::FlatFieldBlurType::VH)) { + std::unique_ptr cfablur1(new float[H * W]); + std::unique_ptr cfablur2(new float[H * W]); + //slightly more complicated blur if trying to correct both vertical and horizontal anomalies + cfaboxblur(riFlatFile->data, cfablur1.get(), 0, 2 * BS, H, W); //now do horizontal blur + cfaboxblur(riFlatFile->data, cfablur2.get(), 2 * BS, 0, H, W); //now do vertical blur + + if (ri->getSensorType() == ST_BAYER || ri->get_colors() == 1) { + unsigned int c[2][2] {}; + unsigned int c4[2][2] {}; + if (ri->get_colors() != 1) { + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 2; ++j) { + c[i][j] = FC(i, j); + } + } + c4[0][0] = (c[0][0] == 1) ? 3 : c[0][0]; + c4[0][1] = (c[0][1] == 1) ? 3 : c[0][1]; + c4[1][0] = c[1][0]; + c4[1][1] = c[1][1]; + } + +#ifdef __SSE2__ + const vfloat blackv[2] = {_mm_set_ps(black[c4[0][1]], black[c4[0][0]], black[c4[0][1]], black[c4[0][0]]), + _mm_set_ps(black[c4[1][1]], black[c4[1][0]], black[c4[1][1]], black[c4[1][0]]) + }; + + const vfloat epsv = F2V(1e-5f); +#endif +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int row = 0; row < H; ++row) { + int col = 0; +#ifdef __SSE2__ + const vfloat rowBlackv = blackv[row & 1]; + + for (; col < W - 3; col += 4) { + const vfloat linecorrv = SQRV(vmaxf(LVFU(cfablur[row * W + col]) - rowBlackv, epsv)) / + (vmaxf(LVFU(cfablur1[row * W + col]) - rowBlackv, epsv) * vmaxf(LVFU(cfablur2[row * W + col]) - rowBlackv, epsv)); + const vfloat valv = LVFU(rawData[row][col]) - rowBlackv; + STVFU(rawData[row][col], valv * linecorrv + rowBlackv); + } + +#endif + + for (; col < W; ++col) { + const float linecorr = SQR(std::max(1e-5f, cfablur[row * W + col] - black[c4[row & 1][col & 1]])) / + (std::max(1e-5f, cfablur1[row * W + col] - black[c4[row & 1][col & 1]]) * std::max(1e-5f, cfablur2[row * W + col] - black[c4[row & 1][col & 1]])); + rawData[row][col] = (rawData[row][col] - black[c4[row & 1][col & 1]]) * linecorr + black[c4[row & 1][col & 1]]; + } + } + } else if (ri->getSensorType() == ST_FUJI_XTRANS) { +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int row = 0; row < H; ++row) { + for (int col = 0; col < W; ++col) { + const int c = ri->XTRANSFC(row, col); + const float hlinecorr = std::max(1e-5f, cfablur[(row) * W + col] - black[c]) / std::max(1e-5f, cfablur1[(row) * W + col] - black[c]); + const float vlinecorr = std::max(1e-5f, cfablur[(row) * W + col] - black[c]) / std::max(1e-5f, cfablur2[(row) * W + col] - black[c]); + rawData[row][col] = (rawData[row][col] - black[c]) * hlinecorr * vlinecorr + black[c]; + } + } + } + } +} +} /* namespace */ diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index e1c39cf9c..dc44307aa 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -15,12 +15,11 @@ #include "settings.h" #include "camconst.h" #include "utils.h" +#include "rtengine.h" namespace rtengine { -extern const Settings* settings; - RawImage::RawImage(const Glib::ustring &name) : data(nullptr) , prefilters(0) diff --git a/rtengine/rawimage.h b/rtengine/rawimage.h index 83c0a25a7..7fb1dbbc4 100644 --- a/rtengine/rawimage.h +++ b/rtengine/rawimage.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 . */ -#ifndef __RAWIMAGE_H -#define __RAWIMAGE_H +#pragma once #include #include #include +#include #include "dcraw.h" #include "imageformat.h" @@ -308,5 +308,3 @@ public: }; } - -#endif // __RAWIMAGE_H diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 254f3c633..fa23fb9ca 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -14,36 +14,41 @@ * GNU General Public License for more details. * * 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 "rtengine.h" -#include "rawimagesource.h" -#include "rawimagesource_i.h" -#include "jaggedarray.h" -#include "median.h" -#include "rawimage.h" -#include "mytime.h" -#include "iccstore.h" +#include "camconst.h" +#include "color.h" #include "curves.h" +#include "dcp.h" #include "dfmanager.h" #include "ffmanager.h" -#include "dcp.h" -#include "rt_math.h" +#include "iccstore.h" +#include "imagefloat.h" #include "improcfun.h" -#include "rtlensfun.h" +#include "jaggedarray.h" +#include "median.h" +#include "mytime.h" #include "pdaflinesfilter.h" -#include "camconst.h" #include "procparams.h" +#include "rawimage.h" +#include "rawimagesource_i.h" +#include "rawimagesource.h" +#include "rt_math.h" +#include "rtengine.h" +#include "rtlensfun.h" +#include "../rtgui/options.h" + +//#define BENCHMARK +#include "StopWatch.h" + #ifdef _OPENMP #include #endif + #include "opthelper.h" -#define clipretinex( val, minv, maxv ) (( val = (val < minv ? minv : val ) ) > maxv ? maxv : val ) -#undef CLIPD -#define CLIPD(a) ((a)>0.0f?((a)<1.0f?(a):1.0f):0.0f) namespace { @@ -416,12 +421,9 @@ void transLineD1x (const float* const red, const float* const green, const float namespace rtengine { -extern const Settings* settings; #undef ABS -#undef DIST #define ABS(a) ((a)<0?-(a):(a)) -#define DIST(a,b) (ABS(a-b)) RawImageSource::RawImageSource() : ImageSource() @@ -429,6 +431,7 @@ RawImageSource::RawImageSource() , plistener(nullptr) , scale_mul{} , c_black{} + , c_white{} , cblacksom{} , ref_pre_mul{} , refwb_red(0.0) @@ -452,6 +455,9 @@ RawImageSource::RawImageSource() , green(0, 0) , red(0, 0) , blue(0, 0) + , greenCache(nullptr) + , redCache(nullptr) + , blueCache(nullptr) , rawDirty(true) , histMatchingParams(new procparams::ColorManagementParams) { @@ -470,6 +476,9 @@ RawImageSource::~RawImageSource() { delete idata; + delete redCache; + delete greenCache; + delete blueCache; for (size_t i = 0; i < numFrames; ++i) { delete riFrames[i]; @@ -491,6 +500,26 @@ RawImageSource::~RawImageSource() } } +unsigned RawImageSource::FC(int row, int col) const +{ + return ri->FC(row, col); +} + +eSensorType RawImageSource::getSensorType () const +{ + return ri != nullptr ? ri->getSensorType() : ST_NONE; +} + +bool RawImageSource::isMono() const +{ + return ri->get_colors() == 1; +} + +int RawImageSource::getRotateDegree() const +{ + return ri->get_rotateDegree(); +} + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void RawImageSource::transformRect(const PreviewProps &pp, int tran, int &ssx1, int &ssy1, int &width, int &height, int &fw) @@ -904,7 +933,7 @@ void RawImageSource::getImage(const ColorTemp &ctemp, int tran, Imagefloat* imag } } -DCPProfile *RawImageSource::getDCP(const ColorManagementParams &cmp, DCPProfile::ApplyState &as) +DCPProfile *RawImageSource::getDCP(const ColorManagementParams &cmp, DCPProfileApplyState &as) { if (cmp.inputProfile == "(camera)" || cmp.inputProfile == "(none)") { return nullptr; @@ -1001,11 +1030,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 @@ -1328,7 +1389,7 @@ void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lens std::unique_ptr pmap; if (lensProf.useLensfun()) { - pmap = LFDatabase::findModifier(lensProf, idata, W, H, coarse, -1); + pmap = LFDatabase::getInstance()->findModifier(lensProf, idata, W, H, coarse, -1); } else { const std::shared_ptr pLCPProf = LCPStore::getInstance()->getProfile(lensProf.lcpFile); @@ -1343,32 +1404,13 @@ void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lens if (ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS || ri->get_colors() == 1) { if (numFrames == 4) { for (int i = 0; i < 4; ++i) { -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < H; y++) { - map.processVignetteLine(W, y, (*rawDataFrames[i])[y]); - } + map.processVignette(W, H, *rawDataFrames[i]); } } else { - -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < H; y++) { - map.processVignetteLine(W, y, rawData[y]); - } + map.processVignette(W, H, rawData); } } else if (ri->get_colors() == 3) { -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int y = 0; y < H; y++) { - map.processVignetteLine3Channels(W, y, rawData[y]); - } + map.processVignette3Channels(W, H, rawData); } } } @@ -1531,7 +1573,7 @@ void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lens } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -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(); @@ -1602,7 +1644,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)); @@ -1879,7 +1963,7 @@ void RawImageSource::retinexPrepareCurves(const RetinexParams &retinexParams, LU } CurveFactory::mapcurve(mapcontlutili, retinexParams.mapcurve, mapcurve, 1, lhist16RETI, histLRETI); - + mapcurve *= 0.5f; retinexParams.getCurves(retinextransmissionCurve, retinexgaintransmissionCurve); } @@ -2313,321 +2397,15 @@ void RawImageSource::HLRecovery_Global(const ToneCurveParams &hrp) } - -void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile, unsigned short black[4]) -{ -// BENCHFUN - float *cfablur = (float (*)) malloc(H * W * sizeof * cfablur); - int BS = raw.ff_BlurRadius; - BS += BS & 1; - - //function call to cfabloxblur - if (raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::FlatFieldBlurType::V)) { - cfaboxblur(riFlatFile, cfablur, 2 * BS, 0); - } else if (raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::FlatFieldBlurType::H)) { - cfaboxblur(riFlatFile, cfablur, 0, 2 * BS); - } else if (raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::FlatFieldBlurType::VH)) { - //slightly more complicated blur if trying to correct both vertical and horizontal anomalies - cfaboxblur(riFlatFile, cfablur, BS, BS); //first do area blur to correct vignette - } else { //(raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::area_ff)) - cfaboxblur(riFlatFile, cfablur, BS, BS); - } - - if(ri->getSensorType() == ST_BAYER || ri->get_colors() == 1) { - float refcolor[2][2]; - - //find centre average values by channel - for (int m = 0; m < 2; m++) - for (int n = 0; n < 2; n++) { - int row = 2 * (H >> 2) + m; - int col = 2 * (W >> 2) + n; - int c = ri->get_colors() != 1 ? FC(row, col) : 0; - int c4 = ri->get_colors() != 1 ? (( c == 1 && !(row & 1) ) ? 3 : c) : 0; - refcolor[m][n] = max(0.0f, cfablur[row * W + col] - black[c4]); - } - - float limitFactor = 1.f; - - if (raw.ff_AutoClipControl) { - for (int m = 0; m < 2; m++) - for (int n = 0; n < 2; n++) { - float maxval = 0.f; - int c = ri->get_colors() != 1 ? FC(m, n) : 0; - int c4 = ri->get_colors() != 1 ? (( c == 1 && !(m & 1) ) ? 3 : c) : 0; -#ifdef _OPENMP - #pragma omp parallel -#endif - { - float maxvalthr = 0.f; -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 0; row < H - m; row += 2) { - for (int col = 0; col < W - n; col += 2) { - float tempval = (rawData[row + m][col + n] - black[c4]) * (refcolor[m][n] / max(1e-5f, cfablur[(row + m) * W + col + n] - black[c4])); - - if (tempval > maxvalthr) { - maxvalthr = tempval; - } - } - } - -#ifdef _OPENMP - #pragma omp critical -#endif - { - - if (maxvalthr > maxval) { - maxval = maxvalthr; - } - - } - } - - // now we have the max value for the channel - // if it clips, calculate factor to avoid clipping - if (maxval + black[c4] >= ri->get_white(c4)) { - limitFactor = min(limitFactor, ri->get_white(c4) / (maxval + black[c4])); - } - } - - flatFieldAutoClipValue = (1.f - limitFactor) * 100.f; // this value can be used to set the clip control slider in gui - } else { - limitFactor = max((float)(100 - raw.ff_clipControl) / 100.f, 0.01f); - } - - for (int m = 0; m < 2; m++) - for (int n = 0; n < 2; n++) { - refcolor[m][n] *= limitFactor; - } - - unsigned int c[2][2] {}; - unsigned int c4[2][2] {}; - if(ri->get_colors() != 1) { - for (int i = 0; i < 2; ++i) { - for(int j = 0; j < 2; ++j) { - c[i][j] = FC(i, j); - } - } - c4[0][0] = ( c[0][0] == 1) ? 3 : c[0][0]; - c4[0][1] = ( c[0][1] == 1) ? 3 : c[0][1]; - c4[1][0] = c[1][0]; - c4[1][1] = c[1][1]; - } - - constexpr float minValue = 1.f; // if the pixel value in the flat field is less or equal this value, no correction will be applied. - -#ifdef __SSE2__ - vfloat refcolorv[2] = {_mm_set_ps(refcolor[0][1], refcolor[0][0], refcolor[0][1], refcolor[0][0]), - _mm_set_ps(refcolor[1][1], refcolor[1][0], refcolor[1][1], refcolor[1][0]) - }; - vfloat blackv[2] = {_mm_set_ps(black[c4[0][1]], black[c4[0][0]], black[c4[0][1]], black[c4[0][0]]), - _mm_set_ps(black[c4[1][1]], black[c4[1][0]], black[c4[1][1]], black[c4[1][0]]) - }; - - vfloat onev = F2V(1.f); - vfloat minValuev = F2V(minValue); -#endif -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int row = 0; row < H; row ++) { - int col = 0; -#ifdef __SSE2__ - vfloat rowBlackv = blackv[row & 1]; - vfloat rowRefcolorv = refcolorv[row & 1]; - - for (; col < W - 3; col += 4) { - vfloat blurv = LVFU(cfablur[(row) * W + col]) - rowBlackv; - vfloat vignettecorrv = rowRefcolorv / blurv; - vignettecorrv = vself(vmaskf_le(blurv, minValuev), onev, vignettecorrv); - vfloat valv = LVFU(rawData[row][col]); - valv -= rowBlackv; - STVFU(rawData[row][col], valv * vignettecorrv + rowBlackv); - } - -#endif - - for (; col < W; col ++) { - float blur = cfablur[(row) * W + col] - black[c4[row & 1][col & 1]]; - float vignettecorr = blur <= minValue ? 1.f : refcolor[row & 1][col & 1] / blur; - rawData[row][col] = (rawData[row][col] - black[c4[row & 1][col & 1]]) * vignettecorr + black[c4[row & 1][col & 1]]; - } - } - } else if (ri->getSensorType() == ST_FUJI_XTRANS) { - float refcolor[3] = {0.f}; - int cCount[3] = {0}; - - //find center ave values by channel - for (int m = -3; m < 3; m++) - for (int n = -3; n < 3; n++) { - int row = 2 * (H >> 2) + m; - int col = 2 * (W >> 2) + n; - int c = riFlatFile->XTRANSFC(row, col); - refcolor[c] += max(0.0f, cfablur[row * W + col] - black[c]); - cCount[c] ++; - } - - for (int c = 0; c < 3; c++) { - refcolor[c] = refcolor[c] / cCount[c]; - } - - float limitFactor = 1.f; - - if (raw.ff_AutoClipControl) { - // determine maximum calculated value to avoid clipping - float maxval = 0.f; - // xtrans files have only one black level actually, so we can simplify the code a bit -#ifdef _OPENMP - #pragma omp parallel -#endif - { - float maxvalthr = 0.f; -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) nowait -#endif - - for (int row = 0; row < H; row++) { - for (int col = 0; col < W; col++) { - float tempval = (rawData[row][col] - black[0]) * (refcolor[ri->XTRANSFC(row, col)] / max(1e-5f, cfablur[(row) * W + col] - black[0])); - - if (tempval > maxvalthr) { - maxvalthr = tempval; - } - } - } - -#ifdef _OPENMP - #pragma omp critical -#endif - { - if (maxvalthr > maxval) { - maxval = maxvalthr; - } - } - } - - // there's only one white level for xtrans - if (maxval + black[0] > ri->get_white(0)) { - limitFactor = ri->get_white(0) / (maxval + black[0]); - flatFieldAutoClipValue = (1.f - limitFactor) * 100.f; // this value can be used to set the clip control slider in gui - } - } else { - limitFactor = max((float)(100 - raw.ff_clipControl) / 100.f, 0.01f); - } - - - for (int c = 0; c < 3; c++) { - refcolor[c] *= limitFactor; - } - - constexpr float minValue = 1.f; // if the pixel value in the flat field is less or equal this value, no correction will be applied. - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int row = 0; row < H; row++) { - for (int col = 0; col < W; col++) { - int c = ri->XTRANSFC(row, col); - float blur = cfablur[(row) * W + col] - black[c]; - float vignettecorr = blur <= minValue ? 1.f : refcolor[c] / blur; - rawData[row][col] = (rawData[row][col] - black[c]) * vignettecorr + black[c]; - } - } - } - - if (raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::FlatFieldBlurType::VH)) { - float *cfablur1 = (float (*)) malloc(H * W * sizeof * cfablur1); - float *cfablur2 = (float (*)) malloc(H * W * sizeof * cfablur2); - //slightly more complicated blur if trying to correct both vertical and horizontal anomalies - cfaboxblur(riFlatFile, cfablur1, 0, 2 * BS); //now do horizontal blur - cfaboxblur(riFlatFile, cfablur2, 2 * BS, 0); //now do vertical blur - - if(ri->getSensorType() == ST_BAYER || ri->get_colors() == 1) { - unsigned int c[2][2] {}; - unsigned int c4[2][2] {}; - if(ri->get_colors() != 1) { - for (int i = 0; i < 2; ++i) { - for(int j = 0; j < 2; ++j) { - c[i][j] = FC(i, j); - } - } - c4[0][0] = ( c[0][0] == 1) ? 3 : c[0][0]; - c4[0][1] = ( c[0][1] == 1) ? 3 : c[0][1]; - c4[1][0] = c[1][0]; - c4[1][1] = c[1][1]; - } - -#ifdef __SSE2__ - vfloat blackv[2] = {_mm_set_ps(black[c4[0][1]], black[c4[0][0]], black[c4[0][1]], black[c4[0][0]]), - _mm_set_ps(black[c4[1][1]], black[c4[1][0]], black[c4[1][1]], black[c4[1][0]]) - }; - - vfloat epsv = F2V(1e-5f); -#endif -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - - for (int row = 0; row < H; row ++) { - int col = 0; -#ifdef __SSE2__ - vfloat rowBlackv = blackv[row & 1]; - - for (; col < W - 3; col += 4) { - vfloat linecorrv = SQRV(vmaxf(LVFU(cfablur[row * W + col]) - rowBlackv, epsv)) / - (vmaxf(LVFU(cfablur1[row * W + col]) - rowBlackv, epsv) * vmaxf(LVFU(cfablur2[row * W + col]) - rowBlackv, epsv)); - vfloat valv = LVFU(rawData[row][col]); - valv -= rowBlackv; - STVFU(rawData[row][col], valv * linecorrv + rowBlackv); - } - -#endif - - for (; col < W; col ++) { - float linecorr = SQR(max(1e-5f, cfablur[row * W + col] - black[c4[row & 1][col & 1]])) / - (max(1e-5f, cfablur1[row * W + col] - black[c4[row & 1][col & 1]]) * max(1e-5f, cfablur2[row * W + col] - black[c4[row & 1][col & 1]])) ; - rawData[row][col] = (rawData[row][col] - black[c4[row & 1][col & 1]]) * linecorr + black[c4[row & 1][col & 1]]; - } - } - } else if (ri->getSensorType() == ST_FUJI_XTRANS) { -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int row = 0; row < H; row++) { - for (int col = 0; col < W; col++) { - int c = ri->XTRANSFC(row, col); - float hlinecorr = (max(1e-5f, cfablur[(row) * W + col] - black[c]) / max(1e-5f, cfablur1[(row) * W + col] - black[c])); - float vlinecorr = (max(1e-5f, cfablur[(row) * W + col] - black[c]) / max(1e-5f, cfablur2[(row) * W + col] - black[c])); - rawData[row][col] = ((rawData[row][col] - black[c]) * hlinecorr * vlinecorr + black[c]); - } - } - - } - - free(cfablur1); - free(cfablur2); - } - - free(cfablur); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - /* Copy original pixel data and * subtract dark frame (if present) from current image and apply flat field correction (if present) */ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, RawImage *riDark, RawImage *riFlatFile, array2D &rawData) { - // TODO: Change type of black[] to float to avoid conversions - unsigned short black[4] = { - (unsigned short)ri->get_cblack(0), (unsigned short)ri->get_cblack(1), - (unsigned short)ri->get_cblack(2), (unsigned short)ri->get_cblack(3) - }; + const float black[4] = { + static_cast(ri->get_cblack(0)), static_cast(ri->get_cblack(1)), + static_cast(ri->get_cblack(2)), static_cast(ri->get_cblack(3)) + }; if (ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS) { if (!rawData) { @@ -2635,11 +2413,22 @@ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, Raw } if (riDark && W == riDark->get_width() && H == riDark->get_height()) { // This works also for xtrans-sensors, because black[0] to black[4] are equal for these + StopWatch Stop1("darkframe subtraction"); +#ifdef _OPENMP + #pragma omp parallel for +#endif for (int row = 0; row < H; row++) { - for (int col = 0; col < W; col++) { - int c = FC(row, col); - int c4 = (c == 1 && !(row & 1)) ? 3 : c; - rawData[row][col] = max(src->data[row][col] + black[c4] - riDark->data[row][col], 0.0f); + const int c0 = FC(row, 0); + const float black0 = black[(c0 == 1 && !(row & 1) ) ? 3 : c0]; + const int c1 = FC(row, 1); + const float black1 = black[(c1 == 1 && !(row & 1) ) ? 3 : c1]; + int col; + for (col = 0; col < W - 1; col += 2) { + rawData[row][col] = max(src->data[row][col] + black0 - riDark->data[row][col], 0.0f); + rawData[row][col + 1] = max(src->data[row][col + 1] + black1 - riDark->data[row][col + 1], 0.0f); + } + if (col < W) { + rawData[row][col] = max(src->data[row][col] + black0 - riDark->data[row][col], 0.0f); } } } else { @@ -2709,253 +2498,6 @@ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, Raw } } -void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur, int boxH, int boxW) -{ - - if (boxW < 0 || boxH < 0 || (boxW == 0 && boxH == 0)) { // nothing to blur or negative values - memcpy(cfablur, riFlatFile->data[0], W * H * sizeof(float)); - return; - } - - float *tmpBuffer = nullptr; - float *cfatmp = nullptr; - float *srcVertical = nullptr; - - - if (boxH > 0 && boxW > 0) { - // we need a temporary buffer if we have to blur both directions - tmpBuffer = (float (*)) calloc(H * W, sizeof * tmpBuffer); - } - - if (boxH == 0) { - // if boxH == 0 we can skip the vertical blur and process the horizontal blur from riFlatFile to cfablur without using a temporary buffer - cfatmp = cfablur; - } else { - cfatmp = tmpBuffer; - } - - if (boxW == 0) { - // if boxW == 0 we can skip the horizontal blur and process the vertical blur from riFlatFile to cfablur without using a temporary buffer - srcVertical = riFlatFile->data[0]; - } else { - srcVertical = cfatmp; - } - -#ifdef _OPENMP - #pragma omp parallel -#endif - { - - if (boxW > 0) { - //box blur cfa image; box size = BS - //horizontal blur -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 0; row < H; row++) { - int len = boxW / 2 + 1; - cfatmp[row * W + 0] = riFlatFile->data[row][0] / len; - cfatmp[row * W + 1] = riFlatFile->data[row][1] / len; - - for (int j = 2; j <= boxW; j += 2) { - cfatmp[row * W + 0] += riFlatFile->data[row][j] / len; - cfatmp[row * W + 1] += riFlatFile->data[row][j + 1] / len; - } - - for (int col = 2; col <= boxW; col += 2) { - cfatmp[row * W + col] = (cfatmp[row * W + col - 2] * len + riFlatFile->data[row][boxW + col]) / (len + 1); - cfatmp[row * W + col + 1] = (cfatmp[row * W + col - 1] * len + riFlatFile->data[row][boxW + col + 1]) / (len + 1); - len ++; - } - - for (int col = boxW + 2; col < W - boxW; col++) { - cfatmp[row * W + col] = cfatmp[row * W + col - 2] + (riFlatFile->data[row][boxW + col] - cfatmp[row * W + col - boxW - 2]) / len; - } - - for (int col = W - boxW; col < W; col += 2) { - cfatmp[row * W + col] = (cfatmp[row * W + col - 2] * len - cfatmp[row * W + col - boxW - 2]) / (len - 1); - - if (col + 1 < W) { - cfatmp[row * W + col + 1] = (cfatmp[row * W + col - 1] * len - cfatmp[row * W + col - boxW - 1]) / (len - 1); - } - - len --; - } - } - } - - if (boxH > 0) { - //vertical blur -#ifdef __SSE2__ - vfloat leninitv = F2V(boxH / 2 + 1); - vfloat onev = F2V(1.0f); - vfloat temp1v, temp2v, temp3v, temp4v, lenv, lenp1v, lenm1v; - int row; -#ifdef _OPENMP - #pragma omp for nowait -#endif - - for (int col = 0; col < W - 7; col += 8) { - lenv = leninitv; - temp1v = LVFU(srcVertical[0 * W + col]) / lenv; - temp2v = LVFU(srcVertical[1 * W + col]) / lenv; - temp3v = LVFU(srcVertical[0 * W + col + 4]) / lenv; - temp4v = LVFU(srcVertical[1 * W + col + 4]) / lenv; - - for (int i = 2; i < boxH + 2; i += 2) { - temp1v += LVFU(srcVertical[i * W + col]) / lenv; - temp2v += LVFU(srcVertical[(i + 1) * W + col]) / lenv; - temp3v += LVFU(srcVertical[i * W + col + 4]) / lenv; - temp4v += LVFU(srcVertical[(i + 1) * W + col + 4]) / lenv; - } - - STVFU(cfablur[0 * W + col], temp1v); - STVFU(cfablur[1 * W + col], temp2v); - STVFU(cfablur[0 * W + col + 4], temp3v); - STVFU(cfablur[1 * W + col + 4], temp4v); - - for (row = 2; row < boxH + 2; row += 2) { - lenp1v = lenv + onev; - temp1v = (temp1v * lenv + LVFU(srcVertical[(row + boxH) * W + col])) / lenp1v; - temp2v = (temp2v * lenv + LVFU(srcVertical[(row + boxH + 1) * W + col])) / lenp1v; - temp3v = (temp3v * lenv + LVFU(srcVertical[(row + boxH) * W + col + 4])) / lenp1v; - temp4v = (temp4v * lenv + LVFU(srcVertical[(row + boxH + 1) * W + col + 4])) / lenp1v; - STVFU(cfablur[row * W + col], temp1v); - STVFU(cfablur[(row + 1)*W + col], temp2v); - STVFU(cfablur[row * W + col + 4], temp3v); - STVFU(cfablur[(row + 1)*W + col + 4], temp4v); - lenv = lenp1v; - } - - for (; row < H - boxH - 1; row += 2) { - temp1v = temp1v + (LVFU(srcVertical[(row + boxH) * W + col]) - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenv; - temp2v = temp2v + (LVFU(srcVertical[(row + 1 + boxH) * W + col]) - LVFU(srcVertical[(row + 1 - boxH - 2) * W + col])) / lenv; - temp3v = temp3v + (LVFU(srcVertical[(row + boxH) * W + col + 4]) - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenv; - temp4v = temp4v + (LVFU(srcVertical[(row + 1 + boxH) * W + col + 4]) - LVFU(srcVertical[(row + 1 - boxH - 2) * W + col + 4])) / lenv; - STVFU(cfablur[row * W + col], temp1v); - STVFU(cfablur[(row + 1)*W + col], temp2v); - STVFU(cfablur[row * W + col + 4], temp3v); - STVFU(cfablur[(row + 1)*W + col + 4], temp4v); - } - - for (; row < H - boxH; row++) { - temp1v = temp1v + (LVFU(srcVertical[(row + boxH) * W + col]) - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenv; - temp3v = temp3v + (LVFU(srcVertical[(row + boxH) * W + col + 4]) - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenv; - STVFU(cfablur[row * W + col], temp1v); - STVFU(cfablur[row * W + col + 4], temp3v); - vfloat swapv = temp1v; - temp1v = temp2v; - temp2v = swapv; - swapv = temp3v; - temp3v = temp4v; - temp4v = swapv; - } - - for (; row < H - 1; row += 2) { - lenm1v = lenv - onev; - temp1v = (temp1v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenm1v; - temp2v = (temp2v * lenv - LVFU(srcVertical[(row - boxH - 1) * W + col])) / lenm1v; - temp3v = (temp3v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenm1v; - temp4v = (temp4v * lenv - LVFU(srcVertical[(row - boxH - 1) * W + col + 4])) / lenm1v; - STVFU(cfablur[row * W + col], temp1v); - STVFU(cfablur[(row + 1)*W + col], temp2v); - STVFU(cfablur[row * W + col + 4], temp3v); - STVFU(cfablur[(row + 1)*W + col + 4], temp4v); - lenv = lenm1v; - } - - for (; row < H; row++) { - lenm1v = lenv - onev; - temp1v = (temp1v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenm1v; - temp3v = (temp3v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenm1v; - STVFU(cfablur[(row)*W + col], temp1v); - STVFU(cfablur[(row)*W + col + 4], temp3v); - } - - } - -#ifdef _OPENMP - #pragma omp single -#endif - - for (int col = W - (W % 8); col < W; col++) { - int len = boxH / 2 + 1; - cfablur[0 * W + col] = srcVertical[0 * W + col] / len; - cfablur[1 * W + col] = srcVertical[1 * W + col] / len; - - for (int i = 2; i < boxH + 2; i += 2) { - cfablur[0 * W + col] += srcVertical[i * W + col] / len; - cfablur[1 * W + col] += srcVertical[(i + 1) * W + col] / len; - } - - for (int row = 2; row < boxH + 2; row += 2) { - cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len + srcVertical[(row + boxH) * W + col]) / (len + 1); - cfablur[(row + 1)*W + col] = (cfablur[(row - 1) * W + col] * len + srcVertical[(row + boxH + 1) * W + col]) / (len + 1); - len ++; - } - - for (int row = boxH + 2; row < H - boxH; row++) { - cfablur[row * W + col] = cfablur[(row - 2) * W + col] + (srcVertical[(row + boxH) * W + col] - srcVertical[(row - boxH - 2) * W + col]) / len; - } - - for (int row = H - boxH; row < H; row += 2) { - cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len - srcVertical[(row - boxH - 2) * W + col]) / (len - 1); - - if (row + 1 < H) { - cfablur[(row + 1)*W + col] = (cfablur[(row - 1) * W + col] * len - srcVertical[(row - boxH - 1) * W + col]) / (len - 1); - } - - len --; - } - } - -#else -#ifdef _OPENMP - #pragma omp for -#endif - - for (int col = 0; col < W; col++) { - int len = boxH / 2 + 1; - cfablur[0 * W + col] = srcVertical[0 * W + col] / len; - cfablur[1 * W + col] = srcVertical[1 * W + col] / len; - - for (int i = 2; i < boxH + 2; i += 2) { - cfablur[0 * W + col] += srcVertical[i * W + col] / len; - cfablur[1 * W + col] += srcVertical[(i + 1) * W + col] / len; - } - - for (int row = 2; row < boxH + 2; row += 2) { - cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len + srcVertical[(row + boxH) * W + col]) / (len + 1); - cfablur[(row + 1)*W + col] = (cfablur[(row - 1) * W + col] * len + srcVertical[(row + boxH + 1) * W + col]) / (len + 1); - len ++; - } - - for (int row = boxH + 2; row < H - boxH; row++) { - cfablur[row * W + col] = cfablur[(row - 2) * W + col] + (srcVertical[(row + boxH) * W + col] - srcVertical[(row - boxH - 2) * W + col]) / len; - } - - for (int row = H - boxH; row < H; row += 2) { - cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len - srcVertical[(row - boxH - 2) * W + col]) / (len - 1); - - if (row + 1 < H) { - cfablur[(row + 1)*W + col] = (cfablur[(row - 1) * W + col] * len - srcVertical[(row - boxH - 1) * W + col]) / (len - 1); - } - - len --; - } - } - -#endif - } - } - - if (tmpBuffer) { - free(tmpBuffer); - } -} - - // Scale original pixels into the range 0 65535 using black offsets and multipliers void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const RAWParams &raw, array2D &rawData) { @@ -3016,12 +2558,10 @@ void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const R for (int row = winy; row < winy + winh; row ++) { for (int col = winx; col < winx + winw; col++) { - float val = rawData[row][col]; - int c = FC(row, col); // three colors, 0=R, 1=G, 2=B - int c4 = (c == 1 && !(row & 1)) ? 3 : c; // four colors, 0=R, 1=G1, 2=B, 3=G2 - val -= cblacksom[c4]; - val *= scale_mul[c4]; - rawData[row][col] = (val); + const int c = FC(row, col); // three colors, 0=R, 1=G, 2=B + const int c4 = ( c == 1 && !(row & 1) ) ? 3 : c; // four colors, 0=R, 1=G1, 2=B, 3=G2 + const float val = max(0.f, rawData[row][col] - cblacksom[c4]) * scale_mul[c4]; + rawData[row][col] = val; tmpchmax[c] = max(tmpchmax[c], val); } } @@ -3048,10 +2588,8 @@ void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const R for (int row = winy; row < winy + winh; row ++) { for (int col = winx; col < winx + winw; col++) { - float val = rawData[row][col]; - val -= cblacksom[0]; - val *= scale_mul[0]; - rawData[row][col] = (val); + const float val = max(0.f, rawData[row][col] - cblacksom[0]) * scale_mul[0]; + rawData[row][col] = val; tmpchmax = max(tmpchmax, val); } } @@ -3077,12 +2615,9 @@ void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const R for (int row = winy; row < winy + winh; row ++) { for (int col = winx; col < winx + winw; col++) { - float val = rawData[row][col]; - int c = ri->XTRANSFC(row, col); - val -= cblacksom[c]; - val *= scale_mul[c]; - - rawData[row][col] = (val); + const int c = ri->XTRANSFC(row, col); + const float val = max(0.f, rawData[row][col] - cblacksom[c]) * scale_mul[c]; + rawData[row][col] = val; tmpchmax[c] = max(tmpchmax[c], val); } } @@ -3111,10 +2646,8 @@ void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const R { for (int col = winx; col < winx + winw; col++) { for (int c = 0; c < 3; c++) { // three colors, 0=R, 1=G, 2=B - float val = rawData[row][3 * col + c]; - val -= cblacksom[c]; - val *= scale_mul[c]; - rawData[row][3 * col + c] = (val); + const float val = max(0.f, rawData[row][3 * col + c] - cblacksom[c]) * scale_mul[c]; + rawData[row][3 * col + c] = val; tmpchmax[c] = max(tmpchmax[c], val); } } @@ -3388,7 +2921,7 @@ lab2ProphotoRgbD50(float L, float A, float B, float& r, float& g, float& b) float X; float Y; float Z; -#define CLIP01(a) ((a)>0?((a)<1?(a):1):0) + { // convert from Lab to XYZ float x, y, z, fx, fy, fz; @@ -3423,9 +2956,6 @@ lab2ProphotoRgbD50(float L, float A, float B, float& r, float& g, float& b) r = prophoto_xyz[0][0] * X + prophoto_xyz[0][1] * Y + prophoto_xyz[0][2] * Z; g = prophoto_xyz[1][0] * X + prophoto_xyz[1][1] * Y + prophoto_xyz[1][2] * Z; b = prophoto_xyz[2][0] * X + prophoto_xyz[2][1] * Y + prophoto_xyz[2][2] * Z; - // r = CLIP01(r); - // g = CLIP01(g); - // b = CLIP01(b); } // Converts raw image including ICC input profile to working space - floating point version @@ -4939,9 +4469,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 11626cc76..b514b24a3 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.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 @@ -23,19 +23,21 @@ #include #include "array2D.h" -#include "color.h" -#include "curves.h" -#include "dcp.h" +#include "colortemp.h" #include "iimage.h" #include "imagesource.h" -#include "pixelsmap.h" #define HR_SCALE 2 namespace rtengine { +class PixelsMap; +class RawImage; +class DiagonalCurve; +class RetinextransmissionCurve; +class RetinexgaintransmissionCurve; -class RawImageSource : public ImageSource +class RawImageSource final : public ImageSource { private: static DiagonalCurve *phaseOneIccCurve; @@ -74,13 +76,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; @@ -88,6 +90,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]; @@ -101,11 +109,8 @@ protected: void transformRect(const PreviewProps &pp, int tran, int &sx1, int &sy1, int &width, int &height, int &fw); void transformPosition(int x, int y, int tran, int& tx, int& ty); - unsigned FC(int row, int col) const - { - return ri->FC(row, col); - } - inline void getRowStartEnd(int x, int &start, int &end); + unsigned FC(int row, int col) const; + inline void getRowStartEnd (int x, int &start, int &end); static void getProfilePreprocParams(cmsHPROFILE in, float& gammafac, float& lineFac, float& lineSum); public: @@ -116,15 +121,14 @@ public: 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 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) override; + bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const procparams::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; void flushRawData () override; void flushRGB () override; void HLRecovery_Global (const procparams::ToneCurveParams &hrp) override; - void refinement_lassus (int PassCount); void refinement(int PassCount); void setBorder(unsigned int rawBorder) override {border = rawBorder;} bool isRGBSourceModified() const override @@ -132,21 +136,14 @@ public: return rgbSourceModified; // tracks whether cached rgb output of demosaic has been modified } - void processFlatField(const RAWParams &raw, RawImage *riFlatFile, unsigned short black[4]); - void copyOriginalPixels(const RAWParams &raw, RawImage *ri, RawImage *riDark, RawImage *riFlatFile, array2D &rawData); - void cfaboxblur(RawImage *riFlatFile, float* cfablur, int boxH, int boxW); - void scaleColors(int winx, int winy, int winw, int winh, const RAWParams &raw, array2D &rawData); // raw for cblack + void processFlatField(const procparams::RAWParams &raw, const RawImage *riFlatFile, const float black[4]); + void copyOriginalPixels(const procparams::RAWParams &raw, RawImage *ri, RawImage *riDark, RawImage *riFlatFile, array2D &rawData ); + void scaleColors (int winx, int winy, int winw, int winh, const procparams::RAWParams &raw, array2D &rawData); // raw for cblack void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw) override; - eSensorType getSensorType () const override - { - return ri != nullptr ? ri->getSensorType() : ST_NONE; - } - bool isMono () const override - { - return ri->get_colors() == 1; - } - ColorTemp getWB () const override + eSensorType getSensorType () const override; + bool isMono () const override; + ColorTemp getWB () const override { return camera_wb; } @@ -164,10 +161,7 @@ public: void getFullSize (int& w, int& h, int tr = TR_NONE) override; void getSize (const PreviewProps &pp, int& w, int& h) override; - int getRotateDegree() const override - { - return ri->get_rotateDegree(); - } + int getRotateDegree() const override; ImageMatrices* getImageMatrices () override { @@ -185,17 +179,17 @@ public: void getAutoExpHistogram (LUTu & histogram, int& histcompr) override; void getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw) override; void getAutoMatchedToneCurve(const procparams::ColorManagementParams &cp, std::vector &outCurve) override; - DCPProfile *getDCP(const procparams::ColorManagementParams &cmp, DCPProfile::ApplyState &as) override; + DCPProfile *getDCP(const procparams::ColorManagementParams &cmp, DCPProfileApplyState &as) override; void convertColorSpace(Imagefloat* image, const procparams::ColorManagementParams &cmp, const ColorTemp &wb) override; static bool findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in); - static void colorSpaceConversion(Imagefloat* im, const ColorManagementParams& cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName) + static void colorSpaceConversion(Imagefloat* im, const procparams::ColorManagementParams& cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName) { colorSpaceConversion_(im, cmp, wb, pre_mul, embedded, camprofile, cam, camName); } static void inverse33(const double (*coeff)[3], double (*icoeff)[3]); - 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 MSR(float** luminance, float **originalLuminance, float **exLuminance, const LUTf& mapcurve, bool mapcontlutili, int width, int height, const procparams::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); static void HLRecovery_CIELab (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval, double cam[3][3], double icam[3][3]); @@ -271,18 +265,15 @@ protected: void eahd_demosaic(); void hphd_demosaic(); void vng4_demosaic(const array2D &rawData, array2D &red, array2D &green, array2D &blue); - void ppg_demosaic(); - void jdl_interpolate_omp(); void igv_interpolate(int winw, int winh); - void lmmse_interpolate_omp(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations); + void lmmse_interpolate_omp(int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations); void amaze_demosaic_RT(int winx, int winy, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, size_t chunkSize = 1, bool measure = false);//Emil's code for AMaZE - void dual_demosaic_RT(bool isBayer, const RAWParams &raw, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, double &contrast, bool autoContrast = false); + void dual_demosaic_RT(bool isBayer, const procparams::RAWParams &raw, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, double &contrast, bool autoContrast = false); void fast_demosaic();//Emil's code for fast demosaicing void dcb_demosaic(int iterations, bool dcb_enhance); void ahd_demosaic(); void rcd_demosaic(size_t chunkSize = 1, bool measure = false); - void border_interpolate(unsigned int border, float (*image)[4], unsigned int start = 0, unsigned int end = 0); - void border_interpolate2(int winw, int winh, int lborders, const array2D &rawData, array2D &red, array2D &green, array2D &blue); + void border_interpolate(int winw, int winh, int lborders, const array2D &rawData, array2D &red, array2D &green, array2D &blue); void dcb_initTileLimits(int &colMin, int &rowMin, int &colMax, int &rowMax, int x0, int y0, int border); void fill_raw(float (*cache)[3], int x0, int y0, float** rawData); void fill_border(float (*cache)[3], int border, int x0, int y0); @@ -301,11 +292,11 @@ protected: void xtransborder_interpolate (int border, array2D &red, array2D &green, array2D &blue); void xtrans_interpolate (const int passes, const bool useCieLab, size_t chunkSize = 1, bool measure = false); void fast_xtrans_interpolate (const array2D &rawData, array2D &red, array2D &green, array2D &blue); - void pixelshift(int winx, int winy, int winw, int winh, const RAWParams &rawParams, unsigned int frame, const std::string &make, const std::string &model, float rawWpCorrection); + void pixelshift(int winx, int winy, int winw, int winh, const procparams::RAWParams &rawParams, unsigned int frame, const std::string &make, const std::string &model, float rawWpCorrection); 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; }; } diff --git a/rtengine/rawimagesource_i.h b/rtengine/rawimagesource_i.h index b24115e0a..9dfc87985 100644 --- a/rtengine/rawimagesource_i.h +++ b/rtengine/rawimagesource_i.h @@ -14,11 +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 RAWIMAGESOURCE_I_H_INCLUDED -#define RAWIMAGESOURCE_I_H_INCLUDED +#pragma once #include "rawimagesource.h" @@ -92,7 +90,7 @@ inline void RawImageSource::interpolate_row_rb_mul_pp (const array2D &raw } b = g_mul * cg[j] + b / std::max(1, n); - ab[jx] = b; + ab[jx] = std::max(0.f, b); } else { // linear R-G interp. horizontally float r; @@ -105,7 +103,7 @@ inline void RawImageSource::interpolate_row_rb_mul_pp (const array2D &raw r = g_mul * cg[j] + (r_mul * rawData[i][j - 1] - g_mul * cg[j - 1] + r_mul * rawData[i][j + 1] - g_mul * cg[j + 1]) / 2; } - ar[jx] = r; + ar[jx] = std::max(0.f, r); // linear B-G interp. vertically float b; @@ -117,7 +115,7 @@ inline void RawImageSource::interpolate_row_rb_mul_pp (const array2D &raw b = g_mul * cg[j] + (b_mul * rawData[i - 1][j] - g_mul * pg[j] + b_mul * rawData[i + 1][j] - g_mul * ng[j]) / 2; } - ab[jx] = b; + ab[jx] = std::max(0.f, b); } } } else if(pg && ng) { @@ -152,7 +150,7 @@ inline void RawImageSource::interpolate_row_rb_mul_pp (const array2D &raw r = g_mul * cg[j] + r / std::max(n, 1); - ar[jx] = r; + ar[jx] = std::max(0.f, r); } else { // linear B-G interp. horizontally float b; @@ -165,7 +163,7 @@ inline void RawImageSource::interpolate_row_rb_mul_pp (const array2D &raw b = g_mul * cg[j] + (b_mul * rawData[i][j - 1] - g_mul * cg[j - 1] + b_mul * rawData[i][j + 1] - g_mul * cg[j + 1]) / 2; } - ab[jx] = b; + ab[jx] = std::max(0.f, b); // linear R-G interp. vertically float r; @@ -177,12 +175,10 @@ inline void RawImageSource::interpolate_row_rb_mul_pp (const array2D &raw r = g_mul * cg[j] + (r_mul * rawData[i - 1][j] - g_mul * pg[j] + r_mul * rawData[i + 1][j] - g_mul * ng[j]) / 2; } - ar[jx] = r; + ar[jx] = std::max(0.f, r); } } } } } - -#endif diff --git a/rtengine/rawmetadatalocation.h b/rtengine/rawmetadatalocation.h index de6c6a0d7..894bc6bd2 100644 --- a/rtengine/rawmetadatalocation.h +++ b/rtengine/rawmetadatalocation.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 _RAWMETADATALOCATION_ -#define _RAWMETADATALOCATION_ +#pragma once namespace rtengine { @@ -36,6 +35,3 @@ public: }; } - -#endif - diff --git a/rtengine/rcd_demosaic.cc b/rtengine/rcd_demosaic.cc index 904daea71..5a86aec40 100644 --- a/rtengine/rcd_demosaic.cc +++ b/rtengine/rcd_demosaic.cc @@ -14,19 +14,25 @@ * GNU General Public License for more details. * * 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 "rawimagesource.h" #include "rt_math.h" -#include "procparams.h" #include "../rtgui/multilangmgr.h" #include "opthelper.h" #include "StopWatch.h" using namespace std; +namespace +{ +unsigned fc(const unsigned int cfa[2][2], int r, int c) { + return cfa[r & 1][c & 1]; +} +} + namespace rtengine { @@ -49,13 +55,14 @@ 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); } + const unsigned int cfarray[2][2] = {{FC(0,0), FC(0,1)}, {FC(1,0), FC(1,1)}}; constexpr int rcdBorder = 9; constexpr int tileSize = 214; constexpr int tileSizeN = tileSize - 2 * rcdBorder; @@ -98,8 +105,8 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure) for (int row = rowStart; row < rowEnd; row++) { int indx = (row - rowStart) * tileSize; - int c0 = FC(row, colStart); - int c1 = FC(row, colStart + 1); + int c0 = fc(cfarray, row, colStart); + int c1 = fc(cfarray, row, colStart + 1); int col = colStart; for (; col < colEnd - 1; col+=2, indx+=2) { @@ -132,7 +139,7 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure) // Step 2.1: Low pass filter incorporating green, red and blue local samples from the raw data for (int row = 2; row < tileRows - 2; row++) { - for (int col = 2 + (FC(row, 0) & 1), indx = row * tileSize + col; col < tilecols - 2; col += 2, indx += 2) { + for (int col = 2 + (fc(cfarray, row, 0) & 1), indx = row * tileSize + col; col < tilecols - 2; col += 2, indx += 2) { lpf[indx>>1] = 0.25f * cfa[indx] + 0.125f * (cfa[indx - w1] + cfa[indx + w1] + cfa[indx - 1] + cfa[indx + 1]) + 0.0625f * (cfa[indx - w1 - 1] + cfa[indx - w1 + 1] + cfa[indx + w1 - 1] + cfa[indx + w1 + 1]); } } @@ -142,7 +149,7 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure) */ // Step 3.1: Populate the green channel at blue and red CFA positions for (int row = 4; row < tileRows - 4; row++) { - for (int col = 4 + (FC(row, 0) & 1), indx = row * tileSize + col; col < tilecols - 4; col += 2, indx += 2) { + for (int col = 4 + (fc(cfarray, row, 0) & 1), indx = row * tileSize + col; col < tilecols - 4; col += 2, indx += 2) { // Refined vertical and horizontal local discrimination float VH_Central_Value = VH_Dir[indx]; @@ -177,7 +184,7 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure) // Step 4.1: Calculate P/Q diagonal local discrimination for (int row = rcdBorder - 4; row < tileRows - rcdBorder + 4; row++) { - for (int col = rcdBorder - 4 + (FC(row, rcdBorder) & 1), indx = row * tileSize + col; col < tilecols - rcdBorder + 4; col += 2, indx += 2) { + for (int col = rcdBorder - 4 + (fc(cfarray, row, rcdBorder) & 1), indx = row * tileSize + col; col < tilecols - rcdBorder + 4; col += 2, indx += 2) { const float cfai = cfa[indx]; float P_Stat = max(epssq, - 18.f * cfai * (cfa[indx - w1 - 1] + cfa[indx + w1 + 1] + 2.f * (cfa[indx - w2 - 2] + cfa[indx + w2 + 2]) - cfa[indx - w3 - 3] - cfa[indx + w3 + 3]) - 2.f * cfai * (cfa[indx - w4 - 4] + cfa[indx + w4 + 4] - 19.f * cfai) - cfa[indx - w1 - 1] * (70.f * cfa[indx + w1 + 1] - 12.f * cfa[indx - w2 - 2] + 24.f * cfa[indx + w2 + 2] - 38.f * cfa[indx - w3 - 3] + 16.f * cfa[indx + w3 + 3] + 12.f * cfa[indx - w4 - 4] - 6.f * cfa[indx + w4 + 4] + 46.f * cfa[indx - w1 - 1]) + cfa[indx + w1 + 1] * (24.f * cfa[indx - w2 - 2] - 12.f * cfa[indx + w2 + 2] + 16.f * cfa[indx - w3 - 3] - 38.f * cfa[indx + w3 + 3] - 6.f * cfa[indx - w4 - 4] + 12.f * cfa[indx + w4 + 4] + 46.f * cfa[indx + w1 + 1]) + cfa[indx - w2 - 2] * (14.f * cfa[indx + w2 + 2] - 12.f * cfa[indx + w3 + 3] - 2.f * (cfa[indx - w4 - 4] - cfa[indx + w4 + 4]) + 11.f * cfa[indx - w2 - 2]) - cfa[indx + w2 + 2] * (12.f * cfa[indx - w3 - 3] + 2.f * (cfa[indx - w4 - 4] - cfa[indx + w4 + 4]) + 11.f * cfa[indx + w2 + 2]) + cfa[indx - w3 - 3] * (2.f * cfa[indx + w3 + 3] - 6.f * cfa[indx - w4 - 4] + 10.f * cfa[indx - w3 - 3]) - cfa[indx + w3 + 3] * (6.f * cfa[indx + w4 + 4] + 10.f * cfa[indx + w3 + 3]) + cfa[indx - w4 - 4] * cfa[indx - w4 - 4] + cfa[indx + w4 + 4] * cfa[indx + w4 + 4]); @@ -190,7 +197,7 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure) // Step 4.2: Populate the red and blue channels at blue and red CFA positions for (int row = rcdBorder - 3; row < tileRows - rcdBorder + 3; row++) { - for (int col = rcdBorder - 3 + (FC(row, rcdBorder - 1) & 1), indx = row * tileSize + col, c = 2 - FC(row, col); col < tilecols - rcdBorder + 3; col += 2, indx += 2) { + for (int col = rcdBorder - 3 + (fc(cfarray, row, rcdBorder - 1) & 1), indx = row * tileSize + col, c = 2 - fc(cfarray, row, col); col < tilecols - rcdBorder + 3; col += 2, indx += 2) { // Refined P/Q diagonal local discrimination float PQ_Central_Value = PQ_Dir[indx]; @@ -222,7 +229,7 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure) // Step 4.3: Populate the red and blue channels at green CFA positions for (int row = rcdBorder; row < tileRows - rcdBorder; row++) { - for (int col = rcdBorder + (FC(row, rcdBorder - 1) & 1), indx = row * tileSize + col; col < tilecols - rcdBorder; col += 2, indx += 2) { + for (int col = rcdBorder + (fc(cfarray, row, rcdBorder - 1) & 1), indx = row * tileSize + col; col < tilecols - rcdBorder; col += 2, indx += 2) { // Refined vertical and horizontal local discrimination float VH_Central_Value = VH_Dir[indx]; @@ -268,9 +275,9 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure) for (int row = rowStart + rcdBorder; row < rowEnd - rcdBorder; ++row) { for (int col = colStart + rcdBorder; col < colEnd - rcdBorder; ++col) { int idx = (row - rowStart) * tileSize + col - colStart ; - red[row][col] = CLIP(rgb[0][idx] * 65535.f); - green[row][col] = CLIP(rgb[1][idx] * 65535.f); - blue[row][col] = CLIP(rgb[2][idx] * 65535.f); + red[row][col] = std::max(0.f, rgb[0][idx] * 65535.f); + green[row][col] = std::max(0.f, rgb[1][idx] * 65535.f); + blue[row][col] = std::max(0.f, rgb[2][idx] * 65535.f); } } @@ -297,7 +304,7 @@ void RawImageSource::rcd_demosaic(size_t chunkSize, bool measure) free(PQ_Dir); } - border_interpolate2(W, H, rcdBorder, rawData, red, green, blue); + border_interpolate(W, H, rcdBorder, rawData, red, green, blue); if (plistener) { plistener->setProgress(1); diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index ab699f7e5..b9073d880 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" @@ -520,8 +520,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = { ALLNORAW, // EvWBEnabled RGBCURVE, // EvRGBEnabled LUMINANCECURVE, // EvLEnabled - 0, // unused - LUMINANCECURVE, // EvLocallabSpotCreated + DEMOSAIC, // EvPdShrEnabled + CAPTURESHARPEN, // EvPdShrMaskToggled LUMINANCECURVE, // EvLocallabSpotDeleted M_VOID, // EvLocallabSpotSelected M_VOID, // EvLocallabSpotName @@ -745,8 +745,200 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, // EvlocallablocalcontMethod LUMINANCECURVE, // Evlocallabwavcurve LUMINANCECURVE, // Evlocallablevelwav - LUMINANCECURVE // Evlocallabresidcont - + LUMINANCECURVE, // Evlocallabresidcont + LUMINANCECURVE, // EvlocallabCCmaskblshape + LUMINANCECURVE, // EvlocallabLLmaskblshape + LUMINANCECURVE, // EvlocallabHHmaskblshape + LUMINANCECURVE, // EvLocallabEnablMask + LUMINANCECURVE, // EvlocallabshowmaskblMethod + LUMINANCECURVE, // Evlocallabblendmaskbl + LUMINANCECURVE, // Evlocallabradmaskbl + LUMINANCECURVE, // Evlocallabchromaskbl + LUMINANCECURVE, // Evlocallabgammaskbl + LUMINANCECURVE, // Evlocallabslomaskbl + LUMINANCECURVE, // EvlocallabblMethod + LUMINANCECURVE, // EvlocallabmedMethod + LUMINANCECURVE, // Evlocallabitera + LUMINANCECURVE, // Evlocallabguidbl + LUMINANCECURVE, // Evlocallabepsbl + LUMINANCECURVE, // EvlocallabshowmaskcolMethodinv + LUMINANCECURVE, // EvlocallabshowmaskexpMethodinv + LUMINANCECURVE, // EvlocallabshowmaskSHMethodinv + LUMINANCECURVE, // Evlocallabclarilres + LUMINANCECURVE, // Evlocallabclarisoft + LUMINANCECURVE, // Evlocallabclaricres + LUMINANCECURVE, // Evlocallabresidchro + LUMINANCECURVE, // Evlocallabgamm + LUMINANCECURVE, // Evlocallabfatamount + LUMINANCECURVE, // Evlocallabfatdetail + LUMINANCECURVE, // Evlocallabfatanchor + LUMINANCECURVE, // Evlocallabfatlevel + LUMINANCECURVE, // EvlocallabSpotCreated + LUMINANCECURVE, // EvlocallabexnoiseMethod + LUMINANCECURVE, // Evlocallabdepth + LUMINANCECURVE, // Evlocallabloglin + LUMINANCECURVE, // Evlocallablumonly + LUMINANCECURVE, // Evlocallaboffs + LUMINANCECURVE, // EvlocallabCTtransCurve + LUMINANCECURVE, // Evlocallabcliptm + LUMINANCECURVE, // Evlocallabenatmmaskaft + LUMINANCECURVE, // EvlocallabenaExpmaskaft + LUMINANCECURVE, // Evlocallablapmasktm + LUMINANCECURVE, // Evlocallablapmaskreti + LUMINANCECURVE, // Evlocallablapmaskexp + LUMINANCECURVE, // Evlocallablapmaskcol + LUMINANCECURVE, // EvlocallablapmaskSH + LUMINANCECURVE, // Evlocallablapmaskcb + LUMINANCECURVE, // Evlocallablapmaskbl + LUMINANCECURVE, // Evlocallablaplac + LUMINANCECURVE, // Evlocallabdetailthr + LUMINANCECURVE, // Evlocallabfftwbl + LUMINANCECURVE, // Evlocallabisogr + LUMINANCECURVE, // Evlocallabstrengr + LUMINANCECURVE, // Evlocallabscalegr + LUMINANCECURVE, // EvlocallabLmaskshape + LUMINANCECURVE, // EvlocallabLmaskexpshape + LUMINANCECURVE, // EvlocallabLmaskSHshape + LUMINANCECURVE, // EvlocallabLmasktmshape + LUMINANCECURVE, // EvlocallabLmaskretishape + LUMINANCECURVE, // EvlocallabLmaskcbshape + LUMINANCECURVE, // EvlocallabLmaskblshape + LUMINANCECURVE, // EvlocallabLLmaskblshapewav + LUMINANCECURVE, // Evlocallabshadmaskbl + LUMINANCECURVE, // EvlocallabLLmaskcolshapewav + LUMINANCECURVE, // Evlocallabshadmaskcol + LUMINANCECURVE, // EvlocallabcsThreshold + LUMINANCECURVE, // EvlocallabcsThresholdblur + LUMINANCECURVE, // EvlocallabcsThresholdcol + LUMINANCECURVE, // Evlocallabdeltae + LUMINANCECURVE, // EvLocallabSpotscopemask + LUMINANCECURVE, // EvlocallabshMethod + LUMINANCECURVE, // EvlocallabEqualizersh + LUMINANCECURVE, // EvlocallabdetailSH + LUMINANCECURVE, // EvlocallabfatamountSH + LUMINANCECURVE, // EvlocallabfatanchorSH + LUMINANCECURVE, // Evlocallabshortc + LUMINANCECURVE, // EvLocallabSpotlumask + LUMINANCECURVE, // EvlocallabgamSH + LUMINANCECURVE, // EvlocallabsloSH + LUMINANCECURVE, // Evlocallabsavrest + LUMINANCECURVE, // Evlocallabrecurs + LUMINANCECURVE, // EvLocallabmergecolMethod + LUMINANCECURVE, // EvLocallabopacol + LUMINANCECURVE, // Evlocallabrgbshape + LUMINANCECURVE, // EvLocallabtoneMethod + LUMINANCECURVE, // EvLocallabspecial + LUMINANCECURVE, // EvLocallabconthrcol + LUMINANCECURVE, // EvLocallabmerMethod + LUMINANCECURVE, // EvLocallabstrumaskcol + LUMINANCECURVE, // EvLocallabstrumaskbl + LUMINANCECURVE, // EvLocallabtoolcol + LUMINANCECURVE, // Evlocallabtoolbl + LUMINANCECURVE, // EvlocallabHHhmaskshape + LUMINANCECURVE, // EvlocallabCCmaskvibshape + LUMINANCECURVE, // EvlocallabLLmaskvibshape + LUMINANCECURVE, // EvlocallabHHmaskvibshape + LUMINANCECURVE, // EvlocallabshowmaskvibMethod + LUMINANCECURVE, // EvLocallabEnavibMask + LUMINANCECURVE, // Evlocallabblendmaskvi + LUMINANCECURVE, // Evlocallabradmaskvib + LUMINANCECURVE, // Evlocallabchromaskvib + LUMINANCECURVE, // Evlocallabgammaskvib + LUMINANCECURVE, // Evlocallabslomaskvib + LUMINANCECURVE, // Evlocallablapmaskvib + LUMINANCECURVE, // EvlocallabLmaskvibshape + LUMINANCECURVE, // EvLocallabLabGridmergValue + LUMINANCECURVE, // EvLocallabmercol + LUMINANCECURVE, // EvLocallabmerlucol + LUMINANCECURVE, // Evlocallabstrmaskexp + LUMINANCECURVE, // Evlocallabangmaskexp + LUMINANCECURVE, // Evlocallabstrexp + LUMINANCECURVE, // Evlocallabangexp + LUMINANCECURVE, // EvlocallabstrSH + LUMINANCECURVE, // EvlocallabangSH + LUMINANCECURVE, // Evlocallabstrcol + LUMINANCECURVE, // Evlocallabangcol + LUMINANCECURVE, // Evlocallabstrcolab + LUMINANCECURVE, // EvLocallabSpotfeather + LUMINANCECURVE, // Evlocallabstrcolh + LUMINANCECURVE, // Evlocallabstrvib + LUMINANCECURVE, // Evlocallabangvib + LUMINANCECURVE, // Evlocallabstrvibab + LUMINANCECURVE, // Evlocallabstrvibh + LUMINANCECURVE, // EvLocallabSpotcomplexMethod + LUMINANCECURVE, // Evlocallabclshape + LUMINANCECURVE, // Evlocallablcshape + LUMINANCECURVE, // Evlocallabblurcol + LUMINANCECURVE, // Evlocallabcontcol + LUMINANCECURVE, // EvLocallabfftColorMask + RGBCURVE | M_AUTOEXP, // EvLocenalog + AUTOEXP, // EvLocallabAuto + LUMINANCECURVE, // EvlocallabsourceGray + AUTOEXP, // EvlocallabsourceGrayAuto + AUTOEXP, // EvlocallabAutoGray + LUMINANCECURVE, // EvlocallabblackEv + LUMINANCECURVE, // EvlocallabwhiteEv + LUMINANCECURVE, // EvlocallabtargetGray + LUMINANCECURVE, // Evlocallabdetail + LUMINANCECURVE, // Evlocallabsensilog + AUTOEXP, // Evlocallabfullimage + LUMINANCECURVE, // Evlocallabbaselog + LUMINANCECURVE, // Evlocallabresidblur + LUMINANCECURVE, // Evlocallabblurlc + LUMINANCECURVE, // Evlocallablevelblur + LUMINANCECURVE, // EvlocallabwavCurvelev + LUMINANCECURVE, // EvlocallabwavCurvecon + LUMINANCECURVE, // Evlocallabsigma + LUMINANCECURVE, // Evlocallaboriglc + LUMINANCECURVE, // Evlocallabfatdet + LUMINANCECURVE, // Evlocallabfatanch + LUMINANCECURVE, // EvlocallabwavCurvecomp + LUMINANCECURVE, // Evlocallabfatres + LUMINANCECURVE, // EvLocallabSpotbalanh + LUMINANCECURVE, // EvlocallabwavCurveden + LUMINANCECURVE, // EvlocallabHHmasklcshape + LUMINANCECURVE, // EvlocallabCCmasklcshape + LUMINANCECURVE, // EvlocallabLLmasklcshape + LUMINANCECURVE, // EvlocallabEnalcMask + LUMINANCECURVE, // EvlocallabshowmasklcMethod + LUMINANCECURVE, // Evlocallabblendmasklc + LUMINANCECURVE, // Evlocallabradmasklc + LUMINANCECURVE, // Evlocallabchromasklc + LUMINANCECURVE, // EvlocallabLmasklcshape + LUMINANCECURVE, // Evlocallabchromalev + LUMINANCECURVE, // Evlocallabchromablu + LUMINANCECURVE, // Evlocallaboffset + LUMINANCECURVE, // Evlocallabwavblur + LUMINANCECURVE, // Evlocallabwavcont + LUMINANCECURVE, // Evlocallabwavcomp + LUMINANCECURVE, // Evlocallabwavcompre + LUMINANCECURVE, // EvlocallabwavCurvecompre + LUMINANCECURVE, // Evlocallabresidcomp + LUMINANCECURVE, // Evlocallabthreswav + LUMINANCECURVE, // Evlocallabstrwav + LUMINANCECURVE, // Evlocallabangwav + LUMINANCECURVE, // Evlocallabwavgradl + LUMINANCECURVE, // Evlocallabstrlog + LUMINANCECURVE, // Evlocallabanglog + LUMINANCECURVE, // EvLocallabSpotcolorde + LUMINANCECURVE, // EvlocallabshowmasksharMethod + LUMINANCECURVE, // Evlocallabshowreset + LUMINANCECURVE, // Evlocallabstrengthw + LUMINANCECURVE, // Evlocallabradiusw + LUMINANCECURVE, // Evlocallabdetailw + LUMINANCECURVE, // Evlocallabgradw + LUMINANCECURVE, // Evlocallabtloww + LUMINANCECURVE, // Evlocallabthigw + LUMINANCECURVE, // EvlocallabwavCurveedg + LUMINANCECURVE, // EvlocallablocaledgMethod + LUMINANCECURVE, // Evlocallabwavedg + LUMINANCECURVE, // Evlocallabedgw + LUMINANCECURVE, // Evlocallabbasew + LUMINANCECURVE, // EvlocallablocalneiMethod + LUMINANCECURVE, // Evlocallabwaveshow + LUMINANCECURVE, // EvLocallabSpotwavMethod + LUMINANCECURVE, // EvlocallabchroMethod + LUMINANCECURVE // Evlocallabstrbl }; diff --git a/rtengine/refreshmap.h b/rtengine/refreshmap.h index b9ccc2b65..0f3e5ee90 100644 --- a/rtengine/refreshmap.h +++ b/rtengine/refreshmap.h @@ -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 . */ -#ifndef __REFRESHMAP__ -#define __REFRESHMAP__ +#pragma once #include + #include "procevents.h" // Use M_VOID if you wish to update the proc params without updating the preview at all ! @@ -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) @@ -78,7 +80,8 @@ extern int refreshmap[]; -namespace rtengine { +namespace rtengine +{ class RefreshMapper { public: @@ -95,5 +98,3 @@ private: }; } // namespace rtengine - -#endif diff --git a/rtengine/rescale.h b/rtengine/rescale.h index ba9a01c99..2138cd8e8 100644 --- a/rtengine/rescale.h +++ b/rtengine/rescale.h @@ -15,14 +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 "array2D.h" +#include "rt_math.h" -namespace rtengine { +template +class array2D; + + +namespace rtengine +{ inline float getBilinearValue(const array2D &src, float x, float y) { @@ -95,5 +100,4 @@ inline void rescaleNearest(const array2D &src, array2D &dst, bool } } - } // namespace rtengine diff --git a/rtengine/rt_algo.cc b/rtengine/rt_algo.cc index 1011ae7b7..a5b48af95 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 @@ -31,7 +31,7 @@ #include "opthelper.h" #include "rt_algo.h" #include "rt_math.h" -#include "sleef.c" +#include "sleef.h" namespace { float calcBlendFactor(float val, float threshold) { @@ -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, bool autoContrast, float ** clipMask) { if (autoContrast) { constexpr float minLuminance = 2000.f; @@ -352,7 +352,7 @@ void buildBlendMask(float** luminance, float **blend, int W, int H, float &contr contrastThreshold = calcContrastThreshold(luminance, minY, minX, tilesize); break; } else { - // in second pass we allow a variance of 4 + // in second pass we allow a variance of 8 // we additionally scan the tiles +-skip pixels around the best tile from pass 2 // Means we scan (2 * skip + 1)^2 tiles in this step to get a better hit rate // fortunately the scan is quite fast, so we use only one core and don't parallelize @@ -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; } } } @@ -403,7 +403,7 @@ void buildBlendMask(float** luminance, float **blend, int W, int H, float &contr if(contrastThreshold == 0.f) { for(int j = 0; j < H; ++j) { for(int i = 0; i < W; ++i) { - blend[j][i] = amount; + blend[j][i] = 1.f; } } } else { @@ -415,7 +415,6 @@ void buildBlendMask(float** luminance, float **blend, int W, int H, float &contr #ifdef __SSE2__ const vfloat contrastThresholdv = F2V(contrastThreshold); const vfloat scalev = F2V(scale); - const vfloat amountv = F2V(amount); #endif #ifdef _OPENMP #pragma omp for schedule(dynamic,16) @@ -424,11 +423,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]) * 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], calcBlendFactor(contrastv, contrastThresholdv)); + } } #endif for(; i < W - 2; ++i) { @@ -436,7 +444,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) * calcBlendFactor(contrast, contrastThreshold); } } @@ -464,8 +472,18 @@ void buildBlendMask(float** luminance, float **blend, int W, int H, float &contr } } +#ifdef __SSE2__ + // flush denormals to zero for gaussian blur to avoid performance penalty if there are a lot of zero values in the mask + const auto oldMode = _MM_GET_FLUSH_ZERO_MODE(); + _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); +#endif + // blur blend mask to smooth transitions gaussianBlur(blend, blend, W, H, 2.0); + +#ifdef __SSE2__ + _MM_SET_FLUSH_ZERO_MODE(oldMode); +#endif } } } diff --git a/rtengine/rt_algo.h b/rtengine/rt_algo.h index a8e2e3e23..a72a7c56b 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,9 @@ 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, bool autoContrast = false, float ** clipmask = nullptr); +// implemented in tmo_fattal02 +void buildGradientsMask(int W, int H, float **luminance, float **out, + float amount, int nlevels, int detail_level, + float alfa, float beta, bool multithread); } diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index dca2fba21..ad97e1b55 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -14,28 +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 . */ #pragma once #include #include #include +#include -#include +#include #include #include "iimage.h" #include "imageformat.h" -#include "LUT.h" #include "procevents.h" #include "rawmetadatalocation.h" -#include "rt_math.h" #include "settings.h" -#include "utils.h" - -#include "../rtexif/rtexif.h" #include "../rtgui/threadutils.h" @@ -46,7 +42,18 @@ * */ +template +class LUT; + +using LUTu = LUT; + class EditDataProvider; +namespace rtexif +{ + +class TagDirectory; + +} namespace rtengine { @@ -376,8 +383,21 @@ public: double chromar; }; + struct locallabRetiMinMax { + double cdma; + double cdmin; + double mini; + double maxi; + double Tmean; + double Tsigma; + double Tmin; + double Tmax; + }; + virtual ~LocallabListener() = default; virtual void refChanged(const std::vector &ref, int selspot) = 0; + virtual void minmaxChanged(const std::vector &minmax, int selspot) = 0; + virtual void logencodChanged(const float blackev, const float whiteev, const float sourceg, const float targetg) = 0; }; class AutoColorTonListener @@ -429,6 +449,13 @@ public : virtual void autoContrastChanged (double autoContrast) = 0; }; +class AutoRadiusListener +{ +public : + virtual ~AutoRadiusListener() = default; + virtual void autoRadiusChanged (double autoRadius) = 0; +}; + class WaveletListener { public: @@ -513,7 +540,7 @@ public: virtual void updateUnLock() = 0; - virtual void setLocallabMaskVisibility(int locallColorMask, int locallExpMask, int locallSHMask, int locallcbMask, int locallretiMask, int locallsoftMask, int localltmMask) = 0; + virtual void setLocallabMaskVisibility(int locallColorMask, int locallColorMaskinv, int locallExpMask, int locallExpMaskinv, int locallSHMask, int locallSHMaskinv, int locallvibMask, int locallsoftMask, int locallblMask, int localltmMask, int locallretiMask, int locallsharMask, int localllcMask, int locallcbMask) = 0; /** Creates and returns a Crop instance that acts as a window on the image * @param editDataProvider pointer to the EditDataProvider that communicates with the EditSubscriber @@ -539,6 +566,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; @@ -552,7 +581,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 () {} @@ -570,7 +599,7 @@ public: * @param baseDir base directory of RT's installation dir * @param userSettingsDir RT's base directory in the user's settings dir * @param loadAll if false, don't load the various dependencies (profiles, HALDClut files, ...), they'll be loaded from disk each time they'll be used (launching time improvement) */ -int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir, bool loadAll = true); +int init (const Settings* s, const Glib::ustring& baseDir, const Glib::ustring& userSettingsDir, bool loadAll = true); /** Cleanup the RT engine (static variables) */ void cleanup (); 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..7ffb9ad33 100644 --- a/rtengine/rtlensfun.cc +++ b/rtengine/rtlensfun.cc @@ -15,17 +15,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 . */ -#include "rtlensfun.h" -#include "procparams.h" -#include "settings.h" #include -namespace rtengine { +#include "imagedata.h" +#include "procparams.h" +#include "rtlensfun.h" +#include "settings.h" -extern const Settings *settings; +namespace rtengine +{ //----------------------------------------------------------------------------- // LFModifier @@ -34,7 +35,6 @@ extern const Settings *settings; LFModifier::~LFModifier() { if (data_) { - MyMutex::MyLock lock(lfModifierMutex); data_->Destroy(); } } @@ -77,11 +77,6 @@ bool LFModifier::isCACorrectionAvailable() const return (flags_ & LF_MODIFY_TCA); } -#ifdef __GNUC__ // silence warning, can be removed when function is implemented -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - void LFModifier::correctCA(double &x, double &y, int cx, int cy, int channel) const { assert(channel >= 0 && channel <= 2); @@ -107,32 +102,46 @@ void LFModifier::correctCA(double &x, double &y, int cx, int cy, int channel) co y -= cy; } -#ifdef __GNUC__ -#pragma GCC diagnostic pop +#ifdef _OPENMP +void LFModifier::processVignette(int width, int height, float** rawData) const +{ + #pragma omp parallel for schedule(dynamic,16) + + for (int y = 0; y < height; ++y) { + data_->ApplyColorModification(rawData[y], 0, y, width, 1, LF_CR_1(INTENSITY), 0); + } +} +#else +void LFModifier::processVignette(int width, int height, float** rawData) const +{ + data_->ApplyColorModification(rawData[0], 0, 0, width, height, LF_CR_1(INTENSITY), width * sizeof(float)); +} + #endif - -void LFModifier::processVignetteLine(int width, int y, float *line) const +#ifdef _OPENMP +void LFModifier::processVignette3Channels(int width, int height, float** rawData) const { - MyMutex::MyLock lock(lfModifierMutex); - data_->ApplyColorModification(line, 0, y, width, 1, LF_CR_1(INTENSITY), 0); + #pragma omp parallel for schedule(dynamic,16) + + for (int y = 0; y < height; ++y) { + data_->ApplyColorModification(rawData[y], 0, y, width, 1, LF_CR_3(RED, GREEN, BLUE), 0); + } +} +#else +void LFModifier::processVignette3Channels(int width, int height, float** rawData) const +{ + data_->ApplyColorModification(rawData[0], 0, 0, width, height, LF_CR_3(RED, GREEN, BLUE), width * 3 * sizeof(float)); } - -void LFModifier::processVignetteLine3Channels(int width, int y, float *line) const -{ - MyMutex::MyLock lock(lfModifierMutex); - data_->ApplyColorModification(line, 0, y, width, 1, LF_CR_3(RED, GREEN, BLUE), 0); -} - - +#endif Glib::ustring LFModifier::getDisplayString() const { if (!data_) { return "NONE"; } else { Glib::ustring ret; - Glib::ustring sep = ""; + Glib::ustring sep; if (flags_ & LF_MODIFY_DISTORTION) { ret += "distortion"; sep = ", "; @@ -499,13 +508,20 @@ std::unique_ptr LFDatabase::getModifier(const LFCamera &camera, cons return ret; } - -std::unique_ptr LFDatabase::findModifier(const LensProfParams &lensProf, const FramesMetaData *idata, int width, int height, const CoarseTransformParams &coarse, int rawRotationDeg) +std::unique_ptr LFDatabase::findModifier( + const procparams::LensProfParams &lensProf, + const FramesMetaData *idata, + int width, + int height, + const procparams::CoarseTransformParams &coarse, + int rawRotationDeg +) const { + const float focallen = idata->getFocalLen(); + Glib::ustring make, model, lens; - float focallen = idata->getFocalLen(); if (lensProf.lfAutoMatch()) { - if (focallen <= 0) { + if (focallen <= 0.f) { return nullptr; } make = idata->getMake(); @@ -516,19 +532,25 @@ std::unique_ptr LFDatabase::findModifier(const LensProfParams &lensP model = lensProf.lfCameraModel; lens = lensProf.lfLens; } + if (make.empty() || model.empty() || lens.empty()) { return nullptr; } - const LFDatabase *db = getInstance(); - LFCamera c = db->findCamera(make, model); - LFLens l = db->findLens(lensProf.lfAutoMatch() ? c : LFCamera(), lens); - if (focallen <= 0 && l.data_ && l.data_->MinFocal == l.data_->MaxFocal) { - focallen = l.data_->MinFocal; - } - if (focallen <= 0) { + const std::string key = (make + model + lens).collate_key(); + if (notFound.find(key) != notFound.end()) { + // This combination was not found => do not search again return nullptr; } + + const LFCamera c = findCamera(make, model); + const LFLens l = findLens( + lensProf.lfAutoMatch() + ? c + : LFCamera(), + lens + ); + bool swap_xy = false; if (rawRotationDeg >= 0) { int rot = (coarse.rotate + rawRotationDeg) % 360; @@ -538,14 +560,28 @@ std::unique_ptr LFDatabase::findModifier(const LensProfParams &lensP } } - std::unique_ptr ret = db->getModifier(c, l, idata->getFocalLen(), idata->getFNumber(), idata->getFocusDist(), width, height, swap_xy); + std::unique_ptr ret = getModifier( + c, + l, + idata->getFocalLen(), + idata->getFNumber(), + idata->getFocusDist(), + width, + height, + swap_xy + ); if (settings->verbose) { std::cout << "LENSFUN:\n" << " camera: " << c.getDisplayString() << "\n" << " lens: " << l.getDisplayString() << "\n" << " correction: " - << (ret ? ret->getDisplayString() : "NONE") << std::endl; + << (ret ? ret->getDisplayString() : "NONE") + << std::endl; + } + + if (!ret) { + notFound.insert(key); } return ret; diff --git a/rtengine/rtlensfun.h b/rtengine/rtlensfun.h index 8b097b30e..2f3e4677d 100644 --- a/rtengine/rtlensfun.h +++ b/rtengine/rtlensfun.h @@ -15,26 +15,31 @@ * GNU General Public License for more details. * * 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 +#include #include -#include +#include #include #include "lcp.h" #include "noncopyable.h" -namespace rtengine { +namespace rtengine +{ + +class FramesMetaData; namespace procparams { +struct CoarseTransformParams; struct LensProfParams; } @@ -51,8 +56,8 @@ public: void correctDistortion(double &x, double &y, int cx, int cy, double scale) const override; bool isCACorrectionAvailable() const override; void correctCA(double &x, double &y, int cx, int cy, int channel) const override; - void processVignetteLine(int width, int y, float *line) const override; - void processVignetteLine3Channels(int width, int y, float *line) const override; + void processVignette(int width, int height, float** rawData) const override; + void processVignette3Channels(int width, int height, float** rawData) const override; Glib::ustring getDisplayString() const; @@ -63,7 +68,6 @@ private: lfModifier *data_; bool swap_xy_; int flags_; - mutable MyMutex lfModifierMutex; }; class LFCamera final @@ -119,7 +123,13 @@ public: LFCamera findCamera(const Glib::ustring &make, const Glib::ustring &model) const; LFLens findLens(const LFCamera &camera, const Glib::ustring &name) const; - static std::unique_ptr findModifier(const procparams::LensProfParams &lensProf, const FramesMetaData *idata, int width, int height, const CoarseTransformParams &coarse, int rawRotationDeg); + std::unique_ptr findModifier( + const procparams::LensProfParams &lensProf, + const FramesMetaData *idata, + int width, int height, + const procparams::CoarseTransformParams &coarse, + int rawRotationDeg + ) const; private: std::unique_ptr getModifier(const LFCamera &camera, const LFLens &lens, @@ -131,6 +141,7 @@ private: mutable MyMutex lfDBMutex; static LFDatabase instance_; lfDatabase *data_; + mutable std::set notFound; }; } // namespace rtengine diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index c366f63c5..8edebb17a 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -14,33 +14,38 @@ * GNU General Public License for more details. * * 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 + +#include +#include +#include + +#include "cieimage.h" +#include "color.h" +#include "colortemp.h" +#include "curves.h" +#include "dcp.h" +#include "iccstore.h" +#include "image8.h" +#include "improcfun.h" +#include "jpeg.h" +#include "labimage.h" +#include "median.h" +#include "procparams.h" +#include "rawimage.h" +#include "rawimagesource.h" #include "rtengine.h" #include "rtthumbnail.h" -#include "../rtgui/options.h" -#include "image8.h" -#include -#include "curves.h" -#include -#include "improcfun.h" -#include "colortemp.h" -#include "mytime.h" -#include "utils.h" -#include "iccstore.h" -#include "iccmatrices.h" -#include "rawimagesource.h" -#include "stdimagesource.h" -#include -#include "rawimage.h" -#include "jpeg.h" -#include "../rtgui/ppversion.h" -#include "improccoordinator.h" #include "settings.h" -#include "procparams.h" -#include +#include "stdimagesource.h" #include "StopWatch.h" -#include "median.h" +#include "utils.h" namespace { @@ -183,13 +188,9 @@ void scale_colors (rtengine::RawImage *ri, float scale_mul[4], float cblack[4], } -extern Options options; - namespace rtengine { -extern const Settings *settings; - using namespace procparams; Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode) @@ -329,7 +330,7 @@ Image8 *load_inspector_mode(const Glib::ustring &fname, RawMetaDataLocation &rml neutral.raw.bayersensor.method = RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::FAST); neutral.raw.xtranssensor.method = RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FAST); neutral.icm.inputProfile = "(camera)"; - neutral.icm.workingProfile = options.rtSettings.srgb; + neutral.icm.workingProfile = settings->srgb; src.preprocess(neutral.raw, neutral.lensProf, neutral.coarse, false); double thresholdDummy = 0.f; @@ -428,7 +429,7 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL // did we succeed? if ( err ) { - if (options.rtSettings.verbose) { + if (settings->verbose) { std::cout << "Could not extract thumb from " << fname.c_str() << std::endl; } delete tpp; @@ -510,8 +511,6 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL ((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==0 || !filter) #define FISGREEN(filter,row,col) \ ((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==1 || !filter) -#define FISBLUE(filter,row,col) \ - ((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==2 || !filter) RawMetaDataLocation Thumbnail::loadMetaDataFromRaw (const Glib::ustring& fname) { @@ -547,6 +546,17 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati 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(); @@ -1225,22 +1235,22 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT ImProcFunctions ipf (¶ms, forHistogramMatching); // enable multithreading when forHistogramMatching is true ipf.setScale (sqrt (double (fw * fw + fh * fh)) / sqrt (double (thumbImg->getWidth() * thumbImg->getWidth() + thumbImg->getHeight() * thumbImg->getHeight()))*scale); - ipf.updateColorProfiles (ICCStore::getInstance()->getDefaultMonitorProfileName(), RenderingIntent(options.rtSettings.monitorIntent), false, false); + ipf.updateColorProfiles (ICCStore::getInstance()->getDefaultMonitorProfileName(), RenderingIntent(settings->monitorIntent), false, false); LUTu hist16 (65536); ipf.firstAnalysis (baseImg, params, hist16); ipf.dehaze(baseImg, params.dehaze); - ipf.ToneMapFattal02(baseImg); + ipf.ToneMapFattal02(baseImg, params.fattal, 3, 0, nullptr, 0, 0, 0); // perform transform - if (ipf.needsTransform()) { + int origFW; + int origFH; + double tscale = 0.0; + getDimensions (origFW, origFH, tscale); + if (ipf.needsTransform(origFW * tscale + 0.5, origFH * tscale + 0.5, 0, metadata)) { Imagefloat* trImg = new Imagefloat (fw, fh); - int origFW; - int origFH; - double tscale = 0.0; - getDimensions (origFW, origFH, tscale); ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, origFW * tscale + 0.5, origFH * tscale + 0.5, metadata, 0, true); // Raw rotate degree not detectable here delete baseImg; baseImg = trImg; @@ -1352,7 +1362,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT LabImage* labView = new LabImage (fw, fh); DCPProfile *dcpProf = nullptr; - DCPProfile::ApplyState as; + DCPProfileApplyState as; if (isRaw) { cmsHPROFILE dummy; @@ -1481,19 +1491,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; } @@ -2113,11 +2126,11 @@ bool Thumbnail::readData (const Glib::ustring& fname) return true; } catch (Glib::Error &err) { - if (options.rtSettings.verbose) { + if (settings->verbose) { printf ("Thumbnail::readData / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str()); } } catch (...) { - if (options.rtSettings.verbose) { + if (settings->verbose) { printf ("Thumbnail::readData / Unknown exception while trying to load \"%s\"!\n", fname.c_str()); } } @@ -2164,11 +2177,11 @@ bool Thumbnail::writeData (const Glib::ustring& fname) keyData = keyFile.to_data (); } catch (Glib::Error& err) { - if (options.rtSettings.verbose) { + if (settings->verbose) { printf ("Thumbnail::writeData / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str()); } } catch (...) { - if (options.rtSettings.verbose) { + if (settings->verbose) { printf ("Thumbnail::writeData / Unknown exception while trying to save \"%s\"!\n", fname.c_str()); } } @@ -2180,7 +2193,7 @@ bool Thumbnail::writeData (const Glib::ustring& fname) FILE *f = g_fopen (fname.c_str (), "wt"); if (!f) { - if (options.rtSettings.verbose) { + if (settings->verbose) { printf ("Thumbnail::writeData / Error: unable to open file \"%s\" with write access!\n", fname.c_str()); } diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h index 09a0510eb..c8d657a62 100644 --- a/rtengine/rtthumbnail.h +++ b/rtengine/rtthumbnail.h @@ -14,19 +14,27 @@ * GNU General Public License for more details. * * 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_ +#pragma once -#include "rawmetadatalocation.h" -#include #include -#include "image8.h" + #include "image16.h" +#include "image8.h" #include "imagefloat.h" +#include "LUT.h" +#include "rawmetadatalocation.h" + #include "../rtgui/threadutils.h" +namespace Glib +{ + +class ustring; + +} + namespace rtengine { @@ -160,6 +168,3 @@ public: } }; } - -#endif - diff --git a/rtengine/satandvalueblendingcurve.h b/rtengine/satandvalueblendingcurve.h new file mode 100644 index 000000000..c610652b4 --- /dev/null +++ b/rtengine/satandvalueblendingcurve.h @@ -0,0 +1,70 @@ +/* + * 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 . + */ +#pragma once + +#include "color.h" +#include "curves.h" + +namespace rtengine +{ + +class SatAndValueBlendingToneCurve : public ToneCurve +{ +public: + void Apply(float& r, float& g, float& b) const; +}; + +// Tone curve modifying the value channel only, preserving hue and saturation +// values in 0xffff space +inline void SatAndValueBlendingToneCurve::Apply (float& ir, float& ig, float& ib) const +{ + + assert (lutToneCurve); + + float r = CLIP(ir); + float g = CLIP(ig); + float b = CLIP(ib); + + const float lum = (r + g + b) / 3.f; + const float newLum = lutToneCurve[lum]; + + if (newLum == lum) { + return; + } + + float h, s, v; + Color::rgb2hsvtc(r, g, b, h, s, v); + + float dV; + if (newLum > lum) { + // Linearly targeting Value = 1 and Saturation = 0 + const float coef = (newLum - lum) / (65535.f - lum); + dV = (1.f - v) * coef; + s *= 1.f - coef; + } else { + // Linearly targeting Value = 0 + const float coef = (newLum - lum) / lum ; + dV = v * coef; + } + Color::hsv2rgbdcp(h, s, v + dV, r, g, b); + + setUnlessOOG(ir, ig, ib, r, g, b); +} + +} diff --git a/rtengine/settings.h b/rtengine/settings.h index de0406060..9ee452321 100644 --- a/rtengine/settings.h +++ b/rtengine/settings.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 _RTSETTINGS_ -#define _RTSETTINGS_ +#pragma once +#include namespace rtengine { @@ -80,6 +80,7 @@ public: // bool bw_complementary; double level0_cbdl; double level123_cbdl; + Glib::ustring lensfunDbDirectory; // The directory containing the lensfun database. If empty, the system defaults will be used, as described in https://lensfun.github.io/manual/latest/dbsearch.html int cropsleep; double reduchigh; double reduclow; @@ -90,7 +91,6 @@ public: // bool showtooltip; - Glib::ustring lensfunDbDirectory; ///< The directory containing the lensfun database. If empty, the system defaults will be used (as described in http://lensfun.sourceforge.net/manual/dbsearch.html) enum class ThumbnailInspectorMode { JPEG, @@ -106,7 +106,5 @@ public: * @param s a pointer to the Settings instance to destroy. */ static void destroy(Settings* s); }; +extern const Settings* settings; } - -#endif - diff --git a/rtengine/shmap.cc b/rtengine/shmap.cc index 1eb911220..abdcc42a4 100644 --- a/rtengine/shmap.cc +++ b/rtengine/shmap.cc @@ -14,13 +14,15 @@ * GNU General Public License for more details. * * 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" +#include "imagefloat.h" #include "rtengine.h" #include "rt_math.h" #include "rawimagesource.h" +#include "sleef.h" #include "jaggedarray.h" #undef THREAD_PRIORITY_NORMAL #include "opthelper.h" @@ -28,8 +30,6 @@ namespace rtengine { -extern const Settings* settings; - SHMap::SHMap (int w, int h) : max_f(0.f), min_f(0.f), avg(0.f), W(w), H(h) { @@ -85,21 +85,14 @@ void SHMap::update (Imagefloat* img, double radius, double lumi[3], bool hq, int if (!hq) { fillLuminance( img, map, lumi); - float *buffer = nullptr; - - if(radius > 40.) { - // When we pass another buffer to gaussianBlur, it will use iterated boxblur which is less prone to artifacts - buffer = new float[W * H]; - } + const bool useBoxBlur = radius > 40.0; // boxblur is less prone to artifacts for large radi #ifdef _OPENMP - #pragma omp parallel + #pragma omp parallel if (!useBoxBlur) #endif { - gaussianBlur (map, map, W, H, radius, buffer); + gaussianBlur (map, map, W, H, radius, useBoxBlur); } - - delete [] buffer; } else { @@ -358,7 +351,7 @@ void SHMap::forceStat (float max_, float min_, float avg_) avg = avg_; } -void SHMap::dirpyr_shmap(float ** data_fine, float ** data_coarse, int width, int height, LUTf & rangefn, int level, int scale) +void SHMap::dirpyr_shmap(float ** data_fine, float ** data_coarse, int width, int height, const LUTf& rangefn, int level, int scale) { //scale is spacing of directional averaging weights diff --git a/rtengine/shmap.h b/rtengine/shmap.h index c51d86dc8..03276276e 100644 --- a/rtengine/shmap.h +++ b/rtengine/shmap.h @@ -14,18 +14,23 @@ * GNU General Public License for more details. * * 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__ +#pragma once -#include "imagefloat.h" -#include "image16.h" #include "noncopyable.h" +template +class LUT; + +using LUTf = LUT; + namespace rtengine { +class Imagefloat; +class LabImage; + class SHMap : public NonCopyable { @@ -48,8 +53,8 @@ private: void fillLuminance( Imagefloat * img, float **luminance, double lumi[3] ); void fillLuminanceL( float ** L, float **luminance ); - void dirpyr_shmap(float ** data_fine, float ** data_coarse, int width, int height, LUTf & rangefn, int level, int scale); + void dirpyr_shmap(float ** data_fine, float ** data_coarse, int width, int height, const LUTf& rangefn, int level, int scale); }; + } -#endif diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index dd9be7d03..c3eda643f 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -14,8 +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 "cieimage.h" +#include "dcp.h" +#include "imagefloat.h" +#include "labimage.h" #include "rtengine.h" #include "colortemp.h" #include "imagesource.h" @@ -25,7 +29,8 @@ #include "clutstore.h" #include "processingjob.h" #include "procparams.h" -#include +#include +#include #include "../rtgui/options.h" #include "rawimagesource.h" #include "../rtgui/multilangmgr.h" @@ -36,7 +41,6 @@ namespace rtengine { -extern const Settings* settings; namespace { @@ -212,7 +216,7 @@ private: imgsrc->preprocess(params.raw, params.lensProf, params.coarse, params.dirpyrDenoise.enabled); // After preprocess, run film negative processing if enabled - if (imgsrc->getSensorType() == ST_BAYER && params.filmNegative.enabled) { + if ((imgsrc->getSensorType() == ST_BAYER || (imgsrc->getSensorType() == ST_FUJI_XTRANS)) && params.filmNegative.enabled) { imgsrc->filmNegativeProcess (params.filmNegative); } @@ -222,7 +226,10 @@ private: 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) { @@ -239,7 +246,6 @@ private: bool dehacontlutili = false; bool mapcontlutili = false; bool useHsl = false; -// multi_array2D conversionBuffer(1, 1); multi_array2D conversionBuffer(1, 1); imgsrc->retinexPrepareBuffers(params.icm, params.retinex, conversionBuffer, dummy); imgsrc->retinexPrepareCurves(params.retinex, cdcurve, mapcurve, dehatransmissionCurve, dehagaintransmissionCurve, dehacontlutili, mapcontlutili, useHsl, dummy, dummy); @@ -799,17 +805,7 @@ private: void stage_denoise() { - procparams::ProcParams& params = job->pparams; - //ImProcFunctions ipf (¶ms, true); - ImProcFunctions &ipf = * (ipf_p.get()); - - // perform luma/chroma denoise -// CieImage *cieView; -// NoisCurve noiseLCurve; -// bool lldenoiseutili=false; -// Imagefloat *calclum ; -// params.dirpyrDenoise.getCurves(noiseLCurve, lldenoiseutili); -// if (params.dirpyrDenoise.enabled && lldenoiseutili) { + const procparams::ProcParams& params = job->pparams; DirPyrDenoiseParams denoiseParams = params.dirpyrDenoise; // make a copy because we cheat here @@ -842,9 +838,7 @@ private: } if (denoiseParams.enabled) { - // CurveFactory::denoiseLL(lldenoiseutili, denoiseParams.lcurve, Noisecurve,1); - //denoiseParams.getCurves(noiseLCurve); -// ipf.RGB_denoise(baseImg, baseImg, calclum, imgsrc->isRAW(), denoiseParams, params.defringe, imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, lldenoiseutili); + ImProcFunctions &ipf = * (ipf_p.get()); float nresi, highresi; int kall = 2; ipf.RGB_denoise(kall, baseImg, baseImg, calclum, ch_M, max_r, max_b, imgsrc->isRAW(), denoiseParams, imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, noiseCCurve, nresi, highresi); @@ -866,7 +860,7 @@ private: void stage_transform() { - procparams::ProcParams& params = job->pparams; + const procparams::ProcParams& params = job->pparams; //ImProcFunctions ipf (¶ms, true); ImProcFunctions &ipf = * (ipf_p.get()); @@ -878,10 +872,10 @@ private: ipf.firstAnalysis(baseImg, params, hist16); ipf.dehaze(baseImg, params.dehaze); - ipf.ToneMapFattal02(baseImg); + ipf.ToneMapFattal02(baseImg, params.fattal, 3, 0, nullptr, 0, 0, 0); // perform transform (excepted resizing) - if (ipf.needsTransform()) { + if (ipf.needsTransform(fw, fh, imgsrc->getRotateDegree(), imgsrc->getMetaData())) { Imagefloat* trImg = nullptr; if (ipf.needsLuminanceOnly()) { @@ -891,7 +885,7 @@ private: } ipf.transform(baseImg, trImg, 0, 0, 0, 0, fw, fh, fw, fh, - imgsrc->getMetaData(), imgsrc->getRotateDegree(), true); + imgsrc->getMetaData(), imgsrc->getRotateDegree(), true, true); if (trImg != baseImg) { delete baseImg; @@ -969,6 +963,7 @@ private: labView = new LabImage(fw, fh); reservView = new LabImage(fw, fh); + lastorigView = new LabImage(fw, fh); if (params.blackwhite.enabled) { CurveFactory::curveBW(params.blackwhite.beforeCurve, params.blackwhite.afterCurve, hist16, dummy, customToneCurvebw1, customToneCurvebw2, 1); @@ -999,8 +994,8 @@ private: } autor = -9000.f; // This will ask to compute the "auto" values for the B&W tool (have to be inferior to -5000) - DCPProfile::ApplyState as; - DCPProfile *dcpProf = imgsrc->getDCP(params.icm, as); + DCPProfileApplyState as; + DCPProfile *dcpProf = imgsrc->getDCP (params.icm, as); LUTu histToneCurve; @@ -1079,6 +1074,7 @@ private: // bool locallutili = false; // bool localcutili = false; reservView->CopyFrom(labView); + lastorigView->CopyFrom(labView); if (params.locallab.enabled) { MyTime t1, t2; @@ -1089,34 +1085,65 @@ private: LUTi centerx(500, -10000); LUTi centery(500, -10000); LocretigainCurve locRETgainCurve; + LocretitransCurve locRETtransCurve; LocLHCurve loclhCurve; LocHHCurve lochhCurve; LocCCmaskCurve locccmasCurve; LocLLmaskCurve locllmasCurve; LocHHmaskCurve lochhmasCurve; - LocCCmaskexpCurve locccmasexpCurve; - LocLLmaskexpCurve locllmasexpCurve; - LocHHmaskexpCurve lochhmasexpCurve; - LocCCmaskSHCurve locccmasSHCurve; - LocLLmaskSHCurve locllmasSHCurve; - LocHHmaskSHCurve lochhmasSHCurve; - LocCCmaskcbCurve locccmascbCurve; - LocLLmaskcbCurve locllmascbCurve; - LocHHmaskcbCurve lochhmascbCurve; - LocCCmaskretiCurve locccmasretiCurve; - LocLLmaskretiCurve locllmasretiCurve; - LocHHmaskretiCurve lochhmasretiCurve; - LocCCmasktmCurve locccmastmCurve; - LocLLmasktmCurve locllmastmCurve; - LocHHmasktmCurve lochhmastmCurve; + LocHHmaskCurve lochhhmasCurve; + LocCCmaskCurve locccmasexpCurve; + LocLLmaskCurve locllmasexpCurve; + LocHHmaskCurve lochhmasexpCurve; + LocCCmaskCurve locccmasSHCurve; + LocLLmaskCurve locllmasSHCurve; + LocHHmaskCurve lochhmasSHCurve; + LocCCmaskCurve locccmasvibCurve; + LocLLmaskCurve locllmasvibCurve; + LocHHmaskCurve lochhmasvibCurve; + LocCCmaskCurve locccmaslcCurve; + LocLLmaskCurve locllmaslcCurve; + LocHHmaskCurve lochhmaslcCurve; + LocCCmaskCurve locccmascbCurve; + LocLLmaskCurve locllmascbCurve; + LocHHmaskCurve lochhmascbCurve; + LocCCmaskCurve locccmasretiCurve; + LocLLmaskCurve locllmasretiCurve; + LocHHmaskCurve lochhmasretiCurve; + LocCCmaskCurve locccmastmCurve; + LocLLmaskCurve locllmastmCurve; + LocHHmaskCurve lochhmastmCurve; + LocCCmaskCurve locccmasblCurve; + LocLLmaskCurve locllmasblCurve; + LocHHmaskCurve lochhmasblCurve; + LocwavCurve loclmasCurveblwav; + LocwavCurve loclmasCurvecolwav; LocwavCurve locwavCurve; + LocwavCurve loclevwavCurve; + LocwavCurve locconwavCurve; + LocwavCurve loccompwavCurve; + LocwavCurve loccomprewavCurve; + LocwavCurve locedgwavCurve; + LocwavCurve locwavCurveden; LUTf lllocalcurve(65536, 0); + LUTf lclocalcurve(65536, 0); + LUTf cllocalcurve(65536, 0); LUTf cclocalcurve(65536, 0); + LUTf rgblocalcurve(65536, 0); LUTf hltonecurveloc(65536, 0); LUTf shtonecurveloc(65536, 0); LUTf tonecurveloc(65536, 0); LUTf lightCurveloc(32770, 0); LUTf exlocalcurve(65536, 0); + LUTf lmasklocalcurve(65536, 0); + LUTf lmaskexplocalcurve(65536, 0); + LUTf lmaskSHlocalcurve(65536, 0); + LUTf lmaskviblocalcurve(65536, 0); + LUTf lmasktmlocalcurve(65536, 0); + LUTf lmaskretilocalcurve(65536, 0); + LUTf lmaskcblocalcurve(65536, 0); + LUTf lmaskbllocalcurve(65536, 0); + LUTf lmasklclocalcurve(65536, 0); // int maxspot = 1; float** shbuffer = nullptr; @@ -1134,15 +1161,36 @@ private: bool LHutili = false; bool HHutili = false; bool locallutili = false; + bool localclutili = false; + bool locallcutili = false; bool localcutili = false; + bool localrgbutili = false; bool localexutili = false; bool llmasutili = false; + bool lhmasutili = false; + bool lhhmasutili = false; + bool lcmasutili = false; + bool localmaskutili = false; + bool localmaskexputili = false; + bool localmaskSHutili = false; + bool localmaskvibutili = false; + bool localmasktmutili = false; + bool localmaskretiutili = false; + bool localmaskcbutili = false; + bool localmaskblutili = false; + bool localmasklcutili = false; bool lcmasexputili = false; bool lhmasexputili = false; bool llmasexputili = false; bool lcmasSHutili = false; bool lhmasSHutili = false; bool llmasSHutili = false; + bool lcmasvibutili = false; + bool lhmasvibutili = false; + bool llmasvibutili = false; + bool lcmaslcutili = false; + bool lhmaslcutili = false; + bool llmaslcutili = false; bool lcmascbutili = false; bool lhmascbutili = false; bool llmascbutili = false; @@ -1152,20 +1200,35 @@ private: bool lcmastmutili = false; bool lhmastmutili = false; bool llmastmutili = false; - bool lcmasutili = false; - bool lhmasutili = false; + bool lcmasblutili = false; + bool lhmasblutili = false; + bool llmasblutili = false; + bool locwavutili = false; + bool locwavdenutili = false; + bool loclevwavutili = false; + bool locconwavutili = false; + bool loccompwavutili = false; + bool loccomprewavutili = false; + bool locedgwavutili = false; + bool lmasutiliblwav = false; + bool lmasutilicolwav = false; locRETgainCurve.Set(params.locallab.spots.at(sp).localTgaincurve); + locRETtransCurve.Set(params.locallab.spots.at(sp).localTtranscurve); loclhCurve.Set(params.locallab.spots.at(sp).LHcurve, LHutili); lochhCurve.Set(params.locallab.spots.at(sp).HHcurve, HHutili); locccmasCurve.Set(params.locallab.spots.at(sp).CCmaskcurve, lcmasutili); locllmasCurve.Set(params.locallab.spots.at(sp).LLmaskcurve, llmasutili); lochhmasCurve.Set(params.locallab.spots.at(sp).HHmaskcurve, lhmasutili); + lochhhmasCurve.Set(params.locallab.spots.at(sp).HHhmaskcurve, lhhmasutili); locccmasexpCurve.Set(params.locallab.spots.at(sp).CCmaskexpcurve, lcmasexputili); locllmasexpCurve.Set(params.locallab.spots.at(sp).LLmaskexpcurve, llmasexputili); lochhmasexpCurve.Set(params.locallab.spots.at(sp).HHmaskexpcurve, lhmasexputili); locccmasSHCurve.Set(params.locallab.spots.at(sp).CCmaskSHcurve, lcmasSHutili); locllmasSHCurve.Set(params.locallab.spots.at(sp).LLmaskSHcurve, llmasSHutili); lochhmasSHCurve.Set(params.locallab.spots.at(sp).HHmaskSHcurve, lhmasSHutili); + locccmasvibCurve.Set(params.locallab.spots.at(sp).CCmaskvibcurve, lcmasvibutili); + locllmasvibCurve.Set(params.locallab.spots.at(sp).LLmaskvibcurve, llmasvibutili); + lochhmasvibCurve.Set(params.locallab.spots.at(sp).HHmaskvibcurve, lhmasvibutili); locccmascbCurve.Set(params.locallab.spots.at(sp).CCmaskcbcurve, lcmascbutili); locllmascbCurve.Set(params.locallab.spots.at(sp).LLmaskcbcurve, llmascbutili); lochhmascbCurve.Set(params.locallab.spots.at(sp).HHmaskcbcurve, lhmascbutili); @@ -1175,10 +1238,34 @@ private: locccmastmCurve.Set(params.locallab.spots.at(sp).CCmasktmcurve, lcmastmutili); locllmastmCurve.Set(params.locallab.spots.at(sp).LLmasktmcurve, llmastmutili); lochhmastmCurve.Set(params.locallab.spots.at(sp).HHmasktmcurve, lhmastmutili); - locwavCurve.Set(params.locallab.spots.at(sp).locwavcurve); + locccmasblCurve.Set(params.locallab.spots.at(sp).CCmaskblcurve, lcmasblutili); + locllmasblCurve.Set(params.locallab.spots.at(sp).LLmaskblcurve, llmasblutili); + lochhmasblCurve.Set(params.locallab.spots.at(sp).HHmaskblcurve, lhmasblutili); + loclmasCurveblwav.Set(params.locallab.spots.at(sp).LLmaskblcurvewav, lmasutiliblwav); + loclmasCurvecolwav.Set(params.locallab.spots.at(sp).LLmaskcolcurvewav, lmasutilicolwav); + + locwavCurve.Set(params.locallab.spots.at(sp).locwavcurve, locwavutili); + locwavCurveden.Set(params.locallab.spots.at(sp).locwavcurveden, locwavdenutili); + loclevwavCurve.Set(params.locallab.spots.at(sp).loclevwavcurve, loclevwavutili); + locconwavCurve.Set(params.locallab.spots.at(sp).locconwavcurve, locconwavutili); + loccompwavCurve.Set(params.locallab.spots.at(sp).loccompwavcurve, loccompwavutili); + loccomprewavCurve.Set(params.locallab.spots.at(sp).loccomprewavcurve, loccomprewavutili); + locedgwavCurve.Set(params.locallab.spots.at(sp).locedgwavcurve, locedgwavutili); CurveFactory::curveLocal(locallutili, params.locallab.spots.at(sp).llcurve, lllocalcurve, 1); + CurveFactory::curveLocal(localclutili, params.locallab.spots.at(sp).clcurve, cllocalcurve, 1); + CurveFactory::curveLocal(locallcutili, params.locallab.spots.at(sp).lccurve, lclocalcurve, 1); CurveFactory::curveCCLocal(localcutili, params.locallab.spots.at(sp).cccurve, cclocalcurve, 1); + CurveFactory::curveLocal(localrgbutili, params.locallab.spots.at(sp).rgbcurve, rgblocalcurve, 1); CurveFactory::curveexLocal(localexutili, params.locallab.spots.at(sp).excurve, exlocalcurve, 1); + CurveFactory::curvemaskLocal(localmaskutili, params.locallab.spots.at(sp).Lmaskcurve, lmasklocalcurve, 1); + CurveFactory::curvemaskLocal(localmaskexputili, params.locallab.spots.at(sp).Lmaskexpcurve, lmaskexplocalcurve, 1); + CurveFactory::curvemaskLocal(localmaskSHutili, params.locallab.spots.at(sp).LmaskSHcurve, lmaskSHlocalcurve, 1); + CurveFactory::curvemaskLocal(localmaskvibutili, params.locallab.spots.at(sp).Lmaskvibcurve, lmaskviblocalcurve, 1); + CurveFactory::curvemaskLocal(localmasktmutili, params.locallab.spots.at(sp).Lmasktmcurve, lmasktmlocalcurve, 1); + CurveFactory::curvemaskLocal(localmaskretiutili, params.locallab.spots.at(sp).Lmaskreticurve, lmaskretilocalcurve, 1); + CurveFactory::curvemaskLocal(localmaskcbutili, params.locallab.spots.at(sp).Lmaskcbcurve, lmaskcblocalcurve, 1); + CurveFactory::curvemaskLocal(localmaskblutili, params.locallab.spots.at(sp).Lmaskblcurve, lmaskbllocalcurve, 1); + CurveFactory::curvemaskLocal(localmasklcutili, params.locallab.spots.at(sp).Lmasklccurve, lmasklclocalcurve, 1); //provisory double ecomp = params.locallab.spots.at(sp).expcomp; double black = params.locallab.spots.at(sp).black; @@ -1187,34 +1274,91 @@ private: double shcompr = params.locallab.spots.at(sp).shcompr; double br = params.locallab.spots.at(sp).lightness; double cont = params.locallab.spots.at(sp).contrast; + if(black < 0. && params.locallab.spots.at(sp).expMethod == "pde" ) { + black *= 1.5; + } // Reference parameters computation double huere, chromare, lumare, huerefblu, chromarefblu, lumarefblu, sobelre; + int lastsav; float avge; if (params.locallab.spots.at(sp).spotMethod == "exc") { - ipf.calc_ref(sp, reservView, reservView, 0, 0, fw, fh, 1, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avge); + ipf.calc_ref(sp, reservView, reservView, 0, 0, fw, fh, 1, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avge, locwavCurveden, locwavdenutili); } else { - ipf.calc_ref(sp, labView, labView, 0, 0, fw, fh, 1, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avge); + ipf.calc_ref(sp, labView, labView, 0, 0, fw, fh, 1, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avge, locwavCurveden, locwavdenutili); } CurveFactory::complexCurvelocal(ecomp, black / 65535., hlcompr, hlcomprthresh, shcompr, br, cont, lumare, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, avge, 1); + float minCD; + float maxCD; + float mini; + float maxi; + float Tmean; + float Tsigma; + float Tmin; + float Tmax; // No Locallab mask is shown in exported picture - ipf.Lab_Local(2, sp, (float**)shbuffer, labView, labView, reservView, 0, 0, fw, fh, 1, locRETgainCurve, lllocalcurve, locallutili, loclhCurve, lochhCurve, locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, - locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, - locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, - locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, - locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, - locwavCurve, - LHutili, HHutili, cclocalcurve, localcutili, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, 0, 0, 0, 0, 0, 0, 0); + ipf.Lab_Local(2, sp, (float**)shbuffer, labView, labView, reservView, lastorigView, 0, 0, fw, fh, 1, locRETgainCurve, locRETtransCurve, + lllocalcurve, locallutili, + cllocalcurve, localclutili, + lclocalcurve, locallcutili, + loclhCurve, lochhCurve, + lmasklocalcurve, localmaskutili, + lmaskexplocalcurve, localmaskexputili, + lmaskSHlocalcurve, localmaskSHutili, + lmaskviblocalcurve, localmaskvibutili, + lmasktmlocalcurve, localmasktmutili, + lmaskretilocalcurve, localmaskretiutili, + lmaskcblocalcurve, localmaskcbutili, + lmaskbllocalcurve, localmaskblutili, + lmasklclocalcurve, localmasklcutili, + locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, lochhhmasCurve, lhhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili, + locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili, + locccmasvibCurve, lcmasvibutili, locllmasvibCurve, llmasvibutili, lochhmasvibCurve, lhmasvibutili, + locccmascbCurve, lcmascbutili, locllmascbCurve, llmascbutili, lochhmascbCurve, lhmascbutili, + locccmasretiCurve, lcmasretiutili, locllmasretiCurve, llmasretiutili, lochhmasretiCurve, lhmasretiutili, + locccmastmCurve, lcmastmutili, locllmastmCurve, llmastmutili, lochhmastmCurve, lhmastmutili, + locccmasblCurve, lcmasblutili, locllmasblCurve, llmasblutili, lochhmasblCurve, lhmasblutili, + locccmaslcCurve, lcmaslcutili, locllmaslcCurve, llmaslcutili, lochhmaslcCurve, lhmaslcutili, + loclmasCurveblwav,lmasutiliblwav, + loclmasCurvecolwav,lmasutilicolwav, + locwavCurve, locwavutili, + loclevwavCurve, loclevwavutili, + locconwavCurve, locconwavutili, + loccompwavCurve, loccompwavutili, + loccomprewavCurve, loccomprewavutili, + locwavCurveden, locwavdenutili, + locedgwavCurve, locedgwavutili, + LHutili, HHutili, cclocalcurve, localcutili, rgblocalcurve, localrgbutili, localexutili, exlocalcurve, hltonecurveloc, shtonecurveloc, tonecurveloc, lightCurveloc, + huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, lastsav, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax); + lastorigView->CopyFrom(labView); + + if (params.locallab.spots.at(sp).spotMethod == "exc") { + ipf.calc_ref(sp, reservView, reservView, 0, 0, fw, fh, 1, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avge, locwavCurveden, locwavdenutili); + } else { + ipf.calc_ref(sp, labView, labView, 0, 0, fw, fh, 1, huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, avge, locwavCurveden, locwavdenutili); + } // Clear local curves lllocalcurve.clear(); + lclocalcurve.clear(); + cllocalcurve.clear(); cclocalcurve.clear(); + rgblocalcurve.clear(); exlocalcurve.clear(); hltonecurveloc.clear(); + lmasklocalcurve.clear(); + lmaskexplocalcurve.clear(); + lmaskSHlocalcurve.clear(); + lmaskviblocalcurve.clear(); + lmasktmlocalcurve.clear(); + lmaskretilocalcurve.clear(); + lmaskcblocalcurve.clear(); + lmaskbllocalcurve.clear(); shtonecurveloc.clear(); tonecurveloc.clear(); lightCurveloc.clear(); @@ -1240,6 +1384,8 @@ private: delete reservView; reservView = nullptr; + delete lastorigView; + lastorigView = nullptr; ipf.chromiLuminanceCurve(nullptr, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy); @@ -1251,13 +1397,10 @@ private: ipf.vibrance(labView, params.vibrance, params.toneCurve.hrenabled, params.icm.workingProfile); ipf.labColorCorrectionRegions(labView); - if ((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { - ipf.impulsedenoise(labView); - } - // for all treatments Defringe, Sharpening, Contrast detail ,Microcontrast they are activated if "CIECAM" function are disabled if ((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { + ipf.impulsedenoise (labView); ipf.defringe(labView); } @@ -1737,6 +1880,7 @@ private: Imagefloat *baseImg; LabImage* labView; LabImage* reservView; + LabImage* lastorigView; LUTu hist16; diff --git a/rtengine/simpleprocess.h b/rtengine/simpleprocess.h index d6efe802d..9b41b4643 100644 --- a/rtengine/simpleprocess.h +++ b/rtengine/simpleprocess.h @@ -4,24 +4,11 @@ * * Created on September 18, 2010, 8:31 PM */ +#pragma once -#ifndef SIMPLEPROCESS_H -#define SIMPLEPROCESS_H - -#ifdef __cplusplus -extern "C" { -#endif - - - - -#ifdef __cplusplus -} -#endif namespace rtengine { extern Glib::Thread *batchThread; -} -#endif /* SIMPLEPROCESS_H */ +} diff --git a/rtengine/sleef.c b/rtengine/sleef.c deleted file mode 100644 index cc92be108..000000000 --- a/rtengine/sleef.c +++ /dev/null @@ -1,1279 +0,0 @@ -//////////////////////////////////////////////////////////////// -// -// this code was taken from http://shibatch.sourceforge.net/ -// Many thanks to the author of original version: Naoki Shibata -// -// This version contains modifications made by Ingo Weyrich -// -//////////////////////////////////////////////////////////////// - -#ifndef _SLEEFC_ -#define _SLEEFC_ - -#include -#include -#include "rt_math.h" -#include "opthelper.h" - -#define PI4_A .7853981554508209228515625 -#define PI4_B .794662735614792836713604629039764404296875e-8 -#define PI4_C .306161699786838294306516483068750264552437361480769e-16 -#define M_4_PI 1.273239544735162542821171882678754627704620361328125 - -#define L2U .69314718055966295651160180568695068359375 -#define L2L .28235290563031577122588448175013436025525412068e-12 -#define R_LN2 1.442695040888963407359924681001892137426645954152985934135449406931 -#define pow_F(a,b) (xexpf(b*xlogf(a))) - -__inline int64_t doubleToRawLongBits(double d) { - union { - double f; - int64_t i; - } tmp; - tmp.f = d; - return tmp.i; -} - -__inline double longBitsToDouble(int64_t i) { - union { - double f; - int64_t i; - } tmp; - tmp.i = i; - return tmp.f; -} - -__inline double xfabs(double x) { - return longBitsToDouble(0x7fffffffffffffffLL & doubleToRawLongBits(x)); -} - -__inline double mulsign(double x, double y) { - return longBitsToDouble(doubleToRawLongBits(x) ^ (doubleToRawLongBits(y) & (1LL << 63))); -} - -__inline double sign(double d) { return mulsign(1, d); } -__inline double mla(double x, double y, double z) { return x * y + z; } -__inline double xrint(double x) { return x < 0 ? (int)(x - 0.5) : (int)(x + 0.5); } - -__inline int xisnan(double x) { return x != x; } -__inline int xisinf(double x) { return x == rtengine::RT_INFINITY || x == -rtengine::RT_INFINITY; } -__inline int xisminf(double x) { return x == -rtengine::RT_INFINITY; } -__inline int xispinf(double x) { return x == rtengine::RT_INFINITY; } - -__inline double ldexpk(double x, int q) { - double u; - int m; - m = q >> 31; - m = (((m + q) >> 9) - m) << 7; - q = q - (m << 2); - u = longBitsToDouble(((int64_t)(m + 0x3ff)) << 52); - double u2 = u*u; - u2 = u2 * u2; - x = x * u2; - u = longBitsToDouble(((int64_t)(q + 0x3ff)) << 52); - return x * u; -} - -__inline double xldexp(double x, int q) { return ldexpk(x, q); } - -__inline int ilogbp1(double d) { - int m = d < 4.9090934652977266E-91; - d = m ? 2.037035976334486E90 * d : d; - int q = (doubleToRawLongBits(d) >> 52) & 0x7ff; - q = m ? q - (300 + 0x03fe) : q - 0x03fe; - return q; -} - -__inline int xilogb(double d) { - int e = ilogbp1(xfabs(d)) - 1; - e = d == 0 ? (-2147483647 - 1) : e; - e = d == rtengine::RT_INFINITY || d == -rtengine::RT_INFINITY ? 2147483647 : e; - return e; -} - -__inline double upper(double d) { - return longBitsToDouble(doubleToRawLongBits(d) & 0xfffffffff8000000LL); -} - -typedef struct { - double x, y; -} double2; - -typedef struct { - float x, y; -} float2; - -__inline double2 dd(double h, double l) { - double2 ret; - ret.x = h; ret.y = l; - return ret; -} - -__inline double2 normalize_d(double2 t) { - double2 s; - - s.x = t.x + t.y; - s.y = t.x - s.x + t.y; - - return s; -} - -__inline double2 scale_d(double2 d, double s) { - double2 r; - - r.x = d.x * s; - r.y = d.y * s; - - return r; -} - -__inline double2 add2_ss(double x, double y) { - double2 r; - - r.x = x + y; - double v = r.x - x; - r.y = (x - (r.x - v)) + (y - v); - - return r; -} - -__inline double2 add_ds(double2 x, double y) { - // |x| >= |y| - - double2 r; - - assert(xisnan(x.x) || xisnan(y) || xfabs(x.x) >= xfabs(y)); - - r.x = x.x + y; - r.y = x.x - r.x + y + x.y; - - return r; -} - -__inline double2 add2_ds(double2 x, double y) { - // |x| >= |y| - - double2 r; - - r.x = x.x + y; - double v = r.x - x.x; - r.y = (x.x - (r.x - v)) + (y - v); - r.y += x.y; - - return r; -} - -__inline double2 add_sd(double x, double2 y) { - // |x| >= |y| - - double2 r; - - assert(xisnan(x) || xisnan(y.x) || xfabs(x) >= xfabs(y.x)); - - r.x = x + y.x; - r.y = x - r.x + y.x + y.y; - - return r; -} - -__inline double2 add_dd(double2 x, double2 y) { - // |x| >= |y| - - double2 r; - - assert(xisnan(x.x) || xisnan(y.x) || xfabs(x.x) >= xfabs(y.x)); - - r.x = x.x + y.x; - r.y = x.x - r.x + y.x + x.y + y.y; - - return r; -} - -__inline double2 add2_dd(double2 x, double2 y) { - double2 r; - - r.x = x.x + y.x; - double v = r.x - x.x; - r.y = (x.x - (r.x - v)) + (y.x - v); - r.y += x.y + y.y; - - return r; -} - -__inline double2 div_dd(double2 n, double2 d) { - double t = 1.0 / d.x; - double dh = upper(d.x), dl = d.x - dh; - double th = upper(t ), tl = t - th; - double nhh = upper(n.x), nhl = n.x - nhh; - - double2 q; - - q.x = n.x * t; - - double u = -q.x + nhh * th + nhh * tl + nhl * th + nhl * tl + - q.x * (1 - dh * th - dh * tl - dl * th - dl * tl); - - q.y = t * (n.y - q.x * d.y) + u; - - return q; -} - -__inline double2 mul_ss(double x, double y) { - double xh = upper(x), xl = x - xh; - double yh = upper(y), yl = y - yh; - double2 r; - - r.x = x * y; - r.y = xh * yh - r.x + xl * yh + xh * yl + xl * yl; - - return r; -} - -__inline double2 mul_ds(double2 x, double y) { - double xh = upper(x.x), xl = x.x - xh; - double yh = upper(y ), yl = y - yh; - double2 r; - - r.x = x.x * y; - r.y = xh * yh - r.x + xl * yh + xh * yl + xl * yl + x.y * y; - - return r; -} - -__inline double2 mul_dd(double2 x, double2 y) { - double xh = upper(x.x), xl = x.x - xh; - double yh = upper(y.x), yl = y.x - yh; - double2 r; - - r.x = x.x * y.x; - r.y = xh * yh - r.x + xl * yh + xh * yl + xl * yl + x.x * y.y + x.y * y.x; - - return r; -} - -__inline double2 squ_d(double2 x) { - double xh = upper(x.x), xl = x.x - xh; - double2 r; - - r.x = x.x * x.x; - r.y = xh * xh - r.x + (xh + xh) * xl + xl * xl + x.x * (x.y + x.y); - - return r; -} - -__inline double2 rec_s(double d) { - double t = 1.0 / d; - double dh = upper(d), dl = d - dh; - double th = upper(t), tl = t - th; - double2 q; - - q.x = t; - q.y = t * (1 - dh * th - dh * tl - dl * th - dl * tl); - - return q; -} - -__inline double2 sqrt_d(double2 d) { - double t = sqrt(d.x + d.y); - return scale_d(mul_dd(add2_dd(d, mul_ss(t, t)), rec_s(t)), 0.5); -} - -__inline double atan2k(double y, double x) { - double s, t, u; - int q = 0; - - if (x < 0) { x = -x; q = -2; } - if (y > x) { t = x; x = y; y = -t; q += 1; } - - s = y / x; - t = s * s; - - u = -1.88796008463073496563746e-05; - u = u * t + (0.000209850076645816976906797); - u = u * t + (-0.00110611831486672482563471); - u = u * t + (0.00370026744188713119232403); - u = u * t + (-0.00889896195887655491740809); - u = u * t + (0.016599329773529201970117); - u = u * t + (-0.0254517624932312641616861); - u = u * t + (0.0337852580001353069993897); - u = u * t + (-0.0407629191276836500001934); - u = u * t + (0.0466667150077840625632675); - u = u * t + (-0.0523674852303482457616113); - u = u * t + (0.0587666392926673580854313); - u = u * t + (-0.0666573579361080525984562); - u = u * t + (0.0769219538311769618355029); - u = u * t + (-0.090908995008245008229153); - u = u * t + (0.111111105648261418443745); - u = u * t + (-0.14285714266771329383765); - u = u * t + (0.199999999996591265594148); - u = u * t + (-0.333333333333311110369124); - - t = u * t * s + s; - t = q * (rtengine::RT_PI_2) + t; - - return t; -} - -__inline double xatan2(double y, double x) { - double r = atan2k(xfabs(y), x); - - r = mulsign(r, x); - if (xisinf(x) || x == 0) r = rtengine::RT_PI_2 - (xisinf(x) ? (sign(x) * (rtengine::RT_PI_2)) : 0); - if (xisinf(y) ) r = rtengine::RT_PI_2 - (xisinf(x) ? (sign(x) * (rtengine::RT_PI*1/4)) : 0); - if ( y == 0) r = (sign(x) == -1 ? rtengine::RT_PI : 0); - - return xisnan(x) || xisnan(y) ? rtengine::RT_NAN : mulsign(r, y); -} - -__inline double xasin(double d) { - return mulsign(atan2k(xfabs(d), sqrt((1+d)*(1-d))), d); -} - -__inline double xacos(double d) { - return mulsign(atan2k(sqrt((1+d)*(1-d)), xfabs(d)), d) + (d < 0 ? rtengine::RT_PI : 0); -} - -__inline double xatan(double s) { - double t, u; - int q = 0; - - if (s < 0) { s = -s; q = 2; } - if (s > 1) { s = 1.0 / s; q |= 1; } - - t = s * s; - - u = -1.88796008463073496563746e-05; - u = u * t + (0.000209850076645816976906797); - u = u * t + (-0.00110611831486672482563471); - u = u * t + (0.00370026744188713119232403); - u = u * t + (-0.00889896195887655491740809); - u = u * t + (0.016599329773529201970117); - u = u * t + (-0.0254517624932312641616861); - u = u * t + (0.0337852580001353069993897); - u = u * t + (-0.0407629191276836500001934); - u = u * t + (0.0466667150077840625632675); - u = u * t + (-0.0523674852303482457616113); - u = u * t + (0.0587666392926673580854313); - u = u * t + (-0.0666573579361080525984562); - u = u * t + (0.0769219538311769618355029); - u = u * t + (-0.090908995008245008229153); - u = u * t + (0.111111105648261418443745); - u = u * t + (-0.14285714266771329383765); - u = u * t + (0.199999999996591265594148); - u = u * t + (-0.333333333333311110369124); - - t = s + s * (t * u); - - if ((q & 1) != 0) t = 1.570796326794896557998982 - t; - if ((q & 2) != 0) t = -t; - - return t; -} - -__inline double xsin(double d) { - int q; - double u, s; - - q = (int)xrint(d * rtengine::RT_1_PI); - - d = mla(q, -PI4_A*4, d); - d = mla(q, -PI4_B*4, d); - d = mla(q, -PI4_C*4, d); - - s = d * d; - - if ((q & 1) != 0) d = -d; - - u = -7.97255955009037868891952e-18; - u = mla(u, s, 2.81009972710863200091251e-15); - u = mla(u, s, -7.64712219118158833288484e-13); - u = mla(u, s, 1.60590430605664501629054e-10); - u = mla(u, s, -2.50521083763502045810755e-08); - u = mla(u, s, 2.75573192239198747630416e-06); - u = mla(u, s, -0.000198412698412696162806809); - u = mla(u, s, 0.00833333333333332974823815); - u = mla(u, s, -0.166666666666666657414808); - - u = mla(s, u * d, d); - - return u; -} - -__inline double xcos(double d) { - int q; - double u, s; - - q = 1 + 2*(int)xrint(d * rtengine::RT_1_PI - 0.5); - - d = mla(q, -PI4_A*2, d); - d = mla(q, -PI4_B*2, d); - d = mla(q, -PI4_C*2, d); - - s = d * d; - - if ((q & 2) == 0) d = -d; - - u = -7.97255955009037868891952e-18; - u = mla(u, s, 2.81009972710863200091251e-15); - u = mla(u, s, -7.64712219118158833288484e-13); - u = mla(u, s, 1.60590430605664501629054e-10); - u = mla(u, s, -2.50521083763502045810755e-08); - u = mla(u, s, 2.75573192239198747630416e-06); - u = mla(u, s, -0.000198412698412696162806809); - u = mla(u, s, 0.00833333333333332974823815); - u = mla(u, s, -0.166666666666666657414808); - - u = mla(s, u * d, d); - - return u; -} - -__inline double2 xsincos(double d) { - int q; - double u, s, t; - double2 r; - - q = (int)xrint(d * (2 * rtengine::RT_1_PI)); - - s = d; - - s = mla(-q, PI4_A*2, s); - s = mla(-q, PI4_B*2, s); - s = mla(-q, PI4_C*2, s); - - t = s; - - s = s * s; - - u = 1.58938307283228937328511e-10; - u = mla(u, s, -2.50506943502539773349318e-08); - u = mla(u, s, 2.75573131776846360512547e-06); - u = mla(u, s, -0.000198412698278911770864914); - u = mla(u, s, 0.0083333333333191845961746); - u = mla(u, s, -0.166666666666666130709393); - u = u * s * t; - - r.x = t + u; - - u = -1.13615350239097429531523e-11; - u = mla(u, s, 2.08757471207040055479366e-09); - u = mla(u, s, -2.75573144028847567498567e-07); - u = mla(u, s, 2.48015872890001867311915e-05); - u = mla(u, s, -0.00138888888888714019282329); - u = mla(u, s, 0.0416666666666665519592062); - u = mla(u, s, -0.5); - - r.y = u * s + 1; - - if ((q & 1) != 0) { s = r.y; r.y = r.x; r.x = s; } - if ((q & 2) != 0) { r.x = -r.x; } - if (((q+1) & 2) != 0) { r.y = -r.y; } - - if (xisinf(d)) { r.x = r.y = rtengine::RT_NAN; } - - return r; -} - -__inline double xtan(double d) { - int q; - double u, s, x; - - q = (int)xrint(d * (2 * rtengine::RT_1_PI)); - - x = mla(q, -PI4_A*2, d); - x = mla(q, -PI4_B*2, x); - x = mla(q, -PI4_C*2, x); - - s = x * x; - - if ((q & 1) != 0) x = -x; - - u = 1.01419718511083373224408e-05; - u = mla(u, s, -2.59519791585924697698614e-05); - u = mla(u, s, 5.23388081915899855325186e-05); - u = mla(u, s, -3.05033014433946488225616e-05); - u = mla(u, s, 7.14707504084242744267497e-05); - u = mla(u, s, 8.09674518280159187045078e-05); - u = mla(u, s, 0.000244884931879331847054404); - u = mla(u, s, 0.000588505168743587154904506); - u = mla(u, s, 0.00145612788922812427978848); - u = mla(u, s, 0.00359208743836906619142924); - u = mla(u, s, 0.00886323944362401618113356); - u = mla(u, s, 0.0218694882853846389592078); - u = mla(u, s, 0.0539682539781298417636002); - u = mla(u, s, 0.133333333333125941821962); - u = mla(u, s, 0.333333333333334980164153); - - u = mla(s, u * x, x); - - if ((q & 1) != 0) u = 1.0 / u; - - if (xisinf(d)) u = rtengine::RT_NAN; - - return u; -} - -__inline double xlog(double d) { - double x, x2, t, m; - int e; - - e = ilogbp1(d * 0.7071); - m = ldexpk(d, -e); - - x = (m-1) / (m+1); - x2 = x * x; - - t = 0.148197055177935105296783; - t = mla(t, x2, 0.153108178020442575739679); - t = mla(t, x2, 0.181837339521549679055568); - t = mla(t, x2, 0.22222194152736701733275); - t = mla(t, x2, 0.285714288030134544449368); - t = mla(t, x2, 0.399999999989941956712869); - t = mla(t, x2, 0.666666666666685503450651); - t = mla(t, x2, 2); - - x = x * t + 0.693147180559945286226764 * e; - - if (xisinf(d)) x = rtengine::RT_INFINITY; - if (d < 0) x = rtengine::RT_NAN; - if (d == 0) x = -rtengine::RT_INFINITY; - - return x; -} - -__inline double xexp(double d) { - int q = (int)xrint(d * R_LN2); - double s, u; - - s = mla(q, -L2U, d); - s = mla(q, -L2L, s); - - u = 2.08860621107283687536341e-09; - u = mla(u, s, 2.51112930892876518610661e-08); - u = mla(u, s, 2.75573911234900471893338e-07); - u = mla(u, s, 2.75572362911928827629423e-06); - u = mla(u, s, 2.4801587159235472998791e-05); - u = mla(u, s, 0.000198412698960509205564975); - u = mla(u, s, 0.00138888888889774492207962); - u = mla(u, s, 0.00833333333331652721664984); - u = mla(u, s, 0.0416666666666665047591422); - u = mla(u, s, 0.166666666666666851703837); - u = mla(u, s, 0.5); - - u = s * s * u + s + 1; - u = ldexpk(u, q); - - if (xisminf(d)) u = 0; - - return u; -} - -__inline double2 logk(double d) { - double2 x, x2; - double m, t; - int e; - - e = ilogbp1(d * 0.7071); - m = ldexpk(d, -e); - - x = div_dd(add2_ss(-1, m), add2_ss(1, m)); - x2 = squ_d(x); - - t = 0.134601987501262130076155; - t = mla(t, x2.x, 0.132248509032032670243288); - t = mla(t, x2.x, 0.153883458318096079652524); - t = mla(t, x2.x, 0.181817427573705403298686); - t = mla(t, x2.x, 0.222222231326187414840781); - t = mla(t, x2.x, 0.285714285651261412873718); - t = mla(t, x2.x, 0.400000000000222439910458); - t = mla(t, x2.x, 0.666666666666666371239645); - - return add2_dd(mul_ds(dd(0.693147180559945286226764, 2.319046813846299558417771e-17), e), - add2_dd(scale_d(x, 2), mul_ds(mul_dd(x2, x), t))); -} - -__inline double expk(double2 d) { - int q = (int)rint((d.x + d.y) * R_LN2); - double2 s, t; - double u; - - s = add2_ds(d, q * -L2U); - s = add2_ds(s, q * -L2L); - - s = normalize_d(s); - - u = 2.51069683420950419527139e-08; - u = mla(u, s.x, 2.76286166770270649116855e-07); - u = mla(u, s.x, 2.75572496725023574143864e-06); - u = mla(u, s.x, 2.48014973989819794114153e-05); - u = mla(u, s.x, 0.000198412698809069797676111); - u = mla(u, s.x, 0.0013888888939977128960529); - u = mla(u, s.x, 0.00833333333332371417601081); - u = mla(u, s.x, 0.0416666666665409524128449); - u = mla(u, s.x, 0.166666666666666740681535); - u = mla(u, s.x, 0.500000000000000999200722); - - t = add_dd(s, mul_ds(squ_d(s), u)); - - t = add_sd(1, t); - return ldexpk(t.x + t.y, q); -} - -__inline double xpow(double x, double y) { - int yisint = (int)y == y; - int yisodd = (1 & (int)y) != 0 && yisint; - - double result = expk(mul_ds(logk(xfabs(x)), y)); - - result = xisnan(result) ? rtengine::RT_INFINITY : result; - result *= (x >= 0 ? 1 : (!yisint ? rtengine::RT_NAN : (yisodd ? -1 : 1))); - - double efx = mulsign(xfabs(x) - 1, y); - if (xisinf(y)) result = efx < 0 ? 0.0 : (efx == 0 ? 1.0 : rtengine::RT_INFINITY); - if (xisinf(x) || x == 0) result = (yisodd ? sign(x) : 1) * ((x == 0 ? -y : y) < 0 ? 0 : rtengine::RT_INFINITY); - if (xisnan(x) || xisnan(y)) result = rtengine::RT_NAN; - if (y == 0 || x == 1) result = 1; - - return result; -} - -__inline double2 expk2(double2 d) { - int q = (int)rint((d.x + d.y) * R_LN2); - double2 s, t; - double u; - - s = add2_ds(d, q * -L2U); - s = add2_ds(s, q * -L2L); - - s = normalize_d(s); - - u = 2.51069683420950419527139e-08; - u = mla(u, s.x, 2.76286166770270649116855e-07); - u = mla(u, s.x, 2.75572496725023574143864e-06); - u = mla(u, s.x, 2.48014973989819794114153e-05); - u = mla(u, s.x, 0.000198412698809069797676111); - u = mla(u, s.x, 0.0013888888939977128960529); - u = mla(u, s.x, 0.00833333333332371417601081); - u = mla(u, s.x, 0.0416666666665409524128449); - u = mla(u, s.x, 0.166666666666666740681535); - u = mla(u, s.x, 0.500000000000000999200722); - - t = add_dd(s, mul_ds(squ_d(s), u)); - - t = add_sd(1, t); - return dd(ldexpk(t.x, q), ldexpk(t.y, q)); -} - -__inline double xsinh(double x) { - double y = xfabs(x); - double2 d = expk2(dd(y, 0)); - d = add2_dd(d, div_dd(dd(-1, 0), d)); - y = (d.x + d.y) * 0.5; - - y = xisinf(x) || xisnan(y) ? rtengine::RT_INFINITY : y; - y = mulsign(y, x); - y = xisnan(x) ? rtengine::RT_NAN : y; - - return y; -} - -__inline double xcosh(double x) { - double2 d = expk2(dd(x, 0)); - d = add2_dd(d, div_dd(dd(1, 0), d)); - double y = (d.x + d.y) * 0.5; - - y = xisinf(x) || xisnan(y) ? rtengine::RT_INFINITY : y; - y = xisnan(x) ? rtengine::RT_NAN : y; - - return y; -} - -__inline double xtanh(double x) { - double y = xfabs(x); - double2 d = expk2(dd(y, 0)); - double2 e = div_dd(dd(1, 0), d); - d = div_dd(add2_dd(d, scale_d(e, -1)), add2_dd(d, e)); - y = d.x + d.y; - - y = xisinf(x) || xisnan(y) ? 1.0 : y; - y = mulsign(y, x); - y = xisnan(x) ? rtengine::RT_NAN : y; - - return y; -} - -__inline double2 logk2(double2 d) { - double2 x, x2, m; - double t; - int e; - - d = normalize_d(d); - e = ilogbp1(d.x * 0.7071); - m = scale_d(d, ldexpk(1, -e)); - - x = div_dd(add2_ds(m, -1), add2_ds(m, 1)); - x2 = squ_d(x); - - t = 0.134601987501262130076155; - t = mla(t, x2.x, 0.132248509032032670243288); - t = mla(t, x2.x, 0.153883458318096079652524); - t = mla(t, x2.x, 0.181817427573705403298686); - t = mla(t, x2.x, 0.222222231326187414840781); - t = mla(t, x2.x, 0.285714285651261412873718); - t = mla(t, x2.x, 0.400000000000222439910458); - t = mla(t, x2.x, 0.666666666666666371239645); - - return add2_dd(mul_ds(dd(0.693147180559945286226764, 2.319046813846299558417771e-17), e), - add2_dd(scale_d(x, 2), mul_ds(mul_dd(x2, x), t))); -} - -__inline double xasinh(double x) { - double y = xfabs(x); - double2 d = logk2(add2_ds(sqrt_d(add2_ds(mul_ss(y, y), 1)), y)); - y = d.x + d.y; - - y = xisinf(x) || xisnan(y) ? rtengine::RT_INFINITY : y; - y = mulsign(y, x); - y = xisnan(x) ? rtengine::RT_NAN : y; - - return y; -} - -__inline double xacosh(double x) { - double2 d = logk2(add2_ds(sqrt_d(add2_ds(mul_ss(x, x), -1)), x)); - double y = d.x + d.y; - - y = xisinf(x) || xisnan(y) ? rtengine::RT_INFINITY : y; - y = x == 1.0 ? 0.0 : y; - y = x < 1.0 ? rtengine::RT_NAN : y; - y = xisnan(x) ? rtengine::RT_NAN : y; - - return y; -} - -__inline double xatanh(double x) { - double y = xfabs(x); - double2 d = logk2(div_dd(add2_ss(1, y), add2_ss(1, -y))); - y = y > 1.0 ? rtengine::RT_NAN : (y == 1.0 ? rtengine::RT_INFINITY : (d.x + d.y) * 0.5); - - y = xisinf(x) || xisnan(y) ? rtengine::RT_NAN : y; - y = mulsign(y, x); - y = xisnan(x) ? rtengine::RT_NAN : y; - - return y; -} - -// - -__inline double xfma(double x, double y, double z) { - union { - double f; - long long int i; - } tmp; - - tmp.f = x; - tmp.i = (tmp.i + 0x4000000) & 0xfffffffff8000000LL; - double xh = tmp.f, xl = x - xh; - - tmp.f = y; - tmp.i = (tmp.i + 0x4000000) & 0xfffffffff8000000LL; - double yh = tmp.f, yl = y - yh; - - double h = x * y; - double l = xh * yh - h + xl * yh + xh * yl + xl * yl; - - double h2, l2, v; - - h2 = h + z; - v = h2 - h; - l2 = (h - (h2 - v)) + (z - v) + l; - - return h2 + l2; -} - -__inline double xsqrt(double d) { // max error : 0.5 ulp - double q = 1; - - if (d < 8.636168555094445E-78) { - d *= 1.157920892373162E77; - q = 2.9387358770557188E-39; - } - - // http://en.wikipedia.org/wiki/Fast_inverse_square_root - double x = longBitsToDouble(0x5fe6ec85e7de30da - (doubleToRawLongBits(d + 1e-320) >> 1)); - - x = x * (1.5 - 0.5 * d * x * x); - x = x * (1.5 - 0.5 * d * x * x); - x = x * (1.5 - 0.5 * d * x * x); - - // You can change xfma to fma if fma is correctly implemented - x = xfma(d * x, d * x, -d) * (x * -0.5) + d * x; - - return d == rtengine::RT_INFINITY ? rtengine::RT_INFINITY : x * q; -} - -__inline double xcbrt(double d) { // max error : 2 ulps - double x, y, q = 1.0; - int e, r; - - e = ilogbp1(d); - d = ldexpk(d, -e); - r = (e + 6144) % 3; - q = (r == 1) ? 1.2599210498948731647672106 : q; - q = (r == 2) ? 1.5874010519681994747517056 : q; - q = ldexpk(q, (e + 6144) / 3 - 2048); - - q = mulsign(q, d); - d = xfabs(d); - - x = -0.640245898480692909870982; - x = x * d + 2.96155103020039511818595; - x = x * d + -5.73353060922947843636166; - x = x * d + 6.03990368989458747961407; - x = x * d + -3.85841935510444988821632; - x = x * d + 2.2307275302496609725722; - - y = x * x; y = y * y; x -= (d * y - x) * (1.0 / 3.0); - y = d * x * x; - y = (y - (2.0 / 3.0) * y * (y * x - 1)) * q; - - return y; -} - -__inline double xexp2(double a) { - double u = expk(mul_ds(dd(0.69314718055994528623, 2.3190468138462995584e-17), a)); - if (xispinf(a)) u = rtengine::RT_INFINITY; - if (xisminf(a)) u = 0; - return u; -} - -__inline double xexp10(double a) { - double u = expk(mul_ds(dd(2.3025850929940459011, -2.1707562233822493508e-16), a)); - if (xispinf(a)) u = rtengine::RT_INFINITY; - if (xisminf(a)) u = 0; - return u; -} - -__inline double xexpm1(double a) { - double2 d = add2_ds(expk2(dd(a, 0)), -1.0); - double x = d.x + d.y; - if (xispinf(a)) x = rtengine::RT_INFINITY; - if (xisminf(a)) x = -1; - return x; -} - -__inline double xlog10(double a) { - double2 d = mul_dd(logk(a), dd(0.43429448190325176116, 6.6494347733425473126e-17)); - double x = d.x + d.y; - - if (xisinf(a)) x = rtengine::RT_INFINITY; - if (a < 0) x = rtengine::RT_NAN; - if (a == 0) x = -rtengine::RT_INFINITY; - - return x; -} - -__inline double xlog1p(double a) { - double2 d = logk2(add2_ss(a, 1)); - double x = d.x + d.y; - - if (xisinf(a)) x = rtengine::RT_INFINITY; - if (a < -1) x = rtengine::RT_NAN; - if (a == -1) x = -rtengine::RT_INFINITY; - - return x; -} - -/////////////////////////////////////////// - -#define PI4_Af 0.78515625f -#define PI4_Bf 0.00024127960205078125f -#define PI4_Cf 6.3329935073852539062e-07f -#define PI4_Df 4.9604681473525147339e-10f - -#define L2Uf 0.693145751953125f -#define L2Lf 1.428606765330187045e-06f - -#define R_LN2f 1.442695040888963407359924681001892137426645954152985934135449406931f - -__inline int32_t floatToRawIntBits(float d) { - union { - float f; - int32_t i; - } tmp; - tmp.f = d; - return tmp.i; -} - -__inline float intBitsToFloat(int32_t i) { - union { - float f; - int32_t i; - } tmp; - tmp.i = i; - return tmp.f; -} - -__inline float xfabsf(float x) { - return intBitsToFloat(0x7fffffffL & floatToRawIntBits(x)); -} - -__inline float mulsignf(float x, float y) { - return intBitsToFloat(floatToRawIntBits(x) ^ (floatToRawIntBits(y) & (1 << 31))); -} - -__inline float signf(float d) { return copysign(1, d); } -__inline float mlaf(float x, float y, float z) { return x * y + z; } - -__inline int xisnanf(float x) { return x != x; } -__inline int xisinff(float x) { return x == rtengine::RT_INFINITY_F || x == -rtengine::RT_INFINITY_F; } -__inline int xisminff(float x) { return x == -rtengine::RT_INFINITY_F; } -__inline int xispinff(float x) { return x == rtengine::RT_INFINITY_F; } - -__inline int ilogbp1f(float d) { - int m = d < 5.421010862427522E-20f; - d = m ? 1.8446744073709552E19f * d : d; - int q = (floatToRawIntBits(d) >> 23) & 0xff; - q = m ? q - (64 + 0x7e) : q - 0x7e; - return q; -} - -__inline float ldexpkf(float x, int q) { - float u; - int m; - m = q >> 31; - m = (((m + q) >> 6) - m) << 4; - q = q - (m << 2); - u = intBitsToFloat(((int32_t)(m + 0x7f)) << 23); - u = u * u; - x = x * u * u; - u = intBitsToFloat(((int32_t)(q + 0x7f)) << 23); - return x * u; -} - -__inline float xcbrtf(float d) { // max error : 2 ulps - float x, y, q = 1.0f; - int e, r; - - e = ilogbp1f(d); - d = ldexpkf(d, -e); - r = (e + 6144) % 3; - q = (r == 1) ? 1.2599210498948731647672106f : q; - q = (r == 2) ? 1.5874010519681994747517056f : q; - q = ldexpkf(q, (e + 6144) / 3 - 2048); - - q = mulsignf(q, d); - d = xfabsf(d); - - x = -0.601564466953277587890625f; - x = mlaf(x, d, 2.8208892345428466796875f); - x = mlaf(x, d, -5.532182216644287109375f); - x = mlaf(x, d, 5.898262500762939453125f); - x = mlaf(x, d, -3.8095417022705078125f); - x = mlaf(x, d, 2.2241256237030029296875f); - - y = d * x * x; - y = (y - (2.0f / 3.0f) * y * (y * x - 1.0f)) * q; - - return y; -} - -__inline float xsinf(float d) { - int q; - float u, s; - - q = rint(d * rtengine::RT_1_PI_F); - - d = mlaf(q, -PI4_Af*4, d); - d = mlaf(q, -PI4_Bf*4, d); - d = mlaf(q, -PI4_Cf*4, d); - d = mlaf(q, -PI4_Df*4, d); - - s = d * d; - - if ((q & 1) != 0) d = -d; - - u = 2.6083159809786593541503e-06f; - u = mlaf(u, s, -0.0001981069071916863322258f); - u = mlaf(u, s, 0.00833307858556509017944336f); - u = mlaf(u, s, -0.166666597127914428710938f); - - u = mlaf(s, u * d, d); - - return u; -} - -__inline float xcosf(float d) { -#ifdef __SSE2__ - // faster than scalar version - return xcosf(_mm_set_ss(d))[0]; -#else - int q; - float u, s; - - q = 1 + 2*rint(d * rtengine::RT_1_PI_F - 0.5f); - - d = mlaf(q, -PI4_Af*2, d); - d = mlaf(q, -PI4_Bf*2, d); - d = mlaf(q, -PI4_Cf*2, d); - d = mlaf(q, -PI4_Df*2, d); - - s = d * d; - - if ((q & 2) == 0) d = -d; - - u = 2.6083159809786593541503e-06f; - u = mlaf(u, s, -0.0001981069071916863322258f); - u = mlaf(u, s, 0.00833307858556509017944336f); - u = mlaf(u, s, -0.166666597127914428710938f); - - u = mlaf(s, u * d, d); - - return u; -#endif -} - -__inline float2 xsincosf(float d) { -#ifdef __SSE2__ - // faster than scalar version - vfloat2 res = xsincosf(_mm_set_ss(d)); - return {res.x[0], res.y[0]}; -#else - int q; - float u, s, t; - float2 r; - - q = rint(d * rtengine::RT_2_PI_F); - - s = d; - - s = mlaf(q, -PI4_Af*2, s); - s = mlaf(q, -PI4_Bf*2, s); - s = mlaf(q, -PI4_Cf*2, s); - s = mlaf(q, -PI4_Df*2, s); - - t = s; - - s = s * s; - - u = -0.000195169282960705459117889f; - u = mlaf(u, s, 0.00833215750753879547119141f); - u = mlaf(u, s, -0.166666537523269653320312f); - u = u * s * t; - - r.x = t + u; - - u = -2.71811842367242206819355e-07f; - u = mlaf(u, s, 2.47990446951007470488548e-05f); - u = mlaf(u, s, -0.00138888787478208541870117f); - u = mlaf(u, s, 0.0416666641831398010253906f); - u = mlaf(u, s, -0.5f); - - r.y = u * s + 1; - - if ((q & 1) != 0) { s = r.y; r.y = r.x; r.x = s; } - if ((q & 2) != 0) { r.x = -r.x; } - if (((q+1) & 2) != 0) { r.y = -r.y; } - - if (xisinff(d)) { r.x = r.y = rtengine::RT_NAN_F; } - - return r; -#endif -} - -__inline float xtanf(float d) { - int q; - float u, s, x; - - q = rint(d * (float)(2 * rtengine::RT_1_PI)); - - x = d; - - x = mlaf(q, -PI4_Af*2, x); - x = mlaf(q, -PI4_Bf*2, x); - x = mlaf(q, -PI4_Cf*2, x); - x = mlaf(q, -PI4_Df*2, x); - - s = x * x; - - if ((q & 1) != 0) x = -x; - - u = 0.00927245803177356719970703f; - u = mlaf(u, s, 0.00331984995864331722259521f); - u = mlaf(u, s, 0.0242998078465461730957031f); - u = mlaf(u, s, 0.0534495301544666290283203f); - u = mlaf(u, s, 0.133383005857467651367188f); - u = mlaf(u, s, 0.333331853151321411132812f); - - u = mlaf(s, u * x, x); - - if ((q & 1) != 0) u = 1.0f / u; - - if (xisinff(d)) u = rtengine::RT_NAN_F; - - return u; -} - -__inline float xatanf(float s) { - float t, u; - int q = 0; - - if (s < 0) { s = -s; q = 2; } - if (s > 1) { s = 1.0f / s; q |= 1; } - - t = s * s; - - u = 0.00282363896258175373077393f; - u = mlaf(u, t, -0.0159569028764963150024414f); - u = mlaf(u, t, 0.0425049886107444763183594f); - u = mlaf(u, t, -0.0748900920152664184570312f); - u = mlaf(u, t, 0.106347933411598205566406f); - u = mlaf(u, t, -0.142027363181114196777344f); - u = mlaf(u, t, 0.199926957488059997558594f); - u = mlaf(u, t, -0.333331018686294555664062f); - - t = s + s * (t * u); - - if ((q & 1) != 0) t = 1.570796326794896557998982f - t; - if ((q & 2) != 0) t = -t; - - return t; -} - -__inline float atan2kf(float y, float x) { - float s, t, u; - float q = 0.f; - - if (x < 0) { x = -x; q = -2.f; } - if (y > x) { t = x; x = y; y = -t; q += 1.f; } - - s = y / x; - t = s * s; - - u = 0.00282363896258175373077393f; - u = mlaf(u, t, -0.0159569028764963150024414f); - u = mlaf(u, t, 0.0425049886107444763183594f); - u = mlaf(u, t, -0.0748900920152664184570312f); - u = mlaf(u, t, 0.106347933411598205566406f); - u = mlaf(u, t, -0.142027363181114196777344f); - u = mlaf(u, t, 0.199926957488059997558594f); - u = mlaf(u, t, -0.333331018686294555664062f); - - t = u * t; - t = mlaf(t,s,s); - return mlaf(q,(float)(rtengine::RT_PI_F_2),t); -} - -__inline float xatan2f(float y, float x) { - float r = atan2kf(xfabsf(y), x); - - r = mulsignf(r, x); - if (xisinff(x) || x == 0) r = rtengine::RT_PI_F/2 - (xisinff(x) ? (signf(x) * (float)(rtengine::RT_PI_F*.5f)) : 0); - if (xisinff(y) ) r = rtengine::RT_PI_F/2 - (xisinff(x) ? (signf(x) * (float)(rtengine::RT_PI_F*.25f)) : 0); - if ( y == 0) r = (signf(x) == -1 ? rtengine::RT_PI_F : 0); - - return xisnanf(x) || xisnanf(y) ? rtengine::RT_NAN_F : mulsignf(r, y); -} - -__inline float xasinf(float d) { - return mulsignf(atan2kf(fabsf(d), sqrtf((1.0f+d)*(1.0f-d))), d); -} - -__inline float xacosf(float d) { - return mulsignf(atan2kf(sqrtf((1.0f+d)*(1.0f-d)), fabsf(d)), d) + (d < 0 ? (float)rtengine::RT_PI : 0.0f); -} - -__inline float xlogf(float d) { - float x, x2, t, m; - int e; - - e = ilogbp1f(d * 0.7071f); - m = ldexpkf(d, -e); - - x = (m-1.0f) / (m+1.0f); - x2 = x * x; - - t = 0.2371599674224853515625f; - t = mlaf(t, x2, 0.285279005765914916992188f); - t = mlaf(t, x2, 0.400005519390106201171875f); - t = mlaf(t, x2, 0.666666567325592041015625f); - t = mlaf(t, x2, 2.0f); - - x = x * t + 0.693147180559945286226764f * e; - - if (xisinff(d)) x = rtengine::RT_INFINITY_F; - if (d < 0) x = rtengine::RT_NAN_F; - if (d == 0) x = -rtengine::RT_INFINITY_F; - - return x; -} - -__inline float xexpf(float d) { - if(d<=-104.0f) return 0.0f; - - int q = rint(d * R_LN2f); - float s, u; - - s = mlaf(q, -L2Uf, d); - s = mlaf(q, -L2Lf, s); - - u = 0.00136324646882712841033936f; - u = mlaf(u, s, 0.00836596917361021041870117f); - u = mlaf(u, s, 0.0416710823774337768554688f); - u = mlaf(u, s, 0.166665524244308471679688f); - u = mlaf(u, s, 0.499999850988388061523438f); - - u = mlaf( s, mlaf(s,u,1.f),1.f); - return ldexpkf(u, q); - -} - -__inline float xmul2f(float d) { - union { - float floatval; - int intval; - } uflint; - uflint.floatval = d; - if (uflint.intval & 0x7FFFFFFF) { // if f==0 do nothing - uflint.intval += 1 << 23; // add 1 to the exponent - } - return uflint.floatval; -} - -__inline float xdiv2f(float d) { - union { - float floatval; - int intval; - } uflint; - uflint.floatval = d; - if (uflint.intval & 0x7FFFFFFF) { // if f==0 do nothing - uflint.intval -= 1 << 23; // sub 1 from the exponent - } - return uflint.floatval; -} - -__inline float xdivf( float d, int n){ - union { - float floatval; - int intval; - } uflint; - uflint.floatval = d; - if (uflint.intval & 0x7FFFFFFF) { // if f==0 do nothing - uflint.intval -= n << 23; // add n to the exponent - } - return uflint.floatval; -} - -__inline float xlin2log(float x, float base) -{ - constexpr float one(1); - return xlogf(x * (base - one) + one) / xlogf(base); -} - -__inline float xlog2lin(float x, float base) -{ - constexpr float one(1); - return (pow_F(base, x) - one) / (base - one); -} - -#endif diff --git a/rtengine/sleef.h b/rtengine/sleef.h new file mode 100644 index 000000000..fc23cbad9 --- /dev/null +++ b/rtengine/sleef.h @@ -0,0 +1,1308 @@ +//////////////////////////////////////////////////////////////// +// +// this code was taken from http://shibatch.sourceforge.net/ +// Many thanks to the author of original version: Naoki Shibata +// +// This version contains modifications made by Ingo Weyrich +// +//////////////////////////////////////////////////////////////// +#pragma once + +#include +#include +#include "rt_math.h" +#include "opthelper.h" + +#define PI4_A .7853981554508209228515625 +#define PI4_B .794662735614792836713604629039764404296875e-8 +#define PI4_C .306161699786838294306516483068750264552437361480769e-16 +#define M_4_PI 1.273239544735162542821171882678754627704620361328125 + +#define L2U .69314718055966295651160180568695068359375 +#define L2L .28235290563031577122588448175013436025525412068e-12 +#define R_LN2 1.442695040888963407359924681001892137426645954152985934135449406931 +#define pow_F(a,b) (xexpf(b*xlogf(a))) + +__inline int64_t doubleToRawLongBits(double d) { + union { + double f; + int64_t i; + } tmp; + tmp.f = d; + return tmp.i; +} + +__inline double longBitsToDouble(int64_t i) { + union { + double f; + int64_t i; + } tmp; + tmp.i = i; + return tmp.f; +} + +__inline double xfabs(double x) { + return longBitsToDouble(0x7fffffffffffffffLL & doubleToRawLongBits(x)); +} + +__inline double mulsign(double x, double y) { + return longBitsToDouble(doubleToRawLongBits(x) ^ (doubleToRawLongBits(y) & (1LL << 63))); +} + +__inline double sign(double d) { return mulsign(1, d); } +__inline double mla(double x, double y, double z) { return x * y + z; } +__inline double xrint(double x) { return x < 0 ? (int)(x - 0.5) : (int)(x + 0.5); } + +__inline int xisnan(double x) { return x != x; } +__inline int xisinf(double x) { return x == rtengine::RT_INFINITY || x == -rtengine::RT_INFINITY; } +__inline int xisminf(double x) { return x == -rtengine::RT_INFINITY; } +__inline int xispinf(double x) { return x == rtengine::RT_INFINITY; } + +__inline double ldexpk(double x, int q) { + double u; + int m; + m = q >> 31; + m = (((m + q) >> 9) - m) << 7; + q = q - (m << 2); + u = longBitsToDouble(((int64_t)(m + 0x3ff)) << 52); + double u2 = u*u; + u2 = u2 * u2; + x = x * u2; + u = longBitsToDouble(((int64_t)(q + 0x3ff)) << 52); + return x * u; +} + +__inline double xldexp(double x, int q) { return ldexpk(x, q); } + +__inline int ilogbp1(double d) { + int m = d < 4.9090934652977266E-91; + d = m ? 2.037035976334486E90 * d : d; + int q = (doubleToRawLongBits(d) >> 52) & 0x7ff; + q = m ? q - (300 + 0x03fe) : q - 0x03fe; + return q; +} + +__inline int xilogb(double d) { + int e = ilogbp1(xfabs(d)) - 1; + e = d == 0 ? (-2147483647 - 1) : e; + e = d == rtengine::RT_INFINITY || d == -rtengine::RT_INFINITY ? 2147483647 : e; + return e; +} + +__inline double upper(double d) { + return longBitsToDouble(doubleToRawLongBits(d) & 0xfffffffff8000000LL); +} + +typedef struct { + double x, y; +} double2; + +typedef struct { + float x, y; +} float2; + +__inline double2 dd(double h, double l) { + double2 ret; + ret.x = h; ret.y = l; + return ret; +} + +__inline double2 normalize_d(double2 t) { + double2 s; + + s.x = t.x + t.y; + s.y = t.x - s.x + t.y; + + return s; +} + +__inline double2 scale_d(double2 d, double s) { + double2 r; + + r.x = d.x * s; + r.y = d.y * s; + + return r; +} + +__inline double2 add2_ss(double x, double y) { + double2 r; + + r.x = x + y; + double v = r.x - x; + r.y = (x - (r.x - v)) + (y - v); + + return r; +} + +__inline double2 add_ds(double2 x, double y) { + // |x| >= |y| + + double2 r; + + assert(xisnan(x.x) || xisnan(y) || xfabs(x.x) >= xfabs(y)); + + r.x = x.x + y; + r.y = x.x - r.x + y + x.y; + + return r; +} + +__inline double2 add2_ds(double2 x, double y) { + // |x| >= |y| + + double2 r; + + r.x = x.x + y; + double v = r.x - x.x; + r.y = (x.x - (r.x - v)) + (y - v); + r.y += x.y; + + return r; +} + +__inline double2 add_sd(double x, double2 y) { + // |x| >= |y| + + double2 r; + + assert(xisnan(x) || xisnan(y.x) || xfabs(x) >= xfabs(y.x)); + + r.x = x + y.x; + r.y = x - r.x + y.x + y.y; + + return r; +} + +__inline double2 add_dd(double2 x, double2 y) { + // |x| >= |y| + + double2 r; + + assert(xisnan(x.x) || xisnan(y.x) || xfabs(x.x) >= xfabs(y.x)); + + r.x = x.x + y.x; + r.y = x.x - r.x + y.x + x.y + y.y; + + return r; +} + +__inline double2 add2_dd(double2 x, double2 y) { + double2 r; + + r.x = x.x + y.x; + double v = r.x - x.x; + r.y = (x.x - (r.x - v)) + (y.x - v); + r.y += x.y + y.y; + + return r; +} + +__inline double2 div_dd(double2 n, double2 d) { + double t = 1.0 / d.x; + double dh = upper(d.x), dl = d.x - dh; + double th = upper(t ), tl = t - th; + double nhh = upper(n.x), nhl = n.x - nhh; + + double2 q; + + q.x = n.x * t; + + double u = -q.x + nhh * th + nhh * tl + nhl * th + nhl * tl + + q.x * (1 - dh * th - dh * tl - dl * th - dl * tl); + + q.y = t * (n.y - q.x * d.y) + u; + + return q; +} + +__inline double2 mul_ss(double x, double y) { + double xh = upper(x), xl = x - xh; + double yh = upper(y), yl = y - yh; + double2 r; + + r.x = x * y; + r.y = xh * yh - r.x + xl * yh + xh * yl + xl * yl; + + return r; +} + +__inline double2 mul_ds(double2 x, double y) { + double xh = upper(x.x), xl = x.x - xh; + double yh = upper(y ), yl = y - yh; + double2 r; + + r.x = x.x * y; + r.y = xh * yh - r.x + xl * yh + xh * yl + xl * yl + x.y * y; + + return r; +} + +__inline double2 mul_dd(double2 x, double2 y) { + double xh = upper(x.x), xl = x.x - xh; + double yh = upper(y.x), yl = y.x - yh; + double2 r; + + r.x = x.x * y.x; + r.y = xh * yh - r.x + xl * yh + xh * yl + xl * yl + x.x * y.y + x.y * y.x; + + return r; +} + +__inline double2 squ_d(double2 x) { + double xh = upper(x.x), xl = x.x - xh; + double2 r; + + r.x = x.x * x.x; + r.y = xh * xh - r.x + (xh + xh) * xl + xl * xl + x.x * (x.y + x.y); + + return r; +} + +__inline double2 rec_s(double d) { + double t = 1.0 / d; + double dh = upper(d), dl = d - dh; + double th = upper(t), tl = t - th; + double2 q; + + q.x = t; + q.y = t * (1 - dh * th - dh * tl - dl * th - dl * tl); + + return q; +} + +__inline double2 sqrt_d(double2 d) { + double t = sqrt(d.x + d.y); + return scale_d(mul_dd(add2_dd(d, mul_ss(t, t)), rec_s(t)), 0.5); +} + +__inline double atan2k(double y, double x) { + double s, t, u; + int q = 0; + + if (x < 0) { x = -x; q = -2; } + if (y > x) { t = x; x = y; y = -t; q += 1; } + + s = y / x; + t = s * s; + + u = -1.88796008463073496563746e-05; + u = u * t + (0.000209850076645816976906797); + u = u * t + (-0.00110611831486672482563471); + u = u * t + (0.00370026744188713119232403); + u = u * t + (-0.00889896195887655491740809); + u = u * t + (0.016599329773529201970117); + u = u * t + (-0.0254517624932312641616861); + u = u * t + (0.0337852580001353069993897); + u = u * t + (-0.0407629191276836500001934); + u = u * t + (0.0466667150077840625632675); + u = u * t + (-0.0523674852303482457616113); + u = u * t + (0.0587666392926673580854313); + u = u * t + (-0.0666573579361080525984562); + u = u * t + (0.0769219538311769618355029); + u = u * t + (-0.090908995008245008229153); + u = u * t + (0.111111105648261418443745); + u = u * t + (-0.14285714266771329383765); + u = u * t + (0.199999999996591265594148); + u = u * t + (-0.333333333333311110369124); + + t = u * t * s + s; + t = q * (rtengine::RT_PI_2) + t; + + return t; +} + +__inline double xatan2(double y, double x) { + double r = atan2k(xfabs(y), x); + + r = mulsign(r, x); + if (xisinf(x) || x == 0) r = rtengine::RT_PI_2 - (xisinf(x) ? (sign(x) * (rtengine::RT_PI_2)) : 0); + if (xisinf(y) ) r = rtengine::RT_PI_2 - (xisinf(x) ? (sign(x) * (rtengine::RT_PI*1/4)) : 0); + if ( y == 0) r = (sign(x) == -1 ? rtengine::RT_PI : 0); + + return xisnan(x) || xisnan(y) ? rtengine::RT_NAN : mulsign(r, y); +} + +__inline double xasin(double d) { + return mulsign(atan2k(xfabs(d), sqrt((1+d)*(1-d))), d); +} + +__inline double xacos(double d) { + return mulsign(atan2k(sqrt((1+d)*(1-d)), xfabs(d)), d) + (d < 0 ? rtengine::RT_PI : 0); +} + +__inline double xatan(double s) { + double t, u; + int q = 0; + + if (s < 0) { s = -s; q = 2; } + if (s > 1) { s = 1.0 / s; q |= 1; } + + t = s * s; + + u = -1.88796008463073496563746e-05; + u = u * t + (0.000209850076645816976906797); + u = u * t + (-0.00110611831486672482563471); + u = u * t + (0.00370026744188713119232403); + u = u * t + (-0.00889896195887655491740809); + u = u * t + (0.016599329773529201970117); + u = u * t + (-0.0254517624932312641616861); + u = u * t + (0.0337852580001353069993897); + u = u * t + (-0.0407629191276836500001934); + u = u * t + (0.0466667150077840625632675); + u = u * t + (-0.0523674852303482457616113); + u = u * t + (0.0587666392926673580854313); + u = u * t + (-0.0666573579361080525984562); + u = u * t + (0.0769219538311769618355029); + u = u * t + (-0.090908995008245008229153); + u = u * t + (0.111111105648261418443745); + u = u * t + (-0.14285714266771329383765); + u = u * t + (0.199999999996591265594148); + u = u * t + (-0.333333333333311110369124); + + t = s + s * (t * u); + + if ((q & 1) != 0) t = 1.570796326794896557998982 - t; + if ((q & 2) != 0) t = -t; + + return t; +} + +__inline double xsin(double d) { + int q; + double u, s; + + q = (int)xrint(d * rtengine::RT_1_PI); + + d = mla(q, -PI4_A*4, d); + d = mla(q, -PI4_B*4, d); + d = mla(q, -PI4_C*4, d); + + s = d * d; + + if ((q & 1) != 0) d = -d; + + u = -7.97255955009037868891952e-18; + u = mla(u, s, 2.81009972710863200091251e-15); + u = mla(u, s, -7.64712219118158833288484e-13); + u = mla(u, s, 1.60590430605664501629054e-10); + u = mla(u, s, -2.50521083763502045810755e-08); + u = mla(u, s, 2.75573192239198747630416e-06); + u = mla(u, s, -0.000198412698412696162806809); + u = mla(u, s, 0.00833333333333332974823815); + u = mla(u, s, -0.166666666666666657414808); + + u = mla(s, u * d, d); + + return u; +} + +__inline double xcos(double d) { + int q; + double u, s; + + q = 1 + 2*(int)xrint(d * rtengine::RT_1_PI - 0.5); + + d = mla(q, -PI4_A*2, d); + d = mla(q, -PI4_B*2, d); + d = mla(q, -PI4_C*2, d); + + s = d * d; + + if ((q & 2) == 0) d = -d; + + u = -7.97255955009037868891952e-18; + u = mla(u, s, 2.81009972710863200091251e-15); + u = mla(u, s, -7.64712219118158833288484e-13); + u = mla(u, s, 1.60590430605664501629054e-10); + u = mla(u, s, -2.50521083763502045810755e-08); + u = mla(u, s, 2.75573192239198747630416e-06); + u = mla(u, s, -0.000198412698412696162806809); + u = mla(u, s, 0.00833333333333332974823815); + u = mla(u, s, -0.166666666666666657414808); + + u = mla(s, u * d, d); + + return u; +} + +__inline double2 xsincos(double d) { + int q; + double u, s, t; + double2 r; + + q = (int)xrint(d * (2 * rtengine::RT_1_PI)); + + s = d; + + s = mla(-q, PI4_A*2, s); + s = mla(-q, PI4_B*2, s); + s = mla(-q, PI4_C*2, s); + + t = s; + + s = s * s; + + u = 1.58938307283228937328511e-10; + u = mla(u, s, -2.50506943502539773349318e-08); + u = mla(u, s, 2.75573131776846360512547e-06); + u = mla(u, s, -0.000198412698278911770864914); + u = mla(u, s, 0.0083333333333191845961746); + u = mla(u, s, -0.166666666666666130709393); + u = u * s * t; + + r.x = t + u; + + u = -1.13615350239097429531523e-11; + u = mla(u, s, 2.08757471207040055479366e-09); + u = mla(u, s, -2.75573144028847567498567e-07); + u = mla(u, s, 2.48015872890001867311915e-05); + u = mla(u, s, -0.00138888888888714019282329); + u = mla(u, s, 0.0416666666666665519592062); + u = mla(u, s, -0.5); + + r.y = u * s + 1; + + if ((q & 1) != 0) { s = r.y; r.y = r.x; r.x = s; } + if ((q & 2) != 0) { r.x = -r.x; } + if (((q+1) & 2) != 0) { r.y = -r.y; } + + if (xisinf(d)) { r.x = r.y = rtengine::RT_NAN; } + + return r; +} + +__inline double xtan(double d) { + int q; + double u, s, x; + + q = (int)xrint(d * (2 * rtengine::RT_1_PI)); + + x = mla(q, -PI4_A*2, d); + x = mla(q, -PI4_B*2, x); + x = mla(q, -PI4_C*2, x); + + s = x * x; + + if ((q & 1) != 0) x = -x; + + u = 1.01419718511083373224408e-05; + u = mla(u, s, -2.59519791585924697698614e-05); + u = mla(u, s, 5.23388081915899855325186e-05); + u = mla(u, s, -3.05033014433946488225616e-05); + u = mla(u, s, 7.14707504084242744267497e-05); + u = mla(u, s, 8.09674518280159187045078e-05); + u = mla(u, s, 0.000244884931879331847054404); + u = mla(u, s, 0.000588505168743587154904506); + u = mla(u, s, 0.00145612788922812427978848); + u = mla(u, s, 0.00359208743836906619142924); + u = mla(u, s, 0.00886323944362401618113356); + u = mla(u, s, 0.0218694882853846389592078); + u = mla(u, s, 0.0539682539781298417636002); + u = mla(u, s, 0.133333333333125941821962); + u = mla(u, s, 0.333333333333334980164153); + + u = mla(s, u * x, x); + + if ((q & 1) != 0) u = 1.0 / u; + + if (xisinf(d)) u = rtengine::RT_NAN; + + return u; +} + +__inline double xlog(double d) { + double x, x2, t, m; + int e; + + e = ilogbp1(d * 0.7071); + m = ldexpk(d, -e); + + x = (m-1) / (m+1); + x2 = x * x; + + t = 0.148197055177935105296783; + t = mla(t, x2, 0.153108178020442575739679); + t = mla(t, x2, 0.181837339521549679055568); + t = mla(t, x2, 0.22222194152736701733275); + t = mla(t, x2, 0.285714288030134544449368); + t = mla(t, x2, 0.399999999989941956712869); + t = mla(t, x2, 0.666666666666685503450651); + t = mla(t, x2, 2); + + x = x * t + 0.693147180559945286226764 * e; + + if (xispinf(d)) x = rtengine::RT_INFINITY; + if (d < 0) x = rtengine::RT_NAN; + if (d == 0) x = -rtengine::RT_INFINITY; + + return x; +} + +__inline double xexp(double d) { + int q = (int)xrint(d * R_LN2); + double s, u; + + s = mla(q, -L2U, d); + s = mla(q, -L2L, s); + + u = 2.08860621107283687536341e-09; + u = mla(u, s, 2.51112930892876518610661e-08); + u = mla(u, s, 2.75573911234900471893338e-07); + u = mla(u, s, 2.75572362911928827629423e-06); + u = mla(u, s, 2.4801587159235472998791e-05); + u = mla(u, s, 0.000198412698960509205564975); + u = mla(u, s, 0.00138888888889774492207962); + u = mla(u, s, 0.00833333333331652721664984); + u = mla(u, s, 0.0416666666666665047591422); + u = mla(u, s, 0.166666666666666851703837); + u = mla(u, s, 0.5); + + u = s * s * u + s + 1; + u = ldexpk(u, q); + + if (xisminf(d)) u = 0; + + return u; +} + +__inline double2 logk(double d) { + double2 x, x2; + double m, t; + int e; + + e = ilogbp1(d * 0.7071); + m = ldexpk(d, -e); + + x = div_dd(add2_ss(-1, m), add2_ss(1, m)); + x2 = squ_d(x); + + t = 0.134601987501262130076155; + t = mla(t, x2.x, 0.132248509032032670243288); + t = mla(t, x2.x, 0.153883458318096079652524); + t = mla(t, x2.x, 0.181817427573705403298686); + t = mla(t, x2.x, 0.222222231326187414840781); + t = mla(t, x2.x, 0.285714285651261412873718); + t = mla(t, x2.x, 0.400000000000222439910458); + t = mla(t, x2.x, 0.666666666666666371239645); + + return add2_dd(mul_ds(dd(0.693147180559945286226764, 2.319046813846299558417771e-17), e), + add2_dd(scale_d(x, 2), mul_ds(mul_dd(x2, x), t))); +} + +__inline double expk(double2 d) { + int q = (int)rint((d.x + d.y) * R_LN2); + double2 s, t; + double u; + + s = add2_ds(d, q * -L2U); + s = add2_ds(s, q * -L2L); + + s = normalize_d(s); + + u = 2.51069683420950419527139e-08; + u = mla(u, s.x, 2.76286166770270649116855e-07); + u = mla(u, s.x, 2.75572496725023574143864e-06); + u = mla(u, s.x, 2.48014973989819794114153e-05); + u = mla(u, s.x, 0.000198412698809069797676111); + u = mla(u, s.x, 0.0013888888939977128960529); + u = mla(u, s.x, 0.00833333333332371417601081); + u = mla(u, s.x, 0.0416666666665409524128449); + u = mla(u, s.x, 0.166666666666666740681535); + u = mla(u, s.x, 0.500000000000000999200722); + + t = add_dd(s, mul_ds(squ_d(s), u)); + + t = add_sd(1, t); + return ldexpk(t.x + t.y, q); +} + +__inline double xpow(double x, double y) { + int yisint = (int)y == y; + int yisodd = (1 & (int)y) != 0 && yisint; + + double result = expk(mul_ds(logk(xfabs(x)), y)); + + result = xisnan(result) ? rtengine::RT_INFINITY : result; + result *= (x >= 0 ? 1 : (!yisint ? rtengine::RT_NAN : (yisodd ? -1 : 1))); + + double efx = mulsign(xfabs(x) - 1, y); + if (xisinf(y)) result = efx < 0 ? 0.0 : (efx == 0 ? 1.0 : rtengine::RT_INFINITY); + if (xisinf(x) || x == 0) result = (yisodd ? sign(x) : 1) * ((x == 0 ? -y : y) < 0 ? 0 : rtengine::RT_INFINITY); + if (xisnan(x) || xisnan(y)) result = rtengine::RT_NAN; + if (y == 0 || x == 1) result = 1; + + return result; +} + +__inline double2 expk2(double2 d) { + int q = (int)rint((d.x + d.y) * R_LN2); + double2 s, t; + double u; + + s = add2_ds(d, q * -L2U); + s = add2_ds(s, q * -L2L); + + s = normalize_d(s); + + u = 2.51069683420950419527139e-08; + u = mla(u, s.x, 2.76286166770270649116855e-07); + u = mla(u, s.x, 2.75572496725023574143864e-06); + u = mla(u, s.x, 2.48014973989819794114153e-05); + u = mla(u, s.x, 0.000198412698809069797676111); + u = mla(u, s.x, 0.0013888888939977128960529); + u = mla(u, s.x, 0.00833333333332371417601081); + u = mla(u, s.x, 0.0416666666665409524128449); + u = mla(u, s.x, 0.166666666666666740681535); + u = mla(u, s.x, 0.500000000000000999200722); + + t = add_dd(s, mul_ds(squ_d(s), u)); + + t = add_sd(1, t); + return dd(ldexpk(t.x, q), ldexpk(t.y, q)); +} + +__inline double xsinh(double x) { + double y = xfabs(x); + double2 d = expk2(dd(y, 0)); + d = add2_dd(d, div_dd(dd(-1, 0), d)); + y = (d.x + d.y) * 0.5; + + y = xisinf(x) || xisnan(y) ? rtengine::RT_INFINITY : y; + y = mulsign(y, x); + y = xisnan(x) ? rtengine::RT_NAN : y; + + return y; +} + +__inline double xcosh(double x) { + double2 d = expk2(dd(x, 0)); + d = add2_dd(d, div_dd(dd(1, 0), d)); + double y = (d.x + d.y) * 0.5; + + y = xisinf(x) || xisnan(y) ? rtengine::RT_INFINITY : y; + y = xisnan(x) ? rtengine::RT_NAN : y; + + return y; +} + +__inline double xtanh(double x) { + double y = xfabs(x); + double2 d = expk2(dd(y, 0)); + double2 e = div_dd(dd(1, 0), d); + d = div_dd(add2_dd(d, scale_d(e, -1)), add2_dd(d, e)); + y = d.x + d.y; + + y = xisinf(x) || xisnan(y) ? 1.0 : y; + y = mulsign(y, x); + y = xisnan(x) ? rtengine::RT_NAN : y; + + return y; +} + +__inline double2 logk2(double2 d) { + double2 x, x2, m; + double t; + int e; + + d = normalize_d(d); + e = ilogbp1(d.x * 0.7071); + m = scale_d(d, ldexpk(1, -e)); + + x = div_dd(add2_ds(m, -1), add2_ds(m, 1)); + x2 = squ_d(x); + + t = 0.134601987501262130076155; + t = mla(t, x2.x, 0.132248509032032670243288); + t = mla(t, x2.x, 0.153883458318096079652524); + t = mla(t, x2.x, 0.181817427573705403298686); + t = mla(t, x2.x, 0.222222231326187414840781); + t = mla(t, x2.x, 0.285714285651261412873718); + t = mla(t, x2.x, 0.400000000000222439910458); + t = mla(t, x2.x, 0.666666666666666371239645); + + return add2_dd(mul_ds(dd(0.693147180559945286226764, 2.319046813846299558417771e-17), e), + add2_dd(scale_d(x, 2), mul_ds(mul_dd(x2, x), t))); +} + +__inline double xasinh(double x) { + double y = xfabs(x); + double2 d = logk2(add2_ds(sqrt_d(add2_ds(mul_ss(y, y), 1)), y)); + y = d.x + d.y; + + y = xisinf(x) || xisnan(y) ? rtengine::RT_INFINITY : y; + y = mulsign(y, x); + y = xisnan(x) ? rtengine::RT_NAN : y; + + return y; +} + +__inline double xacosh(double x) { + double2 d = logk2(add2_ds(sqrt_d(add2_ds(mul_ss(x, x), -1)), x)); + double y = d.x + d.y; + + y = xisinf(x) || xisnan(y) ? rtengine::RT_INFINITY : y; + y = x == 1.0 ? 0.0 : y; + y = x < 1.0 ? rtengine::RT_NAN : y; + y = xisnan(x) ? rtengine::RT_NAN : y; + + return y; +} + +__inline double xatanh(double x) { + double y = xfabs(x); + double2 d = logk2(div_dd(add2_ss(1, y), add2_ss(1, -y))); + y = y > 1.0 ? rtengine::RT_NAN : (y == 1.0 ? rtengine::RT_INFINITY : (d.x + d.y) * 0.5); + + y = xisinf(x) || xisnan(y) ? rtengine::RT_NAN : y; + y = mulsign(y, x); + y = xisnan(x) ? rtengine::RT_NAN : y; + + return y; +} + +// + +__inline double xfma(double x, double y, double z) { + union { + double f; + long long int i; + } tmp; + + tmp.f = x; + tmp.i = (tmp.i + 0x4000000) & 0xfffffffff8000000LL; + double xh = tmp.f, xl = x - xh; + + tmp.f = y; + tmp.i = (tmp.i + 0x4000000) & 0xfffffffff8000000LL; + double yh = tmp.f, yl = y - yh; + + double h = x * y; + double l = xh * yh - h + xl * yh + xh * yl + xl * yl; + + double h2, l2, v; + + h2 = h + z; + v = h2 - h; + l2 = (h - (h2 - v)) + (z - v) + l; + + return h2 + l2; +} + +__inline double xsqrt(double d) { // max error : 0.5 ulp + double q = 1; + + if (d < 8.636168555094445E-78) { + d *= 1.157920892373162E77; + q = 2.9387358770557188E-39; + } + + // http://en.wikipedia.org/wiki/Fast_inverse_square_root + double x = longBitsToDouble(0x5fe6ec85e7de30da - (doubleToRawLongBits(d + 1e-320) >> 1)); + + x = x * (1.5 - 0.5 * d * x * x); + x = x * (1.5 - 0.5 * d * x * x); + x = x * (1.5 - 0.5 * d * x * x); + + // You can change xfma to fma if fma is correctly implemented + x = xfma(d * x, d * x, -d) * (x * -0.5) + d * x; + + return d == rtengine::RT_INFINITY ? rtengine::RT_INFINITY : x * q; +} + +__inline double xcbrt(double d) { // max error : 2 ulps + double x, y, q = 1.0; + int e, r; + + e = ilogbp1(d); + d = ldexpk(d, -e); + r = (e + 6144) % 3; + q = (r == 1) ? 1.2599210498948731647672106 : q; + q = (r == 2) ? 1.5874010519681994747517056 : q; + q = ldexpk(q, (e + 6144) / 3 - 2048); + + q = mulsign(q, d); + d = xfabs(d); + + x = -0.640245898480692909870982; + x = x * d + 2.96155103020039511818595; + x = x * d + -5.73353060922947843636166; + x = x * d + 6.03990368989458747961407; + x = x * d + -3.85841935510444988821632; + x = x * d + 2.2307275302496609725722; + + y = x * x; y = y * y; x -= (d * y - x) * (1.0 / 3.0); + y = d * x * x; + y = (y - (2.0 / 3.0) * y * (y * x - 1)) * q; + + return y; +} + +__inline double xexp2(double a) { + double u = expk(mul_ds(dd(0.69314718055994528623, 2.3190468138462995584e-17), a)); + if (xispinf(a)) u = rtengine::RT_INFINITY; + if (xisminf(a)) u = 0; + return u; +} + +__inline double xexp10(double a) { + double u = expk(mul_ds(dd(2.3025850929940459011, -2.1707562233822493508e-16), a)); + if (xispinf(a)) u = rtengine::RT_INFINITY; + if (xisminf(a)) u = 0; + return u; +} + +__inline double xexpm1(double a) { + double2 d = add2_ds(expk2(dd(a, 0)), -1.0); + double x = d.x + d.y; + if (xispinf(a)) x = rtengine::RT_INFINITY; + if (xisminf(a)) x = -1; + return x; +} + +__inline double xlog10(double a) { + double2 d = mul_dd(logk(a), dd(0.43429448190325176116, 6.6494347733425473126e-17)); + double x = d.x + d.y; + + if (xispinf(a)) x = rtengine::RT_INFINITY; + if (a < 0) x = rtengine::RT_NAN; + if (a == 0) x = -rtengine::RT_INFINITY; + + return x; +} + +__inline double xlog1p(double a) { + double2 d = logk2(add2_ss(a, 1)); + double x = d.x + d.y; + + if (xispinf(a)) x = rtengine::RT_INFINITY; + if (a < -1) x = rtengine::RT_NAN; + if (a == -1) x = -rtengine::RT_INFINITY; + + return x; +} + +/////////////////////////////////////////// + +#define PI4_Af 0.78515625f +#define PI4_Bf 0.00024127960205078125f +#define PI4_Cf 6.3329935073852539062e-07f +#define PI4_Df 4.9604681473525147339e-10f + +#define L2Uf 0.693145751953125f +#define L2Lf 1.428606765330187045e-06f + +#define R_LN2f 1.442695040888963407359924681001892137426645954152985934135449406931f + +#ifdef __SSE2__ +__inline int xrintf(float x) { + return _mm_cvt_ss2si(_mm_set_ss(x)); +} +#else +__inline int xrintf(float x) { + return x + (x < 0 ? -0.5f : 0.5f); +} +#endif +__inline int32_t floatToRawIntBits(float d) { + union { + float f; + int32_t i; + } tmp; + tmp.f = d; + return tmp.i; +} + +__inline float intBitsToFloat(int32_t i) { + union { + float f; + int32_t i; + } tmp; + tmp.i = i; + return tmp.f; +} + +__inline float xfabsf(float x) { + return intBitsToFloat(0x7fffffffL & floatToRawIntBits(x)); +} + +__inline float mulsignf(float x, float y) { + return intBitsToFloat(floatToRawIntBits(x) ^ (floatToRawIntBits(y) & (1 << 31))); +} + +__inline float signf(float d) { return std::copysign(1.f, d); } +__inline float mlaf(float x, float y, float z) { return x * y + z; } + +__inline int xisnanf(float x) { return x != x; } +__inline int xisinff(float x) { return x == rtengine::RT_INFINITY_F || x == -rtengine::RT_INFINITY_F; } +__inline int xisminff(float x) { return x == -rtengine::RT_INFINITY_F; } +__inline int xispinff(float x) { return x == rtengine::RT_INFINITY_F; } + +__inline int ilogbp1f(float d) { + int m = d < 5.421010862427522E-20f; + d = m ? 1.8446744073709552E19f * d : d; + int q = (floatToRawIntBits(d) >> 23) & 0xff; + q = m ? q - (64 + 0x7e) : q - 0x7e; + return q; +} + +__inline float ldexpkf(float x, int q) { + float u; + int m; + m = q >> 31; + m = (((m + q) >> 6) - m) << 4; + q = q - (m << 2); + u = intBitsToFloat(((int32_t)(m + 0x7f)) << 23); + u = u * u; + x = x * u * u; + u = intBitsToFloat(((int32_t)(q + 0x7f)) << 23); + return x * u; +} + +__inline float xcbrtf(float d) { // max error : 2 ulps + float x, y, q = 1.0f; + int e, r; + + e = ilogbp1f(d); + d = ldexpkf(d, -e); + r = (e + 6144) % 3; + q = (r == 1) ? 1.2599210498948731647672106f : q; + q = (r == 2) ? 1.5874010519681994747517056f : q; + q = ldexpkf(q, (e + 6144) / 3 - 2048); + + q = mulsignf(q, d); + d = xfabsf(d); + + x = -0.601564466953277587890625f; + x = mlaf(x, d, 2.8208892345428466796875f); + x = mlaf(x, d, -5.532182216644287109375f); + x = mlaf(x, d, 5.898262500762939453125f); + x = mlaf(x, d, -3.8095417022705078125f); + x = mlaf(x, d, 2.2241256237030029296875f); + + y = d * x * x; + y = (y - (2.0f / 3.0f) * y * (y * x - 1.0f)) * q; + + return y; +} + +__inline float xsinf(float d) { + int q; + float u, s; + + q = xrintf(d * rtengine::RT_1_PI_F); + + d = mlaf(q, -PI4_Af*4, d); + d = mlaf(q, -PI4_Bf*4, d); + d = mlaf(q, -PI4_Cf*4, d); + d = mlaf(q, -PI4_Df*4, d); + + s = d * d; + + if ((q & 1) != 0) d = -d; + + u = 2.6083159809786593541503e-06f; + u = mlaf(u, s, -0.0001981069071916863322258f); + u = mlaf(u, s, 0.00833307858556509017944336f); + u = mlaf(u, s, -0.166666597127914428710938f); + + u = mlaf(s, u * d, d); + + return u; +} + +__inline float xcosf(float d) { +#ifdef __SSE2__ + // faster than scalar version + return xcosf(_mm_set_ss(d))[0]; +#else + int q; + float u, s; + + q = 1 + 2*xrintf(d * rtengine::RT_1_PI_F - 0.5f); + + d = mlaf(q, -PI4_Af*2, d); + d = mlaf(q, -PI4_Bf*2, d); + d = mlaf(q, -PI4_Cf*2, d); + d = mlaf(q, -PI4_Df*2, d); + + s = d * d; + + if ((q & 2) == 0) d = -d; + + u = 2.6083159809786593541503e-06f; + u = mlaf(u, s, -0.0001981069071916863322258f); + u = mlaf(u, s, 0.00833307858556509017944336f); + u = mlaf(u, s, -0.166666597127914428710938f); + + u = mlaf(s, u * d, d); + + return u; +#endif +} + +__inline float2 xsincosf(float d) { +#ifdef __SSE2__ + // faster than scalar version + vfloat2 res = xsincosf(_mm_set_ss(d)); + return {res.x[0], res.y[0]}; +#else + int q; + float u, s, t; + float2 r; + + q = xrintf(d * rtengine::RT_2_PI_F); + + s = d; + + s = mlaf(q, -PI4_Af*2, s); + s = mlaf(q, -PI4_Bf*2, s); + s = mlaf(q, -PI4_Cf*2, s); + s = mlaf(q, -PI4_Df*2, s); + + t = s; + + s = s * s; + + u = -0.000195169282960705459117889f; + u = mlaf(u, s, 0.00833215750753879547119141f); + u = mlaf(u, s, -0.166666537523269653320312f); + u = u * s * t; + + r.x = t + u; + + u = -2.71811842367242206819355e-07f; + u = mlaf(u, s, 2.47990446951007470488548e-05f); + u = mlaf(u, s, -0.00138888787478208541870117f); + u = mlaf(u, s, 0.0416666641831398010253906f); + u = mlaf(u, s, -0.5f); + + r.y = u * s + 1; + + if ((q & 1) != 0) { s = r.y; r.y = r.x; r.x = s; } + if ((q & 2) != 0) { r.x = -r.x; } + if (((q+1) & 2) != 0) { r.y = -r.y; } + + if (xisinff(d)) { r.x = r.y = rtengine::RT_NAN_F; } + + return r; +#endif +} + +__inline float xtanf(float d) { + int q; + float u, s, x; + + q = xrintf(d * (float)(2 * rtengine::RT_1_PI)); + + x = d; + + x = mlaf(q, -PI4_Af*2, x); + x = mlaf(q, -PI4_Bf*2, x); + x = mlaf(q, -PI4_Cf*2, x); + x = mlaf(q, -PI4_Df*2, x); + + s = x * x; + + if ((q & 1) != 0) x = -x; + + u = 0.00927245803177356719970703f; + u = mlaf(u, s, 0.00331984995864331722259521f); + u = mlaf(u, s, 0.0242998078465461730957031f); + u = mlaf(u, s, 0.0534495301544666290283203f); + u = mlaf(u, s, 0.133383005857467651367188f); + u = mlaf(u, s, 0.333331853151321411132812f); + + u = mlaf(s, u * x, x); + + if ((q & 1) != 0) u = 1.0f / u; + + if (xisinff(d)) u = rtengine::RT_NAN_F; + + return u; +} + +__inline float xatanf(float s) { + float t, u; + int q = 0; + + if (s < 0) { s = -s; q = 2; } + if (s > 1) { s = 1.0f / s; q |= 1; } + + t = s * s; + + u = 0.00282363896258175373077393f; + u = mlaf(u, t, -0.0159569028764963150024414f); + u = mlaf(u, t, 0.0425049886107444763183594f); + u = mlaf(u, t, -0.0748900920152664184570312f); + u = mlaf(u, t, 0.106347933411598205566406f); + u = mlaf(u, t, -0.142027363181114196777344f); + u = mlaf(u, t, 0.199926957488059997558594f); + u = mlaf(u, t, -0.333331018686294555664062f); + + t = s + s * (t * u); + + if ((q & 1) != 0) t = 1.570796326794896557998982f - t; + if ((q & 2) != 0) t = -t; + + return t; +} + +__inline float atan2kf(float y, float x) { + float s, t, u; + float q = 0.f; + + if (x < 0) { x = -x; q = -2.f; } + if (y > x) { t = x; x = y; y = -t; q += 1.f; } + + s = y / x; + t = s * s; + + u = 0.00282363896258175373077393f; + u = mlaf(u, t, -0.0159569028764963150024414f); + u = mlaf(u, t, 0.0425049886107444763183594f); + u = mlaf(u, t, -0.0748900920152664184570312f); + u = mlaf(u, t, 0.106347933411598205566406f); + u = mlaf(u, t, -0.142027363181114196777344f); + u = mlaf(u, t, 0.199926957488059997558594f); + u = mlaf(u, t, -0.333331018686294555664062f); + + t = u * t; + t = mlaf(t,s,s); + return mlaf(q,(float)(rtengine::RT_PI_F_2),t); +} + +__inline float xatan2f(float y, float x) { + float r = atan2kf(xfabsf(y), x); + + r = mulsignf(r, x); + if (xisinff(x) || x == 0) r = rtengine::RT_PI_F/2 - (xisinff(x) ? (signf(x) * (float)(rtengine::RT_PI_F*.5f)) : 0); + if (xisinff(y) ) r = rtengine::RT_PI_F/2 - (xisinff(x) ? (signf(x) * (float)(rtengine::RT_PI_F*.25f)) : 0); + if ( y == 0) r = (signf(x) == -1 ? rtengine::RT_PI_F : 0); + + return xisnanf(x) || xisnanf(y) ? rtengine::RT_NAN_F : mulsignf(r, y); +} + +__inline float xasinf(float d) { + return mulsignf(atan2kf(fabsf(d), sqrtf((1.0f+d)*(1.0f-d))), d); +} + +__inline float xacosf(float d) { + return mulsignf(atan2kf(sqrtf((1.0f+d)*(1.0f-d)), fabsf(d)), d) + (d < 0 ? (float)rtengine::RT_PI : 0.0f); +} + +__inline float xlogf(float d) { + float x, x2, t, m; + int e; + + e = ilogbp1f(d * 0.7071f); + m = ldexpkf(d, -e); + + x = (m-1.0f) / (m+1.0f); + x2 = x * x; + + t = 0.2371599674224853515625f; + t = mlaf(t, x2, 0.285279005765914916992188f); + t = mlaf(t, x2, 0.400005519390106201171875f); + t = mlaf(t, x2, 0.666666567325592041015625f); + t = mlaf(t, x2, 2.0f); + + x = x * t + 0.693147180559945286226764f * e; + + if (xispinff(d)) x = rtengine::RT_INFINITY_F; + if (d < 0) x = rtengine::RT_NAN_F; + if (d == 0) x = -rtengine::RT_INFINITY_F; + + return x; +} + +__inline float xlogf1(float d) { // does xlogf(vmaxf(d, 1.f)) but faster + float x, x2, t, m; + int e; + + e = ilogbp1f(d * 0.7071f); + m = ldexpkf(d, -e); + + x = (m-1.0f) / (m+1.0f); + x2 = x * x; + + t = 0.2371599674224853515625f; + t = mlaf(t, x2, 0.285279005765914916992188f); + t = mlaf(t, x2, 0.400005519390106201171875f); + t = mlaf(t, x2, 0.666666567325592041015625f); + t = mlaf(t, x2, 2.0f); + + x = x * t + 0.693147180559945286226764f * e; + + if (xispinff(d)) x = rtengine::RT_INFINITY_F; + if (d <= 1.f) x = 0; + + return x; +} + +__inline float xexpf(float d) { + if(d<=-104.0f) return 0.0f; + + int q = xrintf(d * R_LN2f); + float s, u; + + s = mlaf(q, -L2Uf, d); + s = mlaf(q, -L2Lf, s); + + u = 0.00136324646882712841033936f; + u = mlaf(u, s, 0.00836596917361021041870117f); + u = mlaf(u, s, 0.0416710823774337768554688f); + u = mlaf(u, s, 0.166665524244308471679688f); + u = mlaf(u, s, 0.499999850988388061523438f); + + u = mlaf( s, mlaf(s,u,1.f),1.f); + return ldexpkf(u, q); + +} + +__inline float xmul2f(float d) { + union { + float floatval; + int intval; + } uflint; + uflint.floatval = d; + if (uflint.intval & 0x7FFFFFFF) { // if f==0 do nothing + uflint.intval += 1 << 23; // add 1 to the exponent + } + return uflint.floatval; +} + +__inline float xdiv2f(float d) { + union { + float floatval; + int intval; + } uflint; + uflint.floatval = d; + if (uflint.intval & 0x7FFFFFFF) { // if f==0 do nothing + uflint.intval -= 1 << 23; // sub 1 from the exponent + } + return uflint.floatval; +} + +__inline float xdivf( float d, int n){ + union { + float floatval; + int intval; + } uflint; + uflint.floatval = d; + if (uflint.intval & 0x7FFFFFFF) { // if f==0 do nothing + uflint.intval -= n << 23; // add n to the exponent + } + return uflint.floatval; +} + +__inline float xlin2log(float x, float base) +{ + constexpr float one(1); + return xlogf(x * (base - one) + one) / xlogf(base); +} + +__inline float xlog2lin(float x, float base) +{ + constexpr float one(1); + return (pow_F(base, x) - one) / (base - one); +} diff --git a/rtengine/sleefsseavx.c b/rtengine/sleefsseavx.c deleted file mode 100644 index 3000c1c10..000000000 --- a/rtengine/sleefsseavx.c +++ /dev/null @@ -1,1447 +0,0 @@ -//////////////////////////////////////////////////////////////// -// -// this code was taken from http://shibatch.sourceforge.net/ -// Many thanks to the author of original version: Naoki Shibata -// -// This version contains modifications made by Ingo Weyrich -// -//////////////////////////////////////////////////////////////// - - -#ifndef SLEEFSSEAVX -#define SLEEFSSEAVX - -#include -#include "rt_math.h" -#ifdef __SSE2__ -#include "helpersse2.h" - -#ifdef ENABLE_AVX -#include "helperavx.h" -#endif - -#ifdef __GNUC__ -#define INLINE __inline -#else -#define INLINE inline -#endif - -#define PI4_A .7853981554508209228515625 -#define PI4_B .794662735614792836713604629039764404296875e-8 -#define PI4_C .306161699786838294306516483068750264552437361480769e-16 -#define M_4_PI 1.273239544735162542821171882678754627704620361328125 - -#define L2U .69314718055966295651160180568695068359375 -#define L2L .28235290563031577122588448175013436025525412068e-12 -#define R_LN2 1.442695040888963407359924681001892137426645954152985934135449406931 - -#define PI4_Af 0.78515625f -#define PI4_Bf 0.00024127960205078125f -#define PI4_Cf 6.3329935073852539062e-07f -#define PI4_Df 4.9604681473525147339e-10f - -#define L2Uf 0.693145751953125f -#define L2Lf 1.428606765330187045e-06f -#define R_LN2f 1.442695040888963407359924681001892137426645954152985934135449406931f - -#define INFINITYf ((float)rtengine::RT_INFINITY) -#define NANf ((float)rtengine::RT_NAN) - -static INLINE vdouble vadd3(vdouble v0, vdouble v1, vdouble v2) { - return vadd(vadd(v0, v1), v2); -} - -static INLINE vdouble vadd4(vdouble v0, vdouble v1, vdouble v2, vdouble v3) { - return vadd3(vadd(v0, v1), v2, v3); -} - -static INLINE vdouble vadd5(vdouble v0, vdouble v1, vdouble v2, vdouble v3, vdouble v4) { - return vadd4(vadd(v0, v1), v2, v3, v4); -} - -static INLINE vdouble vadd6(vdouble v0, vdouble v1, vdouble v2, vdouble v3, vdouble v4, vdouble v5) { - return vadd5(vadd(v0, v1), v2, v3, v4, v5); -} - -static INLINE vdouble vadd7(vdouble v0, vdouble v1, vdouble v2, vdouble v3, vdouble v4, vdouble v5, vdouble v6) { - return vadd6(vadd(v0, v1), v2, v3, v4, v5, v6); -} - -static INLINE vdouble vsub3(vdouble v0, vdouble v1, vdouble v2) { - return vsub(vsub(v0, v1), v2); -} - -static INLINE vdouble vsub4(vdouble v0, vdouble v1, vdouble v2, vdouble v3) { - return vsub3(vsub(v0, v1), v2, v3); -} - -static INLINE vdouble vsub5(vdouble v0, vdouble v1, vdouble v2, vdouble v3, vdouble v4) { - return vsub4(vsub(v0, v1), v2, v3, v4); -} - -// - -static INLINE vdouble2 normalize_d(vdouble2 t) { - vdouble2 s; - - s.x = vadd(t.x, t.y); - s.y = vadd(vsub(t.x, s.x), t.y); - - return s; -} - -static INLINE vdouble2 scale_d(vdouble2 d, vdouble s) { - vdouble2 r = {vmul(d.x, s), vmul(d.y, s)}; - return r; -} - -static INLINE vdouble2 add_ss(vdouble x, vdouble y) { - vdouble2 r; - - r.x = vadd(x, y); - r.y = vadd(vsub(x, r.x), y); - - return r; -} - -static INLINE vdouble2 add2_ss(vdouble x, vdouble y) { - vdouble2 r; - - r.x = vadd(x, y); - vdouble v = vsub(r.x, x); - r.y = vadd(vsub(x, vsub(r.x, v)), vsub(y, v)); - - return r; -} - -static INLINE vdouble2 add_ds(vdouble2 x, vdouble y) { - vdouble2 r; - - r.x = vadd(x.x, y); - r.y = vadd3(vsub(x.x, r.x), y, x.y); - - return r; -} - -static INLINE vdouble2 add2_ds(vdouble2 x, vdouble y) { - vdouble2 r; - - r.x = vadd(x.x, y); - vdouble v = vsub(r.x, x.x); - r.y = vadd(vsub(x.x, vsub(r.x, v)), vsub(y, v)); - r.y = vadd(r.y, x.y); - - return r; -} - -static INLINE vdouble2 add_sd(vdouble x, vdouble2 y) { - vdouble2 r; - - r.x = vadd(x, y.x); - r.y = vadd3(vsub(x, r.x), y.x, y.y); - - return r; -} - -static INLINE vdouble2 add_dd(vdouble2 x, vdouble2 y) { - // |x| >= |y| - - vdouble2 r; - - r.x = vadd(x.x, y.x); - r.y = vadd4(vsub(x.x, r.x), y.x, x.y, y.y); - - return r; -} - -static INLINE vdouble2 add2_dd(vdouble2 x, vdouble2 y) { - vdouble2 r; - - r.x = vadd(x.x, y.x); - vdouble v = vsub(r.x, x.x); - r.y = vadd(vsub(x.x, vsub(r.x, v)), vsub(y.x, v)); - r.y = vadd(r.y, vadd(x.y, y.y)); - - return r; -} - -static INLINE vdouble2 div_dd(vdouble2 n, vdouble2 d) { - vdouble t = vrec(d.x); - vdouble dh = vupper(d.x), dl = vsub(d.x, dh); - vdouble th = vupper(t ), tl = vsub(t , th); - vdouble nhh = vupper(n.x), nhl = vsub(n.x, nhh); - - vdouble2 q; - - q.x = vmul(n.x, t); - - vdouble u = vadd5(vsub(vmul(nhh, th), q.x), vmul(nhh, tl), vmul(nhl, th), vmul(nhl, tl), - vmul(q.x, vsub5(vcast_vd_d(1), vmul(dh, th), vmul(dh, tl), vmul(dl, th), vmul(dl, tl)))); - - q.y = vadd(vmul(t, vsub(n.y, vmul(q.x, d.y))), u); - - return q; -} - -static INLINE vdouble2 mul_ss(vdouble x, vdouble y) { - vdouble xh = vupper(x), xl = vsub(x, xh); - vdouble yh = vupper(y), yl = vsub(y, yh); - vdouble2 r; - - r.x = vmul(x, y); - r.y = vadd5(vmul(xh, yh), vneg(r.x), vmul(xl, yh), vmul(xh, yl), vmul(xl, yl)); - - return r; -} - -static INLINE vdouble2 mul_ds(vdouble2 x, vdouble y) { - vdouble xh = vupper(x.x), xl = vsub(x.x, xh); - vdouble yh = vupper(y ), yl = vsub(y , yh); - vdouble2 r; - - r.x = vmul(x.x, y); - r.y = vadd6(vmul(xh, yh), vneg(r.x), vmul(xl, yh), vmul(xh, yl), vmul(xl, yl), vmul(x.y, y)); - - return r; -} - -static INLINE vdouble2 mul_dd(vdouble2 x, vdouble2 y) { - vdouble xh = vupper(x.x), xl = vsub(x.x, xh); - vdouble yh = vupper(y.x), yl = vsub(y.x, yh); - vdouble2 r; - - r.x = vmul(x.x, y.x); - r.y = vadd7(vmul(xh, yh), vneg(r.x), vmul(xl, yh), vmul(xh, yl), vmul(xl, yl), vmul(x.x, y.y), vmul(x.y, y.x)); - - return r; -} - -static INLINE vdouble2 squ_d(vdouble2 x) { - vdouble xh = vupper(x.x), xl = vsub(x.x, xh); - vdouble2 r; - - r.x = vmul(x.x, x.x); - r.y = vadd5(vmul(xh, xh), vneg(r.x), vmul(vadd(xh, xh), xl), vmul(xl, xl), vmul(x.x, vadd(x.y, x.y))); - - return r; -} - -static INLINE vdouble2 rec_s(vdouble d) { - vdouble t = vrec(d); - vdouble dh = vupper(d), dl = vsub(d, dh); - vdouble th = vupper(t), tl = vsub(t, th); - vdouble2 q; - - q.x = t; - q.y = vmul(t, vsub5(vcast_vd_d(1), vmul(dh, th), vmul(dh, tl), vmul(dl, th), vmul(dl, tl))); - - return q; -} - -static INLINE vdouble2 sqrt_d(vdouble2 d) { - vdouble t = vsqrt(vadd(d.x, d.y)); - return scale_d(mul_dd(add2_dd(d, mul_ss(t, t)), rec_s(t)), vcast_vd_d(0.5)); -} - -// - -static INLINE vdouble xldexp(vdouble x, vint q) { return vldexp(x, q); } - -static INLINE vint xilogb(vdouble d) { - vdouble e = vcast_vd_vi(vsubi(vilogbp1(vabs(d)), vcast_vi_i(1))); - e = vsel(vmask_eq(d, vcast_vd_d(0)), vcast_vd_d(-2147483648.0), e); - e = vsel(vmask_eq(vabs(d), vcast_vd_d(rtengine::RT_INFINITY)), vcast_vd_d(2147483647), e); - return vrint_vi_vd(e); -} - -static INLINE vdouble xsin(vdouble d) { - vint q; - vdouble u, s; - - q = vrint_vi_vd(vmul(d, vcast_vd_d(rtengine::RT_1_PI))); - - u = vcast_vd_vi(q); - d = vadd(d, vmul(u, vcast_vd_d(-PI4_A*4))); - d = vadd(d, vmul(u, vcast_vd_d(-PI4_B*4))); - d = vadd(d, vmul(u, vcast_vd_d(-PI4_C*4))); - - s = vmul(d, d); - - d = vsel(vmaski_eq(vandi(q, vcast_vi_i(1)), vcast_vi_i(1)), vneg(d), d); - - u = vcast_vd_d(-7.97255955009037868891952e-18); - u = vmla(u, s, vcast_vd_d(2.81009972710863200091251e-15)); - u = vmla(u, s, vcast_vd_d(-7.64712219118158833288484e-13)); - u = vmla(u, s, vcast_vd_d(1.60590430605664501629054e-10)); - u = vmla(u, s, vcast_vd_d(-2.50521083763502045810755e-08)); - u = vmla(u, s, vcast_vd_d(2.75573192239198747630416e-06)); - u = vmla(u, s, vcast_vd_d(-0.000198412698412696162806809)); - u = vmla(u, s, vcast_vd_d(0.00833333333333332974823815)); - u = vmla(u, s, vcast_vd_d(-0.166666666666666657414808)); - - u = vmla(s, vmul(u, d), d); - - return u; -} - -static INLINE vdouble xcos(vdouble d) { - vint q; - vdouble u, s; - - q = vrint_vi_vd(vsub(vmul(d, vcast_vd_d(rtengine::RT_1_PI)), vcast_vd_d(0.5))); - q = vaddi(vaddi(q, q), vcast_vi_i(1)); - - u = vcast_vd_vi(q); - d = vadd(d, vmul(u, vcast_vd_d(-PI4_A*2))); - d = vadd(d, vmul(u, vcast_vd_d(-PI4_B*2))); - d = vadd(d, vmul(u, vcast_vd_d(-PI4_C*2))); - - s = vmul(d, d); - - d = vsel(vmaski_eq(vandi(q, vcast_vi_i(2)), vcast_vi_i(0)), vneg(d), d); - - u = vcast_vd_d(-7.97255955009037868891952e-18); - u = vmla(u, s, vcast_vd_d(2.81009972710863200091251e-15)); - u = vmla(u, s, vcast_vd_d(-7.64712219118158833288484e-13)); - u = vmla(u, s, vcast_vd_d(1.60590430605664501629054e-10)); - u = vmla(u, s, vcast_vd_d(-2.50521083763502045810755e-08)); - u = vmla(u, s, vcast_vd_d(2.75573192239198747630416e-06)); - u = vmla(u, s, vcast_vd_d(-0.000198412698412696162806809)); - u = vmla(u, s, vcast_vd_d(0.00833333333333332974823815)); - u = vmla(u, s, vcast_vd_d(-0.166666666666666657414808)); - - u = vmla(s, vmul(u, d), d); - - return u; -} - -static INLINE vdouble2 xsincos(vdouble d) { - vint q; - vmask m; - vdouble u, s, t, rx, ry; - vdouble2 r; - - q = vrint_vi_vd(vmul(d, vcast_vd_d(rtengine::RT_2_PI))); - - s = d; - - u = vcast_vd_vi(q); - s = vmla(u, vcast_vd_d(-PI4_A*2), s); - s = vmla(u, vcast_vd_d(-PI4_B*2), s); - s = vmla(u, vcast_vd_d(-PI4_C*2), s); - - t = s; - - s = vmul(s, s); - - u = vcast_vd_d(1.58938307283228937328511e-10); - u = vmla(u, s, vcast_vd_d(-2.50506943502539773349318e-08)); - u = vmla(u, s, vcast_vd_d(2.75573131776846360512547e-06)); - u = vmla(u, s, vcast_vd_d(-0.000198412698278911770864914)); - u = vmla(u, s, vcast_vd_d(0.0083333333333191845961746)); - u = vmla(u, s, vcast_vd_d(-0.166666666666666130709393)); - u = vmul(vmul(u, s), t); - - rx = vadd(t, u); - - u = vcast_vd_d(-1.13615350239097429531523e-11); - u = vmla(u, s, vcast_vd_d(2.08757471207040055479366e-09)); - u = vmla(u, s, vcast_vd_d(-2.75573144028847567498567e-07)); - u = vmla(u, s, vcast_vd_d(2.48015872890001867311915e-05)); - u = vmla(u, s, vcast_vd_d(-0.00138888888888714019282329)); - u = vmla(u, s, vcast_vd_d(0.0416666666666665519592062)); - u = vmla(u, s, vcast_vd_d(-0.5)); - - ry = vadd(vcast_vd_d(1), vmul(s, u)); - - m = vmaski_eq(vandi(q, vcast_vi_i(1)), vcast_vi_i(0)); - r.x = vsel(m, rx, ry); - r.y = vsel(m, ry, rx); - - m = vmaski_eq(vandi(q, vcast_vi_i(2)), vcast_vi_i(2)); - r.x = vreinterpret_vd_vm(vxorm(vandm(m, vreinterpret_vm_vd(vcast_vd_d(-0.0))), vreinterpret_vm_vd(r.x))); - - m = vmaski_eq(vandi(vaddi(q, vcast_vi_i(1)), vcast_vi_i(2)), vcast_vi_i(2)); - r.y = vreinterpret_vd_vm(vxorm(vandm(m, vreinterpret_vm_vd(vcast_vd_d(-0.0))), vreinterpret_vm_vd(r.y))); - - m = vmask_isinf(d); - r.x = vsel(m, vcast_vd_d(rtengine::RT_NAN), r.x); - r.y = vsel(m, vcast_vd_d(rtengine::RT_NAN), r.y); - - return r; -} - -static INLINE vdouble xtan(vdouble d) { - vint q; - vdouble u, s, x; - vmask m; - - q = vrint_vi_vd(vmul(d, vcast_vd_d(rtengine::RT_2_PI))); - - u = vcast_vd_vi(q); - x = vadd(d, vmul(u, vcast_vd_d(-PI4_A*2))); - x = vadd(x, vmul(u, vcast_vd_d(-PI4_B*2))); - x = vadd(x, vmul(u, vcast_vd_d(-PI4_C*2))); - - s = vmul(x, x); - - m = vmaski_eq(vandi(q, vcast_vi_i(1)), vcast_vi_i(1)); - x = vsel(m, vneg(x), x); - - u = vcast_vd_d(1.01419718511083373224408e-05); - u = vmla(u, s, vcast_vd_d(-2.59519791585924697698614e-05)); - u = vmla(u, s, vcast_vd_d(5.23388081915899855325186e-05)); - u = vmla(u, s, vcast_vd_d(-3.05033014433946488225616e-05)); - u = vmla(u, s, vcast_vd_d(7.14707504084242744267497e-05)); - u = vmla(u, s, vcast_vd_d(8.09674518280159187045078e-05)); - u = vmla(u, s, vcast_vd_d(0.000244884931879331847054404)); - u = vmla(u, s, vcast_vd_d(0.000588505168743587154904506)); - u = vmla(u, s, vcast_vd_d(0.00145612788922812427978848)); - u = vmla(u, s, vcast_vd_d(0.00359208743836906619142924)); - u = vmla(u, s, vcast_vd_d(0.00886323944362401618113356)); - u = vmla(u, s, vcast_vd_d(0.0218694882853846389592078)); - u = vmla(u, s, vcast_vd_d(0.0539682539781298417636002)); - u = vmla(u, s, vcast_vd_d(0.133333333333125941821962)); - u = vmla(u, s, vcast_vd_d(0.333333333333334980164153)); - - u = vmla(s, vmul(u, x), x); - - u = vsel(m, vrec(u), u); - - u = vsel(vmask_isinf(d), vcast_vd_d(rtengine::RT_NAN), u); - - return u; -} - -static INLINE vdouble atan2k(vdouble y, vdouble x) { - vdouble s, t, u; - vint q; - vmask p; - - q = vseli_lt(x, vcast_vd_d(0), vcast_vi_i(-2), vcast_vi_i(0)); - x = vabs(x); - - q = vseli_lt(x, y, vaddi(q, vcast_vi_i(1)), q); - p = vmask_lt(x, y); - s = vsel (p, vneg(x), y); - t = vmax (x, y); - - s = vdiv(s, t); - t = vmul(s, s); - - u = vcast_vd_d(-1.88796008463073496563746e-05); - u = vmla(u, t, vcast_vd_d(0.000209850076645816976906797)); - u = vmla(u, t, vcast_vd_d(-0.00110611831486672482563471)); - u = vmla(u, t, vcast_vd_d(0.00370026744188713119232403)); - u = vmla(u, t, vcast_vd_d(-0.00889896195887655491740809)); - u = vmla(u, t, vcast_vd_d(0.016599329773529201970117)); - u = vmla(u, t, vcast_vd_d(-0.0254517624932312641616861)); - u = vmla(u, t, vcast_vd_d(0.0337852580001353069993897)); - u = vmla(u, t, vcast_vd_d(-0.0407629191276836500001934)); - u = vmla(u, t, vcast_vd_d(0.0466667150077840625632675)); - u = vmla(u, t, vcast_vd_d(-0.0523674852303482457616113)); - u = vmla(u, t, vcast_vd_d(0.0587666392926673580854313)); - u = vmla(u, t, vcast_vd_d(-0.0666573579361080525984562)); - u = vmla(u, t, vcast_vd_d(0.0769219538311769618355029)); - u = vmla(u, t, vcast_vd_d(-0.090908995008245008229153)); - u = vmla(u, t, vcast_vd_d(0.111111105648261418443745)); - u = vmla(u, t, vcast_vd_d(-0.14285714266771329383765)); - u = vmla(u, t, vcast_vd_d(0.199999999996591265594148)); - u = vmla(u, t, vcast_vd_d(-0.333333333333311110369124)); - - t = vadd(s, vmul(s, vmul(t, u))); - t = vadd(t, vmul(vcast_vd_vi(q), vcast_vd_d(rtengine::RT_PI/2))); - - return t; -} - -static INLINE vdouble xatan2(vdouble y, vdouble x) { - vdouble r = atan2k(vabs(y), x); - - r = vmulsign(r, x); - r = vsel(vorm(vmask_isinf(x), vmask_eq(x, vcast_vd_d(0))), vsub(vcast_vd_d(rtengine::RT_PI/2), visinf2(x, vmulsign(vcast_vd_d(rtengine::RT_PI/2), x))), r); - r = vsel(vmask_isinf(y), vsub(vcast_vd_d(rtengine::RT_PI/2), visinf2(x, vmulsign(vcast_vd_d(rtengine::RT_PI/4), x))), r); - r = vsel(vmask_eq(y, vcast_vd_d(0)), vsel(vmask_eq(vsign(x), vcast_vd_d(-1.0)), vcast_vd_d(rtengine::RT_PI), vcast_vd_d(0)), r); - - return vsel(vorm(vmask_isnan(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_NAN), vmulsign(r, y)); -} - -static INLINE vdouble xasin(vdouble d) { - vdouble x, y; - x = vadd(vcast_vd_d(1), d); - y = vsub(vcast_vd_d(1), d); - x = vmul(x, y); - x = vsqrt(x); - x = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), atan2k(vabs(d), x)); - return vmulsign(x, d); -} - -static INLINE vdouble xacos(vdouble d) { - vdouble x, y; - x = vadd(vcast_vd_d(1), d); - y = vsub(vcast_vd_d(1), d); - x = vmul(x, y); - x = vsqrt(x); - x = vmulsign(atan2k(x, vabs(d)), d); - y = (vdouble)vandm(vmask_lt(d, vcast_vd_d(0)), (vmask)vcast_vd_d(rtengine::RT_PI)); - x = vadd(x, y); - return x; -} - -static INLINE vdouble xatan(vdouble s) { - vdouble t, u; - vint q; - - q = vseli_lt(s, vcast_vd_d(0), vcast_vi_i(2), vcast_vi_i(0)); - s = vabs(s); - - q = vseli_lt(vcast_vd_d(1), s, vaddi(q, vcast_vi_i(1)), q); - s = vsel(vmask_lt(vcast_vd_d(1), s), vdiv(vcast_vd_d(1), s), s); - - t = vmul(s, s); - - u = vcast_vd_d(-1.88796008463073496563746e-05); - u = vmla(u, t, vcast_vd_d(0.000209850076645816976906797)); - u = vmla(u, t, vcast_vd_d(-0.00110611831486672482563471)); - u = vmla(u, t, vcast_vd_d(0.00370026744188713119232403)); - u = vmla(u, t, vcast_vd_d(-0.00889896195887655491740809)); - u = vmla(u, t, vcast_vd_d(0.016599329773529201970117)); - u = vmla(u, t, vcast_vd_d(-0.0254517624932312641616861)); - u = vmla(u, t, vcast_vd_d(0.0337852580001353069993897)); - u = vmla(u, t, vcast_vd_d(-0.0407629191276836500001934)); - u = vmla(u, t, vcast_vd_d(0.0466667150077840625632675)); - u = vmla(u, t, vcast_vd_d(-0.0523674852303482457616113)); - u = vmla(u, t, vcast_vd_d(0.0587666392926673580854313)); - u = vmla(u, t, vcast_vd_d(-0.0666573579361080525984562)); - u = vmla(u, t, vcast_vd_d(0.0769219538311769618355029)); - u = vmla(u, t, vcast_vd_d(-0.090908995008245008229153)); - u = vmla(u, t, vcast_vd_d(0.111111105648261418443745)); - u = vmla(u, t, vcast_vd_d(-0.14285714266771329383765)); - u = vmla(u, t, vcast_vd_d(0.199999999996591265594148)); - u = vmla(u, t, vcast_vd_d(-0.333333333333311110369124)); - - t = vadd(s, vmul(s, vmul(t, u))); - - t = vsel(vmaski_eq(vandi(q, vcast_vi_i(1)), vcast_vi_i(1)), vsub(vcast_vd_d(rtengine::RT_PI/2), t), t); - t = vsel(vmaski_eq(vandi(q, vcast_vi_i(2)), vcast_vi_i(2)), vneg(t), t); - - return t; -} - -static INLINE vdouble xlog(vdouble d) { - vdouble x, x2; - vdouble t, m; - vint e; - - e = vilogbp1(vmul(d, vcast_vd_d(0.7071))); - m = vldexp(d, vsubi(vcast_vi_i(0), e)); - - x = vdiv(vadd(vcast_vd_d(-1), m), vadd(vcast_vd_d(1), m)); - x2 = vmul(x, x); - - t = vcast_vd_d(0.148197055177935105296783); - t = vmla(t, x2, vcast_vd_d(0.153108178020442575739679)); - t = vmla(t, x2, vcast_vd_d(0.181837339521549679055568)); - t = vmla(t, x2, vcast_vd_d(0.22222194152736701733275)); - t = vmla(t, x2, vcast_vd_d(0.285714288030134544449368)); - t = vmla(t, x2, vcast_vd_d(0.399999999989941956712869)); - t = vmla(t, x2, vcast_vd_d(0.666666666666685503450651)); - t = vmla(t, x2, vcast_vd_d(2)); - - x = vadd(vmul(x, t), vmul(vcast_vd_d(0.693147180559945286226764), vcast_vd_vi(e))); - - x = vsel(vmask_ispinf(d), vcast_vd_d(rtengine::RT_INFINITY), x); - x = vsel(vmask_gt(vcast_vd_d(0), d), vcast_vd_d(rtengine::RT_NAN), x); - x = vsel(vmask_eq(d, vcast_vd_d(0)), vcast_vd_d(-rtengine::RT_INFINITY), x); - - return x; -} - -static INLINE vdouble xexp(vdouble d) { - vint q = vrint_vi_vd(vmul(d, vcast_vd_d(R_LN2))); - vdouble s, u; - - s = vadd(d, vmul(vcast_vd_vi(q), vcast_vd_d(-L2U))); - s = vadd(s, vmul(vcast_vd_vi(q), vcast_vd_d(-L2L))); - - u = vcast_vd_d(2.08860621107283687536341e-09); - u = vmla(u, s, vcast_vd_d(2.51112930892876518610661e-08)); - u = vmla(u, s, vcast_vd_d(2.75573911234900471893338e-07)); - u = vmla(u, s, vcast_vd_d(2.75572362911928827629423e-06)); - u = vmla(u, s, vcast_vd_d(2.4801587159235472998791e-05)); - u = vmla(u, s, vcast_vd_d(0.000198412698960509205564975)); - u = vmla(u, s, vcast_vd_d(0.00138888888889774492207962)); - u = vmla(u, s, vcast_vd_d(0.00833333333331652721664984)); - u = vmla(u, s, vcast_vd_d(0.0416666666666665047591422)); - u = vmla(u, s, vcast_vd_d(0.166666666666666851703837)); - u = vmla(u, s, vcast_vd_d(0.5)); - - u = vadd(vcast_vd_d(1), vadd(s, vmul(vmul(s, s), u))); - - u = vldexp(u, q); - - u = vsel(vmask_isminf(d), vcast_vd_d(0), u); - - return u; -} - -static INLINE vdouble2 logk(vdouble d) { - vdouble2 x, x2; - vdouble t, m; - vint e; - - e = vilogbp1(vmul(d, vcast_vd_d(0.7071))); - m = vldexp(d, vsubi(vcast_vi_i(0), e)); - - x = div_dd(add2_ss(vcast_vd_d(-1), m), add2_ss(vcast_vd_d(1), m)); - x2 = squ_d(x); - x2 = normalize_d(x2); - - t = vcast_vd_d(0.134601987501262130076155); - t = vmla(t, x2.x, vcast_vd_d(0.132248509032032670243288)); - t = vmla(t, x2.x, vcast_vd_d(0.153883458318096079652524)); - t = vmla(t, x2.x, vcast_vd_d(0.181817427573705403298686)); - t = vmla(t, x2.x, vcast_vd_d(0.222222231326187414840781)); - t = vmla(t, x2.x, vcast_vd_d(0.285714285651261412873718)); - t = vmla(t, x2.x, vcast_vd_d(0.400000000000222439910458)); - t = vmla(t, x2.x, vcast_vd_d(0.666666666666666371239645)); - - return add2_dd(mul_ds(dd(vcast_vd_d(0.693147180559945286226764), vcast_vd_d(2.319046813846299558417771e-17)), - vcast_vd_vi(e)), - add2_dd(scale_d(x, vcast_vd_d(2)), mul_ds(mul_dd(x2, x), t))); -} - -static INLINE vdouble expk(vdouble2 d) { - vdouble u = vmul(vadd(d.x, d.y), vcast_vd_d(R_LN2)); - vint q = vrint_vi_vd(u); - vdouble2 s, t; - - s = add2_ds(d, vmul(vcast_vd_vi(q), vcast_vd_d(-L2U))); - s = add2_ds(s, vmul(vcast_vd_vi(q), vcast_vd_d(-L2L))); - - q = vrint_vi_vd(vmin(vmax(vcast_vd_d(-2047.49), u), vcast_vd_d(2047.49))); - - s = normalize_d(s); - - u = vcast_vd_d(2.51069683420950419527139e-08); - u = vmla(u, s.x, vcast_vd_d(2.76286166770270649116855e-07)); - u = vmla(u, s.x, vcast_vd_d(2.75572496725023574143864e-06)); - u = vmla(u, s.x, vcast_vd_d(2.48014973989819794114153e-05)); - u = vmla(u, s.x, vcast_vd_d(0.000198412698809069797676111)); - u = vmla(u, s.x, vcast_vd_d(0.0013888888939977128960529)); - u = vmla(u, s.x, vcast_vd_d(0.00833333333332371417601081)); - u = vmla(u, s.x, vcast_vd_d(0.0416666666665409524128449)); - u = vmla(u, s.x, vcast_vd_d(0.166666666666666740681535)); - u = vmla(u, s.x, vcast_vd_d(0.500000000000000999200722)); - - t = add_dd(s, mul_ds(squ_d(s), u)); - - t = add_sd(vcast_vd_d(1), t); - u = vadd(t.x, t.y); - u = vldexp(u, q); - - return u; -} - -static INLINE vdouble xpow(vdouble x, vdouble y) { -#if 1 - vmask yisint = vmask_eq(vcast_vd_vi(vrint_vi_vd(y)), y); - vmask yisodd = vandm(vmaski_eq(vandi(vrint_vi_vd(y), vcast_vi_i(1)), vcast_vi_i(1)), yisint); - - vdouble result = expk(mul_ds(logk(vabs(x)), y)); - - //result = vsel(vmask_isnan(result), vcast_vd_d(rtengine::RT_INFINITY), result); - - result = vmul(result, - vsel(vmask_gt(x, vcast_vd_d(0)), - vcast_vd_d(1), - vsel(yisint, - vsel(yisodd, - vcast_vd_d(-1), - vcast_vd_d(1)), - vcast_vd_d(rtengine::RT_NAN)))); - - vdouble efx = vreinterpret_vd_vm(vxorm(vreinterpret_vm_vd(vsub(vabs(x), vcast_vd_d(1))), vsignbit(y))); - - result = vsel(vmask_isinf(y), - vsel(vmask_lt(efx, vcast_vd_d(0)), - vcast_vd_d(0), - vsel(vmask_eq(efx, vcast_vd_d(0)), - vcast_vd_d(1.0), - vcast_vd_d(rtengine::RT_INFINITY))), - result); - - result = vsel(vorm(vmask_isinf(x), vmask_eq(x, vcast_vd_d(0))), - vmul(vsel(yisodd, vsign(x), vcast_vd_d(1)), - vsel(vmask_lt(vsel(vmask_eq(x, vcast_vd_d(0)), vneg(y), y), vcast_vd_d(0)), - vcast_vd_d(0), - vcast_vd_d(rtengine::RT_INFINITY))), - result); - - result = vsel(vorm(vmask_isnan(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_NAN), result); - - result = vsel(vorm(vmask_eq(y, vcast_vd_d(0)), vmask_eq(x, vcast_vd_d(1))), vcast_vd_d(1), result); - - return result; -#else - return expk(mul_ds(logk(x), y)); -#endif -} - -static INLINE vdouble2 expk2(vdouble2 d) { - vdouble u = vmul(vadd(d.x, d.y), vcast_vd_d(R_LN2)); - vint q = vrint_vi_vd(u); - vdouble2 s, t; - - s = add2_ds(d, vmul(vcast_vd_vi(q), vcast_vd_d(-L2U))); - s = add2_ds(s, vmul(vcast_vd_vi(q), vcast_vd_d(-L2L))); - - q = vrint_vi_vd(vmin(vmax(vcast_vd_d(-2047.49), u), vcast_vd_d(2047.49))); - - s = normalize_d(s); - - u = vcast_vd_d(2.51069683420950419527139e-08); - u = vmla(u, s.x, vcast_vd_d(2.76286166770270649116855e-07)); - u = vmla(u, s.x, vcast_vd_d(2.75572496725023574143864e-06)); - u = vmla(u, s.x, vcast_vd_d(2.48014973989819794114153e-05)); - u = vmla(u, s.x, vcast_vd_d(0.000198412698809069797676111)); - u = vmla(u, s.x, vcast_vd_d(0.0013888888939977128960529)); - u = vmla(u, s.x, vcast_vd_d(0.00833333333332371417601081)); - u = vmla(u, s.x, vcast_vd_d(0.0416666666665409524128449)); - u = vmla(u, s.x, vcast_vd_d(0.166666666666666740681535)); - u = vmla(u, s.x, vcast_vd_d(0.500000000000000999200722)); - - t = add_dd(s, mul_ds(squ_d(s), u)); - - t = add_sd(vcast_vd_d(1), t); - - return dd(vldexp(t.x, q), vldexp(t.y, q)); -} - -static INLINE vdouble xsinh(vdouble x) { - vdouble y = vabs(x); - vdouble2 d = expk2(dd(y, vcast_vd_d(0))); - d = add2_dd(d, div_dd(dd(vcast_vd_d(-1), vcast_vd_d(0)), d)); - y = vmul(vadd(d.x, d.y), vcast_vd_d(0.5)); - - y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_INFINITY), y); - y = vmulsign(y, x); - y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); - - return y; -} - -static INLINE vdouble xcosh(vdouble x) { - vdouble2 d = expk2(dd(x, vcast_vd_d(0))); - d = add2_dd(d, div_dd(dd(vcast_vd_d(1), vcast_vd_d(0)), d)); - vdouble y = vmul(vadd(d.x, d.y), vcast_vd_d(0.5)); - - y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_INFINITY), y); - y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); - - return y; -} - -static INLINE vdouble xtanh(vdouble x) { - vdouble y = vabs(x); - vdouble2 d = expk2(dd(y, vcast_vd_d(0))); - vdouble2 e = div_dd(dd(vcast_vd_d(1), vcast_vd_d(0)), d); - d = div_dd(add2_dd(d, scale_d(e, vcast_vd_d(-1))), add2_dd(d, e)); - y = d.x + d.y; - - y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(1.0), y); - y = vmulsign(y, x); - y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); - - return y; -} - -static INLINE vdouble2 logk2(vdouble2 d) { - vdouble2 x, x2, m; - vdouble t; - vint e; - - d = normalize_d(d); - e = vilogbp1(vmul(d.x, vcast_vd_d(0.7071))); - m = scale_d(d, vldexp(vcast_vd_d(1), vsubi(vcast_vi_i(0), e))); - - x = div_dd(add2_ds(m, vcast_vd_d(-1)), add2_ds(m, vcast_vd_d(1))); - x2 = squ_d(x); - x2 = normalize_d(x2); - - t = vcast_vd_d(0.134601987501262130076155); - t = vmla(t, x2.x, vcast_vd_d(0.132248509032032670243288)); - t = vmla(t, x2.x, vcast_vd_d(0.153883458318096079652524)); - t = vmla(t, x2.x, vcast_vd_d(0.181817427573705403298686)); - t = vmla(t, x2.x, vcast_vd_d(0.222222231326187414840781)); - t = vmla(t, x2.x, vcast_vd_d(0.285714285651261412873718)); - t = vmla(t, x2.x, vcast_vd_d(0.400000000000222439910458)); - t = vmla(t, x2.x, vcast_vd_d(0.666666666666666371239645)); - - return add2_dd(mul_ds(dd(vcast_vd_d(0.693147180559945286226764), vcast_vd_d(2.319046813846299558417771e-17)), - vcast_vd_vi(e)), - add2_dd(scale_d(x, vcast_vd_d(2)), mul_ds(mul_dd(x2, x), t))); -} - -static INLINE vdouble xasinh(vdouble x) { - vdouble y = vabs(x); - vdouble2 d = logk2(add2_ds(sqrt_d(add2_ds(mul_ss(y, y), vcast_vd_d(1))), y)); - y = vadd(d.x, d.y); - - y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_INFINITY), y); - y = vmulsign(y, x); - y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); - - return y; -} - -static INLINE vdouble xacosh(vdouble x) { - vdouble2 d = logk2(add2_ds(sqrt_d(add2_ds(mul_ss(x, x), vcast_vd_d(-1))), x)); - vdouble y = vadd(d.x, d.y); - - y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_INFINITY), y); - y = vsel(vmask_eq(x, vcast_vd_d(1.0)), vcast_vd_d(0.0), y); - y = vsel(vmask_lt(x, vcast_vd_d(1.0)), vcast_vd_d(rtengine::RT_NAN), y); - y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); - - return y; -} - -static INLINE vdouble xatanh(vdouble x) { - vdouble y = vabs(x); - vdouble2 d = logk2(div_dd(add2_ss(vcast_vd_d(1), y), add2_ss(vcast_vd_d(1), -y))); - y = vsel(vmask_gt(y, vcast_vd_d(1.0)), vcast_vd_d(rtengine::RT_NAN), vsel(vmask_eq(y, vcast_vd_d(1.0)), vcast_vd_d(rtengine::RT_INFINITY), vmul(vadd(d.x, d.y), vcast_vd_d(0.5)))); - - y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_NAN), y); - y = vmulsign(y, x); - y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); - - return y; -} - -static INLINE vdouble xcbrt(vdouble d) { - vdouble x, y, q = vcast_vd_d(1.0); - vint e, qu, re; - vdouble t; - - e = vilogbp1(vabs(d)); - d = vldexp(d, vsubi(vcast_vi_i(0), e)); - - t = vadd(vcast_vd_vi(e), vcast_vd_d(6144)); - qu = vtruncate_vi_vd(vdiv(t, vcast_vd_d(3))); - re = vtruncate_vi_vd(vsub(t, vmul(vcast_vd_vi(qu), vcast_vd_d(3)))); - - q = vsel(vmaski_eq(re, vcast_vi_i(1)), vcast_vd_d(1.2599210498948731647672106), q); - q = vsel(vmaski_eq(re, vcast_vi_i(2)), vcast_vd_d(1.5874010519681994747517056), q); - q = vldexp(q, vsubi(qu, vcast_vi_i(2048))); - - q = vmulsign(q, d); - - d = vabs(d); - - x = vcast_vd_d(-0.640245898480692909870982); - x = vmla(x, d, vcast_vd_d(2.96155103020039511818595)); - x = vmla(x, d, vcast_vd_d(-5.73353060922947843636166)); - x = vmla(x, d, vcast_vd_d(6.03990368989458747961407)); - x = vmla(x, d, vcast_vd_d(-3.85841935510444988821632)); - x = vmla(x, d, vcast_vd_d(2.2307275302496609725722)); - - y = vmul(x, x); y = vmul(y, y); x = vsub(x, vmul(vmla(d, y, vneg(x)), vcast_vd_d(1.0 / 3.0))); - y = vmul(vmul(d, x), x); - y = vmul(vsub(y, vmul(vmul(vcast_vd_d(2.0 / 3.0), y), vmla(y, x, vcast_vd_d(-1.0)))), q); - - return y; -} - -static INLINE vdouble xexp2(vdouble a) { - vdouble u = expk(mul_ds(dd(vcast_vd_d(0.69314718055994528623), vcast_vd_d(2.3190468138462995584e-17)), a)); - u = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), u); - u = vsel(vmask_isminf(a), vcast_vd_d(0), u); - return u; -} - -static INLINE vdouble xexp10(vdouble a) { - vdouble u = expk(mul_ds(dd(vcast_vd_d(2.3025850929940459011), vcast_vd_d(-2.1707562233822493508e-16)), a)); - u = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), u); - u = vsel(vmask_isminf(a), vcast_vd_d(0), u); - return u; -} - -static INLINE vdouble xexpm1(vdouble a) { - vdouble2 d = add2_ds(expk2(dd(a, vcast_vd_d(0))), vcast_vd_d(-1.0)); - vdouble x = d.x + d.y; - x = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), x); - x = vsel(vmask_isminf(a), vcast_vd_d(-1), x); - return x; -} - -static INLINE vdouble xlog10(vdouble a) { - vdouble2 d = mul_dd(logk(a), dd(vcast_vd_d(0.43429448190325176116), vcast_vd_d(6.6494347733425473126e-17))); - vdouble x = d.x + d.y; - - x = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), x); - x = vsel(vmask_gt(vcast_vd_d(0), a), vcast_vd_d(rtengine::RT_NAN), x); - x = vsel(vmask_eq(a, vcast_vd_d(0)), vcast_vd_d(-rtengine::RT_INFINITY), x); - - return x; -} - -static INLINE vdouble xlog1p(vdouble a) { - vdouble2 d = logk2(add2_ss(a, vcast_vd_d(1))); - vdouble x = d.x + d.y; - - x = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), x); - x = vsel(vmask_gt(vcast_vd_d(-1), a), vcast_vd_d(rtengine::RT_NAN), x); - x = vsel(vmask_eq(a, vcast_vd_d(-1)), vcast_vd_d(-rtengine::RT_INFINITY), x); - - return x; -} - -// - -typedef struct { - vfloat x, y; -} vfloat2; - -static INLINE vfloat vabsf(vfloat f) { return (vfloat)vandnotm((vmask)vcast_vf_f(-0.0f), (vmask)f); } -static INLINE vfloat vnegf(vfloat f) { return (vfloat)vxorm((vmask)f, (vmask)vcast_vf_f(-0.0f)); } - -#ifdef __SSE4_1__ - // only one instruction when using SSE4.1 - static INLINE vfloat vself(vmask mask, vfloat x, vfloat y) { - return _mm_blendv_ps(y,x,(vfloat)mask); - } - - static INLINE vint vselc(vmask mask, vint x, vint y) { - return _mm_blendv_epi8(y,x,mask); - } - -#else - // three instructions when using SSE2 - static INLINE vfloat vself(vmask mask, vfloat x, vfloat y) { - return (vfloat)vorm(vandm(mask, (vmask)x), vandnotm(mask, (vmask)y)); - } - - static INLINE vint vselc(vmask mask, vint x, vint y) { - return vorm(vandm(mask, (vmask)x), vandnotm(mask, (vmask)y)); - } -#endif - -static INLINE vfloat vselfzero(vmask mask, vfloat x) { - // returns value of x if corresponding mask bits are 1, else returns 0 - // faster than vself(mask, x, ZEROV) - return _mm_and_ps((vfloat)mask, x); -} -static INLINE vfloat vselfnotzero(vmask mask, vfloat x) { - // returns value of x if corresponding mask bits are 0, else returns 0 - // faster than vself(mask, ZEROV, x) - return _mm_andnot_ps((vfloat)mask, x); -} - -static INLINE vint vselizero(vmask mask, vint x) { - // returns value of x if corresponding mask bits are 1, else returns 0 - // faster than vselc(mask, x, ZEROV) - return _mm_and_si128(mask, x); -} -static INLINE vint vselinotzero(vmask mask, vint x) { - // returns value of x if corresponding mask bits are 0, else returns 0 - // faster than vselc(mask, ZEROV, x) - return _mm_andnot_si128(mask, x); -} - -static INLINE vint2 vseli2_lt(vfloat f0, vfloat f1, vint2 x, vint2 y) { - vint2 m2 = vcast_vi2_vm(vmaskf_lt(f0, f1)); - return vori2(vandi2(m2, x), vandnoti2(m2, y)); -} - -static INLINE vmask vsignbitf(vfloat f) { - return vandm((vmask)f, (vmask)vcast_vf_f(-0.0f)); -} - -static INLINE vfloat vmulsignf(vfloat x, vfloat y) { - return (vfloat)vxorm((vmask)x, vsignbitf(y)); -} - -static INLINE vfloat vsignf(vfloat f) { - return (vfloat)vorm((vmask)vcast_vf_f(1.0f), vandm((vmask)vcast_vf_f(-0.0f), (vmask)f)); -} - -static INLINE vmask vmaskf_isinf(vfloat d) { return vmaskf_eq(vabsf(d), vcast_vf_f(INFINITYf)); } -static INLINE vmask vmaskf_ispinf(vfloat d) { return vmaskf_eq(d, vcast_vf_f(INFINITYf)); } -static INLINE vmask vmaskf_isminf(vfloat d) { return vmaskf_eq(d, vcast_vf_f(-INFINITYf)); } -static INLINE vmask vmaskf_isnan(vfloat d) { return vmaskf_neq(d, d); } -// the following is equivalent to vorm(vmaskf_isnan(a), vmaskf_isnan(b)), but faster -static INLINE vmask vmaskf_isnan(vfloat a, vfloat b) { return (vmask)_mm_cmpunord_ps(a, b); } -static INLINE vfloat visinf2f(vfloat d, vfloat m) { return (vfloat)vandm(vmaskf_isinf(d), vorm(vsignbitf(d), (vmask)m)); } -static INLINE vfloat visinff(vfloat d) { return visinf2f(d, vcast_vf_f(1.0f)); } - -static INLINE vint2 vilogbp1f(vfloat d) { - vmask m = vmaskf_lt(d, vcast_vf_f(5.421010862427522E-20f)); - d = vself(m, vmulf(vcast_vf_f(1.8446744073709552E19f), d), d); - vint2 q = vandi2(vsrli2(vcast_vi2_vm(vreinterpret_vm_vf(d)), 23), vcast_vi2_i(0xff)); - q = vsubi2(q, vseli2(m, vcast_vi2_i(64 + 0x7e), vcast_vi2_i(0x7e))); - return q; -} - -static INLINE vfloat vldexpf(vfloat x, vint2 q) { - vfloat u; - vint2 m = vsrai2(q, 31); - m = vslli2(vsubi2(vsrai2(vaddi2(m, q), 6), m), 4); - q = vsubi2(q, vslli2(m, 2)); - u = vreinterpret_vf_vm(vcast_vm_vi2(vslli2(vaddi2(m, vcast_vi2_i(0x7f)), 23))); - x = vmulf(vmulf(vmulf(vmulf(x, u), u), u), u); - u = vreinterpret_vf_vm(vcast_vm_vi2(vslli2(vaddi2(q, vcast_vi2_i(0x7f)), 23))); - return vmulf(x, u); -} - -static INLINE vfloat xsinf(vfloat d) { - vint2 q; - vfloat u, s; - - q = vrint_vi2_vf(vmulf(d, vcast_vf_f((float)rtengine::RT_1_PI))); - - u = vcast_vf_vi2(q); - d = vmlaf(u, vcast_vf_f(-PI4_Af*4), d); - d = vmlaf(u, vcast_vf_f(-PI4_Bf*4), d); - d = vmlaf(u, vcast_vf_f(-PI4_Cf*4), d); - d = vmlaf(u, vcast_vf_f(-PI4_Df*4), d); - - s = vmulf(d, d); - - d = vself(vmaski2_eq(vandi2(q, vcast_vi2_i(1)), vcast_vi2_i(1)), vnegf(d), d); - - u = vcast_vf_f(2.6083159809786593541503e-06f); - u = vmlaf(u, s, vcast_vf_f(-0.0001981069071916863322258f)); - u = vmlaf(u, s, vcast_vf_f(0.00833307858556509017944336f)); - u = vmlaf(u, s, vcast_vf_f(-0.166666597127914428710938f)); - - u = vmlaf(s, vmulf(u, d), d); - - return u; -} - -static INLINE vfloat xcosf(vfloat d) { - vint2 q; - vfloat u, s; - - q = vrint_vi2_vf(vsubf(vmulf(d, vcast_vf_f((float)rtengine::RT_1_PI)), vcast_vf_f(0.5f))); - q = vaddi2(vaddi2(q, q), vcast_vi2_i(1)); - - u = vcast_vf_vi2(q); - d = vmlaf(u, vcast_vf_f(-PI4_Af*2), d); - d = vmlaf(u, vcast_vf_f(-PI4_Bf*2), d); - d = vmlaf(u, vcast_vf_f(-PI4_Cf*2), d); - d = vmlaf(u, vcast_vf_f(-PI4_Df*2), d); - - s = vmulf(d, d); - - d = vself(vmaski2_eq(vandi2(q, vcast_vi2_i(2)), vcast_vi2_i(2)), d, vnegf(d)); - - u = vcast_vf_f(2.6083159809786593541503e-06f); - u = vmlaf(u, s, vcast_vf_f(-0.0001981069071916863322258f)); - u = vmlaf(u, s, vcast_vf_f(0.00833307858556509017944336f)); - u = vmlaf(u, s, vcast_vf_f(-0.166666597127914428710938f)); - - u = vmlaf(s, vmulf(u, d), d); - - return u; -} - -static INLINE vfloat2 xsincosf(vfloat d) { - vint2 q; - vmask m; - vfloat u, s, t, rx, ry; - vfloat2 r; - - q = vrint_vi2_vf(vmulf(d, vcast_vf_f((float)rtengine::RT_2_PI))); - - s = d; - - u = vcast_vf_vi2(q); - s = vmlaf(u, vcast_vf_f(-PI4_Af*2), s); - s = vmlaf(u, vcast_vf_f(-PI4_Bf*2), s); - s = vmlaf(u, vcast_vf_f(-PI4_Cf*2), s); - s = vmlaf(u, vcast_vf_f(-PI4_Df*2), s); - - t = s; - - s = vmulf(s, s); - - u = vcast_vf_f(-0.000195169282960705459117889f); - u = vmlaf(u, s, vcast_vf_f(0.00833215750753879547119141f)); - u = vmlaf(u, s, vcast_vf_f(-0.166666537523269653320312f)); - u = vmulf(vmulf(u, s), t); - - rx = vaddf(t, u); - - u = vcast_vf_f(-2.71811842367242206819355e-07f); - u = vmlaf(u, s, vcast_vf_f(2.47990446951007470488548e-05f)); - u = vmlaf(u, s, vcast_vf_f(-0.00138888787478208541870117f)); - u = vmlaf(u, s, vcast_vf_f(0.0416666641831398010253906f)); - u = vmlaf(u, s, vcast_vf_f(-0.5)); - - ry = vaddf(vcast_vf_f(1), vmulf(s, u)); - - m = vmaski2_eq(vandi2(q, vcast_vi2_i(1)), vcast_vi2_i(0)); - r.x = vself(m, rx, ry); - r.y = vself(m, ry, rx); - - m = vmaski2_eq(vandi2(q, vcast_vi2_i(2)), vcast_vi2_i(2)); - r.x = vreinterpret_vf_vm(vxorm(vandm(m, vreinterpret_vm_vf(vcast_vf_f(-0.0))), vreinterpret_vm_vf(r.x))); - - m = vmaski2_eq(vandi2(vaddi2(q, vcast_vi2_i(1)), vcast_vi2_i(2)), vcast_vi2_i(2)); - r.y = vreinterpret_vf_vm(vxorm(vandm(m, vreinterpret_vm_vf(vcast_vf_f(-0.0))), vreinterpret_vm_vf(r.y))); - - m = vmaskf_isinf(d); - r.x = vself(m, vcast_vf_f(rtengine::RT_NAN), r.x); - r.y = vself(m, vcast_vf_f(rtengine::RT_NAN), r.y); - - return r; -} - -static INLINE vfloat xtanf(vfloat d) { - vint2 q; - vmask m; - vfloat u, s, x; - - q = vrint_vi2_vf(vmulf(d, vcast_vf_f((float)(2 * rtengine::RT_1_PI)))); - - x = d; - - u = vcast_vf_vi2(q); - x = vmlaf(u, vcast_vf_f(-PI4_Af*2), x); - x = vmlaf(u, vcast_vf_f(-PI4_Bf*2), x); - x = vmlaf(u, vcast_vf_f(-PI4_Cf*2), x); - x = vmlaf(u, vcast_vf_f(-PI4_Df*2), x); - - s = vmulf(x, x); - - m = vmaski2_eq(vandi2(q, vcast_vi2_i(1)), vcast_vi2_i(1)); - x = vself(m, vnegf(x), x); - - u = vcast_vf_f(0.00927245803177356719970703f); - u = vmlaf(u, s, vcast_vf_f(0.00331984995864331722259521f)); - u = vmlaf(u, s, vcast_vf_f(0.0242998078465461730957031f)); - u = vmlaf(u, s, vcast_vf_f(0.0534495301544666290283203f)); - u = vmlaf(u, s, vcast_vf_f(0.133383005857467651367188f)); - u = vmlaf(u, s, vcast_vf_f(0.333331853151321411132812f)); - - u = vmlaf(s, vmulf(u, x), x); - - u = vself(m, vrecf(u), u); - - u = vself(vmaskf_isinf(d), vcast_vf_f(NANf), u); - - return u; -} - -static INLINE vfloat xatanf(vfloat s) { - vfloat t, u; - vint2 q; - - q = vseli2_lt(s, vcast_vf_f(0.0f), vcast_vi2_i(2), vcast_vi2_i(0)); - s = vabsf(s); - - q = vseli2_lt(vcast_vf_f(1.0f), s, vaddi2(q, vcast_vi2_i(1)), q); - s = vself(vmaskf_lt(vcast_vf_f(1.0f), s), vdivf(vcast_vf_f(1.0f), s), s); - - t = vmulf(s, s); - - u = vcast_vf_f(0.00282363896258175373077393f); - u = vmlaf(u, t, vcast_vf_f(-0.0159569028764963150024414f)); - u = vmlaf(u, t, vcast_vf_f(0.0425049886107444763183594f)); - u = vmlaf(u, t, vcast_vf_f(-0.0748900920152664184570312f)); - u = vmlaf(u, t, vcast_vf_f(0.106347933411598205566406f)); - u = vmlaf(u, t, vcast_vf_f(-0.142027363181114196777344f)); - u = vmlaf(u, t, vcast_vf_f(0.199926957488059997558594f)); - u = vmlaf(u, t, vcast_vf_f(-0.333331018686294555664062f)); - - t = vaddf(s, vmulf(s, vmulf(t, u))); - - t = vself(vmaski2_eq(vandi2(q, vcast_vi2_i(1)), vcast_vi2_i(1)), vsubf(vcast_vf_f((float)(rtengine::RT_PI/2)), t), t); - t = vself(vmaski2_eq(vandi2(q, vcast_vi2_i(2)), vcast_vi2_i(2)), vnegf(t), t); - - return t; -} - -static INLINE vfloat atan2kf(vfloat y, vfloat x) { - vfloat s, t, u; - vint2 q; - vmask p; - - q = vseli2_lt(x, vcast_vf_f(0.0f), vcast_vi2_i(-2), vcast_vi2_i(0)); - x = vabsf(x); - - q = vseli2_lt(x, y, vaddi2(q, vcast_vi2_i(1)), q); - p = vmaskf_lt(x, y); - s = vself(p, vnegf(x), y); - t = vmaxf(x, y); - - s = vdivf(s, t); - t = vmulf(s, s); - - u = vcast_vf_f(0.00282363896258175373077393f); - u = vmlaf(u, t, vcast_vf_f(-0.0159569028764963150024414f)); - u = vmlaf(u, t, vcast_vf_f(0.0425049886107444763183594f)); - u = vmlaf(u, t, vcast_vf_f(-0.0748900920152664184570312f)); - u = vmlaf(u, t, vcast_vf_f(0.106347933411598205566406f)); - u = vmlaf(u, t, vcast_vf_f(-0.142027363181114196777344f)); - u = vmlaf(u, t, vcast_vf_f(0.199926957488059997558594f)); - u = vmlaf(u, t, vcast_vf_f(-0.333331018686294555664062f)); - - t = vaddf(s, vmulf(s, vmulf(t, u))); - t = vaddf(t, vmulf(vcast_vf_vi2(q), vcast_vf_f((float)(rtengine::RT_PI/2)))); - - return t; -} - -static INLINE vfloat xatan2f(vfloat y, vfloat x) { - vfloat r = atan2kf(vabsf(y), x); - - r = vmulsignf(r, x); - r = vself(vorm(vmaskf_isinf(x), vmaskf_eq(x, vcast_vf_f(0.0f))), vsubf(vcast_vf_f((float)(rtengine::RT_PI/2)), visinf2f(x, vmulsignf(vcast_vf_f((float)(rtengine::RT_PI/2)), x))), r); - r = vself(vmaskf_isinf(y), vsubf(vcast_vf_f((float)(rtengine::RT_PI/2)), visinf2f(x, vmulsignf(vcast_vf_f((float)(rtengine::RT_PI/4)), x))), r); - r = vself(vmaskf_eq(y, vcast_vf_f(0.0f)), vselfzero(vmaskf_eq(vsignf(x), vcast_vf_f(-1.0f)), vcast_vf_f((float)rtengine::RT_PI)), r); - - return vself(vmaskf_isnan(x, y), vcast_vf_f(NANf), vmulsignf(r, y)); -} - -static INLINE vfloat xasinf(vfloat d) { - vfloat x, y; - x = vaddf(vcast_vf_f(1.0f), d); - y = vsubf(vcast_vf_f(1.0f), d); - x = vmulf(x, y); - x = vsqrtf(x); - x = vself(vmaskf_isnan(x), vcast_vf_f(NANf), atan2kf(vabsf(d), x)); - return vmulsignf(x, d); -} - -static INLINE vfloat xacosf(vfloat d) { - vfloat x, y; - x = vaddf(vcast_vf_f(1.0f), d); - y = vsubf(vcast_vf_f(1.0f), d); - x = vmulf(x, y); - x = vsqrtf(x); - x = vmulsignf(atan2kf(x, vabsf(d)), d); - y = (vfloat)vandm(vmaskf_lt(d, vcast_vf_f(0.0f)), (vmask)vcast_vf_f((float)rtengine::RT_PI)); - x = vaddf(x, y); - return x; -} - -static INLINE vfloat xlogf(vfloat d) { - vfloat x, x2, t, m; - vint2 e; - - e = vilogbp1f(vmulf(d, vcast_vf_f(0.7071f))); - m = vldexpf(d, vsubi2(vcast_vi2_i(0), e)); - - x = vdivf(vaddf(vcast_vf_f(-1.0f), m), vaddf(vcast_vf_f(1.0f), m)); - x2 = vmulf(x, x); - - t = vcast_vf_f(0.2371599674224853515625f); - t = vmlaf(t, x2, vcast_vf_f(0.285279005765914916992188f)); - t = vmlaf(t, x2, vcast_vf_f(0.400005519390106201171875f)); - t = vmlaf(t, x2, vcast_vf_f(0.666666567325592041015625f)); - t = vmlaf(t, x2, vcast_vf_f(2.0f)); - - x = vaddf(vmulf(x, t), vmulf(vcast_vf_f(0.693147180559945286226764f), vcast_vf_vi2(e))); - - x = vself(vmaskf_ispinf(d), vcast_vf_f(INFINITYf), x); - x = vself(vmaskf_gt(vcast_vf_f(0), d), vcast_vf_f(NANf), x); - x = vself(vmaskf_eq(d, vcast_vf_f(0)), vcast_vf_f(-INFINITYf), x); - - return x; -} - -static INLINE vfloat xlogf0(vfloat d) { - vfloat x, x2, t, m; - vint2 e; - - e = vilogbp1f(vmulf(d, vcast_vf_f(0.7071f))); - m = vldexpf(d, vsubi2(vcast_vi2_i(0), e)); - - x = vdivf(vaddf(vcast_vf_f(-1.0f), m), vaddf(vcast_vf_f(1.0f), m)); - x2 = vmulf(x, x); - - t = vcast_vf_f(0.2371599674224853515625f); - t = vmlaf(t, x2, vcast_vf_f(0.285279005765914916992188f)); - t = vmlaf(t, x2, vcast_vf_f(0.400005519390106201171875f)); - t = vmlaf(t, x2, vcast_vf_f(0.666666567325592041015625f)); - t = vmlaf(t, x2, vcast_vf_f(2.0f)); - - x = vaddf(vmulf(x, t), vmulf(vcast_vf_f(0.693147180559945286226764f), vcast_vf_vi2(e))); - - x = vself(vmaskf_ispinf(d), vcast_vf_f(0), x); - x = vself(vmaskf_gt(vcast_vf_f(0), d), vcast_vf_f(0), x); - x = vself(vmaskf_eq(d, vcast_vf_f(0)), vcast_vf_f(0), x); - - return x; -} - -static INLINE vfloat xlogfNoCheck(vfloat d) { // this version does not check input values. Use it only when you know the input values are > 0 e.g. when filling a lookup table - vfloat x, x2, t, m; - vint2 e; - - e = vilogbp1f(vmulf(d, vcast_vf_f(0.7071f))); - m = vldexpf(d, vsubi2(vcast_vi2_i(0), e)); - - x = vdivf(vaddf(vcast_vf_f(-1.0f), m), vaddf(vcast_vf_f(1.0f), m)); - x2 = vmulf(x, x); - - t = vcast_vf_f(0.2371599674224853515625f); - t = vmlaf(t, x2, vcast_vf_f(0.285279005765914916992188f)); - t = vmlaf(t, x2, vcast_vf_f(0.400005519390106201171875f)); - t = vmlaf(t, x2, vcast_vf_f(0.666666567325592041015625f)); - t = vmlaf(t, x2, vcast_vf_f(2.0f)); - - return vaddf(vmulf(x, t), vmulf(vcast_vf_f(0.693147180559945286226764f), vcast_vf_vi2(e))); - -} - -static INLINE vfloat xexpf(vfloat d) { - vint2 q = vrint_vi2_vf(vmulf(d, vcast_vf_f(R_LN2f))); - vfloat s, u; - - s = vmlaf(vcast_vf_vi2(q), vcast_vf_f(-L2Uf),d); - s = vmlaf(vcast_vf_vi2(q), vcast_vf_f(-L2Lf),s); - - u = vcast_vf_f(0.00136324646882712841033936f); - u = vmlaf(u, s, vcast_vf_f(0.00836596917361021041870117f)); - u = vmlaf(u, s, vcast_vf_f(0.0416710823774337768554688f)); - u = vmlaf(u, s, vcast_vf_f(0.166665524244308471679688f)); - u = vmlaf(u, s, vcast_vf_f(0.499999850988388061523438f)); - - u = vaddf(vcast_vf_f(1.0f), vmlaf(vmulf(s, s), u, s)); - - u = vldexpf(u, q); - - // -104.0 - return vselfnotzero(vmaskf_gt(vcast_vf_f(-104.f), d), u); -} - -static INLINE vfloat xexpfNoCheck(vfloat d) { // this version does not check input values. Use it only when you know the input values are > -104.f e.g. when filling a lookup table - vint2 q = vrint_vi2_vf(vmulf(d, vcast_vf_f(R_LN2f))); - vfloat s, u; - - s = vmlaf(vcast_vf_vi2(q), vcast_vf_f(-L2Uf),d); - s = vmlaf(vcast_vf_vi2(q), vcast_vf_f(-L2Lf),s); - - u = vcast_vf_f(0.00136324646882712841033936f); - u = vmlaf(u, s, vcast_vf_f(0.00836596917361021041870117f)); - u = vmlaf(u, s, vcast_vf_f(0.0416710823774337768554688f)); - u = vmlaf(u, s, vcast_vf_f(0.166665524244308471679688f)); - u = vmlaf(u, s, vcast_vf_f(0.499999850988388061523438f)); - - u = vaddf(vcast_vf_f(1.0f), vmlaf(vmulf(s, s), u, s)); - - return vldexpf(u, q); -} - -static INLINE vfloat xcbrtf(vfloat d) { - vfloat x, y, q = vcast_vf_f(1.0), t; - vint2 e, qu, re; - - e = vilogbp1f(vabsf(d)); - d = vldexpf(d, vsubi2(vcast_vi2_i(0), e)); - - t = vaddf(vcast_vf_vi2(e), vcast_vf_f(6144)); - qu = vtruncate_vi2_vf(vdivf(t, vcast_vf_f(3))); - re = vtruncate_vi2_vf(vsubf(t, vmulf(vcast_vf_vi2(qu), vcast_vf_f(3)))); - - q = vself(vmaski2_eq(re, vcast_vi2_i(1)), vcast_vf_f(1.2599210498948731647672106f), q); - q = vself(vmaski2_eq(re, vcast_vi2_i(2)), vcast_vf_f(1.5874010519681994747517056f), q); - q = vldexpf(q, vsubi2(qu, vcast_vi2_i(2048))); - - q = vmulsignf(q, d); - d = vabsf(d); - - x = vcast_vf_f(-0.601564466953277587890625f); - x = vmlaf(x, d, vcast_vf_f(2.8208892345428466796875f)); - x = vmlaf(x, d, vcast_vf_f(-5.532182216644287109375f)); - x = vmlaf(x, d, vcast_vf_f(5.898262500762939453125f)); - x = vmlaf(x, d, vcast_vf_f(-3.8095417022705078125f)); - x = vmlaf(x, d, vcast_vf_f(2.2241256237030029296875f)); - - y = vmulf(vmulf(d, x), x); - y = vmulf(vsubf(y, vmulf(vmulf(vcast_vf_f(2.0f / 3.0f), y), vmlaf(y, x, vcast_vf_f(-1.0f)))), q); - - return y; -} - -static INLINE vfloat vclampf(vfloat value, vfloat low, vfloat high) { - // clamps value in [low;high], returns low if value is NaN - return vmaxf(vminf(high, value), low); -} - -static INLINE vfloat SQRV(vfloat a){ - return a * a; -} - -static inline void vswap( vmask condition, vfloat &a, vfloat &b) { - // conditional swap the elements of two vfloats - vfloat temp = vself(condition, a, b); // the values which fit to condition - a = vself(condition, b, a); // the values which fit to inverted condition - b = temp; -} - -static inline float vhadd( vfloat a ) { - // returns a[0] + a[1] + a[2] + a[3] - a += _mm_movehl_ps(a, a); - return _mm_cvtss_f32(_mm_add_ss(a, _mm_shuffle_ps(a, a, 1))); -} - -static INLINE vfloat vmul2f(vfloat a){ - // fastest way to multiply by 2 - return a + a; -} - -static INLINE vfloat vintpf(vfloat a, vfloat b, vfloat c) { - // calculate a * b + (1 - a) * c (interpolate two values) - // following is valid: - // vintpf(a, b+x, c+x) = vintpf(a, b, c) + x - // vintpf(a, b*x, c*x) = vintpf(a, b, c) * x - return a * (b-c) + c; -} - -static INLINE vfloat vdup(vfloat a){ - // returns { a[0],a[0],a[1],a[1] } - return _mm_unpacklo_ps( a, a ); -} - -static INLINE vfloat vaddc2vfu(float &a) -{ - // loads a[0]..a[7] and returns { a[0]+a[1], a[2]+a[3], a[4]+a[5], a[6]+a[7] } - vfloat a1 = _mm_loadu_ps( &a ); - vfloat a2 = _mm_loadu_ps( (&a) + 4 ); - return _mm_shuffle_ps(a1,a2,_MM_SHUFFLE( 2,0,2,0 )) + _mm_shuffle_ps(a1,a2,_MM_SHUFFLE( 3,1,3,1 )); -} - -static INLINE vfloat vadivapb (vfloat a, vfloat b) { - return a / (a+b); -} - -static INLINE void vconvertrgbrgbrgbrgb2rrrrggggbbbb (const float * src, vfloat &rv, vfloat &gv, vfloat &bv) { // cool function name, isn't it ? :P - // converts a sequence of 4 float RGB triplets to 3 red, green and blue quadruples - rv = _mm_setr_ps(src[0],src[3],src[6],src[9]); - gv = _mm_setr_ps(src[1],src[4],src[7],src[10]); - bv = _mm_setr_ps(src[2],src[5],src[8],src[11]); -} - -#if defined( __SSE4_1__ ) && defined( __x86_64__ ) -static INLINE vfloat vceilf(vfloat x) { - return _mm_round_ps(x, _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC); -} - -#else - -static INLINE vfloat vceilf(vfloat x) { - __m128i zerov = _mm_setzero_si128(); - zerov = _mm_cmpeq_epi32(zerov, zerov); - const vfloat onev = (vfloat)_mm_slli_epi32(_mm_srli_epi32(zerov, 25), 23); //create vector 1.0f - const vfloat xi = _mm_cvtepi32_ps(_mm_cvttps_epi32(x)); - return xi + _mm_and_ps(_mm_cmplt_ps(xi, x), onev); -} -#endif - -#endif // __SSE2__ -#endif // SLEEFSSEAVX diff --git a/rtengine/sleefsseavx.h b/rtengine/sleefsseavx.h index 8fe20c54b..c10f4a0c2 100644 --- a/rtengine/sleefsseavx.h +++ b/rtengine/sleefsseavx.h @@ -1,124 +1,897 @@ -#include -#include +//////////////////////////////////////////////////////////////// +// +// this code was taken from http://shibatch.sourceforge.net/ +// Many thanks to the author of original version: Naoki Shibata +// +// This version contains modifications made by Ingo Weyrich +// +//////////////////////////////////////////////////////////////// +#pragma once +#include "rt_math.h" #ifdef __SSE2__ -#define VECTLENDP 2 -#define VECTLENSP 4 - -typedef __m128d vdouble; -typedef __m128i vint; - -typedef __m128 vfloat; -typedef __m128i vint2; -typedef __m128i vmask; - -static vdouble vloadu(double *p) -{ - return _mm_loadu_pd(p); -} -static void vstoreu(double *p, vdouble v) -{ - _mm_storeu_pd(p, v); -} - -static vfloat vloaduf(float *p) -{ - return _mm_loadu_ps(p); -} -static void vstoreuf(float *p, vfloat v) -{ - _mm_storeu_ps(p, v); -} - -static vint2 vloadui2(int32_t *p) -{ - return (vint2)_mm_loadu_si128((__m128i *)p); -} -static void vstoreui2(int32_t *p, vint2 v) -{ - _mm_storeu_si128((__m128i *)p, (__m128i)v); -} -#endif +#include "helpersse2.h" #ifdef ENABLE_AVX -#define VECTLENDP 4 -#define VECTLENSP 8 +#include "helperavx.h" +#endif -typedef __m256d vdouble; -typedef __m128i vint; +#ifdef __GNUC__ +#define INLINE __inline +#else +#define INLINE inline +#endif +#define PI4_A .7853981554508209228515625 +#define PI4_B .794662735614792836713604629039764404296875e-8 +#define PI4_C .306161699786838294306516483068750264552437361480769e-16 +#define M_4_PI 1.273239544735162542821171882678754627704620361328125 -typedef __m256 vfloat; -typedef struct { - vint x, y; -} vint2; +#define L2U .69314718055966295651160180568695068359375 +#define L2L .28235290563031577122588448175013436025525412068e-12 +#define R_LN2 1.442695040888963407359924681001892137426645954152985934135449406931 -static vdouble vloadu(double *p) -{ - return _mm256_loadu_pd(p); -} -static void vstoreu(double *p, vdouble v) -{ - return _mm256_storeu_pd(p, v); +#define PI4_Af 0.78515625f +#define PI4_Bf 0.00024127960205078125f +#define PI4_Cf 6.3329935073852539062e-07f +#define PI4_Df 4.9604681473525147339e-10f + +#define L2Uf 0.693145751953125f +#define L2Lf 1.428606765330187045e-06f +#define R_LN2f 1.442695040888963407359924681001892137426645954152985934135449406931f + +#define INFINITYf ((float)rtengine::RT_INFINITY) +#define NANf ((float)rtengine::RT_NAN) + +static INLINE vdouble vadd3(vdouble v0, vdouble v1, vdouble v2) { + return vadd(vadd(v0, v1), v2); } -static vfloat vloaduf(float *p) -{ - return _mm256_loadu_ps(p); -} -static void vstoreuf(float *p, vfloat v) -{ - return _mm256_storeu_ps(p, v); +static INLINE vdouble vadd4(vdouble v0, vdouble v1, vdouble v2, vdouble v3) { + return vadd3(vadd(v0, v1), v2, v3); } -static vint2 vloadui2(int32_t *p) -{ - vint2 r; - r.x = _mm_loadu_si128((__m128i *) p ); - r.y = _mm_loadu_si128((__m128i *)(p + 4)); +static INLINE vdouble vadd5(vdouble v0, vdouble v1, vdouble v2, vdouble v3, vdouble v4) { + return vadd4(vadd(v0, v1), v2, v3, v4); +} + +static INLINE vdouble vadd6(vdouble v0, vdouble v1, vdouble v2, vdouble v3, vdouble v4, vdouble v5) { + return vadd5(vadd(v0, v1), v2, v3, v4, v5); +} + +static INLINE vdouble vadd7(vdouble v0, vdouble v1, vdouble v2, vdouble v3, vdouble v4, vdouble v5, vdouble v6) { + return vadd6(vadd(v0, v1), v2, v3, v4, v5, v6); +} + +static INLINE vdouble vsub3(vdouble v0, vdouble v1, vdouble v2) { + return vsub(vsub(v0, v1), v2); +} + +static INLINE vdouble vsub4(vdouble v0, vdouble v1, vdouble v2, vdouble v3) { + return vsub3(vsub(v0, v1), v2, v3); +} + +static INLINE vdouble vsub5(vdouble v0, vdouble v1, vdouble v2, vdouble v3, vdouble v4) { + return vsub4(vsub(v0, v1), v2, v3, v4); +} + +// + +static INLINE vdouble2 normalize_d(vdouble2 t) { + vdouble2 s; + + s.x = vadd(t.x, t.y); + s.y = vadd(vsub(t.x, s.x), t.y); + + return s; +} + +static INLINE vdouble2 scale_d(vdouble2 d, vdouble s) { + vdouble2 r = {vmul(d.x, s), vmul(d.y, s)}; return r; } -static void vstoreui2(int32_t *p, vint2 v) -{ - _mm_storeu_si128((__m128i *) p , v.x); - _mm_storeu_si128((__m128i *)(p + 4), v.y); +static INLINE vdouble2 add_ss(vdouble x, vdouble y) { + vdouble2 r; + + r.x = vadd(x, y); + r.y = vadd(vsub(x, r.x), y); + + return r; } -#endif -typedef struct { +static INLINE vdouble2 add2_ss(vdouble x, vdouble y) { + vdouble2 r; + + r.x = vadd(x, y); + vdouble v = vsub(r.x, x); + r.y = vadd(vsub(x, vsub(r.x, v)), vsub(y, v)); + + return r; +} + +static INLINE vdouble2 add_ds(vdouble2 x, vdouble y) { + vdouble2 r; + + r.x = vadd(x.x, y); + r.y = vadd3(vsub(x.x, r.x), y, x.y); + + return r; +} + +static INLINE vdouble2 add2_ds(vdouble2 x, vdouble y) { + vdouble2 r; + + r.x = vadd(x.x, y); + vdouble v = vsub(r.x, x.x); + r.y = vadd(vsub(x.x, vsub(r.x, v)), vsub(y, v)); + r.y = vadd(r.y, x.y); + + return r; +} + +static INLINE vdouble2 add_sd(vdouble x, vdouble2 y) { + vdouble2 r; + + r.x = vadd(x, y.x); + r.y = vadd3(vsub(x, r.x), y.x, y.y); + + return r; +} + +static INLINE vdouble2 add_dd(vdouble2 x, vdouble2 y) { + // |x| >= |y| + + vdouble2 r; + + r.x = vadd(x.x, y.x); + r.y = vadd4(vsub(x.x, r.x), y.x, x.y, y.y); + + return r; +} + +static INLINE vdouble2 add2_dd(vdouble2 x, vdouble2 y) { + vdouble2 r; + + r.x = vadd(x.x, y.x); + vdouble v = vsub(r.x, x.x); + r.y = vadd(vsub(x.x, vsub(r.x, v)), vsub(y.x, v)); + r.y = vadd(r.y, vadd(x.y, y.y)); + + return r; +} + +static INLINE vdouble2 div_dd(vdouble2 n, vdouble2 d) { + vdouble t = vrec(d.x); + vdouble dh = vupper(d.x), dl = vsub(d.x, dh); + vdouble th = vupper(t ), tl = vsub(t , th); + vdouble nhh = vupper(n.x), nhl = vsub(n.x, nhh); + + vdouble2 q; + + q.x = vmul(n.x, t); + + vdouble u = vadd5(vsub(vmul(nhh, th), q.x), vmul(nhh, tl), vmul(nhl, th), vmul(nhl, tl), + vmul(q.x, vsub5(vcast_vd_d(1), vmul(dh, th), vmul(dh, tl), vmul(dl, th), vmul(dl, tl)))); + + q.y = vadd(vmul(t, vsub(n.y, vmul(q.x, d.y))), u); + + return q; +} + +static INLINE vdouble2 mul_ss(vdouble x, vdouble y) { + vdouble xh = vupper(x), xl = vsub(x, xh); + vdouble yh = vupper(y), yl = vsub(y, yh); + vdouble2 r; + + r.x = vmul(x, y); + r.y = vadd5(vmul(xh, yh), vneg(r.x), vmul(xl, yh), vmul(xh, yl), vmul(xl, yl)); + + return r; +} + +static INLINE vdouble2 mul_ds(vdouble2 x, vdouble y) { + vdouble xh = vupper(x.x), xl = vsub(x.x, xh); + vdouble yh = vupper(y ), yl = vsub(y , yh); + vdouble2 r; + + r.x = vmul(x.x, y); + r.y = vadd6(vmul(xh, yh), vneg(r.x), vmul(xl, yh), vmul(xh, yl), vmul(xl, yl), vmul(x.y, y)); + + return r; +} + +static INLINE vdouble2 mul_dd(vdouble2 x, vdouble2 y) { + vdouble xh = vupper(x.x), xl = vsub(x.x, xh); + vdouble yh = vupper(y.x), yl = vsub(y.x, yh); + vdouble2 r; + + r.x = vmul(x.x, y.x); + r.y = vadd7(vmul(xh, yh), vneg(r.x), vmul(xl, yh), vmul(xh, yl), vmul(xl, yl), vmul(x.x, y.y), vmul(x.y, y.x)); + + return r; +} + +static INLINE vdouble2 squ_d(vdouble2 x) { + vdouble xh = vupper(x.x), xl = vsub(x.x, xh); + vdouble2 r; + + r.x = vmul(x.x, x.x); + r.y = vadd5(vmul(xh, xh), vneg(r.x), vmul(vadd(xh, xh), xl), vmul(xl, xl), vmul(x.x, vadd(x.y, x.y))); + + return r; +} + +static INLINE vdouble2 rec_s(vdouble d) { + vdouble t = vrec(d); + vdouble dh = vupper(d), dl = vsub(d, dh); + vdouble th = vupper(t), tl = vsub(t, th); + vdouble2 q; + + q.x = t; + q.y = vmul(t, vsub5(vcast_vd_d(1), vmul(dh, th), vmul(dh, tl), vmul(dl, th), vmul(dl, tl))); + + return q; +} + +static INLINE vdouble2 sqrt_d(vdouble2 d) { + vdouble t = vsqrt(vadd(d.x, d.y)); + return scale_d(mul_dd(add2_dd(d, mul_ss(t, t)), rec_s(t)), vcast_vd_d(0.5)); +} + +// + +static INLINE vdouble xldexp(vdouble x, vint q) { return vldexp(x, q); } + +static INLINE vint xilogb(vdouble d) { + vdouble e = vcast_vd_vi(vsubi(vilogbp1(vabs(d)), vcast_vi_i(1))); + e = vsel(vmask_eq(d, vcast_vd_d(0)), vcast_vd_d(-2147483648.0), e); + e = vsel(vmask_eq(vabs(d), vcast_vd_d(rtengine::RT_INFINITY)), vcast_vd_d(2147483647), e); + return vrint_vi_vd(e); +} + +static INLINE vdouble xsin(vdouble d) { + vint q; + vdouble u, s; + + q = vrint_vi_vd(vmul(d, vcast_vd_d(rtengine::RT_1_PI))); + + u = vcast_vd_vi(q); + d = vadd(d, vmul(u, vcast_vd_d(-PI4_A*4))); + d = vadd(d, vmul(u, vcast_vd_d(-PI4_B*4))); + d = vadd(d, vmul(u, vcast_vd_d(-PI4_C*4))); + + s = vmul(d, d); + + d = vsel(vmaski_eq(vandi(q, vcast_vi_i(1)), vcast_vi_i(1)), vneg(d), d); + + u = vcast_vd_d(-7.97255955009037868891952e-18); + u = vmla(u, s, vcast_vd_d(2.81009972710863200091251e-15)); + u = vmla(u, s, vcast_vd_d(-7.64712219118158833288484e-13)); + u = vmla(u, s, vcast_vd_d(1.60590430605664501629054e-10)); + u = vmla(u, s, vcast_vd_d(-2.50521083763502045810755e-08)); + u = vmla(u, s, vcast_vd_d(2.75573192239198747630416e-06)); + u = vmla(u, s, vcast_vd_d(-0.000198412698412696162806809)); + u = vmla(u, s, vcast_vd_d(0.00833333333333332974823815)); + u = vmla(u, s, vcast_vd_d(-0.166666666666666657414808)); + + u = vmla(s, vmul(u, d), d); + + return u; +} + +static INLINE vdouble xcos(vdouble d) { + vint q; + vdouble u, s; + + q = vrint_vi_vd(vsub(vmul(d, vcast_vd_d(rtengine::RT_1_PI)), vcast_vd_d(0.5))); + q = vaddi(vaddi(q, q), vcast_vi_i(1)); + + u = vcast_vd_vi(q); + d = vadd(d, vmul(u, vcast_vd_d(-PI4_A*2))); + d = vadd(d, vmul(u, vcast_vd_d(-PI4_B*2))); + d = vadd(d, vmul(u, vcast_vd_d(-PI4_C*2))); + + s = vmul(d, d); + + d = vsel(vmaski_eq(vandi(q, vcast_vi_i(2)), vcast_vi_i(0)), vneg(d), d); + + u = vcast_vd_d(-7.97255955009037868891952e-18); + u = vmla(u, s, vcast_vd_d(2.81009972710863200091251e-15)); + u = vmla(u, s, vcast_vd_d(-7.64712219118158833288484e-13)); + u = vmla(u, s, vcast_vd_d(1.60590430605664501629054e-10)); + u = vmla(u, s, vcast_vd_d(-2.50521083763502045810755e-08)); + u = vmla(u, s, vcast_vd_d(2.75573192239198747630416e-06)); + u = vmla(u, s, vcast_vd_d(-0.000198412698412696162806809)); + u = vmla(u, s, vcast_vd_d(0.00833333333333332974823815)); + u = vmla(u, s, vcast_vd_d(-0.166666666666666657414808)); + + u = vmla(s, vmul(u, d), d); + + return u; +} + +static INLINE vdouble2 xsincos(vdouble d) { + vint q; + vmask m; + vdouble u, s, t, rx, ry; + vdouble2 r; + + q = vrint_vi_vd(vmul(d, vcast_vd_d(rtengine::RT_2_PI))); + + s = d; + + u = vcast_vd_vi(q); + s = vmla(u, vcast_vd_d(-PI4_A*2), s); + s = vmla(u, vcast_vd_d(-PI4_B*2), s); + s = vmla(u, vcast_vd_d(-PI4_C*2), s); + + t = s; + + s = vmul(s, s); + + u = vcast_vd_d(1.58938307283228937328511e-10); + u = vmla(u, s, vcast_vd_d(-2.50506943502539773349318e-08)); + u = vmla(u, s, vcast_vd_d(2.75573131776846360512547e-06)); + u = vmla(u, s, vcast_vd_d(-0.000198412698278911770864914)); + u = vmla(u, s, vcast_vd_d(0.0083333333333191845961746)); + u = vmla(u, s, vcast_vd_d(-0.166666666666666130709393)); + u = vmul(vmul(u, s), t); + + rx = vadd(t, u); + + u = vcast_vd_d(-1.13615350239097429531523e-11); + u = vmla(u, s, vcast_vd_d(2.08757471207040055479366e-09)); + u = vmla(u, s, vcast_vd_d(-2.75573144028847567498567e-07)); + u = vmla(u, s, vcast_vd_d(2.48015872890001867311915e-05)); + u = vmla(u, s, vcast_vd_d(-0.00138888888888714019282329)); + u = vmla(u, s, vcast_vd_d(0.0416666666666665519592062)); + u = vmla(u, s, vcast_vd_d(-0.5)); + + ry = vadd(vcast_vd_d(1), vmul(s, u)); + + m = vmaski_eq(vandi(q, vcast_vi_i(1)), vcast_vi_i(0)); + r.x = vsel(m, rx, ry); + r.y = vsel(m, ry, rx); + + m = vmaski_eq(vandi(q, vcast_vi_i(2)), vcast_vi_i(2)); + r.x = vreinterpret_vd_vm(vxorm(vandm(m, vreinterpret_vm_vd(vcast_vd_d(-0.0))), vreinterpret_vm_vd(r.x))); + + m = vmaski_eq(vandi(vaddi(q, vcast_vi_i(1)), vcast_vi_i(2)), vcast_vi_i(2)); + r.y = vreinterpret_vd_vm(vxorm(vandm(m, vreinterpret_vm_vd(vcast_vd_d(-0.0))), vreinterpret_vm_vd(r.y))); + + m = vmask_isinf(d); + r.x = vsel(m, vcast_vd_d(rtengine::RT_NAN), r.x); + r.y = vsel(m, vcast_vd_d(rtengine::RT_NAN), r.y); + + return r; +} + +static INLINE vdouble xtan(vdouble d) { + vint q; + vdouble u, s, x; + vmask m; + + q = vrint_vi_vd(vmul(d, vcast_vd_d(rtengine::RT_2_PI))); + + u = vcast_vd_vi(q); + x = vadd(d, vmul(u, vcast_vd_d(-PI4_A*2))); + x = vadd(x, vmul(u, vcast_vd_d(-PI4_B*2))); + x = vadd(x, vmul(u, vcast_vd_d(-PI4_C*2))); + + s = vmul(x, x); + + m = vmaski_eq(vandi(q, vcast_vi_i(1)), vcast_vi_i(1)); + x = vsel(m, vneg(x), x); + + u = vcast_vd_d(1.01419718511083373224408e-05); + u = vmla(u, s, vcast_vd_d(-2.59519791585924697698614e-05)); + u = vmla(u, s, vcast_vd_d(5.23388081915899855325186e-05)); + u = vmla(u, s, vcast_vd_d(-3.05033014433946488225616e-05)); + u = vmla(u, s, vcast_vd_d(7.14707504084242744267497e-05)); + u = vmla(u, s, vcast_vd_d(8.09674518280159187045078e-05)); + u = vmla(u, s, vcast_vd_d(0.000244884931879331847054404)); + u = vmla(u, s, vcast_vd_d(0.000588505168743587154904506)); + u = vmla(u, s, vcast_vd_d(0.00145612788922812427978848)); + u = vmla(u, s, vcast_vd_d(0.00359208743836906619142924)); + u = vmla(u, s, vcast_vd_d(0.00886323944362401618113356)); + u = vmla(u, s, vcast_vd_d(0.0218694882853846389592078)); + u = vmla(u, s, vcast_vd_d(0.0539682539781298417636002)); + u = vmla(u, s, vcast_vd_d(0.133333333333125941821962)); + u = vmla(u, s, vcast_vd_d(0.333333333333334980164153)); + + u = vmla(s, vmul(u, x), x); + + u = vsel(m, vrec(u), u); + + u = vsel(vmask_isinf(d), vcast_vd_d(rtengine::RT_NAN), u); + + return u; +} + +static INLINE vdouble atan2k(vdouble y, vdouble x) { + vdouble s, t, u; + vint q; + vmask p; + + q = vseli_lt(x, vcast_vd_d(0), vcast_vi_i(-2), vcast_vi_i(0)); + x = vabs(x); + + q = vseli_lt(x, y, vaddi(q, vcast_vi_i(1)), q); + p = vmask_lt(x, y); + s = vsel (p, vneg(x), y); + t = vmax (x, y); + + s = vdiv(s, t); + t = vmul(s, s); + + u = vcast_vd_d(-1.88796008463073496563746e-05); + u = vmla(u, t, vcast_vd_d(0.000209850076645816976906797)); + u = vmla(u, t, vcast_vd_d(-0.00110611831486672482563471)); + u = vmla(u, t, vcast_vd_d(0.00370026744188713119232403)); + u = vmla(u, t, vcast_vd_d(-0.00889896195887655491740809)); + u = vmla(u, t, vcast_vd_d(0.016599329773529201970117)); + u = vmla(u, t, vcast_vd_d(-0.0254517624932312641616861)); + u = vmla(u, t, vcast_vd_d(0.0337852580001353069993897)); + u = vmla(u, t, vcast_vd_d(-0.0407629191276836500001934)); + u = vmla(u, t, vcast_vd_d(0.0466667150077840625632675)); + u = vmla(u, t, vcast_vd_d(-0.0523674852303482457616113)); + u = vmla(u, t, vcast_vd_d(0.0587666392926673580854313)); + u = vmla(u, t, vcast_vd_d(-0.0666573579361080525984562)); + u = vmla(u, t, vcast_vd_d(0.0769219538311769618355029)); + u = vmla(u, t, vcast_vd_d(-0.090908995008245008229153)); + u = vmla(u, t, vcast_vd_d(0.111111105648261418443745)); + u = vmla(u, t, vcast_vd_d(-0.14285714266771329383765)); + u = vmla(u, t, vcast_vd_d(0.199999999996591265594148)); + u = vmla(u, t, vcast_vd_d(-0.333333333333311110369124)); + + t = vadd(s, vmul(s, vmul(t, u))); + t = vadd(t, vmul(vcast_vd_vi(q), vcast_vd_d(rtengine::RT_PI/2))); + + return t; +} + +static INLINE vdouble xatan2(vdouble y, vdouble x) { + vdouble r = atan2k(vabs(y), x); + + r = vmulsign(r, x); + r = vsel(vorm(vmask_isinf(x), vmask_eq(x, vcast_vd_d(0))), vsub(vcast_vd_d(rtengine::RT_PI/2), visinf2(x, vmulsign(vcast_vd_d(rtengine::RT_PI/2), x))), r); + r = vsel(vmask_isinf(y), vsub(vcast_vd_d(rtengine::RT_PI/2), visinf2(x, vmulsign(vcast_vd_d(rtengine::RT_PI/4), x))), r); + r = vsel(vmask_eq(y, vcast_vd_d(0)), vsel(vmask_eq(vsign(x), vcast_vd_d(-1.0)), vcast_vd_d(rtengine::RT_PI), vcast_vd_d(0)), r); + + return vsel(vorm(vmask_isnan(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_NAN), vmulsign(r, y)); +} + +static INLINE vdouble xasin(vdouble d) { vdouble x, y; -} vdouble2; + x = vadd(vcast_vd_d(1), d); + y = vsub(vcast_vd_d(1), d); + x = vmul(x, y); + x = vsqrt(x); + x = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), atan2k(vabs(d), x)); + return vmulsign(x, d); +} -vdouble xldexp(vdouble x, vint q); -vint xilogb(vdouble d); +static INLINE vdouble xacos(vdouble d) { + vdouble x, y; + x = vadd(vcast_vd_d(1), d); + y = vsub(vcast_vd_d(1), d); + x = vmul(x, y); + x = vsqrt(x); + x = vmulsign(atan2k(x, vabs(d)), d); + y = (vdouble)vandm(vmask_lt(d, vcast_vd_d(0)), (vmask)vcast_vd_d(rtengine::RT_PI)); + x = vadd(x, y); + return x; +} -vdouble xsin(vdouble d); -vdouble xcos(vdouble d); -vdouble2 xsincos(vdouble d); -vdouble xtan(vdouble d); -vdouble xasin(vdouble s); -vdouble xacos(vdouble s); -vdouble xatan(vdouble s); -vdouble xatan2(vdouble y, vdouble x); -vdouble xlog(vdouble d); -vdouble xexp(vdouble d); -vdouble xpow(vdouble x, vdouble y); +static INLINE vdouble xatan(vdouble s) { + vdouble t, u; + vint q; -vdouble xsinh(vdouble d); -vdouble xcosh(vdouble d); -vdouble xtanh(vdouble d); -vdouble xasinh(vdouble s); -vdouble xacosh(vdouble s); -vdouble xatanh(vdouble s); + q = vseli_lt(s, vcast_vd_d(0), vcast_vi_i(2), vcast_vi_i(0)); + s = vabs(s); -vdouble xcbrt(vdouble d); + q = vseli_lt(vcast_vd_d(1), s, vaddi(q, vcast_vi_i(1)), q); + s = vsel(vmask_lt(vcast_vd_d(1), s), vdiv(vcast_vd_d(1), s), s); -vdouble xexp2(vdouble a); -vdouble xexp10(vdouble a); -vdouble xexpm1(vdouble a); -vdouble xlog10(vdouble a); -vdouble xlog1p(vdouble a); + t = vmul(s, s); + + u = vcast_vd_d(-1.88796008463073496563746e-05); + u = vmla(u, t, vcast_vd_d(0.000209850076645816976906797)); + u = vmla(u, t, vcast_vd_d(-0.00110611831486672482563471)); + u = vmla(u, t, vcast_vd_d(0.00370026744188713119232403)); + u = vmla(u, t, vcast_vd_d(-0.00889896195887655491740809)); + u = vmla(u, t, vcast_vd_d(0.016599329773529201970117)); + u = vmla(u, t, vcast_vd_d(-0.0254517624932312641616861)); + u = vmla(u, t, vcast_vd_d(0.0337852580001353069993897)); + u = vmla(u, t, vcast_vd_d(-0.0407629191276836500001934)); + u = vmla(u, t, vcast_vd_d(0.0466667150077840625632675)); + u = vmla(u, t, vcast_vd_d(-0.0523674852303482457616113)); + u = vmla(u, t, vcast_vd_d(0.0587666392926673580854313)); + u = vmla(u, t, vcast_vd_d(-0.0666573579361080525984562)); + u = vmla(u, t, vcast_vd_d(0.0769219538311769618355029)); + u = vmla(u, t, vcast_vd_d(-0.090908995008245008229153)); + u = vmla(u, t, vcast_vd_d(0.111111105648261418443745)); + u = vmla(u, t, vcast_vd_d(-0.14285714266771329383765)); + u = vmla(u, t, vcast_vd_d(0.199999999996591265594148)); + u = vmla(u, t, vcast_vd_d(-0.333333333333311110369124)); + + t = vadd(s, vmul(s, vmul(t, u))); + + t = vsel(vmaski_eq(vandi(q, vcast_vi_i(1)), vcast_vi_i(1)), vsub(vcast_vd_d(rtengine::RT_PI/2), t), t); + t = vsel(vmaski_eq(vandi(q, vcast_vi_i(2)), vcast_vi_i(2)), vneg(t), t); + + return t; +} + +static INLINE vdouble xlog(vdouble d) { + vdouble x, x2; + vdouble t, m; + vint e; + + e = vilogbp1(vmul(d, vcast_vd_d(0.7071))); + m = vldexp(d, vsubi(vcast_vi_i(0), e)); + + x = vdiv(vadd(vcast_vd_d(-1), m), vadd(vcast_vd_d(1), m)); + x2 = vmul(x, x); + + t = vcast_vd_d(0.148197055177935105296783); + t = vmla(t, x2, vcast_vd_d(0.153108178020442575739679)); + t = vmla(t, x2, vcast_vd_d(0.181837339521549679055568)); + t = vmla(t, x2, vcast_vd_d(0.22222194152736701733275)); + t = vmla(t, x2, vcast_vd_d(0.285714288030134544449368)); + t = vmla(t, x2, vcast_vd_d(0.399999999989941956712869)); + t = vmla(t, x2, vcast_vd_d(0.666666666666685503450651)); + t = vmla(t, x2, vcast_vd_d(2)); + + x = vadd(vmul(x, t), vmul(vcast_vd_d(0.693147180559945286226764), vcast_vd_vi(e))); + + x = vsel(vmask_ispinf(d), vcast_vd_d(rtengine::RT_INFINITY), x); + x = vsel(vmask_gt(vcast_vd_d(0), d), vcast_vd_d(rtengine::RT_NAN), x); + x = vsel(vmask_eq(d, vcast_vd_d(0)), vcast_vd_d(-rtengine::RT_INFINITY), x); + + return x; +} + +static INLINE vdouble xexp(vdouble d) { + vint q = vrint_vi_vd(vmul(d, vcast_vd_d(R_LN2))); + vdouble s, u; + + s = vadd(d, vmul(vcast_vd_vi(q), vcast_vd_d(-L2U))); + s = vadd(s, vmul(vcast_vd_vi(q), vcast_vd_d(-L2L))); + + u = vcast_vd_d(2.08860621107283687536341e-09); + u = vmla(u, s, vcast_vd_d(2.51112930892876518610661e-08)); + u = vmla(u, s, vcast_vd_d(2.75573911234900471893338e-07)); + u = vmla(u, s, vcast_vd_d(2.75572362911928827629423e-06)); + u = vmla(u, s, vcast_vd_d(2.4801587159235472998791e-05)); + u = vmla(u, s, vcast_vd_d(0.000198412698960509205564975)); + u = vmla(u, s, vcast_vd_d(0.00138888888889774492207962)); + u = vmla(u, s, vcast_vd_d(0.00833333333331652721664984)); + u = vmla(u, s, vcast_vd_d(0.0416666666666665047591422)); + u = vmla(u, s, vcast_vd_d(0.166666666666666851703837)); + u = vmla(u, s, vcast_vd_d(0.5)); + + u = vadd(vcast_vd_d(1), vadd(s, vmul(vmul(s, s), u))); + + u = vldexp(u, q); + + u = vsel(vmask_isminf(d), vcast_vd_d(0), u); + + return u; +} + +static INLINE vdouble2 logk(vdouble d) { + vdouble2 x, x2; + vdouble t, m; + vint e; + + e = vilogbp1(vmul(d, vcast_vd_d(0.7071))); + m = vldexp(d, vsubi(vcast_vi_i(0), e)); + + x = div_dd(add2_ss(vcast_vd_d(-1), m), add2_ss(vcast_vd_d(1), m)); + x2 = squ_d(x); + x2 = normalize_d(x2); + + t = vcast_vd_d(0.134601987501262130076155); + t = vmla(t, x2.x, vcast_vd_d(0.132248509032032670243288)); + t = vmla(t, x2.x, vcast_vd_d(0.153883458318096079652524)); + t = vmla(t, x2.x, vcast_vd_d(0.181817427573705403298686)); + t = vmla(t, x2.x, vcast_vd_d(0.222222231326187414840781)); + t = vmla(t, x2.x, vcast_vd_d(0.285714285651261412873718)); + t = vmla(t, x2.x, vcast_vd_d(0.400000000000222439910458)); + t = vmla(t, x2.x, vcast_vd_d(0.666666666666666371239645)); + + return add2_dd(mul_ds(dd(vcast_vd_d(0.693147180559945286226764), vcast_vd_d(2.319046813846299558417771e-17)), + vcast_vd_vi(e)), + add2_dd(scale_d(x, vcast_vd_d(2)), mul_ds(mul_dd(x2, x), t))); +} + +static INLINE vdouble expk(vdouble2 d) { + vdouble u = vmul(vadd(d.x, d.y), vcast_vd_d(R_LN2)); + vint q = vrint_vi_vd(u); + vdouble2 s, t; + + s = add2_ds(d, vmul(vcast_vd_vi(q), vcast_vd_d(-L2U))); + s = add2_ds(s, vmul(vcast_vd_vi(q), vcast_vd_d(-L2L))); + + q = vrint_vi_vd(vmin(vmax(vcast_vd_d(-2047.49), u), vcast_vd_d(2047.49))); + + s = normalize_d(s); + + u = vcast_vd_d(2.51069683420950419527139e-08); + u = vmla(u, s.x, vcast_vd_d(2.76286166770270649116855e-07)); + u = vmla(u, s.x, vcast_vd_d(2.75572496725023574143864e-06)); + u = vmla(u, s.x, vcast_vd_d(2.48014973989819794114153e-05)); + u = vmla(u, s.x, vcast_vd_d(0.000198412698809069797676111)); + u = vmla(u, s.x, vcast_vd_d(0.0013888888939977128960529)); + u = vmla(u, s.x, vcast_vd_d(0.00833333333332371417601081)); + u = vmla(u, s.x, vcast_vd_d(0.0416666666665409524128449)); + u = vmla(u, s.x, vcast_vd_d(0.166666666666666740681535)); + u = vmla(u, s.x, vcast_vd_d(0.500000000000000999200722)); + + t = add_dd(s, mul_ds(squ_d(s), u)); + + t = add_sd(vcast_vd_d(1), t); + u = vadd(t.x, t.y); + u = vldexp(u, q); + + return u; +} + +static INLINE vdouble xpow(vdouble x, vdouble y) { +#if 1 + vmask yisint = vmask_eq(vcast_vd_vi(vrint_vi_vd(y)), y); + vmask yisodd = vandm(vmaski_eq(vandi(vrint_vi_vd(y), vcast_vi_i(1)), vcast_vi_i(1)), yisint); + + vdouble result = expk(mul_ds(logk(vabs(x)), y)); + + //result = vsel(vmask_isnan(result), vcast_vd_d(rtengine::RT_INFINITY), result); + + result = vmul(result, + vsel(vmask_gt(x, vcast_vd_d(0)), + vcast_vd_d(1), + vsel(yisint, + vsel(yisodd, + vcast_vd_d(-1), + vcast_vd_d(1)), + vcast_vd_d(rtengine::RT_NAN)))); + + vdouble efx = vreinterpret_vd_vm(vxorm(vreinterpret_vm_vd(vsub(vabs(x), vcast_vd_d(1))), vsignbit(y))); + + result = vsel(vmask_isinf(y), + vsel(vmask_lt(efx, vcast_vd_d(0)), + vcast_vd_d(0), + vsel(vmask_eq(efx, vcast_vd_d(0)), + vcast_vd_d(1.0), + vcast_vd_d(rtengine::RT_INFINITY))), + result); + + result = vsel(vorm(vmask_isinf(x), vmask_eq(x, vcast_vd_d(0))), + vmul(vsel(yisodd, vsign(x), vcast_vd_d(1)), + vsel(vmask_lt(vsel(vmask_eq(x, vcast_vd_d(0)), vneg(y), y), vcast_vd_d(0)), + vcast_vd_d(0), + vcast_vd_d(rtengine::RT_INFINITY))), + result); + + result = vsel(vorm(vmask_isnan(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_NAN), result); + + result = vsel(vorm(vmask_eq(y, vcast_vd_d(0)), vmask_eq(x, vcast_vd_d(1))), vcast_vd_d(1), result); + + return result; +#else + return expk(mul_ds(logk(x), y)); +#endif +} + +static INLINE vdouble2 expk2(vdouble2 d) { + vdouble u = vmul(vadd(d.x, d.y), vcast_vd_d(R_LN2)); + vint q = vrint_vi_vd(u); + vdouble2 s, t; + + s = add2_ds(d, vmul(vcast_vd_vi(q), vcast_vd_d(-L2U))); + s = add2_ds(s, vmul(vcast_vd_vi(q), vcast_vd_d(-L2L))); + + q = vrint_vi_vd(vmin(vmax(vcast_vd_d(-2047.49), u), vcast_vd_d(2047.49))); + + s = normalize_d(s); + + u = vcast_vd_d(2.51069683420950419527139e-08); + u = vmla(u, s.x, vcast_vd_d(2.76286166770270649116855e-07)); + u = vmla(u, s.x, vcast_vd_d(2.75572496725023574143864e-06)); + u = vmla(u, s.x, vcast_vd_d(2.48014973989819794114153e-05)); + u = vmla(u, s.x, vcast_vd_d(0.000198412698809069797676111)); + u = vmla(u, s.x, vcast_vd_d(0.0013888888939977128960529)); + u = vmla(u, s.x, vcast_vd_d(0.00833333333332371417601081)); + u = vmla(u, s.x, vcast_vd_d(0.0416666666665409524128449)); + u = vmla(u, s.x, vcast_vd_d(0.166666666666666740681535)); + u = vmla(u, s.x, vcast_vd_d(0.500000000000000999200722)); + + t = add_dd(s, mul_ds(squ_d(s), u)); + + t = add_sd(vcast_vd_d(1), t); + + return dd(vldexp(t.x, q), vldexp(t.y, q)); +} + +static INLINE vdouble xsinh(vdouble x) { + vdouble y = vabs(x); + vdouble2 d = expk2(dd(y, vcast_vd_d(0))); + d = add2_dd(d, div_dd(dd(vcast_vd_d(-1), vcast_vd_d(0)), d)); + y = vmul(vadd(d.x, d.y), vcast_vd_d(0.5)); + + y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_INFINITY), y); + y = vmulsign(y, x); + y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); + + return y; +} + +static INLINE vdouble xcosh(vdouble x) { + vdouble2 d = expk2(dd(x, vcast_vd_d(0))); + d = add2_dd(d, div_dd(dd(vcast_vd_d(1), vcast_vd_d(0)), d)); + vdouble y = vmul(vadd(d.x, d.y), vcast_vd_d(0.5)); + + y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_INFINITY), y); + y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); + + return y; +} + +static INLINE vdouble xtanh(vdouble x) { + vdouble y = vabs(x); + vdouble2 d = expk2(dd(y, vcast_vd_d(0))); + vdouble2 e = div_dd(dd(vcast_vd_d(1), vcast_vd_d(0)), d); + d = div_dd(add2_dd(d, scale_d(e, vcast_vd_d(-1))), add2_dd(d, e)); + y = d.x + d.y; + + y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(1.0), y); + y = vmulsign(y, x); + y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); + + return y; +} + +static INLINE vdouble2 logk2(vdouble2 d) { + vdouble2 x, x2, m; + vdouble t; + vint e; + + d = normalize_d(d); + e = vilogbp1(vmul(d.x, vcast_vd_d(0.7071))); + m = scale_d(d, vldexp(vcast_vd_d(1), vsubi(vcast_vi_i(0), e))); + + x = div_dd(add2_ds(m, vcast_vd_d(-1)), add2_ds(m, vcast_vd_d(1))); + x2 = squ_d(x); + x2 = normalize_d(x2); + + t = vcast_vd_d(0.134601987501262130076155); + t = vmla(t, x2.x, vcast_vd_d(0.132248509032032670243288)); + t = vmla(t, x2.x, vcast_vd_d(0.153883458318096079652524)); + t = vmla(t, x2.x, vcast_vd_d(0.181817427573705403298686)); + t = vmla(t, x2.x, vcast_vd_d(0.222222231326187414840781)); + t = vmla(t, x2.x, vcast_vd_d(0.285714285651261412873718)); + t = vmla(t, x2.x, vcast_vd_d(0.400000000000222439910458)); + t = vmla(t, x2.x, vcast_vd_d(0.666666666666666371239645)); + + return add2_dd(mul_ds(dd(vcast_vd_d(0.693147180559945286226764), vcast_vd_d(2.319046813846299558417771e-17)), + vcast_vd_vi(e)), + add2_dd(scale_d(x, vcast_vd_d(2)), mul_ds(mul_dd(x2, x), t))); +} + +static INLINE vdouble xasinh(vdouble x) { + vdouble y = vabs(x); + vdouble2 d = logk2(add2_ds(sqrt_d(add2_ds(mul_ss(y, y), vcast_vd_d(1))), y)); + y = vadd(d.x, d.y); + + y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_INFINITY), y); + y = vmulsign(y, x); + y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); + + return y; +} + +static INLINE vdouble xacosh(vdouble x) { + vdouble2 d = logk2(add2_ds(sqrt_d(add2_ds(mul_ss(x, x), vcast_vd_d(-1))), x)); + vdouble y = vadd(d.x, d.y); + + y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_INFINITY), y); + y = vsel(vmask_eq(x, vcast_vd_d(1.0)), vcast_vd_d(0.0), y); + y = vsel(vmask_lt(x, vcast_vd_d(1.0)), vcast_vd_d(rtengine::RT_NAN), y); + y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); + + return y; +} + +static INLINE vdouble xatanh(vdouble x) { + vdouble y = vabs(x); + vdouble2 d = logk2(div_dd(add2_ss(vcast_vd_d(1), y), add2_ss(vcast_vd_d(1), -y))); + y = vsel(vmask_gt(y, vcast_vd_d(1.0)), vcast_vd_d(rtengine::RT_NAN), vsel(vmask_eq(y, vcast_vd_d(1.0)), vcast_vd_d(rtengine::RT_INFINITY), vmul(vadd(d.x, d.y), vcast_vd_d(0.5)))); + + y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_NAN), y); + y = vmulsign(y, x); + y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); + + return y; +} + +static INLINE vdouble xcbrt(vdouble d) { + vdouble x, y, q = vcast_vd_d(1.0); + vint e, qu, re; + vdouble t; + + e = vilogbp1(vabs(d)); + d = vldexp(d, vsubi(vcast_vi_i(0), e)); + + t = vadd(vcast_vd_vi(e), vcast_vd_d(6144)); + qu = vtruncate_vi_vd(vdiv(t, vcast_vd_d(3))); + re = vtruncate_vi_vd(vsub(t, vmul(vcast_vd_vi(qu), vcast_vd_d(3)))); + + q = vsel(vmaski_eq(re, vcast_vi_i(1)), vcast_vd_d(1.2599210498948731647672106), q); + q = vsel(vmaski_eq(re, vcast_vi_i(2)), vcast_vd_d(1.5874010519681994747517056), q); + q = vldexp(q, vsubi(qu, vcast_vi_i(2048))); + + q = vmulsign(q, d); + + d = vabs(d); + + x = vcast_vd_d(-0.640245898480692909870982); + x = vmla(x, d, vcast_vd_d(2.96155103020039511818595)); + x = vmla(x, d, vcast_vd_d(-5.73353060922947843636166)); + x = vmla(x, d, vcast_vd_d(6.03990368989458747961407)); + x = vmla(x, d, vcast_vd_d(-3.85841935510444988821632)); + x = vmla(x, d, vcast_vd_d(2.2307275302496609725722)); + + y = vmul(x, x); y = vmul(y, y); x = vsub(x, vmul(vmla(d, y, vneg(x)), vcast_vd_d(1.0 / 3.0))); + y = vmul(vmul(d, x), x); + y = vmul(vsub(y, vmul(vmul(vcast_vd_d(2.0 / 3.0), y), vmla(y, x, vcast_vd_d(-1.0)))), q); + + return y; +} + +static INLINE vdouble xexp2(vdouble a) { + vdouble u = expk(mul_ds(dd(vcast_vd_d(0.69314718055994528623), vcast_vd_d(2.3190468138462995584e-17)), a)); + u = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), u); + u = vsel(vmask_isminf(a), vcast_vd_d(0), u); + return u; +} + +static INLINE vdouble xexp10(vdouble a) { + vdouble u = expk(mul_ds(dd(vcast_vd_d(2.3025850929940459011), vcast_vd_d(-2.1707562233822493508e-16)), a)); + u = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), u); + u = vsel(vmask_isminf(a), vcast_vd_d(0), u); + return u; +} + +static INLINE vdouble xexpm1(vdouble a) { + vdouble2 d = add2_ds(expk2(dd(a, vcast_vd_d(0))), vcast_vd_d(-1.0)); + vdouble x = d.x + d.y; + x = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), x); + x = vsel(vmask_isminf(a), vcast_vd_d(-1), x); + return x; +} + +static INLINE vdouble xlog10(vdouble a) { + vdouble2 d = mul_dd(logk(a), dd(vcast_vd_d(0.43429448190325176116), vcast_vd_d(6.6494347733425473126e-17))); + vdouble x = d.x + d.y; + + x = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), x); + x = vsel(vmask_gt(vcast_vd_d(0), a), vcast_vd_d(rtengine::RT_NAN), x); + x = vsel(vmask_eq(a, vcast_vd_d(0)), vcast_vd_d(-rtengine::RT_INFINITY), x); + + return x; +} + +static INLINE vdouble xlog1p(vdouble a) { + vdouble2 d = logk2(add2_ss(a, vcast_vd_d(1))); + vdouble x = d.x + d.y; + + x = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), x); + x = vsel(vmask_gt(vcast_vd_d(-1), a), vcast_vd_d(rtengine::RT_NAN), x); + x = vsel(vmask_eq(a, vcast_vd_d(-1)), vcast_vd_d(-rtengine::RT_INFINITY), x); + + return x; +} // @@ -126,15 +899,580 @@ typedef struct { vfloat x, y; } vfloat2; -vfloat xsinf(vfloat d); -vfloat xcosf(vfloat d); -vfloat2 xsincosf(vfloat d); -vfloat xtanf(vfloat d); -vfloat xasinf(vfloat s); -vfloat xacosf(vfloat s); -vfloat xatanf(vfloat s); -vfloat xatan2f(vfloat y, vfloat x); -vfloat xlogf(vfloat d); -vfloat xlogf0(vfloat d); -vfloat xexpf(vfloat d); -vfloat xcbrtf(vfloat s); +static INLINE vfloat vabsf(vfloat f) { return (vfloat)vandnotm((vmask)vcast_vf_f(-0.0f), (vmask)f); } +static INLINE vfloat vnegf(vfloat f) { return (vfloat)vxorm((vmask)f, (vmask)vcast_vf_f(-0.0f)); } + +#ifdef __SSE4_1__ +// only one instruction when using SSE4.1 +static INLINE vfloat vself(vmask mask, vfloat x, vfloat y) { + return _mm_blendv_ps(y,x,(vfloat)mask); +} + +static INLINE vint vselc(vmask mask, vint x, vint y) { + return _mm_blendv_epi8(y,x,mask); +} + +#else +// three instructions when using SSE2 +static INLINE vfloat vself(vmask mask, vfloat x, vfloat y) { + return (vfloat)vorm(vandm(mask, (vmask)x), vandnotm(mask, (vmask)y)); +} + +static INLINE vint vselc(vmask mask, vint x, vint y) { + return vorm(vandm(mask, (vmask)x), vandnotm(mask, (vmask)y)); +} +#endif + +static INLINE vfloat vselfzero(vmask mask, vfloat x) { + // returns value of x if corresponding mask bits are 1, else returns 0 + // faster than vself(mask, x, ZEROV) + return _mm_and_ps((vfloat)mask, x); +} +static INLINE vfloat vselfnotzero(vmask mask, vfloat x) { + // returns value of x if corresponding mask bits are 0, else returns 0 + // faster than vself(mask, ZEROV, x) + return _mm_andnot_ps((vfloat)mask, x); +} + +static INLINE vint vselizero(vmask mask, vint x) { + // returns value of x if corresponding mask bits are 1, else returns 0 + // faster than vselc(mask, x, ZEROV) + return _mm_and_si128(mask, x); +} +static INLINE vint vselinotzero(vmask mask, vint x) { + // returns value of x if corresponding mask bits are 0, else returns 0 + // faster than vselc(mask, ZEROV, x) + return _mm_andnot_si128(mask, x); +} + +static INLINE vint2 vseli2_lt(vfloat f0, vfloat f1, vint2 x, vint2 y) { + vint2 m2 = vcast_vi2_vm(vmaskf_lt(f0, f1)); + return vori2(vandi2(m2, x), vandnoti2(m2, y)); +} + +static INLINE vmask vsignbitf(vfloat f) { + return vandm((vmask)f, (vmask)vcast_vf_f(-0.0f)); +} + +static INLINE vfloat vmulsignf(vfloat x, vfloat y) { + return (vfloat)vxorm((vmask)x, vsignbitf(y)); +} + +static INLINE vfloat vsignf(vfloat f) { + return (vfloat)vorm((vmask)vcast_vf_f(1.0f), vandm((vmask)vcast_vf_f(-0.0f), (vmask)f)); +} + +static INLINE vmask vmaskf_isinf(vfloat d) { return vmaskf_eq(vabsf(d), vcast_vf_f(INFINITYf)); } +static INLINE vmask vmaskf_ispinf(vfloat d) { return vmaskf_eq(d, vcast_vf_f(INFINITYf)); } +static INLINE vmask vmaskf_isminf(vfloat d) { return vmaskf_eq(d, vcast_vf_f(-INFINITYf)); } +static INLINE vmask vmaskf_isnan(vfloat d) { return vmaskf_neq(d, d); } +// the following is equivalent to vorm(vmaskf_isnan(a), vmaskf_isnan(b)), but faster +static INLINE vmask vmaskf_isnan(vfloat a, vfloat b) { return (vmask)_mm_cmpunord_ps(a, b); } +static INLINE vfloat visinf2f(vfloat d, vfloat m) { return (vfloat)vandm(vmaskf_isinf(d), vorm(vsignbitf(d), (vmask)m)); } +static INLINE vfloat visinff(vfloat d) { return visinf2f(d, vcast_vf_f(1.0f)); } + +static INLINE vint2 vilogbp1f(vfloat d) { + vmask m = vmaskf_lt(d, vcast_vf_f(5.421010862427522E-20f)); + d = vself(m, vmulf(vcast_vf_f(1.8446744073709552E19f), d), d); + vint2 q = vandi2(vsrli2(vcast_vi2_vm(vreinterpret_vm_vf(d)), 23), vcast_vi2_i(0xff)); + q = vsubi2(q, vseli2(m, vcast_vi2_i(64 + 0x7e), vcast_vi2_i(0x7e))); + return q; +} + +static INLINE vfloat vldexpf(vfloat x, vint2 q) { + vfloat u; + vint2 m = vsrai2(q, 31); + m = vslli2(vsubi2(vsrai2(vaddi2(m, q), 6), m), 4); + q = vsubi2(q, vslli2(m, 2)); + u = vreinterpret_vf_vm(vcast_vm_vi2(vslli2(vaddi2(m, vcast_vi2_i(0x7f)), 23))); + x = vmulf(vmulf(vmulf(vmulf(x, u), u), u), u); + u = vreinterpret_vf_vm(vcast_vm_vi2(vslli2(vaddi2(q, vcast_vi2_i(0x7f)), 23))); + return vmulf(x, u); +} + +static INLINE vfloat xsinf(vfloat d) { + vint2 q; + vfloat u, s; + + q = vrint_vi2_vf(vmulf(d, vcast_vf_f((float)rtengine::RT_1_PI))); + + u = vcast_vf_vi2(q); + d = vmlaf(u, vcast_vf_f(-PI4_Af*4), d); + d = vmlaf(u, vcast_vf_f(-PI4_Bf*4), d); + d = vmlaf(u, vcast_vf_f(-PI4_Cf*4), d); + d = vmlaf(u, vcast_vf_f(-PI4_Df*4), d); + + s = vmulf(d, d); + + d = vself(vmaski2_eq(vandi2(q, vcast_vi2_i(1)), vcast_vi2_i(1)), vnegf(d), d); + + u = vcast_vf_f(2.6083159809786593541503e-06f); + u = vmlaf(u, s, vcast_vf_f(-0.0001981069071916863322258f)); + u = vmlaf(u, s, vcast_vf_f(0.00833307858556509017944336f)); + u = vmlaf(u, s, vcast_vf_f(-0.166666597127914428710938f)); + + u = vmlaf(s, vmulf(u, d), d); + + return u; +} + +static INLINE vfloat xcosf(vfloat d) { + vint2 q; + vfloat u, s; + + q = vrint_vi2_vf(vsubf(vmulf(d, vcast_vf_f((float)rtengine::RT_1_PI)), vcast_vf_f(0.5f))); + q = vaddi2(vaddi2(q, q), vcast_vi2_i(1)); + + u = vcast_vf_vi2(q); + d = vmlaf(u, vcast_vf_f(-PI4_Af*2), d); + d = vmlaf(u, vcast_vf_f(-PI4_Bf*2), d); + d = vmlaf(u, vcast_vf_f(-PI4_Cf*2), d); + d = vmlaf(u, vcast_vf_f(-PI4_Df*2), d); + + s = vmulf(d, d); + + d = vself(vmaski2_eq(vandi2(q, vcast_vi2_i(2)), vcast_vi2_i(2)), d, vnegf(d)); + + u = vcast_vf_f(2.6083159809786593541503e-06f); + u = vmlaf(u, s, vcast_vf_f(-0.0001981069071916863322258f)); + u = vmlaf(u, s, vcast_vf_f(0.00833307858556509017944336f)); + u = vmlaf(u, s, vcast_vf_f(-0.166666597127914428710938f)); + + u = vmlaf(s, vmulf(u, d), d); + + return u; +} + +static INLINE vfloat2 xsincosf(vfloat d) { + vint2 q; + vmask m; + vfloat u, s, t, rx, ry; + vfloat2 r; + + q = vrint_vi2_vf(vmulf(d, vcast_vf_f((float)rtengine::RT_2_PI))); + + s = d; + + u = vcast_vf_vi2(q); + s = vmlaf(u, vcast_vf_f(-PI4_Af*2), s); + s = vmlaf(u, vcast_vf_f(-PI4_Bf*2), s); + s = vmlaf(u, vcast_vf_f(-PI4_Cf*2), s); + s = vmlaf(u, vcast_vf_f(-PI4_Df*2), s); + + t = s; + + s = vmulf(s, s); + + u = vcast_vf_f(-0.000195169282960705459117889f); + u = vmlaf(u, s, vcast_vf_f(0.00833215750753879547119141f)); + u = vmlaf(u, s, vcast_vf_f(-0.166666537523269653320312f)); + u = vmulf(vmulf(u, s), t); + + rx = vaddf(t, u); + + u = vcast_vf_f(-2.71811842367242206819355e-07f); + u = vmlaf(u, s, vcast_vf_f(2.47990446951007470488548e-05f)); + u = vmlaf(u, s, vcast_vf_f(-0.00138888787478208541870117f)); + u = vmlaf(u, s, vcast_vf_f(0.0416666641831398010253906f)); + u = vmlaf(u, s, vcast_vf_f(-0.5)); + + ry = vaddf(vcast_vf_f(1), vmulf(s, u)); + + m = vmaski2_eq(vandi2(q, vcast_vi2_i(1)), vcast_vi2_i(0)); + r.x = vself(m, rx, ry); + r.y = vself(m, ry, rx); + + m = vmaski2_eq(vandi2(q, vcast_vi2_i(2)), vcast_vi2_i(2)); + r.x = vreinterpret_vf_vm(vxorm(vandm(m, vreinterpret_vm_vf(vcast_vf_f(-0.0))), vreinterpret_vm_vf(r.x))); + + m = vmaski2_eq(vandi2(vaddi2(q, vcast_vi2_i(1)), vcast_vi2_i(2)), vcast_vi2_i(2)); + r.y = vreinterpret_vf_vm(vxorm(vandm(m, vreinterpret_vm_vf(vcast_vf_f(-0.0))), vreinterpret_vm_vf(r.y))); + + m = vmaskf_isinf(d); + r.x = vself(m, vcast_vf_f(rtengine::RT_NAN), r.x); + r.y = vself(m, vcast_vf_f(rtengine::RT_NAN), r.y); + + return r; +} + +static INLINE vfloat xtanf(vfloat d) { + vint2 q; + vmask m; + vfloat u, s, x; + + q = vrint_vi2_vf(vmulf(d, vcast_vf_f((float)(2 * rtengine::RT_1_PI)))); + + x = d; + + u = vcast_vf_vi2(q); + x = vmlaf(u, vcast_vf_f(-PI4_Af*2), x); + x = vmlaf(u, vcast_vf_f(-PI4_Bf*2), x); + x = vmlaf(u, vcast_vf_f(-PI4_Cf*2), x); + x = vmlaf(u, vcast_vf_f(-PI4_Df*2), x); + + s = vmulf(x, x); + + m = vmaski2_eq(vandi2(q, vcast_vi2_i(1)), vcast_vi2_i(1)); + x = vself(m, vnegf(x), x); + + u = vcast_vf_f(0.00927245803177356719970703f); + u = vmlaf(u, s, vcast_vf_f(0.00331984995864331722259521f)); + u = vmlaf(u, s, vcast_vf_f(0.0242998078465461730957031f)); + u = vmlaf(u, s, vcast_vf_f(0.0534495301544666290283203f)); + u = vmlaf(u, s, vcast_vf_f(0.133383005857467651367188f)); + u = vmlaf(u, s, vcast_vf_f(0.333331853151321411132812f)); + + u = vmlaf(s, vmulf(u, x), x); + + u = vself(m, vrecf(u), u); + + u = vself(vmaskf_isinf(d), vcast_vf_f(NANf), u); + + return u; +} + +static INLINE vfloat xatanf(vfloat s) { + vfloat t, u; + vint2 q; + + q = vseli2_lt(s, vcast_vf_f(0.0f), vcast_vi2_i(2), vcast_vi2_i(0)); + s = vabsf(s); + + q = vseli2_lt(vcast_vf_f(1.0f), s, vaddi2(q, vcast_vi2_i(1)), q); + s = vself(vmaskf_lt(vcast_vf_f(1.0f), s), vdivf(vcast_vf_f(1.0f), s), s); + + t = vmulf(s, s); + + u = vcast_vf_f(0.00282363896258175373077393f); + u = vmlaf(u, t, vcast_vf_f(-0.0159569028764963150024414f)); + u = vmlaf(u, t, vcast_vf_f(0.0425049886107444763183594f)); + u = vmlaf(u, t, vcast_vf_f(-0.0748900920152664184570312f)); + u = vmlaf(u, t, vcast_vf_f(0.106347933411598205566406f)); + u = vmlaf(u, t, vcast_vf_f(-0.142027363181114196777344f)); + u = vmlaf(u, t, vcast_vf_f(0.199926957488059997558594f)); + u = vmlaf(u, t, vcast_vf_f(-0.333331018686294555664062f)); + + t = vaddf(s, vmulf(s, vmulf(t, u))); + + t = vself(vmaski2_eq(vandi2(q, vcast_vi2_i(1)), vcast_vi2_i(1)), vsubf(vcast_vf_f((float)(rtengine::RT_PI/2)), t), t); + t = vself(vmaski2_eq(vandi2(q, vcast_vi2_i(2)), vcast_vi2_i(2)), vnegf(t), t); + + return t; +} + +static INLINE vfloat atan2kf(vfloat y, vfloat x) { + vfloat s, t, u; + vint2 q; + vmask p; + + q = vseli2_lt(x, vcast_vf_f(0.0f), vcast_vi2_i(-2), vcast_vi2_i(0)); + x = vabsf(x); + + q = vseli2_lt(x, y, vaddi2(q, vcast_vi2_i(1)), q); + p = vmaskf_lt(x, y); + s = vself(p, vnegf(x), y); + t = vmaxf(x, y); + + s = vdivf(s, t); + t = vmulf(s, s); + + u = vcast_vf_f(0.00282363896258175373077393f); + u = vmlaf(u, t, vcast_vf_f(-0.0159569028764963150024414f)); + u = vmlaf(u, t, vcast_vf_f(0.0425049886107444763183594f)); + u = vmlaf(u, t, vcast_vf_f(-0.0748900920152664184570312f)); + u = vmlaf(u, t, vcast_vf_f(0.106347933411598205566406f)); + u = vmlaf(u, t, vcast_vf_f(-0.142027363181114196777344f)); + u = vmlaf(u, t, vcast_vf_f(0.199926957488059997558594f)); + u = vmlaf(u, t, vcast_vf_f(-0.333331018686294555664062f)); + + t = vaddf(s, vmulf(s, vmulf(t, u))); + t = vaddf(t, vmulf(vcast_vf_vi2(q), vcast_vf_f((float)(rtengine::RT_PI/2)))); + + return t; +} + +static INLINE vfloat xatan2f(vfloat y, vfloat x) { + vfloat r = atan2kf(vabsf(y), x); + + r = vmulsignf(r, x); + r = vself(vorm(vmaskf_isinf(x), vmaskf_eq(x, vcast_vf_f(0.0f))), vsubf(vcast_vf_f((float)(rtengine::RT_PI/2)), visinf2f(x, vmulsignf(vcast_vf_f((float)(rtengine::RT_PI/2)), x))), r); + r = vself(vmaskf_isinf(y), vsubf(vcast_vf_f((float)(rtengine::RT_PI/2)), visinf2f(x, vmulsignf(vcast_vf_f((float)(rtengine::RT_PI/4)), x))), r); + r = vself(vmaskf_eq(y, vcast_vf_f(0.0f)), vselfzero(vmaskf_eq(vsignf(x), vcast_vf_f(-1.0f)), vcast_vf_f((float)rtengine::RT_PI)), r); + + return vself(vmaskf_isnan(x, y), vcast_vf_f(NANf), vmulsignf(r, y)); +} + +static INLINE vfloat xasinf(vfloat d) { + vfloat x, y; + x = vaddf(vcast_vf_f(1.0f), d); + y = vsubf(vcast_vf_f(1.0f), d); + x = vmulf(x, y); + x = vsqrtf(x); + x = vself(vmaskf_isnan(x), vcast_vf_f(NANf), atan2kf(vabsf(d), x)); + return vmulsignf(x, d); +} + +static INLINE vfloat xacosf(vfloat d) { + vfloat x, y; + x = vaddf(vcast_vf_f(1.0f), d); + y = vsubf(vcast_vf_f(1.0f), d); + x = vmulf(x, y); + x = vsqrtf(x); + x = vmulsignf(atan2kf(x, vabsf(d)), d); + y = (vfloat)vandm(vmaskf_lt(d, vcast_vf_f(0.0f)), (vmask)vcast_vf_f((float)rtengine::RT_PI)); + x = vaddf(x, y); + return x; +} + +static INLINE vfloat xlogf(vfloat d) { + vfloat x, x2, t, m; + vint2 e; + + e = vilogbp1f(vmulf(d, vcast_vf_f(0.7071f))); + m = vldexpf(d, vsubi2(vcast_vi2_i(0), e)); + + x = vdivf(vaddf(vcast_vf_f(-1.0f), m), vaddf(vcast_vf_f(1.0f), m)); + x2 = vmulf(x, x); + + t = vcast_vf_f(0.2371599674224853515625f); + t = vmlaf(t, x2, vcast_vf_f(0.285279005765914916992188f)); + t = vmlaf(t, x2, vcast_vf_f(0.400005519390106201171875f)); + t = vmlaf(t, x2, vcast_vf_f(0.666666567325592041015625f)); + t = vmlaf(t, x2, vcast_vf_f(2.0f)); + + x = vaddf(vmulf(x, t), vmulf(vcast_vf_f(0.693147180559945286226764f), vcast_vf_vi2(e))); + + x = vself(vmaskf_ispinf(d), vcast_vf_f(INFINITYf), x); + x = vself(vmaskf_gt(vcast_vf_f(0), d), vcast_vf_f(NANf), x); + x = vself(vmaskf_eq(d, vcast_vf_f(0)), vcast_vf_f(-INFINITYf), x); + + return x; +} + +static INLINE vfloat xlogf1(vfloat d) { // does xlogf(vmaxf(d, 1.f)) but faster + vfloat x, x2, t, m; + vint2 e; + + e = vilogbp1f(vmulf(d, vcast_vf_f(0.7071f))); + m = vldexpf(d, vsubi2(vcast_vi2_i(0), e)); + + x = vdivf(vaddf(vcast_vf_f(-1.0f), m), vaddf(vcast_vf_f(1.0f), m)); + x2 = vmulf(x, x); + + t = vcast_vf_f(0.2371599674224853515625f); + t = vmlaf(t, x2, vcast_vf_f(0.285279005765914916992188f)); + t = vmlaf(t, x2, vcast_vf_f(0.400005519390106201171875f)); + t = vmlaf(t, x2, vcast_vf_f(0.666666567325592041015625f)); + t = vmlaf(t, x2, vcast_vf_f(2.0f)); + + x = vaddf(vmulf(x, t), vmulf(vcast_vf_f(0.693147180559945286226764f), vcast_vf_vi2(e))); + + x = vself(vmaskf_ispinf(d), vcast_vf_f(INFINITYf), x); + x = vselfnotzero(vmaskf_le(d, vcast_vf_f(1.f)), x); + + return x; +} + +static INLINE vfloat xlogf0(vfloat d) { + vfloat x, x2, t, m; + vint2 e; + + e = vilogbp1f(vmulf(d, vcast_vf_f(0.7071f))); + m = vldexpf(d, vsubi2(vcast_vi2_i(0), e)); + + x = vdivf(vaddf(vcast_vf_f(-1.0f), m), vaddf(vcast_vf_f(1.0f), m)); + x2 = vmulf(x, x); + + t = vcast_vf_f(0.2371599674224853515625f); + t = vmlaf(t, x2, vcast_vf_f(0.285279005765914916992188f)); + t = vmlaf(t, x2, vcast_vf_f(0.400005519390106201171875f)); + t = vmlaf(t, x2, vcast_vf_f(0.666666567325592041015625f)); + t = vmlaf(t, x2, vcast_vf_f(2.0f)); + + x = vaddf(vmulf(x, t), vmulf(vcast_vf_f(0.693147180559945286226764f), vcast_vf_vi2(e))); + + x = vself(vmaskf_ispinf(d), vcast_vf_f(0), x); + x = vself(vmaskf_gt(vcast_vf_f(0), d), vcast_vf_f(0), x); + x = vself(vmaskf_eq(d, vcast_vf_f(0)), vcast_vf_f(0), x); + + return x; +} + +static INLINE vfloat xlogfNoCheck(vfloat d) { // this version does not check input values. Use it only when you know the input values are > 0 e.g. when filling a lookup table + vfloat x, x2, t, m; + vint2 e; + + e = vilogbp1f(vmulf(d, vcast_vf_f(0.7071f))); + m = vldexpf(d, vsubi2(vcast_vi2_i(0), e)); + + x = vdivf(vaddf(vcast_vf_f(-1.0f), m), vaddf(vcast_vf_f(1.0f), m)); + x2 = vmulf(x, x); + + t = vcast_vf_f(0.2371599674224853515625f); + t = vmlaf(t, x2, vcast_vf_f(0.285279005765914916992188f)); + t = vmlaf(t, x2, vcast_vf_f(0.400005519390106201171875f)); + t = vmlaf(t, x2, vcast_vf_f(0.666666567325592041015625f)); + t = vmlaf(t, x2, vcast_vf_f(2.0f)); + + return vaddf(vmulf(x, t), vmulf(vcast_vf_f(0.693147180559945286226764f), vcast_vf_vi2(e))); + +} + +static INLINE vfloat xexpf(vfloat d) { + vint2 q = vrint_vi2_vf(vmulf(d, vcast_vf_f(R_LN2f))); + vfloat s, u; + + s = vmlaf(vcast_vf_vi2(q), vcast_vf_f(-L2Uf),d); + s = vmlaf(vcast_vf_vi2(q), vcast_vf_f(-L2Lf),s); + + u = vcast_vf_f(0.00136324646882712841033936f); + u = vmlaf(u, s, vcast_vf_f(0.00836596917361021041870117f)); + u = vmlaf(u, s, vcast_vf_f(0.0416710823774337768554688f)); + u = vmlaf(u, s, vcast_vf_f(0.166665524244308471679688f)); + u = vmlaf(u, s, vcast_vf_f(0.499999850988388061523438f)); + + u = vaddf(vcast_vf_f(1.0f), vmlaf(vmulf(s, s), u, s)); + + u = vldexpf(u, q); + + // -104.0 + return vselfnotzero(vmaskf_gt(vcast_vf_f(-104.f), d), u); +} + +static INLINE vfloat xexpfNoCheck(vfloat d) { // this version does not check input values. Use it only when you know the input values are > -104.f e.g. when filling a lookup table + vint2 q = vrint_vi2_vf(vmulf(d, vcast_vf_f(R_LN2f))); + vfloat s, u; + + s = vmlaf(vcast_vf_vi2(q), vcast_vf_f(-L2Uf),d); + s = vmlaf(vcast_vf_vi2(q), vcast_vf_f(-L2Lf),s); + + u = vcast_vf_f(0.00136324646882712841033936f); + u = vmlaf(u, s, vcast_vf_f(0.00836596917361021041870117f)); + u = vmlaf(u, s, vcast_vf_f(0.0416710823774337768554688f)); + u = vmlaf(u, s, vcast_vf_f(0.166665524244308471679688f)); + u = vmlaf(u, s, vcast_vf_f(0.499999850988388061523438f)); + + u = vaddf(vcast_vf_f(1.0f), vmlaf(vmulf(s, s), u, s)); + + return vldexpf(u, q); +} + +static INLINE vfloat xcbrtf(vfloat d) { + vfloat x, y, q = vcast_vf_f(1.0), t; + vint2 e, qu, re; + + e = vilogbp1f(vabsf(d)); + d = vldexpf(d, vsubi2(vcast_vi2_i(0), e)); + + t = vaddf(vcast_vf_vi2(e), vcast_vf_f(6144)); + qu = vtruncate_vi2_vf(vdivf(t, vcast_vf_f(3))); + re = vtruncate_vi2_vf(vsubf(t, vmulf(vcast_vf_vi2(qu), vcast_vf_f(3)))); + + q = vself(vmaski2_eq(re, vcast_vi2_i(1)), vcast_vf_f(1.2599210498948731647672106f), q); + q = vself(vmaski2_eq(re, vcast_vi2_i(2)), vcast_vf_f(1.5874010519681994747517056f), q); + q = vldexpf(q, vsubi2(qu, vcast_vi2_i(2048))); + + q = vmulsignf(q, d); + d = vabsf(d); + + x = vcast_vf_f(-0.601564466953277587890625f); + x = vmlaf(x, d, vcast_vf_f(2.8208892345428466796875f)); + x = vmlaf(x, d, vcast_vf_f(-5.532182216644287109375f)); + x = vmlaf(x, d, vcast_vf_f(5.898262500762939453125f)); + x = vmlaf(x, d, vcast_vf_f(-3.8095417022705078125f)); + x = vmlaf(x, d, vcast_vf_f(2.2241256237030029296875f)); + + y = vmulf(vmulf(d, x), x); + y = vmulf(vsubf(y, vmulf(vmulf(vcast_vf_f(2.0f / 3.0f), y), vmlaf(y, x, vcast_vf_f(-1.0f)))), q); + + return y; +} + +static INLINE vfloat vclampf(vfloat value, vfloat low, vfloat high) { + // clamps value in [low;high], returns low if value is NaN + return vmaxf(vminf(high, value), low); +} + +static INLINE vfloat SQRV(vfloat a){ + return a * a; +} + +static inline void vswap( vmask condition, vfloat &a, vfloat &b) { + // conditional swap the elements of two vfloats + vfloat temp = vself(condition, a, b); // the values which fit to condition + a = vself(condition, b, a); // the values which fit to inverted condition + b = temp; +} + +static inline float vhadd( vfloat a ) { + // returns a[0] + a[1] + a[2] + a[3] + a += _mm_movehl_ps(a, 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; +} + +static INLINE vfloat vintpf(vfloat a, vfloat b, vfloat c) { + // calculate a * b + (1 - a) * c (interpolate two values) + // following is valid: + // vintpf(a, b+x, c+x) = vintpf(a, b, c) + x + // vintpf(a, b*x, c*x) = vintpf(a, b, c) * x + return a * (b-c) + c; +} + +static INLINE vfloat vdup(vfloat a){ + // returns { a[0],a[0],a[1],a[1] } + return _mm_unpacklo_ps( a, a ); +} + +static INLINE vfloat vaddc2vfu(float &a) +{ + // loads a[0]..a[7] and returns { a[0]+a[1], a[2]+a[3], a[4]+a[5], a[6]+a[7] } + vfloat a1 = _mm_loadu_ps( &a ); + vfloat a2 = _mm_loadu_ps( (&a) + 4 ); + return _mm_shuffle_ps(a1,a2,_MM_SHUFFLE( 2,0,2,0 )) + _mm_shuffle_ps(a1,a2,_MM_SHUFFLE( 3,1,3,1 )); +} + +static INLINE vfloat vadivapb (vfloat a, vfloat b) { + return a / (a+b); +} + +static INLINE void vconvertrgbrgbrgbrgb2rrrrggggbbbb (const float * src, vfloat &rv, vfloat &gv, vfloat &bv) { // cool function name, isn't it ? :P + // converts a sequence of 4 float RGB triplets to 3 red, green and blue quadruples + rv = _mm_setr_ps(src[0],src[3],src[6],src[9]); + gv = _mm_setr_ps(src[1],src[4],src[7],src[10]); + bv = _mm_setr_ps(src[2],src[5],src[8],src[11]); +} + +#if defined( __SSE4_1__ ) && defined( __x86_64__ ) +static INLINE vfloat vceilf(vfloat x) { + return _mm_round_ps(x, _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC); +} + +#else + +static INLINE vfloat vceilf(vfloat x) { + __m128i zerov = _mm_setzero_si128(); + zerov = _mm_cmpeq_epi32(zerov, zerov); + const vfloat onev = (vfloat)_mm_slli_epi32(_mm_srli_epi32(zerov, 25), 23); //create vector 1.0f + const vfloat xi = _mm_cvtepi32_ps(_mm_cvttps_epi32(x)); + return xi + _mm_and_ps(_mm_cmplt_ps(xi, x), onev); +} +#endif + +#endif // __SSE2__ diff --git a/rtengine/slicer.cc b/rtengine/slicer.cc deleted file mode 100644 index 72a42e07e..000000000 --- a/rtengine/slicer.cc +++ /dev/null @@ -1,152 +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 -#include -#include "rt_math.h" - -#include "slicer.h" - -#ifdef _OPENMP -#include -#endif - -using namespace std; - -// If no parameter set, everything = 0 -> process all the image -Block::Block() -{ - posX = 0; - posY = 0; - width = 0; - height = 0; -} - -Block::Block(unsigned int x, unsigned int y, unsigned int w, unsigned int h) -{ - posX = x; - posY = y; - width = w; - height = h; -} - -/* - * Slice a sub-region to process in blocks who's size is given by the number of processor - * and the number of pixel per block (and hence the memory footprint) - */ -Slicer::Slicer(unsigned int imageWidth, unsigned int imageHeight, Block *subRegion, unsigned int pixels ) -{ - // If the sub-region has a portrait shape, X and Y coordinates are swapped for better result - // It will be swapped back when sending back the block coordinates - region.width = !(subRegion->width) ? imageWidth : subRegion->width; - region.height = !(subRegion->height) ? imageHeight : subRegion->height; // Assuming that the sub-region is under posY - - if (region.width < region.height) { - region.width = !(subRegion->height) ? imageHeight : subRegion->height; - region.height = !(subRegion->width) ? imageWidth : subRegion->width; // Assuming that the sub-region is under posY - portrait = true; - imWidth = imageHeight; - imHeight = imageWidth; - region.posX = subRegion->posY; - region.posY = subRegion->posX; - } else { - portrait = false; - imWidth = imageWidth; - imHeight = imageHeight; - region.posX = subRegion->posX; - region.posY = subRegion->posY; - } - - double subRegionRatio = (double)(region.width) / (double)(region.height); - - //total number of core/processor -#ifdef _OPENMP - unsigned int procNumber = omp_get_num_procs(); -#else - unsigned int procNumber = 1; -#endif - - //calculate the number of block - blockNumber = (double(region.width * region.height) / (double)pixels); - blockNumber = int((rtengine::max(blockNumber, 1U) + (double)procNumber / 2.) / procNumber) * procNumber; - vBlockNumber = (unsigned int)(sqrt((double)blockNumber / subRegionRatio) + 0.5); - vBlockNumber = CLAMP(vBlockNumber, 1, blockNumber); - hBlockNumber = (double)blockNumber / (double)vBlockNumber; - blockWidth = 1.0 / hBlockNumber; - - double maxPixelNumberX = (double)region.height / (double)vBlockNumber; - double maxPixelNumberY = (double)region.width / (double)((unsigned int)hBlockNumber); - - if (maxPixelNumberX - (double)((unsigned int)maxPixelNumberX) != 0.) { - maxPixelNumberX += 1.; - } - - if (maxPixelNumberY - (double)((unsigned int)maxPixelNumberY) != 0.) { - maxPixelNumberY += 1.; - } - - maxPixelNumber = (unsigned int)maxPixelNumberX * (unsigned int)maxPixelNumberY; - -} - -// return the absolute position and size of the requested block -void Slicer::get_block(unsigned int numBlock, Block *block) -{ - double roundingTradeOff = (hBlockNumber - (double)((int)hBlockNumber)) == 0.5 ? 2.1 : 2.0; - unsigned int alreadyCompletedLineNbr = (unsigned int)((double)(numBlock) * blockWidth + (blockWidth / roundingTradeOff)); - - unsigned int prevLineEnd = (unsigned int)((double)alreadyCompletedLineNbr * hBlockNumber + 0.5); - unsigned int myLineEnd = (unsigned int)((double)(alreadyCompletedLineNbr + 1) * hBlockNumber + 0.5); - - unsigned int nbrCellsOnMyLine = myLineEnd - prevLineEnd; - unsigned int cellOnMyLine = numBlock - prevLineEnd; - - unsigned int blockStart = (unsigned int)(((double)region.width / (double)nbrCellsOnMyLine) * (double)(cellOnMyLine)); - unsigned int blockEnd = (unsigned int)(((double)region.width / (double)nbrCellsOnMyLine) * (double)(cellOnMyLine + 1)); - block->width = blockEnd - blockStart; - block->posX = region.posX + blockStart; - - if (cellOnMyLine == (nbrCellsOnMyLine - 1)) { - // We make sure that the last block of the row take the rest of the remaining X space - block->width = region.posX + region.width - block->posX; - } - - blockStart = (unsigned int)(((double)region.height / (double)vBlockNumber) * (double)(alreadyCompletedLineNbr)); - blockEnd = (unsigned int)(((double)region.height / (double)vBlockNumber) * (double)(alreadyCompletedLineNbr + 1)); - block->height = blockEnd - blockStart; - block->posY = region.posY + blockStart; - - if (alreadyCompletedLineNbr == (vBlockNumber - 1)) { - block->height = region.posY + region.height - block->posY; - } - - if (portrait) { - // we swap back the X/Y coordinates - unsigned int temp; - - temp = block->posX; - block->posX = block->posY; - block->posY = temp; - - temp = block->width; - block->width = block->height; - block->height = temp; - - } -} diff --git a/rtengine/slicer.h b/rtengine/slicer.h deleted file mode 100644 index 06e1522cd..000000000 --- a/rtengine/slicer.h +++ /dev/null @@ -1,63 +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 . - */ -#ifndef _SLICER_ -#define _SLICER_ - -//The image is divided in blocks even on single processor machine, mainly to decrease memory consumption -//maximum number of pixel per block -#define PIXELS_PER_BLOCK 250000 - -/* - * Used to specify a subregion of an image and to specify a cell in this subregion - */ -class Block -{ -public: - unsigned int posX; - unsigned int posY; - unsigned int width; // If 0, use the full width of the image - unsigned int height; // If 0, use the full height of the image - Block(); - Block(unsigned int x, unsigned int y, unsigned int w, unsigned int h); -}; - -/* - * This class handle the best slicing of the image with a given number of pixels per block and the number of - * processor, and tries to create blocks as square as possible. There can be a different number of block on - * each line, and the pixel per block requested may be oversized by very few percents. - */ -class Slicer -{ -protected: - bool portrait; // Orientation of the sub-region - unsigned int imWidth; // Image width - unsigned int imHeight; // Image height - Block region; // Sub-region to process - double hBlockNumber; // Horizontal number of block for the sub-region - unsigned int vBlockNumber; // Vertical number of block for the sub-region - double blockWidth; - -public: - unsigned int blockNumber; // number of block for the sub-region - unsigned int maxPixelNumber; // number of pixel of the biggest block (for memory allocation purpose) - Slicer(unsigned int imageWidth, unsigned int imageHeight, Block *subRegion, unsigned int pixels); - void get_block(unsigned int blockId, Block *block); -}; - -#endif diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc index e5c98a93a..271818303 100644 --- a/rtengine/stdimagesource.cc +++ b/rtengine/stdimagesource.cc @@ -14,24 +14,25 @@ * GNU General Public License for more details. * * 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" #include "color.h" -#include "curves.h" #include "iccstore.h" +#include "image8.h" +#include "image16.h" +#include "imagefloat.h" #include "imageio.h" #include "mytime.h" #include "procparams.h" +#include "utils.h" #undef THREAD_PRIORITY_NORMAL namespace rtengine { -extern const Settings* settings; - template void freeArray (T** a, int H) { for (int i = 0; i < H; i++) { @@ -52,7 +53,6 @@ template T** allocArray (int W, int H) return t; } -#define HR_SCALE 2 StdImageSource::StdImageSource () : ImageSource(), img(nullptr), plistener(nullptr), full(false), max{}, rgbSourceModified(false) { diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index 8f16880dc..b95328c80 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -14,16 +14,29 @@ * GNU General Public License for more details. * * 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_ +#pragma once +#include "colortemp.h" #include "imagesource.h" namespace rtengine { +class ImageIO; + +namespace procparams +{ + +class ProcParams; + +struct ToneCurveParams; +struct RAWParams; +struct ColorManagementParams; + +} + class StdImageSource : public ImageSource { @@ -43,7 +56,7 @@ public: ~StdImageSource () override; int load (const Glib::ustring &fname) override; - void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw) override; + void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw) override; ColorTemp getWB () const override { return wb; @@ -87,8 +100,8 @@ public: plistener = pl; } - void convertColorSpace(Imagefloat* image, const ColorManagementParams &cmp, const ColorTemp &wb) override;// RAWParams raw will not be used for non-raw files (see imagesource.h) - static void colorSpaceConversion (Imagefloat* im, const ColorManagementParams &cmp, cmsHPROFILE embedded, IIOSampleFormat sampleFormat); + void convertColorSpace(Imagefloat* image, const procparams::ColorManagementParams &cmp, const ColorTemp &wb) override;// RAWParams raw will not be used for non-raw files (see imagesource.h) + static void colorSpaceConversion (Imagefloat* im, const procparams::ColorManagementParams &cmp, cmsHPROFILE embedded, IIOSampleFormat sampleFormat); bool isRGBSourceModified() const override { @@ -102,7 +115,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..a87d7510c 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 . */ /** @@ -50,31 +50,33 @@ * $Id: tmo_fattal02.cpp,v 1.3 2008/11/04 23:43:08 rafm Exp $ */ - #ifdef _OPENMP #include #endif + +#include #include #include #include -#include -#include #include +#include -#include #include #include +#include #include "array2D.h" -#include "improcfun.h" -#include "settings.h" +#include "color.h" #include "iccstore.h" -#include "StopWatch.h" -#include "sleef.c" +#include "imagefloat.h" +#include "improcfun.h" #include "opthelper.h" -#include "rt_algo.h" -#include "rescale.h" #include "procparams.h" +#include "rescale.h" +#include "rt_algo.h" +#include "settings.h" +#include "sleef.h" +#include "StopWatch.h" namespace rtengine { @@ -83,7 +85,6 @@ namespace rtengine * RT code ******************************************************************************/ -extern const Settings *settings; extern MyMutex *fftwMutex; using namespace std; @@ -96,60 +97,62 @@ class Array2Df: public array2D typedef array2D Super; public: Array2Df(): Super() {} - Array2Df (int w, int h): Super (w, h) {} + Array2Df(int w, int h): Super(w, h) {} + Array2Df(int w, int h, float **data): + Super(w, h, data, ARRAY2D_BYREFERENCE) {} - float &operator() (int w, int h) + float &operator()(int w, int h) { return (*this)[h][w]; } - const float &operator() (int w, int h) const + const float &operator()(int w, int h) const { return (*this)[h][w]; } - float &operator() (int i) + float &operator()(int i) { - return static_cast (*this)[i]; + return static_cast(*this)[i]; } - const float &operator() (int i) const + const float &operator()(int i) const { - return const_cast (*this).operator() (i); + return const_cast(*this).operator()(i); } int getRows() const { - return const_cast (*this).height(); + return const_cast(*this).height(); } int getCols() const { - return const_cast (*this).width(); + return const_cast(*this).width(); } float *data() { - return static_cast (*this); + return static_cast(*this); } const float *data() const { - return const_cast (*this).data(); + return const_cast(*this).data(); } }; // upper bound on image dimension used in tmo_fattal02 -- see the comment there const int RT_dimension_cap = 1920; -void rescale_bilinear (const Array2Df &src, Array2Df &dst, bool multithread); +void rescale_bilinear(const Array2Df &src, Array2Df &dst, bool multithread); /****************************************************************************** * Luminance HDR code (modifications are marked with an RT comment) ******************************************************************************/ -void downSample (const Array2Df& A, Array2Df& B) +void downSample(const Array2Df& A, Array2Df& B) { const int width = B.getCols(); const int height = B.getRows(); @@ -159,18 +162,18 @@ void downSample (const Array2Df& A, Array2Df& B) // speed improvements. The main issue is the pde solver and in case of the // fft solver uses optimised threaded fftw routines. //#pragma omp parallel for - for ( int y = 0 ; y < height ; y++ ) { - for ( int x = 0 ; x < width ; x++ ) { - float p = A (2 * x, 2 * y); - p += A (2 * x + 1, 2 * y); - p += A (2 * x, 2 * y + 1); - p += A (2 * x + 1, 2 * y + 1); - B (x, y) = p * 0.25f; // p / 4.0f; + for (int y = 0 ; y < height ; y++) { + for (int x = 0 ; x < width ; x++) { + float p = A(2 * x, 2 * y); + p += A(2 * x + 1, 2 * y); + p += A(2 * x, 2 * y + 1); + p += A(2 * x + 1, 2 * y + 1); + B(x, y) = p * 0.25f; // p / 4.0f; } } } -void gaussianBlur (const Array2Df& I, Array2Df& L, bool multithread) +void gaussianBlur(const Array2Df& I, Array2Df& L, bool multithread) { const int width = I.getCols(); const int height = I.getRows(); @@ -178,30 +181,30 @@ void gaussianBlur (const Array2Df& I, Array2Df& L, bool multithread) if (width < 3 || height < 3) { if (&I != &L) { for (int i = 0, n = width * height; i < n; ++i) { - L (i) = I (i); + L(i) = I(i); } } return; } - Array2Df T (width, height); + Array2Df T(width, height); //--- X blur #ifdef _OPENMP #pragma omp parallel for shared(I, T) if(multithread) #endif - for ( int y = 0 ; y < height ; y++ ) { - for ( int x = 1 ; x < width - 1 ; x++ ) { - float t = 2.f * I (x, y); - t += I (x - 1, y); - t += I (x + 1, y); - T (x, y) = t * 0.25f; // t / 4.f; + for (int y = 0 ; y < height ; y++) { + for (int x = 1 ; x < width - 1 ; x++) { + float t = 2.f * I(x, y); + t += I(x - 1, y); + t += I(x + 1, y); + T(x, y) = t * 0.25f; // t / 4.f; } - T (0, y) = ( 3.f * I (0, y) + I (1, y) ) * 0.25f; // / 4.f; - T (width - 1, y) = ( 3.f * I (width - 1, y) + I (width - 2, y) ) * 0.25f; // / 4.f; + T(0, y) = (3.f * I(0, y) + I(1, y)) * 0.25f; // / 4.f; + T(width - 1, y) = (3.f * I(width - 1, y) + I(width - 2, y)) * 0.25f; // / 4.f; } //--- Y blur @@ -209,66 +212,66 @@ void gaussianBlur (const Array2Df& I, Array2Df& L, bool multithread) #pragma omp parallel for if(multithread) #endif - for ( int x = 0 ; x < width - 7 ; x += 8 ) { - for ( int y = 1 ; y < height - 1 ; y++ ) { + for (int x = 0 ; x < width - 7 ; x += 8) { + for (int y = 1 ; y < height - 1 ; y++) { for (int xx = 0; xx < 8; ++xx) { - float t = 2.f * T (x + xx, y); - t += T (x + xx, y - 1); - t += T (x + xx, y + 1); - L (x + xx, y) = t * 0.25f; // t/4.0f; + float t = 2.f * T(x + xx, y); + t += T(x + xx, y - 1); + t += T(x + xx, y + 1); + L(x + xx, y) = t * 0.25f; // t/4.0f; } } for (int xx = 0; xx < 8; ++xx) { - L (x + xx, 0) = ( 3.f * T (x + xx, 0) + T (x + xx, 1) ) * 0.25f; // / 4.0f; - L (x + xx, height - 1) = ( 3.f * T (x + xx, height - 1) + T (x + xx, height - 2) ) * 0.25f; // / 4.0f; + L(x + xx, 0) = (3.f * T(x + xx, 0) + T(x + xx, 1)) * 0.25f; // / 4.0f; + L(x + xx, height - 1) = (3.f * T(x + xx, height - 1) + T(x + xx, height - 2)) * 0.25f; // / 4.0f; } } - for ( int x = width - (width % 8) ; x < width ; x++ ) { - for ( int y = 1 ; y < height - 1 ; y++ ) { - float t = 2.f * T (x, y); - t += T (x, y - 1); - t += T (x, y + 1); - L (x, y) = t * 0.25f; // t/4.0f; + for (int x = width - (width % 8) ; x < width ; x++) { + for (int y = 1 ; y < height - 1 ; y++) { + float t = 2.f * T(x, y); + t += T(x, y - 1); + t += T(x, y + 1); + L(x, y) = t * 0.25f; // t/4.0f; } - L (x, 0) = ( 3.f * T (x, 0) + T (x, 1) ) * 0.25f; // / 4.0f; - L (x, height - 1) = ( 3.f * T (x, height - 1) + T (x, height - 2) ) * 0.25f; // / 4.0f; + L(x, 0) = (3.f * T(x, 0) + T(x, 1)) * 0.25f; // / 4.0f; + L(x, height - 1) = (3.f * T(x, height - 1) + T(x, height - 2)) * 0.25f; // / 4.0f; } } -void createGaussianPyramids (Array2Df** pyramids, int nlevels, bool multithread) +void createGaussianPyramids(Array2Df** pyramids, int nlevels, bool multithread) { // pyramids[0] is already set int width = pyramids[0]->getCols(); int height = pyramids[0]->getRows(); - Array2Df* L = new Array2Df (width, height); - gaussianBlur ( *pyramids[0], *L, multithread ); + Array2Df* L = new Array2Df(width, height); + gaussianBlur(*pyramids[0], *L, multithread); - for ( int k = 1 ; k < nlevels ; k++ ) { + for (int k = 1 ; k < nlevels ; k++) { if (width > 2 && height > 2) { width /= 2; height /= 2; - pyramids[k] = new Array2Df (width, height); - downSample (*L, *pyramids[k]); + pyramids[k] = new Array2Df(width, height); + downSample(*L, *pyramids[k]); } else { // RT - now nlevels is fixed in tmo_fattal02 (see the comment in // there), so it might happen that we have to add some padding to // the gaussian pyramids - pyramids[k] = new Array2Df (width, height); + pyramids[k] = new Array2Df(width, height); for (int j = 0, n = width * height; j < n; ++j) { - (*pyramids[k]) (j) = (*L) (j); + (*pyramids[k])(j) = (*L)(j); } } if (k < nlevels - 1) { delete L; - L = new Array2Df (width, height); - gaussianBlur ( *pyramids[k], *L, multithread ); + L = new Array2Df(width, height); + gaussianBlur(*pyramids[k], *L, multithread); } } @@ -277,37 +280,37 @@ void createGaussianPyramids (Array2Df** pyramids, int nlevels, bool multithread) //-------------------------------------------------------------------- -float calculateGradients (Array2Df* H, Array2Df* G, int k, bool multithread) +float calculateGradients(Array2Df* H, Array2Df* G, int k, bool multithread) { const int width = H->getCols(); const int height = H->getRows(); - const float divider = pow ( 2.0f, k + 1 ); + const float divider = pow(2.0f, k + 1); double avgGrad = 0.0; // use double precision for large summations #ifdef _OPENMP #pragma omp parallel for reduction(+:avgGrad) if(multithread) #endif - for ( int y = 0 ; y < height ; y++ ) { + for (int y = 0 ; y < height ; y++) { int n = (y == 0 ? 0 : y - 1); int s = (y + 1 == height ? y : y + 1); - for ( int x = 0 ; x < width ; x++ ) { + for (int x = 0 ; x < width ; x++) { float gx, gy; int w, e; w = (x == 0 ? 0 : x - 1); e = (x + 1 == width ? x : x + 1); - gx = ((*H) (w, y) - (*H) (e, y)); + gx = ((*H)(w, y) - (*H)(e, y)); - gy = ((*H) (x, s) - (*H) (x, n)); + gy = ((*H)(x, s) - (*H)(x, n)); // note this implicitly assumes that H(-1)=H(0) // for the fft-pde slover this would need adjustment as H(-1)=H(1) // is assumed, which means gx=0.0, gy=0.0 at the boundaries // however, the impact is not visible so we ignore this here - (*G) (x, y) = sqrt (gx * gx + gy * gy) / divider; - avgGrad += (*G) (x, y); + (*G)(x, y) = sqrt(gx * gx + gy * gy) / divider; + avgGrad += (*G)(x, y); } } @@ -316,7 +319,7 @@ float calculateGradients (Array2Df* H, Array2Df* G, int k, bool multithread) //-------------------------------------------------------------------- -void upSample (const Array2Df& A, Array2Df& B) +void upSample(const Array2Df& A, Array2Df& B) { const int width = B.getCols(); const int height = B.getRows(); @@ -324,14 +327,14 @@ void upSample (const Array2Df& A, Array2Df& B) const int aheight = A.getRows(); //#pragma omp parallel for shared(A, B) - for ( int y = 0 ; y < height ; y++ ) { - for ( int x = 0 ; x < width ; x++ ) { - int ax = static_cast (x * 0.5f); //x / 2.f; - int ay = static_cast (y * 0.5f); //y / 2.f; + for (int y = 0 ; y < height ; y++) { + for (int x = 0 ; x < width ; x++) { + int ax = static_cast(x * 0.5f); //x / 2.f; + int ay = static_cast(y * 0.5f); //y / 2.f; ax = (ax < awidth) ? ax : awidth - 1; ay = (ay < aheight) ? ay : aheight - 1; - B (x, y) = A (ax, ay); + B(x, y) = A(ax, ay); } } @@ -351,24 +354,25 @@ void upSample (const Array2Df& A, Array2Df& B) } -void calculateFiMatrix (Array2Df* FI, Array2Df* gradients[], - float avgGrad[], int nlevels, int detail_level, - float alfa, float beta, float noise, bool multithread) +void calculateFiMatrix(Array2Df* FI, Array2Df* gradients[], + float avgGrad[], int nlevels, int detail_level, + float alfa, float beta, float noise, bool multithread) { int width = gradients[nlevels - 1]->getCols(); int height = gradients[nlevels - 1]->getRows(); Array2Df** fi = new Array2Df*[nlevels]; - fi[nlevels - 1] = new Array2Df (width, height); + fi[nlevels - 1] = new Array2Df(width, height); #ifdef _OPENMP #pragma omp parallel for shared(fi) if(multithread) #endif - for ( int k = 0 ; k < width * height ; k++ ) { - (*fi[nlevels - 1]) (k) = 1.0f; + + for (int k = 0 ; k < width * height ; k++) { + (*fi[nlevels - 1])(k) = 1.0f; } - for ( int k = nlevels - 1; k >= 0 ; k-- ) { + for (int k = nlevels - 1; k >= 0 ; k--) { width = gradients[k]->getCols(); height = gradients[k]->getRows(); @@ -378,50 +382,51 @@ void calculateFiMatrix (Array2Df* FI, Array2Df* gradients[], #ifdef _OPENMP #pragma omp parallel for shared(fi,avgGrad) if(multithread) #endif - for ( int y = 0; y < height; y++ ) { - for ( int x = 0; x < width; x++ ) { - float grad = ((*gradients[k]) (x, y) < 1e-4f) ? 1e-4 : (*gradients[k]) (x, y); - float a = alfa * avgGrad[k]; - float value = pow ((grad + noise) / a, beta - 1.0f); - (*fi[k]) (x, y) *= value; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + float grad = ((*gradients[k])(x, y) < 1e-4f) ? 1e-4 : (*gradients[k])(x, y); + float a = alfa * avgGrad[k]; + float value = pow((grad + noise) / a, beta - 1.0f); + + (*fi[k])(x, y) *= value; } } } // create next level - if ( k > 1 ) { + if (k > 1) { width = gradients[k - 1]->getCols(); height = gradients[k - 1]->getRows(); - fi[k - 1] = new Array2Df (width, height); + fi[k - 1] = new Array2Df(width, height); } else { fi[0] = FI; // highest level -> result } if (k > 0) { - upSample (*fi[k], *fi[k - 1]); // upsample to next level - gaussianBlur (*fi[k - 1], *fi[k - 1], multithread); + upSample(*fi[k], *fi[k - 1]); // upsample to next level + gaussianBlur(*fi[k - 1], *fi[k - 1], multithread); } } - for ( int k = 1 ; k < nlevels ; k++ ) { + for (int k = 1 ; k < nlevels ; k++) { delete fi[k]; } delete[] fi; } -void solve_pde_fft (Array2Df *F, Array2Df *U, Array2Df *buf, bool multithread); +void solve_pde_fft(Array2Df *F, Array2Df *U, Array2Df *buf, bool multithread, int algo); -void tmo_fattal02 (size_t width, - size_t height, - const Array2Df& Y, - Array2Df& L, - float alfa, - float beta, - float noise, - int detail_level, - bool multithread) +void tmo_fattal02(size_t width, + size_t height, + const Array2Df& Y, + Array2Df& L, + float alfa, + float beta, + float noise, + int detail_level, + bool multithread, int algo) { // #ifdef TIMER_PROFILING // msec_timer stop_watch; @@ -430,13 +435,14 @@ void tmo_fattal02 (size_t width, // static const float black_point = 0.1f; // static const float white_point = 0.5f; static const float gamma = 1.0f; // 0.8f; +//paramet // static const int detail_level = 3; - if ( detail_level < 0 ) { + if (detail_level < 0) { detail_level = 0; } - if ( detail_level > 3 ) { + if (detail_level > 3) { detail_level = 3; } @@ -461,29 +467,34 @@ void tmo_fattal02 (size_t width, int size = width * height; - +//paramet // find max value, normalize to range 0..100 and take logarithm // float minLum = Y (0, 0); - float maxLum = Y (0, 0); + float maxLum = Y(0, 0); #ifdef _OPENMP #pragma omp parallel for reduction(max:maxLum) if(multithread) #endif - for ( int i = 0 ; i < size ; i++ ) { - maxLum = std::max (maxLum, Y (i)); + for (int i = 0 ; i < size ; i++) { + maxLum = std::max(maxLum, Y(i)); } - Array2Df* H = new Array2Df (width, height); + Array2Df* H = new Array2Df(width, height); float temp = 100.f / maxLum; - float eps = 1e-4f; + + if (algo == 1) { + temp = 1.f; + } + #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) @@ -494,13 +505,13 @@ void tmo_fattal02 (size_t width, #ifdef __SSE2__ for (; j < width - 3; j += 4) { - STVFU ((*H)[i][j], xlogf (tempv * LVFU (Y[i][j]) + epsv)); + STVFU((*H)[i][j], xlogf(tempv * LVFU(Y[i][j]) + epsv)); } #endif for (; j < width; ++j) { - (*H)[i][j] = xlogf (temp * Y[i][j] + eps); + (*H)[i][j] = xlogf(temp * Y[i][j] + eps); } } } @@ -527,13 +538,13 @@ void tmo_fattal02 (size_t width, * improved */ int fullwidth = width; int fullheight = height; - int dim = std::max (width, height); + int dim = std::max(width, height); Array2Df *fullH = nullptr; if (dim > RT_dimension_cap) { float s = float (RT_dimension_cap) / float (dim); - Array2Df *HH = new Array2Df (width * s, height * s); - rescale_bilinear (*H, *HH, multithread); + Array2Df *HH = new Array2Df(width * s, height * s); + rescale_bilinear(*H, *HH, multithread); fullH = H; H = HH; width = H->getCols(); @@ -546,25 +557,27 @@ void tmo_fattal02 (size_t width, Array2Df* pyramids[nlevels]; pyramids[0] = H; - createGaussianPyramids (pyramids, nlevels, multithread); + createGaussianPyramids(pyramids, nlevels, multithread); // calculate gradients and its average values on pyramid levels Array2Df* gradients[nlevels]; float avgGrad[nlevels]; - for ( int k = 0 ; k < nlevels ; k++ ) { - gradients[k] = new Array2Df (pyramids[k]->getCols(), pyramids[k]->getRows()); - avgGrad[k] = calculateGradients (pyramids[k], gradients[k], k, multithread); - if(k != 0) // pyramids[0] is H. Will be deleted later + for (int k = 0 ; k < nlevels ; k++) { + gradients[k] = new Array2Df(pyramids[k]->getCols(), pyramids[k]->getRows()); + avgGrad[k] = calculateGradients(pyramids[k], gradients[k], k, multithread); + + if (k != 0) { // pyramids[0] is H. Will be deleted later delete pyramids[k]; + } } // calculate fi matrix - Array2Df* FI = new Array2Df (width, height); - calculateFiMatrix (FI, gradients, avgGrad, nlevels, detail_level, alfa, beta, noise, multithread); + Array2Df* FI = new Array2Df(width, height); + calculateFiMatrix(FI, gradients, avgGrad, nlevels, detail_level, alfa, beta, noise, multithread); - for ( int i = 0 ; i < nlevels ; i++ ) { + for (int i = 0 ; i < nlevels ; i++) { delete gradients[i]; } @@ -572,8 +585,8 @@ void tmo_fattal02 (size_t width, if (fullH) { delete H; H = fullH; - Array2Df *FI2 = new Array2Df (fullwidth, fullheight); - rescale_bilinear (*FI, *FI2, multithread); + Array2Df *FI2 = new Array2Df(fullwidth, fullheight); + rescale_bilinear(*FI, *FI2, multithread); delete FI; FI = FI2; width = fullwidth; @@ -583,7 +596,7 @@ void tmo_fattal02 (size_t width, /** RT */ // attenuate gradients - Array2Df* Gx = new Array2Df (width, height); + Array2Df* Gx = new Array2Df(width, height); Array2Df* Gy = &L; // use L as buffer for Gy // the fft solver solves the Poisson pde but with slightly different @@ -594,16 +607,16 @@ void tmo_fattal02 (size_t width, #pragma omp parallel for if(multithread) #endif - for ( size_t y = 0 ; y < height ; y++ ) { + for (size_t y = 0 ; y < height ; y++) { // sets index+1 based on the boundary assumption H(N+1)=H(N-1) unsigned int yp1 = (y + 1 >= height ? height - 2 : y + 1); - for ( size_t x = 0 ; x < width ; x++ ) { + for (size_t x = 0 ; x < width ; x++) { // sets index+1 based on the boundary assumption H(N+1)=H(N-1) unsigned int xp1 = (x + 1 >= width ? width - 2 : x + 1); // forward differences in H, so need to use between-points approx of FI - (*Gx) (x, y) = ((*H) (xp1, y) - (*H) (x, y)) * 0.5 * ((*FI) (xp1, y) + (*FI) (x, y)); - (*Gy) (x, y) = ((*H) (x, yp1) - (*H) (x, y)) * 0.5 * ((*FI) (x, yp1) + (*FI) (x, y)); + (*Gx)(x, y) = ((*H)(xp1, y) - (*H)(x, y)) * 0.5 * ((*FI)(xp1, y) + (*FI)(x, y)); + (*Gy)(x, y) = ((*H)(x, yp1) - (*H)(x, y)) * 0.5 * ((*FI)(x, yp1) + (*FI)(x, y)); } } @@ -614,24 +627,24 @@ void tmo_fattal02 (size_t width, #pragma omp parallel for if(multithread) #endif - for ( size_t y = 0; y < height; ++y ) { - for ( size_t x = 0; x < width; ++x ) { - (*FI) (x, y) = (*Gx) (x, y) + (*Gy) (x, y); + for (size_t y = 0; y < height; ++y) { + for (size_t x = 0; x < width; ++x) { + (*FI)(x, y) = (*Gx)(x, y) + (*Gy)(x, y); - if ( x > 0 ) { - (*FI) (x, y) -= (*Gx) (x - 1, y); + if (x > 0) { + (*FI)(x, y) -= (*Gx)(x - 1, y); } - if ( y > 0 ) { - (*FI) (x, y) -= (*Gy) (x, y - 1); + if (y > 0) { + (*FI)(x, y) -= (*Gy)(x, y - 1); } if (x == 0) { - (*FI) (x, y) += (*Gx) (x, y); + (*FI)(x, y) += (*Gx)(x, y); } if (y == 0) { - (*FI) (x, y) += (*Gy) (x, y); + (*FI)(x, y) += (*Gy)(x, y); } } @@ -641,8 +654,8 @@ void tmo_fattal02 (size_t width, // solve pde and exponentiate (ie recover compressed image) { - MyMutex::MyLock lock (*fftwMutex); - solve_pde_fft (FI, &L, Gx, multithread); + MyMutex::MyLock lock(*fftwMutex); + solve_pde_fft(FI, &L, Gx, multithread, algo); } delete Gx; delete FI; @@ -652,7 +665,7 @@ void tmo_fattal02 (size_t width, #endif { #ifdef __SSE2__ - vfloat gammav = F2V (gamma); + vfloat gammav = F2V(gamma); #endif #ifdef _OPENMP #pragma omp for schedule(dynamic,16) @@ -663,13 +676,13 @@ void tmo_fattal02 (size_t width, #ifdef __SSE2__ for (; j < width - 3; j += 4) { - STVFU (L[i][j], xexpf (gammav * LVFU (L[i][j]))); + STVFU(L[i][j], xexpf(gammav * LVFU(L[i][j]))); } #endif for (; j < width; j++) { - L[i][j] = xexpf ( gamma * L[i][j]); + L[i][j] = xexpf(gamma * L[i][j]); } } } @@ -723,11 +736,11 @@ void tmo_fattal02 (size_t width, // returns T = EVy A EVx^tr // note, modifies input data -void transform_ev2normal (Array2Df *A, Array2Df *T, bool multithread) +void transform_ev2normal(Array2Df *A, Array2Df *T, bool multithread) { int width = A->getCols(); int height = A->getRows(); - assert ((int)T->getCols() == width && (int)T->getRows() == height); + assert((int)T->getCols() == width && (int)T->getRows() == height); // the discrete cosine transform is not exactly the transform needed // need to scale input values to get the right transformation @@ -735,19 +748,19 @@ void transform_ev2normal (Array2Df *A, Array2Df *T, bool multithread) #pragma omp parallel for if(multithread) #endif - for (int y = 1 ; y < height - 1 ; y++ ) - for (int x = 1 ; x < width - 1 ; x++ ) { - (*A) (x, y) *= 0.25f; + for (int y = 1 ; y < height - 1 ; y++) + for (int x = 1 ; x < width - 1 ; x++) { + (*A)(x, y) *= 0.25f; } - for (int x = 1 ; x < width - 1 ; x++ ) { - (*A) (x, 0) *= 0.5f; - (*A) (x, height - 1) *= 0.5f; + for (int x = 1 ; x < width - 1 ; x++) { + (*A)(x, 0) *= 0.5f; + (*A)(x, height - 1) *= 0.5f; } - for (int y = 1 ; y < height - 1 ; y++ ) { - (*A) (0, y) *= 0.5; - (*A) (width - 1, y) *= 0.5f; + for (int y = 1 ; y < height - 1 ; y++) { + (*A)(0, y) *= 0.5; + (*A)(width - 1, y) *= 0.5f; } // note, fftw provides its own memory allocation routines which @@ -761,26 +774,26 @@ void transform_ev2normal (Array2Df *A, Array2Df *T, bool multithread) // executes 2d discrete cosine transform fftwf_plan p; - p = fftwf_plan_r2r_2d (height, width, A->data(), T->data(), - FFTW_REDFT00, FFTW_REDFT00, FFTW_ESTIMATE); - fftwf_execute (p); - fftwf_destroy_plan (p); + p = fftwf_plan_r2r_2d(height, width, A->data(), T->data(), + FFTW_REDFT00, FFTW_REDFT00, FFTW_ESTIMATE); + fftwf_execute(p); + fftwf_destroy_plan(p); } // returns T = EVy^-1 * A * (EVx^-1)^tr -void transform_normal2ev (Array2Df *A, Array2Df *T, bool multithread) +void transform_normal2ev(Array2Df *A, Array2Df *T, bool multithread) { int width = A->getCols(); int height = A->getRows(); - assert ((int)T->getCols() == width && (int)T->getRows() == height); + assert((int)T->getCols() == width && (int)T->getRows() == height); // executes 2d discrete cosine transform fftwf_plan p; - p = fftwf_plan_r2r_2d (height, width, A->data(), T->data(), - FFTW_REDFT00, FFTW_REDFT00, FFTW_ESTIMATE); - fftwf_execute (p); - fftwf_destroy_plan (p); + p = fftwf_plan_r2r_2d(height, width, A->data(), T->data(), + FFTW_REDFT00, FFTW_REDFT00, FFTW_ESTIMATE); + fftwf_execute(p); + fftwf_destroy_plan(p); // need to scale the output matrix to get the right transform float factor = (1.0f / ((height - 1) * (width - 1))); @@ -788,30 +801,30 @@ void transform_normal2ev (Array2Df *A, Array2Df *T, bool multithread) #pragma omp parallel for if(multithread) #endif - for (int y = 0 ; y < height ; y++ ) - for (int x = 0 ; x < width ; x++ ) { - (*T) (x, y) *= factor; + for (int y = 0 ; y < height ; y++) + for (int x = 0 ; x < width ; x++) { + (*T)(x, y) *= factor; } - for (int x = 0 ; x < width ; x++ ) { - (*T) (x, 0) *= 0.5f; - (*T) (x, height - 1) *= 0.5f; + for (int x = 0 ; x < width ; x++) { + (*T)(x, 0) *= 0.5f; + (*T)(x, height - 1) *= 0.5f; } - for (int y = 0 ; y < height ; y++ ) { - (*T) (0, y) *= 0.5f; - (*T) (width - 1, y) *= 0.5f; + for (int y = 0 ; y < height ; y++) { + (*T)(0, y) *= 0.5f; + (*T)(width - 1, y) *= 0.5f; } } // returns the eigenvalues of the 1d laplace operator -std::vector get_lambda (int n) +std::vector get_lambda(int n) { - assert (n > 1); - std::vector v (n); + assert(n > 1); + std::vector v(n); for (int i = 0; i < n; i++) { - v[i] = -4.0 * SQR (sin ((double)i / (2 * (n - 1)) * RT_PI)); + v[i] = -4.0 * SQR(sin((double)i / (2 * (n - 1)) * RT_PI)); } return v; @@ -861,22 +874,22 @@ std::vector get_lambda (int n) // not modified and the equation might not have a solution but an // approximate solution with a minimum error is then calculated // double precision version -void solve_pde_fft (Array2Df *F, Array2Df *U, Array2Df *buf, bool multithread)/*, pfs::Progress &ph, +void solve_pde_fft(Array2Df *F, Array2Df *U, Array2Df *buf, bool multithread, int algo)/*, pfs::Progress &ph, bool adjust_bound)*/ { // ph.setValue(20); //DEBUG_STR << "solve_pde_fft: solving Laplace U = F ..." << std::endl; int width = F->getCols(); int height = F->getRows(); - assert ((int)U->getCols() == width && (int)U->getRows() == height); - assert (buf->getCols() == width && buf->getRows() == height); + assert((int)U->getCols() == width && (int)U->getRows() == height); + assert(buf->getCols() == width && buf->getRows() == height); // activate parallel execution of fft routines #ifdef RT_FFTW3F_OMP if (multithread) { fftwf_init_threads(); - fftwf_plan_with_nthreads ( omp_get_max_threads() ); + fftwf_plan_with_nthreads(omp_get_max_threads()); } // #else @@ -896,29 +909,29 @@ void solve_pde_fft (Array2Df *F, Array2Df *U, Array2Df *buf, bool multithread)/* // transforms F into eigenvector space: Ftr = //DEBUG_STR << "solve_pde_fft: transform F to ev space (fft)" << std::endl; Array2Df* F_tr = buf; - transform_normal2ev (F, F_tr, multithread); + transform_normal2ev(F, F_tr, multithread); // TODO: F no longer needed so could release memory, but as it is an // input parameter we won't do that // in the eigenvector space the solution is very simple - std::vector l1 = get_lambda (height); - std::vector l2 = get_lambda (width); + std::vector l1 = get_lambda(height); + std::vector l2 = get_lambda(width); #ifdef _OPENMP #pragma omp parallel for if(multithread) #endif - for (int y = 0 ; y < height ; y++ ) { - for (int x = 0 ; x < width ; x++ ) { - (*F_tr) (x, y) = (*F_tr) (x, y) / (l1[y] + l2[x]); + for (int y = 0 ; y < height ; y++) { + for (int x = 0 ; x < width ; x++) { + (*F_tr)(x, y) = (*F_tr)(x, y) / (l1[y] + l2[x]); } } - (*F_tr) (0, 0) = 0.f; // any value ok, only adds a const to the solution + (*F_tr)(0, 0) = 0.f; // any value ok, only adds a const to the solution // transforms F_tr back to the normal space - transform_ev2normal (F_tr, U, multithread); + transform_ev2normal(F_tr, U, multithread); // the solution U as calculated will satisfy something like int U = 0 // since for any constant c, U-c is also a solution and we are mainly @@ -926,21 +939,23 @@ 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; + if (algo == 0) { + 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)); - } + for (int i = 0; i < width * height; i++) { + maxVal = std::max(maxVal, (*U)(i)); + } #ifdef _OPENMP - #pragma omp parallel for if(multithread) + #pragma omp parallel for if(multithread) #endif - for (int i = 0; i < width * height; i++) { - (*U) (i) -= max; + for (int i = 0; i < width * height; i++) { + (*U)(i) -= maxVal; + } } } @@ -974,27 +989,27 @@ void solve_pde_fft (Array2Df *F, Array2Df *U, Array2Df *buf, bool multithread)/* * RT code from here on *****************************************************************************/ -inline void rescale_bilinear (const Array2Df &src, Array2Df &dst, bool multithread) +inline void rescale_bilinear(const Array2Df &src, Array2Df &dst, bool multithread) { rescaleBilinear(src, dst, multithread); } -inline void rescale_nearest (const Array2Df &src, Array2Df &dst, bool multithread) +inline void rescale_nearest(const Array2Df &src, Array2Df &dst, bool multithread) { rescaleNearest(src, dst, multithread); } -inline float luminance (float r, float g, float b, TMatrix ws) +inline float luminance(float r, float g, float b, TMatrix ws) { return Color::rgbLuminance(r, g, b, ws); } -inline int round_up_pow2 (int dim) +inline int round_up_pow2(int dim) { // from https://graphics.stanford.edu/~seander/bithacks.html - assert (dim > 0); + assert(dim > 0); unsigned int v = dim; v--; v |= v >> 1; @@ -1006,7 +1021,7 @@ inline int round_up_pow2 (int dim) return v; } -inline int find_fast_dim (int dim) +inline int find_fast_dim(int dim) { // as per the FFTW docs: // @@ -1018,7 +1033,7 @@ inline int find_fast_dim (int dim) // the above form. This is not exhaustive, but should be ok for pictures // up to 100MPix at least - int d1 = round_up_pow2 (dim); + int d1 = round_up_pow2(dim); std::vector d = { d1 / 128 * 65, d1 / 64 * 33, @@ -1040,72 +1055,93 @@ inline int find_fast_dim (int dim) } } - assert (false); + assert(false); return dim; } + + } // namespace -void ImProcFunctions::ToneMapFattal02 (Imagefloat *rgb) +void ImProcFunctions::ToneMapFattal02(Imagefloat *rgb, const FattalToneMappingParams &fatParams, int detail_level, int Lalone, float **Lum, int WW, int HH, int algo) +//algo allows to use ART algorithme algo = 0 RT, algo = 1 ART +//Lalone allows to use L without RGB values in RT mode { - if (!params->fattal.enabled) { + if (!fatParams.enabled) { return; } - + BENCHFUN - const int detail_level = 3; +// const int detail_level = 3; float alpha = 1.f; - if (params->fattal.threshold < 0) { - alpha += (params->fattal.threshold * 0.9f) / 100.f; - } else if (params->fattal.threshold > 0) { - alpha += params->fattal.threshold / 100.f; + if (fatParams.threshold < 0) { + alpha += (fatParams.threshold * 0.9f) / 100.f; + } else if (fatParams.threshold > 0) { + alpha += fatParams.threshold / 100.f; } - float beta = 1.f - (params->fattal.amount * 0.3f) / 100.f; + float beta = 1.f - (fatParams.amount * 0.3f) / 100.f; // sanity check if (alpha <= 0 || beta <= 0) { return; } - int w = rgb->getWidth(); - int h = rgb->getHeight(); + int w; + int h; - Array2Df Yr (w, h); + if (Lalone != 0) { + w = WW; + h = HH; + } else { + w = rgb->getWidth(); + h = rgb->getHeight(); + } + + Array2Df Yr(w, h); constexpr float epsilon = 1e-4f; constexpr float luminance_noise_floor = 65.535f; constexpr float min_luminance = 1.f; - TMatrix ws = ICCStore::getInstance()->workingSpaceMatrix (params->icm.workingProfile); - + TMatrix ws = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile); #ifdef _OPENMP #pragma omp parallel for if(multiThread) #endif + for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { - Yr (x, y) = std::max (luminance (rgb->r (y, x), rgb->g (y, x), rgb->b (y, x), ws), min_luminance); // clip really black pixels + if (Lalone != 0) { + Yr(x, y) = std::max(2.f * Lum[y][x], min_luminance); // clip really black pixels + } else { + Yr(x, y) = std::max(luminance(rgb->r(y, x), rgb->g(y, x), rgb->b(y, x), ws), min_luminance); // clip really black pixels + } } } float oldMedian; - const float percentile = float(LIM(params->fattal.anchor, 1, 100)) / 100.f; - findMinMaxPercentile (Yr.data(), Yr.getRows() * Yr.getCols(), percentile, oldMedian, percentile, oldMedian, multiThread); + float percentile = 1.f; + + if (algo == 0) { + percentile = float(LIM(fatParams.anchor, 1, 100)) / 100.f; + findMinMaxPercentile(Yr.data(), static_cast(Yr.getRows()) * Yr.getCols(), percentile, oldMedian, percentile, oldMedian, multiThread); + } + // median filter on the deep shadows, to avoid boosting noise // because w2 >= w and h2 >= h, we can use the L buffer as temporary buffer for Median_Denoise() - int w2 = find_fast_dim (w) + 1; - int h2 = find_fast_dim (h) + 1; - Array2Df L (w2, h2); + int w2 = find_fast_dim(w) + 1; + int h2 = find_fast_dim(h) + 1; + Array2Df L(w2, h2); { #ifdef _OPENMP int num_threads = multiThread ? omp_get_max_threads() : 1; #else int num_threads = 1; #endif - float r = float (std::max (w, h)) / float (RT_dimension_cap); + float r = float (std::max(w, h)) / float (RT_dimension_cap); Median med; if (r >= 3) { @@ -1118,7 +1154,7 @@ void ImProcFunctions::ToneMapFattal02 (Imagefloat *rgb) med = Median::TYPE_3X3_STRONG; } - Median_Denoise (Yr, Yr, luminance_noise_floor, w, h, med, 1, num_threads, L); + Median_Denoise(Yr, Yr, luminance_noise_floor, w, h, med, 1, num_threads, L); } float noise = alpha * 0.01f; @@ -1128,19 +1164,72 @@ void ImProcFunctions::ToneMapFattal02 (Imagefloat *rgb) << ", detail_level = " << detail_level << std::endl; } - rescale_nearest (Yr, L, multiThread); - tmo_fattal02 (w2, h2, L, L, alpha, beta, noise, detail_level, multiThread); + rescale_nearest(Yr, L, multiThread); + + tmo_fattal02(w2, h2, L, L, alpha, beta, noise, detail_level, multiThread, 0); const float hr = float(h2) / float(h); const float wr = float(w2) / float(w); - float newMedian; - findMinMaxPercentile (L.data(), L.getRows() * L.getCols(), percentile, newMedian, percentile, newMedian, multiThread); - const float scale = (oldMedian == 0.f || newMedian == 0.f) ? 65535.f : (oldMedian / newMedian); // avoid Nan + float offset = 0.f; + float scale = 65535.f; + + if (algo == 0) { + float newMedian; + findMinMaxPercentile(L.data(), static_cast(L.getRows()) * L.getCols(), percentile, newMedian, percentile, newMedian, multiThread); + scale = (oldMedian == 0.f || newMedian == 0.f) ? 65535.f : (oldMedian / newMedian); // avoid Nan + } else { + + scale = 65535.f; + { + float ratio = 0.f; + int ww, hh; + + if (w >= h) { + ratio = 200.f / w; + ww = 200; + hh = ratio * h; + } else { + ratio = 200.f / h; + hh = 200; + ww = ratio * w; + } + + Array2Df tmp(ww, hh); + int sz = ww * hh; + int idx = sz / 2; + int oidx = LIM(int(sz * 0.05f + 0.5f), 1, sz - 1); + rescale_nearest(Yr, tmp, multiThread); + std::sort(tmp.data(), tmp.data() + sz); + float oldMedian = tmp(idx); + float old_min = 0.f; + + for (int i = 0; i <= oidx; ++i) { + old_min += tmp(i); + } + + old_min /= oidx; + rescale_nearest(L, tmp, multiThread); + std::sort(tmp.data(), tmp.data() + sz); + float newMedian = tmp(idx); + scale = (oldMedian == 0.f || newMedian == 0.f) ? 65535.f : (oldMedian / newMedian); // avoid Nan + float new_min = 0.f; + + for (int i = 0; i <= oidx; ++i) { + new_min += tmp(i); + } + + new_min /= oidx; + offset = old_min - new_min; + } + + + } #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) if(multiThread) #endif + for (int y = 0; y < h; y++) { int yy = y * hr + 1; @@ -1149,16 +1238,106 @@ void ImProcFunctions::ToneMapFattal02 (Imagefloat *rgb) float Y = std::max(Yr(x, y), epsilon); float l = std::max(L(xx, yy), epsilon) * (scale / Y); - rgb->r(y, x) *= l; - rgb->g(y, x) *= l; - rgb->b(y, x) *= l; - assert(std::isfinite(rgb->r(y, x))); - assert(std::isfinite(rgb->g(y, x))); - assert(std::isfinite(rgb->b(y, x))); + if (Lalone == 0) { + float &r = rgb->r(y, x); + float &g = rgb->g(y, x); + float &b = rgb->b(y, x); + if(l > 1.f) { + r = max(r * l - offset, r); + g = max(g * l - offset, g); + b = max(b * l - offset, b); + } else { + r *= l; + g *= l; + b *= l; + } + assert(std::isfinite(rgb->r(y, x))); + assert(std::isfinite(rgb->g(y, x))); + assert(std::isfinite(rgb->b(y, x))); + } else { + if (Lalone == 1) { + Lum[y][x] *= (0.5f * l - offset); + } else if (Lalone == -1) { + Lum[y][x] *= (-0.5f * l + offset); + } + } } } + } +void buildGradientsMask(int W, int H, float **luminance, float **out, + float amount, int nlevels, int detail_level, + float alfa, float beta, bool multithread) +{ + Array2Df Y(W, H, luminance); + const float noise = alfa * 0.01f; + + Array2Df *pyramids[nlevels]; + pyramids[0] = &Y; + createGaussianPyramids(pyramids, nlevels, multithread); + + // calculate gradients and its average values on pyramid levels + Array2Df *gradients[nlevels]; + float avgGrad[nlevels]; + + for (int k = 0 ; k < nlevels ; k++) { + gradients[k] = new Array2Df(pyramids[k]->getCols(), pyramids[k]->getRows()); + avgGrad[k] = calculateGradients(pyramids[k], gradients[k], k, multithread); + + if (k != 0) { // pyramids[0] is Y + delete pyramids[k]; + } + } + + + // calculate fi matrix + Array2Df FI(W, H, out); + calculateFiMatrix(&FI, gradients, avgGrad, nlevels, detail_level, alfa, beta, noise, multithread); + + for (int i = 0 ; i < nlevels ; i++) { + delete gradients[i]; + } + + // rescale the mask + float m = out[0][0]; +#ifdef _OPENMP + # pragma omp parallel for reduction(max:m) if (multithread) +#endif + + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + float v = std::abs(out[y][x]); + out[y][x] = v; + m = std::max(v, m); + } + } + + if (m > 0.f) { + const float f = amount / m; +#ifdef _OPENMP + # pragma omp parallel for reduction(max:m) if (multithread) +#endif + + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + out[y][x] *= f; + } + } + } + + // { + // Imagefloat tmp(W, H); + // for (int y = 0; y < H; ++y) { + // for (int x = 0; x < W; ++x) { + // tmp.r(y, x) = tmp.g(y, x) = tmp.b(y, x) = out[y][x] * 65535.f; + // } + // } + // std::ostringstream name; + // name << "/tmp/FI-" << W << "x" << H << ".tif"; + // tmp.saveAsTIFF(name.str(), 16); + // } +} } // namespace rtengine diff --git a/rtengine/utils.cc b/rtengine/utils.cc index 613b67be8..0674c9806 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 @@ -22,7 +22,6 @@ #include "rt_math.h" #include "utils.h" -#include "rt_math.h" using namespace std; 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..ef456af3a 100644 --- a/rtengine/vng4_demosaic_RT.cc +++ b/rtengine/vng4_demosaic_RT.cc @@ -16,13 +16,13 @@ // 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 "rtengine.h" +#include "rawimage.h" #include "rawimagesource.h" -#include "procparams.h" #include "../rtgui/multilangmgr.h" //#define BENCHMARK #include "StopWatch.h" @@ -45,12 +45,12 @@ inline void vng4interpolate_row_redblue (const RawImage *ri, const array2D &rawData, array2D(height) * width, sizeof * image); int lcode[16][16][32]; float mul[16][16][8]; @@ -354,7 +354,7 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D firstRow) { vng4interpolate_row_redblue(ri, rawData, red[row - 1], blue[row - 1], green[row - 2], green[row - 1], green[row], row - 1, W); @@ -384,7 +384,7 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D. +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// +#include "color.h" #include "rtengine.h" +#include "rawimage.h" #include "rawimagesource.h" #include "rt_algo.h" #include "rt_math.h" @@ -39,9 +41,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 +293,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 +521,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 +565,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 +630,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 +657,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 +702,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); @@ -941,9 +939,9 @@ void RawImageSource::xtrans_interpolate (const int passes, const bool useCieLab, avg[3]++; } - red[row + top][col + left] = avg[0] / avg[3]; - green[row + top][col + left] = avg[1] / avg[3]; - blue[row + top][col + left] = avg[2] / avg[3]; + red[row + top][col + left] = std::max(0.f, avg[0] / avg[3]); + green[row + top][col + left] = std::max(0.f, avg[1] / avg[3]); + blue[row + top][col + left] = std::max(0.f, avg[2] / avg[3]); } if(plistenerActive && ((++progressCounter) % 32 == 0)) { @@ -963,7 +961,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/rtexif/CMakeLists.txt b/rtexif/CMakeLists.txt index 9747b03fb..5a3831455 100644 --- a/rtexif/CMakeLists.txt +++ b/rtexif/CMakeLists.txt @@ -1,4 +1,16 @@ -add_library(rtexif rtexif.cc stdattribs.cc nikonattribs.cc canonattribs.cc pentaxattribs.cc fujiattribs.cc sonyminoltaattribs.cc olympusattribs.cc kodakattribs.cc panasonicattribs.cc) +add_library(rtexif STATIC + canonattribs.cc + fujiattribs.cc + kodakattribs.cc + nikonattribs.cc + olympusattribs.cc + panasonicattribs.cc + pentaxattribs.cc + rtexif.cc + sonyminoltaattribs.cc + stdattribs.cc +) + add_dependencies(rtexif UpdateInfo) if(WIN32) diff --git a/rtexif/canonattribs.cc b/rtexif/canonattribs.cc index 2dcbdd96f..c434634dc 100644 --- a/rtexif/canonattribs.cc +++ b/rtexif/canonattribs.cc @@ -14,10 +14,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 . */ -#ifndef _CANONATTRIBS_ -#define _CANONATTRIBS_ #include #include @@ -557,7 +555,8 @@ public: { choices = { {1, "Canon EF 50mm f/1.8"}, - {2, "Canon EF 28mm f/2.8"}, + {2, "Canon EF 28mm f/2.8 or Sigma Lens"}, + {2, "Sigma 24mm f/2.8 Super Wide II"}, {3, "Canon EF 135mm f/2.8 Soft"}, {4, "Canon EF 35-105mm f/3.5-4.5 or Sigma Lens"}, {4, "Sigma UC Zoom 35-135mm f/4-5.6"}, @@ -598,6 +597,8 @@ public: {26, "Tamron SP AF 90mm f/2.8 Di Macro"}, {26, "Tamron SP AF 180mm f/3.5 Di Macro"}, {26, "Carl Zeiss Planar T* 50mm f/1.4"}, + {26, "Voigtlander APO Lanthar 125mm F2.5 SL Macro"}, + {26, "Carl Zeiss Planar T 85mm f/1.4 ZE"}, {27, "Canon EF 35-80mm f/4-5.6"}, {28, "Canon EF 80-200mm f/4.5-5.6 or Tamron Lens"}, {28, "Tamron SP AF 28-105mm f/2.8 LD Aspherical IF"}, @@ -629,7 +630,7 @@ public: {36, "Canon EF 38-76mm f/4.5-5.6"}, {37, "Canon EF 35-80mm f/4-5.6 or Tamron Lens"}, {37, "Tamron 70-200mm f/2.8 Di LD IF Macro"}, - {37, "Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical [IF] Macro Model A20"}, + {37, "Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical [IF] Macro (A20)"}, {37, "Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical [IF]"}, {37, "Tamron AF 18-270mm f/3.5-6.3 Di II VC LD Aspherical [IF] Macro"}, {38, "Canon EF 80-200mm f/4.5-5.6"}, @@ -637,13 +638,14 @@ public: {40, "Canon EF 28-80mm f/3.5-5.6"}, {41, "Canon EF 28-90mm f/4-5.6"}, {42, "Canon EF 28-200mm f/3.5-5.6 or Tamron Lens"}, - {42, "Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical [IF] Macro Model A20"}, + {42, "Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical [IF] Macro (A20)"}, {43, "Canon EF 28-105mm f/4-5.6"}, {44, "Canon EF 90-300mm f/4.5-5.6"}, {45, "Canon EF-S 18-55mm f/3.5-5.6 [II]"}, {46, "Canon EF 28-90mm f/4-5.6"}, {47, "Zeiss Milvus 35mm f/2 or 50mm f/2"}, {47, "Zeiss Milvus 50mm f/2 Makro"}, + {47, "Zeiss Milvus 135mm f/2 ZE"}, {48, "Canon EF-S 18-55mm f/3.5-5.6 IS"}, {49, "Canon EF-S 55-250mm f/4-5.6 IS"}, {50, "Canon EF-S 18-200mm f/3.5-5.6 IS"}, @@ -660,10 +662,17 @@ public: {103, "Samyang AF 14mm f/2.8 EF or Rokinon Lens"}, {103, "Rokinon SP 14mm f/2.4"}, {103, "Rokinon AF 14mm f/2.8 EF"}, + {106, "Rokinon SP / Samyang XP 35mm f/1.2"}, + {112, "Sigma 28mm f/1.5 FF High-speed Prime or other Sigma Lens"}, + {112, "Sigma 40mm f/1.5 FF High-speed Prime"}, + {112, "Sigma 105mm f/1.5 FF High-speed Prime"}, + {117, "Tamron 35-150mm f/2.8-4.0 Di VC OSD (A043) or other Tamron Lens"}, + {117, "Tamron SP 35mm f/1.4 Di USD (F045)"}, {124, "Canon MP-E 65mm f/2.8 1-5x Macro Photo"}, {125, "Canon TS-E 24mm f/3.5L"}, {126, "Canon TS-E 45mm f/2.8"}, - {127, "Canon TS-E 90mm f/2.8"}, + {127, "Canon TS-E 90mm f/2.8 or Tamron Lens"}, + {127, "Tamron 18-200mm f/3.5-6.3 Di II VC (B018)"}, {129, "Canon EF 300mm f/2.8L USM"}, {130, "Canon EF 50mm f/1.0L USM"}, {131, "Canon EF 28-80mm f/2.8-4L USM or Sigma Lens"}, @@ -674,10 +683,12 @@ public: {131, "Sigma APO 120-300mm f/2.8 EX DG HSM"}, {131, "Sigma 4.5mm f/2.8 EX DC HSM Circular Fisheye"}, {131, "Sigma 70-200mm f/2.8 APO EX HSM"}, + {131, "Sigma 28-70mm f/2.8-4 DG"}, {132, "Canon EF 1200mm f/5.6L USM"}, {134, "Canon EF 600mm f/4L IS USM"}, {135, "Canon EF 200mm f/1.8L USM"}, {136, "Canon EF 300mm f/2.8L USM"}, + {136, "Tamron SP 15-30mm f/2.8 Di VC USD (A012)"}, {137, "Canon EF 85mm f/1.2L USM or Sigma or Tamron Lens"}, {137, "Sigma 18-50mm f/2.8-4.5 DC OS HSM"}, {137, "Sigma 50-200mm f/4-5.6 DC OS HSM"}, @@ -687,14 +698,15 @@ public: {137, "Sigma 17-70mm f/2.8-4 DC Macro OS HSM | C"}, {137, "Sigma 17-50mm f/2.8 OS HSM"}, {137, "Sigma 18-200mm f/3.5-6.3 DC OS HSM [II]"}, - {137, "Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD"}, + {137, "Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD (B008)"}, {137, "Sigma 8-16mm f/4.5-5.6 DC HSM"}, - {137, "Tamron SP 17-50mm f/2.8 XR Di II VC"}, - {137, "Tamron SP 60mm f/2 Macro Di II"}, + {137, "Tamron SP 17-50mm f/2.8 XR Di II VC (B005)"}, + {137, "Tamron SP 60mm f/2 Macro Di II (G005)"}, {137, "Sigma 10-20mm f/3.5 EX DC HSM"}, {137, "Tamron SP 24-70mm f/2.8 Di VC USD"}, {137, "Sigma 18-35mm f/1.8 DC HSM"}, {137, "Sigma 12-24mm f/4.5-5.6 DG HSM II"}, + {137, "Sigma 70-300mm f/4-5.6 DG OS"}, {138, "Canon EF 28-80mm f/2.8-4L"}, {139, "Canon EF 400mm f/2.8L USM"}, {140, "Canon EF 500mm f/4.5L USM"}, @@ -713,23 +725,28 @@ public: {150, "Sigma 30mm f/1.4 DC HSM"}, {150, "Sigma 24mm f/1.8 DG Macro EX"}, {150, "Sigma 28mm f/1.8 DG Macro EX"}, + {150, "Sigma 18-35mm f/1.8 DC HSM | A"}, {151, "Canon EF 200mm f/2.8L USM"}, {152, "Canon EF 300mm f/4L IS USM or Sigma Lens"}, {152, "Sigma 12-24mm f/4.5-5.6 EX DG ASPHERICAL HSM"}, {152, "Sigma 14mm f/2.8 EX Aspherical HSM"}, {152, "Sigma 10-20mm f/4-5.6"}, {152, "Sigma 100-300mm f/4"}, + {152, "Sigma 300-800mm f/5.6 APO EX DG HSM"}, {153, "Canon EF 35-350mm f/3.5-5.6L USM or Sigma or Tamron Lens"}, {153, "Sigma 50-500mm f/4-6.3 APO HSM EX"}, {153, "Tamron AF 28-300mm f/3.5-6.3 XR LD Aspherical [IF] Macro"}, - {153, "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical [IF] Macro Model A14"}, + {153, "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical [IF] Macro (A14)"}, {153, "Tamron 18-250mm f/3.5-6.3 Di II LD Aspherical [IF] Macro"}, {154, "Canon EF 20mm f/2.8 USM or Zeiss Lens"}, {154, "Zeiss Milvus 21mm f/2.8"}, - {155, "Canon EF 85mm f/1.8 USM"}, + {154, "Zeiss Milvus 15mm f/2.8 ZE"}, + {154, "Zeiss Milvus 18mm f/2.8 ZE"}, + {155, "Canon EF 85mm f/1.8 USM or Sigma Lens"}, + {155, "Sigma 14mm f/1.8 DG HSM | A"}, {156, "Canon EF 28-105mm f/3.5-4.5 USM or Tamron Lens"}, - {156, "Tamron SP 70-300mm f/4-5.6 Di VC USD"}, - {156, "Tamron SP AF 28-105mm f/2.8 LD Aspherical IF"}, + {156, "Tamron SP 70-300mm f/4-5.6 Di VC USD (A005)"}, + {156, "Tamron SP AF 28-105mm f/2.8 LD Aspherical IF (176D)"}, {160, "Canon EF 20-35mm f/3.5-4.5 USM or Tamron or Tokina Lens"}, {160, "Tamron AF 19-35mm f/3.5-4.5"}, {160, "Tokina AT-X 124 AF Pro DX 12-24mm f/4"}, @@ -742,7 +759,7 @@ public: {161, "Sigma 24-60mm f/2.8 EX DG"}, {161, "Tamron AF 17-50mm f/2.8 Di-II LD Aspherical"}, {161, "Tamron 90mm f/2.8"}, - {161, "Tamron SP AF 17-35mm f/2.8-4 Di LD Aspherical IF"}, + {161, "Tamron SP AF 17-35mm f/2.8-4 Di LD Aspherical IF (A05)"}, {161, "Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical [IF] Macro"}, {161, "Tokina AT-X 24-70mm f/2.8 PRO FX (IF)"}, {162, "Canon EF 200mm f/2.8L USM"}, @@ -762,18 +779,30 @@ public: {169, "Sigma 30mm f/1.4 EX DC HSM"}, {169, "Sigma 35mm f/1.4 DG HSM"}, {169, "Sigma 35mm f/1.5 FF High-Speed Prime | 017"}, - {170, "Canon EF 200mm f/2.8L II USM"}, + {169, "Sigma 70mm f/2.8 Macro EX DG"}, + {170, "Canon EF 200mm f/2.8L II USM or Sigma Lens"}, + {170, "Sigma 300mm f/2.8 APO EX DG HSM"}, + {170, "Sigma 800mm f/5.6 APO EX DG HSM"}, {171, "Canon EF 300mm f/4L USM"}, {172, "Canon EF 400mm f/5.6L USM or Sigma Lens"}, {172, "Sigma 150-600mm f/5-6.3 DG OS HSM | S"}, + {172, "Sigma 500mm f/4.5 APO EX DG HSM"}, {173, "Canon EF 180mm Macro f/3.5L USM or Sigma Lens"}, {173, "Sigma 180mm EX HSM Macro f/3.5"}, {173, "Sigma APO Macro 150mm f/2.8 EX DG HSM"}, + {173, "Sigma 10mm f/2.8 EX DC Fisheye"}, + {173, "Sigma 15mm f/2.8 EX DG Diagonal Fisheye"}, + {173, "Venus Laowa 100mm F2.8 2X Ultra Macro APO"}, {174, "Canon EF 135mm f/2L USM or Other Lens"}, {174, "Sigma 70-200mm f/2.8 EX DG APO OS HSM"}, {174, "Sigma 50-500mm f/4.5-6.3 APO DG OS HSM"}, {174, "Sigma 150-500mm f/5-6.3 APO DG OS HSM"}, {174, "Zeiss Milvus 100mm f/2 Makro"}, + {174, "Sigma APO 50-150mm f/2.8 EX DC OS HSM"}, + {174, "Sigma APO 120-300mm f/2.8 EX DG OS HSM"}, + {174, "Sigma 120-300mm f/2.8 DG OS HSM S013"}, + {174, "Sigma 120-400mm f/4.5-5.6 APO DG OS HSM"}, + {174, "Sigma 200-500mm f/2.8 APO EX DG"}, {175, "Canon EF 400mm f/2.8L USM"}, {176, "Canon EF 24-85mm f/3.5-4.5 USM"}, {177, "Canon EF 300mm f/4L IS USM"}, @@ -788,6 +817,8 @@ public: {180, "Sigma 24mm f/1.5 FF High-Speed Prime | 017"}, {180, "Sigma 50mm f/1.5 FF High-Speed Prime | 017"}, {180, "Sigma 85mm f/1.5 FF High-Speed Prime | 017"}, + {180, "Tokina Opera 50mm f/1.4 FF"}, + {180, "Sigma 20mm f/1.4 DG HSM | A"}, {181, "Canon EF 100-400mm f/4.5-5.6L IS USM + 1.4x or Sigma Lens"}, {181, "Sigma 150-600mm f/5-6.3 DG OS HSM | S + 1.4x"}, {182, "Canon EF 100-400mm f/4.5-5.6L IS USM + 2x or Sigma Lens"}, @@ -815,10 +846,13 @@ public: {196, "Canon EF 75-300mm f/4-5.6 USM"}, {197, "Canon EF 75-300mm f/4-5.6 IS USM or Sigma Lens"}, {197, "Sigma 18-300mm f/3.5-6.3 DC Macro OS HS"}, - {198, "Canon EF 50mm f/1.4 USM or Zeiss Lens"}, + {198, "Canon EF 50mm f/1.4 USM or Other Lens"}, {198, "Zeiss Otus 55mm f/1.4 ZE"}, {198, "Zeiss Otus 85mm f/1.4 ZE"}, {198, "Zeiss Milvus 25mm f/1.4"}, + {198, "Zeiss Otus 100mm f/1.4"}, + {198, "Zeiss Milvus 35mm f/1.4 ZE"}, + {198, "Yongnuo YN 35mm f/2"}, {199, "Canon EF 28-80mm f/3.5-5.6 USM"}, {200, "Canon EF 75-300mm f/4-5.6 USM"}, {201, "Canon EF 28-80mm f/3.5-5.6 USM"}, @@ -829,13 +863,14 @@ public: {211, "Canon EF 28-200mm f/3.5-5.6 USM"}, {212, "Canon EF 28-105mm f/4-5.6 USM"}, {213, "Canon EF 90-300mm f/4.5-5.6 USM or Tamron Lens"}, - {213, "Tamron SP 150-600mm f/5-6.3 Di VC USD"}, - {213, "Tamron 16-300mm f/3.5-6.3 Di II VC PZD Macro"}, - {213, "Tamron SP 35mm f/1.8 Di VC USD"}, - {213, "Tamron SP 45mm f/1.8 Di VC USD"}, + {213, "Tamron SP 150-600mm f/5-6.3 Di VC USD (A011)"}, + {213, "Tamron 16-300mm f/3.5-6.3 Di II VC PZD Macro (B016)"}, + {213, "Tamron SP 35mm f/1.8 Di VC USD (F012)"}, + {213, "Tamron SP 45mm f/1.8 Di VC USD (F013)"}, {214, "Canon EF-S 18-55mm f/3.5-5.6 USM"}, {215, "Canon EF 55-200mm f/4.5-5.6 II USM"}, {217, "Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD"}, + {220, "Yongnuo YN 50mm f/1.8"}, {224, "Canon EF 70-200mm f/2.8L IS USM"}, {225, "Canon EF 70-200mm f/2.8L IS USM + 1.4x"}, {226, "Canon EF 70-200mm f/2.8L IS USM + 2x"}, @@ -843,7 +878,8 @@ public: {228, "Canon EF 28-105mm f/3.5-4.5 USM"}, {229, "Canon EF 16-35mm f/2.8L USM"}, {230, "Canon EF 24-70mm f/2.8L USM"}, - {231, "Canon EF 17-40mm f/4L USM"}, + {231, "Canon EF 17-40mm f/4L USM or Sigma Lens"}, + {231, "Sigma 12-24mm f/4 DG HSM A016"}, {232, "Canon EF 70-300mm f/4.5-5.6 DO IS USM"}, {233, "Canon EF 28-300mm f/3.5-5.6L IS USM"}, {234, "Canon EF-S 17-85mm f/4-5.6 IS USM or Tokina Lens"}, @@ -867,13 +903,19 @@ public: {248, "Sigma 24-35mm f/2 DG HSM | A"}, {248, "Sigma 135mm f/2 FF High-Speed Prime | 017"}, {248, "Sigma 24-35mm f/2.2 FF Zoom | 017"}, + {248, "Sigma 135mm f/1.8 DG HSM A017"}, {249, "Canon EF 800mm f/5.6L IS USM"}, {250, "Canon EF 24mm f/1.4L II USM or Sigma Lens"}, {250, "Sigma 20mm f/1.4 DG HSM | A"}, {250, "Sigma 20mm f/1.5 FF High-Speed Prime | 017"}, + {250, "Tokina Opera 16-28mm f/2.8 FF"}, + {250, "Sigma 85mm f/1.4 DG HSM A016"}, {251, "Canon EF 70-200mm f/2.8L IS II USM"}, + {251, "Canon EF 70-200mm f/2.8L IS III USM"}, {252, "Canon EF 70-200mm f/2.8L IS II USM + 1.4x"}, + {252, "Canon EF 70-200mm f/2.8L IS III USM + 1.4x"}, {253, "Canon EF 70-200mm f/2.8L IS II USM + 2x"}, + {253, "Canon EF 70-200mm f/2.8L IS III USM + 2x"}, {254, "Canon EF 100mm f/2.8L Macro IS USM"}, {255, "Sigma 24-105mm f/4 DG OS HSM | A or Other Sigma Lens"}, {255, "Sigma 180mm f/2.8 EX DG OS HSM APO Macro"}, @@ -882,6 +924,12 @@ public: {368, "Sigma 50mm f/1.4 DG HSM | A"}, {368, "Sigma 40mm f/1.4 DG HSM | A"}, {368, "Sigma 60-600mm f/4.5-6.3 DG OS HSM | S"}, + {368, "Sigma 28mm f/1.4 DG HSM | A"}, + {368, "Sigma 150-600mm f/5-6.3 DG OS HSM | S"}, + {368, "Sigma 85mm f/1.4 DG HSM | A"}, + {368, "Sigma 105mm f/1.4 DG HSM"}, + {368, "Sigma 14-24mm f/2.8 DG HSM"}, + {368, "Sigma 70mm f/2.8 DG Macro"}, {488, "Canon EF-S 15-85mm f/3.5-5.6 IS USM"}, {489, "Canon EF 70-300mm f/4-5.6L IS USM"}, {490, "Canon EF 8-15mm f/4L Fisheye USM"}, @@ -897,7 +945,7 @@ public: {493, "Canon EF 24-105mm f/4L IS USM"}, {494, "Canon EF 600mm f/4L IS II USM"}, {495, "Canon EF 24-70mm f/2.8L II USM or Sigma Lens"}, - {495, "Sigma 24-70mm F2.8 DG OS HSM | A"}, + {495, "Sigma 24-70mm f/2.8 DG OS HSM | A"}, {496, "Canon EF 200-400mm f/4L IS USM"}, {499, "Canon EF 200-400mm f/4L IS USM + 1.4x"}, {502, "Canon EF 28mm f/2.8 IS USM or Tamron Lens"}, @@ -908,14 +956,16 @@ public: {506, "Canon EF 400mm f/4 DO IS II USM"}, {507, "Canon EF 16-35mm f/4L IS USM"}, {508, "Canon EF 11-24mm f/4L USM or Tamron Lens"}, - {508, "Tamron 10-24mm f/3.5-4.5 Di II VC HLD"}, + {508, "Tamron 10-24mm f/3.5-4.5 Di II VC HLD (B023)"}, + {624, "Sigma 70-200mm f/2.8 DG OS HSM | S"}, {747, "Canon EF 100-400mm f/4.5-5.6L IS II USM or Tamron Lens"}, {747, "Tamron SP 150-600mm f/5-6.3 Di VC USD G2"}, {748, "Canon EF 100-400mm f/4.5-5.6L IS II USM + 1.4x or Tamron Lens"}, {748, "Tamron 100-400mm f/4.5-6.3 Di VC USD A035E + 1.4x"}, {748, "Tamron 70-210mm f/4 Di VC USD (A034) + 2x"}, {749, "Tamron 100-400mm f/4.5-6.3 Di VC USD A035E + 2x"}, - {750, "Canon EF 35mm f/1.4L II USM"}, + {750, "Canon EF 35mm f/1.4L II USM or Tamron Lens"}, + {750, "Tamron SP 85mm f/1.8 Di VC USD (F016)"}, {751, "Canon EF 16-35mm f/2.8L III USM"}, {752, "Canon EF 24-105mm f/4L IS II USM"}, {753, "Canon EF 85mm f/1.4L IS USM"}, @@ -938,16 +988,21 @@ public: {4154, "Canon EF-S 24mm f/2.8 STM"}, {4155, "Canon EF-M 28mm f/3.5 Macro IS STM"}, {4156, "Canon EF 50mm f/1.8 STM"}, - {4157, "Canon EF-M 18-150mm 1:3.5-6.3 IS STM"}, + {4157, "Canon EF-M 18-150mm f/3.5-6.3 IS STM"}, {4158, "Canon EF-S 18-55mm f/4-5.6 IS STM"}, {4159, "Canon EF-M 32mm f/1.4 STM"}, {4160, "Canon EF-S 35mm f/2.8 Macro IS STM"}, + {4208, "Sigma 56mm f/1.4 DC DN | C"}, {36910, "Canon EF 70-300mm f/4-5.6 IS II USM"}, {36912, "Canon EF-S 18-135mm f/3.5-5.6 IS USM"}, {61182, "Canon RF 35mm F1.8 Macro IS STM or other Canon RF Lens"}, {61182, "Canon RF 50mm F1.2 L USM"}, {61182, "Canon RF 24-105mm F4 L IS USM"}, {61182, "Canon RF 28-70mm F2 L USM"}, + {61182, "Canon RF 85mm F1.2L USM"}, + {61182, "Canon RF 24-240mm F4-6.3 IS USM"}, + {61182, "Canon RF 24-70mm F2.8 L IS USM"}, + {61182, "Canon RF 15-35mm F2.8 L IS USM"}, {61491, "Canon CN-E 14mm T3.1 L F"}, {61492, "Canon CN-E 24mm T1.5 L F"}, {61494, "Canon CN-E 85mm T1.3 L F"}, @@ -1514,7 +1569,11 @@ public: { choices[1042] = "EOS M50 / Kiss M"; choices[2049] = "PowerShot SX740 HS"; + choices[2052] = "PowerShot G5 X Mark II"; choices[2053] = "PowerShot SX70 HS"; + choices[2056] = "PowerShot G7 X Mark III"; + choices[2065] = "EOS M6 Mark II"; + choices[2066] = "EOS M200"; choices[16842752] = "PowerShot A30"; choices[17039360] = "PowerShot S300 / Digital IXUS 300 / IXY Digital 300"; choices[17170432] = "PowerShot A20"; @@ -1679,6 +1738,7 @@ public: choices[52822016] = "PowerShot A3400 IS"; choices[52887552] = "PowerShot A2400 IS"; choices[52953088] = "PowerShot A2300"; + choices[53608448] = "PowerShot S100V"; choices[53673984] = "PowerShot G15"; choices[53739520] = "PowerShot SX50 HS"; choices[53805056] = "PowerShot SX160 IS"; @@ -1737,7 +1797,7 @@ public: choices[67239936] = "PowerShot SX420 IS"; choices[67305472] = "PowerShot ELPH 190 IS / IXUS 180 / IXY 190"; choices[67371008] = "PowerShot G1"; - choices[67371009] = "IXY 180"; + choices[67371009] = "PowerShot ELPH 180 IS / IXUS 175 / IXY 180"; choices[67436544] = "PowerShot SX720 HS"; choices[67502080] = "PowerShot SX620 HS"; choices[67567616] = "EOS M6"; @@ -1821,7 +1881,7 @@ public: choices[2147484453] = "EOS 70D"; choices[2147484454] = "EOS Rebel T5i / 700D / Kiss X7i"; choices[2147484455] = "EOS Rebel T5 / 1200D / Kiss X70 / Hi"; - choices[2147484456] = "EOS-1D X MARK II"; + choices[2147484456] = "EOS-1D X Mark II"; choices[2147484465] = "EOS M"; choices[2147484486] = "EOS Rebel SL1 / 100D / Kiss X7"; choices[2147484487] = "EOS Rebel T6s / 760D / 8000D"; @@ -1837,8 +1897,14 @@ public: choices[2147484680] = "EOS 77D / 9000D"; choices[2147484695] = "EOS Rebel SL2 / 200D / Kiss X9"; choices[2147484706] = "EOS Rebel T100 / 4000D / 3000D"; - choices[2147484708] = "EOR R"; + choices[2147484708] = "EOS R"; + choices[2147484712] = "EOS-1D X Mark III"; choices[2147484722] = "EOS Rebel T7 / 2000D / 1500D / Kiss X90"; + choices[2147484723] = "EOS RP"; + choices[2147484726] = "EOS SL3 / 250D / Kiss X10"; + choices[2147484727] = "EOS 90D"; + choices[2147484960] = "EOS D2000C"; + choices[2147485024] = "EOS D6000C"; } }; CAModelIDInterpreter caModelIDInterpreter; @@ -2074,5 +2140,4 @@ const TagAttrib canonAttribs[] = { { -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr} }; } -#endif diff --git a/rtexif/fujiattribs.cc b/rtexif/fujiattribs.cc index 2e17a68f9..ffbf3a0be 100644 --- a/rtexif/fujiattribs.cc +++ b/rtexif/fujiattribs.cc @@ -14,10 +14,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 . */ -#ifndef _FUJIATTRIBS_ -#define _FUJIATTRIBS_ #include "rtexif.h" @@ -312,5 +310,4 @@ const TagAttrib fujiAttribs[] = { { -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr} }; } -#endif diff --git a/rtexif/kodakattribs.cc b/rtexif/kodakattribs.cc index a9c168a70..619925760 100644 --- a/rtexif/kodakattribs.cc +++ b/rtexif/kodakattribs.cc @@ -1,8 +1,6 @@ /* * This file is part of RawTherapee. */ -#ifndef _KODAKATTRIBS_ -#define _KODAKATTRIBS_ #include #include "rtexif.h" @@ -161,5 +159,4 @@ const TagAttrib kodakIfdAttribs[] = { }; } -#endif diff --git a/rtexif/nikonattribs.cc b/rtexif/nikonattribs.cc index 1c6ead006..9c52f3b8a 100644 --- a/rtexif/nikonattribs.cc +++ b/rtexif/nikonattribs.cc @@ -14,10 +14,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 . */ -#ifndef _NIKONATTRIBS_ -#define _NIKONATTRIBS_ #include #include @@ -380,7 +378,7 @@ public: } } - std::string EffectiveMaxApertureString = ""; + std::string EffectiveMaxApertureString; if (!d100) { int EffectiveMaxApertureValue; @@ -627,6 +625,7 @@ const std::map NALensDataInterpreter::lenses = { {"02 48 65 65 24 24 02 00", "Sigma Macro 90mm f/2.8"}, {"03 43 5C 81 35 35 02 00", "Soligor AF C/D Zoom UMCS 70-210mm 1:4.5"}, {"03 48 5C 81 30 30 02 00", "AF Zoom-Nikkor 70-210mm f/4"}, + {"03 54 68 68 0C 0C 00 00", "Zeiss Otus 1.4/100"}, {"04 48 3C 3C 24 24 03 00", "AF Nikkor 28mm f/2.8"}, {"05 54 50 50 0C 0C 04 00", "AF Nikkor 50mm f/1.4"}, {"06 3F 68 68 2C 2C 06 00", "Cosina AF 100mm f/3.5 Macro"}, @@ -906,12 +905,14 @@ const std::map NALensDataInterpreter::lenses = { {"7F 48 2B 5C 24 34 1C 06", "Sigma 17-70mm f/2.8-4.5 DC Macro Asp. IF"}, {"7F 48 2D 50 24 24 1C 06", "Sigma 18-50mm f/2.8 EX DC Macro"}, {"80 48 1A 1A 24 24 85 06", "AF DX Fisheye-Nikkor 10.5mm f/2.8G ED"}, + {"80 48 1C 29 24 24 7A 06", "Tokina atx-i 11-16mm f/2.8 CF"}, {"81 34 76 A6 38 40 4B 0E", "Sigma 150-600mm f/5-6.3 DG OS HSM | S"}, {"81 54 80 80 18 18 86 0E", "AF-S VR Nikkor 200mm f/2G IF-ED"}, {"82 34 76 A6 38 40 4B 0E", "Sigma 150-600mm f/5-6.3 DG OS HSM | C"}, {"82 48 8E 8E 24 24 87 0E", "AF-S VR Nikkor 300mm f/2.8G IF-ED"}, {"83 00 B0 B0 5A 5A 88 04", "FSA-L2, EDG 65, 800mm f/13 G"}, {"88 54 50 50 0C 0C 4B 06", "Sigma 50mm f/1.4 DG HSM | A"}, + {"89 30 2D 80 2C 40 4B 0E", "Sigma 18-200mm f/3.5-6.3 DC Macro OS HS | C"}, {"89 3C 53 80 30 3C 8B 06", "AF-S DX Zoom-Nikkor 55-200mm f/4-5.6G ED"}, {"8A 3C 37 6A 30 30 4B 0E", "Sigma 24-105mm f/4 DG OS HSM"}, {"8A 54 6A 6A 24 24 8C 0E", "AF-S VR Micro-Nikkor 105mm f/2.8G IF-ED"}, @@ -955,6 +956,7 @@ const std::map NALensDataInterpreter::lenses = { {"9E 38 11 29 34 3C 4B 06", "Sigma 8-16mm f/4.5-5.6 DC HSM"}, {"9E 40 2D 6A 2C 3C A0 0E", "AF-S DX VR Zoom-Nikkor 18-105mm f/3.5-5.6G ED"}, {"9F 37 50 A0 34 40 4B 0E", "Sigma 50-500mm f/4.5-6.3 DG OS HSM"}, + {"9F 48 48 48 24 24 A1 06", "Yongnuo YN40mm f/2.8N"}, {"9F 58 44 44 14 14 A1 06", "AF-S DX Nikkor 35mm f/1.8G"}, {"A0 40 2D 53 2C 3C CA 0E", "AF-P DX Nikkor 18-55mm f/3.5-5.6G VR"}, {"A0 40 2D 53 2C 3C CA 8E", "AF-P DX Nikkor 18-55mm f/3.5-5.6G"}, @@ -1007,6 +1009,7 @@ const std::map NALensDataInterpreter::lenses = { {"AA 48 88 A4 3C 3C D5 4E", "AF-S Nikkor 180-400mm f/4E TC1.4 FL ED VR + 1.4x TC"}, {"AB 3C A0 A0 30 30 C6 4E", "AF-S Nikkor 500mm f/4E FL ED VR"}, {"AB 44 5C 8E 34 3C D6 0E", "AF-P Nikkor 70-300mm f/4.5-5.6E ED VR"}, + {"AB 44 5C 8E 34 3C D6 4E", "AF-P Nikkor 70-300mm f/4.5-5.6E ED VR"}, {"AB 44 5C 8E 34 3C D6 CE", "AF-P Nikkor 70-300mm f/4.5-5.6E ED VR"}, {"AC 38 53 8E 34 3C AE 0E", "AF-S DX Nikkor 55-300mm f/4.5-5.6G ED VR"}, {"AC 3C A6 A6 30 30 C7 4E", "AF-S Nikkor 600mm f/4E FL ED VR"}, @@ -1038,6 +1041,8 @@ const std::map NALensDataInterpreter::lenses = { {"C1 48 24 37 24 24 4B 46", "Sigma 14-24mm f/2.8 DG HSM | A"}, {"C2 4C 24 24 14 14 4B 06", "Sigma 14mm f/1.8 DG HSM | A"}, {"C3 34 68 98 38 40 4B 4E", "Sigma 100-400mm f/5-6.3 DG OS HSM | C"}, + {"C8 54 44 44 0D 0D DF 46", "Tamron SP 35mm f/1.4 Di USD (F045)"}, + {"C8 54 62 62 0C 0C 4B 06", "Sigma 85mm f/1.4 DG HSM | A"}, {"C8 54 62 62 0C 0C 4B 46", "Sigma 85mm f/1.4 DG HSM | A"}, {"C9 48 37 5C 24 24 4B 4E", "Sigma 24-70mm f/2.8 DG OS HSM | A"}, {"CA 48 27 3E 24 24 DF 4E", "Tamron SP 15-30mm f/2.8 Di VC USD G2 (A041)"}, @@ -1051,21 +1056,22 @@ const std::map NALensDataInterpreter::lenses = { {"DC 48 19 19 24 24 4B 06", "Sigma 10mm f/2.8 EX DC HSM Fisheye"}, {"DE 54 50 50 0C 0C 4B 06", "Sigma 50mm f/1.4 EX DG HSM"}, {"E0 3C 5C 8E 30 3C 4B 06", "Sigma 70-300mm f/4-5.6 APO DG Macro HSM"}, - {"E0 40 2D 98 2C 41 DF 4E", "Tamron AF 18-400mm f/3.5-6.3 Di II VC HLD (B028)"}, + {"E0 40 2D 98 2C 41 DF 4E", "Tamron 18-400mm f/3.5-6.3 Di II VC HLD (B028)"}, {"E1 40 19 36 2C 35 DF 4E", "Tamron 10-24mm f/3.5-4.5 Di II VC HLD (B023)"}, {"E1 58 37 37 14 14 1C 02", "Sigma 24mm f/1.8 EX DG Aspherical Macro"}, {"E2 47 5C 80 24 24 DF 4E", "Tamron SP 70-200mm f/2.8 Di VC USD G2 (A025)"}, {"E3 40 76 A6 38 40 DF 4E", "Tamron SP 150-600mm f/5-6.3 Di VC USD G2"}, {"E3 54 50 50 24 24 35 02", "Sigma Macro 50mm f/2.8 EX DG"}, {"E4 54 64 64 24 24 DF 0E", "Tamron SP 90mm f/2.8 Di VC USD Macro 1:1 (F017)"}, + {"E5 4C 62 62 14 14 C9 4E", "Tamron SP 85mm f/1.8 Di VC USD (F016)"}, {"E5 54 6A 6A 24 24 35 02", "Sigma Macro 105mm f/2.8 EX DG"}, - {"E6 40 2D 80 2C 40 DF 0E", "Tamron AF 18-200mm f/3.5-6.3 Di II VC (B018)"}, + {"E6 40 2D 80 2C 40 DF 0E", "Tamron 18-200mm f/3.5-6.3 Di II VC (B018)"}, {"E6 41 3C 8E 2C 40 1C 02", "Sigma 28-300mm f/3.5-6.3 DG Macro"}, {"E7 4C 4C 4C 14 14 DF 0E", "Tamron SP 45mm f/1.8 Di VC USD (F013)"}, {"E8 4C 44 44 14 14 DF 0E", "Tamron SP 35mm f/1.8 Di VC USD (F012)"}, {"E9 48 27 3E 24 24 DF 0E", "Tamron SP 15-30mm f/2.8 Di VC USD (A012)"}, {"E9 54 37 5C 24 24 1C 02", "Sigma 24-70mm f/2.8 EX DG Macro"}, - {"EA 40 29 8E 2C 40 DF 0E", "Tamron AF 16-300mm f/3.5-6.3 Di II VC PZD (B016)"}, + {"EA 40 29 8E 2C 40 DF 0E", "Tamron 16-300mm f/3.5-6.3 Di II VC PZD (B016)"}, {"EA 48 27 27 24 24 1C 02", "Sigma 15mm f/2.8 EX Diagonal Fisheye"}, {"EB 40 76 A6 38 40 DF 0E", "Tamron SP AF 150-600mm f/5-6.3 VC USD (A011)"}, {"ED 40 2D 80 2C 40 4B 0E", "Sigma 18-200mm f/3.5-6.3 DC OS HSM"}, @@ -1076,6 +1082,7 @@ const std::map NALensDataInterpreter::lenses = { {"F1 47 5C 8E 30 3C DF 0E", "Tamron SP 70-300mm f/4-5.6 Di VC USD (A005)"}, {"F3 48 68 8E 30 30 4B 02", "Sigma APO 100-300mm f/4 EX IF HSM"}, {"F3 54 2B 50 24 24 84 0E", "Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical (IF) (B005)"}, + {"F4 4C 7C 7C 2C 2C 4B 02", "Sigma APO Macro 180mm f/3.5 EX DG HSM"}, {"F4 54 56 56 18 18 84 06", "Tamron SP AF 60mm f/2.0 Di II Macro 1:1 (G005)"}, {"F5 40 2C 8A 2C 40 40 0E", "Tamron AF 18-270mm f/3.5-6.3 Di II VC LD Aspherical (IF) Macro (B003)"}, {"F5 48 76 76 24 24 4B 06", "Sigma APO Macro 150mm f/2.8 EX DG HSM"}, @@ -1220,5 +1227,3 @@ const TagAttrib nikon3Attribs[] = { }; } -#endif - diff --git a/rtexif/olympusattribs.cc b/rtexif/olympusattribs.cc index e42763e35..ec7ab98c7 100644 --- a/rtexif/olympusattribs.cc +++ b/rtexif/olympusattribs.cc @@ -14,10 +14,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 . */ -#ifndef _OLYMPUSATTRIBS_ -#define _OLYMPUSATTRIBS_ #include #include @@ -130,6 +128,7 @@ public: lenses["00 30 10"] = "Olympus M.Zuiko Digital ED 45mm f/1.2 Pro"; lenses["00 31 00"] = "Olympus Zuiko Digital ED 12-60mm f/2.8-4.0 SWD"; lenses["00 32 00"] = "Olympus Zuiko Digital ED 14-35mm f/2.0 SWD"; + lenses["00 32 10"] = "Olympus M.Zuiko Digital ED 12-200mm f/3.5-6.3"; lenses["00 33 00"] = "Olympus Zuiko Digital 25mm f/2.8"; lenses["00 34 00"] = "Olympus Zuiko Digital ED 9-18mm f/4.0-5.6"; lenses["00 35 00"] = "Olympus Zuiko Digital 14-54mm f/2.8-3.5 II"; @@ -190,6 +189,13 @@ public: lenses["02 26 10"] = "Lumix G 25mm f/1.7 Asph."; lenses["02 27 10"] = "Leica DG Vario-Elmar 100-400mm f/4.0-6.3 Asph. Power OIS"; lenses["02 28 10"] = "Lumix G Vario 12-60mm f/3.5-5.6 Asph. Power OIS"; + lenses["02 29 10"] = "Leica DG Summilux 12mm f/1.4 Asph."; + lenses["02 30 10"] = "Leica DG Vario-Elmarit 12-60mm f/2.8-4 Asph. Power OIS"; + lenses["02 33 10"] = "Lumix G X Vario 12-35mm f/2.8 II Asph. Power OIS"; + lenses["02 35 10"] = "Leica DG Vario-Elmarit 8-18mm f/2.8-4 Asph."; + lenses["02 36 10"] = "Leica DG Elmarit 200mm f/2.8 Power OIS"; + lenses["02 37 10"] = "Leica DG Vario-Elmarit 50-200mm f/2.8-4 Asph. Power OIS"; + lenses["02 38 10"] = "Leica DG Vario-Summilux 10-25mm f/1.7 Asph."; lenses["03 01 00"] = "Leica D Vario Elmarit 14-50mm f/2.8-3.5 Asph."; lenses["03 02 00"] = "Leica D Summilux 25mm f/1.4 Asph."; lenses["05 01 10"] = "Tamron 14-150mm f/3.5-5.8 Di III"; @@ -842,5 +848,3 @@ const TagAttrib olympusAttribs[] = { { -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr} }; } -#endif - diff --git a/rtexif/panasonicattribs.cc b/rtexif/panasonicattribs.cc index 3062824cf..4ebcf2447 100644 --- a/rtexif/panasonicattribs.cc +++ b/rtexif/panasonicattribs.cc @@ -1,8 +1,6 @@ /* * This file is part of RawTherapee. */ -#ifndef _PANASONICATTRIBS_ -#define _PANASONICATTRIBS_ #include #include "rtexif.h" @@ -138,5 +136,3 @@ const TagAttrib panasonicRawAttribs[] = { }; } -#endif - diff --git a/rtexif/pentaxattribs.cc b/rtexif/pentaxattribs.cc index 7e861d64f..abc25b7a1 100644 --- a/rtexif/pentaxattribs.cc +++ b/rtexif/pentaxattribs.cc @@ -14,10 +14,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 . */ -#ifndef _PENTAXATTRIBS_ -#define _PENTAXATTRIBS_ #include #include @@ -696,7 +694,7 @@ public: }; PAColorSpaceInterpreter paColorSpaceInterpreter; -class PALensTypeInterpreter : public IntLensInterpreter< int > +class PALensTypeInterpreter final: public IntLensInterpreter< int > { public: PALensTypeInterpreter () @@ -752,7 +750,7 @@ public: choices.insert (p_t (256 * 3 + 44, "Sigma 17-70mm f/2.8-4.5 DC Macro")); choices.insert (p_t (256 * 3 + 44, "Sigma 18-50mm f/3.5-5.6 DC")); choices.insert (p_t (256 * 3 + 44, "Sigma 17-35mm f/2.8-4 EX DG")); - choices.insert (p_t (256 * 3 + 44, "Tamron 35-90mm f/4 AF")); + choices.insert (p_t (256 * 3 + 44, "Tamron 35-90mm f/4-5.6 AF")); choices.insert (p_t (256 * 3 + 44, "Sigma AF 18-35mm f/3.5-4.5 Aspherical")); choices.insert (p_t (256 * 3 + 46, "Sigma or Samsung Lens (3 46)")); choices.insert (p_t (256 * 3 + 46, "Sigma APO 70-200mm f/2.8 EX")); @@ -908,8 +906,9 @@ public: choices.insert (p_t (256 * 7 + 243, "smc PENTAX-DA 70mm f/2.4 Limited")); choices.insert (p_t (256 * 7 + 244, "smc PENTAX-DA 21mm f/3.2 AL Limited")); choices.insert (p_t (256 * 8 + 0, "Sigma 50-150mm f/2.8 II APO EX DC HSM")); - choices.insert (p_t (256 * 8 + 3, "Sigma AF 18-125mm f/3.5-5.6 DC")); + choices.insert (p_t (256 * 8 + 3, "Sigma 18-125mm f/3.8-5.6 DC HSM")); choices.insert (p_t (256 * 8 + 4, "Sigma 50mm f/1.4 EX DG HSM")); + choices.insert (p_t (256 * 8 + 6, "Sigma 4.5mm f/2.8 EX DC Fisheye")); choices.insert (p_t (256 * 8 + 7, "Sigma 24-70mm f/2.8 IF EX DG HSM")); choices.insert (p_t (256 * 8 + 8, "Sigma 18-250mm f/3.5-6.3 DC OS HSM")); choices.insert (p_t (256 * 8 + 11, "Sigma 10-20mm f/3.5 EX DC HSM")); @@ -920,6 +919,7 @@ public: choices.insert (p_t (256 * 8 + 16, "Sigma 70-200mm f/2.8 EX DG Macro HSM II")); choices.insert (p_t (256 * 8 + 17, "Sigma 50-500mm f/4.5-6.3 DG OS HSM")); choices.insert (p_t (256 * 8 + 18, "Sigma 8-16mm f/4.5-5.6 DC HSM")); + choices.insert (p_t (256 * 8 + 20, "Sigma 18-50mm f/2.8-4.5 DC HSM")); choices.insert (p_t (256 * 8 + 21, "Sigma 17-50mm f/2.8 EX DC OS HSM")); choices.insert (p_t (256 * 8 + 22, "Sigma 85mm f/1.4 EX DG HSM")); choices.insert (p_t (256 * 8 + 23, "Sigma 70-200mm f/2.8 APO EX DG OS HSM")); @@ -938,6 +938,7 @@ public: choices.insert (p_t (256 * 8 + 62, "HD PENTAX-D FA 24-70mm f/2.8 ED SDM WR")); choices.insert (p_t (256 * 8 + 63, "HD PENTAX-D FA 15-30mm f/2.8 ED SDM WR")); choices.insert (p_t (256 * 8 + 64, "HD PENTAX-D FA* 50mm f/1.4 SDM AW")); + choices.insert (p_t (256 * 8 + 196, "HD PENTAX-DA* 11-18mm f/2.8 ED DC AW")); choices.insert (p_t (256 * 8 + 197, "HD PENTAX-DA 55-300mm f/4.5-6.3 ED PLM WR RE")); choices.insert (p_t (256 * 8 + 198, "smc PENTAX-DA L 18-50mm f/4-5.6 DC WR RE")); choices.insert (p_t (256 * 8 + 199, "HD PENTAX-DA 18-50mm f/4-5.6 DC WR RE")); @@ -992,6 +993,7 @@ public: choices.insert (p_t (256 * 22 + 3, "03 Fish-eye 3.2mm f/5.6")); choices.insert (p_t (256 * 22 + 4, "04 Toy Lens Wide 6.3mm f/7.1")); choices.insert (p_t (256 * 22 + 5, "05 Toy Lens Telephoto 18mm f/8")); + choices.insert (p_t (256 * 31 + 1, "GR Lens")); } std::string toString (const Tag* t) const override { @@ -2212,7 +2214,6 @@ const TagAttrib pentaxCameraInfoAttribs[] = { }; } -#endif diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index 312cbd1c7..89ff6cd33 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.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 RawTherapee. If not, see . + * along with RawTherapee. If not, see . */ #include #include @@ -29,6 +29,7 @@ #include #include +#include #include "rtexif.h" @@ -53,13 +54,13 @@ Interpreter stdInterpreter; //----------------------------------------------------------------------------- TagDirectory::TagDirectory () - : attribs (ifdAttribs), order (HOSTORDER), parent (nullptr) {} + : attribs (ifdAttribs), order (HOSTORDER), parent (nullptr), parseJPEG(true) {} TagDirectory::TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border) - : attribs (ta), order (border), parent (p) {} + : attribs (ta), order (border), parent (p), parseJPEG(true) {} -TagDirectory::TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border, bool skipIgnored) - : attribs (ta), order (border), parent (p) +TagDirectory::TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border, bool skipIgnored, bool parseJpeg) + : attribs (ta), order (border), parent (p), parseJPEG(parseJpeg) { int numOfTags = get2 (f, order); @@ -673,7 +674,7 @@ int TagDirectory::calculateSize () return size; } -TagDirectory* TagDirectory::clone (TagDirectory* parent) +TagDirectory* TagDirectory::clone (TagDirectory* parent) const { TagDirectory* td = new TagDirectory (parent, attribs, order); @@ -857,7 +858,7 @@ TagDirectoryTable::TagDirectoryTable (TagDirectory* p, FILE* f, int memsize, int } } } -TagDirectory* TagDirectoryTable::clone (TagDirectory* parent) +TagDirectory* TagDirectoryTable::clone (TagDirectory* parent) const { TagDirectory* td = new TagDirectoryTable (parent, values, valuesSize, zeroOffset, defaultType, attribs, order); @@ -979,9 +980,10 @@ Tag::Tag (TagDirectory* p, FILE* f, int base) } } - if (tag == 0x002e) { // location of the embedded preview image in raw files of Panasonic cameras + if (parent->getParseJpeg() && tag == 0x002e) { // location of the embedded preview image in raw files of Panasonic cameras ExifManager eManager(f, nullptr, true); const auto fpos = ftell(f); + if (fpos >= 0) { eManager.parseJPEG(fpos); // try to parse the exif data from the preview image @@ -1238,7 +1240,7 @@ defsubdirs: for (size_t j = 0, i = 0; j < count; j++, i++) { int newpos = base + toInt (j * 4, LONG); fseek (f, newpos, SEEK_SET); - directory[i] = new TagDirectory (parent, f, base, attrib->subdirAttribs, order); + directory[i] = new TagDirectory (parent, f, base, attrib->subdirAttribs, order, true, parent->getParseJpeg()); } // set the terminating NULL @@ -1373,7 +1375,7 @@ bool Tag::parseMakerNote (FILE* f, int base, ByteOrder bom ) value = new unsigned char[12]; fread (value, 1, 12, f); directory = new TagDirectory*[2]; - directory[0] = new TagDirectory (parent, f, base, panasonicAttribs, bom); + directory[0] = new TagDirectory (parent, f, base, panasonicAttribs, bom, true, parent->getParseJpeg()); directory[1] = nullptr; } else { return false; @@ -1382,7 +1384,7 @@ bool Tag::parseMakerNote (FILE* f, int base, ByteOrder bom ) return true; } -Tag* Tag::clone (TagDirectory* parent) +Tag* Tag::clone (TagDirectory* parent) const { Tag* t = new Tag (parent, attrib); @@ -1397,7 +1399,7 @@ Tag* Tag::clone (TagDirectory* parent) t->value = new unsigned char [valuesize]; memcpy (t->value, value, valuesize); } else { - value = nullptr; + t->value = nullptr; } t->makerNoteKind = makerNoteKind; @@ -2776,7 +2778,7 @@ void ExifManager::parseStd (bool skipIgnored) { parse(false, skipIgnored); } -void ExifManager::parse (bool isRaw, bool skipIgnored) +void ExifManager::parse (bool isRaw, bool skipIgnored, bool parseJpeg) { int ifdOffset = IFDOffset; @@ -2805,7 +2807,7 @@ void ExifManager::parse (bool isRaw, bool skipIgnored) fseek (f, rml->exifBase + ifdOffset, SEEK_SET); // first read the IFD directory - TagDirectory* root = new TagDirectory (nullptr, f, rml->exifBase, ifdAttribs, order, skipIgnored); + TagDirectory* root = new TagDirectory (nullptr, f, rml->exifBase, ifdAttribs, order, skipIgnored, parseJpeg); // fix ISO issue with nikon and panasonic cameras Tag* make = root->getTag ("Make"); @@ -3173,7 +3175,7 @@ void ExifManager::parseJPEG (int offset) rml.reset(new rtengine::RawMetaDataLocation(0)); } rml->exifBase = tiffbase; - parse (false); + parse (false, true, false); if (rmlCreated) { rml.reset(); } diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index 43b296746..1a956a4a5 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.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 _MEXIF3_ -#define _MEXIF3_ +#pragma once #include #include @@ -30,11 +29,15 @@ #include #include -#include +#include #include "../rtengine/noncopyable.h" #include "../rtengine/rawmetadatalocation.h" +namespace Glib +{ + class KeyFile; +} namespace rtengine { @@ -116,11 +119,12 @@ protected: const TagAttrib* attribs; // descriptor table to decode the tags ByteOrder order; // byte order TagDirectory* parent; // parent directory (NULL if root) + bool parseJPEG; static Glib::ustring getDumpKey (int tagID, const Glib::ustring &tagName); public: TagDirectory (); - TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border, bool skipIgnored = true); + TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border, bool skipIgnored = true, bool parseJpeg = true); TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border); virtual ~TagDirectory (); @@ -132,6 +136,10 @@ public: { return parent; } + inline bool getParseJpeg() const + { + return parseJPEG; + } TagDirectory* getRoot (); inline int getCount () const { @@ -155,14 +163,14 @@ public: // Try to get the Tag in the current directory and in subdirectories // if lookUpward = true, it will scan the parents TagDirectory up to the root one, // but w/o looking into their subdirs - virtual Tag* findTag (const char* name, bool lookUpward = false) const; + Tag* findTag (const char* name, bool lookUpward = false) const; // Find a all Tags with the given name by scanning the whole tag tree std::vector findTags (const char* name); // Find a all Tags with the given ID by scanning the whole tag tree std::vector findTags (int ID); // Try to get the Tag in the current directory and in parent directories // (won't look into subdirs) - virtual Tag* findTagUpward (const char* name) const; + Tag* findTagUpward (const char* name) const; bool getXMPTagValue (const char* name, char* value) const; void keepTag (int ID); @@ -180,17 +188,17 @@ public: virtual int calculateSize (); virtual int write (int start, unsigned char* buffer); - virtual TagDirectory* clone (TagDirectory* parent); + virtual TagDirectory* clone (TagDirectory* parent) const; void applyChange (const std::string &field, const Glib::ustring &value); - virtual void printAll (unsigned int level = 0) const; // reentrant debug function, keep level=0 on first call ! - virtual bool CPBDump (const Glib::ustring &commFName, const Glib::ustring &imageFName, const Glib::ustring &profileFName, const Glib::ustring &defaultPParams, + void printAll (unsigned int level = 0) const; // reentrant debug function, keep level=0 on first call ! + bool CPBDump (const Glib::ustring &commFName, const Glib::ustring &imageFName, const Glib::ustring &profileFName, const Glib::ustring &defaultPParams, const CacheImageData* cfs, const bool flagMode, Glib::KeyFile *keyFile = nullptr, Glib::ustring tagDirName = "") const; - virtual void sort (); + void sort (); }; // a table of tags: id are offset from beginning and not identifiers -class TagDirectoryTable: public TagDirectory +class TagDirectoryTable: public TagDirectory, public rtengine::NonCopyable { protected: unsigned char *values; // Tags values are saved internally here @@ -204,7 +212,7 @@ public: ~TagDirectoryTable() override; int calculateSize () override; int write (int start, unsigned char* buffer) override; - TagDirectory* clone (TagDirectory* parent) override; + TagDirectory* clone (TagDirectory* parent) const override; }; // a class representing a single tag @@ -310,7 +318,7 @@ public: // functions for writing int calculateSize (); int write (int offs, int dataOffs, unsigned char* buffer); - Tag* clone (TagDirectory* parent); + Tag* clone (TagDirectory* parent) const; // to control if the tag shall be written bool getKeep () @@ -343,7 +351,7 @@ class ExifManager Tag* saveCIFFMNTag (TagDirectory* root, int len, const char* name); void parseCIFF (int length, TagDirectory* root); - void parse (bool isRaw, bool skipIgnored = true); + void parse (bool isRaw, bool skipIgnored = true, bool parseJpeg = true); public: FILE* f; @@ -405,7 +413,6 @@ public: // Get the value as a double virtual double toDouble (const Tag* t, int ofs = 0) { - double ud, dd; switch (t->getType()) { case SBYTE: @@ -428,10 +435,11 @@ public: return (double) ((int)sget4 (t->getValue() + ofs, t->getOrder())); case SRATIONAL: - case RATIONAL: - ud = (int)sget4 (t->getValue() + ofs, t->getOrder()); - dd = (int)sget4 (t->getValue() + ofs + 4, t->getOrder()); - return dd == 0. ? 0. : (double)ud / (double)dd; + case RATIONAL: { + const double dividend = (int)sget4 (t->getValue() + ofs, t->getOrder()); + const double divisor = (int)sget4 (t->getValue() + ofs + 4, t->getOrder()); + return divisor == 0. ? 0. : dividend / divisor; + } case FLOAT: return double (sget4 (t->getValue() + ofs, t->getOrder())); @@ -686,5 +694,5 @@ extern const TagAttrib kodakIfdAttribs[]; void parseKodakIfdTextualInfo (Tag *textualInfo, Tag* exif); extern const TagAttrib panasonicAttribs[]; extern const TagAttrib panasonicRawAttribs[]; + } -#endif diff --git a/rtexif/sonyminoltaattribs.cc b/rtexif/sonyminoltaattribs.cc index 0c6e433ff..ee41b2a9b 100644 --- a/rtexif/sonyminoltaattribs.cc +++ b/rtexif/sonyminoltaattribs.cc @@ -13,10 +13,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 . */ -#ifndef _SONYMINOLTAATTRIBS_ -#define _SONYMINOLTAATTRIBS_ #include @@ -541,7 +539,7 @@ public: }; SAAntiBlurInterpreter saAntiBlurInterpreter; -class SALensIDInterpreter : public IntLensInterpreter +class SALensIDInterpreter final : public IntLensInterpreter { public: SALensIDInterpreter () @@ -574,11 +572,12 @@ public: {23, "Minolta AF 200mm f/4 Macro APO G"}, {24, "Minolta/Sony AF 24-105mm f/3.5-4.5 (D) or Sigma or Tamron Lens"}, {24, "Sigma 18-50mm f/2.8"}, - {24, "Sigma 17-70mm f/2.8-4.5 (D)"}, + {24, "Sigma 17-70mm f/2.8-4.5 DC Macro"}, {24, "Sigma 20-40mm f/2.8 EX DG Aspherical IF"}, {24, "Sigma 18-200mm f/3.5-6.3 DC"}, {24, "Sigma DC 18-125mm f/4-5,6 D"}, {24, "Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical [IF] Macro"}, + {24, "Sigma 15-30mm f/3.5-4.5 EX DG Aspherical"}, {25, "Minolta AF 100-300mm f/4.5-5.6 APO (D) or Sigma Lens"}, {25, "Sigma 100-300mm f/4 EX (APO (D) or D IF)"}, {25, "Sigma 70mm f/2.8 EX DG Macro"}, @@ -612,8 +611,9 @@ public: {45, "Carl Zeiss Planar T* 85mm f/1.4 ZA (SAL85F14Z)"}, {46, "Carl Zeiss Vario-Sonnar T* DT 16-80mm f/3.5-4.5 ZA (SAL1680Z)"}, {47, "Carl Zeiss Sonnar T* 135mm f/1.8 ZA (SAL135F18Z)"}, - {48, "Carl Zeiss Vario-Sonnar T* 24-70mm f/2.8 ZA SSM (SAL2470Z) or ZA SSM II"}, + {48, "Carl Zeiss Vario-Sonnar T* 24-70mm f/2.8 ZA SSM (SAL2470Z) or Other Lens"}, {48, "Carl Zeiss Vario-Sonnar T* 24-70mm f/2.8 ZA SSM II (SAL2470Z2)"}, + {48, "Tamron SP 24-70mm f/2.8 Di USD"}, {49, "Sony DT 55-200mm f/4-5.6 (SAL55200)"}, {50, "Sony DT 18-250mm f/3.5-6.3 (SAL18250)"}, {51, "Sony DT 16-105mm f/3.5-5.6 (SAL16105)"}, @@ -645,7 +645,6 @@ public: {128, "Tamron or Sigma Lens (128)"}, {128, "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical [IF] Macro"}, {128, "Tamron AF 28-300mm f/3.5-6.3 XR Di LD Aspherical [IF] Macro"}, - {128, "Tamron 80-300mm f/3.5-6.3"}, {128, "Tamron AF 28-200mm f/3.8-5.6 XR Di Aspherical [IF] Macro"}, {128, "Tamron SP AF 17-35mm f/2.8-4 Di LD Aspherical IF"}, {128, "Sigma AF 50-150mm f/2.8 EX DC APO HSM II"}, @@ -680,7 +679,7 @@ public: {137, "Cosina 70-210mm f/2.8-4 AF"}, {138, "Soligor 19-35mm f/3.5-4.5"}, {139, "Tokina AF 28-300mm f/4-6.3"}, - {142, "Voigtlander 70-300mm f/4.5-5.6"}, + {142, "Cosina AF 70-300mm f/4.5-5.6 MC"}, {146, "Voigtlander Macro APO-Lanthar 125mm f/2.5 SL"}, {194, "Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical [IF]"}, {202, "Tamron SP AF 70-200mm f/2.8 Di LD [IF] Macro"}, @@ -723,10 +722,11 @@ public: {2552, "Angenieux AF 28-70mm f/2.6"}, {2552, "Tokina AT-X 17 AF 17mm f/3.5"}, {2552, "Tokina 20-35mm f/3.5-4.5 II AF"}, - {2553, "Minolta AF 28-135mm f/4-4.5 or Sigma Lens"}, + {2553, "Minolta AF 28-135mm f/4-4.5 or Other Lens"}, {2553, "Sigma ZOOM-alpha 35-135mm f/3.5-4.5"}, {2553, "Sigma 28-105mm f/2.8-4 Aspherical"}, {2553, "Sigma 28-105mm f/4-5.6 UC"}, + {2553, "Tokina AT-X 242 AF 24-200mm f/3.5-5.6"}, {2554, "Minolta AF 35-105mm f/3.5-4.5"}, {2555, "Minolta AF 70-210mm f/4 Macro or Sigma Lens"}, {2555, "Sigma 70-210mm f/4-5.6 APO"}, @@ -805,7 +805,7 @@ public: {2624, "Minolta AF 35-80mm f/4-5.6 Power Zoom"}, {2628, "Minolta AF 80-200mm f/2.8 HS-APO G"}, {2629, "Minolta AF 85mm f/1.4 New"}, - {2631, "Minolta/Sony AF 100-300mm f/4.5-5.6 APO"}, + {2631, "Minolta AF 100-300mm f/4.5-5.6 APO"}, {2632, "Minolta AF 24-50mm f/4 New"}, {2638, "Minolta AF 50mm f/2.8 Macro New"}, {2639, "Minolta AF 100mm f/2.8 Macro"}, @@ -818,6 +818,7 @@ public: {2672, "Minolta AF 24-105mm f/3.5-4.5 (D)"}, {3046, "Metabones Canon EF Speed Booster"}, {4567, "Tokina 70-210mm f/4-5.6"}, + {4568, "Tokina AF 35-200mm f/4-5.6 Zoom SD"}, {4570, "Tamron AF 35-135mm f/3.5-4.5"}, {4571, "Vivitar 70-210mm f/4.5-5.6"}, {4574, "2x Teleconverter or Tamron or Tokina Lens"}, @@ -832,97 +833,6 @@ public: {6118, "Canon EF Adapter"}, {6528, "Sigma 16mm f/2.8 Filtermatic Fisheye"}, {6553, "E-Mount, T-Mount, Other Lens or no lens"}, - {6553, "Sony E 16mm f/2.8"}, - {6553, "Sony E 18-55mm f/3.5-5.6 OSS"}, - {6553, "Sony E 55-210mm f/4.5-6.3 OSS"}, - {6553, "Sony E 18-200mm f/3.5-6.3 OSS"}, - {6553, "Sony E 30mm f/3.5 Macro"}, - {6553, "Sony E 24mm f/1.8 ZA"}, - {6553, "Sony E 50mm f/1.8 OSS"}, - {6553, "Sony E 16-70mm f/4 ZA OSS"}, - {6553, "Sony E 10-18mm f/4 OSS"}, - {6553, "Sony E PZ 16-50mm f/3.5-5.6 OSS"}, - {6553, "Sony FE 35mm f/2.8 ZA"}, - {6553, "Sony FE 24-70mm f/4 ZA OSS"}, - {6553, "Sony FE 85mm f/1.8"}, - {6553, "Sony E 18-200mm f/3.5-6.3 OSS LE"}, - {6553, "Sony E 20mm f/2.8"}, - {6553, "Sony E 35mm f/1.8 OSS"}, - {6553, "Sony E PZ 18-105mm f/4 G OSS"}, - {6553, "Sony FE 12-24mm f/4 G"}, - {6553, "Sony FE 90mm f/2.8 Macro G OSS"}, - {6553, "Sony E 18-50mm f/4-5.6"}, - {6553, "Sony FE 24mm f/1.4 GM"}, - {6553, "Sony FE 24-105mm f/4 G OSS"}, - {6553, "Sony E PZ 18-200mm f/3.5-6.3 OSS"}, - {6553, "Sony FE 55mm f/1.8 ZA"}, - {6553, "Sony FE 70-200mm f/4 G OSS"}, - {6553, "Sony FE 16-35mm f/4 ZA OSS"}, - {6553, "Sony FE 50mm f/2.8 Macro"}, - {6553, "Sony FE 28-70mm f/3.5-5.6 OSS"}, - {6553, "Sony FE 35mm f/1.4 ZA"}, - {6553, "Sony FE 24-240mm f/3.5-6.3 OSS"}, - {6553, "Sony FE 28mm f/2"}, - {6553, "Sony FE PZ 28-135mm f/4 G OSS"}, - {6553, "Sony FE 100mm f/2.8 STF GM OSS"}, - {6553, "Sony E PZ 18-110mm f/4 G OSS"}, - {6553, "Sony FE 24-70mm f/2.8 GM"}, - {6553, "Sony FE 50mm f/1.4 ZA"}, - {6553, "Sony FE 85mm f/1.4 GM"}, - {6553, "Sony FE 50mm f/1.8"}, - {6553, "Sony FE 21mm f/2.8 (SEL28F20 + SEL075UWC)"}, - {6553, "Sony FE 16mm f/3.5 Fisheye (SEL28F20 + SEL057FEC)"}, - {6553, "Sony FE 70-300mm f/4.5-5.6 G OSS"}, - {6553, "Sony FE 100-400mm f/4.5-5.6 GM OSS"}, - {6553, "Sony FE 70-200mm f/2.8 GM OSS"}, - {6553, "Sony FE 16-35mm f/2.8 GM"}, - {6553, "Sony FE 400mm f/2.8 GM OSS"}, - {6553, "Sony E 18-135mm f/3.5-5.6 OSS"}, - {6553, "Sony FE 70-200mm f/2.8 GM OSS + 1.4X Teleconverter"}, - {6553, "Sony FE 70-200mm f/2.8 GM OSS + 2X Teleconverter"}, - {6553, "Sony FE 100-400mm f/4.5-5.6 GM OSS + 1.4X Teleconverter"}, - {6553, "Sony FE 100-400mm f/4.5-5.6 GM OSS + 2X Teleconverter"}, - {6553, "Sony FE 400mm f/2.8 GM OSS + 1.4X Teleconverter"}, - {6553, "Sony FE 400mm f/2.8 GM OSS + 2X Teleconverter"}, - {6553, "Samyang AF 50mm f/1.4 FE"}, - {6553, "Samyang AF 14mm f/2.8 FE"}, - {6553, "Samyang AF 24mm f/2.8"}, - {6553, "Samyang AF 35mm f/2.8 FE"}, - {6553, "Samyang AF 35mm f/1.4"}, - {6553, "Sigma 19mm f/2.8 [EX] DN"}, - {6553, "Sigma 30mm f/2.8 [EX] DN"}, - {6553, "Sigma 60mm f/2.8 DN"}, - {6553, "Sigma 30mm f/1.4 DC DN | C"}, - {6553, "Sigma 85mm f/1.4 DG HSM | A"}, - {6553, "Sigma 16mm f/1.4 DC DN | C"}, - {6553, "Sigma 105mm f/1.4 DG HSM | A"}, - {6553, "Sigma 56mm f/1.4 DC DN | C"}, - {6553, "Sigma 70-200mm f/2.8 DG OS HSM | S"}, - {6553, "Sigma 70mm f/2.8 DG MACRO | A"}, - {6553, "Tamron 18-200mm f/3.5-6.3 Di III VC"}, - {6553, "Tamron 28-75mm f/2.8 Di III RXD"}, - {6553, "Tokina Firin 20mm f/2 FE MF"}, - {6553, "Voigtlander SUPER WIDE-HELIAR 15mm f/4.5 III"}, - {6553, "Voigtlander HELIAR-HYPER WIDE 10mm f/5.6"}, - {6553, "Voigtlander ULTRA WIDE-HELIAR 12mm f/5.6 III"}, - {6553, "Voigtlander MACRO APO-LANTHAR 65mm f/2 Aspherical"}, - {6553, "Voigtlander NOKTON 40mm f/1.2 Aspherical"}, - {6553, "Voigtlander NOKTON classic 35mm f/1.4"}, - {6553, "Voigtlander MACRO APO-LANTHAR 110mm f/2.5"}, - {6553, "Voigtlander COLOR-SKOPAR 21mm f/3.5 Aspherical"}, - {6553, "Zeiss Touit 12mm f/2.8"}, - {6553, "Zeiss Touit 32mm f/1.8"}, - {6553, "Zeiss Touit 50mm f/2.8 Macro"}, - {6553, "Zeiss Batis 25mm f/2"}, - {6553, "Zeiss Batis 85mm f/1.8"}, - {6553, "Zeiss Batis 18mm f/2.8"}, - {6553, "Zeiss Batis 135mm f/2.8"}, - {6553, "Zeiss Batis 40mm f/2 CF"}, - {6553, "Zeiss Loxia 50mm f/2"}, - {6553, "Zeiss Loxia 35mm f/2"}, - {6553, "Zeiss Loxia 21mm f/2.8"}, - {6553, "Zeiss Loxia 85mm f/2.4"}, - {6553, "Zeiss Loxia 25mm f/2.4"}, {6553, "Arax MC 35mm f/2.8 Tilt+Shift"}, {6553, "Arax MC 80mm f/2.8 Tilt+Shift"}, {6553, "Zenitar MF 16mm f/2.8 Fisheye M42"}, @@ -948,10 +858,11 @@ public: {25521, "Angenieux AF 28-70mm f/2.6"}, {25521, "Tokina AT-X 17 AF 17mm f/3.5"}, {25521, "Tokina 20-35mm f/3.5-4.5 II AF"}, - {25531, "Minolta AF 28-135mm f/4-4.5 or Sigma Lens"}, + {25531, "Minolta AF 28-135mm f/4-4.5 or Other Lens"}, {25531, "Sigma ZOOM-alpha 35-135mm f/3.5-4.5"}, {25531, "Sigma 28-105mm f/2.8-4 Aspherical"}, {25531, "Sigma 28-105mm f/4-5.6 UC"}, + {25531, "Tokina AT-X 242 AF 24-200mm f/3.5-5.6"}, {25541, "Minolta AF 35-105mm f/3.5-4.5"}, {25551, "Minolta AF 70-210mm f/4 Macro or Sigma Lens"}, {25551, "Sigma 70-210mm f/4-5.6 APO"}, @@ -1030,7 +941,7 @@ public: {26241, "Minolta AF 35-80mm f/4-5.6 Power Zoom"}, {26281, "Minolta AF 80-200mm f/2.8 HS-APO G"}, {26291, "Minolta AF 85mm f/1.4 New"}, - {26311, "Minolta/Sony AF 100-300mm f/4.5-5.6 APO"}, + {26311, "Minolta AF 100-300mm f/4.5-5.6 APO"}, {26321, "Minolta AF 24-50mm f/4 New"}, {26381, "Minolta AF 50mm f/2.8 Macro New"}, {26391, "Minolta AF 100mm f/2.8 Macro"}, @@ -1043,6 +954,7 @@ public: {26721, "Minolta AF 24-105mm f/3.5-4.5 (D)"}, {30464, "Metabones Canon EF Speed Booster"}, {45671, "Tokina 70-210mm f/4-5.6"}, + {45681, "Tokina AF 35-200mm f/4-5.6 Zoom SD"}, {45701, "Tamron AF 35-135mm f/3.5-4.5"}, {45711, "Vivitar 70-210mm f/4.5-5.6"}, {45741, "2x Teleconverter or Tamron or Tokina Lens"}, @@ -1057,104 +969,13 @@ public: {61184, "Canon EF Adapter"}, {65280, "Sigma 16mm f/2.8 Filtermatic Fisheye"}, {65535, "E-Mount, T-Mount, Other Lens or no lens"}, - {65535, "Sony E 16mm f/2.8"}, - {65535, "Sony E 18-55mm f/3.5-5.6 OSS"}, - {65535, "Sony E 55-210mm f/4.5-6.3 OSS"}, - {65535, "Sony E 18-200mm f/3.5-6.3 OSS"}, - {65535, "Sony E 30mm f/3.5 Macro"}, - {65535, "Sony E 24mm f/1.8 ZA"}, - {65535, "Sony E 50mm f/1.8 OSS"}, - {65535, "Sony E 16-70mm f/4 ZA OSS"}, - {65535, "Sony E 10-18mm f/4 OSS"}, - {65535, "Sony E PZ 16-50mm f/3.5-5.6 OSS"}, - {65535, "Sony FE 35mm f/2.8 ZA"}, - {65535, "Sony FE 24-70mm f/4 ZA OSS"}, - {65535, "Sony FE 85mm f/1.8"}, - {65535, "Sony E 18-200mm f/3.5-6.3 OSS LE"}, - {65535, "Sony E 20mm f/2.8"}, - {65535, "Sony E 35mm f/1.8 OSS"}, - {65535, "Sony E PZ 18-105mm f/4 G OSS"}, - {65535, "Sony FE 12-24mm f/4 G"}, - {65535, "Sony FE 90mm f/2.8 Macro G OSS"}, - {65535, "Sony E 18-50mm f/4-5.6"}, - {65535, "Sony FE 24mm f/1.4 GM"}, - {65535, "Sony FE 24-105mm f/4 G OSS"}, - {65535, "Sony E PZ 18-200mm f/3.5-6.3 OSS"}, - {65535, "Sony FE 55mm f/1.8 ZA"}, - {65535, "Sony FE 70-200mm f/4 G OSS"}, - {65535, "Sony FE 16-35mm f/4 ZA OSS"}, - {65535, "Sony FE 50mm f/2.8 Macro"}, - {65535, "Sony FE 28-70mm f/3.5-5.6 OSS"}, - {65535, "Sony FE 35mm f/1.4 ZA"}, - {65535, "Sony FE 24-240mm f/3.5-6.3 OSS"}, - {65535, "Sony FE 28mm f/2"}, - {65535, "Sony FE PZ 28-135mm f/4 G OSS"}, - {65535, "Sony FE 100mm f/2.8 STF GM OSS"}, - {65535, "Sony E PZ 18-110mm f/4 G OSS"}, - {65535, "Sony FE 24-70mm f/2.8 GM"}, - {65535, "Sony FE 50mm f/1.4 ZA"}, - {65535, "Sony FE 85mm f/1.4 GM"}, - {65535, "Sony FE 50mm f/1.8"}, - {65535, "Sony FE 21mm f/2.8 (SEL28F20 + SEL075UWC)"}, - {65535, "Sony FE 16mm f/3.5 Fisheye (SEL28F20 + SEL057FEC)"}, - {65535, "Sony FE 70-300mm f/4.5-5.6 G OSS"}, - {65535, "Sony FE 100-400mm f/4.5-5.6 GM OSS"}, - {65535, "Sony FE 70-200mm f/2.8 GM OSS"}, - {65535, "Sony FE 16-35mm f/2.8 GM"}, - {65535, "Sony FE 400mm f/2.8 GM OSS"}, - {65535, "Sony E 18-135mm f/3.5-5.6 OSS"}, - {65535, "Sony FE 70-200mm f/2.8 GM OSS + 1.4X Teleconverter"}, - {65535, "Sony FE 70-200mm f/2.8 GM OSS + 2X Teleconverter"}, - {65535, "Sony FE 100-400mm f/4.5-5.6 GM OSS + 1.4X Teleconverter"}, - {65535, "Sony FE 100-400mm f/4.5-5.6 GM OSS + 2X Teleconverter"}, - {65535, "Sony FE 400mm f/2.8 GM OSS + 1.4X Teleconverter"}, - {65535, "Sony FE 400mm f/2.8 GM OSS + 2X Teleconverter"}, - {65535, "Samyang AF 50mm f/1.4 FE"}, - {65535, "Samyang AF 14mm f/2.8 FE"}, - {65535, "Samyang AF 24mm f/2.8"}, - {65535, "Samyang AF 35mm f/2.8 FE"}, - {65535, "Samyang AF 35mm f/1.4"}, - {65535, "Sigma 19mm f/2.8 [EX] DN"}, - {65535, "Sigma 30mm f/2.8 [EX] DN"}, - {65535, "Sigma 60mm f/2.8 DN"}, - {65535, "Sigma 30mm f/1.4 DC DN | C"}, - {65535, "Sigma 85mm f/1.4 DG HSM | A"}, - {65535, "Sigma 16mm f/1.4 DC DN | C"}, - {65535, "Sigma 105mm f/1.4 DG HSM | A"}, - {65535, "Sigma 56mm f/1.4 DC DN | C"}, - {65535, "Sigma 70-200mm f/2.8 DG OS HSM | S"}, - {65535, "Sigma 70mm f/2.8 DG MACRO | A"}, - {65535, "Tamron 18-200mm f/3.5-6.3 Di III VC"}, - {65535, "Tamron 28-75mm f/2.8 Di III RXD"}, - {65535, "Tokina Firin 20mm f/2 FE MF"}, - {65535, "Voigtlander SUPER WIDE-HELIAR 15mm f/4.5 III"}, - {65535, "Voigtlander HELIAR-HYPER WIDE 10mm f/5.6"}, - {65535, "Voigtlander ULTRA WIDE-HELIAR 12mm f/5.6 III"}, - {65535, "Voigtlander MACRO APO-LANTHAR 65mm f/2 Aspherical"}, - {65535, "Voigtlander NOKTON 40mm f/1.2 Aspherical"}, - {65535, "Voigtlander NOKTON classic 35mm f/1.4"}, - {65535, "Voigtlander MACRO APO-LANTHAR 110mm f/2.5"}, - {65535, "Voigtlander COLOR-SKOPAR 21mm f/3.5 Aspherical"}, - {65535, "Zeiss Touit 12mm f/2.8"}, - {65535, "Zeiss Touit 32mm f/1.8"}, - {65535, "Zeiss Touit 50mm f/2.8 Macro"}, - {65535, "Zeiss Batis 25mm f/2"}, - {65535, "Zeiss Batis 85mm f/1.8"}, - {65535, "Zeiss Batis 18mm f/2.8"}, - {65535, "Zeiss Batis 135mm f/2.8"}, - {65535, "Zeiss Batis 40mm f/2 CF"}, - {65535, "Zeiss Loxia 50mm f/2"}, - {65535, "Zeiss Loxia 35mm f/2"}, - {65535, "Zeiss Loxia 21mm f/2.8"}, - {65535, "Zeiss Loxia 85mm f/2.4"}, - {65535, "Zeiss Loxia 25mm f/2.4"}, {65535, "Arax MC 35mm f/2.8 Tilt+Shift"}, {65535, "Arax MC 80mm f/2.8 Tilt+Shift"}, {65535, "Zenitar MF 16mm f/2.8 Fisheye M42"}, {65535, "Samyang 500mm Mirror f/8.0"}, {65535, "Pentacon Auto 135mm f/2.8"}, {65535, "Pentacon Auto 29mm f/2.8"}, - {65535, "Helios 44-2 58mm f/2.0"}, + {65535, "Helios 44-2 58mm f/2.0"} }; } @@ -1192,18 +1013,31 @@ public: }; SALensIDInterpreter saLensIDInterpreter; -class SALensID2Interpreter : public IntLensInterpreter< int > +class SALensID2Interpreter final : public IntLensInterpreter< int > { public: SALensID2Interpreter () { choices.insert (p_t (0, "Unknown E-mount lens or other lens")); + choices.insert (p_t (0, "Sigma 19mm f/2.8 [EX] DN")); + choices.insert (p_t (0, "Sigma 30mm f/2.8 [EX] DN")); + choices.insert (p_t (0, "Sigma 60mm f/2.8 DN")); + choices.insert (p_t (0, "Sony E 18-200mm f/3.5-6.3 OSS LE")); + choices.insert (p_t (0, "Tamron 18-200mm f/3.5-6.3 Di III VC")); + choices.insert (p_t (0, "Tokina FiRIN 20mm f/2 FE AF")); + choices.insert (p_t (0, "Tokina FiRIN 20mm f/2 FE MF")); + choices.insert (p_t (0, "Zeiss Touit 12mm f/2.8")); + choices.insert (p_t (0, "Zeiss Touit 32mm f/1.8")); + choices.insert (p_t (0, "Zeiss Touit 50mm f/2.8 Macro")); + choices.insert (p_t (0, "Zeiss Loxia 50mm f/2")); + choices.insert (p_t (0, "Zeiss Loxia 35mm f/2")); choices.insert (p_t (1, "Sony LA-EA1 or Sigma MC-11 Adapter")); choices.insert (p_t (2, "Sony LA-EA2 Adapter")); choices.insert (p_t (3, "Sony LA-EA3 Adapter")); choices.insert (p_t (6, "Sony LA-EA4 Adapter")); choices.insert (p_t (44, "Metabones Canon EF Smart Adapter")); choices.insert (p_t (78, "Metabones Canon EF Smart Adapter Mark III or Other Adapter")); + choices.insert (p_t (184, "Metabones Canon EF Speed Booster Ultra")); choices.insert (p_t (234, "Metabones Canon EF Smart Adapter Mark IV")); choices.insert (p_t (239, "Metabones Canon EF Speed Booster")); choices.insert (p_t (32784, "Sony E 16mm f/2.8")); @@ -1211,17 +1045,19 @@ public: choices.insert (p_t (32786, "Sony E 55-210mm f/4.5-6.3 OSS")); choices.insert (p_t (32787, "Sony E 18-200mm f/3.5-6.3 OSS")); choices.insert (p_t (32788, "Sony E 30mm f/3.5 Macro")); - choices.insert (p_t (32789, "Sony E 24mm f/1.8 ZA or Samyang AF 50mm f/1.4 FE")); - choices.insert (p_t (32789, "Samyang AF 50mm f/1.4 FE")); - choices.insert (p_t (32790, "Sony E 50mm f/1.8 OSS or Samyang AF 14mm f/2.8 FE")); - choices.insert (p_t (32790, "Samyang AF 14mm f/2.8 FE")); + choices.insert (p_t (32789, "Sony E 24mm f/1.8 ZA or Samyang AF 50mm f/1.4")); + choices.insert (p_t (32789, "Samyang AF 50mm f/1.4")); + choices.insert (p_t (32790, "Sony E 50mm f/1.8 OSS or Samyang AF 14mm f/2.8")); + choices.insert (p_t (32790, "Samyang AF 14mm f/2.8")); choices.insert (p_t (32791, "Sony E 16-70mm f/4 ZA OSS")); choices.insert (p_t (32792, "Sony E 10-18mm f/4 OSS")); choices.insert (p_t (32793, "Sony E PZ 16-50mm f/3.5-5.6 OSS")); - choices.insert (p_t (32794, "Sony FE 35mm f/2.8 ZA or Samyang AF 24mm f/2.8 FE")); - choices.insert (p_t (32794, "Samyang AF 24mm f/2.8 FE")); + choices.insert (p_t (32794, "Sony FE 35mm f/2.8 ZA or Samyang Lens")); + choices.insert (p_t (32794, "Samyang AF 24mm f/2.8")); + choices.insert (p_t (32794, "Samyang AF 35mm f/2.8")); choices.insert (p_t (32795, "Sony FE 24-70mm f/4 ZA OSS")); - choices.insert (p_t (32796, "Sony FE 85mm f/1.8")); + choices.insert (p_t (32796, "Sony FE 85mm f/1.8 or Viltrox PFU RBMH 85mm f/1.8")); + choices.insert (p_t (32796, "Viltrox PFU RBMH 85mm f/1.8")); choices.insert (p_t (32797, "Sony E 18-200mm f/3.5-6.3 OSS LE")); choices.insert (p_t (32798, "Sony E 20mm f/2.8")); choices.insert (p_t (32799, "Sony E 35mm f/1.8 OSS")); @@ -1245,7 +1081,8 @@ public: choices.insert (p_t (32820, "Sony E PZ 18-110mm f/4 G OSS")); choices.insert (p_t (32821, "Sony FE 24-70mm f/2.8 GM")); choices.insert (p_t (32822, "Sony FE 50mm f/1.4 ZA")); - choices.insert (p_t (32823, "Sony FE 85mm f/1.4 GM")); + choices.insert (p_t (32823, "Sony FE 85mm f/1.4 GM or Samyang AF 85mm f/1.4")); + choices.insert (p_t (32823, "Samyang AF 85mm f/1.4")); choices.insert (p_t (32824, "Sony FE 50mm f/1.8")); choices.insert (p_t (32826, "Sony FE 21mm f/2.8 (SEL28F20 + SEL075UWC)")); choices.insert (p_t (32827, "Sony FE 16mm f/3.5 Fisheye (SEL28F20 + SEL057FEC)")); @@ -1255,6 +1092,12 @@ public: choices.insert (p_t (32831, "Sony FE 16-35mm f/2.8 GM")); choices.insert (p_t (32848, "Sony FE 400mm f/2.8 GM OSS")); choices.insert (p_t (32849, "Sony E 18-135mm f/3.5-5.6 OSS")); + choices.insert (p_t (32850, "Sony FE 135mm f/1.8 GM")); + choices.insert (p_t (32851, "Sony FE 200-600mm f/5.6-6.3 G OSS")); + choices.insert (p_t (32852, "Sony FE 600mm f/4 GM OSS")); + choices.insert (p_t (32853, "Sony E 16-55mm f/2.8 G")); + choices.insert (p_t (32854, "Sony E 70-350mm f/4.5-6.3 G OSS")); + choices.insert (p_t (32858, "Sony FE 35mm f/1.8")); choices.insert (p_t (33072, "Sony FE 70-200mm f/2.8 GM OSS + 1.4X Teleconverter")); choices.insert (p_t (33073, "Sony FE 70-200mm f/2.8 GM OSS + 2X Teleconverter")); choices.insert (p_t (33076, "Sony FE 100mm f/2.8 STF GM OSS (macro mode)")); @@ -1262,6 +1105,10 @@ public: choices.insert (p_t (33078, "Sony FE 100-400mm f/4.5-5.6 GM OSS + 2X Teleconverter")); choices.insert (p_t (33079, "Sony FE 400mm f/2.8 GM OSS + 1.4X Teleconverter")); choices.insert (p_t (33080, "Sony FE 400mm f/2.8 GM OSS + 2X Teleconverter")); + choices.insert (p_t (33081, "Sony FE 200-600mm f/5.6-6.3 G OSS + 1.4X Teleconverter")); + choices.insert (p_t (33082, "Sony FE 200-600mm f/5.6-6.3 G OSS + 2X Teleconverter")); + choices.insert (p_t (33083, "Sony FE 600mm f/4 GM OSS + 1.4X Teleconverter")); + choices.insert (p_t (33084, "Sony FE 600mm f/4 GM OSS + 2X Teleconverter")); choices.insert (p_t (49201, "Zeiss Touit 12mm f/2.8")); choices.insert (p_t (49202, "Zeiss Touit 32mm f/1.8")); choices.insert (p_t (49203, "Zeiss Touit 50mm f/2.8 Macro")); @@ -1276,11 +1123,17 @@ public: choices.insert (p_t (49235, "Zeiss Loxia 85mm f/2.4")); choices.insert (p_t (49236, "Zeiss Loxia 25mm f/2.4")); choices.insert (p_t (49457, "Tamron 28-75mm f/2.8 Di III RXD")); + choices.insert (p_t (49458, "Tamron 17-28mm f/2.8 Di III RXD")); + choices.insert (p_t (49459, "Tamron 35mm f/2.8 Di III OSD M1:2")); + choices.insert (p_t (49460, "Tamron 24mm f/2.8 Di III OSD M1:2")); + choices.insert (p_t (49712, "Tokina FiRIN 20mm f/2 FE AF")); + choices.insert (p_t (49713, "Tokina FiRIN 100mm f/2.8 FE MACRO")); choices.insert (p_t (50480, "Sigma 30mm f/1.4 DC DN | C")); choices.insert (p_t (50481, "Sigma 50mm f/1.4 DG HSM | A")); choices.insert (p_t (50482, "Sigma 18-300mm f/3.5-6.3 DC MACRO OS HSM | C + MC-11")); choices.insert (p_t (50483, "Sigma 18-35mm f/1.8 DC HSM | A + MC-11")); choices.insert (p_t (50484, "Sigma 24-35mm f/2 DG HSM | A + MC-11")); + choices.insert (p_t (50485, "Sigma 24mm f/1.4 DG HSM | A + MC-11")); choices.insert (p_t (50486, "Sigma 150-600mm f/5-6.3 DG OS HSM | C + MC-11")); choices.insert (p_t (50487, "Sigma 20mm f/1.4 DG HSM | A + MC-11")); choices.insert (p_t (50488, "Sigma 35mm f/1.4 DG HSM | A")); @@ -1294,8 +1147,11 @@ public: choices.insert (p_t (50503, "Sigma 16mm f/1.4 DC DN | C")); choices.insert (p_t (50507, "Sigma 105mm f/1.4 DG HSM | A")); choices.insert (p_t (50508, "Sigma 56mm f/1.4 DC DN | C")); - choices.insert (p_t (50512, "Sigma 70-200mm f/2.8 DG OS HSM | S")); + choices.insert (p_t (50512, "Sigma 70-200mm f/2.8 DG OS HSM | S + MC-11")); choices.insert (p_t (50513, "Sigma 70mm f/2.8 DG MACRO | A")); + choices.insert (p_t (50514, "Sigma 45mm f/2.8 DG DN | C")); + choices.insert (p_t (50515, "Sigma 35mm f/1.2 DG DN | A")); + choices.insert (p_t (50516, "Sigma 14-24mm f/2.8 DG DN | A")); choices.insert (p_t (50992, "Voigtlander SUPER WIDE-HELIAR 15mm f/4.5 III")); choices.insert (p_t (50993, "Voigtlander HELIAR-HYPER WIDE 10mm f/5.6")); choices.insert (p_t (50994, "Voigtlander ULTRA WIDE-HELIAR 12mm f/5.6 III")); @@ -1304,9 +1160,15 @@ public: choices.insert (p_t (50997, "Voigtlander NOKTON classic 35mm f/1.4")); choices.insert (p_t (50998, "Voigtlander MACRO APO-LANTHAR 110mm f/2.5")); choices.insert (p_t (50999, "Voigtlander COLOR-SKOPAR 21mm f/3.5 Aspherical")); - choices.insert (p_t (51505, "Samyang AF 14mm f/2.8 FE or Samyang AF 35mm f/2.8 FE")); - choices.insert (p_t (51505, "Samyang AF 35mm f/2.8 FE")); + choices.insert (p_t (51000, "Voigtlander NOKTON 50mm f/1.2 Aspherical")); + choices.insert (p_t (51001, "Voigtlander NOKTON 21mm f/1.4 Aspherical")); + choices.insert (p_t (51002, "Voigtlander APO-LANTHAR 50mm f/2 Aspherical")); + choices.insert (p_t (51504, "Samyang AF 50mm f/1.4")); + choices.insert (p_t (51505, "Samyang AF 14mm f/2.8 or Samyang AF 35mm f/2.8")); + choices.insert (p_t (51505, "Samyang AF 35mm f/2.8")); choices.insert (p_t (51507, "Samyang AF 35mm f/1.4")); + choices.insert (p_t (51508, "Samyang AF 45mm f/1.8")); + choices.insert (p_t (51510, "Samyang AF 18mm f/2.8")); } std::string toString (const Tag* t) const override @@ -2635,6 +2497,4 @@ const TagAttrib sonyCameraSettingsAttribs3[] = { {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}};*/ } -#endif - diff --git a/rtexif/stdattribs.cc b/rtexif/stdattribs.cc index ec5534381..be7a28a5c 100644 --- a/rtexif/stdattribs.cc +++ b/rtexif/stdattribs.cc @@ -15,10 +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 . */ -#ifndef _STDATTRIBS_ -#define _STDATTRIBS_ #include #include @@ -927,5 +925,3 @@ const TagAttrib ifdAttribs[] = { { -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr} }; } - -#endif diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index 85884ab78..6c449f4cb 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -80,7 +80,6 @@ set(NONCLISOURCEFILES hsvequalizer.cc iccprofilecreator.cc icmpanel.cc - ilabel.cc imagearea.cc imageareapanel.cc impulsedenoise.cc @@ -110,6 +109,7 @@ set(NONCLISOURCEFILES partialpastedlg.cc pathutils.cc pcvignette.cc + pdsharpening.cc perspective.cc placesbrowser.cc popupbutton.cc @@ -289,6 +289,7 @@ target_link_libraries(rth rtengine ${ZLIB_LIBRARIES} ${LENSFUN_LIBRARIES} ${RSVG_LIBRARIES} + ${TCMALLOC_LIBRARIES} ) target_link_libraries(rth-cli rtengine @@ -310,6 +311,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..05150517f 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -1,6 +1,4 @@ -#ifndef _ADDSETIDS_ -#define _ADDSETIDS_ - +#pragma once // UPDATE THE DEFAULT VALUE IN OPTIONS.CC int babehav[] TOO !!! @@ -145,5 +143,3 @@ enum { ADDSET_PARAM_NUM // THIS IS USED AS A DELIMITER!! }; - -#endif diff --git a/rtgui/adjuster.cc b/rtgui/adjuster.cc index 0d2c2961f..142374213 100644 --- a/rtgui/adjuster.cc +++ b/rtgui/adjuster.cc @@ -14,17 +14,17 @@ * GNU General Public License for more details. * * 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 #include -#include "multilangmgr.h" -#include "../rtengine/rtengine.h" -#include "options.h" -#include "guiutils.h" -#include "rtimage.h" +#include "multilangmgr.h" +#include "options.h" +#include "rtimage.h" +#include "../rtengine/rt_math.h" namespace { @@ -230,23 +230,8 @@ void Adjuster::setDefaultEditedState (EditedState eState) void Adjuster::autoToggled () { - if (!editedCheckBox) { - // If not used in the BatchEditor panel - if (automatic->get_active()) { - // Disable the slider and spin button - spin->set_sensitive(false); - slider->set_sensitive(false); - reset->set_sensitive(false); - } else { - // Enable the slider and spin button - spin->set_sensitive(true); - slider->set_sensitive(true); - reset->set_sensitive(true); - } - } - - if (adjusterListener != nullptr && !blocked) { - adjusterListener->adjusterAutoToggled(this, automatic->get_active()); + if (adjusterListener && !blocked) { + adjusterListener->adjusterAutoToggled(this); } } @@ -380,6 +365,9 @@ void Adjuster::spinChanged () if (adjusterListener && !blocked) { if (!buttonReleaseSlider.connected() || afterReset) { eventPending = false; + if (automatic) { + setAutoValue(false); + } adjusterListener->adjusterChanged(this, spin->get_value()); } else { eventPending = true; @@ -419,6 +407,9 @@ void Adjuster::sliderChanged () if (adjusterListener && !blocked) { if (!buttonReleaseSlider.connected() || afterReset) { eventPending = false; + if (automatic) { + setAutoValue(false); + } adjusterListener->adjusterChanged(this, spin->get_value()); } else { eventPending = true; @@ -459,21 +450,6 @@ void Adjuster::setAutoValue (bool a) const bool oldVal = autoChange.block(true); automatic->set_active(a); autoChange.block(oldVal); - - if (!editedCheckBox) { - // If not used in the BatchEditor panel - if (a) { - // Disable the slider and spin button - spin->set_sensitive(false); - slider->set_sensitive(false); - reset->set_sensitive(false); - } else { - // Enable the slider and spin button - spin->set_sensitive(true); - slider->set_sensitive(true); - reset->set_sensitive(true); - } - } } } @@ -481,6 +457,9 @@ bool Adjuster::notifyListener () { if (eventPending && adjusterListener != nullptr && !blocked) { + if (automatic) { + setAutoValue(false); + } adjusterListener->adjusterChanged(this, spin->get_value()); } @@ -493,7 +472,7 @@ bool Adjuster::notifyListenerAutoToggled () { if (adjusterListener != nullptr && !blocked) { - adjusterListener->adjusterAutoToggled(this, automatic->get_active()); + adjusterListener->adjusterAutoToggled(this); } return false; @@ -571,6 +550,9 @@ void Adjuster::showEditedCB () void Adjuster::editedToggled () { if (adjusterListener && !blocked) { + if (automatic) { + setAutoValue(false); + } adjusterListener->adjusterChanged(this, spin->get_value()); } @@ -631,21 +613,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 f3f256940..143268786 100644 --- a/rtgui/adjuster.h +++ b/rtgui/adjuster.h @@ -14,12 +14,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 . */ -#ifndef _ADJUSTER_H_ -#define _ADJUSTER_H_ +#pragma once -#include #include "editedstate.h" #include "guiutils.h" @@ -30,12 +28,12 @@ class AdjusterListener public: virtual ~AdjusterListener() = default; virtual void adjusterChanged (Adjuster* a, double newval) = 0; - virtual void adjusterAutoToggled (Adjuster* a, bool newval) {} + virtual void adjusterAutoToggled (Adjuster* a) {} }; typedef double(*double2double_fun)(double val); -class Adjuster : public Gtk::Grid +class Adjuster final : public Gtk::Grid { protected: @@ -130,5 +128,3 @@ public: void trimValue (int &val) const; void setLogScale(double base, double pivot, bool anchorMiddle = false); }; - -#endif 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 239057b87..8b4583877 100644 --- a/rtgui/batchqueue.cc +++ b/rtgui/batchqueue.cc @@ -14,9 +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 . */ -#include +#include #include #include #include @@ -28,12 +28,15 @@ #include #include +#include "cachemanager.h" #include "thumbnail.h" #include "batchqueue.h" +#include "batchqueueentry.h" #include "multilangmgr.h" #include "filecatalog.h" #include "batchqueuebuttonset.h" #include "guiutils.h" +#include "pathutils.h" #include "rtimage.h" #include @@ -144,7 +147,7 @@ int BatchQueue::getThumbnailHeight () return std::max(std::min(options.thumbSizeQueue, 200), 10); } -void BatchQueue::rightClicked (ThumbBrowserEntryBase* entry) +void BatchQueue::rightClicked () { pmenu.popup (3, this->eventTime); } @@ -341,9 +344,8 @@ bool BatchQueue::loadBatchQueue () auto job = rtengine::ProcessingJob::create (source, thumb->getType () == FT_Raw, pparams, fast); - auto prevh = getMaxThumbnailHeight (); - auto prevw = prevh; - thumb->getThumbnailSize (prevw, prevh, &pparams); + const auto prevh = getMaxThumbnailHeight (); + const auto prevw = thumb->getThumbnailWidth(prevh, &pparams); auto entry = new BatchQueueEntry (job, pparams, source, prevw, prevh, thumb, options.overwriteOutputFile); thumb->decreaseRef (); // Removing the refCount acquired by cacheMgr->getEntry @@ -811,7 +813,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 +859,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..5cde37748 100644 --- a/rtgui/batchqueue.h +++ b/rtgui/batchqueue.h @@ -13,23 +13,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 _BATCHQUEUE_ -#define _BATCHQUEUE_ +#pragma once #include #include -#include "../rtengine/rtengine.h" - -#include "batchqueueentry.h" +#include "lwbutton.h" #include "lwbuttonset.h" -#include "options.h" #include "threadutils.h" #include "thumbbrowserbase.h" +#include "../rtengine/rtengine.h" +#include "../rtengine/noncopyable.h" + +class BatchQueueEntry; + 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); @@ -72,7 +74,7 @@ public: void error(const Glib::ustring& descr) override; rtengine::ProcessingJob* imageReady(rtengine::IImagefloat* img) override; - void rightClicked (ThumbBrowserEntryBase* entry) override; + void rightClicked () override; void doubleClicked (ThumbBrowserEntryBase* entry) override; bool keyPressed (GdkEventKey* event) override; void buttonPressed (LWButton* button, int actionCode, void* actionData) override; @@ -122,5 +124,3 @@ private: IdleRegister idle_register; }; - -#endif diff --git a/rtgui/batchqueuebuttonset.cc b/rtgui/batchqueuebuttonset.cc index b42d3c773..969a55079 100644 --- a/rtgui/batchqueuebuttonset.cc +++ b/rtgui/batchqueuebuttonset.cc @@ -14,12 +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 . */ #include "batchqueuebuttonset.h" +#include "lwbutton.h" #include "multilangmgr.h" #include "rtimage.h" +#include "rtsurface.h" bool BatchQueueButtonSet::iconsLoaded = false; diff --git a/rtgui/batchqueuebuttonset.h b/rtgui/batchqueuebuttonset.h index e97819719..fb45df518 100644 --- a/rtgui/batchqueuebuttonset.h +++ b/rtgui/batchqueuebuttonset.h @@ -14,16 +14,17 @@ * GNU General Public License for more details. * * 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_ +#pragma once -#include "lwbuttonset.h" -#include "rtsurface.h" #include +#include "lwbuttonset.h" + class BatchQueueEntry; +class RTSurface; + class BatchQueueButtonSet : public LWButtonSet { @@ -40,5 +41,3 @@ public: explicit BatchQueueButtonSet (BatchQueueEntry* myEntry); }; - -#endif diff --git a/rtgui/batchqueueentry.cc b/rtgui/batchqueueentry.cc index 23982095c..90079b2cc 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" @@ -25,8 +25,10 @@ #include "rtimage.h" #include "multilangmgr.h" #include "thumbbrowserbase.h" +#include "thumbnail.h" #include "../rtengine/procparams.h" +#include "../rtengine/rtengine.h" bool BatchQueueEntry::iconsLoaded(false); Glib::RefPtr BatchQueueEntry::savedAsIcon; @@ -40,7 +42,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()), diff --git a/rtgui/batchqueueentry.h b/rtgui/batchqueueentry.h index 0ea56e403..f06b65046 100644 --- a/rtgui/batchqueueentry.h +++ b/rtgui/batchqueueentry.h @@ -14,18 +14,34 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include #include -#include "../rtengine/rtengine.h" -#include "thumbbrowserentrybase.h" -#include "thumbnail.h" + #include "bqentryupdater.h" +#include "options.h" +#include "thumbbrowserentrybase.h" + +#include "../rtengine/noncopyable.h" + +class Thumbnail; + +namespace rtengine +{ +class ProcessingJob; + +namespace procparams +{ + +class ProcParams; + +} + +} class BatchQueueEntry; struct BatchQueueEntryIdleHelper { @@ -34,7 +50,7 @@ struct BatchQueueEntryIdleHelper { int pending; }; -class BatchQueueEntry : public ThumbBrowserEntryBase, public BQEntryUpdateListener +class BatchQueueEntry final : public ThumbBrowserEntryBase, public BQEntryUpdateListener, public rtengine::NonCopyable { guint8* opreview; @@ -76,7 +92,3 @@ public: void updateImage (guint8* img, int w, int h, int origw, int origh, guint8* newOPreview) override; void _updateImage (guint8* img, int w, int h); // inside gtk thread }; - - - -#endif diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index b800907e9..f7a73a30b 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -14,11 +14,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 . */ #include "batchqueuepanel.h" #include "options.h" -#include "preferences.h" #include "multilangmgr.h" #include "rtwindow.h" #include "soundman.h" diff --git a/rtgui/batchqueuepanel.h b/rtgui/batchqueuepanel.h index a1ee7326f..7c0a367d4 100644 --- a/rtgui/batchqueuepanel.h +++ b/rtgui/batchqueuepanel.h @@ -14,21 +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 . */ -#ifndef _BATCHQUEUEPANEL_ -#define _BATCHQUEUEPANEL_ +#pragma once #include #include + #include "batchqueue.h" -#include "saveformatpanel.h" #include "guiutils.h" +#include "saveformatpanel.h" class RTWindow; class FileCatalog; class Thumbnail; + class BatchQueuePanel : public Gtk::VBox, public BatchQueueListener, public FormatChangeListener @@ -83,5 +84,3 @@ private: void formatChanged(const Glib::ustring& format) override; void updateTab (int qsize, int forceOrientation = 0); // forceOrientation=0: base on options / 1: horizontal / 2: vertical }; -#endif - diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index 0fd96cea1..ad55e5860 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -14,14 +14,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 . */ + +#include "bayerpreprocess.h" +#include "bayerprocess.h" + #include "multilangmgr.h" #include "batchtoolpanelcoord.h" #include "options.h" #include "filepanel.h" #include "procparamchangers.h" #include "addsetids.h" +#include "thumbnail.h" using namespace rtengine::procparams; @@ -153,6 +158,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); 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..ea11f97c8 100644 --- a/rtgui/batchtoolpanelcoord.h +++ b/rtgui/batchtoolpanelcoord.h @@ -14,20 +14,21 @@ * GNU General Public License for more details. * * 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__ +#pragma once -#include "thumbnail.h" -#include "toolpanelcoord.h" #include "fileselectionchangelistener.h" -#include "../rtengine/rtengine.h" #include "paramsedited.h" #include "thumbnaillistener.h" +#include "toolpanelcoord.h" + +#include "../rtengine/procevents.h" +#include "../rtengine/procparams.h" class FilePanel; -class BatchToolPanelCoordinator : +class Thumbnail; +class BatchToolPanelCoordinator final : public ToolPanelCoordinator, public FileSelectionChangeListener, public BatchPParamsChangeListener, @@ -84,5 +85,3 @@ public: void optionsChanged (); }; - -#endif diff --git a/rtgui/bayerpreprocess.cc b/rtgui/bayerpreprocess.cc index 0ba60d045..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 diff --git a/rtgui/bayerpreprocess.h b/rtgui/bayerpreprocess.h index f50ac90bb..16b469626 100644 --- a/rtgui/bayerpreprocess.h +++ b/rtgui/bayerpreprocess.h @@ -14,17 +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 . */ -#ifndef _BAYERPREPROCESS_H_ -#define _BAYERPREPROCESS_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -#include "../rtengine/rawimage.h" -class BayerPreProcess : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class BayerPreProcess final : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { protected: @@ -54,5 +53,3 @@ public: void lineDenoiseDirectionChanged(); void pdafLinesFilterChanged(); }; - -#endif diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index 6f38f4c43..5b5cfe9c4 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" @@ -23,6 +23,7 @@ #include "options.h" #include "../rtengine/procparams.h" +#include "../rtengine/utils.h" using namespace rtengine; using namespace rtengine::procparams; @@ -671,7 +672,7 @@ void BayerProcess::checkBoxToggled (CheckBox* c, CheckValue newval) } } -void BayerProcess::adjusterAutoToggled(Adjuster* a, bool newval) +void BayerProcess::adjusterAutoToggled(Adjuster* a) { if (multiImage) { if (dualDemosaicContrast->getAutoInconsistent()) { @@ -729,7 +730,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..f8348e02b 100644 --- a/rtgui/bayerprocess.h +++ b/rtgui/bayerprocess.h @@ -14,18 +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 _BAYERPROCESS_H_ -#define _BAYERPROCESS_H_ +#pragma once #include + #include "adjuster.h" #include "checkbox.h" #include "guiutils.h" #include "toolpanel.h" -class BayerProcess : public ToolParamBlock, public AdjusterListener, public CheckBoxListener, public FoldableToolPanel, public rtengine::FrameCountListener, public rtengine::AutoContrastListener +class BayerProcess final : + public ToolParamBlock, + public AdjusterListener, + public CheckBoxListener, + public FoldableToolPanel, + public rtengine::FrameCountListener, + public rtengine::AutoContrastListener { protected: @@ -82,12 +88,10 @@ public: void methodChanged(); void imageNumberChanged(); void adjusterChanged(Adjuster* a, double newval) override; - void adjusterAutoToggled (Adjuster* a, bool newval) override; + void adjusterAutoToggled (Adjuster* a) override; void checkBoxToggled(CheckBox* c, CheckValue newval) override; void pixelShiftMotionMethodChanged(); void pixelShiftDemosaicMethodChanged(); void autoContrastChanged (double autoContrast) override; void FrameCountChanged(int n, int frameNum) override; }; - -#endif diff --git a/rtgui/bayerrawexposure.cc b/rtgui/bayerrawexposure.cc index 12158c774..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" diff --git a/rtgui/bayerrawexposure.h b/rtgui/bayerrawexposure.h index e955afc12..eb18aa0e3 100644 --- a/rtgui/bayerrawexposure.h +++ b/rtgui/bayerrawexposure.h @@ -14,28 +14,23 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include + #include "adjuster.h" #include "checkbox.h" #include "toolpanel.h" -class BayerRAWExposure : public ToolParamBlock, public AdjusterListener, public CheckBoxListener, public FoldableToolPanel +class BayerRAWExposure final : + public ToolParamBlock, + public AdjusterListener, + public CheckBoxListener, + public FoldableToolPanel { - -protected: - Adjuster* PexBlack0; - Adjuster* PexBlack1; - Adjuster* PexBlack2; - Adjuster* PexBlack3; - CheckBox* PextwoGreen; - public: - BayerRAWExposure (); void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; @@ -46,6 +41,11 @@ public: void checkBoxToggled (CheckBox* c, CheckValue newval) override; void setAdjusterBehavior (bool pexblackadd); void trimValues (rtengine::procparams::ProcParams* pp) override; -}; -#endif +protected: + Adjuster* PexBlack0; + Adjuster* PexBlack1; + Adjuster* PexBlack2; + Adjuster* PexBlack3; + CheckBox* PextwoGreen; +}; diff --git a/rtgui/blackwhite.cc b/rtgui/blackwhite.cc index 2b97188e2..596d99607 100644 --- a/rtgui/blackwhite.cc +++ b/rtgui/blackwhite.cc @@ -14,18 +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 #include #include "blackwhite.h" +#include "curveeditor.h" +#include "curveeditorgroup.h" #include "guiutils.h" #include "rtimage.h" +#include "options.h" #include "../rtengine/color.h" #include "../rtengine/procparams.h" +#include "../rtengine/utils.h" using namespace rtengine; using namespace rtengine::procparams; diff --git a/rtgui/blackwhite.h b/rtgui/blackwhite.h index 242926924..1aed86997 100644 --- a/rtgui/blackwhite.h +++ b/rtgui/blackwhite.h @@ -14,21 +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 . */ -#ifndef _BLACKWHITE_H_ -#define _BLACKWHITE_H_ +#pragma once #include -#include "adjuster.h" -#include "toolpanel.h" -#include "guiutils.h" -#include "curveeditor.h" -#include "curveeditorgroup.h" -#include "mycurve.h" -#include "colorprovider.h" +#include "adjuster.h" +#include "colorprovider.h" +#include "curvelistener.h" +#include "guiutils.h" +#include "toolpanel.h" + +class DiagonalCurveEditor; +class CurveEditorGroup; class EditDataProvider; +class FlatCurveEditor; class BlackWhite final : public ToolParamBlock, @@ -144,5 +145,3 @@ private: IdleRegister idle_register; }; - -#endif diff --git a/rtgui/bqentryupdater.cc b/rtgui/bqentryupdater.cc index f5adf56f9..61683e158 100644 --- a/rtgui/bqentryupdater.cc +++ b/rtgui/bqentryupdater.cc @@ -14,11 +14,29 @@ * GNU General Public License for more details. * * 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 + #include "guiutils.h" +#include "options.h" +#include "thumbnail.h" +#include "../rtengine/utils.h" + +namespace +{ + +void thumbInterp(const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh) +{ + + if (options.thumbInterp == 0) { + rtengine::nearestInterp (src, sw, sh, dst, dw, dh); + } else if (options.thumbInterp == 1) { + rtengine::bilinearInterp (src, sw, sh, dst, dw, dh); + } +} + +} BatchQueueEntryUpdater batchQueueEntryUpdater; @@ -27,7 +45,7 @@ BatchQueueEntryUpdater::BatchQueueEntryUpdater () { } -void BatchQueueEntryUpdater::process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener, rtengine::ProcParams* pparams, Thumbnail* thumbnail) +void BatchQueueEntryUpdater::process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener, rtengine::procparams::ProcParams* pparams, Thumbnail* thumbnail) { if (!oimg && (!pparams || !thumbnail)) { //printf("WARNING! !oimg && (!pparams || !thumbnail)\n"); @@ -100,13 +118,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..dfd42aff1 100644 --- a/rtgui/bqentryupdater.h +++ b/rtgui/bqentryupdater.h @@ -14,16 +14,26 @@ * GNU General Public License for more details. * * 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_ +#pragma once + +#include -#include -#include "../rtengine/rtengine.h" #include "threadutils.h" -#include "thumbnail.h" +class Thumbnail; + +namespace rtengine +{ +namespace procparams +{ + +class ProcParams; + +} + +} class BQEntryUpdateListener { @@ -39,7 +49,7 @@ class BatchQueueEntryUpdater guint8* oimg; int ow, oh, newh; BQEntryUpdateListener* listener; - rtengine::ProcParams* pparams; + rtengine::procparams::ProcParams* pparams; Thumbnail* thumbnail; }; @@ -53,7 +63,7 @@ protected: public: BatchQueueEntryUpdater (); - void process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener, rtengine::ProcParams* pparams = nullptr, Thumbnail* thumbnail = nullptr); + void process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener, rtengine::procparams::ProcParams* pparams = nullptr, Thumbnail* thumbnail = nullptr); void removeJobs (BQEntryUpdateListener* listener); void terminate (); @@ -61,5 +71,3 @@ public: }; extern BatchQueueEntryUpdater batchQueueEntryUpdater; - -#endif 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..df9a94c11 100644 --- a/rtgui/browserfilter.h +++ b/rtgui/browserfilter.h @@ -14,17 +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 . */ -#ifndef _BROWSERFILTER_ -#define _BROWSERFILTER_ +#pragma once + +#include #include "exiffiltersettings.h" -#include class BrowserFilter { - public: bool showRanked[6]; bool showCLabeled[6]; @@ -33,15 +32,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 (); }; - -#endif diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 1756f523b..d44ca28ec 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -14,15 +14,17 @@ * GNU General Public License for more details. * * 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 #include +#include #include "version.h" #include #include "../rtengine/procparams.h" +#include "../rtengine/settings.h" CacheImageData::CacheImageData() : supported(false), @@ -223,11 +225,11 @@ int CacheImageData::load (const Glib::ustring& fname) return 0; } } catch (Glib::Error &err) { - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { printf("CacheImageData::load / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str()); } } catch (...) { - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { printf("CacheImageData::load / Unknown exception while trying to load \"%s\"!\n", fname.c_str()); } } @@ -305,11 +307,11 @@ int CacheImageData::save (const Glib::ustring& fname) keyData = keyFile.to_data (); } catch (Glib::Error &err) { - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { printf("CacheImageData::save / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str()); } } catch (...) { - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { printf("CacheImageData::save / Unknown exception while trying to save \"%s\"!\n", fname.c_str()); } } @@ -321,7 +323,7 @@ int CacheImageData::save (const Glib::ustring& fname) FILE *f = g_fopen (fname.c_str (), "wt"); if (!f) { - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { printf("CacheImageData::save / Error: unable to open file \"%s\" with write access!\n", fname.c_str()); } diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index 9de9d186f..caab1de5b 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -14,19 +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 _CACHEIMAGEDATA_ -#define _CACHEIMAGEDATA_ +#pragma once + +#include -#include #include "options.h" -#include "../rtengine/rtengine.h" + #include "../rtengine/imageformat.h" +#include "../rtengine/rtengine.h" -class CacheImageData: public rtengine::FramesMetaData +class CacheImageData : + public rtengine::FramesMetaData { - public: // basic information @@ -115,4 +116,3 @@ public: std::string getImageType (unsigned int frame) const override { return isPixelShift ? "PS" : isHDR ? "HDR" : "STD"; } rtengine::IIOSampleFormat getSampleFormat (unsigned int frame = 0) const override { return sampleFormat; } }; -#endif diff --git a/rtgui/cachemanager.cc b/rtgui/cachemanager.cc index fbc6ae491..9a3fc9574 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 @@ -25,16 +25,16 @@ #include #ifdef WIN32 -#include +#include #endif #include "cachemanager.h" #include "guiutils.h" #include "options.h" -#include "procparamchangers.h" #include "thumbnail.h" -//#include "md5helper.h" +#include "procparamchangers.h" + namespace { @@ -64,8 +64,8 @@ void CacheManager::init () } } - if (error != 0 && options.rtSettings.verbose) { - std::cerr << "Failed to create all cache directories: " << g_strerror (errno) << std::endl; + if (error != 0 && rtengine::settings->verbose) { + std::cerr << "Failed to create all cache directories: " << g_strerror(errno) << std::endl; } } @@ -197,8 +197,8 @@ void CacheManager::renameEntry (const std::string& oldfilename, const std::strin error |= g_rename (getCacheFileName ("embprofiles", oldfilename, ".icc", oldmd5).c_str (), getCacheFileName ("embprofiles", newfilename, ".icc", newmd5).c_str ()); error |= g_rename (getCacheFileName ("data", oldfilename, ".txt", oldmd5).c_str (), getCacheFileName ("data", newfilename, ".txt", newmd5).c_str ()); - if (error != 0 && options.rtSettings.verbose) { - std::cerr << "Failed to rename all files for cache entry '" << oldfilename << "': " << g_strerror (errno) << std::endl; + if (error != 0 && rtengine::settings->verbose) { + std::cerr << "Failed to rename all files for cache entry '" << oldfilename << "': " << g_strerror(errno) << std::endl; } // check if it is opened @@ -273,8 +273,8 @@ void CacheManager::deleteDir (const Glib::ustring& dirName) const error |= g_remove (Glib::build_filename (baseDir, dirName, *entry).c_str ()); } - if (error != 0 && options.rtSettings.verbose) { - std::cerr << "Failed to delete all entries in cache directory '" << dirName << "': " << g_strerror (errno) << std::endl; + if (error != 0 && rtengine::settings->verbose) { + std::cerr << "Failed to delete all entries in cache directory '" << dirName << "': " << g_strerror(errno) << std::endl; } } catch (Glib::Error&) {} @@ -296,7 +296,10 @@ void CacheManager::deleteFiles (const Glib::ustring& fname, const std::string& m if (purgeProfile) { error |= g_remove (getCacheFileName ("profiles", fname, paramFileExtension, md5).c_str ()); + } + if (error != 0 && rtengine::settings->verbose) { + std::cerr << "Failed to delete all files for cache entry '" << fname << "': " << g_strerror(errno) << std::endl; } } diff --git a/rtgui/cachemanager.h b/rtgui/cachemanager.h index 574617808..61602aeba 100644 --- a/rtgui/cachemanager.h +++ b/rtgui/cachemanager.h @@ -14,20 +14,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 . */ -#ifndef _CACHEMANAGER_ -#define _CACHEMANAGER_ +#pragma once -#include #include +#include #include -#include "../rtengine/noncopyable.h" - #include "threadutils.h" +#include "../rtengine/noncopyable.h" + class Thumbnail; class CacheManager : @@ -69,6 +68,3 @@ public: }; #define cacheMgr CacheManager::getInstance() - -#endif - diff --git a/rtgui/cacorrection.cc b/rtgui/cacorrection.cc index 5b66dd6c3..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 diff --git a/rtgui/cacorrection.h b/rtgui/cacorrection.h index 4fa85038c..12d6396eb 100644 --- a/rtgui/cacorrection.h +++ b/rtgui/cacorrection.h @@ -14,16 +14,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 . */ -#ifndef _CACORRECTION_H_ -#define _CACORRECTION_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -class CACorrection : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class CACorrection final: + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -43,5 +46,3 @@ public: void setAdjusterBehavior (bool badd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; - -#endif 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..45433300c 100644 --- a/rtgui/checkbox.h +++ b/rtgui/checkbox.h @@ -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 . */ -#ifndef _CHECKBOX_H_ -#define _CHECKBOX_H_ +#pragma once #include + #include "editedstate.h" #include "guiutils.h" @@ -72,5 +72,3 @@ public: void set_tooltip_markup (const Glib::ustring& tooltip); */ }; - -#endif diff --git a/rtgui/chmixer.cc b/rtgui/chmixer.cc index 82e885f08..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" diff --git a/rtgui/chmixer.h b/rtgui/chmixer.h index a0fff9b26..d80b89cf7 100644 --- a/rtgui/chmixer.h +++ b/rtgui/chmixer.h @@ -14,16 +14,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 . */ -#ifndef _CHMIXER_H_ -#define _CHMIXER_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -class ChMixer : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class ChMixer final: + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -46,5 +49,3 @@ public: void trimValues (rtengine::procparams::ProcParams* pp) override; void enabledChanged() override; }; - -#endif diff --git a/rtgui/clipboard.cc b/rtgui/clipboard.cc index c8eb94d7b..f64f2ed07 100644 --- a/rtgui/clipboard.cc +++ b/rtgui/clipboard.cc @@ -14,10 +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 . */ #include "clipboard.h" +#include "paramsedited.h" #include "../rtengine/procparams.h" Clipboard clipboard; diff --git a/rtgui/clipboard.h b/rtgui/clipboard.h index 74c9f6770..0a1c8e2fa 100644 --- a/rtgui/clipboard.h +++ b/rtgui/clipboard.h @@ -14,27 +14,26 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include #include -#include "mydiagonalcurve.h" -#include "myflatcurve.h" -#include "paramsedited.h" +#include "../rtengine/diagonalcurvetypes.h" +#include "../rtengine/flatcurvetypes.h" -#include "../rtengine/rtengine.h" +struct ParamsEdited; namespace rtengine { namespace procparams { - +class ProcParams; class PartialProfile; +class IPTCPairs; } @@ -80,5 +79,3 @@ private: }; extern Clipboard clipboard; - -#endif 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..b7b4f8cf7 100644 --- a/rtgui/coarsepanel.h +++ b/rtgui/coarsepanel.h @@ -14,15 +14,17 @@ * GNU General Public License for more details. * * 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__ +#pragma once #include + #include "toolpanel.h" -class CoarsePanel : public Gtk::HBox, public ToolPanel +class CoarsePanel final : + public Gtk::HBox, + public ToolPanel { protected: @@ -46,5 +48,3 @@ public: void flipHorizontal (); void flipVertical (); }; - -#endif diff --git a/rtgui/colorappearance.cc b/rtgui/colorappearance.cc index f78a1f32b..62f6eee2c 100644 --- a/rtgui/colorappearance.cc +++ b/rtgui/colorappearance.cc @@ -14,16 +14,21 @@ * GNU General Public License for more details. * * 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 "colorappearance.h" +#include "curveeditor.h" +#include "curveeditorgroup.h" #include "guiutils.h" +#include "options.h" +#include "rtimage.h" #include "../rtengine/color.h" #include "../rtengine/procparams.h" +#include "../rtengine/utils.h" #define MINTEMP0 2000 //1200 #define MAXTEMP0 12000 //12000 @@ -1560,7 +1565,7 @@ void ColorAppearance::adjusterChanged(Adjuster* a, double newval) } } -void ColorAppearance::adjusterAutoToggled(Adjuster* a, bool newval) +void ColorAppearance::adjusterAutoToggled(Adjuster* a) { if (multiImage) { if (degree->getAutoInconsistent()) { diff --git a/rtgui/colorappearance.h b/rtgui/colorappearance.h index 3f95d9f74..c42bca774 100644 --- a/rtgui/colorappearance.h +++ b/rtgui/colorappearance.h @@ -14,27 +14,29 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include + #include "adjuster.h" -#include "toolpanel.h" -#include "curveeditor.h" -#include "curveeditorgroup.h" -#include "mycurve.h" -#include "guiutils.h" #include "colorprovider.h" +#include "curvelistener.h" +#include "guiutils.h" +#include "toolpanel.h" + +class DiagonalCurveEditor; +class CurveEditorGroup; +class CurveEditor; class ColorAppearance final : - public ToolParamBlock, - public AdjusterListener, - public FoldableToolPanel, - public rtengine::AutoCamListener, - public CurveListener, - public ColorProvider + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public rtengine::AutoCamListener, + public CurveListener, + public ColorProvider { public: ColorAppearance (); @@ -45,7 +47,7 @@ public: 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 adjusterAutoToggled (Adjuster* a, bool newval) override; + void adjusterAutoToggled (Adjuster* a) override; // void adjusterAdapToggled (Adjuster* a, bool newval); void enabledChanged () override; void surroundChanged (); @@ -173,5 +175,3 @@ private: IdleRegister idle_register; }; - -#endif diff --git a/rtgui/coloredbar.cc b/rtgui/coloredbar.cc index 7d623949e..adafcbdde 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" @@ -142,7 +142,7 @@ void ColoredBar::updateBackBuffer(Gtk::DrawingArea &drawingArea) case (RTO_Left2Right): for (int py = 0; py < h; ++py) { for (int px = 0; px < w; ++px) { - unsigned char *pixel = surfaceData + (py * w + px) * 4; + unsigned char *pixel = surfaceData + (py * w + px) * 4; double x_ = double( px); //double y_ = double((h-1)-py); unused double x01 = x_ / double(w - 1); @@ -158,7 +158,7 @@ void ColoredBar::updateBackBuffer(Gtk::DrawingArea &drawingArea) case (RTO_Right2Left): for (int py = 0; py < h; ++py) { for (int px = 0; px < w; ++px) { - unsigned char *pixel = surfaceData + (py * w + px) * 4; + unsigned char *pixel = surfaceData + (py * w + px) * 4; //double x_ = double((w-1)-px); unused //double y_ = double((h-1)-py); unused double x01 = double(px) / double(w - 1); @@ -174,7 +174,7 @@ void ColoredBar::updateBackBuffer(Gtk::DrawingArea &drawingArea) case (RTO_Bottom2Top): for (int py = 0; py < h; ++py) { for (int px = 0; px < w; ++px) { - unsigned char *pixel = surfaceData + (py * w + px) * 4; + unsigned char *pixel = surfaceData + (py * w + px) * 4; //double x_ = double((w-1)-px); unused //double y_ = double((h-1)-py); unused double x01 = double(px) / double(w - 1); @@ -191,7 +191,7 @@ void ColoredBar::updateBackBuffer(Gtk::DrawingArea &drawingArea) default: for (int py = 0; py < h; ++py) { for (int px = 0; px < w; ++px) { - unsigned char *pixel = surfaceData + (py * w + px) * 4; + unsigned char *pixel = surfaceData + (py * w + px) * 4; double x_ = double( px); double y_ = double( py); double x01 = x_ / double(w - 1); diff --git a/rtgui/coloredbar.h b/rtgui/coloredbar.h index 010d0dcb6..69cfa47d1 100644 --- a/rtgui/coloredbar.h +++ b/rtgui/coloredbar.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 _COLOREDBAR_ -#define _COLOREDBAR_ +#pragma once #include "colorprovider.h" #include "guiutils.h" @@ -31,7 +30,7 @@ * the bar itself, i.e. use render_background (depending on its Gtk::Style) * */ -class ColoredBar : private BackBuffer, public ColorCaller +class ColoredBar final : private BackBuffer, public ColorCaller { private: @@ -62,5 +61,3 @@ public: BackBuffer::setDirty(isDirty); } }; - -#endif diff --git a/rtgui/colorprovider.h b/rtgui/colorprovider.h index ab6fb2865..988b080bd 100644 --- a/rtgui/colorprovider.h +++ b/rtgui/colorprovider.h @@ -14,12 +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 _COLORPROVIDER_ -#define _COLORPROVIDER_ - -#include +#pragma once class ColorProvider; @@ -61,10 +58,7 @@ public: */ class ColorProvider { - public: - virtual ~ColorProvider() {}; + virtual ~ColorProvider() = default; virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) {}; }; - -#endif diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index e164739e5..59768a6ce 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -2,10 +2,14 @@ * This file is part of RawTherapee. */ #include "colortoning.h" +#include "curveeditor.h" +#include "curveeditorgroup.h" #include "mycurve.h" #include "rtimage.h" #include "eventmapper.h" #include "labgrid.h" +#include "options.h" +#include "../rtengine/color.h" using namespace rtengine; using namespace rtengine::procparams; diff --git a/rtgui/colortoning.h b/rtgui/colortoning.h index faba1e383..f1024f41c 100644 --- a/rtgui/colortoning.h +++ b/rtgui/colortoning.h @@ -1,20 +1,25 @@ /* * This file is part of RawTherapee. */ -#ifndef _COLORTONING_H_ -#define _COLORTONING_H_ +#pragma once #include + #include "adjuster.h" -#include "toolpanel.h" -#include "guiutils.h" -#include "curveeditor.h" -#include "curveeditorgroup.h" -#include "thresholdadjuster.h" #include "colorprovider.h" -#include "labgrid.h" +#include "curvelistener.h" +#include "guiutils.h" +#include "thresholdadjuster.h" +#include "toolpanel.h" + #include "../rtengine/procparams.h" +class CurveEditor; +class CurveEditorGroup; +class DiagonalCurveEditor; +class FlatCurveEditor; +class LabGrid; + class ColorToning final : public ToolParamBlock, public FoldableToolPanel, @@ -166,5 +171,3 @@ private: IdleRegister idle_register; }; - -#endif 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/controlspotpanel.cc b/rtgui/controlspotpanel.cc index 5423be38f..9ebd1b82f 100644 --- a/rtgui/controlspotpanel.cc +++ b/rtgui/controlspotpanel.cc @@ -20,11 +20,10 @@ #include "../rtengine/rt_math.h" #include "controlspotpanel.h" -#include "multilangmgr.h" -#include #include "editwidgets.h" #include "options.h" #include "../rtengine/procparams.h" +#include "rtimage.h" using namespace rtengine; using namespace procparams; @@ -53,11 +52,11 @@ ControlSpotPanel::ControlSpotPanel(): spotMethod_(Gtk::manage(new MyComboBoxText())), shapeMethod_(Gtk::manage(new MyComboBoxText())), qualityMethod_(Gtk::manage(new MyComboBoxText())), + complexMethod_(Gtk::manage(new MyComboBoxText())), + wavMethod_(Gtk::manage(new MyComboBoxText())), sensiexclu_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIEXCLU"), 0, 100, 1, 12))), structexclu_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRUCCOL"), 0, 100, 1, 0))), - - struc_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_THRES"), 1.0, 12.0, 0.1, 4.0))), locX_(Gtk::manage(new Adjuster(M("TP_LOCAL_WIDTH"), 2, 3000, 1, 150))), locXL_(Gtk::manage(new Adjuster(M("TP_LOCAL_WIDTH_L"), 2, 3000, 1, 150))), locY_(Gtk::manage(new Adjuster(M("TP_LOCAL_HEIGHT"), 2, 3000, 1, 150))), @@ -65,14 +64,25 @@ ControlSpotPanel::ControlSpotPanel(): centerX_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CENTER_X"), -1000, 1000, 1, 0))), centerY_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CENTER_Y"), -1000, 1000, 1, 0))), circrad_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CIRCRADIUS"), 2, 150, 1, 18))), - transit_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_TRANSITVALUE"), 5, 95, 1, 60))), + transit_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_TRANSITVALUE"), 2., 100., 0.1, 60.))), + transitweak_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_TRANSITWEAK"), 0.5, 15.0, 0.1, 1.0))), + transitgrad_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_TRANSITGRAD"), -1.0, 1.0, 0.01, 0.0))), + feather_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FEATVALUE"), 10., 100., 0.1, 25.))), + struc_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_THRES"), 1.0, 12.0, 0.1, 4.0))), thresh_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_THRESDELTAE"), 0.0, 10.0, 0.1, 2.0))), iter_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_PROXI"), 0.2, 10.0, 0.1, 2.0))), - balan_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BALAN"), 0.2, 2.5, 0.1, 1.0, Gtk::manage(new RTImage("rawtherapee-logo-16.png")), Gtk::manage(new RTImage("circle-white-small.png"))))), - transitweak_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_TRANSITWEAK"), 0.5, 8.0, 0.1, 1.0))), - transitgrad_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_TRANSITGRAD"), -1.0, 1.0, 0.01, 0.0))), + balan_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BALAN"), 0.2, 2.5, 0.1, 1.0, Gtk::manage(new RTImage("rawtherapee-logo-16.png")), Gtk::manage(new RTImage("circle-white-small.png"))))), + balanh_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BALANH"), 0.2, 2.5, 0.1, 1.0, Gtk::manage(new RTImage("rawtherapee-logo-16.png")), Gtk::manage(new RTImage("circle-red-green-small.png"))))), + colorde_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_COLORDE"), -15, 15, 2, 5, Gtk::manage(new RTImage("circle-blue-yellow-small.png")), Gtk::manage(new RTImage("circle-gray-green-small.png"))))), + scopemask_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SCOPEMASK"), 0, 100, 1, 60))), + lumask_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LUMASK"), 0, 30, 1, 10))), avoid_(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_AVOID")))), + recurs_(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_RECURS")))), + laplac_(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_LAPLACC")))), + deltae_(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_DELTAEC")))), + shortc_(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_SHORTC")))), + savrest_(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_SAVREST")))), lastObject_(-1), nbSpotChanged_(false), @@ -84,6 +94,7 @@ ControlSpotPanel::ControlSpotPanel(): maskPrevActive(false) { const bool showtooltip = options.showtooltip; + const int complexsoft = options.complexity; Gtk::HBox* const hbox1_ = Gtk::manage(new Gtk::HBox(true, 4)); buttonaddconn_ = button_add_->signal_clicked().connect( @@ -214,7 +225,10 @@ ControlSpotPanel::ControlSpotPanel(): sigc::mem_fun( *this, &ControlSpotPanel::shapeMethodChanged)); ctboxshapemethod->pack_start(*shapeMethod_); - pack_start(*ctboxshapemethod); + + if (complexsoft < 2) { + pack_start(*ctboxshapemethod); + } pack_start(*locX_); locX_->setAdjusterListener(this); @@ -252,7 +266,10 @@ ControlSpotPanel::ControlSpotPanel(): sigc::mem_fun( *this, &ControlSpotPanel::qualityMethodChanged)); ctboxqualitymethod->pack_start(*qualityMethod_); - pack_start(*ctboxqualitymethod); + + if (complexsoft < 2) { + pack_start(*ctboxqualitymethod); + } Gtk::Frame* const transitFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_TRANSIT"))); transitFrame->set_label_align(0.025, 0.5); @@ -271,17 +288,34 @@ ControlSpotPanel::ControlSpotPanel(): transitweak_->set_tooltip_text(M("TP_LOCALLAB_TRANSITWEAK_TOOLTIP")); } + if (showtooltip) { + feather_->set_tooltip_text(M("TP_LOCALLAB_FEATH_TOOLTIP")); + } + if (showtooltip) { transitgrad_->set_tooltip_text(M("TP_LOCALLAB_TRANSITGRAD_TOOLTIP")); } + if (showtooltip) { + scopemask_->set_tooltip_text(M("TP_LOCALLAB_SCOPEMASK_TOOLTIP")); + } + transit_->setAdjusterListener(this); transitweak_->setAdjusterListener(this); transitgrad_->setAdjusterListener(this); - + feather_->setAdjusterListener(this); + scopemask_->setAdjusterListener(this); transitBox->pack_start(*transit_); - transitBox->pack_start(*transitweak_); - transitBox->pack_start(*transitgrad_); + + if (complexsoft < 2) { + transitBox->pack_start(*transitweak_); + } + + if (complexsoft < 2) { + transitBox->pack_start(*transitgrad_); + } + + transitBox->pack_start(*feather_); transitFrame->add(*transitBox); pack_start(*transitFrame); @@ -293,21 +327,132 @@ ControlSpotPanel::ControlSpotPanel(): } ToolParamBlock* const artifBox = Gtk::manage(new ToolParamBlock()); - thresh_->setAdjusterListener(this); struc_->setAdjusterListener(this); - artifBox->pack_start(*struc_); - artifBox->pack_start(*thresh_); - artifBox->pack_start(*iter_); - artifBox->pack_start(*balan_); + thresh_->setAdjusterListener(this); iter_->setAdjusterListener(this); balan_->setAdjusterListener(this); + balanh_->setAdjusterListener(this); + colorde_->setAdjusterListener(this); + + if (showtooltip) { + balan_->set_tooltip_text(M("TP_LOCALLAB_BALAN_TOOLTIP")); + balanh_->set_tooltip_text(M("TP_LOCALLAB_BALAN_TOOLTIP")); + colorde_->set_tooltip_text(M("TP_LOCALLAB_COLORDE_TOOLTIP")); + } + + if (complexsoft < 2) { + artifBox->pack_start(*struc_); + } + + if (complexsoft < 2) { + artifBox->pack_start(*thresh_); + } + + artifBox->pack_start(*iter_); + artifBox->pack_start(*balan_); + artifBox->pack_start(*balanh_); + artifBox->pack_start(*colorde_); artifFrame->add(*artifBox); pack_start(*artifFrame); - + avoidConn_ = avoid_->signal_toggled().connect( sigc::mem_fun(*this, &ControlSpotPanel::avoidChanged)); pack_start(*avoid_); + recursConn_ = recurs_->signal_toggled().connect( + sigc::mem_fun(*this, &ControlSpotPanel::recursChanged)); + + if (showtooltip) { + recurs_->set_tooltip_text(M("TP_LOCALLAB_RECURS_TOOLTIP")); + } + + pack_start(*recurs_); + + Gtk::Frame* const maskFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_MASFRAME"))); + maskFrame->set_label_align(0.025, 0.5); + + if (showtooltip) { + maskFrame->set_tooltip_text(M("TP_LOCALLAB_MASFRAME_TOOLTIP")); + } + + ToolParamBlock* const maskBox = Gtk::manage(new ToolParamBlock()); + laplacConn_ = laplac_->signal_toggled().connect( + sigc::mem_fun(*this, &ControlSpotPanel::laplacChanged)); + deltaeConn_ = deltae_->signal_toggled().connect( + sigc::mem_fun(*this, &ControlSpotPanel::deltaeChanged)); + shortcConn_ = shortc_->signal_toggled().connect( + sigc::mem_fun(*this, &ControlSpotPanel::shortcChanged)); + + if (showtooltip) { + shortc_->set_tooltip_text(M("TP_LOCALLAB_SHORTCMASK_TOOLTIP")); + } + + lumask_->setAdjusterListener(this); + savrestConn_ = savrest_->signal_toggled().connect( + sigc::mem_fun(*this, &ControlSpotPanel::savrestChanged)); + + if (showtooltip) { + savrest_->set_tooltip_text(M("TP_LOCALLAB_SAVREST_TOOLTIP")); + } + + if (complexsoft < 1) { + maskBox->pack_start(*laplac_); + } + + maskBox->pack_start(*deltae_); + maskBox->pack_start(*scopemask_); + // maskBox->pack_start(*shortc_); + maskBox->pack_start(*lumask_); + // maskBox->pack_start(*savrest_); + maskFrame->add(*maskBox); + pack_start(*maskFrame); + + Gtk::HSeparator *separatormet = Gtk::manage(new Gtk::HSeparator()); + pack_start(*separatormet, Gtk::PACK_SHRINK, 2); + + Gtk::HBox* const ctboxcomplexmethod = Gtk::manage(new Gtk::HBox()); + + if (showtooltip) { + ctboxcomplexmethod->set_tooltip_markup(M("TP_LOCALLAB_COMPLEXMETHOD_TOOLTIP")); + } + + Gtk::Label* const labelcomplexmethod = Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_COMPLEX_METHOD") + ":")); + ctboxcomplexmethod->pack_start(*labelcomplexmethod, Gtk::PACK_SHRINK, 4); + + if (showtooltip) { + complexMethod_->set_tooltip_markup(M("TP_LOCALLAB_COMPLEX_TOOLTIP")); + } + + complexMethod_->append(M("TP_LOCALLAB_SIM")); + complexMethod_->append(M("TP_LOCALLAB_MED")); + complexMethod_->append(M("TP_LOCALLAB_ALL")); + complexMethod_->set_active(1); + complexMethodconn_ = complexMethod_->signal_changed().connect( + sigc::mem_fun( + *this, &ControlSpotPanel::complexMethodChanged)); + ctboxcomplexmethod->pack_start(*complexMethod_); + // pack_start(*ctboxcomplexmethod); + + Gtk::HBox* const ctboxwavmethod = Gtk::manage(new Gtk::HBox()); + Gtk::Label* const labelwavmethod = Gtk::manage(new Gtk::Label(M("TP_WAVELET_DAUBLOCAL") + ":")); + ctboxwavmethod->pack_start(*labelwavmethod, Gtk::PACK_SHRINK, 4); + + if (showtooltip) { + ctboxwavmethod->set_tooltip_markup(M("TP_WAVELET_DAUB_TOOLTIP")); + } + + wavMethod_->append(M("TP_WAVELET_DAUB2")); + wavMethod_->append(M("TP_WAVELET_DAUB4")); + wavMethod_->append(M("TP_WAVELET_DAUB6")); + wavMethod_->append(M("TP_WAVELET_DAUB10")); + wavMethod_->append(M("TP_WAVELET_DAUB14")); + wavMethod_->set_active(1); + wavMethodconn_ = wavMethod_->signal_changed().connect( + sigc::mem_fun( + *this, &ControlSpotPanel::wavMethodChanged)); + ctboxwavmethod->pack_start(*wavMethod_); + pack_start(*ctboxwavmethod); + show_all(); // Define row background color @@ -577,7 +722,6 @@ void ControlSpotPanel::load_ControlSpot_param() spotMethod_->set_active(row[spots_.spotMethod]); sensiexclu_->setValue((double)row[spots_.sensiexclu]); structexclu_->setValue((double)row[spots_.structexclu]); - struc_->setValue((double)row[spots_.struc]); shapeMethod_->set_active(row[spots_.shapeMethod]); locX_->setValue((double)row[spots_.locX]); locXL_->setValue((double)row[spots_.locXL]); @@ -588,12 +732,25 @@ void ControlSpotPanel::load_ControlSpot_param() circrad_->setValue((double)row[spots_.circrad]); qualityMethod_->set_active(row[spots_.qualityMethod]); transit_->setValue((double)row[spots_.transit]); + transitweak_->setValue((double)row[spots_.transitweak]); + transitgrad_->setValue((double)row[spots_.transitgrad]); + feather_->setValue((double)row[spots_.feather]); + struc_->setValue((double)row[spots_.struc]); thresh_->setValue((double)row[spots_.thresh]); iter_->setValue((double)row[spots_.iter]); balan_->setValue((double)row[spots_.balan]); - transitweak_->setValue((double)row[spots_.transitweak]); - transitgrad_->setValue((double)row[spots_.transitgrad]); + balanh_->setValue((double)row[spots_.balanh]); + colorde_->setValue((double)row[spots_.colorde]); avoid_->set_active(row[spots_.avoid]); + recurs_->set_active(row[spots_.recurs]); + laplac_->set_active(row[spots_.laplac]); + deltae_->set_active(row[spots_.deltae]); + scopemask_->setValue((double)row[spots_.scopemask]); + shortc_->set_active(row[spots_.shortc]); + lumask_->setValue((double)row[spots_.lumask]); + savrest_->set_active(row[spots_.savrest]); + complexMethod_->set_active(row[spots_.complexMethod]); + wavMethod_->set_active(row[spots_.wavMethod]); } void ControlSpotPanel::controlspotChanged() @@ -773,6 +930,60 @@ void ControlSpotPanel::qualityMethodChanged() } } +void ControlSpotPanel::complexMethodChanged() +{ + // printf("qualityMethodChanged\n"); + + // Get selected control spot + const auto s = treeview_->get_selection(); + + if (!s->count_selected_rows()) { + return; + } + + const auto iter = s->get_selected(); + Gtk::TreeModel::Row row = *iter; + + row[spots_.complexMethod] = complexMethod_->get_active_row_number(); + + if (multiImage && complexMethod_->get_active_text() == M("GENERAL_UNCHANGED")) { + // excluFrame->show(); + } else if (complexMethod_->get_active_row_number() == 0) { //sim + // excluFrame->hide(); + } else if (complexMethod_->get_active_row_number() == 1) { // mod + // excluFrame->show(); + } else if (complexMethod_->get_active_row_number() == 2) { // all + // excluFrame->show(); + } + + // Raise event + if (listener) { + listener->panelChanged(EvLocallabSpotcomplexMethod, complexMethod_->get_active_text()); + } +} + +void ControlSpotPanel::wavMethodChanged() +{ + // printf("qualityMethodChanged\n"); + + // Get selected control spot + const auto s = treeview_->get_selection(); + + if (!s->count_selected_rows()) { + return; + } + + const auto iter = s->get_selected(); + Gtk::TreeModel::Row row = *iter; + + row[spots_.wavMethod] = wavMethod_->get_active_row_number(); + + // Raise event + if (listener) { + listener->panelChanged(EvLocallabSpotwavMethod, wavMethod_->get_active_text()); + } +} + void ControlSpotPanel::updateParamVisibility() { // printf("updateParamVisibility\n"); @@ -864,14 +1075,6 @@ void ControlSpotPanel::adjusterChanged(Adjuster* a, double newval) } } - if (a == struc_) { - row[spots_.struc] = struc_->getValue(); - - if (listener) { - listener->panelChanged(EvLocallabSpotStruc, struc_->getTextValue()); - } - } - if (a == locX_) { row[spots_.locX] = locX_->getIntValue(); @@ -962,13 +1165,44 @@ void ControlSpotPanel::adjusterChanged(Adjuster* a, double newval) } if (a == transit_) { - row[spots_.transit] = transit_->getIntValue(); + row[spots_.transit] = transit_->getValue(); if (listener) { listener->panelChanged(EvLocallabSpotTransit, transit_->getTextValue()); } } + if (a == transitweak_) { + row[spots_.transitweak] = transitweak_->getValue(); + + if (listener) { + listener->panelChanged(EvLocallabSpotTransitweak, transitweak_->getTextValue()); + } + } + + if (a == transitgrad_) { + row[spots_.transitgrad] = transitgrad_->getValue(); + + if (listener) { + listener->panelChanged(EvLocallabSpotTransitgrad, transitgrad_->getTextValue()); + } + } + + if (a == feather_) { + row[spots_.feather] = feather_->getValue(); + + if (listener) { + listener->panelChanged(EvLocallabSpotfeather, feather_->getTextValue()); + } + } + + if (a == struc_) { + row[spots_.struc] = struc_->getValue(); + + if (listener) { + listener->panelChanged(EvLocallabSpotStruc, struc_->getTextValue()); + } + } if (a == thresh_) { row[spots_.thresh] = thresh_->getValue(); @@ -994,22 +1228,37 @@ void ControlSpotPanel::adjusterChanged(Adjuster* a, double newval) } } - if (a == transitweak_) { - row[spots_.transitweak] = transitweak_->getValue(); + if (a == balanh_) { + row[spots_.balanh] = balanh_->getValue(); if (listener) { - listener->panelChanged(EvLocallabSpotTransitweak, transitweak_->getTextValue()); + listener->panelChanged(EvLocallabSpotbalanh, balanh_->getTextValue()); } } - if (a == transitgrad_) { - row[spots_.transitgrad] = transitgrad_->getValue(); + if (a == colorde_) { + row[spots_.colorde] = colorde_->getValue(); if (listener) { - listener->panelChanged(EvLocallabSpotTransitgrad, transitgrad_->getTextValue()); + listener->panelChanged(EvLocallabSpotcolorde, colorde_->getTextValue()); } } + if (a == scopemask_) { + row[spots_.scopemask] = scopemask_->getIntValue(); + + if (listener) { + listener->panelChanged(EvLocallabSpotscopemask, scopemask_->getTextValue()); + } + } + + if (a == lumask_) { + row[spots_.lumask] = lumask_->getIntValue(); + + if (listener) { + listener->panelChanged(EvLocallabSpotlumask, lumask_->getTextValue()); + } + } } void ControlSpotPanel::avoidChanged() @@ -1025,16 +1274,6 @@ void ControlSpotPanel::avoidChanged() const auto iter = s->get_selected(); Gtk::TreeModel::Row row = *iter; - - if (multiImage) { - if (avoid_->get_inconsistent()) { - avoid_->set_inconsistent(false); - avoidConn_.block(true); - avoid_->set_active(false); - avoidConn_.block(false); - } - } - row[spots_.avoid] = avoid_->get_active(); // Raise event @@ -1047,6 +1286,132 @@ void ControlSpotPanel::avoidChanged() } } +void ControlSpotPanel::recursChanged() +{ + // printf("recursChanged\n"); + + // Get selected control spot + const auto s = treeview_->get_selection(); + + if (!s->count_selected_rows()) { + return; + } + + const auto iter = s->get_selected(); + Gtk::TreeModel::Row row = *iter; + row[spots_.recurs] = recurs_->get_active(); + + // Raise event + if (listener) { + if (recurs_->get_active()) { + listener->panelChanged(Evlocallabrecurs, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(Evlocallabrecurs, M("GENERAL_DISABLED")); + } + } +} + + +void ControlSpotPanel::laplacChanged() +{ + // printf("laplacChanged\n"); + + // Get selected control spot + const auto s = treeview_->get_selection(); + + if (!s->count_selected_rows()) { + return; + } + + const auto iter = s->get_selected(); + Gtk::TreeModel::Row row = *iter; + row[spots_.laplac] = laplac_->get_active(); + + // Raise event + if (listener) { + if (laplac_->get_active()) { + listener->panelChanged(Evlocallablaplac, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(Evlocallablaplac, M("GENERAL_DISABLED")); + } + } +} + + +void ControlSpotPanel::deltaeChanged() +{ + // printf("laplacChanged\n"); + + // Get selected control spot + const auto s = treeview_->get_selection(); + + if (!s->count_selected_rows()) { + return; + } + + const auto iter = s->get_selected(); + Gtk::TreeModel::Row row = *iter; + row[spots_.deltae] = deltae_->get_active(); + + // Raise event + if (listener) { + if (deltae_->get_active()) { + listener->panelChanged(Evlocallabdeltae, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(Evlocallabdeltae, M("GENERAL_DISABLED")); + } + } +} + +void ControlSpotPanel::shortcChanged() +{ + + // Get selected control spot + const auto s = treeview_->get_selection(); + + if (!s->count_selected_rows()) { + return; + } + + const auto iter = s->get_selected(); + Gtk::TreeModel::Row row = *iter; + row[spots_.shortc] = shortc_->get_active(); + + // Raise event + if (listener) { + if (shortc_->get_active()) { + listener->panelChanged(Evlocallabshortc, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(Evlocallabshortc, M("GENERAL_DISABLED")); + } + } +} + +void ControlSpotPanel::savrestChanged() +{ + + // Get selected control spot + const auto s = treeview_->get_selection(); + + if (!s->count_selected_rows()) { + return; + } + + const auto iter = s->get_selected(); + Gtk::TreeModel::Row row = *iter; + row[spots_.savrest] = savrest_->get_active(); + + // Raise event + if (listener) { + if (savrest_->get_active()) { + listener->panelChanged(Evlocallabsavrest, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(Evlocallabsavrest, M("GENERAL_DISABLED")); + } + } +} + + void ControlSpotPanel::disableParamlistener(bool cond) { // printf("disableParamlistener: %d\n", cond); @@ -1061,7 +1426,6 @@ void ControlSpotPanel::disableParamlistener(bool cond) spotMethodconn_.block(cond); sensiexclu_->block(cond); structexclu_->block(cond); - struc_->block(cond); shapeMethodconn_.block(cond); locX_->block(cond); locXL_->block(cond); @@ -1072,12 +1436,25 @@ void ControlSpotPanel::disableParamlistener(bool cond) circrad_->block(cond); qualityMethodconn_.block(cond); transit_->block(cond); + transitweak_->block(cond); + transitgrad_->block(cond); + feather_->block(cond); + struc_->block(cond); thresh_->block(cond); iter_->block(cond); balan_->block(cond); - transitweak_->block(cond); - transitgrad_->block(cond); + balanh_->block(cond); + colorde_->block(cond); avoidConn_.block(cond); + recursConn_.block(cond); + laplacConn_.block(cond); + deltaeConn_.block(cond); + scopemask_->block(cond); + shortcConn_.block(cond); + lumask_->block(cond); + savrestConn_.block(cond); + complexMethodconn_.block(cond); + wavMethodconn_.block(cond); } void ControlSpotPanel::setParamEditable(bool cond) @@ -1088,7 +1465,6 @@ void ControlSpotPanel::setParamEditable(bool cond) spotMethod_->set_sensitive(cond); sensiexclu_->set_sensitive(cond); structexclu_->set_sensitive(cond); - struc_->set_sensitive(cond); shapeMethod_->set_sensitive(cond); locX_->set_sensitive(cond); locXL_->set_sensitive(cond); @@ -1099,12 +1475,25 @@ void ControlSpotPanel::setParamEditable(bool cond) circrad_->set_sensitive(cond); qualityMethod_->set_sensitive(cond); transit_->set_sensitive(cond); + transitweak_->set_sensitive(cond); + transitgrad_->set_sensitive(cond); + feather_->set_sensitive(cond); + struc_->set_sensitive(cond); thresh_->set_sensitive(cond); iter_->set_sensitive(cond); balan_->set_sensitive(cond); - transitweak_->set_sensitive(cond); - transitgrad_->set_sensitive(cond); + balanh_->set_sensitive(cond); + colorde_->set_sensitive(cond); avoid_->set_sensitive(cond); + recurs_->set_sensitive(cond); + laplac_->set_sensitive(cond); + deltae_->set_sensitive(cond); + scopemask_->set_sensitive(cond); + shortc_->set_sensitive(cond); + lumask_->set_sensitive(cond); + savrest_->set_sensitive(cond); + complexMethod_->set_sensitive(cond); + wavMethod_->set_sensitive(cond); } void ControlSpotPanel::addControlSpotCurve(Gtk::TreeModel::Row& row) @@ -1720,6 +2109,7 @@ ControlSpotPanel::SpotRow* ControlSpotPanel::getSpot(const int index) r->isvisible = row[spots_.isvisible]; r->shape = row[spots_.shape]; r->spotMethod = row[spots_.spotMethod]; +// r->mergeMethod = row[spots_.mergeMethod]; r->sensiexclu = row[spots_.sensiexclu]; r->structexclu = row[spots_.structexclu]; r->struc = row[spots_.struc]; @@ -1732,13 +2122,25 @@ ControlSpotPanel::SpotRow* ControlSpotPanel::getSpot(const int index) r->centerY = row[spots_.centerY]; r->circrad = row[spots_.circrad]; r->qualityMethod = row[spots_.qualityMethod]; + r->complexMethod = row[spots_.complexMethod]; r->transit = row[spots_.transit]; + r->feather = row[spots_.feather]; r->thresh = row[spots_.thresh]; r->iter = row[spots_.iter]; r->balan = row[spots_.balan]; + r->balanh = row[spots_.balanh]; + r->colorde = row[spots_.colorde]; r->transitweak = row[spots_.transitweak]; r->transitgrad = row[spots_.transitgrad]; + r->scopemask = row[spots_.scopemask]; + r->lumask = row[spots_.lumask]; r->avoid = row[spots_.avoid]; + r->recurs = row[spots_.recurs]; + r->laplac = row[spots_.laplac]; + r->deltae = row[spots_.deltae]; + r->shortc = row[spots_.shortc]; + r->savrest = row[spots_.savrest]; + r->wavMethod = row[spots_.wavMethod]; return r; } @@ -1827,7 +2229,6 @@ void ControlSpotPanel::addControlSpot(SpotRow* newSpot) row[spots_.spotMethod] = newSpot->spotMethod; row[spots_.sensiexclu] = newSpot->sensiexclu; row[spots_.structexclu] = newSpot->structexclu; - row[spots_.struc] = newSpot->struc; row[spots_.shapeMethod] = newSpot->shapeMethod; row[spots_.locX] = newSpot->locX; row[spots_.locXL] = newSpot->locXL; @@ -1838,12 +2239,25 @@ void ControlSpotPanel::addControlSpot(SpotRow* newSpot) row[spots_.circrad] = newSpot->circrad; row[spots_.qualityMethod] = newSpot->qualityMethod; row[spots_.transit] = newSpot->transit; + row[spots_.transitweak] = newSpot->transitweak; + row[spots_.transitgrad] = newSpot->transitgrad; + row[spots_.feather] = newSpot->feather; + row[spots_.struc] = newSpot->struc; row[spots_.thresh] = newSpot->thresh; row[spots_.iter] = newSpot->iter; row[spots_.balan] = newSpot->balan; - row[spots_.transitweak] = newSpot->transitweak; - row[spots_.transitgrad] = newSpot->transitgrad; + row[spots_.balanh] = newSpot->balanh; + row[spots_.colorde] = newSpot->colorde; row[spots_.avoid] = newSpot->avoid; + row[spots_.recurs] = newSpot->recurs; + row[spots_.laplac] = newSpot->laplac; + row[spots_.deltae] = newSpot->deltae; + row[spots_.scopemask] = newSpot->scopemask; + row[spots_.shortc] = newSpot->shortc; + row[spots_.lumask] = newSpot->lumask; + row[spots_.savrest] = newSpot->savrest; + row[spots_.complexMethod] = newSpot->complexMethod; + row[spots_.wavMethod] = newSpot->wavMethod; updateParamVisibility(); disableParamlistener(false); @@ -1854,7 +2268,7 @@ void ControlSpotPanel::addControlSpot(SpotRow* newSpot) void ControlSpotPanel::deleteControlSpot(const int index) { - // printf("deleteControlSpot: %d\n", id); + // printf("deleteControlSpot: %d\n", index); MyMutex::MyLock lock(mTreeview); @@ -1886,7 +2300,6 @@ void ControlSpotPanel::setDefaults(const rtengine::procparams::ProcParams * defP // Set default values for adjuster widgets sensiexclu_->setDefault((double)defSpot.sensiexclu); structexclu_->setDefault((double)defSpot.structexclu); - struc_->setDefault(defSpot.struc); locX_->setDefault((double)defSpot.locX); locXL_->setDefault((double)defSpot.locXL); locY_->setDefault((double)defSpot.locY); @@ -1894,12 +2307,18 @@ void ControlSpotPanel::setDefaults(const rtengine::procparams::ProcParams * defP centerX_->setDefault((double)defSpot.centerX); centerY_->setDefault((double)defSpot.centerY); circrad_->setDefault((double)defSpot.circrad); - transit_->setDefault((double)defSpot.transit); + transit_->setDefault(defSpot.transit); + transitweak_->setDefault(defSpot.transitweak); + transitgrad_->setDefault(defSpot.transitgrad); + feather_->setDefault(defSpot.feather); + struc_->setDefault(defSpot.struc); thresh_->setDefault(defSpot.thresh); iter_->setDefault(defSpot.iter); balan_->setDefault(defSpot.balan); - transitweak_->setDefault(defSpot.transitweak); - transitgrad_->setDefault(defSpot.transitgrad); + balanh_->setDefault(defSpot.balanh); + colorde_->setDefault(defSpot.colorde); + scopemask_->setDefault((double)defSpot.scopemask); + lumask_->setDefault((double)defSpot.lumask); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -1919,7 +2338,6 @@ ControlSpotPanel::ControlSpots::ControlSpots() add(spotMethod); add(sensiexclu); add(structexclu); - add(struc); add(shapeMethod); add(locX); add(locXL); @@ -1930,12 +2348,25 @@ ControlSpotPanel::ControlSpots::ControlSpots() add(circrad); add(qualityMethod); add(transit); + add(transitweak); + add(transitgrad); + add(feather); + add(struc); add(thresh); add(iter); add(balan); - add(transitweak); - add(transitgrad); + add(balanh); + add(colorde); add(avoid); + add(recurs); + add(laplac); + add(deltae); + add(scopemask); + add(shortc); + add(lumask); + add(savrest); + add(complexMethod); + add(wavMethod); } //----------------------------------------------------------------------------- diff --git a/rtgui/controlspotpanel.h b/rtgui/controlspotpanel.h index 07d9c7454..fadf0fc73 100644 --- a/rtgui/controlspotpanel.h +++ b/rtgui/controlspotpanel.h @@ -22,13 +22,10 @@ #define _CONTROLSPOTPANEL_H_ #include "../rtengine/coord.h" -#include "adjuster.h" #include "editcallbacks.h" -#include "guiutils.h" #include "threadutils.h" #include "toolpanel.h" -#include -#include +#include "adjuster.h" class ControlSpotPanel: public ToolParamBlock, @@ -47,7 +44,6 @@ public: int spotMethod; // 0 = Normal, 1 = Excluding int sensiexclu; int structexclu; - double struc; int shapeMethod; // 0 = Independent (mouse), 1 = Symmetrical (mouse), 2 = Independent (mouse + sliders), 3 = Symmetrical (mouse + sliders) int locX; int locXL; @@ -57,13 +53,26 @@ public: int centerY; int circrad; int qualityMethod; // 0 = Standard, 1 = Enhanced, 2 = Enhanced + chroma denoise - int transit; + double transit; + double transitweak; + double transitgrad; + double feather; + double struc; double thresh; double iter; double balan; - double transitweak; - double transitgrad; + double balanh; + double colorde; bool avoid; + bool recurs; + bool laplac; + bool deltae; + int scopemask; + bool shortc; + int lumask; + bool savrest; + int complexMethod; // 0 = Simple, 1 = Moderate, 2 = all + int wavMethod; // 0 = D2, 1 = D4, 2 = D6, 3 = D10, 4 = D14 }; /** @@ -190,9 +199,19 @@ private: void spotMethodChanged(); void shapeMethodChanged(); void qualityMethodChanged(); + void complexMethodChanged(); + void wavMethodChanged(); + void updateParamVisibility(); + void adjusterChanged(Adjuster* a, double newval); + void avoidChanged(); + void recursChanged(); + void laplacChanged(); + void deltaeChanged(); + void shortcChanged(); + void savrestChanged(); void disableParamlistener(bool cond); @@ -222,7 +241,6 @@ private: Gtk::TreeModelColumn spotMethod; // 0 = Normal, 1 = Excluding Gtk::TreeModelColumn sensiexclu; Gtk::TreeModelColumn structexclu; - Gtk::TreeModelColumn struc; Gtk::TreeModelColumn shapeMethod; // 0 = Independent (mouse), 1 = Symmetrical (mouse), 2 = Independent (mouse + sliders), 3 = Symmetrical (mouse + sliders) Gtk::TreeModelColumn locX; Gtk::TreeModelColumn locXL; @@ -232,13 +250,26 @@ private: Gtk::TreeModelColumn centerY; Gtk::TreeModelColumn circrad; Gtk::TreeModelColumn qualityMethod; // 0 = Standard, 1 = Enhanced, 2 = Enhanced + chroma denoise - Gtk::TreeModelColumn transit; + Gtk::TreeModelColumn transit; + Gtk::TreeModelColumn transitweak; + Gtk::TreeModelColumn transitgrad; + Gtk::TreeModelColumn feather; + Gtk::TreeModelColumn struc; Gtk::TreeModelColumn thresh; Gtk::TreeModelColumn iter; Gtk::TreeModelColumn balan; - Gtk::TreeModelColumn transitweak; - Gtk::TreeModelColumn transitgrad; + Gtk::TreeModelColumn balanh; + Gtk::TreeModelColumn colorde; Gtk::TreeModelColumn avoid; + Gtk::TreeModelColumn recurs; + Gtk::TreeModelColumn laplac; + Gtk::TreeModelColumn deltae; + Gtk::TreeModelColumn scopemask; + Gtk::TreeModelColumn shortc; + Gtk::TreeModelColumn lumask; + Gtk::TreeModelColumn savrest; + Gtk::TreeModelColumn complexMethod; // 0 = Simple, 1 = mod, 2 = all + Gtk::TreeModelColumn wavMethod; // 0 = D2, 1 = D4, 2 = D6, 3 = D10, 4 = D14 }; class RenameDialog: @@ -285,10 +316,13 @@ private: sigc::connection shapeMethodconn_; MyComboBoxText* const qualityMethod_; sigc::connection qualityMethodconn_; + MyComboBoxText* const complexMethod_; + sigc::connection complexMethodconn_; + MyComboBoxText* const wavMethod_; + sigc::connection wavMethodconn_; Adjuster* const sensiexclu_; Adjuster* const structexclu_; - Adjuster* const struc_; Adjuster* const locX_; Adjuster* const locXL_; Adjuster* const locY_; @@ -297,14 +331,30 @@ private: Adjuster* const centerY_; Adjuster* const circrad_; Adjuster* const transit_; + Adjuster* const transitweak_; + Adjuster* const transitgrad_; + Adjuster* const feather_; + Adjuster* const struc_; Adjuster* const thresh_; Adjuster* const iter_; Adjuster* const balan_; - Adjuster* const transitweak_; - Adjuster* const transitgrad_; + Adjuster* const balanh_; + Adjuster* const colorde_; + Adjuster* const scopemask_; + Adjuster* const lumask_; Gtk::CheckButton* const avoid_; sigc::connection avoidConn_; + Gtk::CheckButton* const recurs_; + sigc::connection recursConn_; + Gtk::CheckButton* const laplac_; + sigc::connection laplacConn_; + Gtk::CheckButton* const deltae_; + sigc::connection deltaeConn_; + Gtk::CheckButton* const shortc_; + sigc::connection shortcConn_; + Gtk::CheckButton* const savrest_; + sigc::connection savrestConn_; // Internal variables int lastObject_; 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..24edc707a 100644 --- a/rtgui/coordinateadjuster.h +++ b/rtgui/coordinateadjuster.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 _COORDINATEADJUSTER_ -#define _COORDINATEADJUSTER_ +#pragma once #include @@ -70,7 +69,7 @@ public: * * The position of the Axis in the vector will be used in the communication between the Adjuster and the Provider to identify the Axis */ -class CoordinateAdjuster : public Gtk::FlowBox +class CoordinateAdjuster final : public Gtk::FlowBox { public: @@ -160,6 +159,3 @@ public: void stopNumericalAdjustment(); }; - - -#endif diff --git a/rtgui/crop.cc b/rtgui/crop.cc index 781a916a1..3bdcf14cf 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" @@ -26,8 +26,6 @@ using namespace rtengine; using namespace rtengine::procparams; -extern Options options; - namespace { @@ -1400,24 +1398,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 +1418,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 +1451,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..b9221a803 100644 --- a/rtgui/crop.h +++ b/rtgui/crop.h @@ -14,16 +14,17 @@ * GNU General Public License for more details. * * 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_ +#pragma once + +#include #include + #include "cropguilistener.h" -#include "toolpanel.h" #include "guiutils.h" -#include +#include "toolpanel.h" class CropPanelListener { @@ -129,5 +130,3 @@ private: IdleRegister idle_register; }; - -#endif diff --git a/rtgui/cropguilistener.h b/rtgui/cropguilistener.h index 7a791ef93..a7e18683a 100644 --- a/rtgui/cropguilistener.h +++ b/rtgui/cropguilistener.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 __CROPGUILISTENER__ -#define __CROPGUILISTENER__ +#pragma once class CropGUIListener { @@ -39,5 +38,3 @@ public: virtual bool inImageArea(int x, int y) = 0; virtual double getRatio() const = 0; }; - -#endif 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..98c925b67 100644 --- a/rtgui/crophandler.h +++ b/rtgui/crophandler.h @@ -14,23 +14,21 @@ * GNU General Public License for more details. * * 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__ +#pragma once #include -#include #include +#include #include -#include "../rtengine/rtengine.h" -#include "editbuffer.h" - #include "lockablecolorpicker.h" #include "threadutils.h" +#include "../rtengine/rtengine.h" + class EditSubscriber; class CropDisplayHandler @@ -139,5 +137,3 @@ private: IdleRegister idle_register; }; - -#endif diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index b29aa5eeb..edc378700 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -14,9 +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 +#ifdef WIN32 +#include +#endif #include "cropwindow.h" @@ -30,9 +33,11 @@ #include "editcallbacks.h" #include "editbuffer.h" #include "editwidgets.h" +#include "pointermotionlistener.h" +#include "rtsurface.h" #include "../rtengine/dcrop.h" -#include "../rtengine/mytime.h" +#include "../rtengine/imagesource.h" #include "../rtengine/procparams.h" #include "../rtengine/rt_math.h" @@ -51,7 +56,7 @@ CropWindow::CropWindow (ImageArea* parent, bool isLowUpdatePriority_, bool isDet 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(); @@ -256,7 +261,7 @@ void CropWindow::getCropAnchorPosition (int& x, int& y) cropHandler.getAnchorPosition(x, y); } -void CropWindow::setCropAnchorPosition (int& x, int& y) +void CropWindow::setCropAnchorPosition (int x, int y) { cropHandler.setAnchorPosition(x, y); } @@ -295,11 +300,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) { @@ -404,6 +414,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; @@ -477,7 +507,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; @@ -492,7 +522,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; @@ -1256,6 +1286,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) { @@ -1461,9 +1493,9 @@ void CropWindow::expose (Cairo::RefPtr cr) const float kernel_size2 = SQR(2.f * blur_radius2 + 1.f); // count of pixels in the small blur kernel const float rkernel_size2 = 1.0f / kernel_size2; // reciprocal of kernel_size to avoid divisions - // aloocate buffer for precalculated Luminance + // allocate buffer for precalculated Luminance float* tmpL = (float*)malloc(bHeight * bWidth * sizeof(float) ); - // aloocate buffers for sums and sums of squares of small kernel + // allocate buffers for sums and sums of squares of small kernel float* tmpLsum = (float*)malloc((bHeight) * (bWidth) * sizeof(float) ); float* tmpLsumSq = (float*)malloc((bHeight) * (bWidth) * sizeof(float) ); float* tmpstdDev2 = (float*)malloc((bHeight) * (bWidth) * sizeof(float) ); @@ -1600,7 +1632,7 @@ void CropWindow::expose (Cairo::RefPtr cr) && stdDev_L2 > stdDev_L //this is the key to select fine detail within lower contrast on larger scale && stdDev_L > focus_threshby10 //options.highlightThreshold ) { - // transpareny depends on sdtDev_L2 and maxstdDev_L2 + // transparency depends on sdtDev_L2 and maxstdDev_L2 float transparency = 1.f - std::min(stdDev_L2 / maxstdDev_L2, 1.0f) ; // first row of circle guint8* currtmp = &curr[0] + (-3 * pixRowStride); @@ -1845,11 +1877,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(); @@ -2198,8 +2228,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); @@ -2215,6 +2243,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 6e2097d3b..623653d2d 100644 --- a/rtgui/cropwindow.h +++ b/rtgui/cropwindow.h @@ -14,25 +14,34 @@ * GNU General Public License for more details. * * 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_ +#pragma once -#include "../rtengine/rtengine.h" -#include -#include "lwbutton.h" -#include "lwbuttonset.h" -#include "editenums.h" -#include "crophandler.h" #include + +#include + #include "cropguilistener.h" -#include "pointermotionlistener.h" +#include "crophandler.h" #include "cursormanager.h" #include "editbuffer.h" #include "editcoordsys.h" +#include "editenums.h" +#include "lwbutton.h" +#include "lwbuttonset.h" + +#include "../rtengine/noncopyable.h" + +namespace rtengine +{ + +struct Coord; + +} class CropWindow; +class PointerMotionListener; class CropWindowListener { @@ -45,7 +54,7 @@ public: }; class ImageArea; -class CropWindow : public LWButtonListener, public CropDisplayHandler, public EditCoordSystem, public ObjectMOBuffer +class CropWindow final : public LWButtonListener, public CropDisplayHandler, public EditCoordSystem, public ObjectMOBuffer, public rtengine::NonCopyable { static bool initialized; @@ -101,6 +110,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 @@ -214,7 +224,7 @@ public: void centerCrop (bool update = true); void getCropSize (int& w, int& h); void getCropAnchorPosition (int& w, int& h); - void setCropAnchorPosition (int& w, int& h); + void setCropAnchorPosition (int w, int h); // listeners void setCropGUIListener (CropGUIListener* cgl); @@ -237,5 +247,3 @@ public: ImageArea* getImageArea(); }; - -#endif diff --git a/rtgui/cursormanager.cc b/rtgui/cursormanager.cc index 3181d288e..e915150aa 100644 --- a/rtgui/cursormanager.cc +++ b/rtgui/cursormanager.cc @@ -14,11 +14,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 . */ #include "cursormanager.h" -#include "options.h" #include "rtimage.h" CursorManager mainWindowCursorManager; diff --git a/rtgui/cursormanager.h b/rtgui/cursormanager.h index 111652726..38f198e32 100644 --- a/rtgui/cursormanager.h +++ b/rtgui/cursormanager.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 _CURSORMANAGER_ -#define _CURSORMANAGER_ +#pragma once #include @@ -89,6 +88,3 @@ public: extern CursorManager mainWindowCursorManager; extern CursorManager editWindowCursorManager; - -#endif - diff --git a/rtgui/curveeditor.cc b/rtgui/curveeditor.cc index 914897845..e38f3a947 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" @@ -21,6 +21,7 @@ #include #include "guiutils.h" #include "multilangmgr.h" +#include "popuptogglebutton.h" #include "../rtengine/LUT.h" #include diff --git a/rtgui/curveeditor.h b/rtgui/curveeditor.h index d1c43fc89..d5ec49559 100644 --- a/rtgui/curveeditor.h +++ b/rtgui/curveeditor.h @@ -14,21 +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 . */ -#ifndef _CURVEEDITOR_ -#define _CURVEEDITOR_ +#pragma once -#include "popuptogglebutton.h" -#include "../rtengine/LUT.h" -#include "coloredbar.h" #include "editcallbacks.h" -#include "mydiagonalcurve.h" -#include "myflatcurve.h" +#include "guiutils.h" + +#include "../rtengine/diagonalcurvetypes.h" +#include "../rtengine/flatcurvetypes.h" +#include "../rtengine/LUT.h" +#include "../rtengine/noncopyable.h" class CurveEditorGroup; class CurveEditorSubGroup; - +class ColorProvider; +class PopUpToggleButton; /* *********************** Curve Editor *********************** @@ -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; @@ -143,7 +144,7 @@ public: */ -class DiagonalCurveEditor : public CurveEditor +class DiagonalCurveEditor final : public CurveEditor { friend class DiagonalCurveEditorSubGroup; @@ -179,9 +180,8 @@ public: */ -class FlatCurveEditor : public CurveEditor +class FlatCurveEditor final : public CurveEditor { - friend class FlatCurveEditorSubGroup; protected: @@ -206,5 +206,3 @@ public: // set the reset curve for a given curve type. This is optional; all curve type have a default reset curve void setResetCurve(FlatCurveType cType, const std::vector &resetCurve); }; - -#endif diff --git a/rtgui/curveeditorgroup.cc b/rtgui/curveeditorgroup.cc index 7ad1e9497..5c120f7e4 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' */ @@ -24,7 +24,10 @@ #include "diagonalcurveeditorsubgroup.h" #include "flatcurveeditorsubgroup.h" #include "multilangmgr.h" +#include "popuptogglebutton.h" #include "rtimage.h" +#include "options.h" +#include "pathutils.h" CurveEditorGroup::CurveEditorGroup (Glib::ustring& curveDir, Glib::ustring groupLabel) : curveDir(curveDir), line(0), curve_reset(nullptr), displayedCurve(nullptr), flatSubGroup(nullptr), diagonalSubGroup(nullptr), cl(nullptr), numberOfPackedCurve(0) @@ -398,7 +401,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 721e71d02..0f7c01a32 100644 --- a/rtgui/curveeditorgroup.h +++ b/rtgui/curveeditorgroup.h @@ -14,20 +14,21 @@ * GNU General Public License for more details. * * 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_ +#pragma once -#include #include #include + +#include + #include "guiutils.h" #include "mycurve.h" -#include "myflatcurve.h" -#include "mydiagonalcurve.h" #include "shcselector.h" -#include "adjuster.h" + +#include "../rtengine/diagonalcurvetypes.h" +#include "../rtengine/flatcurvetypes.h" class CurveEditor; class DiagonalCurveEditorSubGroup; @@ -39,7 +40,7 @@ class FlatCurveEditorSubGroup; * - to start a new line of curve button, use the 'newLine' method * - if you add more than one curve, you must add a "CurveEditor* ce" parameter to your listener */ -class CurveEditorGroup : public Gtk::Grid, public CurveListener +class CurveEditorGroup final : public Gtk::Grid, public CurveListener { friend class CurveEditor; @@ -70,7 +71,7 @@ public: * dialogs. */ - CurveEditorGroup(Glib::ustring& curveDir, Glib::ustring groupLabel = ""); + explicit CurveEditorGroup(Glib::ustring& curveDir, Glib::ustring groupLabel = ""); ~CurveEditorGroup() override; void newLine(); void curveListComplete(); @@ -171,5 +172,3 @@ protected: virtual const std::vector getCurveFromGUI (int type) = 0; }; - -#endif diff --git a/rtgui/curvelistener.h b/rtgui/curvelistener.h index 3c85db712..d99167a98 100644 --- a/rtgui/curvelistener.h +++ b/rtgui/curvelistener.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 _CURVELISTENER_ -#define _CURVELISTENER_ +#pragma once #include @@ -86,5 +85,3 @@ public: return retVal; } }; - -#endif diff --git a/rtgui/darkframe.cc b/rtgui/darkframe.cc index 8ffca7544..74ef1384a 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 @@ -25,6 +25,7 @@ #include "rtimage.h" #include "../rtengine/procparams.h" +#include "../rtengine/rawimage.h" using namespace rtengine; using namespace rtengine::procparams; diff --git a/rtgui/darkframe.h b/rtgui/darkframe.h index c385a2153..30696e3db 100644 --- a/rtgui/darkframe.h +++ b/rtgui/darkframe.h @@ -14,26 +14,36 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include + #include -#include "toolpanel.h" -#include "../rtengine/rawimage.h" + #include "guiutils.h" +#include "toolpanel.h" + +namespace rtengine +{ + +class RawImage; + +} class DFProvider { public: + virtual ~DFProvider() = default; virtual rtengine::RawImage* getDF() = 0; virtual Glib::ustring GetCurrentImageFilePath() = 0; // add other info here }; -class DarkFrame : public ToolParamBlock, public FoldableToolPanel +class DarkFrame final: + public ToolParamBlock, + public FoldableToolPanel { protected: @@ -66,5 +76,3 @@ public: dfp = p; }; }; - -#endif diff --git a/rtgui/defringe.cc b/rtgui/defringe.cc index 03bf648dd..cdec88edc 100644 --- a/rtgui/defringe.cc +++ b/rtgui/defringe.cc @@ -14,13 +14,17 @@ * GNU General Public License for more details. * * 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 "defringe.h" +#include "curveeditor.h" +#include "curveeditorgroup.h" +#include "options.h" +#include "../rtengine/color.h" #include "../rtengine/procparams.h" using namespace rtengine; diff --git a/rtgui/defringe.h b/rtgui/defringe.h index c02fd8d6a..ebf1eecd8 100644 --- a/rtgui/defringe.h +++ b/rtgui/defringe.h @@ -14,20 +14,27 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include -#include "adjuster.h" -#include "toolpanel.h" -#include "guiutils.h" -#include "curveeditor.h" -#include "curveeditorgroup.h" -#include "colorprovider.h" -class Defringe : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider +#include "adjuster.h" +#include "colorprovider.h" +#include "curvelistener.h" +#include "guiutils.h" +#include "toolpanel.h" + +class CurveEditorGroup; +class FlatCurveEditor; + +class Defringe final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public CurveListener, + public ColorProvider { protected: @@ -54,5 +61,3 @@ public: void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) override; }; - -#endif 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 66720a9fd..79d2e015c 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 @@ -23,17 +23,19 @@ #include "adjuster.h" #include "toolpanel.h" -class Dehaze: public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class Dehaze final : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { 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,6 +49,7 @@ public: void adjusterChanged(Adjuster *a, double newval) override; void enabledChanged() override; void showDepthMapChanged(); + void luminanceChanged(); void setAdjusterBehavior(bool strengthAdd); }; diff --git a/rtgui/diagonalcurveeditorsubgroup.cc b/rtgui/diagonalcurveeditorsubgroup.cc index 9e2406309..eed6c63d3 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" @@ -31,6 +31,8 @@ #include "curveeditor.h" #include "diagonalcurveeditorsubgroup.h" #include "rtimage.h" +#include "options.h" +#include "popuptogglebutton.h" #include "../rtengine/curves.h" diff --git a/rtgui/diagonalcurveeditorsubgroup.h b/rtgui/diagonalcurveeditorsubgroup.h index 54f424dc6..9b1f67462 100644 --- a/rtgui/diagonalcurveeditorsubgroup.h +++ b/rtgui/diagonalcurveeditorsubgroup.h @@ -14,17 +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 _DIAGONALCURVEEDITORSUBGROUP_ -#define _DIAGONALCURVEEDITORSUBGROUP_ +#pragma once #include + #include "curveeditorgroup.h" +#include "adjuster.h" +#include "../rtengine/noncopyable.h" class DiagonalCurveEditor; +class MyDiagonalCurve; -class DiagonalCurveEditorSubGroup : public CurveEditorSubGroup, public SHCListener, public AdjusterListener +class DiagonalCurveEditorSubGroup final : + public CurveEditorSubGroup, + public SHCListener, + public AdjusterListener, + public rtengine::NonCopyable { friend class DiagonalCurveEditor; @@ -110,5 +117,3 @@ protected: void setSubGroupRangeLabels(Glib::ustring r1, Glib::ustring r2, Glib::ustring r3, Glib::ustring r4); void setSubGroupBottomBarBgGradient(); }; - -#endif diff --git a/rtgui/dirbrowser.cc b/rtgui/dirbrowser.cc index fcc40abc9..10ef61566 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" @@ -63,7 +63,7 @@ std::vector listSubDirs (const Glib::RefPtr& dir, bool subDirs.push_back (file->get_name ()); } catch (const Glib::Exception& exception) { - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { std::cerr << exception.what().c_str() << std::endl; } @@ -72,7 +72,7 @@ std::vector listSubDirs (const Glib::RefPtr& dir, bool } catch (const Glib::Exception& exception) { - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { std::cerr << "Failed to list subdirectories of \"" << dir->get_parse_name() << "\": " << exception.what () << std::endl; } @@ -293,36 +293,32 @@ void DirBrowser::row_expanded (const Gtk::TreeModel::iterator& iter, const Gtk:: auto dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname)); auto subDirs = listSubDirs (dir, options.fbShowHidden); - if (subDirs.empty()) { - dirtree->collapse_row(path); - } else { - Gtk::TreeNodeChildren children = iter->children(); - std::list forErase(children.begin(), children.end()); + Gtk::TreeNodeChildren children = iter->children(); + std::list forErase(children.begin(), children.end()); - std::sort (subDirs.begin (), subDirs.end (), [] (const Glib::ustring& firstDir, const Glib::ustring& secondDir) - { - switch (options.dirBrowserSortType) { - default: - case Gtk::SORT_ASCENDING: - return firstDir < secondDir; - case Gtk::SORT_DESCENDING: - return firstDir > secondDir; - } - }); - - for (auto it = subDirs.begin(), end = subDirs.end(); it != end; ++it) { - addDir(iter, *it); + std::sort (subDirs.begin (), subDirs.end (), [] (const Glib::ustring& firstDir, const Glib::ustring& secondDir) + { + switch (options.dirBrowserSortType) { + default: + case Gtk::SORT_ASCENDING: + return firstDir < secondDir; + case Gtk::SORT_DESCENDING: + return firstDir > secondDir; } + }); - for (auto it = forErase.begin(), end = forErase.end(); it != end; ++it) { - dirTreeModel->erase(*it); - } - - dirTreeModel->set_sort_column(prevSortColumn, prevSortType); - - expandSuccess = true; + for (auto it = subDirs.begin(), end = subDirs.end(); it != end; ++it) { + addDir(iter, *it); } + for (auto it = forErase.begin(), end = forErase.end(); it != end; ++it) { + dirTreeModel->erase(*it); + } + + dirTreeModel->set_sort_column(prevSortColumn, prevSortType); + + expandSuccess = true; + Glib::RefPtr monitor = dir->monitor_directory (); iter->set_value (dtColumns.monitor, monitor); monitor->signal_changed().connect (sigc::bind(sigc::mem_fun(*this, &DirBrowser::file_changed), iter, dir->get_parse_name())); @@ -383,8 +379,10 @@ void DirBrowser::row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewC Glib::ustring dname = dirTreeModel->get_iter (path)->get_value (dtColumns.dirname); - if (Glib::file_test (dname, Glib::FILE_TEST_IS_DIR)) + if (Glib::file_test (dname, Glib::FILE_TEST_IS_DIR)) { dirSelectionSignal (dname, Glib::ustring()); + dirtree->expand_row(path, false); + } } Gtk::TreePath DirBrowser::expandToDir (const Glib::ustring& absDirPath) diff --git a/rtgui/dirbrowser.h b/rtgui/dirbrowser.h index 15b6dd201..6ead83919 100644 --- a/rtgui/dirbrowser.h +++ b/rtgui/dirbrowser.h @@ -14,18 +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 . */ -#ifndef _DIRBROWSER_ -#define _DIRBROWSER_ +#pragma once #include #include #include "guiutils.h" -#ifdef WIN32 -#include "windows.h" -#endif class DirBrowser : public Gtk::VBox { @@ -110,5 +106,3 @@ inline DirBrowser::DirSelectionSignal DirBrowser::dirSelected () const { return dirSelectionSignal; } - -#endif diff --git a/rtgui/dirpyrdenoise.cc b/rtgui/dirpyrdenoise.cc index c3528d5dd..7129542d1 100644 --- a/rtgui/dirpyrdenoise.cc +++ b/rtgui/dirpyrdenoise.cc @@ -14,21 +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 . */ #include #include #include "dirpyrdenoise.h" -#include "guiutils.h" - -#include "../rtengine/procparams.h" +#include "curveeditor.h" +#include "curveeditorgroup.h" #include "editbuffer.h" +#include "guiutils.h" +#include "options.h" + +#include "../rtengine/color.h" +#include "../rtengine/procparams.h" using namespace rtengine; using namespace rtengine::procparams; -extern Options options; DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP_DIRPYRDENOISE_LABEL"), true, true), lastmedian(false) { diff --git a/rtgui/dirpyrdenoise.h b/rtgui/dirpyrdenoise.h index 7bdaff853..c754e705c 100644 --- a/rtgui/dirpyrdenoise.h +++ b/rtgui/dirpyrdenoise.h @@ -14,20 +14,21 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include -#include "adjuster.h" -#include "toolpanel.h" -#include "curveeditor.h" -#include "curveeditorgroup.h" -#include "colorprovider.h" -#include "guiutils.h" -#include "options.h" +#include "adjuster.h" +#include "colorprovider.h" +#include "curvelistener.h" +#include "guiutils.h" +#include "toolpanel.h" + +class CurveEditor; +class CurveEditorGroup; +class FlatCurveEditor; class EditDataProvider; class DirPyrDenoise final : @@ -138,5 +139,3 @@ private: IdleRegister idle_register; }; - -#endif diff --git a/rtgui/dirpyrequalizer.cc b/rtgui/dirpyrequalizer.cc index be6f9c97b..fd0268efa 100644 --- a/rtgui/dirpyrequalizer.cc +++ b/rtgui/dirpyrequalizer.cc @@ -12,13 +12,15 @@ * GNU General Public License for more details. * * 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 "dirpyrequalizer.h" +#include "../rtengine/color.h" + using namespace rtengine; using namespace rtengine::procparams; diff --git a/rtgui/dirpyrequalizer.h b/rtgui/dirpyrequalizer.h index 4eb110428..84924099e 100644 --- a/rtgui/dirpyrequalizer.h +++ b/rtgui/dirpyrequalizer.h @@ -12,21 +12,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 . * * (C) 2010 Emil Martinec */ - -#ifndef DIRPYREQUALIZER_H_INCLUDED -#define DIRPYREQUALIZER_H_INCLUDED +#pragma once #include -#include "adjuster.h" -#include "toolpanel.h" -#include "thresholdadjuster.h" -#include "colorprovider.h" -class DirPyrEqualizer : public ToolParamBlock, public ThresholdAdjusterListener, public AdjusterListener, public FoldableToolPanel +#include "adjuster.h" +#include "colorprovider.h" +#include "thresholdadjuster.h" +#include "toolpanel.h" + +class DirPyrEqualizer final : + public ToolParamBlock, + public ThresholdAdjusterListener, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -77,5 +80,3 @@ public: void adjusterChanged(ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) override; void adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) override; }; - -#endif diff --git a/rtgui/distortion.cc b/rtgui/distortion.cc index 3620dbc21..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 diff --git a/rtgui/distortion.h b/rtgui/distortion.h index a279913cb..7ef33d73a 100644 --- a/rtgui/distortion.h +++ b/rtgui/distortion.h @@ -14,17 +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 _DISTORTION_H_ -#define _DISTORTION_H_ +#pragma once #include -#include "adjuster.h" -#include "toolpanel.h" -#include "lensgeomlistener.h" -class Distortion : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +#include "adjuster.h" +#include "lensgeomlistener.h" +#include "toolpanel.h" + +class Distortion final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -51,5 +54,3 @@ public: rlistener = l; } }; - -#endif diff --git a/rtgui/dynamicprofilepanel.cc b/rtgui/dynamicprofilepanel.cc index d83c70669..d7ed8ee97 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" @@ -22,6 +22,7 @@ #include "../rtengine/profilestore.h" #include "../rtengine/rtengine.h" #include "../rtengine/dynamicprofile.h" +#include "../rtengine/settings.h" #include #include @@ -615,7 +616,7 @@ void DynamicProfilePanel::save() if (!ProfileStore::getInstance()->storeRules()) { printf ("Error in saving dynamic profile rules\n"); - } else if (options.rtSettings.verbose) { + } else if (rtengine::settings->verbose) { printf ("Saved %d dynamic profile rules\n", int (rules.size())); } } diff --git a/rtgui/dynamicprofilepanel.h b/rtgui/dynamicprofilepanel.h index e271edc5a..5796c9c85 100644 --- a/rtgui/dynamicprofilepanel.h +++ b/rtgui/dynamicprofilepanel.h @@ -14,16 +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 _DYNAMICPROFILEPANEL_H_ -#define _DYNAMICPROFILEPANEL_H_ +#pragma once #include -#include "../rtengine/dynamicprofile.h" + #include "profilestorecombobox.h" -class DynamicProfilePanel: public Gtk::VBox +#include "../rtengine/dynamicprofile.h" + +class DynamicProfilePanel : + public Gtk::VBox { public: DynamicProfilePanel(); @@ -133,5 +135,3 @@ private: Gtk::Button button_edit_; Gtk::Button button_delete_; }; - -#endif // _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..a5cf8d0e4 100644 --- a/rtgui/editbuffer.h +++ b/rtgui/editbuffer.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 . */ #pragma once #include "editid.h" -#include "../rtengine/coord.h" #include -#ifdef GUIVERSION -#include "rtsurface.h" -#endif +namespace rtengine { + +struct Coord; + +} class EditDataProvider; class EditSubscriber; diff --git a/rtgui/editcallbacks.cc b/rtgui/editcallbacks.cc index 876a5e3a7..5404b0bc9 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 7517ef865..524ec1622 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 @@ -129,19 +129,19 @@ public: @param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys. If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected. @return true if the preview has to be redrawn, false otherwise */ - virtual bool pick1 (bool picked); + bool pick1 (bool picked); /** @brief Triggered when the user is releasing mouse button 2 while in action==ES_ACTION_PICKING mode @param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys. If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected. @return true if the preview has to be redrawn, false otherwise */ - virtual bool pick2 (bool picked); + bool pick2 (bool picked); /** @brief Triggered when the user is releasing mouse button 3 while in action==ES_ACTION_PICKING mode @param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys. If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected. @return true if the preview has to be redrawn, false otherwise */ - virtual bool pick3 (bool picked); + bool pick3 (bool picked); /** @brief Get the geometry to be shown to the user */ const std::vector& getVisibleGeometry (); 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..c34aaf539 100644 --- a/rtgui/editedstate.h +++ b/rtgui/editedstate.h @@ -14,12 +14,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 . */ -#ifndef _EDITEDSTATE_ -#define _EDITEDSTATE_ +#pragma once enum EditedState { UnEdited = 0, Edited = 1, Irrelevant = 2 }; - -#endif - diff --git a/rtgui/editenums.h b/rtgui/editenums.h index 264576789..f1ade8bfc 100644 --- a/rtgui/editenums.h +++ b/rtgui/editenums.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 _EDITENUMS_ -#define _EDITENUMS_ +#pragma once enum ImgEditState {SNormal, SCropMove, SHandMove, SResizeW1, SResizeW2, SResizeH1, SResizeH2, SResizeTL, SResizeTR, SResizeBL, SResizeBR, SCropSelecting, SRotateSelecting, SCropWinMove, SCropFrameMove, SCropImgMove, SCropWinResize, SObservedMove, @@ -26,5 +25,3 @@ enum ImgEditState {SNormal, SCropMove, SHandMove, SResizeW1, SResizeW2, SResizeH enum CursorArea {CropWinButtons, CropToolBar, CropImage, ColorPicker, CropBorder, CropTop, CropTopLeft, CropTopRight, CropBottom, CropBottomLeft, CropBottomRight, CropLeft, CropRight, CropInside, CropResize, CropObserved }; - -#endif diff --git a/rtgui/editid.h b/rtgui/editid.h index 5c1cf2389..39dc2bf7c 100644 --- a/rtgui/editid.h +++ b/rtgui/editid.h @@ -14,11 +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 _EDITID_H_ -#define _EDITID_H_ - +#pragma once /// @brief List of pipette editing operation enum EditUniqueID : int { @@ -67,5 +65,3 @@ enum ObjectMode { OM_255, /// less or equal than 255 objects OM_65535 /// less or equal than 65535 objects }; - -#endif diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 59831bf67..9a2ecf316 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" @@ -23,15 +23,27 @@ #include "../rtengine/imagesource.h" #include "../rtengine/iccstore.h" +#include "batchqueue.h" +#include "batchqueueentry.h" #include "soundman.h" #include "rtimage.h" #include "rtwindow.h" +#include "filepanel.h" #include "guiutils.h" #include "popupbutton.h" #include "options.h" +#include "navigator.h" +#include "previewwindow.h" #include "progressconnector.h" #include "procparamchangers.h" #include "placesbrowser.h" +#include "pathutils.h" +#include "thumbnail.h" +#include "toolpanelcoord.h" + +#ifdef WIN32 +#include "windows.h" +#endif using namespace rtengine::procparams; @@ -49,7 +61,7 @@ void setprogressStrUI(double val, const Glib::ustring str, MyProgressBar* pProgr } } - +#if !defined(__APPLE__) // monitor profile not supported on apple bool find_default_monitor_profile (GdkWindow *rootwin, Glib::ustring &defprof, Glib::ustring &defprofname) { #ifdef WIN32 @@ -79,7 +91,7 @@ bool find_default_monitor_profile (GdkWindow *rootwin, Glib::ustring &defprof, G ReleaseDC (NULL, hDC); } -#elif !defined(__APPLE__) +#else // taken from geeqie (image.c) and adapted // Originally licensed as GPL v2+, with the following copyright: // * Copyright (C) 2006 John Ellis @@ -117,7 +129,7 @@ bool find_default_monitor_profile (GdkWindow *rootwin, Glib::ustring &defprof, G #endif return false; } - +#endif } @@ -889,41 +901,17 @@ EditorPanel::~EditorPanel () delete vboxright; //delete saveAsDialog; - if (catalogPane) { - delete catalogPane; - } - - if (iTopPanel_1_Show) { - delete iTopPanel_1_Show; - } - - if (iTopPanel_1_Hide) { - delete iTopPanel_1_Hide; - } - - if (iHistoryShow) { - delete iHistoryShow; - } - - if (iHistoryHide) { - delete iHistoryHide; - } - - if (iBeforeLockON) { - delete iBeforeLockON; - } - - if (iBeforeLockOFF) { - delete iBeforeLockOFF; - } - - if (iRightPanel_1_Show) { - delete iRightPanel_1_Show; - } - - if (iRightPanel_1_Hide) { - delete iRightPanel_1_Hide; - } + delete catalogPane; + delete iTopPanel_1_Show; + delete iTopPanel_1_Hide; + delete iHistoryShow; + delete iHistoryHide; + delete iBeforeLockON; + delete iBeforeLockOFF; + delete iRightPanel_1_Show; + delete iRightPanel_1_Hide; + delete iShowHideSidePanels_exit; + delete iShowHideSidePanels; } void EditorPanel::leftPaneButtonReleased (GdkEventButton *event) @@ -1090,7 +1078,7 @@ void EditorPanel::close () if (iareapanel) { iareapanel->imageArea->setPreviewHandler (nullptr); iareapanel->imageArea->setImProcCoordinator (nullptr); - iareapanel->imageArea->unsubscribe(); + tpc->editModeSwitchedOff(); } rtengine::StagedImageProcessor::destroy (ipc); @@ -1130,7 +1118,7 @@ Glib::ustring EditorPanel::getShortName () } } -Glib::ustring EditorPanel::getFileName () +Glib::ustring EditorPanel::getFileName () const { if (openThm) { return openThm->getFileName (); @@ -1377,7 +1365,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 ()); } @@ -2040,9 +2028,9 @@ bool EditorPanel::idle_sendToGimp ( ProgressConnector *p if (img) { // get file name base - Glib::ustring shortname = removeExtension (Glib::path_get_basename (fname)); - Glib::ustring dirname = Glib::get_tmp_dir (); - Glib::ustring fname = Glib::build_filename (dirname, shortname); + const Glib::ustring shortname = removeExtension (Glib::path_get_basename (fname)); + const Glib::ustring dirname = Glib::get_tmp_dir (); + const Glib::ustring lfname = Glib::build_filename (dirname, shortname); SaveFormat sf; sf.format = "tif"; @@ -2051,13 +2039,13 @@ bool EditorPanel::idle_sendToGimp ( ProgressConnector *p sf.tiffUncompressed = true; sf.saveParams = true; - Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format); + Glib::ustring fileName = Glib::ustring::compose ("%1.%2", lfname, sf.format); // TODO: Just list all file with a suitable name instead of brute force... int tries = 1; while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries < 1000) { - fileName = Glib::ustring::compose ("%1-%2.%3", fname, tries, sf.format); + fileName = Glib::ustring::compose ("%1-%2.%3", lfname, tries, sf.format); tries++; } @@ -2085,6 +2073,7 @@ bool EditorPanel::idle_sentToGimp (ProgressConnector *pc, rtengine::IImagef { img->free (); int errore = pc->returnValue(); + setProgressState(false); delete pc; if (!errore) { diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index de5360646..8993fea07 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -15,28 +15,30 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include -#include "imageareapanel.h" -#include "toolpanelcoord.h" -#include "profilepanel.h" -#include "../rtengine/rtengine.h" -#include "history.h" -#include "histogrampanel.h" -#include "thumbnail.h" -#include "saveasdlg.h" -#include "batchqueueentry.h" -#include "thumbnaillistener.h" -#include "navigator.h" -#include "progressconnector.h" -#include "filepanel.h" +#include "histogrampanel.h" +#include "history.h" +#include "imageareapanel.h" +#include "profilepanel.h" +#include "progressconnector.h" +#include "saveasdlg.h" +#include "thumbnaillistener.h" + +#include "../rtengine/noncopyable.h" +#include "../rtengine/rtengine.h" + +class BatchQueueEntry; class EditorPanel; +class FilePanel; class MyProgressBar; +class Navigator; +class Thumbnail; +class ToolPanelCoordinator; struct EditorPanelIdleHelper { EditorPanel* epanel; @@ -52,7 +54,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); @@ -147,7 +150,7 @@ public: void saveProfile (); Glib::ustring getShortName (); - Glib::ustring getFileName (); + Glib::ustring getFileName () const; bool handleShortcutKey (GdkEventKey* event); bool getIsProcessing() const @@ -257,6 +260,3 @@ private: IdleRegister idle_register; }; - -#endif - diff --git a/rtgui/editwidgets.cc b/rtgui/editwidgets.cc index 444ad5a65..2928104b7 100644 --- a/rtgui/editwidgets.cc +++ b/rtgui/editwidgets.cc @@ -14,12 +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 . */ #include "editwidgets.h" + #include "editbuffer.h" #include "editcallbacks.h" +#include "rtsurface.h" #include "../rtengine/rt_math.h" RGBColor Geometry::getInnerLineColor () diff --git a/rtgui/editwidgets.h b/rtgui/editwidgets.h index a0018bc68..c86949cb4 100644 --- a/rtgui/editwidgets.h +++ b/rtgui/editwidgets.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 . */ #pragma once #ifdef GUIVERSION -#include "rtsurface.h" -#include "editbuffer.h" +#include +#include + #include "editcoordsys.h" #include "../rtengine/coord.h" class ObjectMOBuffer; +class RTSurface; /** @file * @@ -53,7 +55,7 @@ class ObjectMOBuffer; * - drag1 * - button1Released * - * Actually, only curves does use this class, and everything is handled for curve implementor (as much as possible). + * Actually, only curves does use this class, and everything is handled for curve implementer (as much as possible). * See the curve's class documentation to see how to implement the curve's pipette feature. * * ### Event handling @@ -284,7 +286,7 @@ public: rtengine::Coord end; Line (); - Line (rtengine::Coord& begin, rtengine::Coord& end); + Line (const rtengine::Coord& begin, const rtengine::Coord& end); Line (int beginX, int beginY, int endX, int endY); void drawOuterGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) override; @@ -554,7 +556,7 @@ inline Circle::Circle (int centerX, int centerY, int radius, bool filled, radiusInImageSpace) { } -inline Line::Line (rtengine::Coord& begin, rtengine::Coord& end) : +inline Line::Line (const rtengine::Coord& begin, const rtengine::Coord& end) : begin (begin), end (end) { } diff --git a/rtgui/editwindow.cc b/rtgui/editwindow.cc index ec7201f84..8841d3d42 100644 --- a/rtgui/editwindow.cc +++ b/rtgui/editwindow.cc @@ -12,16 +12,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 . */ #include "editwindow.h" +#include "editorpanel.h" +#include "filepanel.h" +#include "../rtengine/procparams.h" #include "options.h" #include "preferences.h" #include "cursormanager.h" #include "rtwindow.h" #include -#include "rtimage.h" #include "threadutils.h" extern Glib::ustring argv0; diff --git a/rtgui/editwindow.h b/rtgui/editwindow.h index 42c8ec20e..f4ada571d 100644 --- a/rtgui/editwindow.h +++ b/rtgui/editwindow.h @@ -12,17 +12,21 @@ * GNU General Public License for more details. * * 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_ +#pragma once -#include -#include "filepanel.h" -#include "editorpanel.h" #include -class EditWindow : public Gtk::Window +#include + +#include "rtimage.h" + +class EditorPanel; +class RTWindow; + +class EditWindow : + public Gtk::Window { private: @@ -66,5 +70,3 @@ public: void set_title_decorated(Glib::ustring fname); void on_realize () override; }; - -#endif diff --git a/rtgui/epd.cc b/rtgui/epd.cc index ab6341866..b13effba3 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 @@ -69,17 +69,18 @@ void EdgePreservingDecompositionUI::read(const ProcParams *pp, const ParamsEdite setEnabled(pp->epd.enabled); strength->set_sensitive (true); - - if(pp->wavelet.enabled) { - if(pp->wavelet.tmrs == 0) { + gamma->set_sensitive (true); +/* + if(pp->wavelet.enabled) { + if(pp->wavelet.tmrs == 0 || pp->wavelet.TMmethod == "cont") { strength->set_sensitive (true); gamma->set_sensitive (true); - } else { + } else if(pp->wavelet.tmrs != 0 && pp->wavelet.TMmethod == "tm") { strength->set_sensitive (false); gamma->set_sensitive (false); } } - +*/ strength->setValue(pp->epd.strength); gamma->setValue(pp->epd.gamma); edgeStopping->setValue(pp->epd.edgeStopping); @@ -98,17 +99,18 @@ void EdgePreservingDecompositionUI::write(ProcParams *pp, ParamsEdited *pedited) pp->epd.reweightingIterates = reweightingIterates->getValue(); pp->epd.enabled = getEnabled(); strength->set_sensitive (true); - - if(pp->wavelet.enabled) { - if(pp->wavelet.tmrs == 0) { + gamma->set_sensitive (true); +/* + if(pp->wavelet.enabled) { + if(pp->wavelet.tmrs == 0 || pp->wavelet.TMmethod == "cont") { strength->set_sensitive (true); gamma->set_sensitive (true); - } else { + } else if(pp->wavelet.tmrs != 0 && pp->wavelet.TMmethod == "tm") { strength->set_sensitive (false); gamma->set_sensitive (false); } } - +*/ if(pedited) { pedited->epd.strength = strength->getEditedState(); pedited->epd.gamma = gamma->getEditedState(); diff --git a/rtgui/epd.h b/rtgui/epd.h index 6b44d9147..6a5160623 100644 --- a/rtgui/epd.h +++ b/rtgui/epd.h @@ -14,16 +14,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 . */ -#ifndef _EPD_H_ -#define _EPD_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -class EdgePreservingDecompositionUI : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class EdgePreservingDecompositionUI final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: Adjuster *strength; @@ -45,5 +48,3 @@ public: void enabledChanged () override; void setAdjusterBehavior (bool stAdd, bool gAdd, bool esAdd, bool scAdd, bool rAdd); }; - -#endif 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..5a25af6ad 100644 --- a/rtgui/exiffiltersettings.h +++ b/rtgui/exiffiltersettings.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 _EXIFFILTERSETTINGS_ -#define _EXIFFILTERSETTINGS_ +#pragma once #include #include @@ -51,6 +50,3 @@ public: ExifFilterSettings (); void clear (); }; - -#endif - diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 6c196e575..341d0f303 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 "exifpanel.h" @@ -632,7 +632,7 @@ Glib::ustring ExifPanel::getSelection (bool onlyeditable) Gtk::TreeModel::iterator iter = exifTreeModel->get_iter (rows[0]); - Glib::ustring ret = ""; + Glib::ustring ret; bool first = true; bool editable = false; diff --git a/rtgui/exifpanel.h b/rtgui/exifpanel.h index c8597a287..d336d83f9 100644 --- a/rtgui/exifpanel.h +++ b/rtgui/exifpanel.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 _EXIFPANEL_ -#define _EXIFPANEL_ +#pragma once #include #include #include "toolpanel.h" +#include "../rtexif/rtexif.h" -class ExifPanel : public Gtk::VBox, public ToolPanel +class ExifPanel final : + public Gtk::VBox, + public ToolPanel { private: @@ -114,5 +116,3 @@ public: void notifyListener(); }; - -#endif 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..7ae7e043c 100644 --- a/rtgui/exportpanel.h +++ b/rtgui/exportpanel.h @@ -15,14 +15,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 _EXPORTPANEL_ -#define _EXPORTPANEL_ +#pragma once #include + #include "guiutils.h" -#include "adjuster.h" class ExportPanelListener { @@ -122,5 +121,3 @@ public: listener = l; } }; - -#endif diff --git a/rtgui/extprog.cc b/rtgui/extprog.cc index 33424fac9..57d57ecd8 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" @@ -22,10 +22,12 @@ #include #ifdef WIN32 -#include #include +#include #endif +#include + #include "options.h" #include "multilangmgr.h" @@ -58,7 +60,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); @@ -143,20 +145,19 @@ bool ExtProgStore::searchProgram (const Glib::ustring& name, filePath = progFilesDir + "\\" + Glib::ustring::compose(exePath, ver); - if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test(filePath, Glib::FILE_TEST_EXISTS)) { break; } - if (!exePath86.empty ()) { + if (!exePath86.empty()) { filePath = progFilesDirx86 + "\\" + Glib::ustring::compose(exePath86, ver); - if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test(filePath, Glib::FILE_TEST_EXISTS)) { break; } } - - filePath.clear (); + filePath.clear(); } } else { @@ -164,21 +165,19 @@ bool ExtProgStore::searchProgram (const Glib::ustring& name, filePath = progFilesDir + "\\" + exePath; - if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test(filePath, Glib::FILE_TEST_EXISTS)) { break; } - if (!exePath86.empty ()) { + if (!exePath86.empty()) { filePath = progFilesDirx86 + "\\" + exePath86; - if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test(filePath, Glib::FILE_TEST_EXISTS)) { break; } } - - filePath.clear (); - + filePath.clear(); } while (false); } @@ -211,7 +210,7 @@ bool ExtProgStore::spawnCommandAsync (const Glib::ustring& cmd) } catch (const Glib::Exception& exception) { - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { std::cerr << "Failed to execute \"" << cmd << "\": " << exception.what() << std::endl; } @@ -230,7 +229,7 @@ bool ExtProgStore::spawnCommandSync (const Glib::ustring& cmd) } catch (const Glib::Exception& exception) { - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { std::cerr << "Failed to execute \"" << cmd << "\": " << exception.what() << std::endl; } @@ -256,13 +255,13 @@ 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 #ifdef WIN32 - if ((uintptr_t)success > 32) { + if (reinterpret_cast(success) > 32) { return true; } #else @@ -277,9 +276,9 @@ bool ExtProgStore::openInGimp (const Glib::ustring& fileName) for (auto ver = 12; ver >= 0; --ver) { executable = Glib::build_filename (options.gimpDir, "bin", Glib::ustring::compose (Glib::ustring("gimp-2.%1.exe"), ver)); - auto success = ShellExecute( NULL, "open", executable.c_str(), fileName.c_str(), NULL, SW_SHOWNORMAL ); + auto lsuccess = ShellExecute( NULL, "open", executable.c_str(), fileName.c_str(), NULL, SW_SHOWNORMAL ); - if ((uintptr_t)success > 32) { + if (reinterpret_cast(lsuccess) > 32) { return true; } } @@ -291,7 +290,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 +311,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 +333,7 @@ bool ExtProgStore::openInCustomEditor (const Glib::ustring& fileName) #else - const auto cmdLine = Glib::ustring("\"") + options.customEditorProg + Glib::ustring("\" \"") + fileName + Glib::ustring("\""); + const auto cmdLine = options.customEditorProg + Glib::ustring(" ") + Glib::shell_quote(fileName); return spawnCommandAsync (cmdLine); #endif diff --git a/rtgui/extprog.h b/rtgui/extprog.h index 154a825e1..c5e00bb1b 100644 --- a/rtgui/extprog.h +++ b/rtgui/extprog.h @@ -14,16 +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 . */ - -#ifndef _EXTPROG_ -#define _EXTPROG_ - -#include +#pragma once #include +#include + #include "threadutils.h" struct ExtProgAction @@ -74,5 +72,3 @@ inline const std::vector& ExtProgStore::getActions () const { return actions; } - -#endif diff --git a/rtgui/fattaltonemap.cc b/rtgui/fattaltonemap.cc index 032df6f40..89a1e9e30 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 @@ -23,6 +23,7 @@ #include "fattaltonemap.h" #include "eventmapper.h" +#include "rtimage.h" #include "../rtengine/procparams.h" diff --git a/rtgui/fattaltonemap.h b/rtgui/fattaltonemap.h index e6eafb605..3d36ec7d2 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 @@ -23,7 +23,7 @@ #include "adjuster.h" #include "toolpanel.h" -class FattalToneMapping: public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class FattalToneMapping final : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { protected: Adjuster *threshold; diff --git a/rtgui/favoritbrowser.cc b/rtgui/favoritbrowser.cc index 0e1b4490b..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 ()); diff --git a/rtgui/favoritbrowser.h b/rtgui/favoritbrowser.h index ed522c1c4..7a73b98af 100644 --- a/rtgui/favoritbrowser.h +++ b/rtgui/favoritbrowser.h @@ -14,19 +14,21 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include + #include "dirbrowserremoteinterface.h" #include "dirselectionlistener.h" -class FavoritBrowser : public Gtk::VBox, public DirSelectionListener +class FavoritBrowser : + public Gtk::VBox, + public DirSelectionListener { - - class FavoritColumns : public Gtk::TreeModel::ColumnRecord + class FavoritColumns : + public Gtk::TreeModel::ColumnRecord { public: Gtk::TreeModelColumn > icon; @@ -61,7 +63,3 @@ public: void delPressed (); void selectionChanged (); }; - -#endif - - diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index 513d131a7..42aafd2e0 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -16,11 +16,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 #include -#include +#include #include "filebrowser.h" @@ -28,16 +29,17 @@ #include "clipboard.h" #include "multilangmgr.h" #include "options.h" +#include "paramsedited.h" +#include "profilestorecombobox.h" #include "procparamchangers.h" #include "rtimage.h" #include "threadutils.h" +#include "thumbnail.h" #include "../rtengine/dfmanager.h" #include "../rtengine/ffmanager.h" #include "../rtengine/procparams.h" -extern Options options; - namespace { @@ -89,41 +91,36 @@ ThumbBrowserEntryBase* selectOriginalEntry (ThumbBrowserEntryBase* original, Thu void findOriginalEntries (const std::vector& entries) { - typedef std::vector EntryVector; - typedef EntryVector::const_iterator EntryIterator; - typedef std::map BasenameMap; - typedef BasenameMap::const_iterator BasenameIterator; - // Sort all entries into buckets by basename without extension - BasenameMap byBasename; + std::map> byBasename; - for (EntryIterator entry = entries.begin (); entry != entries.end (); ++entry) { - const Glib::ustring basename = Glib::path_get_basename ((*entry)->filename.lowercase()); + for (const auto entry : entries) { + const auto basename = Glib::path_get_basename(entry->filename.lowercase()); - const Glib::ustring::size_type pos = basename.find_last_of ('.'); - if (pos >= basename.length () - 1) { - (*entry)->setOriginal (nullptr); + const auto pos = basename.find_last_of('.'); + if (pos >= basename.length() - 1) { + entry->setOriginal(nullptr); continue; } - const Glib::ustring withoutExtension = basename.substr (0, pos); + const auto withoutExtension = basename.substr(0, pos); - byBasename[withoutExtension].push_back (*entry); + byBasename[withoutExtension].push_back(entry); } // Find the original image for each bucket - for (BasenameIterator bucket = byBasename.begin (); bucket != byBasename.end (); ++bucket) { - const EntryVector& entries = bucket->second; + for (const auto& bucket : byBasename) { + const auto& lentries = bucket.second; ThumbBrowserEntryBase* original = nullptr; // Select the most likely original in a first pass... - for (EntryIterator entry = entries.begin (); entry != entries.end (); ++entry) { - original = selectOriginalEntry (original, *entry); + for (const auto entry : lentries) { + original = selectOriginalEntry(original, entry); } // ...and link all other images to it in a second pass. - for (EntryIterator entry = entries.begin (); entry != entries.end (); ++entry) { - (*entry)->setOriginal (*entry != original ? original : nullptr); + for (const auto entry : lentries) { + entry->setOriginal(entry != original ? original : nullptr); } } } @@ -486,7 +483,7 @@ FileBrowser::~FileBrowser () delete[] amiExtProg; } -void FileBrowser::rightClicked (ThumbBrowserEntryBase* entry) +void FileBrowser::rightClicked () { { @@ -622,7 +619,7 @@ void FileBrowser::addEntry_ (FileBrowserEntry* entry) initEntry(entry); } - redraw(false); + redraw(entry); } FileBrowserEntry* FileBrowser::delEntry (const Glib::ustring& fname) @@ -839,10 +836,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) { @@ -915,10 +912,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) { @@ -1080,17 +1077,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(); } @@ -1474,12 +1471,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; } @@ -1498,44 +1495,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; } @@ -1544,10 +1519,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 @@ -1555,17 +1530,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)) @@ -1573,7 +1543,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..53f3f1f2b 100644 --- a/rtgui/filebrowser.h +++ b/rtgui/filebrowser.h @@ -14,26 +14,29 @@ * GNU General Public License for more details. * * 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_ +#pragma once + +#include #include -#include -#include "thumbbrowserbase.h" -#include "exiffiltersettings.h" -#include "filebrowserentry.h" + #include "browserfilter.h" -#include "pparamschangelistener.h" -#include "partialpastedlg.h" #include "exportpanel.h" #include "extprog.h" -#include "profilestorecombobox.h" +#include "filebrowserentry.h" +#include "lwbutton.h" +#include "partialpastedlg.h" +#include "pparamschangelistener.h" +#include "../rtengine/profilestore.h" +#include "thumbbrowserbase.h" + +#include "../rtengine/noncopyable.h" -class ProfileStoreLabel; class FileBrowser; class FileBrowserEntry; +class ProfileStoreLabel; class FileBrowserListener { @@ -53,10 +56,11 @@ public: /* * Class handling actions common to all thumbnails of the file browser */ -class FileBrowser : public ThumbBrowserBase, +class FileBrowser final : public ThumbBrowserBase, public LWButtonListener, public ExportPanelListener, - public ProfileStoreListener + public ProfileStoreListener, + public rtengine::NonCopyable { private: typedef sigc::signal type_trash_changed; @@ -168,8 +172,8 @@ public: void buttonPressed (LWButton* button, int actionCode, void* actionData) override; void redrawNeeded (LWButton* button) override; - bool checkFilter (ThumbBrowserEntryBase* entry) override; - void rightClicked (ThumbBrowserEntryBase* entry) override; + bool checkFilter (ThumbBrowserEntryBase* entry) const override; + void rightClicked () override; void doubleClicked (ThumbBrowserEntryBase* entry) override; bool keyPressed (GdkEventKey* event) override; @@ -208,5 +212,3 @@ public: type_trash_changed trash_changed(); }; - -#endif diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc index 4b1764824..3129e93e2 100644 --- a/rtgui/filebrowserentry.cc +++ b/rtgui/filebrowserentry.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 "filebrowserentry.h" #include #include +#include "cropguilistener.h" #include "cursormanager.h" #include "guiutils.h" #include "inspector.h" #include "rtimage.h" #include "threadutils.h" #include "thumbbrowserbase.h" +#include "thumbnail.h" +#include "toolbar.h" #include "../rtengine/procparams.h" @@ -115,7 +118,7 @@ void FileBrowserEntry::calcThumbnailSize () { if (thumbnail) { - thumbnail->getThumbnailSize (prew, preh); + prew = thumbnail->getThumbnailWidth(preh); } } @@ -251,32 +254,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); } } } @@ -318,24 +324,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; @@ -345,7 +363,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; @@ -353,7 +374,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; @@ -361,19 +385,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; @@ -396,7 +429,10 @@ bool FileBrowserEntry::motionNotify (int x, int y) cropParams->h = cy1 - cy2 + 1; } + { + MYREADERLOCK(l, lockRW); updateBackBuffer (); + } parent->redrawNeeded (this); } @@ -564,6 +600,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; } @@ -764,6 +801,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; @@ -779,6 +818,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 5122de55f..67b953514 100644 --- a/rtgui/filebrowserentry.h +++ b/rtgui/filebrowserentry.h @@ -14,29 +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 _FILEBROWSERENTRY_ -#define _FILEBROWSERENTRY_ +#pragma once #include #include #include -#include "../rtengine/rtengine.h" - -#include "crophandler.h" #include "editenums.h" #include "filethumbnailbuttonset.h" #include "imageareatoollistener.h" #include "thumbbrowserentrybase.h" #include "thumbimageupdater.h" -#include "thumbnail.h" #include "thumbnaillistener.h" +#include "../rtengine/noncopyable.h" +#include "../rtengine/rtengine.h" class FileBrowserEntry; +class Thumbnail; + struct FileBrowserEntryIdleHelper { FileBrowserEntry* fbentry; bool destroyed; @@ -44,9 +43,10 @@ struct FileBrowserEntryIdleHelper { }; class FileThumbnailButtonSet; -class FileBrowserEntry : public ThumbBrowserEntryBase, +class FileBrowserEntry final : public ThumbBrowserEntryBase, public ThumbnailListener, - public ThumbImageUpdateListener + public ThumbImageUpdateListener, + public rtengine::NonCopyable { double scale; @@ -107,5 +107,3 @@ public: bool pressNotify (int button, int type, int bstate, int x, int y) override; bool releaseNotify (int button, int type, int bstate, int x, int y) override; }; - -#endif diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index dd54e81fc..8249b7c34 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" @@ -25,22 +25,26 @@ #include #include "../rtengine/rt_math.h" +#include "../rtengine/procparams.h" #include "guiutils.h" #include "options.h" #include "rtimage.h" #include "cachemanager.h" #include "multilangmgr.h" +#include "coarsepanel.h" #include "filepanel.h" #include "renamedlg.h" #include "thumbimageupdater.h" #include "batchqueue.h" +#include "batchqueueentry.h" #include "placesbrowser.h" +#include "pathutils.h" +#include "thumbnail.h" +#include "toolbar.h" using namespace std; -#define CHECKTIME 2000 - FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : filepanel(filepanel), selectedDirectoryId(1), @@ -49,6 +53,8 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : fslistener(nullptr), iatlistener(nullptr), hbToolBar1STB(nullptr), + progressImage(nullptr), + progressLabel(nullptr), hasValidCurrentEFS(false), filterPanel(nullptr), exportPanel(nullptr), @@ -457,8 +463,6 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : hScrollPos[i] = 0; vScrollPos[i] = 0; } - - selectedDirectory = ""; } FileCatalog::~FileCatalog() @@ -604,7 +608,7 @@ std::vector FileCatalog::getFileList() names.push_back(Glib::build_filename(selectedDirectory, fname)); } catch (Glib::Exception& exception) { - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { std::cerr << exception.what() << std::endl; } } @@ -612,7 +616,7 @@ std::vector FileCatalog::getFileList() } catch (Glib::Exception& exception) { - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { std::cerr << "Failed to list directory \"" << selectedDirectory << "\": " << exception.what() << std::endl; } @@ -701,35 +705,38 @@ void FileCatalog::_refreshProgressBar () // The second, usually longer pass is done multithreaded down in the single entries and is NOT measured by this 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::Label *label = nullptr; + if (!progressImage || !progressLabel) { + // create tab label once + Gtk::Notebook *nb = (Gtk::Notebook *)(filepanel->get_parent()); + Gtk::Grid* grid = Gtk::manage(new Gtk::Grid()); + progressImage = Gtk::manage(new RTImage("folder-closed.png")); + progressLabel = Gtk::manage(new Gtk::Label(M("MAIN_FRAME_FILEBROWSER"))); + grid->attach_next_to(*progressImage, options.mainNBVertical ? Gtk::POS_TOP : Gtk::POS_RIGHT, 1, 1); + grid->attach_next_to(*progressLabel, options.mainNBVertical ? Gtk::POS_TOP : Gtk::POS_RIGHT, 1, 1); + grid->set_tooltip_markup(M("MAIN_FRAME_FILEBROWSER_TOOLTIP")); + grid->show_all(); + if (options.mainNBVertical) { + progressLabel->set_angle(90); + } + if (nb) { + nb->set_tab_label(*filepanel, *grid); + } + } if (!previewsToLoad) { - grid->attach_next_to(*Gtk::manage(new RTImage("folder-closed.png")), options.mainNBVertical ? Gtk::POS_TOP : Gtk::POS_RIGHT, 1, 1); + progressImage->changeImage("folder-closed.png"); 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 ? "]" : ")"))); + progressLabel->set_text(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 ) + "%]" )); + progressImage->changeImage("magnifier.png"); + progressLabel->set_text(M("MAIN_FRAME_FILEBROWSER") + " [" + + Glib::ustring::format(previewsLoaded) + "/" + + Glib::ustring::format(previewsToLoad) + "]" ); filepanel->loadingThumbs("", (double)previewsLoaded / previewsToLoad); } - - 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(); - - if (nb) { - nb->set_tab_label(*filepanel, *grid); - } } } @@ -804,28 +811,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); @@ -1220,9 +1227,8 @@ void FileCatalog::developRequested(const std::vector& tbe, bo rtengine::ProcessingJob* pjob = rtengine::ProcessingJob::create (fbe->filename, th->getType() == FT_Raw, params, fastmode && options.fastexport_use_fast_pipeline); - int pw; - int ph = BatchQueue::calcMaxThumbnailHeight(); - th->getThumbnailSize (pw, ph); + const int ph = BatchQueue::calcMaxThumbnailHeight(); + const int pw = th->getThumbnailWidth(ph); // processThumbImage is the processing intensive part, but adding to queue must be ordered //#pragma omp ordered @@ -1603,7 +1609,6 @@ BrowserFilter FileCatalog::getFilter () anyRankFilterActive || anyCLabelFilterActive || anyEditedFilterActive; } - filter.multiselect = false; /* * Step 2 @@ -1619,7 +1624,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; @@ -1656,14 +1660,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; } diff --git a/rtgui/filecatalog.h b/rtgui/filecatalog.h index 964318cb6..5f3623c2c 100644 --- a/rtgui/filecatalog.h +++ b/rtgui/filecatalog.h @@ -14,37 +14,41 @@ * GNU General Public License for more details. * * 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_ +#pragma once -#include "filebrowser.h" -#include "exiffiltersettings.h" -#include -#include "fileselectionlistener.h" #include -#include "fileselectionchangelistener.h" -#include "coarsepanel.h" -#include "toolbar.h" -#include "filterpanel.h" + +#include + +#include "exiffiltersettings.h" #include "exportpanel.h" +#include "filebrowser.h" +#include "fileselectionchangelistener.h" +#include "fileselectionlistener.h" +#include "filterpanel.h" #include "previewloader.h" -#include "multilangmgr.h" #include "threadutils.h" +#include "../rtengine/noncopyable.h" + class FilePanel; +class CoarsePanel; +class ToolBar; + /* * Class: * - handling the list of file (add/remove them) * - handling the thumbnail toolbar, * - monitoring the directory (for any change) */ -class FileCatalog : public Gtk::VBox, +class FileCatalog final : public Gtk::VBox, public PreviewLoaderListener, public FilterPanelListener, public FileBrowserListener, - public ExportPanelListener + public ExportPanelListener, + public rtengine::NonCopyable { public: typedef sigc::slot DirSelectionSlot; @@ -120,6 +124,9 @@ private: Gtk::Button* zoomInButton; Gtk::Button* zoomOutButton; + RTImage* progressImage; + Gtk::Label* progressLabel; + MyMutex dirEFSMutex; ExifFilterSettings dirEFS; ExifFilterSettings currentEFS; @@ -287,5 +294,3 @@ inline void FileCatalog::setDirSelector (const FileCatalog::DirSelectionSlot& se { this->selectDir = selectDir; } - -#endif diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index da33caddf..1a66aed7c 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -14,13 +14,21 @@ * GNU General Public License for more details. * * 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" +#include "dirbrowser.h" +#include "batchtoolpanelcoord.h" +#include "editorpanel.h" #include "rtwindow.h" #include "inspector.h" #include "placesbrowser.h" +#include "thumbnail.h" + +#ifdef WIN32 +#include "windows.h" +#endif FilePanel::FilePanel () : parent(nullptr), error(0) { diff --git a/rtgui/filepanel.h b/rtgui/filepanel.h index df61cb60d..cbfe8e53e 100644 --- a/rtgui/filepanel.h +++ b/rtgui/filepanel.h @@ -14,29 +14,32 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include -#include "batchtoolpanelcoord.h" -#include "filecatalog.h" -#include "dirbrowser.h" -#include "fileselectionlistener.h" -#include "placesbrowser.h" -#include "recentbrowser.h" -#include "pparamschangelistener.h" -#include "history.h" -#include "filterpanel.h" -#include "exportpanel.h" -#include "progressconnector.h" +#include "exportpanel.h" +#include "filecatalog.h" +#include "fileselectionlistener.h" +#include "filterpanel.h" +#include "history.h" +#include "placesbrowser.h" +#include "pparamschangelistener.h" +#include "progressconnector.h" +#include "recentbrowser.h" + +#include "../rtengine/noncopyable.h" + +class BatchToolPanelCoordinator; class RTWindow; +class DirBrowser; class FilePanel final : public Gtk::HPaned, - public FileSelectionListener + public FileSelectionListener, + public rtengine::NonCopyable { public: FilePanel (); @@ -106,6 +109,3 @@ private: IdleRegister idle_register; }; - -#endif - diff --git a/rtgui/fileselectionchangelistener.h b/rtgui/fileselectionchangelistener.h index 5f1b20fcc..64251c1bd 100644 --- a/rtgui/fileselectionchangelistener.h +++ b/rtgui/fileselectionchangelistener.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 _FILESELECTIONCHANGELISTENER_ -#define _FILESELECTIONCHANGELISTENER_ +#pragma once class Thumbnail; @@ -27,6 +26,3 @@ public: virtual ~FileSelectionChangeListener() = default; virtual void selectionChanged(const std::vector& selected) = 0; }; - -#endif - diff --git a/rtgui/fileselectionlistener.h b/rtgui/fileselectionlistener.h index 0cac24d46..394a35f51 100644 --- a/rtgui/fileselectionlistener.h +++ b/rtgui/fileselectionlistener.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 _FILESELECTIONLISTENER_ -#define _FILESELECTIONLISTENER_ +#pragma once -class Thumbnail; class BatchQueueEntry; +class Thumbnail; class FileSelectionListener { @@ -29,6 +28,3 @@ public: virtual bool fileSelected(Thumbnail* thm) = 0; virtual bool addBatchQueueJobs(const std::vector& entries) = 0; }; - -#endif - diff --git a/rtgui/filethumbnailbuttonset.cc b/rtgui/filethumbnailbuttonset.cc index 4c7d8743d..bb64675a1 100644 --- a/rtgui/filethumbnailbuttonset.cc +++ b/rtgui/filethumbnailbuttonset.cc @@ -14,12 +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 . */ #include "filethumbnailbuttonset.h" #include "rtimage.h" #include "multilangmgr.h" +#include "lwbutton.h" +#include "rtsurface.h" bool FileThumbnailButtonSet::iconsLoaded = false; diff --git a/rtgui/filethumbnailbuttonset.h b/rtgui/filethumbnailbuttonset.h index 13265b8c0..868d3b58a 100644 --- a/rtgui/filethumbnailbuttonset.h +++ b/rtgui/filethumbnailbuttonset.h @@ -14,20 +14,21 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include -#include "lwbuttonset.h" #include -#include "filebrowserentry.h" -#include "rtsurface.h" + +#include "lwbuttonset.h" class FileBrowserEntry; -class FileThumbnailButtonSet : public LWButtonSet +class RTSurface; + +class FileThumbnailButtonSet : + public LWButtonSet { static bool iconsLoaded; @@ -55,5 +56,3 @@ public: void setInTrash (bool inTrash); }; - -#endif diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 6e93b2364..90cedf148 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.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/filmnegative.h b/rtgui/filmnegative.h index e967f535c..bca155ceb 100644 --- a/rtgui/filmnegative.h +++ b/rtgui/filmnegative.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 @@ -26,9 +26,6 @@ #include "editcallbacks.h" #include "guiutils.h" #include "toolpanel.h" -#include "wbprovider.h" - -#include "../rtengine/noncopyable.h" class FilmNegProvider { @@ -38,8 +35,7 @@ public: virtual bool getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, std::array& newExps) = 0; }; -class FilmNegative : - public rtengine::NonCopyable, +class FilmNegative final : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, diff --git a/rtgui/filmsimulation.h b/rtgui/filmsimulation.h index b5c9ffa6b..cfe7016bb 100644 --- a/rtgui/filmsimulation.h +++ b/rtgui/filmsimulation.h @@ -1,14 +1,17 @@ -#ifndef FILM_SIMULATION_INCLUDED -#define FILM_SIMULATION_INCLUDED +#pragma once + +#include #include -#include -#include -#include "toolpanel.h" -#include "guiutils.h" -#include "adjuster.h" -class ClutComboBox : public MyComboBox +#include + +#include "adjuster.h" +#include "guiutils.h" +#include "toolpanel.h" + +class ClutComboBox final : + public MyComboBox { public: explicit ClutComboBox(const Glib::ustring &path); @@ -74,5 +77,3 @@ private: Adjuster *m_strength; }; - -#endif diff --git a/rtgui/filterpanel.cc b/rtgui/filterpanel.cc index c140acfb0..2c4fc52d2 100644 --- a/rtgui/filterpanel.cc +++ b/rtgui/filterpanel.cc @@ -107,8 +107,8 @@ FilterPanel::FilterPanel () : listener (nullptr) scamera->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); scamera->set_size_request(-1, 80); scamera->add(*camera); - cvb->pack_start (*scamera, Gtk::PACK_SHRINK, 0); - pack_start (*cvb, Gtk::PACK_SHRINK, 4); + cvb->pack_start (*scamera, Gtk::PACK_EXPAND_WIDGET, 0); + pack_start (*cvb, Gtk::PACK_EXPAND_WIDGET, 4); enaLens = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_LENS") + ":")); Gtk::VBox* lvb = Gtk::manage(new Gtk::VBox ()); @@ -119,8 +119,8 @@ FilterPanel::FilterPanel () : listener (nullptr) slens->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); slens->set_size_request(-1, 80); slens->add(*lens); - lvb->pack_start (*slens, Gtk::PACK_SHRINK, 0); - pack_start (*lvb, Gtk::PACK_SHRINK, 4); + lvb->pack_start (*slens, Gtk::PACK_EXPAND_WIDGET, 0); + pack_start (*lvb, Gtk::PACK_EXPAND_WIDGET, 4); enaFiletype = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_FILETYPE") + ":")); Gtk::VBox* ftvb = Gtk::manage(new Gtk::VBox ()); @@ -131,8 +131,8 @@ FilterPanel::FilterPanel () : listener (nullptr) sfiletype->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); sfiletype->set_size_request(-1, 80); sfiletype->add(*filetype); - ftvb->pack_start (*sfiletype, Gtk::PACK_SHRINK, 0); - pack_start (*ftvb, Gtk::PACK_SHRINK, 4); + ftvb->pack_start (*sfiletype, Gtk::PACK_EXPAND_WIDGET, 0); + pack_start (*ftvb, Gtk::PACK_EXPAND_WIDGET, 4); // add panel ending Gtk::VBox* vboxpe = Gtk::manage (new Gtk::VBox ()); diff --git a/rtgui/filterpanel.h b/rtgui/filterpanel.h index 7f32a88d9..25a368b27 100644 --- a/rtgui/filterpanel.h +++ b/rtgui/filterpanel.h @@ -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 . */ -#ifndef _FILTERPANEL_ -#define _FILTERPANEL_ +#pragma once #include + #include "exiffiltersettings.h" class FilterPanelListener @@ -79,5 +79,3 @@ public: enabled->set_active(enabledState); } }; - -#endif diff --git a/rtgui/flatcurveeditorsubgroup.cc b/rtgui/flatcurveeditorsubgroup.cc index a6b9416d7..1cc3f5c14 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" @@ -32,6 +32,8 @@ #include "curveeditor.h" #include "flatcurveeditorsubgroup.h" #include "rtimage.h" +#include "options.h" +#include "popuptogglebutton.h" #include "../rtengine/curves.h" diff --git a/rtgui/flatcurveeditorsubgroup.h b/rtgui/flatcurveeditorsubgroup.h index f31ad5bbc..79dd5e7d0 100644 --- a/rtgui/flatcurveeditorsubgroup.h +++ b/rtgui/flatcurveeditorsubgroup.h @@ -14,17 +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 . */ -#ifndef _FLATCURVEEDITORSUBGROUP_ -#define _FLATCURVEEDITORSUBGROUP_ +#pragma once #include + #include "curveeditorgroup.h" -class FlatCurveEditor; +#include "../rtengine/noncopyable.h" -class FlatCurveEditorSubGroup: public CurveEditorSubGroup +class FlatCurveEditor; +class MyFlatCurve; + +class FlatCurveEditorSubGroup final : + public CurveEditorSubGroup, + public rtengine::NonCopyable { friend class FlatCurveEditor; @@ -77,5 +82,3 @@ protected: void editPointToggled(Gtk::ToggleButton *button); void editToggled (Gtk::ToggleButton *button); }; - -#endif diff --git a/rtgui/flatfield.cc b/rtgui/flatfield.cc index 25482909e..7433fd4de 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 @@ -25,6 +25,7 @@ #include "rtimage.h" #include "../rtengine/procparams.h" +#include "../rtengine/rawimage.h" using namespace rtengine; using namespace rtengine::procparams; @@ -32,18 +33,17 @@ using namespace rtengine::procparams; FlatField::FlatField () : FoldableToolPanel(this, "flatfield", M("TP_FLATFIELD_LABEL")) { hbff = Gtk::manage(new Gtk::HBox()); - hbff->set_spacing(2); flatFieldFile = Gtk::manage(new MyFileChooserButton(M("TP_FLATFIELD_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); bindCurrentFolder (*flatFieldFile, options.lastFlatfieldDir); ffLabel = Gtk::manage(new Gtk::Label(M("GENERAL_FILE"))); flatFieldFileReset = Gtk::manage(new Gtk::Button()); flatFieldFileReset->set_image (*Gtk::manage(new RTImage ("cancel-small.png"))); - hbff->pack_start(*ffLabel, Gtk::PACK_SHRINK, 0); + hbff->pack_start(*ffLabel, Gtk::PACK_SHRINK); hbff->pack_start(*flatFieldFile); - hbff->pack_start(*flatFieldFileReset, Gtk::PACK_SHRINK, 0); + hbff->pack_start(*flatFieldFileReset, Gtk::PACK_SHRINK); flatFieldAutoSelect = Gtk::manage(new Gtk::CheckButton((M("TP_FLATFIELD_AUTOSELECT")))); - ffInfo = Gtk::manage(new Gtk::Label("")); - ffInfo->set_alignment(0, 0); //left align + ffInfo = Gtk::manage(new Gtk::Label("-")); + setExpandAlignProperties(ffInfo, true, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); flatFieldBlurRadius = Gtk::manage(new Adjuster (M("TP_FLATFIELD_BLURRADIUS"), 0, 200, 2, 32)); flatFieldBlurRadius->setAdjusterListener (this); @@ -54,15 +54,14 @@ FlatField::FlatField () : FoldableToolPanel(this, "flatfield", M("TP_FLATFIELD_L flatFieldBlurRadius->show(); Gtk::HBox* hbffbt = Gtk::manage (new Gtk::HBox ()); - hbffbt->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_FLATFIELD_BLURTYPE") + ":"))); - hbffbt->set_spacing(4); + hbffbt->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_FLATFIELD_BLURTYPE") + ":")), Gtk::PACK_SHRINK); flatFieldBlurType = Gtk::manage (new MyComboBoxText ()); flatFieldBlurType->append(M("TP_FLATFIELD_BT_AREA")); flatFieldBlurType->append(M("TP_FLATFIELD_BT_VERTICAL")); flatFieldBlurType->append(M("TP_FLATFIELD_BT_HORIZONTAL")); flatFieldBlurType->append(M("TP_FLATFIELD_BT_VERTHORIZ")); flatFieldBlurType->set_active(0); - hbffbt->pack_end (*flatFieldBlurType); + hbffbt->pack_end (*flatFieldBlurType, Gtk::PACK_EXPAND_WIDGET); flatFieldClipControl = Gtk::manage (new Adjuster(M("TP_FLATFIELD_CLIPCONTROL"), 0., 100., 1., 0.)); flatFieldClipControl->setAdjusterListener(this); @@ -75,18 +74,17 @@ FlatField::FlatField () : FoldableToolPanel(this, "flatfield", M("TP_FLATFIELD_L flatFieldClipControl->show(); flatFieldClipControl->set_tooltip_markup (M("TP_FLATFIELD_CLIPCONTROL_TOOLTIP")); - pack_start( *hbff, Gtk::PACK_SHRINK, 0); - pack_start( *flatFieldAutoSelect, Gtk::PACK_SHRINK, 0); - pack_start( *ffInfo, Gtk::PACK_SHRINK, 0); - pack_start( *hbffbt, Gtk::PACK_SHRINK, 0); - pack_start( *flatFieldBlurRadius, Gtk::PACK_SHRINK, 0); - pack_start( *flatFieldClipControl, Gtk::PACK_SHRINK, 0); + pack_start( *hbff, Gtk::PACK_SHRINK); + pack_start( *flatFieldAutoSelect, Gtk::PACK_SHRINK); + pack_start( *ffInfo, Gtk::PACK_SHRINK); + pack_start( *hbffbt, Gtk::PACK_SHRINK); + pack_start( *flatFieldBlurRadius, Gtk::PACK_SHRINK); + pack_start( *flatFieldClipControl, Gtk::PACK_SHRINK); flatFieldFileconn = flatFieldFile->signal_file_set().connect ( sigc::mem_fun(*this, &FlatField::flatFieldFileChanged)); //, true); 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; @@ -170,7 +168,7 @@ void FlatField::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi ffInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND"))); } } else { - ffInfo->set_text(""); + ffInfo->set_text("-"); } ffChanged = false; @@ -254,7 +252,7 @@ void FlatField::adjusterChanged(Adjuster* a, double newval) } } -void FlatField::adjusterAutoToggled (Adjuster* a, bool newval) +void FlatField::adjusterAutoToggled (Adjuster* a) { if (multiImage) { if (flatFieldClipControl->getAutoInconsistent()) { @@ -335,7 +333,7 @@ void FlatField::flatFieldFile_Reset() flatFieldFile->set_current_folder(options.lastFlatfieldDir); } - ffInfo->set_text(""); + ffInfo->set_text("-"); if (listener) { listener->panelChanged (EvFlatFieldFile, M("GENERAL_NONE") ); @@ -385,7 +383,7 @@ void FlatField::flatFieldAutoSelectChanged() ffInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND"))); } } else { - ffInfo->set_text(""); + ffInfo->set_text("-"); } if (listener) { diff --git a/rtgui/flatfield.h b/rtgui/flatfield.h index 46e2f6ddd..5cbc49684 100644 --- a/rtgui/flatfield.h +++ b/rtgui/flatfield.h @@ -14,17 +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 _FLATFIELD_H_ -#define _FLATFIELD_H_ +#pragma once #include + #include + #include "adjuster.h" -#include "toolpanel.h" -#include "../rtengine/rawimage.h" #include "guiutils.h" +#include "toolpanel.h" + +namespace rtengine +{ + +class RawImage; + +} class FFProvider { @@ -35,7 +42,7 @@ public: // add other info here }; -class FlatField : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::FlatFieldAutoClipListener +class FlatField final : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::FlatFieldAutoClipListener { protected: @@ -72,7 +79,7 @@ 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 adjusterAutoToggled (Adjuster* a) override; void flatFieldFileChanged (); void flatFieldFile_Reset (); void flatFieldAutoSelectChanged (); @@ -84,5 +91,3 @@ public: }; void flatFieldAutoClipValueChanged(int n = 0) override; }; - -#endif diff --git a/rtgui/gradient.cc b/rtgui/gradient.cc index e0f993dee..fceb6c006 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 ); @@ -424,9 +424,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 05a267a0d..f2be47ccc 100644 --- a/rtgui/gradient.h +++ b/rtgui/gradient.h @@ -1,16 +1,20 @@ /* * This file is part of RawTherapee. */ -#ifndef _GRADIENT_H_ -#define _GRADIENT_H_ +#pragma once #include + #include "adjuster.h" #include "editcallbacks.h" -#include "toolpanel.h" #include "guiutils.h" +#include "toolpanel.h" -class Gradient : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public EditSubscriber +class Gradient final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public EditSubscriber { private: @@ -58,5 +62,3 @@ public: bool drag1(int modifierKey) override; void switchOffEditMode () override; }; - -#endif diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index eb3704076..9a4e71ab4 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -13,14 +13,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 "../rtengine/rt_math.h" #include "guiutils.h" #include "options.h" -#include "../rtengine/rt_math.h" #include "../rtengine/utils.h" #include "../rtengine/procparams.h" #include "rtimage.h" @@ -217,16 +216,6 @@ bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference) } } -void thumbInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh) -{ - - if (options.thumbInterp == 0) { - rtengine::nearestInterp (src, sw, sh, dst, dw, dh); - } else if (options.thumbInterp == 1) { - rtengine::bilinearInterp (src, sw, sh, dst, dw, dh); - } -} - bool confirmOverwrite (Gtk::Window& parent, const std::string& filename) { bool safe = true; @@ -298,17 +287,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 +432,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 +453,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 +466,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 +652,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 +941,26 @@ 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; - } + const double 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; - } + const double 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); - } + const double value2 = rtengine::LIM(value + event->delta_y * step, lowerBound, upperBound); + if (value2 != value) { scroll->set_value(value2); } @@ -1050,8 +1008,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 +1018,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 +1562,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 +1595,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..d4c91734a 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.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 __GUI_UTILS_ -#define __GUI_UTILS_ +#pragma once #include #include @@ -26,19 +25,29 @@ #include +#include "threadutils.h" + #include "../rtengine/coord.h" #include "../rtengine/noncopyable.h" -#include "../rtengine/rtengine.h" -#include "rtimage.h" +namespace rtengine +{ -// for convenience... -#include "pathutils.h" +namespace procparams +{ +class ProcParams; + +struct CropParams; + +} + +} + +class RTImage; Glib::ustring escapeHtmlChars(const Glib::ustring &src); bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference = true); -void thumbInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh); bool confirmOverwrite (Gtk::Window& parent, const std::string& filename); void writeFailed (Gtk::Window& parent, const std::string& filename); void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int imh, int startx, int starty, double scale, const rtengine::procparams::CropParams& cparams, bool drawGuide = true, bool useBgColor = true, bool fullImageVisible = true); @@ -83,7 +92,7 @@ private: * } * */ -class GThreadLock +class GThreadLock final { public: GThreadLock() @@ -101,7 +110,7 @@ public: * * Will relock on destruction. */ -class GThreadUnLock +class GThreadUnLock final { public: GThreadUnLock() @@ -116,7 +125,7 @@ public: #pragma GCC diagnostic pop -class ConnectionBlocker +class ConnectionBlocker final { public: explicit ConnectionBlocker (Gtk::Widget *associatedWidget, sigc::connection& connection) : connection (associatedWidget ? &connection : nullptr), wasBlocked(false) @@ -143,7 +152,7 @@ private: /** * @brief Glue box to control visibility of the MyExpender's content ; also handle the frame around it */ -class ExpanderBox: public Gtk::EventBox +class ExpanderBox final : public Gtk::EventBox { private: Gtk::Container *pC; @@ -176,7 +185,7 @@ public: * * Warning: once you've instantiated this class with a text label or a widget label, you won't be able to revert to the other solution. */ -class MyExpander : public Gtk::VBox +class MyExpander final : public Gtk::VBox { public: typedef sigc::signal type_signal_enabled_toggled; @@ -286,7 +295,7 @@ public: /** * @brief subclass of Gtk::ScrolledWindow in order to handle the scrollwheel */ -class MyScrolledWindow : public Gtk::ScrolledWindow +class MyScrolledWindow final : public Gtk::ScrolledWindow { bool on_scroll_event (GdkEventScroll* event) override; @@ -301,7 +310,7 @@ public: /** * @brief subclass of Gtk::ScrolledWindow in order to handle the large toolbars (wider than available space) */ -class MyScrolledToolbar : public Gtk::ScrolledWindow +class MyScrolledToolbar final : public Gtk::ScrolledWindow { bool on_scroll_event (GdkEventScroll* event) override; @@ -331,7 +340,7 @@ public: /** * @brief subclass of Gtk::ComboBoxText in order to handle the scrollwheel */ -class MyComboBoxText : public Gtk::ComboBoxText +class MyComboBoxText final : public Gtk::ComboBoxText { int naturalWidth, minimumWidth; sigc::connection myConnection; @@ -351,7 +360,7 @@ public: /** * @brief subclass of Gtk::SpinButton in order to handle the scrollwheel */ -class MySpinButton : public Gtk::SpinButton +class MySpinButton final : public Gtk::SpinButton { protected: @@ -366,7 +375,7 @@ public: /** * @brief subclass of Gtk::HScale in order to handle the scrollwheel */ -class MyHScale : public Gtk::HScale +class MyHScale final : public Gtk::HScale { bool on_scroll_event (GdkEventScroll* event) override; @@ -376,7 +385,7 @@ class MyHScale : public Gtk::HScale /** * @brief subclass of Gtk::FileChooserButton in order to handle the scrollwheel */ -class MyFileChooserButton: public Gtk::Button { +class MyFileChooserButton final : public Gtk::Button { private: void show_chooser(); @@ -400,7 +409,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(); @@ -464,14 +473,14 @@ typedef enum RTNav { /** * @brief Handle the switch between text and image to be displayed in the HBox (to be used in a button/toolpanel) */ -class TextOrIcon : public Gtk::HBox +class TextOrIcon final : public Gtk::HBox { public: TextOrIcon (const Glib::ustring &filename, const Glib::ustring &labelTx, const Glib::ustring &tooltipTx); }; -class MyImageMenuItem : public Gtk::MenuItem +class MyImageMenuItem final : public Gtk::MenuItem { private: Gtk::Grid *box; @@ -484,7 +493,7 @@ public: const Gtk::Label* getLabel () const; }; -class MyProgressBar : public Gtk::ProgressBar +class MyProgressBar final : public Gtk::ProgressBar { private: int w; @@ -503,7 +512,7 @@ public: /** * @brief Define a gradient milestone */ -class GradientMilestone +class GradientMilestone final { public: double position; @@ -644,5 +653,3 @@ inline Gtk::Window& getToplevelWindow (Gtk::Widget* widget) { return *static_cast (widget->get_toplevel ()); } - -#endif diff --git a/rtgui/histogrampanel.cc b/rtgui/histogrampanel.cc index 49960b2db..dd0cbde46 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" @@ -24,15 +24,10 @@ #include #include "../rtengine/LUT.h" #include "rtimage.h" -#include "../rtengine/improccoordinator.h" #include "../rtengine/color.h" -#include "../rtengine/opthelper.h" -#include "../rtengine/iccstore.h" using namespace rtengine; -extern Options options; - // // @@ -142,7 +137,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 +146,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 +461,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 +499,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 +612,6 @@ void HistogramRGBArea::on_realize () { Gtk::DrawingArea::on_realize(); - Glib::RefPtr window = get_window(); add_events(Gdk::BUTTON_PRESS_MASK); } @@ -964,7 +959,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,12 +979,11 @@ 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); } void HistogramArea::drawCurve(Cairo::RefPtr &cr, - LUTu & data, double scale, int hsize, int vsize) + const LUTu & data, double scale, int hsize, int vsize) { double s = RTScalable::getScale(); @@ -1019,7 +1013,7 @@ void HistogramArea::drawCurve(Cairo::RefPtr &cr, } void HistogramArea::drawMarks(Cairo::RefPtr &cr, - LUTu & data, double scale, int hsize, int & ui, int & oi) + const LUTu & data, double scale, int hsize, int & ui, int & oi) { int s = 8 * RTScalable::getScale(); @@ -1037,8 +1031,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..cec44ed03 100644 --- a/rtgui/histogrampanel.h +++ b/rtgui/histogrampanel.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 _HISTOGRAMPANEL_ -#define _HISTOGRAMPANEL_ - +#pragma once #include -#include -#include -#include "../rtengine/LUT.h" -#include "../rtengine/improccoordinator.h" -#include "guiutils.h" +#include + +#include + +#include "guiutils.h" #include "pointermotionlistener.h" +#include "../rtengine/LUT.h" +#include "../rtengine/noncopyable.h" + class HistogramArea; + struct HistogramAreaIdleHelper { HistogramArea* harea; bool destroyed; @@ -51,7 +53,7 @@ public: double log (double vsize, double val); }; -class HistogramRGBArea : public Gtk::DrawingArea, public BackBuffer, private HistogramScaling +class HistogramRGBArea final : public Gtk::DrawingArea, public BackBuffer, private HistogramScaling, public rtengine::NonCopyable { private: typedef const double (*TMatrix)[3]; @@ -114,7 +116,7 @@ public: virtual void toggleButtonMode() = 0; }; -class HistogramArea : public Gtk::DrawingArea, public BackBuffer, private HistogramScaling +class HistogramArea final : public Gtk::DrawingArea, public BackBuffer, private HistogramScaling, public rtengine::NonCopyable { public: typedef sigc::signal type_signal_factor_changed; @@ -163,8 +165,8 @@ public: type_signal_factor_changed signal_factor_changed(); private: - void drawCurve(Cairo::RefPtr &cr, LUTu & data, double scale, int hsize, int vsize); - void drawMarks(Cairo::RefPtr &cr, LUTu & data, double scale, int hsize, int & ui, int & oi); + void drawCurve(Cairo::RefPtr &cr, const LUTu & data, double scale, int hsize, int vsize); + void drawMarks(Cairo::RefPtr &cr, const LUTu & data, double scale, int hsize, int & ui, int & oi); Gtk::SizeRequestMode get_request_mode_vfunc () const override; void get_preferred_height_vfunc (int& minimum_height, int& natural_height) const override; void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const override; @@ -172,7 +174,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 final : public Gtk::Grid, public PointerMotionListener, public DrawModeListener, public rtengine::NonCopyable { protected: @@ -251,5 +253,3 @@ public: // drawModeListener interface void toggleButtonMode () override; }; - -#endif diff --git a/rtgui/history.cc b/rtgui/history.cc index 5051c1158..1a9cc1258 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..faebe4765 100644 --- a/rtgui/history.h +++ b/rtgui/history.h @@ -14,16 +14,17 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include -#include "../rtengine/rtengine.h" + +#include "paramsedited.h" #include "pparamschangelistener.h" #include "profilechangelistener.h" -#include "paramsedited.h" + +#include "../rtengine/rtengine.h" class HistoryBeforeLineListener { @@ -135,5 +136,3 @@ public: bmnum = 1; }; }; - -#endif diff --git a/rtgui/hsvequalizer.cc b/rtgui/hsvequalizer.cc index f489696d2..ee3eb90a7 100644 --- a/rtgui/hsvequalizer.cc +++ b/rtgui/hsvequalizer.cc @@ -12,12 +12,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 . * * 2010 Ilya Popov */ #include "hsvequalizer.h" +#include "curveeditor.h" +#include "curveeditorgroup.h" +#include "options.h" + #include "../rtengine/color.h" #include "../rtengine/procparams.h" diff --git a/rtgui/hsvequalizer.h b/rtgui/hsvequalizer.h index 8d34b486b..77c1ee1b0 100644 --- a/rtgui/hsvequalizer.h +++ b/rtgui/hsvequalizer.h @@ -12,24 +12,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 . * * 2010 Ilya Popov */ - -#ifndef HSVEQUALIZER_H_INCLUDED -#define HSVEQUALIZER_H_INCLUDED +#pragma once #include -#include "adjuster.h" -#include "toolpanel.h" -#include "guiutils.h" -#include "curveeditor.h" -#include "curveeditorgroup.h" + #include "colorprovider.h" +#include "curvelistener.h" +#include "guiutils.h" +#include "toolpanel.h" +class CurveEditor; +class CurveEditorGroup; +class FlatCurveEditor; -class HSVEqualizer : public ToolParamBlock, public FoldableToolPanel, public CurveListener, public ColorProvider +class HSVEqualizer final : + public ToolParamBlock, + public FoldableToolPanel, + public CurveListener, + public ColorProvider { protected: @@ -53,8 +57,5 @@ public: void autoOpenCurve () override; void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) override; - //void adjusterChanged (Adjuster* a, double newval); void enabledChanged() override; }; - -#endif diff --git a/rtgui/iccprofilecreator.cc b/rtgui/iccprofilecreator.cc index 0ab1ac61d..a8f9be007 100644 --- a/rtgui/iccprofilecreator.cc +++ b/rtgui/iccprofilecreator.cc @@ -15,27 +15,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 +#include + #include #include "iccprofilecreator.h" +#include "../rtengine/iccstore.h" #include "multilangmgr.h" #include "cachemanager.h" -#include "addsetids.h" #include "../rtengine/color.h" +#include "options.h" +#include "pathutils.h" #include "rtimage.h" -#ifdef _OPENMP -#include -#endif - -extern Options options; - -namespace rtengine -{ - -extern const Settings* settings; - -} +#include "rtwindow.h" const char* sTRCPreset[] = {"BT709_g2.2_s4.5", "sRGB_g2.4_s12.92", "linear_g1.0", "standard_g2.2", "standard_g1.8", "High_g1.3_s3.35", "Low_g2.6_s6.9", "Lab_g3.0s9.03296"}; //gamma free @@ -674,8 +669,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; @@ -687,11 +680,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; @@ -703,32 +694,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 5265d5ab2..8ee46a71d 100644 --- a/rtgui/iccprofilecreator.h +++ b/rtgui/iccprofilecreator.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 + #include #include "adjuster.h" -#include "options.h" #include -#include "rtwindow.h" -class ICCProfileCreator : public Gtk::Dialog, public AdjusterListener +class RTWindow; + +class ICCProfileCreator final : public Gtk::Dialog, public AdjusterListener { private: diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index e7efa20e9..3e3c0508c 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 @@ -23,6 +23,7 @@ #include "eventmapper.h" #include "guiutils.h" #include "options.h" +#include "pathutils.h" #include "rtimage.h" #include "../rtengine/dcp.h" @@ -32,9 +33,7 @@ using namespace rtengine; 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 +303,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)); @@ -617,8 +614,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(); diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index a03bd6fa7..cc46c5d37 100644 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -14,18 +14,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 . */ -#ifndef _ICMPANEL_ -#define _ICMPANEL_ +#pragma once #include + #include + #include "adjuster.h" #include "guiutils.h" - -#include "toolpanel.h" #include "popupbutton.h" +#include "toolpanel.h" + #include "../rtengine/imagedata.h" class ICMPanelListener @@ -35,7 +36,7 @@ public: virtual void saveInputICCReference(const Glib::ustring& fname, bool apply_wb) = 0; }; -class ICMPanel : +class ICMPanel final : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel @@ -148,5 +149,3 @@ public: icmplistener = ipl; } }; - -#endif diff --git a/rtgui/ilabel.cc b/rtgui/ilabel.cc deleted file mode 100644 index 65040b93b..000000000 --- a/rtgui/ilabel.cc +++ /dev/null @@ -1,66 +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 "ilabel.h" - -ILabel::ILabel (const Glib::ustring &lab) : label(lab) {} - -void ILabel::on_realize() -{ - - Gtk::DrawingArea::on_realize(); - add_events(Gdk::EXPOSURE_MASK); - - Glib::RefPtr fn = create_pango_layout(label); - fn->set_markup (label); - int labw, labh; - fn->get_pixel_size (labw, labh); - set_size_request (2 + labw, 2 + labh); -} - -bool ILabel::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) -{ - - Glib::RefPtr style = get_style_context (); - - Gtk::StateFlags state = get_state_flags(); - Gdk::RGBA c = style->get_background_color(state); - cr->set_source_rgb (c.get_red(), c.get_green(), c.get_blue()); - cr->rectangle (0, 0, get_width (), get_height()); - cr->fill (); - - Glib::RefPtr fn = create_pango_layout (label); - fn->set_markup (label); - cr->move_to(1., 1.); - fn->add_to_cairo_context(cr); - c = style->get_color (state); - cr->set_source_rgb (c.get_red(), c.get_green(), c.get_blue()); - cr->fill(); - - return true; -} - -void ILabel::on_style_updated () -{ - - Glib::RefPtr fn = create_pango_layout(label); - fn->set_markup (label); - int labw, labh; - fn->get_pixel_size (labw, labh); - set_size_request (2 + labw, 2 + labh); -} diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index c417f6837..22e140e7d 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 @@ -25,11 +25,11 @@ #include "../rtengine/refreshmap.h" #include "../rtengine/procparams.h" #include "options.h" +#include "rtscalable.h" ImageArea::ImageArea (ImageAreaPanel* p) : parent(p), fullImageWidth(0), fullImageHeight(0) { - infotext = ""; cropgl = nullptr; pmlistener = nullptr; pmhlistener = nullptr; @@ -148,7 +148,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 +160,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; diff --git a/rtgui/imagearea.h b/rtgui/imagearea.h index 72e679da6..ad6fd305f 100644 --- a/rtgui/imagearea.h +++ b/rtgui/imagearea.h @@ -14,26 +14,31 @@ * GNU General Public License for more details. * * 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__ +#pragma once #include + #include "cropguilistener.h" -#include "imageareapanel.h" -#include "editenums.h" -#include "toolbar.h" -#include "previewhandler.h" -#include "imageareatoollistener.h" #include "cropwindow.h" #include "editcallbacks.h" -#include "zoompanel.h" +#include "editenums.h" +#include "imageareapanel.h" +#include "imageareatoollistener.h" #include "indclippedpanel.h" +#include "previewhandler.h" #include "previewmodepanel.h" +#include "toolbar.h" +#include "zoompanel.h" class ImageAreaPanel; -class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public EditDataProvider, public LockablePickerToolListener + +class ImageArea final : + public Gtk::DrawingArea, + public CropWindowListener, + public EditDataProvider, + public LockablePickerToolListener { friend class ZoomPanel; @@ -160,7 +165,3 @@ public: return mainCropWindow; } }; - - - -#endif 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..f52ca9060 100644 --- a/rtgui/imageareapanel.h +++ b/rtgui/imageareapanel.h @@ -14,15 +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 . */ -#ifndef _IMAGEAREAPANEL_ -#define _IMAGEAREAPANEL_ +#pragma once #include "imagearea.h" class ImageArea; -class ImageAreaPanel : public Gtk::VBox + +class ImageAreaPanel final : + public Gtk::VBox { protected: @@ -42,5 +43,3 @@ public: void setBeforeAfterViews (ImageAreaPanel* bef, ImageAreaPanel* aft); void syncBeforeAfterViews(); }; - -#endif diff --git a/rtgui/imageareatoollistener.h b/rtgui/imageareatoollistener.h index 705888676..b022aa4b7 100644 --- a/rtgui/imageareatoollistener.h +++ b/rtgui/imageareatoollistener.h @@ -14,15 +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 _IMAGEAREATOOLLISTENER_ -#define _IMAGEAREATOOLLISTENER_ - -#include "toolbar.h" -#include "thumbnail.h" -#include "cropguilistener.h" +#pragma once +class CropGUIListener; +class Thumbnail; +class ToolBar; class ImageAreaToolListener { @@ -36,6 +34,3 @@ public: virtual ToolBar* getToolBar() const = 0; virtual CropGUIListener* startCropEditing(Thumbnail* thm = nullptr) = 0; }; - -#endif - diff --git a/rtgui/impulsedenoise.cc b/rtgui/impulsedenoise.cc index d4ecebfb5..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 diff --git a/rtgui/impulsedenoise.h b/rtgui/impulsedenoise.h index ae6aaa6a8..b8acafcfc 100644 --- a/rtgui/impulsedenoise.h +++ b/rtgui/impulsedenoise.h @@ -14,16 +14,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 . */ -#ifndef _IMPULSEDENOISE_H_ -#define _IMPULSEDENOISE_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -class ImpulseDenoise : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class ImpulseDenoise final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -45,5 +48,3 @@ public: void setAdjusterBehavior (bool threshadd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; - -#endif 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..1017b58f1 100644 --- a/rtgui/indclippedpanel.h +++ b/rtgui/indclippedpanel.h @@ -13,16 +13,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 _INDCLIPPEDPANEL_ -#define _INDCLIPPEDPANEL_ +#pragma once -#include #include +#include + class ImageArea; -class IndicateClippedPanel : public Gtk::HBox + +class IndicateClippedPanel : + public Gtk::HBox { protected: @@ -59,5 +61,3 @@ public: return indClippedH->get_active(); } }; - -#endif diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc index a183a3419..9002cc389 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" @@ -22,9 +22,10 @@ #include "cursormanager.h" #include "guiutils.h" #include "options.h" +#include "pathutils.h" +#include "rtscalable.h" #include "../rtengine/previewimage.h" - -extern Options options; +#include "../rtengine/rt_math.h" InspectorBuffer::InspectorBuffer(const Glib::ustring &imagePath) : currTransform(0), fromRaw(false) { @@ -83,7 +84,6 @@ InspectorBuffer::~InspectorBuffer() { Inspector::Inspector () : currImage(nullptr), zoom(0.0), active(false) { - Glib::RefPtr style = get_style_context(); set_name("Inspector"); } @@ -115,7 +115,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 +124,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 +137,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 86ad9114e..1526f90be 100644 --- a/rtgui/inspector.h +++ b/rtgui/inspector.h @@ -14,14 +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 . */ -#ifndef _INSPECTOR_ -#define _INSPECTOR_ +#pragma once #include + #include "guiutils.h" + #include "../rtengine/coord.h" +#include "../rtengine/coord2d.h" class InspectorBuffer { @@ -38,7 +40,7 @@ public: //~InspectorBuffer(); }; -class Inspector : public Gtk::DrawingArea +class Inspector final : public Gtk::DrawingArea { private: @@ -99,5 +101,3 @@ public: void get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const override; }; - -#endif diff --git a/rtgui/iptcpanel.cc b/rtgui/iptcpanel.cc index 7347927a0..25cd20560 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 "iptcpanel.h" #include "clipboard.h" diff --git a/rtgui/iptcpanel.h b/rtgui/iptcpanel.h index 25683ccec..100904d1a 100644 --- a/rtgui/iptcpanel.h +++ b/rtgui/iptcpanel.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 _IPTCPANEL_ -#define _IPTCPANEL_ +#pragma once #include @@ -26,7 +25,9 @@ #include "guiutils.h" #include "toolpanel.h" -class IPTCPanel : public Gtk::VBox, public ToolPanel +class IPTCPanel final : + public Gtk::VBox, + public ToolPanel { private: @@ -92,5 +93,3 @@ public: void copyClicked (); void pasteClicked (); }; - -#endif diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc index 4b25c1e4f..491b02c4c 100644 --- a/rtgui/labcurve.cc +++ b/rtgui/labcurve.cc @@ -14,12 +14,17 @@ * GNU General Public License for more details. * * 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 "labcurve.h" +#include "curveeditor.h" +#include "curveeditorgroup.h" +#include "options.h" + +#include "../rtengine/color.h" #include "../rtengine/improcfun.h" #include "../rtengine/procparams.h" #include "editcallbacks.h" @@ -29,9 +34,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 +100,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 +115,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 +173,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 +205,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); diff --git a/rtgui/labcurve.h b/rtgui/labcurve.h index db75a686a..e8488a8c6 100644 --- a/rtgui/labcurve.h +++ b/rtgui/labcurve.h @@ -14,21 +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 _LABCURVE_H_ -#define _LABCURVE_H_ +#pragma once #include + #include "adjuster.h" -#include "toolpanel.h" -#include "curveeditor.h" -#include "curveeditorgroup.h" #include "colorprovider.h" +#include "curvelistener.h" +#include "toolpanel.h" +class CurveEditorGroup; +class DiagonalCurveEditor; class EditDataProvider; +class FlatCurveEditor; -class LCurve : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider +class LCurve final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public CurveListener, + public ColorProvider { protected: @@ -97,5 +104,3 @@ public: void enabledChanged() override; }; - -#endif diff --git a/rtgui/labgrid.cc b/rtgui/labgrid.cc index 4576885e8..516dbb825 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,12 +33,14 @@ 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" +#include "../rtengine/color.h" #include "options.h" +#include "rtimage.h" using rtengine::Color; diff --git a/rtgui/labgrid.h b/rtgui/labgrid.h index dbb0cc427..4693c897c 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 @@ -43,7 +43,7 @@ #include "toolpanel.h" -class LabGridArea: public Gtk::DrawingArea, public BackBuffer { +class LabGridArea final : public Gtk::DrawingArea, public BackBuffer { private: rtengine::ProcEvent evt; Glib::ustring evtMsg; diff --git a/rtgui/lensgeom.cc b/rtgui/lensgeom.cc index baf816c8b..762726107 100644 --- a/rtgui/lensgeom.cc +++ b/rtgui/lensgeom.cc @@ -14,9 +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 . */ #include "lensgeom.h" + +#include "eventmapper.h" #include "guiutils.h" #include "rtimage.h" @@ -28,6 +30,18 @@ using namespace rtengine::procparams; LensGeometry::LensGeometry () : FoldableToolPanel(this, "lensgeom", M("TP_LENSGEOM_LABEL")), rlistener(nullptr), lastFill(false) { + auto m = ProcEventMapper::getInstance(); + EvTransMethod = m->newEvent(TRANSFORM, "HISTORY_MSG_TRANS_METHOD"); + + Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); + hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_DMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); + method = Gtk::manage (new MyComboBoxText ()); + method->append(M("TP_LENSGEOM_LOG")); + method->append(M("TP_LENSGEOM_LIN")); + method->set_active(0); + hb1->pack_end (*method, Gtk::PACK_EXPAND_WIDGET, 4); + pack_start( *hb1, Gtk::PACK_SHRINK, 4); + fill = Gtk::manage (new Gtk::CheckButton (M("TP_LENSGEOM_FILL"))); pack_start (*fill); @@ -39,8 +53,9 @@ LensGeometry::LensGeometry () : FoldableToolPanel(this, "lensgeom", M("TP_LENSGE packBox = Gtk::manage (new ToolParamBlock ()); pack_start (*packBox); - autoCrop->signal_pressed().connect( sigc::mem_fun(*this, &LensGeometry::autoCropPressed) ); - fillConn = fill->signal_toggled().connect( sigc::mem_fun(*this, &LensGeometry::fillPressed) ); + method->connect(method->signal_changed().connect(sigc::mem_fun(*this, &LensGeometry::methodChanged))); + autoCrop->signal_pressed().connect(sigc::mem_fun(*this, &LensGeometry::autoCropPressed)); + fillConn = fill->signal_toggled().connect(sigc::mem_fun(*this, &LensGeometry::fillPressed)); fill->set_active (true); show_all (); @@ -55,8 +70,14 @@ void LensGeometry::read (const ProcParams* pp, const ParamsEdited* pedited) { disableListener (); + method->block (true); + method->set_active(pp->commonTrans.method == "log" ? 0 : 1); if (pedited) { + if(!pedited->commonTrans.method) { + method->set_active_text(M("GENERAL_UNCHANGED")); + } + fill->set_inconsistent (!pedited->commonTrans.autofill); } @@ -67,15 +88,20 @@ void LensGeometry::read (const ProcParams* pp, const ParamsEdited* pedited) lastFill = pp->commonTrans.autofill; + method->block (false); enableListener (); } void LensGeometry::write (ProcParams* pp, ParamsEdited* pedited) { - + int currentRow = method->get_active_row_number(); + if( currentRow >= 0 && method->get_active_text() != M("GENERAL_UNCHANGED")) { + pp->commonTrans.method = currentRow == 0 ? "log" : "lin"; + } pp->commonTrans.autofill = fill->get_active (); if (pedited) { + pedited->commonTrans.method = method->get_active_text() != M("GENERAL_UNCHANGED"); pedited->commonTrans.autofill = !fill->get_inconsistent(); } } @@ -115,6 +141,14 @@ void LensGeometry::fillPressed () } } +void LensGeometry::methodChanged () +{ + + if (listener && method->get_active_row_number() >= 0) { + listener->panelChanged(EvTransMethod, method->get_active_text()); + } +} + void LensGeometry::setBatchMode (bool batchMode) { diff --git a/rtgui/lensgeom.h b/rtgui/lensgeom.h index 20bb4b7eb..73c28b006 100644 --- a/rtgui/lensgeom.h +++ b/rtgui/lensgeom.h @@ -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 . */ -#ifndef _LENSGEOM_H_ -#define _LENSGEOM_H_ +#pragma once #include -#include "toolpanel.h" -#include "lensgeomlistener.h" -class LensGeometry : public ToolParamBlock, public FoldableToolPanel +#include "lensgeomlistener.h" +#include "toolpanel.h" + +class LensGeometry final : + public ToolParamBlock, + public FoldableToolPanel { protected: + MyComboBoxText* method; Gtk::Button* autoCrop; LensGeomListener* rlistener; Gtk::CheckButton* fill; @@ -34,6 +37,7 @@ protected: sigc::connection fillConn; ToolParamBlock* packBox; + rtengine::ProcEvent EvTransMethod; public: LensGeometry (); @@ -48,6 +52,7 @@ public: void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; void setBatchMode (bool batchMode) override; + void methodChanged(); void fillPressed (); void autoCropPressed (); void setLensGeomListener (LensGeomListener* l) @@ -58,5 +63,3 @@ public: private: IdleRegister idle_register; }; - -#endif diff --git a/rtgui/lensgeomlistener.h b/rtgui/lensgeomlistener.h index c6ba966b1..7bfa0fb45 100644 --- a/rtgui/lensgeomlistener.h +++ b/rtgui/lensgeomlistener.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 _LENSGEOMLISTENER_H_ -#define _LENSGEOMLISTENER_H_ +#pragma once class LensGeomListener { @@ -27,5 +26,3 @@ public: virtual void autoCropRequested () = 0; virtual double autoDistorRequested () = 0; }; - -#endif diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index 0dd3cb1b7..1a8391f66 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -14,13 +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 . */ #include #include +#include #include -#include +#include #include "lensprofile.h" @@ -585,22 +586,23 @@ void LensProfilePanel::onCorrModeChanged(const Gtk::RadioButton* rbChanged) LensProfilePanel::LFDbHelper::LFDbHelper() { + lensfunCameraModel = Gtk::TreeStore::create(lensfunModelCam); + lensfunLensModel = Gtk::TreeStore::create(lensfunModelLens); + #ifdef _OPENMP -#pragma omp parallel sections if (!options.rtSettings.verbose) +#pragma omp parallel sections if (!settings->verbose) #endif { #ifdef _OPENMP #pragma omp section #endif { - lensfunCameraModel = Gtk::TreeStore::create(lensfunModelCam); fillLensfunCameras(); } #ifdef _OPENMP #pragma omp section #endif { - lensfunLensModel = Gtk::TreeStore::create(lensfunModelLens); fillLensfunLenses(); } } @@ -608,7 +610,7 @@ LensProfilePanel::LFDbHelper::LFDbHelper() void LensProfilePanel::LFDbHelper::fillLensfunCameras() { - if (options.rtSettings.verbose) { + if (settings->verbose) { std::cout << "LENSFUN, scanning cameras:" << std::endl; } @@ -618,7 +620,7 @@ void LensProfilePanel::LFDbHelper::fillLensfunCameras() for (const auto& c : camlist) { camnames[c.getMake()].insert(c.getModel()); - if (options.rtSettings.verbose) { + if (settings->verbose) { std::cout << " found: " << c.getDisplayString().c_str() << std::endl; } } @@ -638,7 +640,7 @@ void LensProfilePanel::LFDbHelper::fillLensfunCameras() void LensProfilePanel::LFDbHelper::fillLensfunLenses() { - if (options.rtSettings.verbose) { + if (settings->verbose) { std::cout << "LENSFUN, scanning lenses:" << std::endl; } @@ -650,7 +652,7 @@ void LensProfilePanel::LFDbHelper::fillLensfunLenses() const auto& make = l.getMake(); lenses[make].insert(name); - if (options.rtSettings.verbose) { + if (settings->verbose) { std::cout << " found: " << l.getDisplayString().c_str() << std::endl; } } @@ -760,7 +762,7 @@ bool LensProfilePanel::checkLensfunCanCorrect(bool automatch) rtengine::procparams::ProcParams lpp; write(&lpp); - const std::unique_ptr mod(LFDatabase::findModifier(lpp.lensProf, metadata, 100, 100, lpp.coarse, -1)); + const std::unique_ptr mod(LFDatabase::getInstance()->findModifier(lpp.lensProf, metadata, 100, 100, lpp.coarse, -1)); return static_cast(mod); } diff --git a/rtgui/lensprofile.h b/rtgui/lensprofile.h index 76c15aa9a..7b5b7343c 100644 --- a/rtgui/lensprofile.h +++ b/rtgui/lensprofile.h @@ -14,14 +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 . */ #pragma once #include #include "guiutils.h" -#include "lensgeom.h" #include "toolpanel.h" class LensProfilePanel final : diff --git a/rtgui/localcontrast.cc b/rtgui/localcontrast.cc index cc4922a65..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 diff --git a/rtgui/localcontrast.h b/rtgui/localcontrast.h index 529c95c89..d1d25fb3d 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 @@ -23,7 +23,7 @@ #include "adjuster.h" #include "toolpanel.h" -class LocalContrast: public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class LocalContrast final : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { private: Adjuster *radius; diff --git a/rtgui/locallab.cc b/rtgui/locallab.cc index 3417bccc2..d12bd3fa9 100644 --- a/rtgui/locallab.cc +++ b/rtgui/locallab.cc @@ -1,11 +1,11 @@ /* * This file is part of RawTherapee. * - * Copyright (c) 2004-2010 Gabor Horvath frame - * + * 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 + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as publishfed by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * @@ -20,7 +20,6 @@ * 2019 Pierre Cabrera */ #include "locallab.h" - #include "options.h" #include "../rtengine/procparams.h" @@ -161,10 +160,12 @@ Locallab::Locallab(): expsharp(Gtk::manage(new LocallabSharp())), expcontrast(Gtk::manage(new LocallabContrast())), expcbdl(Gtk::manage(new LocallabCBDL())), - expdenoi(Gtk::manage(new LocallabDenoise())) -{ - const bool showtooltip = options.showtooltip; + expdenoi(Gtk::manage(new LocallabDenoise())), + explog(Gtk::manage(new LocallabLog())), + // Other widgets + resetshowButton(Gtk::manage(new Gtk::Button(M("TP_LOCALLAB_RESETSHOW")))) +{ // Create panel widget to receive Locallab GUI elements ToolVBox* const panel = Gtk::manage(new ToolVBox()); panel->set_spacing(2); @@ -198,6 +199,14 @@ Locallab::Locallab(): addTool(toolpanel, expdenoi); panel->pack_start(*toolpanel, false, false); + // Add separator + Gtk::HSeparator* const separator2 = Gtk::manage(new Gtk::HSeparator()); + panel->pack_start(*separator2, false, false); + + // Add mask reset button to panel widget + resetshowButton->signal_pressed().connect(sigc::mem_fun(*this, &Locallab::resetshowPressed)); + panel->pack_start(*resetshowButton); + // Add panel widget to Locallab GUI pack_start(*panel); @@ -212,6 +221,7 @@ Locallab::Locallab(): void Locallab::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { // printf("Locallab read\n"); + const int complexsoft = options.complexity; // Disable all listeners disableListener(); @@ -254,16 +264,19 @@ void Locallab::read(const rtengine::procparams::ProcParams* pp, const ParamsEdit r->sensiexclu = pp->locallab.spots.at(i).sensiexclu; r->structexclu = pp->locallab.spots.at(i).structexclu; - r->struc = pp->locallab.spots.at(i).struc; - if (pp->locallab.spots.at(i).shapeMethod == "IND") { - r->shapeMethod = 0; - } else if (pp->locallab.spots.at(i).shapeMethod == "SYM") { - r->shapeMethod = 1; - } else if (pp->locallab.spots.at(i).shapeMethod == "INDSL") { - r->shapeMethod = 2; + if (complexsoft < 2) { + if (pp->locallab.spots.at(i).shapeMethod == "IND") { + r->shapeMethod = 0; + } else if (pp->locallab.spots.at(i).shapeMethod == "SYM") { + r->shapeMethod = 1; + } else if (pp->locallab.spots.at(i).shapeMethod == "INDSL") { + r->shapeMethod = 2; + } else { + r->shapeMethod = 3; + } } else { - r->shapeMethod = 3; + r->shapeMethod = 0; } r->locX = pp->locallab.spots.at(i).locX; @@ -281,12 +294,50 @@ void Locallab::read(const rtengine::procparams::ProcParams* pp, const ParamsEdit } r->transit = pp->locallab.spots.at(i).transit; + + if (complexsoft < 2) { + r->transitweak = pp->locallab.spots.at(i).transitweak; + r->transitgrad = pp->locallab.spots.at(i).transitgrad; + } else { + r->transitweak = 1.; + r->transitgrad = 0.; + } + + r->feather = pp->locallab.spots.at(i).feather; + r->struc = pp->locallab.spots.at(i).struc; r->thresh = pp->locallab.spots.at(i).thresh; r->iter = pp->locallab.spots.at(i).iter; r->balan = pp->locallab.spots.at(i).balan; - r->transitweak = pp->locallab.spots.at(i).transitweak; - r->transitgrad = pp->locallab.spots.at(i).transitgrad; + r->balanh = pp->locallab.spots.at(i).balanh; + r->colorde = pp->locallab.spots.at(i).colorde; r->avoid = pp->locallab.spots.at(i).avoid; + r->recurs = pp->locallab.spots.at(i).recurs; + r->laplac = pp->locallab.spots.at(i).laplac; + r->deltae = pp->locallab.spots.at(i).deltae; + r->scopemask = pp->locallab.spots.at(i).scopemask; + r->shortc = pp->locallab.spots.at(i).shortc; + r->lumask = pp->locallab.spots.at(i).lumask; + r->savrest = pp->locallab.spots.at(i).savrest; + + if (pp->locallab.spots.at(i).complexMethod == "sim") { + r->complexMethod = 0; + } else if (pp->locallab.spots.at(i).complexMethod == "mod") { + r->complexMethod = 1; + } else if (pp->locallab.spots.at(i).complexMethod == "all") { + r->complexMethod = 2; + } + + if (pp->locallab.spots.at(i).wavMethod == "D2") { + r->wavMethod = 0; + } else if (pp->locallab.spots.at(i).wavMethod == "D4") { + r->wavMethod = 1; + } else if (pp->locallab.spots.at(i).wavMethod == "D6") { + r->wavMethod = 2; + } else if (pp->locallab.spots.at(i).wavMethod == "D10") { + r->wavMethod = 3; + } else if (pp->locallab.spots.at(i).wavMethod == "D14") { + r->wavMethod = 4; + } expsettings->addControlSpot(r); } @@ -342,7 +393,7 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited const int spotPanelEvent = expsettings->getEventType(); int spotIndex; ControlSpotPanel::SpotRow* r; - LocallabParams::LocallabSpot* newSpot; + rtengine::procparams::LocallabParams::LocallabSpot* newSpot; int imW, imH; // Size of image int prW, prH; // Size of preview area @@ -373,7 +424,6 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited r->sensiexclu = newSpot->sensiexclu; r->structexclu = newSpot->structexclu; - r->struc = newSpot->struc; if (newSpot->shapeMethod == "IND") { r->shapeMethod = 0; @@ -419,12 +469,44 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited } r->transit = newSpot->transit; + r->transitweak = newSpot->transitweak; + r->transitgrad = newSpot->transitgrad; + r->feather = newSpot->feather; + r->struc = newSpot->struc; r->thresh = newSpot->thresh; r->iter = newSpot->iter; r->balan = newSpot->balan; - r->transitweak = newSpot->transitweak; - r->transitgrad = newSpot->transitgrad; + r->balanh = newSpot->balanh; + r->colorde = newSpot->colorde; r->avoid = newSpot->avoid; + r->recurs = newSpot->recurs; + r->laplac = newSpot->laplac; + r->deltae = newSpot->deltae; + r->scopemask = newSpot->scopemask; + r->shortc = newSpot->shortc; + r->lumask = newSpot->lumask; + r->savrest = newSpot->savrest; + + if (newSpot->complexMethod == "sim") { + r->complexMethod = 0; + } else if (newSpot->complexMethod == "mod") { + r->complexMethod = 1; + } else if (newSpot->complexMethod == "all") { + r->complexMethod = 2; + } + + if (newSpot->wavMethod == "D2") { + r->wavMethod = 0; + } else if (newSpot->wavMethod == "D4") { + r->wavMethod = 1; + } else if (newSpot->wavMethod == "D6") { + r->wavMethod = 2; + } else if (newSpot->wavMethod == "D10") { + r->wavMethod = 3; + } else if (newSpot->wavMethod == "D14") { + r->wavMethod = 4; + } + expsettings->addControlSpot(r); // ProcParams update @@ -568,6 +650,20 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited } } + // Update Locallab Retinex tool min/max + if (pp->locallab.selspot < (int)retiMinMax.size()) { + const double cdma = retiMinMax.at(pp->locallab.selspot).cdma; + const double cdmin = retiMinMax.at(pp->locallab.selspot).cdmin; + const double mini = retiMinMax.at(pp->locallab.selspot).mini; + const double maxi = retiMinMax.at(pp->locallab.selspot).maxi; + const double Tmean = retiMinMax.at(pp->locallab.selspot).Tmean; + const double Tsigma = retiMinMax.at(pp->locallab.selspot).Tsigma; + const double Tmin = retiMinMax.at(pp->locallab.selspot).Tmin; + const double Tmax = retiMinMax.at(pp->locallab.selspot).Tmax; + + expreti->updateMinMax(cdma, cdmin, mini, maxi, Tmean, Tsigma, Tmin, Tmax); + } + // Update default values according to selected spot setDefaults(pp, pedited); @@ -612,7 +708,6 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited r->sensiexclu = newSpot->sensiexclu; r->structexclu = newSpot->structexclu; - r->struc = newSpot->struc; if (newSpot->shapeMethod == "IND") { r->shapeMethod = 0; @@ -658,12 +753,44 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited } r->transit = newSpot->transit; + r->transitweak = newSpot->transitweak; + r->transitgrad = newSpot->transitgrad; + r->feather = newSpot->feather; + r->struc = newSpot->struc; r->thresh = newSpot->thresh; r->iter = newSpot->iter; r->balan = newSpot->balan; - r->transitweak = newSpot->transitweak; - r->transitgrad = newSpot->transitgrad; + r->balanh = newSpot->balanh; + r->colorde = newSpot->colorde; r->avoid = newSpot->avoid; + r->recurs = newSpot->recurs; + r->laplac = newSpot->laplac; + r->deltae = newSpot->deltae; + r->scopemask = newSpot->scopemask; + r->shortc = newSpot->shortc; + r->lumask = newSpot->lumask; + r->savrest = newSpot->savrest; + + if (newSpot->complexMethod == "sim") { + r->complexMethod = 0; + } else if (newSpot->complexMethod == "mod") { + r->complexMethod = 1; + } else if (newSpot->complexMethod == "all") { + r->complexMethod = 2; + } + + if (newSpot->wavMethod == "D2") { + r->wavMethod = 0; + } else if (newSpot->wavMethod == "D4") { + r->wavMethod = 1; + } else if (newSpot->wavMethod == "D6") { + r->wavMethod = 2; + } else if (newSpot->wavMethod == "D10") { + r->wavMethod = 3; + } else if (newSpot->wavMethod == "D14") { + r->wavMethod = 4; + } + expsettings->addControlSpot(r); // ProcParams update @@ -741,7 +868,6 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited pp->locallab.spots.at(pp->locallab.selspot).sensiexclu = r->sensiexclu; pp->locallab.spots.at(pp->locallab.selspot).structexclu = r->structexclu; - pp->locallab.spots.at(pp->locallab.selspot).struc = r->struc; if (r->shapeMethod == 0) { pp->locallab.spots.at(pp->locallab.selspot).shapeMethod = "IND"; @@ -768,12 +894,43 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited } pp->locallab.spots.at(pp->locallab.selspot).transit = r->transit; + pp->locallab.spots.at(pp->locallab.selspot).transitweak = r->transitweak; + pp->locallab.spots.at(pp->locallab.selspot).transitgrad = r->transitgrad; + pp->locallab.spots.at(pp->locallab.selspot).feather = r->feather; + pp->locallab.spots.at(pp->locallab.selspot).struc = r->struc; pp->locallab.spots.at(pp->locallab.selspot).thresh = r->thresh; pp->locallab.spots.at(pp->locallab.selspot).iter = r->iter; pp->locallab.spots.at(pp->locallab.selspot).balan = r->balan; - pp->locallab.spots.at(pp->locallab.selspot).transitweak = r->transitweak; - pp->locallab.spots.at(pp->locallab.selspot).transitgrad = r->transitgrad; + pp->locallab.spots.at(pp->locallab.selspot).balanh = r->balanh; + pp->locallab.spots.at(pp->locallab.selspot).colorde = r->colorde; pp->locallab.spots.at(pp->locallab.selspot).avoid = r->avoid; + pp->locallab.spots.at(pp->locallab.selspot).recurs = r->recurs; + pp->locallab.spots.at(pp->locallab.selspot).laplac = r->laplac; + pp->locallab.spots.at(pp->locallab.selspot).deltae = r->deltae; + pp->locallab.spots.at(pp->locallab.selspot).scopemask = r->scopemask; + pp->locallab.spots.at(pp->locallab.selspot).shortc = r->shortc; + pp->locallab.spots.at(pp->locallab.selspot).lumask = r->lumask; + pp->locallab.spots.at(pp->locallab.selspot).savrest = r->savrest; + + if (r->complexMethod == 0) { + pp->locallab.spots.at(pp->locallab.selspot).complexMethod = "sim"; + } else if (r->complexMethod == 1) { + pp->locallab.spots.at(pp->locallab.selspot).complexMethod = "mod"; + } else if (r->complexMethod == 2) { + pp->locallab.spots.at(pp->locallab.selspot).complexMethod = "all"; + } + + if (r->wavMethod == 0) { + pp->locallab.spots.at(pp->locallab.selspot).wavMethod = "D2"; + } else if (r->wavMethod == 1) { + pp->locallab.spots.at(pp->locallab.selspot).wavMethod = "D4"; + } else if (r->wavMethod == 2) { + pp->locallab.spots.at(pp->locallab.selspot).wavMethod = "D6"; + } else if (r->wavMethod == 3) { + pp->locallab.spots.at(pp->locallab.selspot).wavMethod = "D10"; + } else if (r->wavMethod == 4) { + pp->locallab.spots.at(pp->locallab.selspot).wavMethod = "D14"; + } } for (auto tool : locallabTools) { @@ -820,6 +977,32 @@ void Locallab::setListener(ToolPanelListener* tpl) } } +void Locallab::minmaxChanged(const std::vector &minmax, int selspot) +{ + // Saving transmitted min/max data + retiMinMax = minmax; + + // Update Locallab Retinex tool min/max + if (selspot < (int)retiMinMax.size()) { + const double cdma = retiMinMax.at(selspot).cdma; + const double cdmin = retiMinMax.at(selspot).cdmin; + const double mini = retiMinMax.at(selspot).mini; + const double maxi = retiMinMax.at(selspot).maxi; + const double Tmean = retiMinMax.at(selspot).Tmean; + const double Tsigma = retiMinMax.at(selspot).Tsigma; + const double Tmin = retiMinMax.at(selspot).Tmin; + const double Tmax = retiMinMax.at(selspot).Tmax; + + expreti->updateMinMax(cdma, cdmin, mini, maxi, Tmean, Tsigma, Tmin, Tmax); + } +} + +void Locallab::logencodChanged(const float blackev, const float whiteev, const float sourceg, const float targetg) +{ + // Update Locallab Log Encoding accordingly + explog->updateAutocompute(blackev, whiteev, sourceg, targetg); +} + void Locallab::refChanged(const std::vector &ref, int selspot) { // Saving transmitted mask background data @@ -851,18 +1034,28 @@ void Locallab::resetMaskVisibility() Locallab::llMaskVisibility Locallab::getMaskVisibility() const { // Get mask preview from Locallab tools - int colorMask, expMask, SHMask, softMask, tmMask, retiMask, cbMask; + int colorMask, colorMaskinv, expMask, expMaskinv, shMask, shMaskinv, vibMask, softMask, blMask, tmMask, retiMask, sharMask, lcMask, cbMask; for (auto tool : locallabTools) { - tool->getMaskView(colorMask, expMask, SHMask, softMask, tmMask, retiMask, cbMask); + tool->getMaskView(colorMask, colorMaskinv, expMask, expMaskinv, shMask, shMaskinv, vibMask, softMask, blMask, tmMask, retiMask, sharMask, lcMask, cbMask); } // Indicate to spot control panel if one mask preview is active - const bool isMaskActive = (colorMask == 0) || (expMask == 0) || (SHMask == 0) || - (softMask == 0) || (tmMask == 0) || (retiMask == 0) || (cbMask == 0); + const bool isMaskActive = (colorMask == 0) || (colorMaskinv == 0) || (expMask == 0) || (expMaskinv == 0) || + (shMask == 0) || (shMaskinv == 0) || (vibMask == 0) || (softMask == 0) || + (blMask == 0) || (tmMask == 0) || (retiMask == 0) || (sharMask == 0) || + (lcMask == 0) || (cbMask == 0); expsettings->setMaskPrevActive(isMaskActive); - return {colorMask, expMask, SHMask, softMask, tmMask, retiMask, cbMask}; + return {colorMask, colorMaskinv, expMask, expMaskinv, shMask, shMaskinv, vibMask, softMask, blMask, tmMask, retiMask, sharMask, lcMask, cbMask}; +} + +void Locallab::resetshowPressed() +{ + // Raise event to reset mask + if (listener) { + listener->panelChanged(Evlocallabshowreset, ""); + } } void Locallab::setEditProvider(EditDataProvider * provider) diff --git a/rtgui/locallab.h b/rtgui/locallab.h index a23d9b3a9..51cde7671 100644 --- a/rtgui/locallab.h +++ b/rtgui/locallab.h @@ -22,6 +22,8 @@ #ifndef _LOCALLAB_H_ #define _LOCALLAB_H_ +#pragma once + #include "controlspotpanel.h" #include "locallabtools.h" @@ -112,12 +114,19 @@ private: LocallabContrast* const expcontrast; LocallabCBDL* const expcbdl; LocallabDenoise* const expdenoi; + LocallabLog* const explog; std::vector locallabTools; + // Locallab tools mask background management data + std::vector retiMinMax; + // Locallab tools mask background management data std::vector maskBackRef; + // Other widgets + Gtk::Button* const resetshowButton; + public: Locallab(); @@ -127,23 +136,39 @@ public: void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); void setListener(ToolPanelListener* tpl); + // Locallab Retinex tool min/man management function + void minmaxChanged(const std::vector &minmax, int selspot); + + // Locallab Log Encoding autocompute function + void logencodChanged(const float blackev, const float whiteev, const float sourceg, const float targetg); + // Locallab tools mask background management function void refChanged(const std::vector &ref, int selspot); // Mask visibility management functions struct llMaskVisibility { int colorMask; + int colorMaskinv; int expMask; + int expMaskinv; int SHMask; - int cbMask; - int retiMask; + int SHMaskinv; + int vibMask; int softMask; + int blMask; int tmMask; + int retiMask; + int sharMask; + int lcMask; + int cbMask; }; void resetMaskVisibility(); llMaskVisibility getMaskVisibility() const; + // Other widgets event functions + void resetshowPressed(); + // EditProvider management function void setEditProvider(EditDataProvider* provider); void subscribe(); diff --git a/rtgui/locallabtools.cc b/rtgui/locallabtools.cc index ff0719ddb..2247a601c 100644 --- a/rtgui/locallabtools.cc +++ b/rtgui/locallabtools.cc @@ -23,18 +23,103 @@ #include "options.h" #include "../rtengine/procparams.h" #include "locallab.h" +#include "thresholdadjuster.h" +#include "rtimage.h" +#include "../rtengine/color.h" + +#define MINRAD 1.5 +#define MAXRAD 10000 +#define CENTERRAD 100 using namespace rtengine; using namespace procparams; extern Options options; +static double blurSlider2radius(double sval) +{ + // Slider range: 0 - 1000 + double radius; + + if (sval <= 100) { + // Linear below center-temp + radius = MINRAD + (sval / 100.0) * (CENTERRAD - MINRAD); + } else { + const double slope = (double)(CENTERRAD - MINRAD) / (MAXRAD - CENTERRAD); + double x = (sval - 100) / 100; // x range: 0 - 1 + double y = x * slope + (1.0 - slope) * pow(x, 4.0); + radius = CENTERRAD + y * (MAXRAD - CENTERRAD); + } + + if (radius < MINRAD) { + radius = MINRAD; + } + + if (radius > MAXRAD) { + radius = MAXRAD; + } + + return radius; +} + +static double blurRadius2Slider(double radius) +{ + double sval; + + if (radius <= CENTERRAD) { + sval = ((radius - MINRAD) / (CENTERRAD - MINRAD)) * 100.0; + } else { + const double slope = (double)(CENTERRAD - MINRAD) / (MAXRAD - CENTERRAD); + const double y = (radius - CENTERRAD) / (MAXRAD - CENTERRAD); + double x = pow(y, 0.25); // Rough guess of x, will be a little lower + double k = 0.1; + bool add = true; + + // The y=f(x) function is a mess to invert, therefore we have this trial-refinement loop instead. + // From tests, worst case is about 20 iterations, i.e. no problem + for (;;) { + double y1 = x * slope + (1.0 - slope) * pow(x, 4.0); + + if (100. * fabs(y1 - y) < 0.1) { + break; + } + + if (y1 < y) { + if (!add) { + k /= 2; + } + + x += k; + add = true; + } else { + if (add) { + k /= 2; + } + + x -= k; + add = false; + } + } + + sval = 100.0 + x * 100.0; + } + + if (sval < 0.) { + sval = 0.; + } + + if (sval > 10000.) { + sval = 10000.; + } + + return sval; +} + /* ==== LocallabTool ==== */ -LocallabTool::LocallabTool(Gtk::Box* content, Glib::ustring toolName, Glib::ustring UILabel, bool need11, maskType usemask): +LocallabTool::LocallabTool(Gtk::Box* content, Glib::ustring toolName, Glib::ustring UILabel, bool need11): ToolPanel(toolName, need11), // LocallabTool parameters - useMask(usemask), isLocActivated(false), locToolListener(nullptr) { @@ -73,117 +158,12 @@ LocallabTool::LocallabTool(Gtk::Box* content, Glib::ustring toolName, Glib::ustr // Create panel for specific widget tools totalBox->pack_start(*content, Gtk::PACK_SHRINK, 0); - - // Create mask panel - if (useMask) { - maskExp = Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOW"))); - setExpandAlignProperties(maskExp, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - - showMaskMethod = Gtk::manage(new MyComboBoxText()); - showMaskMethod->append(M("TP_LOCALLAB_SHOWMNONE")); - showMaskMethod->append(M("TP_LOCALLAB_SHOWMODIF")); - showMaskMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); - showMaskMethod->append(M("TP_LOCALLAB_SHOWMASK")); - showMaskMethod->append(M("TP_LOCALLAB_SHOWSTRUC")); - showMaskMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); - showMaskMethod->set_active(0); - - if (showtooltip) { - showMaskMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); - } - - showMaskMethodConn = showMaskMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabTool::showMaskMethodChanged)); - - enaMask = Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK"))); - enaMaskConn = enaMask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabTool::enaMaskChanged)); - - if (useMask == MaskWithTrMap) { - enaMaskTrMap = Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_TM_MASK"))); - enaMaskTrMapConn = enaMaskTrMap->signal_toggled().connect(sigc::mem_fun(*this, &LocallabTool::enaMaskTrMapChanged)); - } - - maskCurveEditorG = new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK")); - maskCurveEditorG->setCurveListener(this); - - CCMaskShape = static_cast(maskCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false)); - CCMaskShape->setIdentityValue(0.); - CCMaskShape->setResetCurve(FlatCurveType(LocallabParams::DEF_MASK_CURVE.at(0)), LocallabParams::DEF_MASK_CURVE); - - if (showtooltip) { - CCMaskShape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); - } - - CCMaskShape->setBottomBarColorProvider(this, 1); - - std::vector bgGradient; - bgGradient.push_back(GradientMilestone(0., 0., 0., 0.)); - bgGradient.push_back(GradientMilestone(1., 1., 1., 1.)); - LLMaskShape = static_cast(maskCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false)); - LLMaskShape->setIdentityValue(0.); - LLMaskShape->setResetCurve(FlatCurveType(LocallabParams::DEF_MASK_CURVE.at(0)), LocallabParams::DEF_MASK_CURVE); - - if (showtooltip) { - LLMaskShape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); - } - - LLMaskShape->setBottomBarBgGradient(bgGradient); - - HHMaskShape = static_cast(maskCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true)); - HHMaskShape->setIdentityValue(0.); - HHMaskShape->setResetCurve(FlatCurveType(LocallabParams::DEF_MASK_CURVE.at(0)), LocallabParams::DEF_MASK_CURVE); - - if (showtooltip) { - HHMaskShape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); - } - - HHMaskShape->setCurveColorProvider(this, 2); - HHMaskShape->setBottomBarColorProvider(this, 2); - - maskCurveEditorG->curveListComplete(); - - blendMask = Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0)); - blendMask->setAdjusterListener(this); - - radMask = Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), 0.0, 100.0, 0.1, 10.)); - radMask->setAdjusterListener(this); - - chroMask = Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.)); - chroMask->setAdjusterListener(this); - - gamMask = Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.25, 4.0, 0.01, 1.)); - gamMask->setAdjusterListener(this); - - sloMask = Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.)); - sloMask->setAdjusterListener(this); - - ToolParamBlock* const maskBox = Gtk::manage(new ToolParamBlock()); - maskBox->pack_start(*showMaskMethod, Gtk::PACK_SHRINK, 4); - maskBox->pack_start(*enaMask, Gtk::PACK_SHRINK, 0); - - if (useMask == MaskWithTrMap) { - maskBox->pack_start(*enaMaskTrMap, Gtk::PACK_SHRINK, 0); - } - - maskBox->pack_start(*maskCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor - maskBox->pack_start(*blendMask, Gtk::PACK_SHRINK, 0); - maskBox->pack_start(*radMask, Gtk::PACK_SHRINK, 0); - maskBox->pack_start(*chroMask, Gtk::PACK_SHRINK, 0); - maskBox->pack_start(*gamMask, Gtk::PACK_SHRINK, 0); - maskBox->pack_start(*sloMask, Gtk::PACK_SHRINK, 0); - maskExp->add(*maskBox, false); - totalBox->pack_start(*maskExp, Gtk::PACK_SHRINK, 0); - } - exp->add(*totalBox, false); } LocallabTool::~LocallabTool() { idle_register.destroy(); - - if (useMask) { - delete maskCurveEditorG; - } } void LocallabTool::addLocallabTool(bool raiseEvent) @@ -233,84 +213,73 @@ bool LocallabTool::isLocallabToolAdded() return exp->get_visible(); } -void LocallabTool::resetMaskView() -{ - if (useMask) { - showMaskMethodConn.block(true); - showMaskMethod->set_active(0); - showMaskMethodConn.block(false); - } -} - void LocallabTool::refChanged(const double huer, const double lumar, const double chromar) { - if (useMask) { - // Hue reference normalization (between 0 and 1) - double normHuer = huer; - float h = Color::huelab_to_huehsv2(normHuer); - h += 1.f / 6.f; + // Hue reference normalization (between 0 and 1) + double normHuer = huer; + float h = Color::huelab_to_huehsv2(normHuer); + h += 1.f / 6.f; - if (h > 1.f) { - h -= 1.f; - } - - normHuer = h; - - // Luma reference normalization (between 0 and 1) - const double normLumar = lumar / 100.f; - - // Chroma reference normalization (between 0 and 1) - const double normChromar = chromar / 137.4f; - - // printf("nh=%f nl=%f nc=%f\n", normHuer, normLumar, normChromar); - - idle_register.add( - [this, normHuer, normLumar, normChromar]() -> bool { - GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected - - // Update mask background - CCMaskShape->updateLocallabBackground(normChromar); - LLMaskShape->updateLocallabBackground(normLumar); - HHMaskShape->updateLocallabBackground(normHuer); - - return false; - } - ); + if (h > 1.f) { + h -= 1.f; } + + normHuer = h; + + // Luma reference normalization (between 0 and 1) + const double normLumar = lumar / 100.f; + + // Chroma reference normalization (between 0 and 1) + const double normChromar = chromar / 137.4f; + + // Update mask curve backgrounds + updateMaskBackground(normChromar, normLumar, normHuer); } void LocallabTool::colorForValue(double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) { - if (useMask) { - float R = 0.f; - float G = 0.f; - float B = 0.f; + float R = 0.f; + float G = 0.f; + float B = 0.f; + float x; - if (elemType == ColorCaller::CCET_VERTICAL_BAR) { - valY = 0.5; - } - - switch (callerId) { - case 1: // CCmaskshape - Color::hsv2rgb01(float(valY), float(valX), 0.5f, R, G, B); - - break; - - case 2: // HHmaskshape - float x = valX - 1.f / 6.f; - - if (x < 0.f) { - x += 1.f; - } - - x = log2lin(x, 3.f); - Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); - } - - caller->ccRed = double (R); - caller->ccGreen = double (G); - caller->ccBlue = double (B); + if (elemType == ColorCaller::CCET_VERTICAL_BAR) { + valY = 0.5; } + + switch (callerId) { + case 1: // Mask CC shape (bottom bar) + Color CC/LC shape (left bar) + Color::hsv2rgb01(float(valY), float(valX), 0.5f, R, G, B); + + break; + + case 2: // Mask HH shape (main curve and bottom bar) + x = valX - 1.f / 6.f; + + if (x < 0.f) { + x += 1.f; + } + + x = log2lin(x, 3.f); + Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); + + break; + + case 3: // Color LH/HH shape (main curve) + Color::hsv2rgb01(float (valX), float (valY), 0.5f, R, G, B); + + break; + + case 4: // Color CC/LC shape (bottom bar) + const float value = (1.f - 0.7f) * float (valX) + 0.7f; + // Whole hue range + // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) + Color::hsv2rgb01(float (valY), float (valX), value, R, G, B); + } + + caller->ccRed = double (R); + caller->ccGreen = double (G); + caller->ccBlue = double (B); } void LocallabTool::disableListener() @@ -318,32 +287,12 @@ void LocallabTool::disableListener() ToolPanel::disableListener(); enaExpConn.block(true); - - if (useMask) { - enaMaskConn.block(true); - - if (useMask == MaskWithTrMap) { - enaMaskTrMapConn.block(true); - } - - showMaskMethodConn.block(true); - } } void LocallabTool::enableListener() { ToolPanel::enableListener(); enaExpConn.block(false); - - if (useMask) { - enaMaskConn.block(false); - - if (useMask == MaskWithTrMap) { - enaMaskTrMapConn.block(false); - } - - showMaskMethodConn.block(false); - } } bool LocallabTool::on_remove_change(GdkEventButton* event) @@ -367,11 +316,11 @@ void LocallabTool::foldThemAll(GdkEventButton* event) /* ==== LocallabColor ==== */ LocallabColor::LocallabColor(): - LocallabTool(this, M("TP_LOCALLAB_COLOR_TOOLNAME"), M("TP_LOCALLAB_COFR"), false, MaskNormal), + LocallabTool(this, M("TP_LOCALLAB_COLOR_TOOLNAME"), M("TP_LOCALLAB_COFR"), false), // Color & Light specific widgets curvactiv(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_CURV")))), - lightness(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LIGHTNESS"), -100, 100, 1, 0))), + lightness(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LIGHTNESS"), -100, 500, 1, 0))), contrast(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CONTRAST"), -100, 100, 1, 0))), chroma(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMA"), -100, 150, 1, 0))), gridFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LABGRID")))), @@ -379,19 +328,84 @@ LocallabColor::LocallabColor(): gridMethod(Gtk::manage(new MyComboBoxText())), strengthgrid(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRGRID"), 0, 100, 1, 30))), sensi(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))), - structcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRUCCOL"), 0, 100, 1, 0))), + structcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRUCCOL1"), 0, 100, 1, 0))), blurcolde(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURDE"), 2, 100, 1, 5))), - softradiuscol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.1, 0.))), + softradiuscol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), -10.0, 1000.0, 0.5, 0.))), + invers(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))), + expgradcol(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_EXPGRAD")))), + strcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTRLUM"), -4., 4., 0.05, 0.))), + strcolab(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTRCHRO"), -6., 6., 0.05, 0.))), + strcolh(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTRHUE"), -6., 6., 0.05, 0.))), + angcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))), labqualcurv(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_QUALCURV_METHOD") + ":"))), qualitycurveMethod(Gtk::manage(new MyComboBoxText())), llCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_LUM"))), + llshape(static_cast(llCurveEditorG->addCurve(CT_Diagonal, "L(L)"))), + ccshape(static_cast(llCurveEditorG->addCurve(CT_Diagonal, "C(C)"))), + clCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_CH"))), + clshape(static_cast(clCurveEditorG->addCurve(CT_Diagonal, "C(L)"))), + lcshape(static_cast(clCurveEditorG->addCurve(CT_Diagonal, "L(C)"))), HCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_HLH"))), - invers(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))) + LHshape(static_cast(HCurveEditorG->addCurve(CT_Flat, "L(H)", nullptr, false, true))), + H2CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_HLH"))), + HHshape(static_cast(H2CurveEditorG->addCurve(CT_Flat, "H(H)", nullptr, false, true))), + rgbCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_RGB"))), + toneMethod(Gtk::manage(new MyComboBoxText())), + rgbshape(static_cast(rgbCurveEditorG->addCurve(CT_Diagonal, "", toneMethod))), + special(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_SPECIAL")))), + expmaskcol1(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWC1")))), + merMethod(Gtk::manage(new MyComboBoxText())), + mask7(Gtk::manage(new ToolParamBlock())), + mergecolMethod(Gtk::manage(new MyComboBoxText())), + mercol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_MERDCOL"), 0.0, 100.0, 0.5, 18.))), + opacol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_OPACOL"), 0.0, 100.0, 0.5, 60.))), + conthrcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CONTTHR"), 0.0, 100.0, 0.5, 0.))), + gridmerFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LABGRIDMERG")))), + labgridmerg(Gtk::manage(new LabGrid(EvLocallabLabGridmergValue, M("TP_LOCALLAB_LABGRID_VALUES"), false))), + merlucol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_MERLUCOL"), 0.0, 100.0, 0.5, 32., Gtk::manage(new RTImage("circle-black-small.png")), Gtk::manage(new RTImage("circle-white-small.png"))))), + showmaskcolMethod(Gtk::manage(new MyComboBoxText())), + showmaskcolMethodinv(Gtk::manage(new MyComboBoxText())), + enaColorMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), + maskCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASKCOL"))), + CCmaskshape(static_cast(maskCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false))), + LLmaskshape(static_cast(maskCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false))), + HHmaskshape(static_cast(maskCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true))), + strumaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRUMASKCOL"), 0., 200., 0.1, 0.))), + toolcol(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_TOOLCOL")))), + fftColorMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_FFTCOL_MASK")))), + contcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CONTCOL"), 0., 200., 0.5, 0.))), + blurcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURCOL"), 0.2, 100., 0.5, 0.2))), + blendmaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), + radmaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), -10.0, 1000.0, 0.1, 0.))), + lapmaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPMASKCOL"), 0.0, 100.0, 0.1, 0.))), + chromaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), + gammaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.25, 4.0, 0.01, 1.))), + slomaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), + shadmaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHAMASKCOL"), 0, 100, 1, 0))), + maskHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASKH"))), + HHhmaskshape(static_cast(maskHCurveEditorG->addCurve(CT_Flat, "H(H)", nullptr, false, true))), + mask2CurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), + Lmaskshape(static_cast(mask2CurveEditorG->addCurve(CT_Diagonal, "L(L)"))), + mask2CurveEditorGwav(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVMASK"))), + LLmaskcolshapewav(static_cast(mask2CurveEditorGwav->addCurve(CT_Flat, "L(L)", nullptr, false, false))), + csThresholdcol(Gtk::manage(new ThresholdAdjuster(M("TP_LOCALLAB_CSTHRESHOLDBLUR"), 0, 9, 0, 0, 6, 5, 0, false))) { float R, G, B; - const bool showtooltip = options.showtooltip; + std::vector six_shape; + for (int i = 0; i < 6; i++) { + const float x = static_cast(i) * (1.f / 6.f); + Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); + six_shape.emplace_back(x, R, G, B); + } + + const LocallabParams::LocallabSpot defSpot; + + const bool showtooltip = options.showtooltip; + const int complexsoft = options.complexity; + + // Parameter Color & Light specific widgets curvactivConn = curvactiv->signal_toggled().connect(sigc::mem_fun(*this, &LocallabColor::curvactivChanged)); lightness->setAdjusterListener(this); @@ -404,6 +418,8 @@ LocallabColor::LocallabColor(): chroma->setAdjusterListener(this); + gridFrame->set_label_align(0.025, 0.5); + gridMethod->append(M("TP_LOCALLAB_GRIDONE")); gridMethod->append(M("TP_LOCALLAB_GRIDTWO")); gridMethod->set_active(0); @@ -421,8 +437,37 @@ LocallabColor::LocallabColor(): blurcolde->setAdjusterListener(this); + softradiuscol->setLogScale(10, -10); softradiuscol->setAdjusterListener(this); + inversConn = invers->signal_toggled().connect(sigc::mem_fun(*this, &LocallabColor::inversChanged)); + + setExpandAlignProperties(expgradcol, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + strcol->setAdjusterListener(this); + + if (showtooltip) { + strcol->set_tooltip_text(M("TP_LOCALLAB_GRADGEN_TOOLTIP")); + } + + strcolab->setAdjusterListener(this); + + if (showtooltip) { + strcolab->set_tooltip_text(M("TP_LOCALLAB_GRADSTRAB_TOOLTIP")); + } + + strcolh->setAdjusterListener(this); + + if (showtooltip) { + strcolh->set_tooltip_text(M("TP_LOCALLAB_GRADSTRHUE_TOOLTIP")); + } + + angcol->setAdjusterListener(this); + + if (showtooltip) { + angcol->set_tooltip_text(M("TP_LOCALLAB_GRADANG_TOOLTIP")); + } + qualitycurveMethod->append(M("TP_LOCALLAB_CURVNONE")); qualitycurveMethod->append(M("TP_LOCALLAB_CURVCURR")); qualitycurveMethod->set_active(0); @@ -434,87 +479,298 @@ LocallabColor::LocallabColor(): qualitycurveMethodConn = qualitycurveMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabColor::qualitycurveMethodChanged)); llCurveEditorG->setCurveListener(this); - llshape = static_cast(llCurveEditorG->addCurve(CT_Diagonal, "L(L)")); - llshape->setResetCurve(DiagonalCurveType(LocallabParams::DEF_COLOR_LCURVE.at(0)), LocallabParams::DEF_COLOR_LCURVE); + + llshape->setResetCurve(DiagonalCurveType(defSpot.llcurve.at(0)), defSpot.llcurve); if (showtooltip) { llshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP")); } - std::vector mllshape; - mllshape.push_back(GradientMilestone(0., 0., 0., 0.)); - mllshape.push_back(GradientMilestone(1., 1., 1., 1.)); - llshape->setBottomBarBgGradient(mllshape); - llshape->setLeftBarBgGradient(mllshape); + llshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + llshape->setLeftBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); - ccshape = static_cast(llCurveEditorG->addCurve(CT_Diagonal, "C(C)")); - ccshape->setResetCurve(DiagonalCurveType(LocallabParams::DEF_COLOR_LCURVE.at(0)), LocallabParams::DEF_COLOR_LCURVE); + ccshape->setResetCurve(DiagonalCurveType(defSpot.cccurve.at(0)), defSpot.cccurve); if (showtooltip) { ccshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP")); } - std::vector mccshape; - mccshape.push_back(GradientMilestone(0., 0., 0., 0.)); - mccshape.push_back(GradientMilestone(1., 1., 1., 1.)); - ccshape->setBottomBarBgGradient(mccshape); - ccshape->setLeftBarBgGradient(mccshape); + ccshape->setBottomBarColorProvider(this, 4); + ccshape->setLeftBarColorProvider(this, 1); - // llCurveEditorG->newLine(); llCurveEditorG->curveListComplete(); + + clCurveEditorG->setCurveListener(this); + + clshape->setResetCurve(DiagonalCurveType(defSpot.clcurve.at(0)), defSpot.clcurve); + + if (showtooltip) { + clshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP")); + } + + clshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + clshape->setLeftBarColorProvider(this, 1); + + lcshape->setResetCurve(DiagonalCurveType(defSpot.lccurve.at(0)), defSpot.lccurve); + + if (showtooltip) { + lcshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP")); + } + + lcshape->setBottomBarColorProvider(this, 4); + lcshape->setLeftBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + clCurveEditorG->curveListComplete(); + HCurveEditorG->setCurveListener(this); - LHshape = static_cast(HCurveEditorG->addCurve(CT_Flat, "L(H)", nullptr, false, true)); LHshape->setIdentityValue(0.); - LHshape->setResetCurve(FlatCurveType(LocallabParams::DEF_COLOR_HCURVE.at(0)), LocallabParams::DEF_COLOR_HCURVE); + LHshape->setResetCurve(FlatCurveType(defSpot.LHcurve.at(0)), defSpot.LHcurve); if (showtooltip) { LHshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP")); } LHshape->setCurveColorProvider(this, 3); - std::vector mLHshape; + LHshape->setBottomBarBgGradient(six_shape); - for (int i = 0; i < 7; i++) { - float x = float (i) * (1.0f / 6.0); - Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); - mLHshape.push_back(GradientMilestone(double (x), double (R), double (G), double (B))); - } + HCurveEditorG->curveListComplete(); - LHshape->setBottomBarBgGradient(mLHshape); + H2CurveEditorG->setCurveListener(this); - HHshape = static_cast(HCurveEditorG->addCurve(CT_Flat, "H(H)", nullptr, false, true)); HHshape->setIdentityValue(0.); - HHshape->setResetCurve(FlatCurveType(LocallabParams::DEF_COLOR_HCURVE.at(0)), LocallabParams::DEF_COLOR_HCURVE); + HHshape->setResetCurve(FlatCurveType(defSpot.HHcurve.at(0)), defSpot.HHcurve); if (showtooltip) { HHshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP")); } HHshape->setCurveColorProvider(this, 3); - std::vector mHHshape; + HHshape->setBottomBarBgGradient(six_shape); - for (int i = 0; i < 7; i++) { - float x = float (i) * (1.0f / 6.0); + H2CurveEditorG->curveListComplete(); - Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); - mHHshape.push_back(GradientMilestone(double (x), double (R), double (G), double (B))); + rgbCurveEditorG->setCurveListener(this); + + toneMethod->append(M("TP_EXPOSURE_TCMODE_STANDARD")); + toneMethod->append(M("TP_EXPOSURE_TCMODE_WEIGHTEDSTD")); + toneMethod->append(M("TP_EXPOSURE_TCMODE_LUMINANCE")); + toneMethod->append(M("TP_EXPOSURE_TCMODE_FILMLIKE")); + toneMethod->set_active(0); + toneMethodConn = toneMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabColor::toneMethodChanged)); + + rgbshape->setResetCurve(DiagonalCurveType(defSpot.rgbcurve.at(0)), defSpot.rgbcurve); + + if (showtooltip) { + rgbshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP")); } - HHshape->setBottomBarBgGradient(mHHshape); + rgbshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + rgbshape->setLeftBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); - HCurveEditorG->curveListComplete(); + rgbCurveEditorG->curveListComplete(); - inversConn = invers->signal_toggled().connect(sigc::mem_fun(*this, &LocallabColor::inversChanged)); + specialConn = special->signal_toggled().connect(sigc::mem_fun(*this, &LocallabColor::specialChanged)); + setExpandAlignProperties(expmaskcol1, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + merMethod->append(M("TP_LOCALLAB_MRONE")); + merMethod->append(M("TP_LOCALLAB_MRTWO")); + merMethod->append(M("TP_LOCALLAB_MRTHR")); + merMethod->append(M("TP_LOCALLAB_MRFOU")); + merMethod->append(M("TP_LOCALLAB_MRFIV")); + merMethod->set_active(0); + merMethodConn = merMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabColor::merMethodChanged)); + + mergecolMethod->append(M("TP_LOCALLAB_MERONE")); + mergecolMethod->append(M("TP_LOCALLAB_MERTWO")); + mergecolMethod->append(M("TP_LOCALLAB_MERTHR")); + mergecolMethod->append(M("TP_LOCALLAB_MERFOU")); + mergecolMethod->append(M("TP_LOCALLAB_MERFIV")); + mergecolMethod->append(M("TP_LOCALLAB_MERSIX")); + mergecolMethod->append(M("TP_LOCALLAB_MERSEV")); + mergecolMethod->append(M("TP_LOCALLAB_MERSEV0")); + mergecolMethod->append(M("TP_LOCALLAB_MERSEV1")); + mergecolMethod->append(M("TP_LOCALLAB_MERSEV2")); + mergecolMethod->append(M("TP_LOCALLAB_MERHEI")); + mergecolMethod->append(M("TP_LOCALLAB_MERNIN")); + mergecolMethod->append(M("TP_LOCALLAB_MERTEN")); + mergecolMethod->append(M("TP_LOCALLAB_MERELE")); + mergecolMethod->append(M("TP_LOCALLAB_MERTWE")); + mergecolMethod->append(M("TP_LOCALLAB_MERTHI")); + mergecolMethod->append(M("TP_LOCALLAB_MERFOR")); + mergecolMethod->append(M("TP_LOCALLAB_MERHUE")); + mergecolMethod->append(M("TP_LOCALLAB_MERSAT")); + mergecolMethod->append(M("TP_LOCALLAB_MERCOL")); + mergecolMethod->append(M("TP_LOCALLAB_MERLUM")); + mergecolMethod->set_active(0); + mergecolMethodConn = mergecolMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabColor::mergecolMethodChanged)); + + mercol->setAdjusterListener(this); + + opacol->setAdjusterListener(this); + + if (showtooltip) { + opacol->set_tooltip_text(M("TP_LOCALLAB_MERGEOPA_TOOLTIP")); + } + + conthrcol->setAdjusterListener(this); + + if (showtooltip) { + conthrcol->set_tooltip_text(M("TP_LOCALLAB_MERGEOPA_TOOLTIP")); + } + + if (showtooltip) { + gridmerFrame->set_tooltip_text(M("TP_LOCALLAB_GRIDFRAME_TOOLTIP")); + } + + merlucol->setAdjusterListener(this); + + showmaskcolMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskcolMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showmaskcolMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); + showmaskcolMethod->append(M("TP_LOCALLAB_SHOWMASK")); + showmaskcolMethod->append(M("TP_LOCALLAB_SHOWSTRUC")); + showmaskcolMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); + showmaskcolMethod->set_active(0); + + if (showtooltip) { + showmaskcolMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmaskcolMethodConn = showmaskcolMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabColor::showmaskcolMethodChanged)); + + showmaskcolMethodinv->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskcolMethodinv->append(M("TP_LOCALLAB_SHOWMASK")); + showmaskcolMethodinv->set_active(0); + + if (showtooltip) { + showmaskcolMethodinv->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmaskcolMethodConninv = showmaskcolMethodinv->signal_changed().connect(sigc::mem_fun(*this, &LocallabColor::showmaskcolMethodChangedinv)); + + enaColorMaskConn = enaColorMask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabColor::enaColorMaskChanged)); + + maskCurveEditorG->setCurveListener(this); + + CCmaskshape->setIdentityValue(0.); + CCmaskshape->setResetCurve(FlatCurveType(defSpot.CCmaskcurve.at(0)), defSpot.CCmaskcurve); + + if (showtooltip) { + CCmaskshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + CCmaskshape->setBottomBarColorProvider(this, 1); + + LLmaskshape->setIdentityValue(0.); + LLmaskshape->setResetCurve(FlatCurveType(defSpot.LLmaskcurve.at(0)), defSpot.LLmaskcurve); + + if (showtooltip) { + LLmaskshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + LLmaskshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + if (showtooltip) { + LLmaskshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + HHmaskshape->setIdentityValue(0.); + HHmaskshape->setResetCurve(FlatCurveType(defSpot.HHmaskcurve.at(0)), defSpot.HHmaskcurve); + + if (showtooltip) { + HHmaskshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + HHmaskshape->setCurveColorProvider(this, 2); + HHmaskshape->setBottomBarColorProvider(this, 2); + + maskCurveEditorG->curveListComplete(); + + strumaskcol->setAdjusterListener(this); + + toolcolConn = toolcol->signal_toggled().connect(sigc::mem_fun(*this, &LocallabColor::toolcolChanged)); + + fftColorMaskConn = fftColorMask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabColor::fftColorMaskChanged)); + + contcol->setAdjusterListener(this); + + blurcol->setAdjusterListener(this); + + blendmaskcol->setAdjusterListener(this); + + radmaskcol->setLogScale(10, -10); + radmaskcol->setAdjusterListener(this); + + if (showtooltip) { + radmaskcol->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + lapmaskcol->setAdjusterListener(this); + + if (showtooltip) { + lapmaskcol->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + chromaskcol->setAdjusterListener(this); + + gammaskcol->setAdjusterListener(this); + + slomaskcol->setAdjusterListener(this); + + shadmaskcol->setAdjusterListener(this); + + maskHCurveEditorG->setCurveListener(this); + + HHhmaskshape->setIdentityValue(0.); + HHhmaskshape->setResetCurve(FlatCurveType(defSpot.HHhmaskcurve.at(0)), defSpot.HHhmaskcurve); + + if (showtooltip) { + HHhmaskshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP")); + } + + HHhmaskshape->setCurveColorProvider(this, 2); + HHhmaskshape->setBottomBarColorProvider(this, 2); + + maskHCurveEditorG->curveListComplete(); + + mask2CurveEditorG->setCurveListener(this); + + Lmaskshape->setResetCurve(DiagonalCurveType(defSpot.Lmaskcurve.at(0)), defSpot.Lmaskcurve); + + if (showtooltip) { + Lmaskshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + } + + Lmaskshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + Lmaskshape->setLeftBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + mask2CurveEditorG->curveListComplete(); + + mask2CurveEditorGwav->setCurveListener(this); + + LLmaskcolshapewav->setIdentityValue(0.); + LLmaskcolshapewav->setResetCurve(FlatCurveType(defSpot.LLmaskcolcurvewav.at(0)), defSpot.LLmaskcolcurvewav); + + if (showtooltip) { + LLmaskcolshapewav->setTooltip(M("TP_LOCALLAB_LMASK_LEVEL_TOOLTIP")); + } + + LLmaskcolshapewav->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + mask2CurveEditorGwav->curveListComplete(); + + csThresholdcol->setAdjusterListener(this); + + // Add Color & Light specific widgets to GUI Gtk::Frame* const superFrame = Gtk::manage(new Gtk::Frame()); superFrame->set_label_align(0.025, 0.5); - superFrame->set_label_widget(*curvactiv); + // superFrame->set_label_widget(*curvactiv); ToolParamBlock* const superBox = Gtk::manage(new ToolParamBlock()); superBox->pack_start(*lightness); superBox->pack_start(*contrast); superBox->pack_start(*chroma); - gridFrame->set_label_align(0.025, 0.5); ToolParamBlock* const gridBox = Gtk::manage(new ToolParamBlock()); gridBox->pack_start(*labgrid); gridBox->pack_start(*gridMethod); @@ -525,21 +781,165 @@ LocallabColor::LocallabColor(): pack_start(*superFrame); pack_start(*sensi); pack_start(*structcol); - pack_start(*blurcolde); - pack_start(*softradiuscol); + + if (complexsoft < 2) { + pack_start(*blurcolde); + pack_start(*softradiuscol); + } + + pack_start(*invers); + MyExpander* const expcurvcol = Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_EXPCURV"))); + setExpandAlignProperties(expcurvcol, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + ToolParamBlock* const gradcolBox = Gtk::manage(new ToolParamBlock()); + gradcolBox->pack_start(*strcol); + + if (complexsoft < 2) { + gradcolBox->pack_start(*strcolab); + } + + if (complexsoft < 2) { + gradcolBox->pack_start(*strcolh); + } + + gradcolBox->pack_start(*angcol); + expgradcol->add(*gradcolBox, false); + pack_start(*expgradcol, false, false); + ToolParamBlock* const curvBox = Gtk::manage(new ToolParamBlock()); Gtk::HBox* const qualcurvbox = Gtk::manage(new Gtk::HBox()); qualcurvbox->pack_start(*labqualcurv, Gtk::PACK_SHRINK, 4); qualcurvbox->pack_start(*qualitycurveMethod); - pack_start(*qualcurvbox); - pack_start(*llCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor - pack_start(*HCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor - pack_start(*invers); + curvBox->pack_start(*qualcurvbox); + curvBox->pack_start(*llCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + + if (complexsoft < 2) { + curvBox->pack_start(*clCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + curvBox->pack_start(*HCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + curvBox->pack_start(*H2CurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + curvBox->pack_start(*rgbCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + curvBox->pack_start(*special); + } + + expcurvcol->add(*curvBox, false); + pack_start(*expcurvcol, false, false); + ToolParamBlock* const mask7Box = Gtk::manage(new ToolParamBlock()); + mask7Box->pack_start(*merMethod); + Gtk::Frame* const merge1colFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_MERGE1COLFRA"))); + merge1colFrame->set_label_align(0.025, 0.5); + ToolParamBlock* const mergecolBox = Gtk::manage(new ToolParamBlock()); + Gtk::HSeparator* const separatormer = Gtk::manage(new Gtk::HSeparator()); + mergecolBox->pack_start(*separatormer, Gtk::PACK_SHRINK, 2); + mergecolBox->pack_start(*mergecolMethod); + mergecolBox->pack_start(*mercol); + mergecolBox->pack_start(*opacol); + mergecolBox->pack_start(*conthrcol); + ToolParamBlock* const gridmerBox = Gtk::manage(new ToolParamBlock()); + gridmerFrame->set_label_align(0.025, 0.5); + gridmerBox->pack_start(*labgridmerg); + gridmerBox->pack_start(*merlucol); + gridmerFrame->add(*gridmerBox); + mergecolBox->pack_start(*gridmerFrame); + + if (complexsoft < 2) { + merge1colFrame->add(*mergecolBox); + } + + mask7->pack_start(*merge1colFrame); + mask7Box->pack_start(*mask7); + expmaskcol1->add(*mask7Box, false); + + if (complexsoft < 2) { + pack_start(*expmaskcol1, false, false); + } + + MyExpander* const expmaskcol = Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWC"))); + setExpandAlignProperties(expmaskcol, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + if (showtooltip) { + expmaskcol->set_tooltip_markup(M("TP_LOCALLAB_MASK_TOOLTIP")); + } + + Gtk::Frame* const mergecolFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_MERGECOLFRA"))); + mergecolFrame->set_label_align(0.025, 0.5); + ToolParamBlock* const maskcolBox = Gtk::manage(new ToolParamBlock()); + maskcolBox->pack_start(*showmaskcolMethod, Gtk::PACK_SHRINK, 4); + maskcolBox->pack_start(*showmaskcolMethodinv, Gtk::PACK_SHRINK, 4); + maskcolBox->pack_start(*enaColorMask, Gtk::PACK_SHRINK, 0); + maskcolBox->pack_start(*maskCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + Gtk::Frame* const struFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LABSTRUM"))); + struFrame->set_label_align(0.025, 0.5); + ToolParamBlock* const strumBox = Gtk::manage(new ToolParamBlock()); + + if (complexsoft < 2) { + strumBox->pack_start(*strumaskcol); + strumBox->pack_start(*toolcol); + } + + struFrame->add(*strumBox); + + if (complexsoft < 2) { + maskcolBox->pack_start(*struFrame, Gtk::PACK_SHRINK, 0); + } + + Gtk::Frame* const blurFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LABBLURM"))); + blurFrame->set_label_align(0.025, 0.5); + ToolParamBlock* const blurmBox = Gtk::manage(new ToolParamBlock()); + + if (complexsoft < 2) { + blurmBox->pack_start(*fftColorMask, Gtk::PACK_SHRINK, 0); + blurmBox->pack_start(*contcol); + blurmBox->pack_start(*blurcol); + } + + blurFrame->add(*blurmBox); + + if (complexsoft < 2) { + maskcolBox->pack_start(*blurFrame, Gtk::PACK_SHRINK, 0); + } + + maskcolBox->pack_start(*blendmaskcol, Gtk::PACK_SHRINK, 0); + Gtk::Frame* const toolcolFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_TOOLMASK"))); + toolcolFrame->set_label_align(0.025, 0.5); + ToolParamBlock* const toolcolBox = Gtk::manage(new ToolParamBlock()); + toolcolBox->pack_start(*radmaskcol, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 1) { + toolcolBox->pack_start(*lapmaskcol, Gtk::PACK_SHRINK, 0); + } + + toolcolBox->pack_start(*chromaskcol, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 2) { + toolcolBox->pack_start(*gammaskcol, Gtk::PACK_SHRINK, 0); + toolcolBox->pack_start(*slomaskcol, Gtk::PACK_SHRINK, 0); + toolcolBox->pack_start(*shadmaskcol, Gtk::PACK_SHRINK, 0); + toolcolBox->pack_start(*maskHCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + } + + toolcolBox->pack_start(*mask2CurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + + if (complexsoft < 1) { + toolcolBox->pack_start(*mask2CurveEditorGwav, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + toolcolBox->pack_start(*csThresholdcol, Gtk::PACK_SHRINK, 0); + } + + toolcolFrame->add(*toolcolBox); + maskcolBox->pack_start(*toolcolFrame); + mergecolFrame->add(*maskcolBox); + expmaskcol->add(*mergecolFrame, false); + pack_start(*expmaskcol, false, false); } LocallabColor::~LocallabColor() { delete llCurveEditorG; + delete clCurveEditorG; delete HCurveEditorG; + delete H2CurveEditorG; + delete rgbCurveEditorG; + delete maskCurveEditorG; + delete maskHCurveEditorG; + delete mask2CurveEditorG; + delete mask2CurveEditorGwav; } void LocallabColor::setListener(ToolPanelListener* tpl) @@ -547,32 +947,25 @@ void LocallabColor::setListener(ToolPanelListener* tpl) LocallabTool::setListener(tpl); labgrid->setListener(tpl); + labgridmerg->setListener(tpl); } -void LocallabColor::getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask) +void LocallabColor::resetMaskView() { - colorMask = showMaskMethod->get_active_row_number(); + showmaskcolMethodConn.block(true); + showmaskcolMethodConninv.block(true); + + showmaskcolMethod->set_active(0); + showmaskcolMethodinv->set_active(0); + + showmaskcolMethodConn.block(false); + showmaskcolMethodConninv.block(false); } -void LocallabColor::colorForValue(double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) +void LocallabColor::getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask) { - LocallabTool::colorForValue(valX, valY, elemType, callerId, caller); // Mask curves - - float R = 0.f; - float G = 0.f; - float B = 0.f; - - if (elemType == ColorCaller::CCET_VERTICAL_BAR) { - valY = 0.5; - } - - if (callerId == 3) { // LHshape and HHshape curves - Color::hsv2rgb01(float (valX), float (valY), 0.5f, R, G, B); - - caller->ccRed = double (R); - caller->ccGreen = double (G); - caller->ccBlue = double (B); - } + colorMask = showmaskcolMethod->get_active_row_number(); + colorMaskinv = showmaskcolMethodinv->get_active_row_number(); } void LocallabColor::disableListener() @@ -581,8 +974,17 @@ void LocallabColor::disableListener() curvactivConn.block(true); gridMethodConn.block(true); - qualitycurveMethodConn.block(true); inversConn.block(true); + qualitycurveMethodConn.block(true); + toneMethodConn.block(true); + specialConn.block(true); + merMethodConn.block(true); + mergecolMethodConn.block(true); + showmaskcolMethodConn.block(true); + showmaskcolMethodConninv.block(true); + enaColorMaskConn.block(true); + toolcolConn.block(true); + fftColorMaskConn.block(true); } void LocallabColor::enableListener() @@ -591,12 +993,23 @@ void LocallabColor::enableListener() curvactivConn.block(false); gridMethodConn.block(false); - qualitycurveMethodConn.block(false); inversConn.block(false); + qualitycurveMethodConn.block(false); + toneMethodConn.block(false); + specialConn.block(false); + merMethodConn.block(false); + mergecolMethodConn.block(false); + showmaskcolMethodConn.block(false); + showmaskcolMethodConninv.block(false); + enaColorMaskConn.block(false); + toolcolConn.block(false); + fftColorMaskConn.block(false); } void LocallabColor::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { + const int complexsoft = options.complexity; + // Disable all listeners disableListener(); @@ -607,8 +1020,8 @@ void LocallabColor::read(const rtengine::procparams::ProcParams* pp, const Param spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot exp->set_visible(pp->locallab.spots.at(index).visicolor); - exp->setEnabled(pp->locallab.spots.at(index).expcolor); + curvactiv->set_active(pp->locallab.spots.at(index).curvactiv); lightness->setValue(pp->locallab.spots.at(index).lightness); contrast->setValue(pp->locallab.spots.at(index).contrast); @@ -628,8 +1041,27 @@ void LocallabColor::read(const rtengine::procparams::ProcParams* pp, const Param strengthgrid->setValue(pp->locallab.spots.at(index).strengthgrid); sensi->setValue(pp->locallab.spots.at(index).sensi); structcol->setValue(pp->locallab.spots.at(index).structcol); - blurcolde->setValue(pp->locallab.spots.at(index).blurcolde); - softradiuscol->setValue(pp->locallab.spots.at(index).softradiuscol); + + if (complexsoft < 2) { + blurcolde->setValue(pp->locallab.spots.at(index).blurcolde); + softradiuscol->setValue(pp->locallab.spots.at(index).softradiuscol); + } else { + blurcolde->setValue(5.); + softradiuscol->setValue(0.); + } + + invers->set_active(pp->locallab.spots.at(index).invers); + strcol->setValue(pp->locallab.spots.at(index).strcol); + + if (complexsoft < 2) { + strcolab->setValue(pp->locallab.spots.at(index).strcolab); + strcolh->setValue(pp->locallab.spots.at(index).strcolh); + } else { + strcolab->setValue(0.); + strcolh->setValue(0.); + } + + angcol->setValue(pp->locallab.spots.at(index).angcol); if (pp->locallab.spots.at(index).qualitycurveMethod == "none") { qualitycurveMethod->set_active(0); @@ -639,25 +1071,167 @@ void LocallabColor::read(const rtengine::procparams::ProcParams* pp, const Param llshape->setCurve(pp->locallab.spots.at(index).llcurve); ccshape->setCurve(pp->locallab.spots.at(index).cccurve); - LHshape->setCurve(pp->locallab.spots.at(index).LHcurve); - HHshape->setCurve(pp->locallab.spots.at(index).HHcurve); - invers->set_active(pp->locallab.spots.at(index).invers); - enaMask->set_active(pp->locallab.spots.at(index).enaColorMask); - CCMaskShape->setCurve(pp->locallab.spots.at(index).CCmaskcurve); - LLMaskShape->setCurve(pp->locallab.spots.at(index).LLmaskcurve); - HHMaskShape->setCurve(pp->locallab.spots.at(index).HHmaskcurve); - blendMask->setValue(pp->locallab.spots.at(index).blendmaskcol); - radMask->setValue(pp->locallab.spots.at(index).radmaskcol); - chroMask->setValue(pp->locallab.spots.at(index).chromaskcol); - gamMask->setValue(pp->locallab.spots.at(index).gammaskcol); - sloMask->setValue(pp->locallab.spots.at(index).slomaskcol); + + if (complexsoft < 2) { + clshape->setCurve(pp->locallab.spots.at(index).clcurve); + lcshape->setCurve(pp->locallab.spots.at(index).lccurve); + LHshape->setCurve(pp->locallab.spots.at(index).LHcurve); + HHshape->setCurve(pp->locallab.spots.at(index).HHcurve); + } else { + clshape->reset(); + lcshape->reset(); + LHshape->reset(); + HHshape->reset(); + } + + if (pp->locallab.spots.at(index).toneMethod == "one") { + toneMethod->set_active(0); + } else if (pp->locallab.spots.at(index).toneMethod == "two") { + toneMethod->set_active(1); + } else if (pp->locallab.spots.at(index).toneMethod == "thr") { + toneMethod->set_active(2); + } else if (pp->locallab.spots.at(index).toneMethod == "fou") { + toneMethod->set_active(3); + } + + if (complexsoft < 2) { + rgbshape->setCurve(pp->locallab.spots.at(index).rgbcurve); + special->set_active(pp->locallab.spots.at(index).special); + + if (pp->locallab.spots.at(index).merMethod == "mone") { + merMethod->set_active(0); + } else if (pp->locallab.spots.at(index).merMethod == "mtwo") { + merMethod->set_active(1); + } else if (pp->locallab.spots.at(index).merMethod == "mthr") { + merMethod->set_active(2); + } else if (pp->locallab.spots.at(index).merMethod == "mfou") { + merMethod->set_active(3); + } else if (pp->locallab.spots.at(index).merMethod == "mfiv") { + merMethod->set_active(4); + } + } else { + rgbshape->reset(); + special->set_active(false); + merMethod->set_active(0); + } + + if (pp->locallab.spots.at(index).mergecolMethod == "one") { + mergecolMethod->set_active(0); + } else if (pp->locallab.spots.at(index).mergecolMethod == "two") { + mergecolMethod->set_active(1); + } else if (pp->locallab.spots.at(index).mergecolMethod == "thr") { + mergecolMethod->set_active(2); + } else if (pp->locallab.spots.at(index).mergecolMethod == "fou") { + mergecolMethod->set_active(3); + } else if (pp->locallab.spots.at(index).mergecolMethod == "fiv") { + mergecolMethod->set_active(4); + } else if (pp->locallab.spots.at(index).mergecolMethod == "six") { + mergecolMethod->set_active(5); + } else if (pp->locallab.spots.at(index).mergecolMethod == "sev") { + mergecolMethod->set_active(6); + } else if (pp->locallab.spots.at(index).mergecolMethod == "sev0") { + mergecolMethod->set_active(7); + } else if (pp->locallab.spots.at(index).mergecolMethod == "sev1") { + mergecolMethod->set_active(8); + } else if (pp->locallab.spots.at(index).mergecolMethod == "sev2") { + mergecolMethod->set_active(9); + } else if (pp->locallab.spots.at(index).mergecolMethod == "hei") { + mergecolMethod->set_active(10); + } else if (pp->locallab.spots.at(index).mergecolMethod == "nin") { + mergecolMethod->set_active(11); + } else if (pp->locallab.spots.at(index).mergecolMethod == "ten") { + mergecolMethod->set_active(12); + } else if (pp->locallab.spots.at(index).mergecolMethod == "ele") { + mergecolMethod->set_active(13); + } else if (pp->locallab.spots.at(index).mergecolMethod == "twe") { + mergecolMethod->set_active(14); + } else if (pp->locallab.spots.at(index).mergecolMethod == "thi") { + mergecolMethod->set_active(15); + } else if (pp->locallab.spots.at(index).mergecolMethod == "for") { + mergecolMethod->set_active(16); + } else if (pp->locallab.spots.at(index).mergecolMethod == "hue") { + mergecolMethod->set_active(17); + } else if (pp->locallab.spots.at(index).mergecolMethod == "sat") { + mergecolMethod->set_active(18); + } else if (pp->locallab.spots.at(index).mergecolMethod == "col") { + mergecolMethod->set_active(19); + } else if (pp->locallab.spots.at(index).mergecolMethod == "lum") { + mergecolMethod->set_active(20); + } + + mercol->setValue(pp->locallab.spots.at(index).mercol); + opacol->setValue(pp->locallab.spots.at(index).opacol); + conthrcol->setValue(pp->locallab.spots.at(index).conthrcol); + labgridmerg->setParams(0, 0, + pp->locallab.spots.at(index).labgridAHighmerg / LocallabParams::LABGRIDL_CORR_MAX, + pp->locallab.spots.at(index).labgridBHighmerg / LocallabParams::LABGRIDL_CORR_MAX, + false); + merlucol->setValue(pp->locallab.spots.at(index).merlucol); + enaColorMask->set_active(pp->locallab.spots.at(index).enaColorMask); + CCmaskshape->setCurve(pp->locallab.spots.at(index).CCmaskcurve); + LLmaskshape->setCurve(pp->locallab.spots.at(index).LLmaskcurve); + HHmaskshape->setCurve(pp->locallab.spots.at(index).HHmaskcurve); + + if (complexsoft < 2) { + strumaskcol->setValue(pp->locallab.spots.at(index).strumaskcol); + toolcol->set_active(pp->locallab.spots.at(index).toolcol); + fftColorMask->set_active(pp->locallab.spots.at(index).fftColorMask); + contcol->setValue(pp->locallab.spots.at(index).contcol); + blurcol->setValue(pp->locallab.spots.at(index).blurcol); + } else { + strumaskcol->setValue(0.); + toolcol->set_active(false); + fftColorMask->set_active(false); + contcol->setValue(0.); + blurcol->setLimits(0.2, 100., 0.5, 0.2); + blurcol->setValue(pp->locallab.spots.at(index).blurcol); + } + + blendmaskcol->setValue(pp->locallab.spots.at(index).blendmaskcol); + radmaskcol->setValue(pp->locallab.spots.at(index).radmaskcol); + + if (complexsoft < 2) { + lapmaskcol->setValue(pp->locallab.spots.at(index).lapmaskcol); + } else { + lapmaskcol->setValue(0.); + } + + chromaskcol->setValue(pp->locallab.spots.at(index).chromaskcol); + + if (complexsoft < 2) { + gammaskcol->setValue(pp->locallab.spots.at(index).gammaskcol); + slomaskcol->setValue(pp->locallab.spots.at(index).slomaskcol); + shadmaskcol->setValue(pp->locallab.spots.at(index).shadmaskcol); + HHhmaskshape->setCurve(pp->locallab.spots.at(index).HHhmaskcurve); + } else { + gammaskcol->setValue(1.); + slomaskcol->setValue(0.); + shadmaskcol->setValue(0.); + HHhmaskshape->reset(); + } + + Lmaskshape->setCurve(pp->locallab.spots.at(index).Lmaskcurve); + + if (complexsoft == 0) { + LLmaskcolshapewav->setCurve(pp->locallab.spots.at(index).LLmaskcolcurvewav); + } else { + LLmaskcolshapewav->reset(); + } + + csThresholdcol->setValue(pp->locallab.spots.at(index).csthresholdcol); } // Enable all listeners enableListener(); // Update GUI according to invers button state - updateColorGUI(); + updateColorGUI1(); + + // Update GUI according to merMethod combobox state + updateColorGUI2(); + + // Update GUI according to fftColorMash button state + updateColorGUI3(); // Note: No need to manage pedited as batch mode is deactivated for Locallab } @@ -668,7 +1242,6 @@ void LocallabColor::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pe if (index < (int)pp->locallab.spots.size()) { pp->locallab.spots.at(index).expcolor = exp->getEnabled(); - pp->locallab.spots.at(index).visicolor = exp->get_visible(); pp->locallab.spots.at(index).curvactiv = curvactiv->get_active(); @@ -685,9 +1258,9 @@ void LocallabColor::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pe pp->locallab.spots.at(index).labgridBHigh *= LocallabParams::LABGRIDL_CORR_MAX; if (gridMethod->get_active_row_number() == 0) { - pp->locallab.spots.at(pp->locallab.selspot).gridMethod = "one"; + pp->locallab.spots.at(index).gridMethod = "one"; } else if (gridMethod->get_active_row_number() == 1) { - pp->locallab.spots.at(pp->locallab.selspot).gridMethod = "two"; + pp->locallab.spots.at(index).gridMethod = "two"; } pp->locallab.spots.at(index).strengthgrid = strengthgrid->getIntValue(); @@ -695,6 +1268,11 @@ void LocallabColor::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pe pp->locallab.spots.at(index).structcol = structcol->getIntValue(); pp->locallab.spots.at(index).blurcolde = blurcolde->getIntValue(); pp->locallab.spots.at(index).softradiuscol = softradiuscol->getValue(); + pp->locallab.spots.at(index).invers = invers->get_active(); + pp->locallab.spots.at(index).strcol = strcol->getValue(); + pp->locallab.spots.at(index).strcolab = strcolab->getValue(); + pp->locallab.spots.at(index).strcolh = strcolh->getValue(); + pp->locallab.spots.at(index).angcol = angcol->getValue(); if (qualitycurveMethod->get_active_row_number() == 0) { pp->locallab.spots.at(index).qualitycurveMethod = "none"; @@ -704,18 +1282,112 @@ void LocallabColor::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pe pp->locallab.spots.at(index).llcurve = llshape->getCurve(); pp->locallab.spots.at(index).cccurve = ccshape->getCurve(); + pp->locallab.spots.at(index).clcurve = clshape->getCurve(); + pp->locallab.spots.at(index).lccurve = lcshape->getCurve(); pp->locallab.spots.at(index).LHcurve = LHshape->getCurve(); pp->locallab.spots.at(index).HHcurve = HHshape->getCurve(); - pp->locallab.spots.at(index).invers = invers->get_active(); - pp->locallab.spots.at(index).enaColorMask = enaMask->get_active(); - pp->locallab.spots.at(index).CCmaskcurve = CCMaskShape->getCurve(); - pp->locallab.spots.at(index).LLmaskcurve = LLMaskShape->getCurve(); - pp->locallab.spots.at(index).HHmaskcurve = HHMaskShape->getCurve(); - pp->locallab.spots.at(index).blendmaskcol = blendMask->getIntValue(); - pp->locallab.spots.at(index).radmaskcol = radMask->getValue(); - pp->locallab.spots.at(index).chromaskcol = chroMask->getValue(); - pp->locallab.spots.at(index).gammaskcol = gamMask->getValue(); - pp->locallab.spots.at(index).slomaskcol = sloMask->getValue(); + + if (toneMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).toneMethod = "one"; + } else if (toneMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).toneMethod = "two"; + } else if (toneMethod->get_active_row_number() == 2) { + pp->locallab.spots.at(index).toneMethod = "thr"; + } else if (toneMethod->get_active_row_number() == 3) { + pp->locallab.spots.at(index).toneMethod = "fou"; + } + + pp->locallab.spots.at(index).rgbcurve = rgbshape->getCurve(); + pp->locallab.spots.at(index).special = special->get_active(); + + if (merMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).merMethod = "mone"; + } else if (merMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).merMethod = "mtwo"; + } else if (merMethod->get_active_row_number() == 2) { + pp->locallab.spots.at(index).merMethod = "mthr"; + } else if (merMethod->get_active_row_number() == 3) { + pp->locallab.spots.at(index).merMethod = "mfou"; + } else if (merMethod->get_active_row_number() == 4) { + pp->locallab.spots.at(index).merMethod = "mfiv"; + } + + if (mergecolMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).mergecolMethod = "one"; + } else if (mergecolMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).mergecolMethod = "two"; + } else if (mergecolMethod->get_active_row_number() == 2) { + pp->locallab.spots.at(index).mergecolMethod = "thr"; + } else if (mergecolMethod->get_active_row_number() == 3) { + pp->locallab.spots.at(index).mergecolMethod = "fou"; + } else if (mergecolMethod->get_active_row_number() == 4) { + pp->locallab.spots.at(index).mergecolMethod = "fiv"; + } else if (mergecolMethod->get_active_row_number() == 5) { + pp->locallab.spots.at(index).mergecolMethod = "six"; + } else if (mergecolMethod->get_active_row_number() == 6) { + pp->locallab.spots.at(index).mergecolMethod = "sev"; + } else if (mergecolMethod->get_active_row_number() == 7) { + pp->locallab.spots.at(index).mergecolMethod = "sev0"; + } else if (mergecolMethod->get_active_row_number() == 8) { + pp->locallab.spots.at(index).mergecolMethod = "sev1"; + } else if (mergecolMethod->get_active_row_number() == 9) { + pp->locallab.spots.at(index).mergecolMethod = "sev2"; + } else if (mergecolMethod->get_active_row_number() == 10) { + pp->locallab.spots.at(index).mergecolMethod = "hei"; + } else if (mergecolMethod->get_active_row_number() == 11) { + pp->locallab.spots.at(index).mergecolMethod = "nin"; + } else if (mergecolMethod->get_active_row_number() == 12) { + pp->locallab.spots.at(index).mergecolMethod = "ten"; + } else if (mergecolMethod->get_active_row_number() == 13) { + pp->locallab.spots.at(index).mergecolMethod = "ele"; + } else if (mergecolMethod->get_active_row_number() == 14) { + pp->locallab.spots.at(index).mergecolMethod = "twe"; + } else if (mergecolMethod->get_active_row_number() == 15) { + pp->locallab.spots.at(index).mergecolMethod = "thi"; + } else if (mergecolMethod->get_active_row_number() == 16) { + pp->locallab.spots.at(index).mergecolMethod = "for"; + } else if (mergecolMethod->get_active_row_number() == 17) { + pp->locallab.spots.at(index).mergecolMethod = "hue"; + } else if (mergecolMethod->get_active_row_number() == 18) { + pp->locallab.spots.at(index).mergecolMethod = "sat"; + } else if (mergecolMethod->get_active_row_number() == 19) { + pp->locallab.spots.at(index).mergecolMethod = "col"; + } else if (mergecolMethod->get_active_row_number() == 20) { + pp->locallab.spots.at(index).mergecolMethod = "lum"; + } + + pp->locallab.spots.at(index).mercol = mercol->getValue(); + pp->locallab.spots.at(index).opacol = opacol->getValue(); + pp->locallab.spots.at(index).conthrcol = conthrcol->getValue(); + labgridmerg->getParams(pp->locallab.spots.at(index).labgridALowmerg, + pp->locallab.spots.at(index).labgridBLowmerg, + pp->locallab.spots.at(index).labgridAHighmerg, + pp->locallab.spots.at(index).labgridBHighmerg); + pp->locallab.spots.at(index).labgridALowmerg *= LocallabParams::LABGRIDL_CORR_MAX; + pp->locallab.spots.at(index).labgridAHighmerg *= LocallabParams::LABGRIDL_CORR_MAX; + pp->locallab.spots.at(index).labgridBLowmerg *= LocallabParams::LABGRIDL_CORR_MAX; + pp->locallab.spots.at(index).labgridBHighmerg *= LocallabParams::LABGRIDL_CORR_MAX; + pp->locallab.spots.at(index).merlucol = merlucol->getValue(); + pp->locallab.spots.at(index).enaColorMask = enaColorMask->get_active(); + pp->locallab.spots.at(index).CCmaskcurve = CCmaskshape->getCurve(); + pp->locallab.spots.at(index).LLmaskcurve = LLmaskshape->getCurve(); + pp->locallab.spots.at(index).HHmaskcurve = HHmaskshape->getCurve(); + pp->locallab.spots.at(index).strumaskcol = strumaskcol->getValue(); + pp->locallab.spots.at(index).toolcol = toolcol->get_active(); + pp->locallab.spots.at(index).fftColorMask = fftColorMask->get_active(); + pp->locallab.spots.at(index).contcol = contcol->getValue(); + pp->locallab.spots.at(index).blurcol = blurcol->getValue(); + pp->locallab.spots.at(index).blendmaskcol = blendmaskcol->getIntValue(); + pp->locallab.spots.at(index).radmaskcol = radmaskcol->getValue(); + pp->locallab.spots.at(index).lapmaskcol = lapmaskcol->getValue(); + pp->locallab.spots.at(index).chromaskcol = chromaskcol->getValue(); + pp->locallab.spots.at(index).gammaskcol = gammaskcol->getValue(); + pp->locallab.spots.at(index).slomaskcol = slomaskcol->getValue(); + pp->locallab.spots.at(index).shadmaskcol = shadmaskcol->getIntValue(); + pp->locallab.spots.at(index).HHhmaskcurve = HHhmaskshape->getCurve(); + pp->locallab.spots.at(index).Lmaskcurve = Lmaskshape->getCurve(); + pp->locallab.spots.at(index).LLmaskcolcurvewav = LLmaskcolshapewav->getCurve(); + pp->locallab.spots.at(index).csthresholdcol = csThresholdcol->getValue(); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -728,7 +1400,7 @@ void LocallabColor::setDefaults(const rtengine::procparams::ProcParams* defParam if (index < (int)defParams->locallab.spots.size()) { const LocallabParams::LocallabSpot defSpot = defParams->locallab.spots.at(index); - // Set default value for adjuster and labgrid widgets + // Set default value for adjuster, labgrid and threshold adjuster widgets lightness->setDefault((double)defSpot.lightness); contrast->setDefault((double)defSpot.contrast); chroma->setDefault((double)defSpot.chroma); @@ -741,11 +1413,29 @@ void LocallabColor::setDefaults(const rtengine::procparams::ProcParams* defParam structcol->setDefault((double)defSpot.structcol); blurcolde->setDefault((double)defSpot.blurcolde); softradiuscol->setDefault(defSpot.softradiuscol); - blendMask->setDefault((double)defSpot.blendmaskcol); - radMask->setDefault(defSpot.radmaskcol); - chroMask->setDefault(defSpot.chromaskcol); - gamMask->setDefault(defSpot.gammaskcol); - sloMask->setDefault(defSpot.slomaskcol); + strcol->setDefault(defSpot.strcol); + strcolab->setDefault(defSpot.strcolab); + strcolh->setDefault(defSpot.strcolh); + angcol->setDefault(defSpot.angcol); + mercol->setDefault(defSpot.mercol); + opacol->setDefault(defSpot.opacol); + conthrcol->setDefault(defSpot.conthrcol); + labgridmerg->setDefault(defSpot.labgridALowmerg / LocallabParams::LABGRIDL_CORR_MAX, + defSpot.labgridBLowmerg / LocallabParams::LABGRIDL_CORR_MAX, + defSpot.labgridAHighmerg / LocallabParams::LABGRIDL_CORR_MAX, + defSpot.labgridBHighmerg / LocallabParams::LABGRIDL_CORR_MAX); + merlucol->setDefault(defSpot.merlucol); + strumaskcol->setDefault(defSpot.strumaskcol); + contcol->setDefault(defSpot.contcol); + blurcol->setDefault(defSpot.blurcol); + blendmaskcol->setDefault((double)defSpot.blendmaskcol); + radmaskcol->setDefault(defSpot.radmaskcol); + lapmaskcol->setDefault(defSpot.lapmaskcol); + chromaskcol->setDefault(defSpot.chromaskcol); + gammaskcol->setDefault(defSpot.gammaskcol); + slomaskcol->setDefault(defSpot.slomaskcol); + shadmaskcol->setDefault((double)defSpot.shadmaskcol); + csThresholdcol->setDefault(defSpot.csthresholdcol); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -810,38 +1500,141 @@ void LocallabColor::adjusterChanged(Adjuster* a, double newval) } } - if (a == blendMask) { + if (a == strcol) { + if (listener) { + listener->panelChanged(Evlocallabstrcol, + strcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strcolab) { + if (listener) { + listener->panelChanged(Evlocallabstrcolab, + strcolab->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strcolh) { + if (listener) { + listener->panelChanged(Evlocallabstrcolh, + strcolh->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == angcol) { + if (listener) { + listener->panelChanged(Evlocallabangcol, + angcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == mercol) { + if (listener) { + listener->panelChanged(Evlocallabmercol, + mercol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == opacol) { + if (listener) { + listener->panelChanged(Evlocallabopacol, + opacol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == conthrcol) { + if (listener) { + listener->panelChanged(Evlocallabconthrcol, + conthrcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == merlucol) { + if (listener) { + listener->panelChanged(Evlocallabmerlucol, + merlucol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strumaskcol) { + if (listener) { + listener->panelChanged(Evlocallabstrumaskcol, + strumaskcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == contcol) { + if (listener) { + listener->panelChanged(Evlocallabcontcol, + contcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blurcol) { + if (listener) { + listener->panelChanged(Evlocallabblurcol, + blurcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blendmaskcol) { if (listener) { listener->panelChanged(Evlocallabblendmaskcol, - blendMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + blendmaskcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == radMask) { + if (a == radmaskcol) { if (listener) { listener->panelChanged(Evlocallabradmaskcol, - radMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + radmaskcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == chroMask) { + if (a == lapmaskcol) { + if (listener) { + listener->panelChanged(Evlocallablapmaskcol, + lapmaskcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chromaskcol) { if (listener) { listener->panelChanged(Evlocallabchromaskcol, - chroMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + chromaskcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == gamMask) { + if (a == gammaskcol) { if (listener) { listener->panelChanged(Evlocallabgammaskcol, - gamMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + gammaskcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == sloMask) { + if (a == slomaskcol) { if (listener) { listener->panelChanged(Evlocallabslomaskcol, - sloMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + slomaskcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == shadmaskcol) { + if (listener) { + listener->panelChanged(Evlocallabshadmaskcol, + shadmaskcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabColor::adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) +{ + if (isLocActivated && exp->getEnabled()) { + if (a == csThresholdcol) { + if (listener) { + listener->panelChanged(EvlocallabcsThresholdcol, + csThresholdcol->getHistoryString() + " (" + escapeHtmlChars(spotName) + ")"); } } } @@ -864,6 +1657,20 @@ void LocallabColor::curveChanged(CurveEditor* ce) } } + if (ce == clshape) { + if (listener) { + listener->panelChanged(Evlocallabclshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == lcshape) { + if (listener) { + listener->panelChanged(Evlocallablcshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + if (ce == LHshape) { if (listener) { listener->panelChanged(EvlocallabLHshape, @@ -878,27 +1685,54 @@ void LocallabColor::curveChanged(CurveEditor* ce) } } - if (ce == CCMaskShape) { + if (ce == rgbshape) { + if (listener) { + listener->panelChanged(Evlocallabrgbshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == CCmaskshape) { if (listener) { listener->panelChanged(EvlocallabCCmaskshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } - if (ce == LLMaskShape) { + if (ce == LLmaskshape) { if (listener) { listener->panelChanged(EvlocallabLLmaskshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } - if (ce == HHMaskShape) { + if (ce == HHmaskshape) { if (listener) { listener->panelChanged(EvlocallabHHmaskshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } + if (ce == HHhmaskshape) { + if (listener) { + listener->panelChanged(EvlocallabHHhmaskshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == Lmaskshape) { + if (listener) { + listener->panelChanged(EvlocallabLmaskshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == LLmaskcolshapewav) { + if (listener) { + listener->panelChanged(EvlocallabLLmaskcolshapewav, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } } } @@ -917,31 +1751,21 @@ void LocallabColor::enabledChanged() } } -void LocallabColor::enaMaskChanged() +void LocallabColor::updateMaskBackground(const double normChromar, const double normLumar, const double normHuer) { - if (isLocActivated && exp->getEnabled()) { - if (listener) { - if (enaMask->get_active()) { - listener->panelChanged(EvLocallabEnaColorMask, - M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); - } else { - listener->panelChanged(EvLocallabEnaColorMask, - M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); - } - } - } -} + idle_register.add( + [this, normHuer, normLumar, normChromar]() -> bool { + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected -void LocallabColor::showMaskMethodChanged() -{ - // If mask preview is activated, deactivate all other tool mask preview - if (locToolListener) { - locToolListener->resetOtherMaskView(this); - } + // Update mask background + CCmaskshape->updateLocallabBackground(normChromar); + LLmaskshape->updateLocallabBackground(normLumar); + HHmaskshape->updateLocallabBackground(normHuer); + HHhmaskshape->updateLocallabBackground(normHuer); - if (listener) { - listener->panelChanged(EvlocallabshowmaskMethod, ""); + return false; } + ); } void LocallabColor::curvactivChanged() @@ -959,9 +1783,19 @@ void LocallabColor::curvactivChanged() } } +void LocallabColor::gridMethodChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvLocallabgridMethod, + gridMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + void LocallabColor::inversChanged() { - updateColorGUI(); // Update GUI according to invers button state + updateColorGUI1(); // Update GUI according to invers button state if (isLocActivated && exp->getEnabled()) { if (listener) { @@ -986,82 +1820,311 @@ void LocallabColor::qualitycurveMethodChanged() } } -void LocallabColor::gridMethodChanged() +void LocallabColor::toneMethodChanged() { if (isLocActivated && exp->getEnabled()) { if (listener) { - listener->panelChanged(EvLocallabgridMethod, - gridMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + listener->panelChanged(EvLocallabtoneMethod, + toneMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); } } } -void LocallabColor::updateColorGUI() +void LocallabColor::specialChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (special->get_active()) { + listener->panelChanged(EvLocallabspecial, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabspecial, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabColor::merMethodChanged() +{ + updateColorGUI2(); // Update GUI according to merMethod combobox state + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvLocallabmerMethod, + merMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +void LocallabColor::mergecolMethodChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvLocallabmergecolMethod, + mergecolMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +void LocallabColor::showmaskcolMethodChanged() +{ + // If mask preview is activated, deactivate other Color & Light mask preview + showmaskcolMethodConninv.block(true); + showmaskcolMethodinv->set_active(0); + showmaskcolMethodConninv.block(false); + + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskMethod, ""); + } +} + +void LocallabColor::showmaskcolMethodChangedinv() +{ + // If mask preview is activated, deactivate other Color & Light mask preview + showmaskcolMethodConn.block(true); + showmaskcolMethod->set_active(0); + showmaskcolMethodConn.block(false); + + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskMethod, ""); + } +} + +void LocallabColor::enaColorMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enaColorMask->get_active()) { + listener->panelChanged(EvLocallabEnaColorMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnaColorMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabColor::toolcolChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (toolcol->get_active()) { + listener->panelChanged(EvLocallabtoolcol, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabtoolcol, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabColor::fftColorMaskChanged() +{ + updateColorGUI3(); // Update GUI according to fftColorMash button state + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (fftColorMask->get_active()) { + listener->panelChanged(EvLocallabfftColorMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabfftColorMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabColor::updateColorGUI1() { if (invers->get_active()) { - sensi->show(); - llCurveEditorG->show(); - HCurveEditorG->hide(); - curvactiv->hide(); - qualitycurveMethod->hide(); - labqualcurv->hide(); - maskExp->hide(); - structcol->hide(); - blurcolde->show(); gridFrame->hide(); - strengthgrid->hide(); + structcol->hide(); softradiuscol->hide(); - + expgradcol->hide(); + labqualcurv->hide(); + qualitycurveMethod->hide(); + clCurveEditorG->hide(); + HCurveEditorG->hide(); + expmaskcol1->hide(); + showmaskcolMethod->hide(); // TODO Manage cases where avoid is activated with mask on + showmaskcolMethodinv->show(); + contcol->hide(); + blurcol->hide(); } else { - sensi->show(); - llCurveEditorG->show(); - HCurveEditorG->show(); - curvactiv->hide(); - qualitycurveMethod->show(); - labqualcurv->show(); - maskExp->show(); - structcol->show(); - blurcolde->show(); gridFrame->show(); + structcol->show(); softradiuscol->show(); + expgradcol->show(); + labqualcurv->show(); + qualitycurveMethod->show(); + clCurveEditorG->show(); + HCurveEditorG->show(); + expmaskcol1->show(); + showmaskcolMethodinv->hide(); + showmaskcolMethod->show(); + contcol->show(); + blurcol->show(); } } +void LocallabColor::updateColorGUI2() +{ + // Note: When a merMethod is selected, invers button is set insensitive to avoid the combobox to disappear + switch (merMethod->get_active_row_number()) { + case 0: + invers->set_sensitive(true); + H2CurveEditorG->set_sensitive(true); + rgbCurveEditorG->set_sensitive(true); + special->set_sensitive(true); + mask7->hide(); + conthrcol->hide(); + gridmerFrame->hide(); + break; + + case 1: + invers->set_sensitive(false); + H2CurveEditorG->set_sensitive(true); + rgbCurveEditorG->set_sensitive(true); + special->set_sensitive(true); + mask7->hide(); + conthrcol->hide(); + gridmerFrame->hide(); + break; + + case 2: + sensi->set_sensitive(false); + invers->set_sensitive(false); + H2CurveEditorG->set_sensitive(true); + rgbCurveEditorG->set_sensitive(false); + special->set_sensitive(false); + mask7->show(); + conthrcol->show(); + gridmerFrame->hide(); + break; + + case 3: + invers->set_sensitive(false); + H2CurveEditorG->set_sensitive(true); + rgbCurveEditorG->set_sensitive(false); + special->set_sensitive(false); + mask7->show(); + conthrcol->show(); + gridmerFrame->hide(); + break; + + case 4: + invers->set_sensitive(false); + H2CurveEditorG->set_sensitive(true); + rgbCurveEditorG->set_sensitive(false); + special->set_sensitive(false); + mask7->show(); + conthrcol->hide(); + gridmerFrame->show(); + } +} + +void LocallabColor::updateColorGUI3() +{ + const double temp = blurcol->getValue(); + + if (fftColorMask->get_active()) { + blurcol->setLimits(0.2, 1000., 0.5, 0.2); + } else { + blurcol->setLimits(0.2, 100., 0.5, 0.2); + } + + blurcol->setValue(temp); +} + /* ==== LocallabExposure ==== */ LocallabExposure::LocallabExposure(): - LocallabTool(this, M("TP_LOCALLAB_EXP_TOOLNAME"), M("TP_LOCALLAB_EXPOSE"), false, MaskNormal), + LocallabTool(this, M("TP_LOCALLAB_EXP_TOOLNAME"), M("TP_LOCALLAB_EXPOSE"), false), // Exposure specific widgets expMethod(Gtk::manage(new MyComboBoxText())), pdeFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_PDEFRA")))), - laplacexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPLACEXP"), 0.0, 100.0, 0.1, 20.))), - linear(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LINEAR"), 0., 1., 0.01, 0.))), - balanexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BALANEXP"), 0.2, 1.2, 0.01, 0.8))), - expcomp(Gtk::manage(new Adjuster(M("TP_EXPOSURE_EXPCOMP"), -2.0, 4.0, 0.05, 0.0))), - hlcompr(Gtk::manage(new Adjuster(M("TP_EXPOSURE_COMPRHIGHLIGHTS"), 0, 500, 1, 0))), - hlcomprthresh(Gtk::manage(new Adjuster(M("TP_EXPOSURE_COMPRHIGHLIGHTSTHRESHOLD"), 0, 100, 1, 0))), - black(Gtk::manage(new Adjuster(M("TP_EXPOSURE_BLACKLEVEL"), -16384, 32768, 50, 0))), - shadex(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHADEX"), 0, 100, 1, 0))), - shcompr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHADEXCOMP"), 0, 100, 1, 50))), - expchroma(Gtk::manage(new Adjuster(M("TP_LOCALLAB_EXPCHROMA"), -50, 100, 1, 30))), - warm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_WARM"), -100., 100., 1., 0., Gtk::manage(new RTImage("circle-blue-small.png")), Gtk::manage(new RTImage("circle-orange-small.png"))))), + laplacexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPLACEXP"), 0.0, 100.0, 0.1, 0.))), + linear(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LINEAR"), 0., 1., 0.01, 0.3))), + balanexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BALANEXP"), 0.5, 1.5, 0.01, 1.0))), + gamm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMM"), 0.2, 1.3, 0.01, 0.4))), + ctboxexpmethod(Gtk::manage(new Gtk::HBox())), + exnoiseMethod(Gtk::manage(new MyComboBoxText())), + fatFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_FATFRA")))), + fatamount(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATAMOUNT"), 1., 100., 1., 1.))), + fatdetail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATDETAIL"), -100., 300., 1., 0.))), + fatlevel(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATLEVEL"), 0.25, 2.5, 0.05, 1.))), + fatanchor(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATANCHORA"), 0.1, 3.0, 0.05, 1.))), sensiex(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))), structexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRUCCOL"), 0, 100, 1, 0))), blurexpde(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURDE"), 2, 100, 1, 5))), - softradiusexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.1, 0.))), + exptoolexp(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_EXPTOOL")))), + expcomp(Gtk::manage(new Adjuster(M("TP_EXPOSURE_EXPCOMP"), -2.0, 3.0, 0.05, 0.0))), + black(Gtk::manage(new Adjuster(M("TP_EXPOSURE_BLACKLEVEL"), -16384, 32768, 10, 0))), + hlcompr(Gtk::manage(new Adjuster(M("TP_EXPOSURE_COMPRHIGHLIGHTS"), 0, 500, 1, 0))), + hlcomprthresh(Gtk::manage(new Adjuster(M("TP_EXPOSURE_COMPRHIGHLIGHTSTHRESHOLD"), 0, 100, 1, 0))), + shadex(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHADEX"), 0, 100, 1, 0))), + shcompr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHADEXCOMP"), 0, 100, 1, 50))), + expchroma(Gtk::manage(new Adjuster(M("TP_LOCALLAB_EXPCHROMA"), -50, 100, 1, 30))), curveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_CURVEEDITOR_TONES_LABEL"))), - inversex(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))) + shapeexpos(static_cast(curveEditorG->addCurve(CT_Diagonal, ""))), + expgradexp(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_EXPGRAD")))), + strexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -4., 4., 0.05, 0.))), + angexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))), + softradiusexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), -10.0, 1000.0, 0.5, 0.))), + inversex(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))), + expmaskexp(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWE")))), + showmaskexpMethod(Gtk::manage(new MyComboBoxText())), + showmaskexpMethodinv(Gtk::manage(new MyComboBoxText())), + enaExpMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), + enaExpMaskaft(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASKAFT")))), + maskexpCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), + CCmaskexpshape(static_cast(maskexpCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false))), + LLmaskexpshape(static_cast(maskexpCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false))), + HHmaskexpshape(static_cast(maskexpCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true))), + blendmaskexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), + radmaskexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), -10.0, 1000.0, 0.1, 0.))), + lapmaskexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPMASKCOL"), 0.0, 100.0, 0.1, 0.))), + chromaskexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), + gammaskexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.25, 4.0, 0.01, 1.))), + slomaskexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), + gradFramemask(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_GRADFRA")))), + strmaskexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -2., 2., 0.05, 0.))), + angmaskexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180., 180., 0.1, 0.))), + mask2expCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), + Lmaskexpshape(static_cast(mask2expCurveEditorG->addCurve(CT_Diagonal, "L(L)"))) { - const bool showtooltip = options.showtooltip; + const LocallabParams::LocallabSpot defSpot; + const bool showtooltip = options.showtooltip; + const int complexsoft = options.complexity; + + // Parameter Exposure specific widgets if (showtooltip) { exp->set_tooltip_text(M("TP_LOCALLAB_EXPOSURE_TOOLTIP")); } expMethod->append(M("TP_LOCALLAB_STD")); - expMethod->append(M("TP_LOCALLAB_PDE")); + + if (complexsoft == 1) { + expMethod->append(M("TP_LOCALLAB_PDE")); + } + expMethod->set_active(0); - expMethodConn = expMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabExposure::expMethodChanged)); + expMethodConn = expMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabExposure::expMethodChanged)); if (showtooltip) { expMethod->set_tooltip_text(M("TP_LOCALLAB_EXPMETHOD_TOOLTIP")); @@ -1069,94 +2132,335 @@ LocallabExposure::LocallabExposure(): pdeFrame->set_label_align(0.025, 0.5); + if (showtooltip) { + pdeFrame->set_tooltip_text(M("TP_LOCALLAB_PDEFRAME_TOOLTIP")); + } + laplacexp->setAdjusterListener(this); linear->setAdjusterListener(this); balanexp->setAdjusterListener(this); + gamm->setAdjusterListener(this); + + exnoiseMethod->append(M("TP_LOCALLAB_NONENOISE")); + exnoiseMethod->append(M("TP_LOCALLAB_MEDIAN")); + exnoiseMethod->append(M("TP_LOCALLAB_WEDIANHI")); + exnoiseMethod->set_active(0); + exnoiseMethodConn = exnoiseMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabExposure::exnoiseMethodChanged)); + + if (showtooltip) { + exnoiseMethod->set_tooltip_text(M("TP_LOCALLAB_EXPMETHOD_TOOLTIP")); + } + + fatFrame->set_label_align(0.025, 0.5); + + if (showtooltip) { + fatFrame->set_tooltip_text(M("TP_LOCALLAB_FATFRAME_TOOLTIP")); + } + + fatamount->setAdjusterListener(this); + + fatdetail->setAdjusterListener(this); + + fatlevel->setAdjusterListener(this); + + fatanchor->setAdjusterListener(this); + + sensiex->setAdjusterListener(this); + + if (showtooltip) { + sensiex->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); + } + + structexp->setAdjusterListener(this); + + blurexpde->setAdjusterListener(this); + + setExpandAlignProperties(exptoolexp, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + expcomp->setAdjusterListener(this); + black->setAdjusterListener(this); + hlcompr->setAdjusterListener(this); hlcomprthresh->setAdjusterListener(this); - black->setAdjusterListener(this); - shadex->setAdjusterListener(this); shcompr->setAdjusterListener(this); expchroma->setAdjusterListener(this); - if (showtooltip) { - warm->set_tooltip_text(M("TP_LOCALLAB_WARM_TOOLTIP")); - } - - warm->setAdjusterListener(this); - - if (showtooltip) { - sensiex->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); - } - - sensiex->setAdjusterListener(this); - - structexp->setAdjusterListener(this); - - blurexpde->setAdjusterListener(this); - - softradiusexp->setAdjusterListener(this); - curveEditorG->setCurveListener(this); - shapeexpos = static_cast(curveEditorG->addCurve(CT_Diagonal, "")); - shapeexpos->setResetCurve(DiagonalCurveType(LocallabParams::DEF_EXP_CURVE.at(0)), LocallabParams::DEF_EXP_CURVE); + shapeexpos->setResetCurve(DiagonalCurveType(defSpot.excurve.at(0)), defSpot.excurve); if (showtooltip) { shapeexpos->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_TONES_TOOLTIP")); } - std::vector mshapeexpos; - mshapeexpos.push_back(GradientMilestone(0., 0., 0., 0.)); - mshapeexpos.push_back(GradientMilestone(1., 1., 1., 1.)); - shapeexpos->setBottomBarBgGradient(mshapeexpos); - shapeexpos->setLeftBarBgGradient(mshapeexpos); + shapeexpos->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1}}); + shapeexpos->setLeftBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1}}); curveEditorG->curveListComplete(); + setExpandAlignProperties(expgradexp, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + strexp->setAdjusterListener(this); + + if (showtooltip) { + strexp->set_tooltip_text(M("TP_LOCALLAB_GRADGEN_TOOLTIP")); + } + + angexp->setAdjusterListener(this); + + if (showtooltip) { + angexp->set_tooltip_text(M("TP_LOCALLAB_GRADANG_TOOLTIP")); + } + + softradiusexp->setLogScale(10, -10); + softradiusexp->setAdjusterListener(this); + inversexConn = inversex->signal_toggled().connect(sigc::mem_fun(*this, &LocallabExposure::inversexChanged)); - pack_start(*expMethod); + setExpandAlignProperties(expmaskexp, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + if (showtooltip) { + expmaskexp->set_tooltip_markup(M("TP_LOCALLAB_MASK_TOOLTIP")); + } + + showmaskexpMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskexpMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showmaskexpMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); + showmaskexpMethod->append(M("TP_LOCALLAB_SHOWMASK")); + showmaskexpMethod->append(M("TP_LOCALLAB_SHOWSTRUCEX")); + showmaskexpMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); + showmaskexpMethod->set_active(0); + + if (showtooltip) { + showmaskexpMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmaskexpMethodConn = showmaskexpMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabExposure::showmaskexpMethodChanged)); + + showmaskexpMethodinv->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskexpMethodinv->append(M("TP_LOCALLAB_SHOWMASK")); + showmaskexpMethodinv->set_active(0); + + if (showtooltip) { + showmaskexpMethodinv->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmaskexpMethodConninv = showmaskexpMethodinv->signal_changed().connect(sigc::mem_fun(*this, &LocallabExposure::showmaskexpMethodChangedinv)); + + enaExpMaskConn = enaExpMask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabExposure::enaExpMaskChanged)); + + enaExpMaskaftConn = enaExpMaskaft->signal_toggled().connect(sigc::mem_fun(*this, &LocallabExposure::enaExpMaskaftChanged)); + + maskexpCurveEditorG->setCurveListener(this); + + CCmaskexpshape->setIdentityValue(0.); + CCmaskexpshape->setResetCurve(FlatCurveType(defSpot.CCmaskexpcurve.at(0)), defSpot.CCmaskexpcurve); + + if (showtooltip) { + CCmaskexpshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + CCmaskexpshape->setBottomBarColorProvider(this, 1); + + LLmaskexpshape->setIdentityValue(0.); + LLmaskexpshape->setResetCurve(FlatCurveType(defSpot.LLmaskexpcurve.at(0)), defSpot.LLmaskexpcurve); + + if (showtooltip) { + LLmaskexpshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + LLmaskexpshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1}}); + + HHmaskexpshape->setIdentityValue(0.); + HHmaskexpshape->setResetCurve(FlatCurveType(defSpot.HHmaskexpcurve.at(0)), defSpot.HHmaskexpcurve); + + if (showtooltip) { + HHmaskexpshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + HHmaskexpshape->setCurveColorProvider(this, 2); + HHmaskexpshape->setBottomBarColorProvider(this, 2); + + maskexpCurveEditorG->curveListComplete(); + + blendmaskexp->setAdjusterListener(this); + + radmaskexp->setLogScale(10, -10); + radmaskexp->setAdjusterListener(this); + + if (showtooltip) { + radmaskexp->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + lapmaskexp->setAdjusterListener(this); + + if (showtooltip) { + lapmaskexp->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + chromaskexp->setAdjusterListener(this); + + gammaskexp->setAdjusterListener(this); + + slomaskexp->setAdjusterListener(this); + + gradFramemask->set_label_align(0.025, 0.5); + + strmaskexp->setAdjusterListener(this); + + if (showtooltip) { + strmaskexp->set_tooltip_text(M("TP_LOCALLAB_GRADGEN_TOOLTIP")); + } + + angmaskexp->setAdjusterListener(this); + + if (showtooltip) { + angmaskexp->set_tooltip_text(M("TP_LOCALLAB_GRADANG_TOOLTIP")); + } + + mask2expCurveEditorG->setCurveListener(this); + + Lmaskexpshape->setResetCurve(DiagonalCurveType(defSpot.Lmaskexpcurve.at(0)), defSpot.Lmaskexpcurve); + + if (showtooltip) { + Lmaskexpshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + } + + Lmaskexpshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1}}); + Lmaskexpshape->setLeftBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1}}); + + mask2expCurveEditorG->curveListComplete(); + + // Add Color & Light specific widgets to GUI + if (complexsoft < 2) { + pack_start(*expMethod); + } + ToolParamBlock* const pdeBox = Gtk::manage(new ToolParamBlock()); pdeBox->pack_start(*laplacexp); pdeBox->pack_start(*linear); pdeBox->pack_start(*balanexp); + pdeBox->pack_start(*gamm); + Gtk::Label* const labelexpmethod = Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_NOISEMETH") + ":")); + ctboxexpmethod->pack_start(*labelexpmethod, Gtk::PACK_SHRINK, 4); + ctboxexpmethod->pack_start(*exnoiseMethod); + pdeBox->pack_start(*ctboxexpmethod); pdeFrame->add(*pdeBox); - pack_start(*pdeFrame); - pack_start(*expcomp); - pack_start(*hlcompr); - pack_start(*hlcomprthresh); - pack_start(*black); - pack_start(*shadex); - pack_start(*shcompr); - pack_start(*expchroma); - pack_start(*warm); + + if (complexsoft < 1) { + pack_start(*pdeFrame); + } + + ToolParamBlock* const fatBox = Gtk::manage(new ToolParamBlock()); + fatBox->pack_start(*fatamount); + fatBox->pack_start(*fatdetail); + + if (complexsoft < 2) { + fatBox->pack_start(*fatlevel); + } + + fatBox->pack_start(*fatanchor); + fatFrame->add(*fatBox); + pack_start(*fatFrame); pack_start(*sensiex); pack_start(*structexp); - pack_start(*blurexpde); - pack_start(*softradiusexp); - pack_start(*curveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor - pack_start(*inversex); + + if (complexsoft < 2) { + pack_start(*blurexpde); + } + + ToolParamBlock* const toolBox = Gtk::manage(new ToolParamBlock()); + toolBox->pack_start(*expcomp); + toolBox->pack_start(*black); + + if (complexsoft < 2) { + toolBox->pack_start(*hlcompr); + toolBox->pack_start(*hlcomprthresh); + toolBox->pack_start(*shadex); + toolBox->pack_start(*shcompr); + toolBox->pack_start(*expchroma); + } + + toolBox->pack_start(*curveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + exptoolexp->add(*toolBox, false); + pack_start(*exptoolexp); + ToolParamBlock* const gradBox = Gtk::manage(new ToolParamBlock()); + gradBox->pack_start(*strexp); + gradBox->pack_start(*angexp); + expgradexp->add(*gradBox, false); + pack_start(*expgradexp); + + if (complexsoft < 2) { + pack_start(*softradiusexp); + pack_start(*inversex); + } + + ToolParamBlock* const maskexpBox = Gtk::manage(new ToolParamBlock()); + maskexpBox->pack_start(*showmaskexpMethod, Gtk::PACK_SHRINK, 4); + maskexpBox->pack_start(*showmaskexpMethodinv, Gtk::PACK_SHRINK, 4); + maskexpBox->pack_start(*enaExpMask, Gtk::PACK_SHRINK, 0); + // maskexpBox->pack_start(*enaExpMaskaft, Gtk::PACK_SHRINK, 0); + maskexpBox->pack_start(*maskexpCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + maskexpBox->pack_start(*blendmaskexp, Gtk::PACK_SHRINK, 0); + maskexpBox->pack_start(*radmaskexp, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 1) { + maskexpBox->pack_start(*lapmaskexp, Gtk::PACK_SHRINK, 0); + } + + maskexpBox->pack_start(*chromaskexp, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 2) { + maskexpBox->pack_start(*gammaskexp, Gtk::PACK_SHRINK, 0); + maskexpBox->pack_start(*slomaskexp, Gtk::PACK_SHRINK, 0); + } + + ToolParamBlock* const gradmaskBox = Gtk::manage(new ToolParamBlock()); + gradmaskBox->pack_start(*strmaskexp); + gradmaskBox->pack_start(*angmaskexp); + gradFramemask->add(*gradmaskBox); + + if (complexsoft < 2) { + maskexpBox->pack_start(*gradFramemask); + } + + maskexpBox->pack_start(*mask2expCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + expmaskexp->add(*maskexpBox, false); + pack_start(*expmaskexp, false, false); } LocallabExposure::~LocallabExposure() { delete curveEditorG; + delete maskexpCurveEditorG; + delete mask2expCurveEditorG; } -void LocallabExposure::getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask) +void LocallabExposure::resetMaskView() { - expMask = showMaskMethod->get_active_row_number(); + showmaskexpMethodConn.block(true); + showmaskexpMethodConninv.block(true); + + showmaskexpMethod->set_active(0); + showmaskexpMethodinv->set_active(0); + + showmaskexpMethodConn.block(false); + showmaskexpMethodConninv.block(false); +} + +void LocallabExposure::getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask) +{ + expMask = showmaskexpMethod->get_active_row_number(); + expMaskinv = showmaskexpMethodinv->get_active_row_number(); } void LocallabExposure::disableListener() @@ -1164,7 +2468,12 @@ void LocallabExposure::disableListener() LocallabTool::disableListener(); expMethodConn.block(true); + exnoiseMethodConn.block(true); inversexConn.block(true); + showmaskexpMethodConn.block(true); + showmaskexpMethodConninv.block(true); + enaExpMaskConn.block(true); + enaExpMaskaftConn.block(true); } void LocallabExposure::enableListener() @@ -1172,11 +2481,18 @@ void LocallabExposure::enableListener() LocallabTool::enableListener(); expMethodConn.block(false); + exnoiseMethodConn.block(false); inversexConn.block(false); + showmaskexpMethodConn.block(false); + showmaskexpMethodConninv.block(false); + enaExpMaskConn.block(false); + enaExpMaskaftConn.block(false); } void LocallabExposure::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { + const int complexsoft = options.complexity; + // Disable all listeners disableListener(); @@ -1187,41 +2503,115 @@ void LocallabExposure::read(const rtengine::procparams::ProcParams* pp, const Pa spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot exp->set_visible(pp->locallab.spots.at(index).visiexpose); - exp->setEnabled(pp->locallab.spots.at(index).expexpose); - if (pp->locallab.spots.at(index).expMethod == "std") { + if (complexsoft < 2) { + if (pp->locallab.spots.at(index).expMethod == "std") { + expMethod->set_active(0); + } else if (pp->locallab.spots.at(index).expMethod == "pde") { + expMethod->set_active(1); + } + } else { expMethod->set_active(0); - } else if (pp->locallab.spots.at(index).expMethod == "pde") { - expMethod->set_active(1); } - laplacexp->setValue(pp->locallab.spots.at(index).laplacexp); + if (complexsoft == 0) { + laplacexp->setValue(pp->locallab.spots.at(index).laplacexp); + } else { + laplacexp->setValue(0.); + } + linear->setValue(pp->locallab.spots.at(index).linear); balanexp->setValue(pp->locallab.spots.at(index).balanexp); - expcomp->setValue(pp->locallab.spots.at(index).expcomp); - hlcompr->setValue(pp->locallab.spots.at(index).hlcompr); - hlcomprthresh->setValue(pp->locallab.spots.at(index).hlcomprthresh); - black->setValue(pp->locallab.spots.at(index).black); - shadex->setValue(pp->locallab.spots.at(index).shadex); - shcompr->setValue(pp->locallab.spots.at(index).shcompr); - expchroma->setValue(pp->locallab.spots.at(index).expchroma); - warm->setValue(pp->locallab.spots.at(index).warm); + gamm->setValue(pp->locallab.spots.at(index).gamm); + + if (pp->locallab.spots.at(index).exnoiseMethod == "one") { + exnoiseMethod->set_active(0); + } else if (pp->locallab.spots.at(index).exnoiseMethod == "med") { + exnoiseMethod->set_active(1); + } else if (pp->locallab.spots.at(index).exnoiseMethod == "medhi") { + exnoiseMethod->set_active(2); + } + + fatamount->setValue(pp->locallab.spots.at(index).fatamount); + fatdetail->setValue(pp->locallab.spots.at(index).fatdetail); + + if (complexsoft == 0) { + fatlevel->setValue(pp->locallab.spots.at(index).fatlevel); + } else { + fatlevel->setValue(1.); + } + + fatanchor->setValue(pp->locallab.spots.at(index).fatanchor); sensiex->setValue(pp->locallab.spots.at(index).sensiex); - structexp->setValue(pp->locallab.spots.at(index).structexp); - blurexpde->setValue(pp->locallab.spots.at(index).blurexpde); + + if (complexsoft < 2) { + structexp->setValue(pp->locallab.spots.at(index).structexp); + blurexpde->setValue(pp->locallab.spots.at(index).blurexpde); + expcomp->setValue(pp->locallab.spots.at(index).expcomp); + } else { + structexp->setValue(0.); + blurexpde->setValue(5.); + expcomp->setValue(0.); + } + + black->setValue(pp->locallab.spots.at(index).black); + + if (complexsoft < 2) { + hlcompr->setValue(pp->locallab.spots.at(index).hlcompr); + hlcomprthresh->setValue(pp->locallab.spots.at(index).hlcomprthresh); + shadex->setValue(pp->locallab.spots.at(index).shadex); + shcompr->setValue(pp->locallab.spots.at(index).shcompr); + expchroma->setValue(pp->locallab.spots.at(index).expchroma); + } else { + hlcompr->setValue(0.); + hlcomprthresh->setValue(0.); + shadex->setValue(0.); + shcompr->setValue(0.); + expchroma->setValue(0.); + } + shapeexpos->setCurve(pp->locallab.spots.at(index).excurve); - softradiusexp->setValue(pp->locallab.spots.at(index).softradiusexp); - inversex->set_active(pp->locallab.spots.at(index).inversex); - enaMask->set_active(pp->locallab.spots.at(index).enaExpMask); - CCMaskShape->setCurve(pp->locallab.spots.at(index).CCmaskexpcurve); - LLMaskShape->setCurve(pp->locallab.spots.at(index).LLmaskexpcurve); - HHMaskShape->setCurve(pp->locallab.spots.at(index).HHmaskexpcurve); - blendMask->setValue(pp->locallab.spots.at(index).blendmaskexp); - radMask->setValue(pp->locallab.spots.at(index).radmaskexp); - chroMask->setValue(pp->locallab.spots.at(index).chromaskexp); - gamMask->setValue(pp->locallab.spots.at(index).gammaskexp); - sloMask->setValue(pp->locallab.spots.at(index).slomaskexp); + strexp->setValue(pp->locallab.spots.at(index).strexp); + angexp->setValue(pp->locallab.spots.at(index).angexp); + + if (complexsoft < 2) { + softradiusexp->setValue(pp->locallab.spots.at(index).softradiusexp); + inversex->set_active(pp->locallab.spots.at(index).inversex); + } else { + softradiusexp->setValue(0.); + inversex->set_active(false); + } + + enaExpMask->set_active(pp->locallab.spots.at(index).enaExpMask); + enaExpMaskaft->set_active(pp->locallab.spots.at(index).enaExpMaskaft); + CCmaskexpshape->setCurve(pp->locallab.spots.at(index).CCmaskexpcurve); + LLmaskexpshape->setCurve(pp->locallab.spots.at(index).LLmaskexpcurve); + HHmaskexpshape->setCurve(pp->locallab.spots.at(index).HHmaskexpcurve); + blendmaskexp->setValue(pp->locallab.spots.at(index).blendmaskexp); + radmaskexp->setValue(pp->locallab.spots.at(index).radmaskexp); + + if (complexsoft == 0) { + lapmaskexp->setValue(pp->locallab.spots.at(index).lapmaskexp); + } else { + lapmaskexp->setValue(0.); + } + + chromaskexp->setValue(pp->locallab.spots.at(index).chromaskexp); + + if (complexsoft < 2) { + gammaskexp->setValue(pp->locallab.spots.at(index).gammaskexp); + slomaskexp->setValue(pp->locallab.spots.at(index).slomaskexp); + strmaskexp->setValue(pp->locallab.spots.at(index).strmaskexp); + angmaskexp->setValue(pp->locallab.spots.at(index).angmaskexp); + } else { + gammaskexp->setValue(1.); + slomaskexp->setValue(0.); + strmaskexp->setValue(0.); + angmaskexp->setValue(0.); + } + + Lmaskexpshape->setCurve(pp->locallab.spots.at(index).Lmaskexpcurve); } // Enable all listeners @@ -1245,7 +2635,6 @@ void LocallabExposure::write(rtengine::procparams::ProcParams* pp, ParamsEdited* if (index < (int)pp->locallab.spots.size()) { pp->locallab.spots.at(index).expexpose = exp->getEnabled(); - pp->locallab.spots.at(index).visiexpose = exp->get_visible(); if (expMethod->get_active_row_number() == 0) { @@ -1257,29 +2646,49 @@ void LocallabExposure::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pp->locallab.spots.at(index).laplacexp = laplacexp->getValue(); pp->locallab.spots.at(index).linear = linear->getValue(); pp->locallab.spots.at(index).balanexp = balanexp->getValue(); - pp->locallab.spots.at(index).expcomp = expcomp->getValue(); - pp->locallab.spots.at(index).hlcompr = hlcompr->getIntValue(); - pp->locallab.spots.at(index).hlcomprthresh = hlcomprthresh->getIntValue(); - pp->locallab.spots.at(index).black = black->getIntValue(); - pp->locallab.spots.at(index).shadex = shadex->getIntValue(); - pp->locallab.spots.at(index).shcompr = shcompr->getIntValue(); - pp->locallab.spots.at(index).expchroma = expchroma->getIntValue(); - pp->locallab.spots.at(index).warm = warm->getIntValue(); + pp->locallab.spots.at(index).gamm = gamm->getValue(); + + if (exnoiseMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).exnoiseMethod = "none"; + } else if (exnoiseMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).exnoiseMethod = "med"; + } else if (exnoiseMethod->get_active_row_number() == 2) { + pp->locallab.spots.at(index).exnoiseMethod = "medhi"; + } + + pp->locallab.spots.at(index).fatamount = fatamount->getValue(); + pp->locallab.spots.at(index).fatdetail = fatdetail->getValue(); + pp->locallab.spots.at(index).fatlevel = fatlevel->getValue(); + pp->locallab.spots.at(index).fatanchor = fatanchor->getValue(); pp->locallab.spots.at(index).sensiex = sensiex->getIntValue(); pp->locallab.spots.at(index).structexp = structexp->getIntValue(); pp->locallab.spots.at(index).blurexpde = blurexpde->getIntValue(); - pp->locallab.spots.at(index).softradiusexp = softradiusexp->getValue(); + pp->locallab.spots.at(index).expcomp = expcomp->getValue(); + pp->locallab.spots.at(index).black = black->getIntValue(); + pp->locallab.spots.at(index).hlcompr = hlcompr->getIntValue(); + pp->locallab.spots.at(index).hlcomprthresh = hlcomprthresh->getIntValue(); + pp->locallab.spots.at(index).shadex = shadex->getIntValue(); + pp->locallab.spots.at(index).shcompr = shcompr->getIntValue(); + pp->locallab.spots.at(index).expchroma = expchroma->getIntValue(); pp->locallab.spots.at(index).excurve = shapeexpos->getCurve(); + pp->locallab.spots.at(index).strexp = strexp->getValue(); + pp->locallab.spots.at(index).angexp = angexp->getValue(); + pp->locallab.spots.at(index).softradiusexp = softradiusexp->getValue(); pp->locallab.spots.at(index).inversex = inversex->get_active(); - pp->locallab.spots.at(index).enaExpMask = enaMask->get_active(); - pp->locallab.spots.at(index).LLmaskexpcurve = LLMaskShape->getCurve(); - pp->locallab.spots.at(index).CCmaskexpcurve = CCMaskShape->getCurve(); - pp->locallab.spots.at(index).HHmaskexpcurve = HHMaskShape->getCurve(); - pp->locallab.spots.at(index).blendmaskexp = blendMask->getIntValue(); - pp->locallab.spots.at(index).radmaskexp = radMask->getValue(); - pp->locallab.spots.at(index).chromaskexp = chroMask->getValue(); - pp->locallab.spots.at(index).gammaskexp = gamMask->getValue(); - pp->locallab.spots.at(index).slomaskexp = sloMask->getValue(); + pp->locallab.spots.at(index).enaExpMask = enaExpMask->get_active(); + pp->locallab.spots.at(index).enaExpMaskaft = enaExpMaskaft->get_active(); + pp->locallab.spots.at(index).CCmaskexpcurve = CCmaskexpshape->getCurve(); + pp->locallab.spots.at(index).LLmaskexpcurve = LLmaskexpshape->getCurve(); + pp->locallab.spots.at(index).HHmaskexpcurve = HHmaskexpshape->getCurve(); + pp->locallab.spots.at(index).blendmaskexp = blendmaskexp->getIntValue(); + pp->locallab.spots.at(index).radmaskexp = radmaskexp->getValue(); + pp->locallab.spots.at(index).lapmaskexp = lapmaskexp->getValue(); + pp->locallab.spots.at(index).chromaskexp = chromaskexp->getValue(); + pp->locallab.spots.at(index).gammaskexp = gammaskexp->getValue(); + pp->locallab.spots.at(index).slomaskexp = slomaskexp->getValue(); + pp->locallab.spots.at(index).strmaskexp = strmaskexp->getValue(); + pp->locallab.spots.at(index).angmaskexp = angmaskexp->getValue(); + pp->locallab.spots.at(index).Lmaskexpcurve = Lmaskexpshape->getCurve(); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -1296,23 +2705,32 @@ void LocallabExposure::setDefaults(const rtengine::procparams::ProcParams* defPa laplacexp->setDefault(defSpot.laplacexp); linear->setDefault(defSpot.linear); balanexp->setDefault(defSpot.balanexp); - expcomp->setDefault(defSpot.expcomp); - hlcompr->setDefault((double)defSpot.hlcompr); - hlcomprthresh->setDefault((double)defSpot.hlcomprthresh); - black->setDefault((double)defSpot.black); - shadex->setDefault((double)defSpot.shadex); - shcompr->setDefault((double)defSpot.shcompr); - expchroma->setDefault((double)defSpot.expchroma); - warm->setDefault((double)defSpot.warm); + gamm->setDefault(defSpot.gamm); + fatamount->setDefault(defSpot.fatamount); + fatdetail->setDefault(defSpot.fatdetail); + fatlevel->setDefault(defSpot.fatlevel); + fatanchor->setDefault(defSpot.fatanchor); sensiex->setDefault((double)defSpot.sensiex); structexp->setDefault((double)defSpot.structexp); blurexpde->setDefault((double)defSpot.blurexpde); + expcomp->setDefault(defSpot.expcomp); + black->setDefault((double)defSpot.black); + hlcompr->setDefault((double)defSpot.hlcompr); + hlcomprthresh->setDefault((double)defSpot.hlcomprthresh); + shadex->setDefault((double)defSpot.shadex); + shcompr->setDefault((double)defSpot.shcompr); + expchroma->setDefault((double)defSpot.expchroma); + strexp->setDefault(defSpot.strexp); + angexp->setDefault(defSpot.angexp); softradiusexp->setDefault(defSpot.softradiusexp); - blendMask->setDefault((double)defSpot.blendmaskexp); - radMask->setDefault(defSpot.radmaskexp); - chroMask->setDefault(defSpot.chromaskexp); - gamMask->setDefault(defSpot.gammaskexp); - sloMask->setDefault(defSpot.slomaskexp); + blendmaskexp->setDefault((double)defSpot.blendmaskexp); + radmaskexp->setDefault(defSpot.radmaskexp); + lapmaskexp->setDefault(defSpot.lapmaskexp); + chromaskexp->setDefault(defSpot.chromaskexp); + gammaskexp->setDefault(defSpot.gammaskexp); + slomaskexp->setDefault(defSpot.slomaskexp); + strmaskexp->setDefault(defSpot.strmaskexp); + angmaskexp->setDefault(defSpot.angmaskexp); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -1347,59 +2765,38 @@ void LocallabExposure::adjusterChanged(Adjuster* a, double newval) } } - if (a == expcomp) { + if (a == gamm) { if (listener) { - listener->panelChanged(Evlocallabexpcomp, - expcomp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + listener->panelChanged(Evlocallabgamm, + gamm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == hlcompr) { + if (a == fatamount) { if (listener) { - listener->panelChanged(Evlocallabhlcompr, - hlcompr->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + listener->panelChanged(Evlocallabfatamount, + fatamount->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == hlcomprthresh) { + if (a == fatdetail) { if (listener) { - listener->panelChanged(Evlocallabhlcomprthresh, - hlcomprthresh->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + listener->panelChanged(Evlocallabfatdetail, + fatdetail->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == black) { + if (a == fatlevel) { if (listener) { - listener->panelChanged(Evlocallabblack, - black->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + listener->panelChanged(Evlocallabfatlevel, + fatlevel->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == shadex) { + if (a == fatanchor) { if (listener) { - listener->panelChanged(Evlocallabshadex, - shadex->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); - } - } - - if (a == shcompr) { - if (listener) { - listener->panelChanged(Evlocallabshcompr, - shcompr->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); - } - } - - if (a == expchroma) { - if (listener) { - listener->panelChanged(Evlocallabexpchroma, - expchroma->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); - } - } - - if (a == warm) { - if (listener) { - listener->panelChanged(Evlocallabwarm, - warm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + listener->panelChanged(Evlocallabfatanchor, + fatanchor->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } @@ -1424,6 +2821,69 @@ void LocallabExposure::adjusterChanged(Adjuster* a, double newval) } } + if (a == expcomp) { + if (listener) { + listener->panelChanged(Evlocallabexpcomp, + expcomp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == black) { + if (listener) { + listener->panelChanged(Evlocallabblack, + black->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == hlcompr) { + if (listener) { + listener->panelChanged(Evlocallabhlcompr, + hlcompr->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == hlcomprthresh) { + if (listener) { + listener->panelChanged(Evlocallabhlcomprthresh, + hlcomprthresh->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == shadex) { + if (listener) { + listener->panelChanged(Evlocallabshadex, + shadex->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == shcompr) { + if (listener) { + listener->panelChanged(Evlocallabshcompr, + shcompr->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == expchroma) { + if (listener) { + listener->panelChanged(Evlocallabexpchroma, + expchroma->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strexp) { + if (listener) { + listener->panelChanged(Evlocallabstrexp, + strexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == angexp) { + if (listener) { + listener->panelChanged(Evlocallabangexp, + angexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + if (a == softradiusexp) { if (listener) { listener->panelChanged(Evlocallabsoftradiusexp, @@ -1431,38 +2891,59 @@ void LocallabExposure::adjusterChanged(Adjuster* a, double newval) } } - if (a == blendMask) { + if (a == blendmaskexp) { if (listener) { listener->panelChanged(Evlocallabblendmaskexp, - blendMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + blendmaskexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == radMask) { + if (a == radmaskexp) { if (listener) { listener->panelChanged(Evlocallabradmaskexp, - radMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + radmaskexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == chroMask) { + if (a == lapmaskexp) { + if (listener) { + listener->panelChanged(Evlocallablapmaskexp, + lapmaskexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chromaskexp) { if (listener) { listener->panelChanged(Evlocallabchromaskexp, - chroMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + chromaskexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == gamMask) { + if (a == gammaskexp) { if (listener) { listener->panelChanged(Evlocallabgammaskexp, - gamMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + gammaskexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == sloMask) { + if (a == slomaskexp) { if (listener) { listener->panelChanged(Evlocallabslomaskexp, - sloMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + slomaskexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strmaskexp) { + if (listener) { + listener->panelChanged(Evlocallabstrmaskexp, + strmaskexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == angmaskexp) { + if (listener) { + listener->panelChanged(Evlocallabangmaskexp, + angmaskexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } } @@ -1478,26 +2959,33 @@ void LocallabExposure::curveChanged(CurveEditor* ce) } } - if (ce == CCMaskShape) { + if (ce == CCmaskexpshape) { if (listener) { listener->panelChanged(EvlocallabCCmaskexpshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } - if (ce == LLMaskShape) { + if (ce == LLmaskexpshape) { if (listener) { listener->panelChanged(EvlocallabLLmaskexpshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } - if (ce == HHMaskShape) { + if (ce == HHmaskexpshape) { if (listener) { listener->panelChanged(EvlocallabHHmaskexpshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } + + if (ce == Lmaskexpshape) { + if (listener) { + listener->panelChanged(EvlocallabLmaskexpshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } } } @@ -1516,31 +3004,21 @@ void LocallabExposure::enabledChanged() } } -void LocallabExposure::enaMaskChanged() -{ - if (isLocActivated && exp->getEnabled()) { - if (listener) { - if (enaMask->get_active()) { - listener->panelChanged(EvLocallabEnaExpMask, - M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); - } else { - listener->panelChanged(EvLocallabEnaExpMask, - M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); - } - } - } -} -void LocallabExposure::showMaskMethodChanged() +void LocallabExposure::updateMaskBackground(const double normChromar, const double normLumar, const double normHuer) { - // If mask preview is activated, deactivate all other tool mask preview - if (locToolListener) { - locToolListener->resetOtherMaskView(this); - } + idle_register.add( + [this, normHuer, normLumar, normChromar]() -> bool { + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected - if (listener) { - listener->panelChanged(EvlocallabshowmaskMethod, ""); + // Update mask background + CCmaskexpshape->updateLocallabBackground(normChromar); + LLmaskexpshape->updateLocallabBackground(normLumar); + HHmaskexpshape->updateLocallabBackground(normHuer); + + return false; } + ); } void LocallabExposure::expMethodChanged() @@ -1556,6 +3034,16 @@ void LocallabExposure::expMethodChanged() } } +void LocallabExposure::exnoiseMethodChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabexnoiseMethod, + exnoiseMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + void LocallabExposure::inversexChanged() { // Update exposure GUI according to inversex button state @@ -1574,6 +3062,70 @@ void LocallabExposure::inversexChanged() } } +void LocallabExposure::showmaskexpMethodChanged() +{ + // If mask preview is activated, deactivate other Exposure mask preview + showmaskexpMethodConninv.block(true); + showmaskexpMethodinv->set_active(0); + showmaskexpMethodConninv.block(false); + + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskMethod, ""); + } +} + +void LocallabExposure::showmaskexpMethodChangedinv() +{ + // If mask preview is activated, deactivate other Exposure mask preview + showmaskexpMethodConn.block(true); + showmaskexpMethod->set_active(0); + showmaskexpMethodConn.block(false); + + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskMethod, ""); + } +} + +void LocallabExposure::enaExpMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enaExpMask->get_active()) { + listener->panelChanged(EvLocallabEnaExpMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnaExpMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabExposure::enaExpMaskaftChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enaExpMaskaft->get_active()) { + listener->panelChanged(EvLocallabEnaExpMaskaft, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnaExpMaskaft, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + void LocallabExposure::updateExposureGUI1() { // Update shcompr sensitivity according to black and shadex value @@ -1590,13 +3142,27 @@ void LocallabExposure::updateExposureGUI2() if (expMethod->get_active_row_number() == 0) { pdeFrame->set_sensitive(false); laplacexp->set_sensitive(false); - balanexp->set_sensitive(false); linear->set_sensitive(false); + balanexp->set_sensitive(false); + gamm->set_sensitive(false); + fatFrame->set_sensitive(false); + fatamount->set_sensitive(false); + fatdetail->set_sensitive(false); + fatlevel->set_sensitive(false); + fatanchor->set_sensitive(false); + softradiusexp->set_sensitive(true); } else if (expMethod->get_active_row_number() == 1) { pdeFrame->set_sensitive(true); laplacexp->set_sensitive(true); - balanexp->set_sensitive(true); linear->set_sensitive(true); + balanexp->set_sensitive(true); + gamm->set_sensitive(true); + fatFrame->set_sensitive(true); + fatamount->set_sensitive(true); + fatdetail->set_sensitive(true); + fatlevel->set_sensitive(true); + fatanchor->set_sensitive(true); + softradiusexp->set_sensitive(false); } } @@ -1604,27 +3170,65 @@ void LocallabExposure::updateExposureGUI3() { // Update exposure GUI according to inversex button state if (inversex->get_active()) { - maskExp->hide(); - structexp->hide(); - softradiusexp->hide(); - shadex->hide(); expMethod->hide(); + + // Manage specific case where expMethod is different from 0 + if (expMethod > 0) { + expMethodConn.block(true); + expMethod->set_active(0); + expMethodConn.block(false); + + // Update GUI accordingly + updateExposureGUI2(); + } + pdeFrame->hide(); + fatFrame->hide(); + structexp->hide(); + shadex->hide(); + softradiusexp->hide(); + expgradexp->hide(); + showmaskexpMethod->hide(); // TODO Manage cases where avoid is activated with mask on + showmaskexpMethodinv->show(); } else { - maskExp->show(); - structexp->show(); - softradiusexp->show(); - shadex->show(); expMethod->show(); pdeFrame->show(); + fatFrame->show(); + structexp->show(); + shadex->show(); + softradiusexp->show(); + expgradexp->show(); + showmaskexpMethodinv->show(); + showmaskexpMethod->hide(); } } /* ==== LocallabShadow ==== */ LocallabShadow::LocallabShadow(): - LocallabTool(this, M("TP_LOCALLAB_SH_TOOLNAME"), M("TP_LOCALLAB_SHADHIGH"), false, MaskNormal), + LocallabTool(this, M("TP_LOCALLAB_SH_TOOLNAME"), M("TP_LOCALLAB_SHADHIGH"), false), // Shadow highlight specific widgets + shMethod(Gtk::manage(new MyComboBoxText())), + multipliersh([this]() -> std::array + { + std::array res = {}; + + for (unsigned int i = 0; i < res.size(); ++i) { + Glib::ustring ss = Glib::ustring::format(i); + + if (i == 0) { + ss += Glib::ustring::compose(" (%1)", M("TP_LOCALLAB_LUMADARKEST")); + } else if (i == 4) { + ss += Glib::ustring::compose(" (%1)", M("TP_LOCALLAB_LUMAWHITESEST")); + } + + res[i] = Gtk::manage(new Adjuster(std::move(ss), -100, 100, 1, 0)); + } + + return res; + } + ()), + detailSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DETAILSH"), -5, 5, 1, 0))), highlights(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_HIGHLIGHTS"), 0, 100, 1, 0))), h_tonalwidth(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_HLTONALW"), 10, 100, 1, 70))), shadows(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_SHADOWS"), 0, 100, 1, 0))), @@ -1632,14 +3236,54 @@ LocallabShadow::LocallabShadow(): sh_radius(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_RADIUS"), 0, 100, 1, 40))), sensihs(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))), blurSHde(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURDE"), 2, 100, 1, 5))), - inverssh(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))) + gamFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_GAMFRA")))), + gamSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMSH"), 0.25, 15.0, 0.01, 2.4))), + sloSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOSH"), 0.0, 150.0, 0.01, 12.92))), + expgradsh(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_EXPGRAD")))), + strSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -4., 4., 0.05, 0.))), + angSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))), + inverssh(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))), + expmasksh(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWS")))), + showmaskSHMethod(Gtk::manage(new MyComboBoxText())), + showmaskSHMethodinv(Gtk::manage(new MyComboBoxText())), + enaSHMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), + maskSHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), + CCmaskSHshape(static_cast(maskSHCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false))), + LLmaskSHshape(static_cast(maskSHCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false))), + HHmaskSHshape(static_cast(maskSHCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true))), + blendmaskSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), + radmaskSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), -10.0, 1000.0, 0.1, 0.))), + lapmaskSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPMASKCOL"), 0.0, 100.0, 0.1, 0.))), + chromaskSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), + gammaskSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.25, 4.0, 0.01, 1.))), + slomaskSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), + mask2SHCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), + LmaskSHshape(static_cast(mask2SHCurveEditorG->addCurve(CT_Diagonal, "L(L)"))), + fatSHFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_FATSHFRA")))), + fatamountSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATAMOUNT"), 1., 100., 1., 1.))), + fatanchorSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATANCHOR"), 1., 100., 1., 50., Gtk::manage(new RTImage("circle-black-small.png")), Gtk::manage(new RTImage("circle-white-small.png"))))) { - const bool showtooltip = options.showtooltip; + const LocallabParams::LocallabSpot defSpot; + const bool showtooltip = options.showtooltip; + const int complexsoft = options.complexity; + + // Parameter Shadow highlight specific widgets if (showtooltip) { exp->set_tooltip_text(M("TP_LOCALLAB_SHADOWHIGHLIGHT_TOOLTIP")); } + shMethod->append(M("TP_LOCALLAB_SH1")); + shMethod->append(M("TP_LOCALLAB_SH2")); + shMethod->set_active(0); + shMethodConn = shMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabShadow::shMethodChanged)); + + for (unsigned int i = 0; i < multipliersh.size(); i++) { + multipliersh[i]->setAdjusterListener(this); + } + + detailSH->setAdjusterListener(this); + highlights->setAdjusterListener(this); h_tonalwidth->setAdjusterListener(this); @@ -1654,39 +3298,247 @@ LocallabShadow::LocallabShadow(): blurSHde->setAdjusterListener(this); - inversshConn = inverssh->signal_toggled().connect(sigc::mem_fun(*this, &LocallabShadow::inversshChanged)); + gamFrame->set_label_align(0.025, 0.5); + gamSH->setAdjusterListener(this); + + sloSH->setAdjusterListener(this); + + setExpandAlignProperties(expgradsh, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + strSH->setAdjusterListener(this); + + if (showtooltip) { + strSH->set_tooltip_text(M("TP_LOCALLAB_GRADGEN_TOOLTIP")); + } + + angSH->setAdjusterListener(this); + + if (showtooltip) { + angSH->set_tooltip_text(M("TP_LOCALLAB_GRADANG_TOOLTIP")); + } + + inversshConn = inverssh->signal_toggled().connect(sigc::mem_fun(*this, &LocallabShadow::inversshChanged)); + + setExpandAlignProperties(expmasksh, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + if (showtooltip) { + expmasksh->set_tooltip_markup(M("TP_LOCALLAB_MASK_TOOLTIP")); + } + + showmaskSHMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskSHMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showmaskSHMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); + showmaskSHMethod->append(M("TP_LOCALLAB_SHOWMASK")); + showmaskSHMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); + showmaskSHMethod->set_active(0); + + if (showtooltip) { + showmaskSHMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmaskSHMethodConn = showmaskSHMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabShadow::showmaskSHMethodChanged)); + + showmaskSHMethodinv->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskSHMethodinv->append(M("TP_LOCALLAB_SHOWMASK")); + + showmaskSHMethodinv->set_active(0); + + if (showtooltip) { + showmaskSHMethodinv->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmaskSHMethodConninv = showmaskSHMethodinv->signal_changed().connect(sigc::mem_fun(*this, &LocallabShadow::showmaskSHMethodChangedinv)); + + enaSHMaskConn = enaSHMask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabShadow::enaSHMaskChanged)); + + maskSHCurveEditorG->setCurveListener(this); + + CCmaskSHshape->setIdentityValue(0.); + CCmaskSHshape->setResetCurve(FlatCurveType(defSpot.CCmaskSHcurve.at(0)), defSpot.CCmaskSHcurve); + + if (showtooltip) { + CCmaskSHshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + CCmaskSHshape->setBottomBarColorProvider(this, 1); + + LLmaskSHshape->setIdentityValue(0.); + LLmaskSHshape->setResetCurve(FlatCurveType(defSpot.LLmaskSHcurve.at(0)), defSpot.LLmaskSHcurve); + + if (showtooltip) { + LLmaskSHshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + LLmaskSHshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + HHmaskSHshape->setIdentityValue(0.); + HHmaskSHshape->setResetCurve(FlatCurveType(defSpot.HHmaskSHcurve.at(0)), defSpot.HHmaskSHcurve); + + if (showtooltip) { + HHmaskSHshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + HHmaskSHshape->setCurveColorProvider(this, 2); + HHmaskSHshape->setBottomBarColorProvider(this, 2); + + maskSHCurveEditorG->curveListComplete(); + + blendmaskSH->setAdjusterListener(this); + + radmaskSH->setLogScale(10, -10); + radmaskSH->setAdjusterListener(this); + + if (showtooltip) { + radmaskSH->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + lapmaskSH->setAdjusterListener(this); + + if (showtooltip) { + lapmaskSH->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + chromaskSH->setAdjusterListener(this); + + gammaskSH->setAdjusterListener(this); + + slomaskSH->setAdjusterListener(this); + + mask2SHCurveEditorG->setCurveListener(this); + + LmaskSHshape->setResetCurve(DiagonalCurveType(defSpot.LmaskSHcurve.at(0)), defSpot.LmaskSHcurve); + + if (showtooltip) { + LmaskSHshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + } + + LmaskSHshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + LmaskSHshape->setLeftBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + mask2SHCurveEditorG->curveListComplete(); + + fatSHFrame->set_label_align(0.025, 0.5); + + fatamountSH->setAdjusterListener(this); + + fatanchorSH->setAdjusterListener(this); + + // Add Shadow highlight specific widgets to GUI + if (complexsoft < 2) { + pack_start(*shMethod); + } + + for (int i = 0; i < 5; ++i) { + pack_start(*multipliersh[i]); + } + + pack_start(*detailSH); pack_start(*highlights); pack_start(*h_tonalwidth); pack_start(*shadows); pack_start(*s_tonalwidth); pack_start(*sh_radius); pack_start(*sensihs); - pack_start(*blurSHde); + + if (complexsoft < 2) { + pack_start(*blurSHde); + } + + ToolParamBlock* const gammBox = Gtk::manage(new ToolParamBlock()); + gammBox->pack_start(*gamSH); + gammBox->pack_start(*sloSH); + gamFrame->add(*gammBox); + pack_start(*gamFrame); + ToolParamBlock* const gradSHBox = Gtk::manage(new ToolParamBlock()); + gradSHBox->pack_start(*strSH); + gradSHBox->pack_start(*angSH); + expgradsh->add(*gradSHBox, false); + pack_start(*expgradsh); pack_start(*inverssh); + ToolParamBlock* const maskSHBox = Gtk::manage(new ToolParamBlock()); + maskSHBox->pack_start(*showmaskSHMethod, Gtk::PACK_SHRINK, 4); + maskSHBox->pack_start(*showmaskSHMethodinv, Gtk::PACK_SHRINK, 4); + maskSHBox->pack_start(*enaSHMask, Gtk::PACK_SHRINK, 0); + maskSHBox->pack_start(*maskSHCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + maskSHBox->pack_start(*blendmaskSH, Gtk::PACK_SHRINK, 0); + maskSHBox->pack_start(*radmaskSH, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 1) { + maskSHBox->pack_start(*lapmaskSH, Gtk::PACK_SHRINK, 0); + } + + maskSHBox->pack_start(*chromaskSH, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 2) { + maskSHBox->pack_start(*gammaskSH, Gtk::PACK_SHRINK, 0); + maskSHBox->pack_start(*slomaskSH, Gtk::PACK_SHRINK, 0); + } + + maskSHBox->pack_start(*mask2SHCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + ToolParamBlock* const fatSHBox = Gtk::manage(new ToolParamBlock()); + fatSHBox->pack_start(*fatamountSH); + fatSHBox->pack_start(*fatanchorSH); + fatSHFrame->add(*fatSHBox); + + if (complexsoft < 1) { + maskSHBox->pack_start(*fatSHFrame); + } + + expmasksh->add(*maskSHBox, false); + pack_start(*expmasksh, false, false); } -void LocallabShadow::getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask) +LocallabShadow::~LocallabShadow() { - shMask = showMaskMethod->get_active_row_number(); + delete maskSHCurveEditorG; + delete mask2SHCurveEditorG; +} + +void LocallabShadow::resetMaskView() +{ + showmaskSHMethodConn.block(true); + showmaskSHMethodConninv.block(true); + + showmaskSHMethod->set_active(0); + showmaskSHMethodinv->set_active(0); + + showmaskSHMethodConn.block(false); + showmaskSHMethodConninv.block(false); +} + +void LocallabShadow::getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask) +{ + shMask = showmaskSHMethod->get_active_row_number(); + shMaskinv = showmaskSHMethodinv->get_active_row_number(); } void LocallabShadow::disableListener() { LocallabTool::disableListener(); + shMethodConn.block(true); inversshConn.block(true); + showmaskSHMethodConn.block(true); + showmaskSHMethodConninv.block(true); + enaSHMaskConn.block(true); } void LocallabShadow::enableListener() { LocallabTool::enableListener(); - inversshConn.block(true); + shMethodConn.block(false); + inversshConn.block(false); + showmaskSHMethodConn.block(false); + showmaskSHMethodConninv.block(false); + enaSHMaskConn.block(false); } void LocallabShadow::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { + const int complexsoft = options.complexity; + // Disable all listeners disableListener(); @@ -1697,32 +3549,83 @@ void LocallabShadow::read(const rtengine::procparams::ProcParams* pp, const Para spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot exp->set_visible(pp->locallab.spots.at(index).visishadhigh); - exp->setEnabled(pp->locallab.spots.at(index).expshadhigh); - highlights->setValue(pp->locallab.spots.at(index).highlights); - h_tonalwidth->setValue(pp->locallab.spots.at(index).h_tonalwidth); - shadows->setValue(pp->locallab.spots.at(index).shadows); - s_tonalwidth->setValue(pp->locallab.spots.at(index).s_tonalwidth); - sh_radius->setValue(pp->locallab.spots.at(index).sh_radius); - sensihs->setValue(pp->locallab.spots.at(index).sensihs); - blurSHde->setValue(pp->locallab.spots.at(index).blurSHde); + + if (complexsoft < 2) { + if (pp->locallab.spots.at(index).shMethod == "std") { + shMethod->set_active(0); + } else if (pp->locallab.spots.at(index).shMethod == "tone") { + shMethod->set_active(1); + } + } else { + shMethod->set_active(1); + } + + for (int i = 0; i < 5; i++) { + multipliersh[i]->setValue((double)pp->locallab.spots.at(index).multsh[i]); + } + + detailSH->setValue((double)pp->locallab.spots.at(index).detailSH); + + if (complexsoft < 2) { + highlights->setValue((double)pp->locallab.spots.at(index).highlights); + } else { + highlights->setValue(0.); + } + + h_tonalwidth->setValue((double)pp->locallab.spots.at(index).h_tonalwidth); + + if (complexsoft < 2) { + shadows->setValue(pp->locallab.spots.at(index).shadows); + } else { + shadows->setValue(0.); + } + + s_tonalwidth->setValue((double)pp->locallab.spots.at(index).s_tonalwidth); + sh_radius->setValue((double)pp->locallab.spots.at(index).sh_radius); + sensihs->setValue((double)pp->locallab.spots.at(index).sensihs); + blurSHde->setValue((double)pp->locallab.spots.at(index).blurSHde); + gamSH->setValue(pp->locallab.spots.at(index).gamSH); + sloSH->setValue(pp->locallab.spots.at(index).sloSH); + strSH->setValue(pp->locallab.spots.at(index).strSH); + angSH->setValue(pp->locallab.spots.at(index).angSH); inverssh->set_active(pp->locallab.spots.at(index).inverssh); - enaMask->set_active(pp->locallab.spots.at(index).enaSHMask); - CCMaskShape->setCurve(pp->locallab.spots.at(index).CCmaskSHcurve); - LLMaskShape->setCurve(pp->locallab.spots.at(index).LLmaskSHcurve); - HHMaskShape->setCurve(pp->locallab.spots.at(index).HHmaskSHcurve); - blendMask->setValue(pp->locallab.spots.at(index).blendmaskSH); - radMask->setValue(pp->locallab.spots.at(index).radmaskSH); - chroMask->setValue(pp->locallab.spots.at(index).chromaskSH); - gamMask->setValue(pp->locallab.spots.at(index).gammaskSH); - sloMask->setValue(pp->locallab.spots.at(index).slomaskSH); + enaSHMask->set_active(pp->locallab.spots.at(index).enaSHMask); + CCmaskSHshape->setCurve(pp->locallab.spots.at(index).CCmaskSHcurve); + LLmaskSHshape->setCurve(pp->locallab.spots.at(index).LLmaskSHcurve); + HHmaskSHshape->setCurve(pp->locallab.spots.at(index).HHmaskSHcurve); + blendmaskSH->setValue((double)pp->locallab.spots.at(index).blendmaskSH); + radmaskSH->setValue(pp->locallab.spots.at(index).radmaskSH); + + if (complexsoft == 0) { + lapmaskSH->setValue(pp->locallab.spots.at(index).lapmaskSH); + } else { + lapmaskSH->setValue(0.); + } + + chromaskSH->setValue(pp->locallab.spots.at(index).chromaskSH); + + if (complexsoft < 2) { + gammaskSH->setValue(pp->locallab.spots.at(index).gammaskSH); + slomaskSH->setValue(pp->locallab.spots.at(index).slomaskSH); + } else { + gammaskSH->setValue(1.); + slomaskSH->setValue(0.); + } + + LmaskSHshape->setCurve(pp->locallab.spots.at(index).LmaskSHcurve); + fatamountSH->setValue(pp->locallab.spots.at(index).fatamountSH); + fatanchorSH->setValue(pp->locallab.spots.at(index).fatanchorSH); } // Enable all listeners enableListener(); // Update shadow highlight GUI according to inverssh button state - updateShadowGUI(); + updateShadowGUI1(); + + // Update shadow highlight GUI according to shMethod combobox state + updateShadowGUI2(); // Note: No need to manage pedited as batch mode is deactivated for Locallab } @@ -1733,9 +3636,19 @@ void LocallabShadow::write(rtengine::procparams::ProcParams* pp, ParamsEdited* p if (index < (int)pp->locallab.spots.size()) { pp->locallab.spots.at(index).expshadhigh = exp->getEnabled(); - pp->locallab.spots.at(index).visishadhigh = exp->get_visible(); + if (shMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).shMethod = "std"; + } else if (shMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).shMethod = "tone"; + } + + for (int i = 0; i < 5; i++) { + pp->locallab.spots.at(index).multsh[i] = multipliersh[i]->getIntValue(); + } + + pp->locallab.spots.at(index).detailSH = detailSH->getIntValue(); pp->locallab.spots.at(index).highlights = highlights->getIntValue(); pp->locallab.spots.at(index).h_tonalwidth = h_tonalwidth->getIntValue(); pp->locallab.spots.at(index).shadows = shadows->getIntValue(); @@ -1743,16 +3656,24 @@ void LocallabShadow::write(rtengine::procparams::ProcParams* pp, ParamsEdited* p pp->locallab.spots.at(index).sh_radius = sh_radius->getIntValue(); pp->locallab.spots.at(index).sensihs = sensihs->getIntValue(); pp->locallab.spots.at(index).blurSHde = blurSHde->getIntValue(); + pp->locallab.spots.at(index).gamSH = gamSH->getValue(); + pp->locallab.spots.at(index).sloSH = sloSH->getValue(); + pp->locallab.spots.at(index).strSH = strSH->getValue(); + pp->locallab.spots.at(index).angSH = angSH->getValue(); pp->locallab.spots.at(index).inverssh = inverssh->get_active(); - pp->locallab.spots.at(index).enaSHMask = enaMask->get_active(); - pp->locallab.spots.at(index).LLmaskSHcurve = LLMaskShape->getCurve(); - pp->locallab.spots.at(index).CCmaskSHcurve = CCMaskShape->getCurve(); - pp->locallab.spots.at(index).HHmaskSHcurve = HHMaskShape->getCurve(); - pp->locallab.spots.at(index).blendmaskSH = blendMask->getIntValue(); - pp->locallab.spots.at(index).radmaskSH = radMask->getValue(); - pp->locallab.spots.at(index).chromaskSH = chroMask->getValue(); - pp->locallab.spots.at(index).gammaskSH = gamMask->getValue(); - pp->locallab.spots.at(index).slomaskSH = sloMask->getValue(); + pp->locallab.spots.at(index).enaSHMask = enaSHMask->get_active(); + pp->locallab.spots.at(index).LLmaskSHcurve = LLmaskSHshape->getCurve(); + pp->locallab.spots.at(index).CCmaskSHcurve = CCmaskSHshape->getCurve(); + pp->locallab.spots.at(index).HHmaskSHcurve = HHmaskSHshape->getCurve(); + pp->locallab.spots.at(index).blendmaskSH = blendmaskSH->getIntValue(); + pp->locallab.spots.at(index).radmaskSH = radmaskSH->getValue(); + pp->locallab.spots.at(index).lapmaskSH = lapmaskSH->getValue(); + pp->locallab.spots.at(index).chromaskSH = chromaskSH->getValue(); + pp->locallab.spots.at(index).gammaskSH = gammaskSH->getValue(); + pp->locallab.spots.at(index).slomaskSH = slomaskSH->getValue(); + pp->locallab.spots.at(index).LmaskSHcurve = LmaskSHshape->getCurve(); + pp->locallab.spots.at(index).fatamountSH = fatamountSH->getValue(); + pp->locallab.spots.at(index).fatanchorSH = fatanchorSH->getValue(); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -1766,6 +3687,11 @@ void LocallabShadow::setDefaults(const rtengine::procparams::ProcParams* defPara const LocallabParams::LocallabSpot defSpot = defParams->locallab.spots.at(index); // Set default values for adjuster widgets + for (int i = 0; i < 5; i++) { + multipliersh[i]->setDefault(defSpot.multsh[i]); + } + + detailSH->setDefault((double)defSpot.detailSH); highlights->setDefault((double)defSpot.highlights); h_tonalwidth->setDefault((double)defSpot.h_tonalwidth); shadows->setDefault((double)defSpot.shadows); @@ -1773,11 +3699,18 @@ void LocallabShadow::setDefaults(const rtengine::procparams::ProcParams* defPara sh_radius->setDefault((double)defSpot.sh_radius); sensihs->setDefault((double)defSpot.sensihs); blurSHde->setDefault((double)defSpot.blurSHde); - blendMask->setDefault((double)defSpot.blendmaskSH); - radMask->setDefault(defSpot.radmaskSH); - chroMask->setDefault(defSpot.chromaskSH); - gamMask->setDefault(defSpot.gammaskSH); - sloMask->setDefault(defSpot.slomaskSH); + gamSH->setDefault(defSpot.gamSH); + sloSH->setDefault(defSpot.sloSH); + strSH->setDefault(defSpot.strSH); + angSH->setDefault(defSpot.angSH); + blendmaskSH->setDefault((double)defSpot.blendmaskSH); + radmaskSH->setDefault(defSpot.radmaskSH); + lapmaskSH->setDefault(defSpot.lapmaskSH); + chromaskSH->setDefault(defSpot.chromaskSH); + gammaskSH->setDefault(defSpot.gammaskSH); + slomaskSH->setDefault(defSpot.slomaskSH); + fatamountSH->setDefault(defSpot.fatamountSH); + fatanchorSH->setDefault(defSpot.fatanchorSH); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -1786,6 +3719,25 @@ void LocallabShadow::setDefaults(const rtengine::procparams::ProcParams* defPara void LocallabShadow::adjusterChanged(Adjuster* a, double newval) { if (isLocActivated && exp->getEnabled()) { + if (a == multipliersh[0] || a == multipliersh[1] || a == multipliersh[2] || a == multipliersh[3] || a == multipliersh[4]) { + if (listener) { + listener->panelChanged(EvlocallabEqualizersh, + Glib::ustring::compose("%1, %2, %3, %4, %5", + Glib::ustring::format(std::fixed, std::setprecision(2), multipliersh[0]->getIntValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multipliersh[1]->getIntValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multipliersh[2]->getIntValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multipliersh[3]->getIntValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multipliersh[4]->getIntValue())) + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == detailSH) { + if (listener) { + listener->panelChanged(EvlocallabdetailSH, + detailSH->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + if (a == highlights) { if (listener) { listener->panelChanged(Evlocallabhighlights, @@ -1835,38 +3787,88 @@ void LocallabShadow::adjusterChanged(Adjuster* a, double newval) } } - if (a == blendMask) { + if (a == gamSH) { + if (listener) { + listener->panelChanged(EvlocallabgamSH, + gamSH->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sloSH) { + if (listener) { + listener->panelChanged(EvlocallabsloSH, + sloSH->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strSH) { + if (listener) { + listener->panelChanged(EvlocallabstrSH, + strSH->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == angSH) { + if (listener) { + listener->panelChanged(EvlocallabangSH, + angSH->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blendmaskSH) { if (listener) { listener->panelChanged(EvlocallabblendmaskSH, - blendMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + blendmaskSH->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == radMask) { + if (a == radmaskSH) { if (listener) { listener->panelChanged(EvlocallabradmaskSH, - radMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + radmaskSH->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == chroMask) { + if (a == lapmaskSH) { + if (listener) { + listener->panelChanged(EvlocallablapmaskSH, + lapmaskSH->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chromaskSH) { if (listener) { listener->panelChanged(EvlocallabchromaskSH, - chroMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + chromaskSH->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == gamMask) { + if (a == gammaskSH) { if (listener) { listener->panelChanged(EvlocallabgammaskSH, - gamMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + gammaskSH->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == sloMask) { + if (a == slomaskSH) { if (listener) { listener->panelChanged(EvlocallabslomaskSH, - sloMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + slomaskSH->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == fatamountSH) { + if (listener) { + listener->panelChanged(EvlocallabfatamountSH, + fatamountSH->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + + if (a == fatanchorSH) { + if (listener) { + listener->panelChanged(EvlocallabfatanchorSH, + fatanchorSH->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } } @@ -1875,26 +3877,33 @@ void LocallabShadow::adjusterChanged(Adjuster* a, double newval) void LocallabShadow::curveChanged(CurveEditor* ce) { if (isLocActivated && exp->getEnabled()) { - if (ce == CCMaskShape) { + if (ce == CCmaskSHshape) { if (listener) { listener->panelChanged(EvlocallabCCmaskSHshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } - if (ce == LLMaskShape) { + if (ce == LLmaskSHshape) { if (listener) { listener->panelChanged(EvlocallabLLmaskSHshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } - if (ce == HHMaskShape) { + if (ce == HHmaskSHshape) { if (listener) { listener->panelChanged(EvlocallabHHmaskSHshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } + + if (ce == LmaskSHshape) { + if (listener) { + listener->panelChanged(EvlocallabLmaskSHshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } } } @@ -1913,37 +3922,40 @@ void LocallabShadow::enabledChanged() } } -void LocallabShadow::enaMaskChanged() +void LocallabShadow::updateMaskBackground(const double normChromar, const double normLumar, const double normHuer) { - if (isLocActivated && exp->getEnabled()) { - if (listener) { - if (enaMask->get_active()) { - listener->panelChanged(EvLocallabEnaSHMask, - M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); - } else { - listener->panelChanged(EvLocallabEnaSHMask, - M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); - } - } + idle_register.add( + [this, normHuer, normLumar, normChromar]() -> bool { + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected + + // Update mask background + CCmaskSHshape->updateLocallabBackground(normChromar); + LLmaskSHshape->updateLocallabBackground(normLumar); + HHmaskSHshape->updateLocallabBackground(normHuer); + + return false; } + ); } -void LocallabShadow::showMaskMethodChanged() +void LocallabShadow::shMethodChanged() { - // If mask preview is activated, deactivate all other tool mask preview - if (locToolListener) { - locToolListener->resetOtherMaskView(this); - } - if (listener) { - listener->panelChanged(EvlocallabshowmaskMethod, ""); + // Update shadow highlight GUI according to shMethod combobox state + updateShadowGUI2(); + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabshMethod, + shMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } } } void LocallabShadow::inversshChanged() { // Update shadow highlight GUI according to inverssh button state - updateShadowGUI(); + updateShadowGUI1(); if (isLocActivated && exp->getEnabled()) { if (listener) { @@ -1958,38 +3970,155 @@ void LocallabShadow::inversshChanged() } } -void LocallabShadow::updateShadowGUI() +void LocallabShadow::showmaskSHMethodChanged() +{ + // If mask preview is activated, deactivate other Shadow highlight mask preview + showmaskSHMethodConninv.block(true); + showmaskSHMethodinv->set_active(0); + showmaskSHMethodConninv.block(false); + + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskMethod, ""); + } +} + +void LocallabShadow::showmaskSHMethodChangedinv() +{ + // If mask preview is activated, deactivate other Shadow highlight mask preview + showmaskSHMethodConn.block(true); + showmaskSHMethod->set_active(0); + showmaskSHMethodConn.block(false); + + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskMethod, ""); + } +} + +void LocallabShadow::enaSHMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enaSHMask->get_active()) { + listener->panelChanged(EvLocallabEnaSHMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnaSHMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabShadow::updateShadowGUI1() { // Update shadow highlight GUI according to inverssh button state if (inverssh->get_active()) { - maskExp->hide(); + expgradsh->hide(); + showmaskSHMethod->hide(); // TODO Manage cases where avoid is activated with mask on + showmaskSHMethodinv->show(); } else { - maskExp->show(); + expgradsh->show(); + showmaskSHMethod->show(); + showmaskSHMethodinv->hide(); + } +} + +void LocallabShadow::updateShadowGUI2() +{ + // Update shadow highlight GUI according to shMethod combobox state + if (shMethod->get_active_row_number() == 0) { + for (int i = 0; i < 5; i++) { + multipliersh[i]->hide(); + } + + detailSH->hide(); + highlights->show(); + h_tonalwidth->show(); + shadows->show(); + s_tonalwidth->show(); + sh_radius->show(); + } else if (shMethod->get_active_row_number() == 1) { + for (int i = 0; i < 5; i++) { + multipliersh[i]->show(); + } + + detailSH->show(); + highlights->hide(); + h_tonalwidth->hide(); + shadows->hide(); + s_tonalwidth->hide(); + sh_radius->hide(); } } /* ==== LocallabVibrance ==== */ LocallabVibrance::LocallabVibrance(): - LocallabTool(this, M("TP_LOCALLAB_VIB_TOOLNAME"), M("TP_LOCALLAB_VIBRANCE"), false, MaskNone), + LocallabTool(this, M("TP_LOCALLAB_VIB_TOOLNAME"), M("TP_LOCALLAB_VIBRANCE"), false), // Vibrance specific widgets saturated(Gtk::manage(new Adjuster(M("TP_VIBRANCE_SATURATED"), -100., 100., 1., 0.))), pastels(Gtk::manage(new Adjuster(M("TP_VIBRANCE_PASTELS"), -100., 100., 1., 0.))), + warm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_WARM"), -100., 100., 1., 0., Gtk::manage(new RTImage("circle-blue-small.png")), Gtk::manage(new RTImage("circle-orange-small.png"))))), psThreshold(Gtk::manage(new ThresholdAdjuster(M("TP_VIBRANCE_PSTHRESHOLD"), -100., 100., 0., M("TP_VIBRANCE_PSTHRESHOLD_WEIGTHING"), 0, 0., 100., 75., M("TP_VIBRANCE_PSTHRESHOLD_SATTHRESH"), 0, this, false))), protectSkins(Gtk::manage(new Gtk::CheckButton(M("TP_VIBRANCE_PROTECTSKINS")))), avoidColorShift(Gtk::manage(new Gtk::CheckButton(M("TP_VIBRANCE_AVOIDCOLORSHIFT")))), pastSatTog(Gtk::manage(new Gtk::CheckButton(M("TP_VIBRANCE_PASTSATTOG")))), sensiv(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))), - curveEditorGG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL"))) + curveEditorGG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL"))), + skinTonesCurve(static_cast(curveEditorGG->addCurve(CT_Diagonal, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES")))), + expgradvib(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_EXPGRAD")))), + strvib(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -4., 4., 0.05, 0.))), + strvibab(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTRCHRO"), -4., 4., 0.05, 0.))), + strvibh(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTRHUE2"), -6., 6., 0.05, 0.))), + angvib(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))), + expmaskvib(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWVI")))), + showmaskvibMethod(Gtk::manage(new MyComboBoxText())), + enavibMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), + maskvibCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), + CCmaskvibshape(static_cast(maskvibCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false))), + LLmaskvibshape(static_cast(maskvibCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false))), + HHmaskvibshape(static_cast(maskvibCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true))), + blendmaskvib(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), + radmaskvib(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), -10.0, 1000.0, 0.1, 0.))), + lapmaskvib(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPMASKCOL"), 0.0, 100.0, 0.1, 0.))), + chromaskvib(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), + gammaskvib(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.25, 4.0, 0.01, 1.))), + slomaskvib(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), + mask2vibCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), + Lmaskvibshape(static_cast(mask2vibCurveEditorG->addCurve(CT_Diagonal, "L(L)"))) { float R, G, B; - const bool showtooltip = options.showtooltip; + const LocallabParams::LocallabSpot defSpot; + const bool showtooltip = options.showtooltip; + const int complexsoft = options.complexity; + + // Parameter Vibrance specific widgets saturated->setAdjusterListener(this); + if (complexsoft == 2) { + pastels->setLabel(M("TP_LOCALLAB_PASTELS2")); + } + pastels->setAdjusterListener(this); + if (showtooltip) { + warm->set_tooltip_text(M("TP_LOCALLAB_WARM_TOOLTIP")); + } + + warm->setAdjusterListener(this); + if (showtooltip) { psThreshold->set_tooltip_markup(M("TP_VIBRANCE_PSTHRESHOLD_TOOLTIP")); } @@ -2006,8 +4135,6 @@ LocallabVibrance::LocallabVibrance(): curveEditorGG->setCurveListener(this); - skinTonesCurve = static_cast(curveEditorGG->addCurve(CT_Diagonal, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES"))); - if (showtooltip) { skinTonesCurve->setTooltip(M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_TOOLTIP")); } @@ -2015,9 +4142,9 @@ LocallabVibrance::LocallabVibrance(): std::vector mskinTonesCurve; // -0.1 rad < Hue < 1.6 rad Color::hsv2rgb01(0.92f, 0.45f, 0.6f, R, G, B); - mskinTonesCurve.push_back(GradientMilestone(0.0, double (R), double (G), double (B))); + mskinTonesCurve.emplace_back(0.0, R, G, B); Color::hsv2rgb01(0.14056f, 0.45f, 0.6f, R, G, B); - mskinTonesCurve.push_back(GradientMilestone(1.0, double (R), double (G), double (B))); + mskinTonesCurve.emplace_back(0.0, R, G, B); skinTonesCurve->setBottomBarBgGradient(mskinTonesCurve); skinTonesCurve->setLeftBarBgGradient(mskinTonesCurve); skinTonesCurve->setRangeLabels( @@ -2028,19 +4155,185 @@ LocallabVibrance::LocallabVibrance(): curveEditorGG->curveListComplete(); - pack_start(*saturated, Gtk::PACK_SHRINK, 0); + setExpandAlignProperties(expgradvib, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + if (showtooltip) { + strvib->set_tooltip_text(M("TP_LOCALLAB_GRADGEN_TOOLTIP")); + } + + strvib->setAdjusterListener(this); + + if (showtooltip) { + strvibab->set_tooltip_text(M("TP_LOCALLAB_GRADSTRAB_TOOLTIP")); + } + + strvibab->setAdjusterListener(this); + + if (showtooltip) { + strvibh->set_tooltip_text(M("TP_LOCALLAB_GRADSTRHUE_TOOLTIP")); + } + + strvibh->setAdjusterListener(this); + + if (showtooltip) { + angvib->set_tooltip_text(M("TP_LOCALLAB_GRADANG_TOOLTIP")); + } + + angvib->setAdjusterListener(this); + + setExpandAlignProperties(expmaskvib, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + if (showtooltip) { + expmaskvib->set_tooltip_markup(M("TP_LOCALLAB_MASK_TOOLTIP")); + } + + showmaskvibMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskvibMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showmaskvibMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); + showmaskvibMethod->append(M("TP_LOCALLAB_SHOWMASK")); + showmaskvibMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); + showmaskvibMethod->set_active(0); + + if (showtooltip) { + showmaskvibMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmaskvibMethodConn = showmaskvibMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabVibrance::showmaskvibMethodChanged)); + + enavibMaskConn = enavibMask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabVibrance::enavibMaskChanged)); + + maskvibCurveEditorG->setCurveListener(this); + + CCmaskvibshape->setIdentityValue(0.); + CCmaskvibshape->setResetCurve(FlatCurveType(defSpot.CCmaskvibcurve.at(0)), defSpot.CCmaskvibcurve); + + if (showtooltip) { + CCmaskvibshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + CCmaskvibshape->setBottomBarColorProvider(this, 1); + + LLmaskvibshape->setIdentityValue(0.); + LLmaskvibshape->setResetCurve(FlatCurveType(defSpot.LLmaskvibcurve.at(0)), defSpot.LLmaskvibcurve); + + if (showtooltip) { + LLmaskvibshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + LLmaskvibshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + HHmaskvibshape->setIdentityValue(0.); + HHmaskvibshape->setResetCurve(FlatCurveType(defSpot.HHmaskvibcurve.at(0)), defSpot.HHmaskvibcurve); + + if (showtooltip) { + HHmaskvibshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + HHmaskvibshape->setCurveColorProvider(this, 2); + HHmaskvibshape->setBottomBarColorProvider(this, 2); + + maskvibCurveEditorG->curveListComplete(); + + blendmaskvib->setAdjusterListener(this); + + radmaskvib->setLogScale(10, -10); + radmaskvib->setAdjusterListener(this); + + lapmaskvib->setAdjusterListener(this); + + chromaskvib->setAdjusterListener(this); + + gammaskvib->setAdjusterListener(this); + + slomaskvib->setAdjusterListener(this); + + mask2vibCurveEditorG->setCurveListener(this); + + Lmaskvibshape->setResetCurve(DiagonalCurveType(defSpot.Lmaskvibcurve.at(0)), defSpot.Lmaskvibcurve); + + if (showtooltip) { + Lmaskvibshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + } + + Lmaskvibshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + Lmaskvibshape->setLeftBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + mask2vibCurveEditorG->curveListComplete(); + + // Add Vibrance specific widgets to GUI + if (complexsoft < 2) { + pack_start(*saturated, Gtk::PACK_SHRINK, 0); + } + pack_start(*pastels, Gtk::PACK_SHRINK, 0); - pack_start(*psThreshold, Gtk::PACK_SHRINK, 0); - pack_start(*protectSkins, Gtk::PACK_SHRINK, 0); - pack_start(*avoidColorShift, Gtk::PACK_SHRINK, 0); - pack_start(*pastSatTog, Gtk::PACK_SHRINK, 0); + pack_start(*warm, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 2) { + pack_start(*psThreshold, Gtk::PACK_SHRINK, 0); + pack_start(*protectSkins, Gtk::PACK_SHRINK, 0); + pack_start(*avoidColorShift, Gtk::PACK_SHRINK, 0); + pack_start(*pastSatTog, Gtk::PACK_SHRINK, 0); + } + pack_start(*sensiv, Gtk::PACK_SHRINK, 0); - pack_start(*curveEditorGG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + + if (complexsoft < 2) { + pack_start(*curveEditorGG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + } + + ToolParamBlock* const gradvibBox = Gtk::manage(new ToolParamBlock()); + gradvibBox->pack_start(*strvib); + + if (complexsoft < 2) { + gradvibBox->pack_start(*strvibab); + gradvibBox->pack_start(*strvibh); + } + + gradvibBox->pack_start(*angvib); + expgradvib->add(*gradvibBox, false); + pack_start(*expgradvib); + ToolParamBlock* const maskvibBox = Gtk::manage(new ToolParamBlock()); + maskvibBox->pack_start(*showmaskvibMethod, Gtk::PACK_SHRINK, 4); + maskvibBox->pack_start(*enavibMask, Gtk::PACK_SHRINK, 0); + maskvibBox->pack_start(*maskvibCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + maskvibBox->pack_start(*blendmaskvib, Gtk::PACK_SHRINK, 0); + maskvibBox->pack_start(*radmaskvib, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 1) { + maskvibBox->pack_start(*lapmaskvib, Gtk::PACK_SHRINK, 0); + } + + maskvibBox->pack_start(*chromaskvib, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 2) { + maskvibBox->pack_start(*gammaskvib, Gtk::PACK_SHRINK, 0); + maskvibBox->pack_start(*slomaskvib, Gtk::PACK_SHRINK, 0); + } + + maskvibBox->pack_start(*mask2vibCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + expmaskvib->add(*maskvibBox, false); + pack_start(*expmaskvib, false, false); } LocallabVibrance::~LocallabVibrance() { delete curveEditorGG; + delete maskvibCurveEditorG; + delete mask2vibCurveEditorG; +} + +void LocallabVibrance::resetMaskView() +{ + showmaskvibMethodConn.block(true); + + showmaskvibMethod->set_active(0); + + showmaskvibMethodConn.block(false); +} + +void LocallabVibrance::getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask) +{ + vibMask = showmaskvibMethod->get_active_row_number(); } void LocallabVibrance::disableListener() @@ -2050,6 +4343,8 @@ void LocallabVibrance::disableListener() pskinsConn.block(true); ashiftConn.block(true); pastsattogConn.block(true); + showmaskvibMethodConn.block(true); + enavibMaskConn.block(true); } void LocallabVibrance::enableListener() @@ -2059,10 +4354,14 @@ void LocallabVibrance::enableListener() pskinsConn.block(false); ashiftConn.block(false); pastsattogConn.block(false); + showmaskvibMethodConn.block(false); + enavibMaskConn.block(false); } void LocallabVibrance::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { + const int complexsoft = options.complexity; + // Disable all listeners disableListener(); @@ -2073,16 +4372,58 @@ void LocallabVibrance::read(const rtengine::procparams::ProcParams* pp, const Pa spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot exp->set_visible(pp->locallab.spots.at(index).visivibrance); - exp->setEnabled(pp->locallab.spots.at(index).expvibrance); + saturated->setValue(pp->locallab.spots.at(index).saturated); pastels->setValue(pp->locallab.spots.at(index).pastels); + warm->setValue(pp->locallab.spots.at(index).warm); psThreshold->setValue(pp->locallab.spots.at(index).psthreshold); protectSkins->set_active(pp->locallab.spots.at(index).protectskins); avoidColorShift->set_active(pp->locallab.spots.at(index).avoidcolorshift); pastSatTog->set_active(pp->locallab.spots.at(index).pastsattog); sensiv->setValue(pp->locallab.spots.at(index).sensiv); - skinTonesCurve->setCurve(pp->locallab.spots.at(index).skintonescurve); + + if (complexsoft < 2) { + skinTonesCurve->setCurve(pp->locallab.spots.at(index).skintonescurve); + } else { + skinTonesCurve->reset(); + } + + strvib->setValue(pp->locallab.spots.at(index).strvib); + + if (complexsoft == 0) { + strvibab->setValue(pp->locallab.spots.at(index).strvibab); + strvibh->setValue(pp->locallab.spots.at(index).strvibh); + } else { + strvibab->setValue(0.); + strvibh->setValue(0.); + } + + angvib->setValue(pp->locallab.spots.at(index).angvib); + enavibMask->set_active(pp->locallab.spots.at(index).enavibMask); + CCmaskvibshape->setCurve(pp->locallab.spots.at(index).CCmaskvibcurve); + LLmaskvibshape->setCurve(pp->locallab.spots.at(index).LLmaskvibcurve); + HHmaskvibshape->setCurve(pp->locallab.spots.at(index).HHmaskvibcurve); + blendmaskvib->setValue(pp->locallab.spots.at(index).blendmaskvib); + radmaskvib->setValue(pp->locallab.spots.at(index).radmaskvib); + + if (complexsoft == 0) { + lapmaskvib->setValue(pp->locallab.spots.at(index).lapmaskvib); + } else { + lapmaskvib->setValue(0.); + } + + chromaskvib->setValue(pp->locallab.spots.at(index).chromaskvib); + + if (complexsoft < 2) { + gammaskvib->setValue(pp->locallab.spots.at(index).gammaskvib); + slomaskvib->setValue(pp->locallab.spots.at(index).slomaskvib); + } else { + gammaskvib->setValue(1.); + slomaskvib->setValue(0.); + } + + Lmaskvibshape->setCurve(pp->locallab.spots.at(index).Lmaskvibcurve); } // Enable all listeners @@ -2100,17 +4441,32 @@ void LocallabVibrance::write(rtengine::procparams::ProcParams* pp, ParamsEdited* if (index < (int)pp->locallab.spots.size()) { pp->locallab.spots.at(index).expvibrance = exp->getEnabled(); - pp->locallab.spots.at(index).visivibrance = exp->get_visible(); pp->locallab.spots.at(index).saturated = saturated->getIntValue(); pp->locallab.spots.at(index).pastels = pastels->getIntValue(); + pp->locallab.spots.at(index).warm = warm->getIntValue(); pp->locallab.spots.at(index).psthreshold = psThreshold->getValue(); pp->locallab.spots.at(index).protectskins = protectSkins->get_active(); pp->locallab.spots.at(index).avoidcolorshift = avoidColorShift->get_active(); pp->locallab.spots.at(index).pastsattog = pastSatTog->get_active(); pp->locallab.spots.at(index).sensiv = sensiv->getIntValue(); pp->locallab.spots.at(index).skintonescurve = skinTonesCurve->getCurve(); + pp->locallab.spots.at(index).strvib = strvib->getValue(); + pp->locallab.spots.at(index).strvibab = strvibab->getValue(); + pp->locallab.spots.at(index).strvibh = strvibh->getValue(); + pp->locallab.spots.at(index).angvib = angvib->getValue(); + pp->locallab.spots.at(index).enavibMask = enavibMask->get_active(); + pp->locallab.spots.at(index).CCmaskvibcurve = CCmaskvibshape->getCurve(); + pp->locallab.spots.at(index).LLmaskvibcurve = LLmaskvibshape->getCurve(); + pp->locallab.spots.at(index).HHmaskvibcurve = HHmaskvibshape->getCurve(); + pp->locallab.spots.at(index).blendmaskvib = blendmaskvib->getIntValue(); + pp->locallab.spots.at(index).radmaskvib = radmaskvib->getValue(); + pp->locallab.spots.at(index).lapmaskvib = lapmaskvib->getValue(); + pp->locallab.spots.at(index).chromaskvib = chromaskvib->getValue(); + pp->locallab.spots.at(index).gammaskvib = gammaskvib->getValue(); + pp->locallab.spots.at(index).slomaskvib = slomaskvib->getValue(); + pp->locallab.spots.at(index).Lmaskvibcurve = Lmaskvibshape->getCurve(); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -2126,8 +4482,19 @@ void LocallabVibrance::setDefaults(const rtengine::procparams::ProcParams* defPa // Set default values for adjuster and threshold adjuster widgets saturated->setDefault((double)defSpot.saturated); pastels->setDefault((double)defSpot.pastels); + warm->setDefault((double)defSpot.warm); psThreshold->setDefault(defSpot.psthreshold); sensiv->setDefault((double)defSpot.sensiv); + strvib->setDefault(defSpot.strvib); + strvibab->setDefault(defSpot.strvibab); + strvibh->setDefault(defSpot.strvibh); + angvib->setDefault(defSpot.angvib); + blendmaskvib->setDefault((double)defSpot.blendmaskvib); + radmaskvib->setDefault(defSpot.radmaskvib); + lapmaskvib->setDefault(defSpot.lapmaskvib); + chromaskvib->setDefault(defSpot.chromaskvib); + gammaskvib->setDefault(defSpot.gammaskvib); + slomaskvib->setDefault(defSpot.slomaskvib); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -2155,12 +4522,89 @@ void LocallabVibrance::adjusterChanged(Adjuster* a, double newval) } } + if (a == warm) { + if (listener) { + listener->panelChanged(Evlocallabwarm, + warm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + if (a == sensiv) { if (listener) { listener->panelChanged(Evlocallabsensiv, sensiv->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } + + if (a == strvib) { + if (listener) { + listener->panelChanged(Evlocallabstrvib, + strvib->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strvibab) { + if (listener) { + listener->panelChanged(Evlocallabstrvibab, + strvibab->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strvibh) { + if (listener) { + listener->panelChanged(Evlocallabstrvibh, + strvibh->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == angvib) { + if (listener) { + listener->panelChanged(Evlocallabangvib, + angvib->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blendmaskvib) { + if (listener) { + listener->panelChanged(Evlocallabblendmaskvi, + blendmaskvib->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == radmaskvib) { + if (listener) { + listener->panelChanged(Evlocallabradmaskvib, + radmaskvib->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == lapmaskvib) { + if (listener) { + listener->panelChanged(Evlocallablapmaskvib, + lapmaskvib->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chromaskvib) { + if (listener) { + listener->panelChanged(Evlocallabchromaskvib, + chromaskvib->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == gammaskvib) { + if (listener) { + listener->panelChanged(Evlocallabgammaskvib, + gammaskvib->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == slomaskvib) { + if (listener) { + listener->panelChanged(Evlocallabslomaskvib, + slomaskvib->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } } } @@ -2231,6 +4675,34 @@ void LocallabVibrance::curveChanged(CurveEditor* ce) M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } + + if (ce == CCmaskvibshape) { + if (listener) { + listener->panelChanged(EvlocallabCCmaskvibshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == LLmaskvibshape) { + if (listener) { + listener->panelChanged(EvlocallabLLmaskvibshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == HHmaskvibshape) { + if (listener) { + listener->panelChanged(EvlocallabHHmaskvibshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == Lmaskvibshape) { + if (listener) { + listener->panelChanged(EvlocallabLmaskvibshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } } } @@ -2249,6 +4721,22 @@ void LocallabVibrance::enabledChanged() } } +void LocallabVibrance::updateMaskBackground(const double normChromar, const double normLumar, const double normHuer) +{ + idle_register.add( + [this, normHuer, normLumar, normChromar]() -> bool { + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected + + // Update mask background + CCmaskvibshape->updateLocallabBackground(normChromar); + LLmaskvibshape->updateLocallabBackground(normLumar); + HHmaskvibshape->updateLocallabBackground(normHuer); + + return false; + } + ); +} + void LocallabVibrance::protectskins_toggled() { if (isLocActivated && exp->getEnabled()) { @@ -2297,6 +4785,33 @@ void LocallabVibrance::pastsattog_toggled() } } +void LocallabVibrance::showmaskvibMethodChanged() +{ + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskMethod, ""); + } +} + +void LocallabVibrance::enavibMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enavibMask->get_active()) { + listener->panelChanged(EvLocallabEnavibMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnavibMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + void LocallabVibrance::updateVibranceGUI() { // Update vibrance GUI according to pastsattog button state @@ -2314,7 +4829,7 @@ void LocallabVibrance::updateVibranceGUI() /* ==== LocallabSoft ==== */ LocallabSoft::LocallabSoft(): - LocallabTool(this, M("TP_LOCALLAB_SOFT_TOOLNAME"), M("TP_LOCALLAB_SOFT"), false, MaskNone), + LocallabTool(this, M("TP_LOCALLAB_SOFT_TOOLNAME"), M("TP_LOCALLAB_SOFT"), false), // Soft light specific widgets softMethod(Gtk::manage(new MyComboBoxText())), @@ -2325,7 +4840,9 @@ LocallabSoft::LocallabSoft(): sensisf(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 1, 100, 1, 15))) { const bool showtooltip = options.showtooltip; + const int complexsoft = options.complexity; + // Parameter Soft light specific widgets softMethod->append(M("TP_LOCALLAB_SOFTM")); softMethod->append(M("TP_LOCALLAB_RETIM")); softMethod->set_active(0); @@ -2341,13 +4858,15 @@ LocallabSoft::LocallabSoft(): showmasksoftMethod->append(M("TP_LOCALLAB_SHOWFOURIER")); showmasksoftMethod->append(M("TP_LOCALLAB_SHOWPOISSON")); showmasksoftMethod->append(M("TP_LOCALLAB_SHOWNORMAL")); + showmasksoftMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showmasksoftMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); showmasksoftMethod->set_active(0); if (showtooltip) { showmasksoftMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKSOFT_TOOLTIP")); } - showmasksoftMethodConn = showmasksoftMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabSoft::showmasksoftMethodChanged)); + showmasksoftMethodConn = showmasksoftMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabSoft::showmasksoftMethodChanged)); streng->setAdjusterListener(this); @@ -2355,7 +4874,11 @@ LocallabSoft::LocallabSoft(): sensisf->setAdjusterListener(this); - pack_start(*softMethod); + // Add Soft light specific widgets to GUI + if (complexsoft < 2) { + pack_start(*softMethod); + } + Gtk::Label* const labelsoftmethod = Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_SHOWDCT") + ":")); ctboxsoftmethod->pack_start(*labelsoftmethod, Gtk::PACK_SHRINK, 4); ctboxsoftmethod->pack_start(*showmasksoftMethod); @@ -2365,7 +4888,14 @@ LocallabSoft::LocallabSoft(): pack_start(*sensisf); } -void LocallabSoft::getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask) +void LocallabSoft::resetMaskView() +{ + showmasksoftMethodConn.block(true); + showmasksoftMethod->set_active(0); + showmasksoftMethodConn.block(false); +} + +void LocallabSoft::getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask) { softMask = showmasksoftMethod->get_active_row_number(); } @@ -2388,6 +4918,8 @@ void LocallabSoft::enableListener() void LocallabSoft::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { + const int complexsoft = options.complexity; + // Disable all listeners disableListener(); @@ -2398,17 +4930,22 @@ void LocallabSoft::read(const rtengine::procparams::ProcParams* pp, const Params spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot exp->set_visible(pp->locallab.spots.at(index).visisoft); - exp->setEnabled(pp->locallab.spots.at(index).expsoft); - if (pp->locallab.spots.at(index).softMethod == "soft") { + if (complexsoft < 2) { + if (pp->locallab.spots.at(index).softMethod == "soft") { + softMethod->set_active(0); + } else if (pp->locallab.spots.at(index).softMethod == "reti") { + softMethod->set_active(1); + } + + streng->setValue((double)pp->locallab.spots.at(index).streng); + } else { softMethod->set_active(0); - } else if (pp->locallab.spots.at(index).softMethod == "reti") { - softMethod->set_active(1); + streng->setValue(1.); } - streng->setValue(pp->locallab.spots.at(index).streng); - sensisf->setValue(pp->locallab.spots.at(index).sensisf); + sensisf->setValue((double)pp->locallab.spots.at(index).sensisf); laplace->setValue(pp->locallab.spots.at(index).laplace); } @@ -2427,7 +4964,6 @@ void LocallabSoft::write(rtengine::procparams::ProcParams* pp, ParamsEdited* ped if (index < (int)pp->locallab.spots.size()) { pp->locallab.spots.at(index).expsoft = exp->getEnabled(); - pp->locallab.spots.at(index).visisoft = exp->get_visible(); if (softMethod->get_active_row_number() == 0) { @@ -2486,13 +5022,6 @@ void LocallabSoft::adjusterChanged(Adjuster* a, double newval) } } -void LocallabSoft::resetMaskView() -{ - showmasksoftMethodConn.block(true); - showmasksoftMethod->set_active(0); - showmasksoftMethodConn.block(false); -} - void LocallabSoft::enabledChanged() { if (isLocActivated) { @@ -2537,7 +5066,7 @@ void LocallabSoft::updateSoftGUI() { // Update soft light GUI according to softMethod combobox if (softMethod->get_active_row_number() == 0) { - laplace->hide(); + laplace->hide(); // TODO Manage case where mask is on when soft method is changed ctboxsoftmethod->hide(); } else { laplace->show(); @@ -2547,21 +5076,100 @@ void LocallabSoft::updateSoftGUI() /* ==== LocallabBlur ==== */ LocallabBlur::LocallabBlur(): - LocallabTool(this, M("TP_LOCALLAB_BLUR_TOOLNAME"), M("TP_LOCALLAB_BLUFR"), false, MaskNone), + LocallabTool(this, M("TP_LOCALLAB_BLUR_TOOLNAME"), M("TP_LOCALLAB_BLUFR"), true), // Blur & Noise specific widgets - radius(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADIUS"), 1.0, 100.0, 0.1, 1.0))), + blMethod(Gtk::manage(new MyComboBoxText())), + fftwbl(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_FFTWBLUR")))), + radius(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADIUS"), MINRAD, MAXRAD, 0.1, 1.5, nullptr, nullptr, &blurSlider2radius, &blurRadius2Slider))), strength(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRENGTH"), 0, 100, 1, 0))), + grainFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_GRAINFRA")))), + isogr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_ISOGR"), 20, 6400, 1, 0))), + strengr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRENGR"), 0, 100, 1, 0))), + scalegr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SCALEGR"), 0, 100, 1, 100))), + medMethod(Gtk::manage(new MyComboBoxText())), + itera(Gtk::manage(new Adjuster(M("TP_DIRPYRDENOISE_MEDIAN_PASSES"), 1, 4, 1, 1))), + guidbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GUIDBL"), 0, 1000, 1, 0))), + strbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRBL"), 0, 100, 1, 50))), + epsbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_EPSBL"), -10, 10, 1, 0))), sensibn(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIBN"), 0, 100, 1, 40))), blurMethod(Gtk::manage(new MyComboBoxText())), - activlum(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ACTIV")))) + chroMethod(Gtk::manage(new MyComboBoxText())), + activlum(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ACTIV")))), + expmaskbl(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWPLUS")))), + showmaskblMethod(Gtk::manage(new MyComboBoxText())), + enablMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), + maskblCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), + CCmaskblshape(static_cast(maskblCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false))), + LLmaskblshape(static_cast(maskblCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false))), + HHmaskblshape(static_cast(maskblCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true))), + strumaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRUMASKCOL"), 0., 200., 0.1, 0.))), + toolbl(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_TOOLCOL")))), + blendmaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), + toolblFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_TOOLMASK")))), + radmaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), -10.0, 1000.0, 0.1, 0.))), + lapmaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPMASKCOL"), 0.0, 100.0, 0.1, 0.))), + chromaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), + gammaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.05, 5.0, 0.01, 1.))), + slomaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), + shadmaskbl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_HIGHMASKCOL"), 0, 100, 1, 0))), + mask2blCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), + Lmaskblshape(static_cast(mask2blCurveEditorG->addCurve(CT_Diagonal, "L(L)"))), + mask2blCurveEditorGwav(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVMASK"))), + LLmaskblshapewav(static_cast(mask2blCurveEditorGwav->addCurve(CT_Flat, "L(L)", nullptr, false, false))), + csThresholdblur(Gtk::manage(new ThresholdAdjuster(M("TP_LOCALLAB_CSTHRESHOLDBLUR"), 0, 9, 0, 0, 6, 5, 0, false))) { + const LocallabParams::LocallabSpot defSpot; + const bool showtooltip = options.showtooltip; + const int complexsoft = options.complexity; + + // Parameter Blur & Noise specific widgets + if (showtooltip) { + exp->set_tooltip_markup(M("TP_LOCALLAB_BLUMETHOD_TOOLTIP")); + } + + blMethod->append(M("TP_LOCALLAB_BLUR")); + blMethod->append(M("TP_LOCALLAB_BLMED")); + blMethod->append(M("TP_LOCALLAB_BLGUID")); + blMethod->set_active(0); + blMethodConn = blMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabBlur::blMethodChanged)); + + fftwblConn = fftwbl->signal_toggled().connect(sigc::mem_fun(*this, &LocallabBlur::fftwblChanged)); + + if (showtooltip) { + radius->set_tooltip_text(M("TP_LOCALLAB_RADIUS_TOOLTIP")); + } radius->setAdjusterListener(this); strength->setAdjusterListener(this); + grainFrame->set_label_align(0.025, 0.5); + + isogr->setAdjusterListener(this); + + strengr->setAdjusterListener(this); + + scalegr->setAdjusterListener(this); + + medMethod->append(M("TP_LOCALLAB_MEDNONE")); + medMethod->append(M("TP_DIRPYRDENOISE_TYPE_3X3")); + medMethod->append(M("TP_DIRPYRDENOISE_TYPE_5X5")); + medMethod->append(M("TP_DIRPYRDENOISE_TYPE_7X7")); + medMethod->append(M("TP_DIRPYRDENOISE_TYPE_9X9")); + medMethod->set_active(0); + medMethodConn = medMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabBlur::medMethodChanged)); + + itera->setAdjusterListener(this); + + guidbl->setLogScale(100, 0); + guidbl->setAdjusterListener(this); + + strbl->setAdjusterListener(this); + + epsbl->setAdjusterListener(this); + if (showtooltip) { sensibn->set_tooltip_text(M("TP_LOCALLAB_SENSIH_TOOLTIP")); } @@ -2578,33 +5186,240 @@ LocallabBlur::LocallabBlur(): blurMethodConn = blurMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabBlur::blurMethodChanged)); - activlumConn = activlum->signal_toggled().connect(sigc::mem_fun(*this, &LocallabBlur::activlumChanged)); + chroMethod->append(M("TP_LOCALLAB_BLLO")); + chroMethod->append(M("TP_LOCALLAB_BLCO")); + chroMethod->append(M("TP_LOCALLAB_BLLC")); + chroMethod->set_active(0); + chroMethodConn = chroMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabBlur::chroMethodChanged)); + + activlumConn = activlum->signal_toggled().connect(sigc::mem_fun(*this, &LocallabBlur::activlumChanged)); + + setExpandAlignProperties(expmaskbl, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + if (showtooltip) { + expmaskbl->set_tooltip_markup(M("TP_LOCALLAB_MASK_TOOLTIP")); + } + + showmaskblMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskblMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showmaskblMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); + showmaskblMethod->append(M("TP_LOCALLAB_SHOWMASK")); + showmaskblMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); + showmaskblMethod->set_active(0); + + if (showtooltip) { + showmaskblMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmaskblMethodConn = showmaskblMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabBlur::showmaskblMethodChanged)); + + enablMaskConn = enablMask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabBlur::enablMaskChanged)); + + maskblCurveEditorG->setCurveListener(this); + + CCmaskblshape->setIdentityValue(0.); + CCmaskblshape->setResetCurve(FlatCurveType(defSpot.CCmaskblcurve.at(0)), defSpot.CCmaskblcurve); + + if (showtooltip) { + CCmaskblshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + CCmaskblshape->setBottomBarColorProvider(this, 1); + + LLmaskblshape->setIdentityValue(0.); + LLmaskblshape->setResetCurve(FlatCurveType(defSpot.LLmaskblcurve.at(0)), defSpot.LLmaskblcurve); + + if (showtooltip) { + LLmaskblshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + LLmaskblshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + HHmaskblshape->setIdentityValue(0.); + HHmaskblshape->setResetCurve(FlatCurveType(defSpot.HHmaskblcurve.at(0)), defSpot.HHmaskblcurve); + + if (showtooltip) { + HHmaskblshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + HHmaskblshape->setCurveColorProvider(this, 2); + HHmaskblshape->setBottomBarColorProvider(this, 2); + + maskblCurveEditorG->curveListComplete(); + + strumaskbl->setAdjusterListener(this); + + toolblConn = toolbl->signal_toggled().connect(sigc::mem_fun(*this, &LocallabBlur::toolblChanged)); + + blendmaskbl->setAdjusterListener(this); + + toolblFrame->set_label_align(0.025, 0.5); + + if (showtooltip) { + radmaskbl->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + radmaskbl->setAdjusterListener(this); + + if (showtooltip) { + lapmaskbl->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + lapmaskbl->setAdjusterListener(this); + + chromaskbl->setAdjusterListener(this); + + gammaskbl->setAdjusterListener(this); + + slomaskbl->setAdjusterListener(this); + + shadmaskbl->setAdjusterListener(this); + + mask2blCurveEditorG->setCurveListener(this); + + Lmaskblshape->setResetCurve(DiagonalCurveType(defSpot.Lmaskblcurve.at(0)), defSpot.Lmaskblcurve); + + if (showtooltip) { + Lmaskblshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + } + + Lmaskblshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + Lmaskblshape->setLeftBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + mask2blCurveEditorG->curveListComplete(); + + mask2blCurveEditorGwav->setCurveListener(this); + + LLmaskblshapewav->setIdentityValue(0.); + LLmaskblshapewav->setResetCurve(FlatCurveType(defSpot.LLmaskblcurvewav.at(0)), defSpot.LLmaskblcurvewav); + + if (showtooltip) { + LLmaskblshapewav->setTooltip(M("TP_LOCALLAB_LMASK_LEVEL_TOOLTIP")); + } + + LLmaskblshapewav->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + mask2blCurveEditorGwav->curveListComplete(); + + csThresholdblur->setAdjusterListener(this); + + // Add Blur & Noise specific widgets to GUI + pack_start(*blMethod); + + if (complexsoft < 2) { + pack_start(*fftwbl, Gtk::PACK_SHRINK, 0); + } pack_start(*radius); pack_start(*strength); + ToolParamBlock* const grainBox = Gtk::manage(new ToolParamBlock()); + grainBox->pack_start(*isogr); + grainBox->pack_start(*strengr); + grainBox->pack_start(*scalegr); + grainFrame->add(*grainBox); + pack_start(*grainFrame); + pack_start(*medMethod); + pack_start(*itera); + pack_start(*guidbl); + pack_start(*strbl); + pack_start(*epsbl); pack_start(*sensibn); pack_start(*blurMethod); - pack_start(*activlum); + pack_start(*chroMethod); + // pack_start(*activlum); + ToolParamBlock* const maskblBox = Gtk::manage(new ToolParamBlock()); + maskblBox->pack_start(*showmaskblMethod, Gtk::PACK_SHRINK, 4); + maskblBox->pack_start(*enablMask, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 2) { + maskblBox->pack_start(*maskblCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + maskblBox->pack_start(*strumaskbl, Gtk::PACK_SHRINK, 0); + maskblBox->pack_start(*toolbl, Gtk::PACK_SHRINK, 0); + } + + Gtk::HSeparator* const separatorstrubl = Gtk::manage(new Gtk::HSeparator()); + maskblBox->pack_start(*separatorstrubl, Gtk::PACK_SHRINK, 2); + maskblBox->pack_start(*blendmaskbl, Gtk::PACK_SHRINK, 0); + ToolParamBlock* const toolblBox = Gtk::manage(new ToolParamBlock()); + toolblBox->pack_start(*radmaskbl, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 1) { + toolblBox->pack_start(*lapmaskbl, Gtk::PACK_SHRINK, 0); + } + + toolblBox->pack_start(*chromaskbl, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 2) { + toolblBox->pack_start(*gammaskbl, Gtk::PACK_SHRINK, 0); + toolblBox->pack_start(*slomaskbl, Gtk::PACK_SHRINK, 0); + toolblBox->pack_start(*shadmaskbl, Gtk::PACK_SHRINK, 0); + } + + toolblBox->pack_start(*mask2blCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + + if (complexsoft < 1) { + toolblBox->pack_start(*mask2blCurveEditorGwav, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + toolblBox->pack_start(*csThresholdblur, Gtk::PACK_SHRINK, 0); + } + + toolblFrame->add(*toolblBox); + maskblBox->pack_start(*toolblFrame); + expmaskbl->add(*maskblBox, false); + pack_start(*expmaskbl); +} + +LocallabBlur::~LocallabBlur() +{ + delete maskblCurveEditorG; + delete mask2blCurveEditorG; + delete mask2blCurveEditorGwav; +} + +void LocallabBlur::resetMaskView() +{ + showmaskblMethodConn.block(true); + showmaskblMethod->set_active(0); + showmaskblMethodConn.block(false); +} + +void LocallabBlur::getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask) +{ + blMask = showmaskblMethod->get_active_row_number(); } void LocallabBlur::disableListener() { LocallabTool::disableListener(); + blMethodConn.block(true); + fftwblConn.block(true); + medMethodConn.block(true); blurMethodConn.block(true); + chroMethodConn.block(true); activlumConn.block(true); + showmaskblMethodConn.block(true); + enablMaskConn.block(true); + toolblConn.block(true); } void LocallabBlur::enableListener() { LocallabTool::enableListener(); + blMethodConn.block(false); + fftwblConn.block(false); + medMethodConn.block(false); blurMethodConn.block(false); + chroMethodConn.block(false); activlumConn.block(false); + showmaskblMethodConn.block(false); + enablMaskConn.block(false); + toolblConn.block(false); } void LocallabBlur::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { + const int complexsoft = options.complexity; + // Disable all listeners disableListener(); @@ -2615,11 +5430,49 @@ void LocallabBlur::read(const rtengine::procparams::ProcParams* pp, const Params spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot exp->set_visible(pp->locallab.spots.at(index).visiblur); - exp->setEnabled(pp->locallab.spots.at(index).expblur); + + if (pp->locallab.spots.at(index).blMethod == "blur") { + blMethod->set_active(0); + } else if (pp->locallab.spots.at(index).blMethod == "med") { + blMethod->set_active(1); + } else if (pp->locallab.spots.at(index).blMethod == "guid") { + blMethod->set_active(2); + } + + if (complexsoft < 2) { + fftwbl->set_active(pp->locallab.spots.at(index).fftwbl); + } else { + fftwbl->set_active(false); + } + radius->setValue(pp->locallab.spots.at(index).radius); strength->setValue(pp->locallab.spots.at(index).strength); - sensibn->setValue(pp->locallab.spots.at(index).sensibn); + isogr->setValue((double)pp->locallab.spots.at(index).isogr); + strengr->setValue((double)pp->locallab.spots.at(index).strengr); + scalegr->setValue((double)pp->locallab.spots.at(index).scalegr); + + if (complexsoft < 2) { + if (pp->locallab.spots.at(index).medMethod == "none") { + medMethod->set_active(0); + } else if (pp->locallab.spots.at(index).medMethod == "33") { + medMethod->set_active(1); + } else if (pp->locallab.spots.at(index).medMethod == "55") { + medMethod->set_active(2); + } else if (pp->locallab.spots.at(index).medMethod == "77") { + medMethod->set_active(3); + } else if (pp->locallab.spots.at(index).medMethod == "99") { + medMethod->set_active(4); + } + } else { + medMethod->set_active(0); + } + + itera->setValue((double)pp->locallab.spots.at(index).itera); + guidbl->setValue((double)pp->locallab.spots.at(index).guidbl); + strbl->setValue((double)pp->locallab.spots.at(index).strbl); + epsbl->setValue((double)pp->locallab.spots.at(index).epsbl); + sensibn->setValue((double)pp->locallab.spots.at(index).sensibn); if (pp->locallab.spots.at(index).blurMethod == "norm") { blurMethod->set_active(0); @@ -2627,12 +5480,65 @@ void LocallabBlur::read(const rtengine::procparams::ProcParams* pp, const Params blurMethod->set_active(1); } + if (pp->locallab.spots.at(index).chroMethod == "lum") { + chroMethod->set_active(0); + } else if (pp->locallab.spots.at(index).chroMethod == "chr") { + chroMethod->set_active(1); + } else if (pp->locallab.spots.at(index).chroMethod == "all") { + chroMethod->set_active(2); + } + activlum->set_active(pp->locallab.spots.at(index).activlum); + enablMask->set_active(pp->locallab.spots.at(index).enablMask); + CCmaskblshape->setCurve(pp->locallab.spots.at(index).CCmaskblcurve); + LLmaskblshape->setCurve(pp->locallab.spots.at(index).LLmaskblcurve); + HHmaskblshape->setCurve(pp->locallab.spots.at(index).HHmaskblcurve); + + if (complexsoft < 2) { + strumaskbl->setValue(pp->locallab.spots.at(index).strumaskbl); + } else { + strumaskbl->setValue(0.); + } + + toolbl->set_active(pp->locallab.spots.at(index).toolbl); + blendmaskbl->setValue((double)pp->locallab.spots.at(index).blendmaskbl); + radmaskbl->setValue(pp->locallab.spots.at(index).radmaskbl); + + if (complexsoft == 0) { + lapmaskbl->setValue(pp->locallab.spots.at(index).lapmaskbl); + } else { + lapmaskbl->setValue(0.); + } + + chromaskbl->setValue(pp->locallab.spots.at(index).chromaskbl); + + if (complexsoft < 2) { + gammaskbl->setValue(pp->locallab.spots.at(index).gammaskbl); + slomaskbl->setValue(pp->locallab.spots.at(index).slomaskbl); + shadmaskbl->setValue((double)pp->locallab.spots.at(index).shadmaskbl); + } else { + gammaskbl->setValue(1.); + slomaskbl->setValue(0.); + shadmaskbl->setValue(0.); + } + + Lmaskblshape->setCurve(pp->locallab.spots.at(index).Lmaskblcurve); + + if (complexsoft == 0) { + LLmaskblshapewav->setCurve(pp->locallab.spots.at(index).LLmaskblcurvewav); + } else { + LLmaskblshapewav->reset(); + } + + csThresholdblur->setValue(pp->locallab.spots.at(index).csthresholdblur); } // Enable all listeners enableListener(); + // Update Blur & Noise GUI according to blMethod combobox state + updateBlurGUI(); + // Note: No need to manage pedited as batch mode is deactivated for Locallab } @@ -2641,15 +5547,41 @@ void LocallabBlur::write(rtengine::procparams::ProcParams* pp, ParamsEdited* ped const int index = pp->locallab.selspot; if (index < (int)pp->locallab.spots.size()) { - pp->locallab.spots.at(index).expsoft = exp->getEnabled(); - - pp->locallab.spots.at(index).visisoft = exp->get_visible(); - pp->locallab.spots.at(index).expblur = exp->getEnabled(); + pp->locallab.spots.at(index).visiblur = exp->get_visible(); + + if (blMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).blMethod = "blur"; + } else if (blMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).blMethod = "med"; + } else if (blMethod->get_active_row_number() == 2) { + pp->locallab.spots.at(index).blMethod = "guid"; + } + + pp->locallab.spots.at(index).fftwbl = fftwbl->get_active(); pp->locallab.spots.at(index).radius = radius->getValue(); pp->locallab.spots.at(index).strength = strength->getIntValue(); - pp->locallab.spots.at(index).sensibn = sensibn->getIntValue(); + pp->locallab.spots.at(index).isogr = isogr->getIntValue(); + pp->locallab.spots.at(index).strengr = strengr->getIntValue(); + pp->locallab.spots.at(index).scalegr = scalegr->getIntValue(); + if (medMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).medMethod = "none"; + } else if (medMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).medMethod = "33"; + } else if (medMethod->get_active_row_number() == 2) { + pp->locallab.spots.at(index).medMethod = "55"; + } else if (medMethod->get_active_row_number() == 3) { + pp->locallab.spots.at(index).medMethod = "77"; + } else if (medMethod->get_active_row_number() == 4) { + pp->locallab.spots.at(index).medMethod = "99"; + } + + pp->locallab.spots.at(index).itera = itera->getIntValue(); + pp->locallab.spots.at(index).guidbl = guidbl->getIntValue(); + pp->locallab.spots.at(index).strbl = strbl->getIntValue(); + pp->locallab.spots.at(index).epsbl = epsbl->getIntValue(); + pp->locallab.spots.at(index).sensibn = sensibn->getIntValue(); if (blurMethod->get_active_row_number() == 0) { pp->locallab.spots.at(index).blurMethod = "norm"; @@ -2657,7 +5589,31 @@ void LocallabBlur::write(rtengine::procparams::ProcParams* pp, ParamsEdited* ped pp->locallab.spots.at(index).blurMethod = "inv"; } + if (chroMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).chroMethod = "lum"; + } else if (chroMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).chroMethod = "chr"; + } else if (chroMethod->get_active_row_number() == 2) { + pp->locallab.spots.at(index).chroMethod = "all"; + } + pp->locallab.spots.at(index).activlum = activlum->get_active(); + pp->locallab.spots.at(index).enablMask = enablMask->get_active(); + pp->locallab.spots.at(index).LLmaskblcurve = LLmaskblshape->getCurve(); + pp->locallab.spots.at(index).CCmaskblcurve = CCmaskblshape->getCurve(); + pp->locallab.spots.at(index).HHmaskblcurve = HHmaskblshape->getCurve(); + pp->locallab.spots.at(index).strumaskbl = strumaskbl->getValue(); + pp->locallab.spots.at(index).toolbl = toolbl->get_active(); + pp->locallab.spots.at(index).blendmaskbl = blendmaskbl->getIntValue(); + pp->locallab.spots.at(index).radmaskbl = radmaskbl->getValue(); + pp->locallab.spots.at(index).lapmaskbl = lapmaskbl->getValue(); + pp->locallab.spots.at(index).chromaskbl = chromaskbl->getValue(); + pp->locallab.spots.at(index).gammaskbl = gammaskbl->getValue(); + pp->locallab.spots.at(index).slomaskbl = slomaskbl->getValue(); + pp->locallab.spots.at(index).shadmaskbl = shadmaskbl->getIntValue(); + pp->locallab.spots.at(index).Lmaskblcurve = Lmaskblshape->getCurve(); + pp->locallab.spots.at(index).LLmaskblcurvewav = LLmaskblshapewav->getCurve(); + pp->locallab.spots.at(index).csthresholdblur = csThresholdblur->getValue(); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -2670,10 +5626,26 @@ void LocallabBlur::setDefaults(const rtengine::procparams::ProcParams* defParams if (index < (int)defParams->locallab.spots.size()) { const LocallabParams::LocallabSpot defSpot = defParams->locallab.spots.at(index); - // Set default value for adjuster widgets + // Set default value for adjuster and threshold adjuster widgets radius->setDefault(defSpot.radius); strength->setDefault((double)defSpot.strength); + isogr->setDefault((double)defSpot.isogr); + strengr->setDefault((double)defSpot.strengr); + scalegr->setDefault((double)defSpot.scalegr); + itera->setDefault((double)defSpot.itera); + guidbl->setDefault((double)defSpot.guidbl); + strbl->setDefault((double)defSpot.strbl); + epsbl->setDefault((double)defSpot.epsbl); sensibn->setDefault((double)defSpot.sensibn); + strumaskbl->setDefault(defSpot.strumaskbl); + blendmaskbl->setDefault((double)defSpot.blendmaskbl); + radmaskbl->setDefault(defSpot.radmaskbl); + lapmaskbl->setDefault(defSpot.lapmaskbl); + chromaskbl->setDefault(defSpot.chromaskbl); + gammaskbl->setDefault(defSpot.gammaskbl); + slomaskbl->setDefault(defSpot.slomaskbl); + shadmaskbl->setDefault(defSpot.shadmaskbl); + csThresholdblur->setDefault(defSpot.csthresholdblur); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -2696,12 +5668,167 @@ void LocallabBlur::adjusterChanged(Adjuster* a, double newval) } } + if (a == isogr) { + if (listener) { + listener->panelChanged(Evlocallabisogr, + isogr->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strengr) { + if (listener) { + listener->panelChanged(Evlocallabstrengr, + strengr->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == scalegr) { + if (listener) { + listener->panelChanged(Evlocallabscalegr, + scalegr->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == itera) { + if (listener) { + listener->panelChanged(Evlocallabitera, + itera->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == guidbl) { + if (listener) { + listener->panelChanged(Evlocallabguidbl, + guidbl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strbl) { + if (listener) { + listener->panelChanged(Evlocallabstrbl, + strbl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == epsbl) { + if (listener) { + listener->panelChanged(Evlocallabepsbl, + epsbl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + if (a == sensibn) { if (listener) { listener->panelChanged(Evlocallabsensibn, sensibn->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } + + if (a == strumaskbl) { + if (listener) { + listener->panelChanged(Evlocallabstrumaskbl, + strumaskbl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blendmaskbl) { + if (listener) { + listener->panelChanged(Evlocallabblendmaskbl, + blendmaskbl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == radmaskbl) { + if (listener) { + listener->panelChanged(Evlocallabradmaskbl, + radmaskbl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == lapmaskbl) { + if (listener) { + listener->panelChanged(Evlocallablapmaskbl, + lapmaskbl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chromaskbl) { + if (listener) { + listener->panelChanged(Evlocallabchromaskbl, + chromaskbl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == gammaskbl) { + if (listener) { + listener->panelChanged(Evlocallabgammaskbl, + gammaskbl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == slomaskbl) { + if (listener) { + listener->panelChanged(Evlocallabslomaskbl, + slomaskbl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == shadmaskbl) { + if (listener) { + listener->panelChanged(Evlocallabshadmaskbl, + shadmaskbl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabBlur::adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabcsThresholdblur, + csThresholdblur->getHistoryString() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +void LocallabBlur::curveChanged(CurveEditor* ce) +{ + if (isLocActivated && exp->getEnabled()) { + if (ce == CCmaskblshape) { + if (listener) { + listener->panelChanged(EvlocallabCCmaskblshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == LLmaskblshape) { + if (listener) { + listener->panelChanged(EvlocallabLLmaskblshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == HHmaskblshape) { + if (listener) { + listener->panelChanged(EvlocallabHHmaskblshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == Lmaskblshape) { + if (listener) { + listener->panelChanged(EvlocallabLmaskblshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == LLmaskblshapewav) { + if (listener) { + listener->panelChanged(EvlocallabLLmaskblshapewav, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } } } @@ -2720,6 +5847,60 @@ void LocallabBlur::enabledChanged() } } +void LocallabBlur::updateMaskBackground(const double normChromar, const double normLumar, const double normHuer) +{ + idle_register.add( + [this, normHuer, normLumar, normChromar]() -> bool { + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected + + // Update mask background + CCmaskblshape->updateLocallabBackground(normChromar); + LLmaskblshape->updateLocallabBackground(normLumar); + HHmaskblshape->updateLocallabBackground(normHuer); + + return false; + } + ); +} + +void LocallabBlur::blMethodChanged() +{ + // Update Blur & Noise GUI according to blMethod combobox state + updateBlurGUI(); + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabblMethod, + blMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +void LocallabBlur::fftwblChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (fftwbl->get_active()) { + listener->panelChanged(Evlocallabfftwbl, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabfftwbl, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabBlur::medMethodChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabmedMethod, + medMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + void LocallabBlur::blurMethodChanged() { if (isLocActivated && exp->getEnabled()) { @@ -2730,6 +5911,16 @@ void LocallabBlur::blurMethodChanged() } } +void LocallabBlur::chroMethodChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabchroMethod, + chroMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + void LocallabBlur::activlumChanged() { if (isLocActivated && exp->getEnabled()) { @@ -2744,3 +5935,83 @@ void LocallabBlur::activlumChanged() } } } + +void LocallabBlur::showmaskblMethodChanged() +{ + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskMethod, ""); + } +} + +void LocallabBlur::enablMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enablMask->get_active()) { + listener->panelChanged(EvLocallabEnablMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnablMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabBlur::toolblChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (toolbl->get_active()) { + listener->panelChanged(Evlocallabtoolbl, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabtoolbl, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabBlur::updateBlurGUI() +{ + if (blMethod->get_active_row_number() == 0) { + fftwbl->show(); + radius->show(); + strength->show(); + grainFrame->show(); + medMethod->hide(); + itera->hide(); + guidbl->hide(); + strbl->hide(); + epsbl->hide(); + activlum->show(); + } else if (blMethod->get_active_row_number() == 1) { + fftwbl->hide(); + radius->hide(); + strength->hide(); + grainFrame->hide(); + medMethod->show(); + itera->show(); + guidbl->hide(); + strbl->hide(); + epsbl->hide(); + activlum->show(); + } else if (blMethod->get_active_row_number() == 2) { + fftwbl->hide(); + radius->hide(); + strength->hide(); + grainFrame->hide(); + medMethod->hide(); + itera->hide(); + guidbl->show(); + strbl->show(); + epsbl->show(); + activlum->hide(); + } +} diff --git a/rtgui/locallabtools.h b/rtgui/locallabtools.h index 49edc4321..df194cc24 100644 --- a/rtgui/locallabtools.h +++ b/rtgui/locallabtools.h @@ -25,6 +25,8 @@ #include "curveeditor.h" #include "labgrid.h" #include "thresholdadjuster.h" +#include "toolpanel.h" +#include "adjuster.h" /* ==== LocallabToolListener ==== */ class LocallabTool; @@ -47,15 +49,7 @@ class LocallabTool: public AdjusterListener { protected: - // Enumeration to manage mask type - enum maskType { - MaskNone = 0, - MaskNormal = 1, - MaskWithTrMap = 2 - }; - // LocallabTool parameters - const maskType useMask; bool isLocActivated; Glib::ustring spotName; LocallabToolListener* locToolListener; @@ -63,28 +57,13 @@ protected: // LocallabTool generic widgets MyExpander* exp; - // Mask widgets - MyExpander* maskExp; - Gtk::CheckButton* enaMask; - Gtk::CheckButton* enaMaskTrMap; - MyComboBoxText* showMaskMethod; - CurveEditorGroup* maskCurveEditorG; - FlatCurveEditor* CCMaskShape; - FlatCurveEditor* LLMaskShape; - FlatCurveEditor* HHMaskShape; - Adjuster* blendMask; - Adjuster* radMask; - Adjuster* chroMask; - Adjuster* gamMask; - Adjuster* sloMask; - sigc::connection enaExpConn, enaMaskConn, enaMaskTrMapConn, showMaskMethodConn; + sigc::connection enaExpConn; -private: IdleRegister idle_register; public: // Locallab tool constructor/destructor - LocallabTool(Gtk::Box* content, Glib::ustring toolName, Glib::ustring UILabel, bool need11 = false, maskType usemask = MaskNone); + LocallabTool(Gtk::Box* content, Glib::ustring toolName, Glib::ustring UILabel, bool need11 = false); virtual ~LocallabTool(); // Getter for Locallab tool expander @@ -128,18 +107,19 @@ public: bool isLocallabToolAdded(); // Mask background management function - void refChanged(const double huer, const double lumar, const double chromar); + void refChanged(const double huer, const double lumar, const double chromar); // Make it virtual // Mask preview functions - void resetMaskView(); - virtual void getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask) {}; + virtual void resetMaskView() {}; + virtual void getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask) {}; - /* To be completed - Notes: - - parent class functions shall be called when using mask - - callerId #1 and #2 are reserved for mask curve color management + /* Notes: + - callerId #1: Mask CC shape (bottom bar) + Color CC/LC shape (left bar) + - callerId #2: Mask HH shape (main curve and bottom bar) + - callerId #3: Color LH/HH shape (main curve) + - callerId #4: Color CC/LC shape (bottom bar) */ - virtual void colorForValue(double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + void colorForValue(double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); // To be implemented virtual void disableListener(); @@ -148,13 +128,11 @@ public: virtual void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) {}; virtual void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) {}; virtual void adjusterChanged(Adjuster* a, double newval) {}; // At least when using mask - virtual void curveChanged(CurveEditor* ce) {}; // At least when using mask + virtual void curveChanged(CurveEditor* ce) {}; // At least when using curve protected: // To be implemented - virtual void enaMaskChanged() {}; // Only necessary when using mask - virtual void enaMaskTrMapChanged() {}; // Only necessary when using mask with transmission map - virtual void showMaskMethodChanged() {}; // Only necessary when using mask + virtual void updateMaskBackground(const double normChromar, const double normLumar, const double normHuer) {}; // Only necessary when using mask private: // Remove button event function @@ -170,7 +148,8 @@ private: /* ==== LocallabColor ==== */ class LocallabColor: public Gtk::VBox, - public LocallabTool + public LocallabTool, + public ThresholdAdjusterListener { private: // Color & Light specific widgets @@ -186,16 +165,66 @@ private: Adjuster* const structcol; Adjuster* const blurcolde; Adjuster* const softradiuscol; + Gtk::CheckButton* const invers; + MyExpander* const expgradcol; + Adjuster* const strcol; + Adjuster* const strcolab; + Adjuster* const strcolh; + Adjuster* const angcol; Gtk::Label* const labqualcurv; MyComboBoxText* const qualitycurveMethod; CurveEditorGroup* const llCurveEditorG; - DiagonalCurveEditor* llshape; - DiagonalCurveEditor* ccshape; + DiagonalCurveEditor* const llshape; + DiagonalCurveEditor* const ccshape; + CurveEditorGroup* const clCurveEditorG; + DiagonalCurveEditor* const clshape; + DiagonalCurveEditor* const lcshape; CurveEditorGroup* const HCurveEditorG; - FlatCurveEditor* LHshape; - FlatCurveEditor* HHshape; - Gtk::CheckButton* const invers; - sigc::connection curvactivConn, gridMethodConn, qualitycurveMethodConn, inversConn; + FlatCurveEditor* const LHshape; + CurveEditorGroup* const H2CurveEditorG; + FlatCurveEditor* const HHshape; + CurveEditorGroup* const rgbCurveEditorG; + MyComboBoxText* const toneMethod; + DiagonalCurveEditor* const rgbshape; + Gtk::CheckButton* const special; + MyExpander* const expmaskcol1; + MyComboBoxText* const merMethod; + ToolParamBlock* const mask7; + MyComboBoxText* const mergecolMethod; + Adjuster* const mercol; + Adjuster* const opacol; + Adjuster* const conthrcol; + Gtk::Frame* const gridmerFrame; + LabGrid* const labgridmerg; + Adjuster* const merlucol; + MyComboBoxText* const showmaskcolMethod; + MyComboBoxText* const showmaskcolMethodinv; + Gtk::CheckButton* const enaColorMask; + CurveEditorGroup* const maskCurveEditorG; + FlatCurveEditor* const CCmaskshape; + FlatCurveEditor* const LLmaskshape; + FlatCurveEditor* const HHmaskshape; + Adjuster* const strumaskcol; + Gtk::CheckButton* const toolcol; + Gtk::CheckButton* const fftColorMask; + Adjuster* const contcol; + Adjuster* const blurcol; + Adjuster* const blendmaskcol; + Adjuster* const radmaskcol; + Adjuster* const lapmaskcol; + Adjuster* const chromaskcol; + Adjuster* const gammaskcol; + Adjuster* const slomaskcol; + Adjuster* const shadmaskcol; + CurveEditorGroup* const maskHCurveEditorG; + FlatCurveEditor* const HHhmaskshape; + CurveEditorGroup* const mask2CurveEditorG; + DiagonalCurveEditor* const Lmaskshape; + CurveEditorGroup* const mask2CurveEditorGwav; + FlatCurveEditor* const LLmaskcolshapewav; + ThresholdAdjuster* const csThresholdcol; + + sigc::connection curvactivConn, gridMethodConn, inversConn, qualitycurveMethodConn, toneMethodConn, specialConn, merMethodConn, mergecolMethodConn, showmaskcolMethodConn, showmaskcolMethodConninv, enaColorMaskConn, toolcolConn, fftColorMaskConn; public: LocallabColor(); @@ -203,9 +232,8 @@ public: void setListener(ToolPanelListener* tpl); - void getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask); - - void colorForValue(double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + void resetMaskView(); + void getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask); void disableListener(); void enableListener(); @@ -213,20 +241,35 @@ public: void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); void adjusterChanged(Adjuster* a, double newval); + void adjusterChanged(ThresholdAdjuster* a, double newBottom, double newTop) {}; // Not used + void adjusterChanged(ThresholdAdjuster* a, double newBottomLeft, double newTopLeft, double newBottomRight, double newTopRight) {}; // Not used + void adjusterChanged(ThresholdAdjuster* a, int newBottom, int newTop) {}; // Not used + void adjusterChanged(ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) {}; // Not used + void adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR); void curveChanged(CurveEditor* ce); private: void enabledChanged(); - void enaMaskChanged(); - void showMaskMethodChanged(); + void updateMaskBackground(const double normChromar, const double normLumar, const double normHuer); void curvactivChanged(); + void gridMethodChanged(); void inversChanged(); void qualitycurveMethodChanged(); - void gridMethodChanged(); + void toneMethodChanged(); + void specialChanged(); + void merMethodChanged(); + void mergecolMethodChanged(); + void showmaskcolMethodChanged(); + void showmaskcolMethodChangedinv(); + void enaColorMaskChanged(); + void toolcolChanged(); + void fftColorMaskChanged(); - void updateColorGUI(); + void updateColorGUI1(); + void updateColorGUI2(); + void updateColorGUI3(); }; /* ==== LocallabExposure ==== */ @@ -235,33 +278,67 @@ class LocallabExposure: public LocallabTool { private: + // Exposure specific widgets MyComboBoxText* const expMethod; Gtk::Frame* const pdeFrame; Adjuster* const laplacexp; Adjuster* const linear; Adjuster* const balanexp; - Adjuster* const expcomp; - Adjuster* const hlcompr; - Adjuster* const hlcomprthresh; - Adjuster* const black; - Adjuster* const shadex; - Adjuster* const shcompr; - Adjuster* const expchroma; - Adjuster* const warm; + Adjuster* const gamm; + Gtk::HBox* const ctboxexpmethod; + MyComboBoxText* const exnoiseMethod; + Gtk::Frame* const fatFrame; + Adjuster* const fatamount; + Adjuster* const fatdetail; + Adjuster* const fatlevel; + Adjuster* const fatanchor; Adjuster* const sensiex; Adjuster* const structexp; Adjuster* const blurexpde; - Adjuster* const softradiusexp; + MyExpander* const exptoolexp; + Adjuster* const expcomp; + Adjuster* const black; + Adjuster* const hlcompr; + Adjuster* const hlcomprthresh; + Adjuster* const shadex; + Adjuster* const shcompr; + Adjuster* const expchroma; CurveEditorGroup* const curveEditorG; DiagonalCurveEditor* shapeexpos; + MyExpander* const expgradexp; + Adjuster* const strexp; + Adjuster* const angexp; + Adjuster* const softradiusexp; Gtk::CheckButton* const inversex; - sigc::connection expMethodConn, inversexConn; + MyExpander* const expmaskexp; + MyComboBoxText* const showmaskexpMethod; + MyComboBoxText* const showmaskexpMethodinv; + Gtk::CheckButton* const enaExpMask; + Gtk::CheckButton* const enaExpMaskaft; + CurveEditorGroup* const maskexpCurveEditorG; + FlatCurveEditor* const CCmaskexpshape; + FlatCurveEditor* const LLmaskexpshape; + FlatCurveEditor* const HHmaskexpshape; + Adjuster* const blendmaskexp; + Adjuster* const radmaskexp; + Adjuster* const lapmaskexp; + Adjuster* const chromaskexp; + Adjuster* const gammaskexp; + Adjuster* const slomaskexp; + Gtk::Frame* const gradFramemask; + Adjuster* const strmaskexp; + Adjuster* const angmaskexp; + CurveEditorGroup* const mask2expCurveEditorG; + DiagonalCurveEditor* const Lmaskexpshape; + + sigc::connection expMethodConn, exnoiseMethodConn, inversexConn, showmaskexpMethodConn, showmaskexpMethodConninv, enaExpMaskConn, enaExpMaskaftConn; public: LocallabExposure(); ~LocallabExposure(); - void getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask); + void resetMaskView(); + void getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask); void disableListener(); void enableListener(); @@ -274,11 +351,15 @@ public: private: void enabledChanged(); - void enaMaskChanged(); - void showMaskMethodChanged(); + void updateMaskBackground(const double normChromar, const double normLumar, const double normHuer); void expMethodChanged(); + void exnoiseMethodChanged(); void inversexChanged(); + void showmaskexpMethodChanged(); + void showmaskexpMethodChangedinv(); + void enaExpMaskChanged(); + void enaExpMaskaftChanged(); void updateExposureGUI1(); void updateExposureGUI2(); @@ -291,6 +372,10 @@ class LocallabShadow: public LocallabTool { private: + // Shadow highlight specific widgets + MyComboBoxText* const shMethod; + const std::array multipliersh; + Adjuster* const detailSH; Adjuster* const highlights; Adjuster* const h_tonalwidth; Adjuster* const shadows; @@ -298,13 +383,41 @@ private: Adjuster* const sh_radius; Adjuster* const sensihs; Adjuster* const blurSHde; + Gtk::Frame* const gamFrame; + Adjuster* const gamSH; + Adjuster* const sloSH; + MyExpander* const expgradsh; + Adjuster* const strSH; + Adjuster* const angSH; Gtk::CheckButton* const inverssh; - sigc::connection inversshConn; + MyExpander* const expmasksh; + MyComboBoxText* const showmaskSHMethod; + MyComboBoxText* const showmaskSHMethodinv; + Gtk::CheckButton* const enaSHMask; + CurveEditorGroup* const maskSHCurveEditorG; + FlatCurveEditor* const CCmaskSHshape; + FlatCurveEditor* const LLmaskSHshape; + FlatCurveEditor* const HHmaskSHshape; + Adjuster* const blendmaskSH; + Adjuster* const radmaskSH; + Adjuster* const lapmaskSH; + Adjuster* const chromaskSH; + Adjuster* const gammaskSH; + Adjuster* const slomaskSH; + CurveEditorGroup* const mask2SHCurveEditorG; + DiagonalCurveEditor* const LmaskSHshape; + Gtk::Frame* const fatSHFrame; + Adjuster* const fatamountSH; + Adjuster* const fatanchorSH; + + sigc::connection shMethodConn, inversshConn, showmaskSHMethodConn, showmaskSHMethodConninv, enaSHMaskConn; public: LocallabShadow(); + ~LocallabShadow(); - void getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask); + void resetMaskView(); + void getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask); void disableListener(); void enableListener(); @@ -317,12 +430,16 @@ public: private: void enabledChanged(); - void enaMaskChanged(); - void showMaskMethodChanged(); + void updateMaskBackground(const double normChromar, const double normLumar, const double normHuer); + void shMethodChanged(); void inversshChanged(); + void showmaskSHMethodChanged(); + void showmaskSHMethodChangedinv(); + void enaSHMaskChanged(); - void updateShadowGUI(); + void updateShadowGUI1(); + void updateShadowGUI2(); }; /* ==== LocallabVibrance ==== */ @@ -333,41 +450,71 @@ class LocallabVibrance: public ThresholdCurveProvider { private: + // Vibrance specific widgets Adjuster* const saturated; Adjuster* const pastels; + Adjuster* const warm; ThresholdAdjuster* const psThreshold; Gtk::CheckButton* const protectSkins; Gtk::CheckButton* const avoidColorShift; Gtk::CheckButton* const pastSatTog; Adjuster* const sensiv; CurveEditorGroup* const curveEditorGG; - DiagonalCurveEditor* skinTonesCurve; - sigc::connection pskinsConn, ashiftConn, pastsattogConn; + DiagonalCurveEditor* const skinTonesCurve; + MyExpander* const expgradvib; + Adjuster* const strvib; + Adjuster* const strvibab; + Adjuster* const strvibh; + Adjuster* const angvib; + MyExpander* const expmaskvib; + MyComboBoxText* const showmaskvibMethod; + Gtk::CheckButton* const enavibMask; + CurveEditorGroup* const maskvibCurveEditorG; + FlatCurveEditor* const CCmaskvibshape; + FlatCurveEditor* const LLmaskvibshape; + FlatCurveEditor* const HHmaskvibshape; + Adjuster* const blendmaskvib; + Adjuster* const radmaskvib; + Adjuster* const lapmaskvib; + Adjuster* const chromaskvib; + Adjuster* const gammaskvib; + Adjuster* const slomaskvib; + CurveEditorGroup* const mask2vibCurveEditorG; + DiagonalCurveEditor* const Lmaskvibshape; + + sigc::connection pskinsConn, ashiftConn, pastsattogConn, showmaskvibMethodConn, enavibMaskConn; public: LocallabVibrance(); ~LocallabVibrance(); + void resetMaskView(); + void getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask); + void disableListener(); void enableListener(); void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); void adjusterChanged(Adjuster* a, double newval); - void adjusterChanged(ThresholdAdjuster* a, double newBottom, double newTop) {}; - void adjusterChanged(ThresholdAdjuster* a, double newBottomLeft, double newTopLeft, double newBottomRight, double newTopRight) {}; + void adjusterChanged(ThresholdAdjuster* a, double newBottom, double newTop) {}; // Not used + void adjusterChanged(ThresholdAdjuster* a, double newBottomLeft, double newTopLeft, double newBottomRight, double newTopRight) {}; // Not used void adjusterChanged(ThresholdAdjuster* a, int newBottom, int newTop); - void adjusterChanged(ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) {}; - void adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) {}; + void adjusterChanged(ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) {}; // Not used + void adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) {}; // Not used std::vector getCurvePoints(ThresholdSelector* tAdjuster) const; void curveChanged(CurveEditor* ce); private: void enabledChanged(); + void updateMaskBackground(const double normChromar, const double normLumar, const double normHuer); + void protectskins_toggled(); void avoidcolorshift_toggled(); void pastsattog_toggled(); + void showmaskvibMethodChanged(); + void enavibMaskChanged(); void updateVibranceGUI(); }; @@ -378,18 +525,21 @@ class LocallabSoft: public LocallabTool { private: + // Soft light specific widgets MyComboBoxText* const softMethod; Gtk::HBox* const ctboxsoftmethod; MyComboBoxText* const showmasksoftMethod; Adjuster* const streng; Adjuster* const laplace; Adjuster* const sensisf; + sigc::connection softMethodConn, showmasksoftMethodConn; public: LocallabSoft(); - void getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask); + void resetMaskView(); + void getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask); void disableListener(); void enableListener(); @@ -398,8 +548,6 @@ public: void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); void adjusterChanged(Adjuster* a, double newval); - void resetMaskView(); - private: void enabledChanged(); @@ -412,18 +560,59 @@ private: /* ==== LocallabBlur ==== */ class LocallabBlur: public Gtk::VBox, - public LocallabTool + public LocallabTool, + public ThresholdAdjusterListener { private: + // Blur & Noise specific widgets + MyComboBoxText* const blMethod; + Gtk::CheckButton* const fftwbl; Adjuster* const radius; Adjuster* const strength; + Gtk::Frame* const grainFrame; + Adjuster* const isogr; + Adjuster* const strengr; + Adjuster* const scalegr; + MyComboBoxText* const medMethod; + Adjuster* const itera; + Adjuster* const guidbl; + Adjuster* const strbl; + Adjuster* const epsbl; Adjuster* const sensibn; MyComboBoxText* const blurMethod; + MyComboBoxText* const chroMethod; Gtk::CheckButton* const activlum; - sigc::connection blurMethodConn, activlumConn; + MyExpander* const expmaskbl; + MyComboBoxText* const showmaskblMethod; + Gtk::CheckButton* const enablMask; + CurveEditorGroup* const maskblCurveEditorG; + FlatCurveEditor* const CCmaskblshape; + FlatCurveEditor* const LLmaskblshape; + FlatCurveEditor* const HHmaskblshape; + Adjuster* const strumaskbl; + Gtk::CheckButton* const toolbl; + Adjuster* const blendmaskbl; + Gtk::Frame* const toolblFrame; + Adjuster* const radmaskbl; + Adjuster* const lapmaskbl; + Adjuster* const chromaskbl; + Adjuster* const gammaskbl; + Adjuster* const slomaskbl; + Adjuster* const shadmaskbl; + CurveEditorGroup* const mask2blCurveEditorG; + DiagonalCurveEditor* const Lmaskblshape; + CurveEditorGroup* const mask2blCurveEditorGwav; + FlatCurveEditor* const LLmaskblshapewav; + ThresholdAdjuster* const csThresholdblur; + + sigc::connection blMethodConn, fftwblConn, medMethodConn, blurMethodConn, chroMethodConn, activlumConn, showmaskblMethodConn, enablMaskConn, toolblConn; public: LocallabBlur(); + ~LocallabBlur(); + + void resetMaskView(); + void getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask); void disableListener(); void enableListener(); @@ -431,12 +620,29 @@ public: void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); void adjusterChanged(Adjuster* a, double newval); + void adjusterChanged(ThresholdAdjuster* a, double newBottom, double newTop) {}; // Not used + void adjusterChanged(ThresholdAdjuster* a, double newBottomLeft, double newTopLeft, double newBottomRight, double newTopRight) {}; // Not used + void adjusterChanged(ThresholdAdjuster* a, int newBottom, int newTop) {}; // Not used + void adjusterChanged(ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) {}; // Not used + void adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR); + void curveChanged(CurveEditor* ce); private: void enabledChanged(); + void updateMaskBackground(const double normChromar, const double normLumar, const double normHuer); + + void blMethodChanged(); + void fftwblChanged(); + void medMethodChanged(); void blurMethodChanged(); + void chroMethodChanged(); void activlumChanged(); + void showmaskblMethodChanged(); + void enablMaskChanged(); + void toolblChanged(); + + void updateBlurGUI(); }; /* ==== LocallabTone ==== */ @@ -445,6 +651,7 @@ class LocallabTone: public LocallabTool { private: + // Tone Mapping specific widgets Adjuster* const amount; Adjuster* const stren; Gtk::CheckButton* const equiltm; @@ -455,12 +662,31 @@ private: Adjuster* const rewei; Adjuster* const softradiustm; Adjuster* const sensitm; - sigc::connection equiltmConn; + MyExpander* const expmasktm; + MyComboBoxText* const showmasktmMethod; + Gtk::CheckButton* const enatmMask; + Gtk::CheckButton* const enatmMaskaft; + CurveEditorGroup* const masktmCurveEditorG; + FlatCurveEditor* const CCmasktmshape; + FlatCurveEditor* const LLmasktmshape; + FlatCurveEditor* const HHmasktmshape; + Adjuster* const blendmasktm; + Adjuster* const lapmasktm; + Adjuster* const radmasktm; + Adjuster* const chromasktm; + Adjuster* const gammasktm; + Adjuster* const slomasktm; + CurveEditorGroup* const mask2tmCurveEditorG; + DiagonalCurveEditor* const Lmasktmshape; + + sigc::connection equiltmConn, showmasktmMethodConn, enatmMaskConn, enatmMaskaftConn; public: LocallabTone(); + ~LocallabTone(); - void getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask); + void resetMaskView(); + void getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask); void disableListener(); void enableListener(); @@ -473,10 +699,12 @@ public: private: void enabledChanged(); - void enaMaskChanged(); - void showMaskMethodChanged(); + void updateMaskBackground(const double normChromar, const double normLumar, const double normHuer); void equiltmChanged(); + void showmasktmMethodChanged(); + void enatmMaskChanged(); + void enatmMaskaftChanged(); }; /* ==== LocallabRetinex ==== */ @@ -485,30 +713,67 @@ class LocallabRetinex: public LocallabTool { private: + // Retinex specific widgets + Gtk::Frame* const dehaFrame; + Adjuster* const dehaz; + Adjuster* const depth; + Gtk::CheckButton* const lumonly; + Gtk::Frame* const retiFrame; + Adjuster* const str; + Gtk::CheckButton* const loglin; + Adjuster* const sensih; + Gtk::Frame* const retitoolFrame; + ToolParamBlock* const retiBox; MyComboBoxText* const retinexMethod; Gtk::CheckButton* const fftwreti; Gtk::CheckButton* const equilret; - Adjuster* const str; - Adjuster* const chrrt; Adjuster* const neigh; Adjuster* const vart; Adjuster* const scalereti; Adjuster* const limd; + Adjuster* const offs; + MyExpander* const expretitools; + Adjuster* const chrrt; Adjuster* const darkness; Adjuster* const lightnessreti; - Adjuster* const dehaz; + Adjuster* const cliptm; Adjuster* const softradiusret; - Adjuster* const sensih; + CurveEditorGroup* const LocalcurveEditortransT; + FlatCurveEditor* const cTtransshape; + Gtk::Label* const mMLabels; + Gtk::Label* const transLabels; + Gtk::Label* const transLabels2; CurveEditorGroup* const LocalcurveEditorgainT; - FlatCurveEditor* cTgainshape; + FlatCurveEditor* const cTgainshape; + MyExpander* const expmaskreti; + ToolParamBlock* const maskretiBox; + MyComboBoxText* const showmaskretiMethod; + Gtk::CheckButton* const enaretiMask; + Gtk::CheckButton* const enaretiMasktmap; + CurveEditorGroup* const maskretiCurveEditorG; + FlatCurveEditor* const CCmaskretishape; + FlatCurveEditor* const LLmaskretishape; + FlatCurveEditor* const HHmaskretishape; + Adjuster* const blendmaskreti; + Adjuster* const radmaskreti; + Adjuster* const lapmaskreti; + Adjuster* const chromaskreti; + Adjuster* const gammaskreti; + Adjuster* const slomaskreti; + CurveEditorGroup* const mask2retiCurveEditorG; + DiagonalCurveEditor* const Lmaskretishape; Gtk::CheckButton* const inversret; - sigc::connection retinexMethodConn, fftwretiConn, equilretConn, inversretConn; + + sigc::connection lumonlyConn, loglinConn, retinexMethodConn, fftwretiConn, equilretConn, showmaskretiMethodConn, enaretiMaskConn, enaretiMasktmapConn, inversretConn; public: LocallabRetinex(); ~LocallabRetinex(); - void getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask); + void updateMinMax(const double cdma, const double cdmin, const double mini, const double maxi, const double Tmean, const double Tsigma, const double Tmin, const double Tmax); + + void resetMaskView(); + void getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask); void disableListener(); void enableListener(); @@ -521,17 +786,21 @@ public: private: void enabledChanged(); - void enaMaskChanged(); - void enaMaskTrMapChanged(); - void showMaskMethodChanged(); + void updateMaskBackground(const double normChromar, const double normLumar, const double normHuer); + void lumonlyChanged(); + void loglinChanged(); void retinexMethodChanged(); void fftwretiChanged(); void equilretChanged(); + void showmaskretiMethodChanged(); + void enaretiMaskChanged(); + void enaretiMasktmapChanged(); void inversretChanged(); - void updateRetinexGUI(); + void updateRetinexGUI1(); void updateRetinexGUI2(); + void updateRetinexGUI3(); }; /* ==== LocallabSharp ==== */ @@ -548,11 +817,17 @@ private: Adjuster* const sharblur; Adjuster* const sensisha; Gtk::CheckButton* const inverssha; - sigc::connection inversshaConn; + Gtk::Frame* const sharFrame; + MyComboBoxText* const showmasksharMethod; + + sigc::connection inversshaConn, showmasksharMethodConn; public: LocallabSharp(); + void resetMaskView(); + void getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask); + void disableListener(); void enableListener(); void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); @@ -564,12 +839,14 @@ private: void enabledChanged(); void inversshaChanged(); + void showmasksharMethodChanged(); }; /* ==== LocallabContrast ==== */ class LocallabContrast: public Gtk::VBox, - public LocallabTool + public LocallabTool, + public ThresholdAdjusterListener { private: MyComboBoxText* const localcontMethod; @@ -578,32 +855,130 @@ private: Adjuster* const lcdarkness; Adjuster* const lclightness; CurveEditorGroup* const LocalcurveEditorwav; - FlatCurveEditor* wavshape; + FlatCurveEditor* const wavshape; Adjuster* const levelwav; + ThresholdAdjuster* const csThreshold; Adjuster* const residcont; + Adjuster* const residchro; Adjuster* const sensilc; + Gtk::Frame* const clariFrame; + Adjuster* const clarilres; + Adjuster* const claricres; + Adjuster* const clarisoft; + Gtk::CheckButton* const origlc; + MyExpander* const expcontrastpyr; + Gtk::Frame* const gradwavFrame; + Gtk::CheckButton* const wavgradl; + Adjuster* const strwav; + Adjuster* const angwav; + Gtk::Frame* const edgFrame; + Gtk::CheckButton* const wavedg; + ToolParamBlock* const edgsBox; + Adjuster* const strengthw; + CurveEditorGroup* const LocalcurveEditorwavedg; + FlatCurveEditor* const wavshapeedg; + Adjuster* const gradw; + Gtk::CheckButton* const waveshow; + ToolParamBlock* const edgsBoxshow; + Adjuster* const radiusw; + Adjuster* const detailw; + MyComboBoxText* const localedgMethod; + Adjuster* const tloww; + Adjuster* const thigw; + Adjuster* const edgw; + Adjuster* const basew; + Gtk::Label* const labmNP; + MyComboBoxText* const localneiMethod; + Gtk::Frame* const blurlevelFrame; + Gtk::CheckButton* const wavblur; + Adjuster* const levelblur; + Adjuster* const chromablu; + CurveEditorGroup* const LocalcurveEditorwavlev; + FlatCurveEditor* const wavshapelev; + Adjuster* const residblur; + Gtk::CheckButton* const blurlc; + MyExpander* const expcontrastpyr2; + Gtk::Frame* const contFrame; + Gtk::CheckButton* const wavcont; + Adjuster* const sigma; + Adjuster* const offset; + Adjuster* const chromalev; + CurveEditorGroup* const LocalcurveEditorwavcon; + FlatCurveEditor* const wavshapecon; + Gtk::Frame* const compreFrame; + Gtk::CheckButton* const wavcompre; + CurveEditorGroup* const LocalcurveEditorwavcompre; + FlatCurveEditor* const wavshapecompre; + Adjuster* const threswav; + Adjuster* const residcomp; + Gtk::Frame* const compFrame; + Gtk::CheckButton* const wavcomp; + Adjuster* const fatdet; + Adjuster* const fatanch; + CurveEditorGroup* const LocalcurveEditorwavcomp; + FlatCurveEditor* const wavshapecomp; + Adjuster* const fatres; Gtk::CheckButton* const fftwlc; - sigc::connection localcontMethodConn, fftwlcConn; + MyExpander* const expmasklc; + MyComboBoxText* const showmasklcMethod; + Gtk::CheckButton* const enalcMask; + CurveEditorGroup* const masklcCurveEditorG; + FlatCurveEditor* const CCmasklcshape; + FlatCurveEditor* const LLmasklcshape; + FlatCurveEditor* const HHmasklcshape; + Adjuster* const blendmasklc; + Adjuster* const radmasklc; + Adjuster* const chromasklc; + CurveEditorGroup* const mask2lcCurveEditorG; + DiagonalCurveEditor* const Lmasklcshape; + + sigc::connection localcontMethodConn, origlcConn, wavgradlConn, wavedgConn, localedgMethodConn, waveshowConn, localneiMethodConn, wavblurConn, blurlcConn, wavcontConn, wavcompreConn, wavcompConn, fftwlcConn, showmasklcMethodConn, enalcMaskConn; public: LocallabContrast(); ~LocallabContrast(); + void resetMaskView(); + void getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask); + void disableListener(); void enableListener(); void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); void adjusterChanged(Adjuster* a, double newval); + void adjusterChanged(ThresholdAdjuster* a, double newBottom, double newTop) {}; // Not used + void adjusterChanged(ThresholdAdjuster* a, double newBottomLeft, double newTopLeft, double newBottomRight, double newTopRight) {}; // Not used + void adjusterChanged(ThresholdAdjuster* a, int newBottom, int newTop) {}; // Not used + void adjusterChanged(ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) {}; // Not used + void adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR); void curveChanged(CurveEditor* ce); private: void enabledChanged(); - void localcontMethodChanged(); - void fftwlcChanged(); + void updateMaskBackground(const double normChromar, const double normLumar, const double normHuer); - void updateContrastGUI(); + void localcontMethodChanged(); + void origlcChanged(); + void wavgradlChanged(); + void wavedgChanged(); + void localedgMethodChanged(); + void waveshowChanged(); + void localneiMethodChanged(); + void wavblurChanged(); + void blurlcChanged(); + void wavcontChanged(); + void wavcompreChanged(); + void wavcompChanged(); + void fftwlcChanged(); + void showmasklcMethodChanged(); + void enalcMaskChanged(); + + void updateContrastGUI1(); + void updateContrastGUI2(); + void updateContrastGUI3(); + void updateContrastGUI4(); }; /* ==== LocallabCBDL ==== */ @@ -612,24 +987,45 @@ class LocallabCBDL: public LocallabTool { private: - Adjuster* multiplier[6]; + const std::array multiplier; Adjuster* const chromacbdl; Adjuster* const threshold; Adjuster* const blurcbdl; + Gtk::Frame* const residFrame; Adjuster* const clarityml; Adjuster* const contresid; Adjuster* const softradiuscb; Adjuster* const sensicb; + MyExpander* const expmaskcb; + MyComboBoxText* const showmaskcbMethod; + Gtk::CheckButton* const enacbMask; + CurveEditorGroup* const maskcbCurveEditorG; + FlatCurveEditor* const CCmaskcbshape; + FlatCurveEditor* const LLmaskcbshape; + FlatCurveEditor* const HHmaskcbshape; + Adjuster* const blendmaskcb; + Adjuster* const radmaskcb; + Adjuster* const lapmaskcb; + Adjuster* const chromaskcb; + Adjuster* const gammaskcb; + Adjuster* const slomaskcb; + CurveEditorGroup* const mask2cbCurveEditorG; + DiagonalCurveEditor* const Lmaskcbshape; + + sigc::connection showmaskcbMethodConn, enacbMaskConn; Gtk::Button* const lumacontrastMinusButton; Gtk::Button* const lumaneutralButton; Gtk::Button* const lumacontrastPlusButton; + sigc::connection lumacontrastMinusPressedConn, lumaneutralPressedConn, lumacontrastPlusPressedConn; public: LocallabCBDL(); + ~LocallabCBDL(); - void getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask); + void resetMaskView(); + void getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask); void disableListener(); void enableListener(); @@ -642,8 +1038,10 @@ public: private: void enabledChanged(); - void enaMaskChanged(); - void showMaskMethodChanged(); + void updateMaskBackground(const double normChromar, const double normLumar, const double normHuer); + + void showmaskcbMethodChanged(); + void enacbMaskChanged(); void lumacontrastMinusPressed(); void lumaneutralPressed(); @@ -656,6 +1054,8 @@ class LocallabDenoise: public LocallabTool { private: + CurveEditorGroup* const LocalcurveEditorwavden; + FlatCurveEditor* const wavshapeden; Adjuster* const noiselumf0; Adjuster* const noiselumf; Adjuster* const noiselumf2; @@ -665,20 +1065,69 @@ private: Adjuster* const noisechrof; Adjuster* const noisechroc; Adjuster* const noisechrodetail; + Adjuster* const detailthr; Adjuster* const adjblur; Adjuster* const bilateral; Adjuster* const sensiden; public: LocallabDenoise(); + ~LocallabDenoise(); void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); void adjusterChanged(Adjuster* a, double newval); + void curveChanged(CurveEditor* ce); private: void enabledChanged(); }; +/* ==== LocallabLog ==== */ +class LocallabLog: + public Gtk::VBox, + public LocallabTool +{ +private: + Gtk::Frame* const logPFrame; + Gtk::ToggleButton* const autocompute; + Adjuster* const blackEv; + Adjuster* const whiteEv; + Gtk::CheckButton* const fullimage; + Gtk::Frame* const logFrame; + Gtk::CheckButton* const Autogray; + Adjuster* const sourceGray; + Adjuster* const targetGray; + Adjuster* const detail; + Adjuster* const baselog; + Adjuster* const sensilog; + Gtk::Frame* const gradlogFrame; + Adjuster* const strlog; + Adjuster* const anglog; + + sigc::connection autoconn, fullimageConn, AutograyConn; + +public: + LocallabLog(); + + void disableListener(); + void enableListener(); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void adjusterChanged(Adjuster* a, double newval); + + void updateAutocompute(const float blackev, const float whiteev, const float sourceg, const float targetg); + +private: + void enabledChanged(); + + void autocomputeToggled(); + void fullimageChanged(); + void AutograyChanged(); + + void updateLogGUI(); +}; + #endif diff --git a/rtgui/locallabtools2.cc b/rtgui/locallabtools2.cc index 00c73947b..9f5a23767 100644 --- a/rtgui/locallabtools2.cc +++ b/rtgui/locallabtools2.cc @@ -22,12 +22,14 @@ #include "options.h" #include "../rtengine/procparams.h" +#include "locallab.h" +#include "rtimage.h" #define MINCHRO 0. -#define MAXCHRO 150 -#define MAXCHROCC 100 -#define MINNEIGH 4 -#define MAXNEIGH 5000 +#define MAXCHRO 150. +#define MAXCHROCC 100. +#define MINNEIGH 0.1 +#define MAXNEIGH 1500 #define CENTERNEIGH 200 using namespace rtengine; @@ -40,13 +42,13 @@ static double retiSlider2neigh(double sval) // Slider range: 0 - 5000 double neigh; - if (sval <= 1000) { + if (sval <= 200) { // Linear below center-temp - neigh = MINNEIGH + (sval / 1000.0) * (CENTERNEIGH - MINNEIGH); + neigh = MINNEIGH + (sval / 200.0) * (CENTERNEIGH - MINNEIGH); } else { const double slope = (double)(CENTERNEIGH - MINNEIGH) / (MAXNEIGH - CENTERNEIGH); - double x = (sval - 1000) / 1000; // x 0..1 - double y = x * slope + (1.0 - slope) * pow(x, 4.0); + const double x = (sval - 200) / 200; // x range: 0 - 1 + const double y = x * slope + (1.0 - slope) * pow(x, 4.0); neigh = CENTERNEIGH + y * (MAXNEIGH - CENTERNEIGH); } @@ -66,11 +68,11 @@ static double retiNeigh2Slider(double neigh) double sval; if (neigh <= CENTERNEIGH) { - sval = ((neigh - MINNEIGH) / (CENTERNEIGH - MINNEIGH)) * 1000.0; + sval = ((neigh - MINNEIGH) / (CENTERNEIGH - MINNEIGH)) * 200.0; } else { const double slope = (double)(CENTERNEIGH - MINNEIGH) / (MAXNEIGH - CENTERNEIGH); const double y = (neigh - CENTERNEIGH) / (MAXNEIGH - CENTERNEIGH); - double x = pow(y, 0.25); // rough guess of x, will be a little lower + double x = pow(y, 0.25); // Rough guess of x, will be a little lower double k = 0.1; bool add = true; @@ -79,7 +81,7 @@ static double retiNeigh2Slider(double neigh) for (;;) { double y1 = x * slope + (1.0 - slope) * pow(x, 4.0); - if (1000 * fabs(y1 - y) < 0.1) { + if (200 * fabs(y1 - y) < 0.1) { break; } @@ -100,15 +102,15 @@ static double retiNeigh2Slider(double neigh) } } - sval = 1000.0 + x * 1000.0; + sval = 200.0 + x * 200.0; } - if (sval < 0) { - sval = 0; + if (sval < 0.) { + sval = 0.; } - if (sval > 5000) { - sval = 5000; + if (sval > 1500.) { + sval = 1500.; } return sval; @@ -116,7 +118,7 @@ static double retiNeigh2Slider(double neigh) /* ==== LocallabTone ==== */ LocallabTone::LocallabTone(): - LocallabTool(this, M("TP_LOCALLAB_TONE_TOOLNAME"), M("TP_LOCALLAB_TM"), true, MaskNormal), + LocallabTool(this, M("TP_LOCALLAB_TONE_TOOLNAME"), M("TP_LOCALLAB_TM"), true), // Tone mapping specific widgets amount(Gtk::manage(new Adjuster(M("TP_LOCALLAB_AMOUNT"), 50., 100.0, 0.5, 95.))), @@ -124,14 +126,34 @@ LocallabTone::LocallabTone(): equiltm(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_EQUIL")))), gamma(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAM"), 0.4, 4.0, 0.11, 1.0))), satur(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SATUR"), -100., 100., 0.1, 0.))), // By default satur = 0 ==> use Mantiuk value - estop(Gtk::manage(new Adjuster(M("TP_LOCALLAB_ESTOP"), 0.1, 4.0, 0.01, 0.5))), - scaltm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SCALTM"), 0.1, 10.0, 0.01, 4.0))), + estop(Gtk::manage(new Adjuster(M("TP_LOCALLAB_ESTOP"), 0.1, 4., 0.01, 1.4))), + scaltm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SCALTM"), 0.1, 10.0, 0.01, 1.0))), rewei(Gtk::manage(new Adjuster(M("TP_LOCALLAB_REWEI"), 0, 3, 1, 0))), - softradiustm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.1, 0.))), - sensitm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))) + softradiustm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), -10.0, 1000.0, 0.1, 0.))), + sensitm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))), + expmasktm(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWT")))), + showmasktmMethod(Gtk::manage(new MyComboBoxText())), + enatmMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), + enatmMaskaft(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_AFTER_MASK")))), + masktmCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), + CCmasktmshape(static_cast(masktmCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false))), + LLmasktmshape(static_cast(masktmCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false))), + HHmasktmshape(static_cast(masktmCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true))), + blendmasktm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), + lapmasktm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPMASKCOL"), 0.0, 100.0, 0.1, 0.))), + radmasktm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), -10.0, 1000.0, 0.1, 0.))), + chromasktm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), + gammasktm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.05, 5.0, 0.01, 1.))), + slomasktm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), + mask2tmCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), + Lmasktmshape(static_cast(mask2tmCurveEditorG->addCurve(CT_Diagonal, "L(L)"))) { const bool showtooltip = options.showtooltip; + const int complexsoft = options.complexity; + const LocallabParams::LocallabSpot defSpot; + + // Parameter Tone Mapping specific widgets if (showtooltip) { exp->set_tooltip_text(M("TP_LOCALLAB_TONEMAP_TOOLTIP")); } @@ -160,6 +182,7 @@ LocallabTone::LocallabTone(): rewei->set_tooltip_text(M("TP_LOCALLAB_TONEMAPESTOP_TOOLTIP")); } + softradiustm->setLogScale(10, -10); softradiustm->setAdjusterListener(this); sensitm->setAdjusterListener(this); @@ -168,21 +191,153 @@ LocallabTone::LocallabTone(): sensitm->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); } + setExpandAlignProperties(expmasktm, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + if (showtooltip) { + expmasktm->set_tooltip_markup(M("TP_LOCALLAB_MASK_TOOLTIP")); + } + + showmasktmMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmasktmMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showmasktmMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); + showmasktmMethod->append(M("TP_LOCALLAB_SHOWMASK")); + showmasktmMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); + showmasktmMethod->set_active(0); + + if (showtooltip) { + showmasktmMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmasktmMethodConn = showmasktmMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabTone::showmasktmMethodChanged)); + + enatmMaskConn = enatmMask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabTone::enatmMaskChanged)); + + enatmMaskaftConn = enatmMaskaft->signal_toggled().connect(sigc::mem_fun(*this, &LocallabTone::enatmMaskaftChanged)); + + masktmCurveEditorG->setCurveListener(this); + + CCmasktmshape->setIdentityValue(0.); + CCmasktmshape->setResetCurve(FlatCurveType(defSpot.CCmasktmcurve.at(0)), defSpot.CCmasktmcurve); + + if (showtooltip) { + CCmasktmshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + CCmasktmshape->setBottomBarColorProvider(this, 1); + + LLmasktmshape->setIdentityValue(0.); + LLmasktmshape->setResetCurve(FlatCurveType(defSpot.LLmasktmcurve.at(0)), defSpot.LLmasktmcurve); + + if (showtooltip) { + LLmasktmshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + LLmasktmshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + HHmasktmshape->setIdentityValue(0.); + HHmasktmshape->setResetCurve(FlatCurveType(defSpot.HHmasktmcurve.at(0)), defSpot.HHmasktmcurve); + + if (showtooltip) { + HHmasktmshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + HHmasktmshape->setCurveColorProvider(this, 2); + HHmasktmshape->setBottomBarColorProvider(this, 2); + + masktmCurveEditorG->curveListComplete(); + + blendmasktm->setAdjusterListener(this); + + lapmasktm->setAdjusterListener(this); + + if (showtooltip) { + lapmasktm->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + radmasktm->setLogScale(10, -10); + radmasktm->setAdjusterListener(this); + + if (showtooltip) { + radmasktm->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + chromasktm->setAdjusterListener(this); + + gammasktm->setAdjusterListener(this); + + slomasktm->setAdjusterListener(this); + + mask2tmCurveEditorG->setCurveListener(this); + Lmasktmshape->setResetCurve(DiagonalCurveType(defSpot.Lmasktmcurve.at(0)), defSpot.Lmasktmcurve); + + if (showtooltip) { + Lmasktmshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + } + + Lmasktmshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + Lmasktmshape->setLeftBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + mask2tmCurveEditorG->curveListComplete(); + + // Add Tone Mapping specific widgets to GUI // pack_start(*amount); // To use if we change transit_shapedetect parameters pack_start(*stren); pack_start(*equiltm); - pack_start(*gamma); - pack_start(*satur); + + if (complexsoft < 2) { + pack_start(*gamma); + pack_start(*satur); + } + pack_start(*estop); pack_start(*scaltm); - pack_start(*rewei); + + if (complexsoft < 2) { + pack_start(*rewei); + } + // pack_start(*softradiustm); // Always bad with TM ?? pack_start(*sensitm); + ToolParamBlock* const masktmBox = Gtk::manage(new ToolParamBlock()); + masktmBox->pack_start(*showmasktmMethod, Gtk::PACK_SHRINK, 4); + masktmBox->pack_start(*enatmMask, Gtk::PACK_SHRINK, 0); + masktmBox->pack_start(*enatmMaskaft, Gtk::PACK_SHRINK, 0); + masktmBox->pack_start(*masktmCurveEditorG, Gtk::PACK_SHRINK, 4); + masktmBox->pack_start(*blendmasktm, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 1) { + masktmBox->pack_start(*lapmasktm, Gtk::PACK_SHRINK, 0); + } + + masktmBox->pack_start(*radmasktm, Gtk::PACK_SHRINK, 0); + masktmBox->pack_start(*chromasktm, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 2) { + masktmBox->pack_start(*gammasktm, Gtk::PACK_SHRINK, 0); + masktmBox->pack_start(*slomasktm, Gtk::PACK_SHRINK, 0); + } + + masktmBox->pack_start(*mask2tmCurveEditorG, Gtk::PACK_SHRINK, 4); + expmasktm->add(*masktmBox, false); + pack_start(*expmasktm, false, false); } -void LocallabTone::getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask) +LocallabTone::~LocallabTone() { - tmMask = showMaskMethod->get_active_row_number(); + delete masktmCurveEditorG; + delete mask2tmCurveEditorG; +} + +void LocallabTone::resetMaskView() +{ + showmasktmMethodConn.block(true); + showmasktmMethod->set_active(0); + showmasktmMethodConn.block(false); +} + +void LocallabTone::getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask) +{ + tmMask = showmasktmMethod->get_active_row_number(); } void LocallabTone::disableListener() @@ -190,6 +345,9 @@ void LocallabTone::disableListener() LocallabTool::disableListener(); equiltmConn.block(true); + showmasktmMethodConn.block(true); + enatmMaskConn.block(true); + enatmMaskaftConn.block(true); } void LocallabTone::enableListener() @@ -197,10 +355,15 @@ void LocallabTone::enableListener() LocallabTool::enableListener(); equiltmConn.block(false); + showmasktmMethodConn.block(false); + enatmMaskConn.block(false); + enatmMaskaftConn.block(false); } void LocallabTone::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { + const int complexsoft = options.complexity; + // Disable all listeners disableListener(); @@ -211,27 +374,56 @@ void LocallabTone::read(const rtengine::procparams::ProcParams* pp, const Params spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot exp->set_visible(pp->locallab.spots.at(index).visitonemap); - exp->setEnabled(pp->locallab.spots.at(index).exptonemap); + amount->setValue(pp->locallab.spots.at(index).amount); stren->setValue(pp->locallab.spots.at(index).stren); equiltm->set_active(pp->locallab.spots.at(index).equiltm); - gamma->setValue(pp->locallab.spots.at(index).gamma); - satur->setValue(pp->locallab.spots.at(index).satur); + + if (complexsoft < 2) { + gamma->setValue(pp->locallab.spots.at(index).gamma); + satur->setValue(pp->locallab.spots.at(index).satur); + } else { + gamma->setValue(1.); + satur->setValue(0.); + } + estop->setValue(pp->locallab.spots.at(index).estop); scaltm->setValue(pp->locallab.spots.at(index).scaltm); - rewei->setValue(pp->locallab.spots.at(index).rewei); + + if (complexsoft < 2) { + rewei->setValue((double)pp->locallab.spots.at(index).rewei); + } else { + rewei->setValue(0.); + } + softradiustm->setValue(pp->locallab.spots.at(index).softradiustm); - sensitm->setValue(pp->locallab.spots.at(index).sensitm); - enaMask->set_active(pp->locallab.spots.at(index).enatmMask); - CCMaskShape->setCurve(pp->locallab.spots.at(index).CCmasktmcurve); - LLMaskShape->setCurve(pp->locallab.spots.at(index).LLmasktmcurve); - HHMaskShape->setCurve(pp->locallab.spots.at(index).HHmasktmcurve); - blendMask->setValue(pp->locallab.spots.at(index).blendmasktm); - radMask->setValue(pp->locallab.spots.at(index).radmasktm); - chroMask->setValue(pp->locallab.spots.at(index).chromasktm); - gamMask->setValue(pp->locallab.spots.at(index).gammasktm); - sloMask->setValue(pp->locallab.spots.at(index).slomasktm); + sensitm->setValue((double)pp->locallab.spots.at(index).sensitm); + enatmMask->set_active(pp->locallab.spots.at(index).enatmMask); + enatmMaskaft->set_active(pp->locallab.spots.at(index).enatmMaskaft); + CCmasktmshape->setCurve(pp->locallab.spots.at(index).CCmasktmcurve); + LLmasktmshape->setCurve(pp->locallab.spots.at(index).LLmasktmcurve); + HHmasktmshape->setCurve(pp->locallab.spots.at(index).HHmasktmcurve); + blendmasktm->setValue((double)pp->locallab.spots.at(index).blendmasktm); + + if (complexsoft == 0) { + lapmasktm->setValue(pp->locallab.spots.at(index).lapmasktm); + } else { + lapmasktm->setValue(0.); + } + + radmasktm->setValue(pp->locallab.spots.at(index).radmasktm); + chromasktm->setValue(pp->locallab.spots.at(index).chromasktm); + + if (complexsoft < 2) { + gammasktm->setValue(pp->locallab.spots.at(index).gammasktm); + slomasktm->setValue(pp->locallab.spots.at(index).slomasktm); + } else { + gammasktm->setValue(1.); + slomasktm->setValue(0.); + } + + Lmasktmshape->setCurve(pp->locallab.spots.at(index).Lmasktmcurve); } // Enable all listeners @@ -246,7 +438,6 @@ void LocallabTone::write(rtengine::procparams::ProcParams* pp, ParamsEdited* ped if (index < (int)pp->locallab.spots.size()) { pp->locallab.spots.at(index).exptonemap = exp->getEnabled(); - pp->locallab.spots.at(index).visitonemap = exp->get_visible(); pp->locallab.spots.at(index).amount = amount->getValue(); @@ -259,15 +450,18 @@ void LocallabTone::write(rtengine::procparams::ProcParams* pp, ParamsEdited* ped pp->locallab.spots.at(index).rewei = rewei->getIntValue(); pp->locallab.spots.at(index).softradiustm = softradiustm->getValue(); pp->locallab.spots.at(index).sensitm = sensitm->getIntValue(); - pp->locallab.spots.at(index).enatmMask = enaMask->get_active(); - pp->locallab.spots.at(index).LLmasktmcurve = LLMaskShape->getCurve(); - pp->locallab.spots.at(index).CCmasktmcurve = CCMaskShape->getCurve(); - pp->locallab.spots.at(index).HHmasktmcurve = HHMaskShape->getCurve(); - pp->locallab.spots.at(index).blendmasktm = blendMask->getIntValue(); - pp->locallab.spots.at(index).radmasktm = radMask->getValue(); - pp->locallab.spots.at(index).chromasktm = chroMask->getValue(); - pp->locallab.spots.at(index).gammasktm = gamMask->getValue(); - pp->locallab.spots.at(index).slomasktm = sloMask->getValue(); + pp->locallab.spots.at(index).enatmMask = enatmMask->get_active(); + pp->locallab.spots.at(index).enatmMaskaft = enatmMaskaft->get_active(); + pp->locallab.spots.at(index).LLmasktmcurve = LLmasktmshape->getCurve(); + pp->locallab.spots.at(index).CCmasktmcurve = CCmasktmshape->getCurve(); + pp->locallab.spots.at(index).HHmasktmcurve = HHmasktmshape->getCurve(); + pp->locallab.spots.at(index).blendmasktm = blendmasktm->getIntValue(); + pp->locallab.spots.at(index).lapmasktm = lapmasktm->getValue(); + pp->locallab.spots.at(index).radmasktm = radmasktm->getValue(); + pp->locallab.spots.at(index).chromasktm = chromasktm->getValue(); + pp->locallab.spots.at(index).gammasktm = gammasktm->getValue(); + pp->locallab.spots.at(index).slomasktm = slomasktm->getValue(); + pp->locallab.spots.at(index).Lmasktmcurve = Lmasktmshape->getCurve(); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -290,11 +484,12 @@ void LocallabTone::setDefaults(const rtengine::procparams::ProcParams* defParams rewei->setDefault((double)defSpot.rewei); softradiustm->setDefault(defSpot.softradiustm); sensitm->setDefault((double)defSpot.sensitm); - blendMask->setDefault((double)defSpot.blendmasktm); - radMask->setDefault(defSpot.radmasktm); - chroMask->setDefault(defSpot.chromasktm); - gamMask->setDefault(defSpot.gammasktm); - sloMask->setDefault(defSpot.slomasktm); + blendmasktm->setDefault((double)defSpot.blendmasktm); + lapmasktm->setDefault(defSpot.lapmasktm); + radmasktm->setDefault(defSpot.radmasktm); + chromasktm->setDefault(defSpot.chromasktm); + gammasktm->setDefault(defSpot.gammasktm); + slomasktm->setDefault(defSpot.slomasktm); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -366,38 +561,45 @@ void LocallabTone::adjusterChanged(Adjuster* a, double newval) } } - if (a == blendMask) { + if (a == blendmasktm) { if (listener) { listener->panelChanged(Evlocallabblendmasktm, - blendMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + blendmasktm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == radMask) { + if (a == lapmasktm) { + if (listener) { + listener->panelChanged(Evlocallablapmasktm, + lapmasktm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == radmasktm) { if (listener) { listener->panelChanged(Evlocallabradmasktm, - radMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + radmasktm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == chroMask) { + if (a == chromasktm) { if (listener) { listener->panelChanged(Evlocallabchromasktm, - chroMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + chromasktm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == gamMask) { + if (a == gammasktm) { if (listener) { listener->panelChanged(Evlocallabgammasktm, - gamMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + gammasktm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == sloMask) { + if (a == slomasktm) { if (listener) { listener->panelChanged(Evlocallabslomasktm, - sloMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + slomasktm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } } @@ -406,26 +608,33 @@ void LocallabTone::adjusterChanged(Adjuster* a, double newval) void LocallabTone::curveChanged(CurveEditor* ce) { if (isLocActivated && exp->getEnabled()) { - if (ce == CCMaskShape) { + if (ce == CCmasktmshape) { if (listener) { listener->panelChanged(EvlocallabCCmasktmshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } - if (ce == LLMaskShape) { + if (ce == LLmasktmshape) { if (listener) { listener->panelChanged(EvlocallabLLmasktmshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } - if (ce == HHMaskShape) { + if (ce == HHmasktmshape) { if (listener) { listener->panelChanged(EvlocallabHHmasktmshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } + + if (ce == Lmasktmshape) { + if (listener) { + listener->panelChanged(EvlocallabLmasktmshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } } } @@ -444,31 +653,20 @@ void LocallabTone::enabledChanged() } } -void LocallabTone::enaMaskChanged() +void LocallabTone::updateMaskBackground(const double normChromar, const double normLumar, const double normHuer) { - if (isLocActivated && exp->getEnabled()) { - if (listener) { - if (enaMask->get_active()) { - listener->panelChanged(EvLocallabEnatmMask, - M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); - } else { - listener->panelChanged(EvLocallabEnatmMask, - M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); - } - } - } -} + idle_register.add( + [this, normHuer, normLumar, normChromar]() -> bool { + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected -void LocallabTone::showMaskMethodChanged() -{ - // If mask preview is activated, deactivate all other tool mask preview - if (locToolListener) { - locToolListener->resetOtherMaskView(this); - } + // Update mask background + CCmasktmshape->updateLocallabBackground(normChromar); + LLmasktmshape->updateLocallabBackground(normLumar); + HHmasktmshape->updateLocallabBackground(normHuer); - if (listener) { - listener->panelChanged(EvlocallabshowmaskMethod, ""); + return false; } + ); } void LocallabTone::equiltmChanged() @@ -486,29 +684,134 @@ void LocallabTone::equiltmChanged() } } +void LocallabTone::showmasktmMethodChanged() +{ + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskMethod, ""); + } +} + +void LocallabTone::enatmMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enatmMask->get_active()) { + listener->panelChanged(EvLocallabEnatmMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnatmMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabTone::enatmMaskaftChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enatmMaskaft->get_active()) { + listener->panelChanged(EvLocallabEnatmMaskaft, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnatmMaskaft, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + /* ==== LocallabRetinex ==== */ LocallabRetinex::LocallabRetinex(): - LocallabTool(this, M("TP_LOCALLAB_RET_TOOLNAME"), M("TP_LOCALLAB_RETI"), true, MaskWithTrMap), + LocallabTool(this, M("TP_LOCALLAB_RET_TOOLNAME"), M("TP_LOCALLAB_RETI"), true), // Retinex specific widgets + dehaFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_DEHAFRA")))), + dehaz(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DEHAZ"), -100, 100, 1, 0))), + depth(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DEPTH"), 0, 100, 1, 25))), + lumonly(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_LUMONLY")))), + retiFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_RETIFRA")))), + str(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STR"), 0., 100., 0.1, 0.2))), + loglin(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_LOGLIN")))), + sensih(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIH"), 0, 100, 1, 60))), + retitoolFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_RETITOOLFRA")))), + retiBox(Gtk::manage(new ToolParamBlock())), retinexMethod(Gtk::manage(new MyComboBoxText())), fftwreti(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_FFTW")))), equilret(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_EQUIL")))), - str(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STR"), 0., 100., 0.1, 0.0))), - chrrt(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHRRT"), 0.0, 100.0, 0.1, 0.0))), - neigh(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NEIGH"), MINNEIGH, MAXNEIGH, 0.5, CENTERNEIGH, nullptr, nullptr, &retiSlider2neigh, &retiNeigh2Slider))), - vart(Gtk::manage(new Adjuster(M("TP_LOCALLAB_VART"), 4.0, 500., 0.1, 70.))), - scalereti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SCALERETI"), 1.0, 10.0, 1., 3.))), + neigh(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NEIGH"), MINNEIGH, MAXNEIGH, 0.5, 50., nullptr, nullptr, &retiSlider2neigh, &retiNeigh2Slider))), + vart(Gtk::manage(new Adjuster(M("TP_LOCALLAB_VART"), 0.1, 500., 0.1, 150.))), + scalereti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SCALERETI"), 1.0, 10.0, 1., 2.))), limd(Gtk::manage(new Adjuster(M("TP_LOCALLAB_THRESRETI"), 1.2, 100.0, 0.1, 8.))), - darkness(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DARKRETI"), 0.01, 3.0, 0.01, 1.))), - lightnessreti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LIGHTRETI"), 0.01, 3.0, 0.01, 1.))), - dehaz(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DEHAZ"), 0, 100, 1, 0))), - softradiusret(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GUIDFILTER"), 0.0, 100.0, 0.1, 0.))), - sensih(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIH"), 0, 100, 1, 30))), + offs(Gtk::manage(new Adjuster(M("TP_LOCALLAB_OFFS"), -16386., 32768., 1., 0.))), + expretitools(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_EXPRETITOOLS")))), + chrrt(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHRRT"), 0.0, 100.0, 0.1, 0.0))), + darkness(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DARKRETI"), 0.01, 6.0, 0.01, 2.0))), + lightnessreti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LIGHTRETI"), 0.01, 4.0, 0.01, 1.))), + cliptm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CLIPTM"), 0.02, 2.0, 0.01, 1.))), + softradiusret(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRETI"), -10.0, 1000.0, 0.5, 40.))), + LocalcurveEditortransT(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_TRANSMISSIONMAP"))), + cTtransshape(static_cast(LocalcurveEditortransT->addCurve(CT_Flat, "", nullptr, false, false))), + mMLabels(Gtk::manage(new Gtk::Label("---"))), + transLabels(Gtk::manage(new Gtk::Label("---"))), + transLabels2(Gtk::manage(new Gtk::Label("---"))), LocalcurveEditorgainT(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_TRANSMISSIONGAIN"))), + cTgainshape(static_cast(LocalcurveEditorgainT->addCurve(CT_Flat, "", nullptr, false, false))), + expmaskreti(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWR")))), + maskretiBox(Gtk::manage(new ToolParamBlock())), + showmaskretiMethod(Gtk::manage(new MyComboBoxText())), + enaretiMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), + enaretiMasktmap(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_TM_MASK")))), + maskretiCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), + CCmaskretishape(static_cast(maskretiCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false))), + LLmaskretishape(static_cast(maskretiCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false))), + HHmaskretishape(static_cast(maskretiCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true))), + blendmaskreti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), + radmaskreti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), -10.0, 1000.0, 0.1, 10.))), + lapmaskreti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPMASKCOL"), 0.0, 100.0, 0.1, 0.))), + chromaskreti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), + gammaskreti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.05, 5.0, 0.01, 1.))), + slomaskreti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), + mask2retiCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), + Lmaskretishape(static_cast(mask2retiCurveEditorG->addCurve(CT_Diagonal, "L(L)"))), inversret(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))) { const bool showtooltip = options.showtooltip; + const int complexsoft = options.complexity; + + const LocallabParams::LocallabSpot defSpot; + + // Parameter Retinex specific widgets + dehaFrame->set_label_align(0.025, 0.5); + + if (showtooltip) { + dehaz->set_tooltip_text(M("TP_LOCALLAB_DEHAZ_TOOLTIP")); + } + + dehaz->setAdjusterListener(this); + + depth->setAdjusterListener(this); + + lumonlyConn = lumonly->signal_toggled().connect(sigc::mem_fun(*this, &LocallabRetinex::lumonlyChanged)); + + retiFrame->set_label_align(0.025, 0.5); + + str->setAdjusterListener(this); + + loglinConn = loglin->signal_toggled().connect(sigc::mem_fun(*this, &LocallabRetinex::loglinChanged)); + + if (showtooltip) { + sensih->set_tooltip_text(M("TP_LOCALLAB_SENSIH_TOOLTIP")); + } + + sensih->setAdjusterListener(this); + + retitoolFrame->set_label_align(0.025, 0.5); retinexMethod->append(M("TP_RETINEX_LOW")); retinexMethod->append(M("TP_RETINEX_UNIFORM")); @@ -525,13 +828,9 @@ LocallabRetinex::LocallabRetinex(): fftwreti->set_tooltip_text(M("TP_LOCALLAB_RETI_FFTW_TOOLTIP")); } - fftwretiConn = fftwreti->signal_toggled().connect(sigc::mem_fun(*this, &LocallabRetinex::fftwretiChanged)); + fftwretiConn = fftwreti->signal_toggled().connect(sigc::mem_fun(*this, &LocallabRetinex::fftwretiChanged)); - equilretConn = equilret->signal_toggled().connect(sigc::mem_fun(*this, &LocallabRetinex::equilretChanged)); - - str->setAdjusterListener(this); - - chrrt->setAdjusterListener(this); + equilretConn = equilret->signal_toggled().connect(sigc::mem_fun(*this, &LocallabRetinex::equilretChanged)); if (showtooltip) { neigh->set_tooltip_text(M("TP_LOCALLAB_RETI_NEIGH_VART_TOOLTIP")); @@ -549,29 +848,54 @@ LocallabRetinex::LocallabRetinex(): limd->setAdjusterListener(this); + offs->setAdjusterListener(this); + + setExpandAlignProperties(expretitools, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + chrrt->setAdjusterListener(this); + darkness->setAdjusterListener(this); lightnessreti->setAdjusterListener(this); - dehaz->setAdjusterListener(this); + cliptm->setAdjusterListener(this); if (showtooltip) { softradiusret->set_tooltip_text(M("TP_LOCALLAB_GUIDFILTER_TOOLTIP")); } + softradiusret->setLogScale(10, -10); softradiusret->setAdjusterListener(this); + LocalcurveEditortransT->setCurveListener(this); + + cTtransshape->setIdentityValue(0.); + cTtransshape->setResetCurve(FlatCurveType(defSpot.localTtranscurve.at(0)), defSpot.localTtranscurve); + if (showtooltip) { - sensih->set_tooltip_text(M("TP_LOCALLAB_SENSIH_TOOLTIP")); + cTtransshape->setTooltip(M("TP_LOCALLAB_TRANSMISSION_TOOLTIP")); } - sensih->setAdjusterListener(this); + LocalcurveEditortransT->curveListComplete(); + + if (showtooltip) { + mMLabels->set_tooltip_markup(M("TP_LOCALLAB_MLABEL_TOOLTIP")); + } + + setExpandAlignProperties(mMLabels, true, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); + + if (showtooltip) { + transLabels->set_tooltip_markup(M("TP_LOCALLAB_TLABEL_TOOLTIP")); + } + + setExpandAlignProperties(transLabels, true, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); + + setExpandAlignProperties(transLabels2, true, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); LocalcurveEditorgainT->setCurveListener(this); - cTgainshape = static_cast(LocalcurveEditorgainT->addCurve(CT_Flat, "", nullptr, false, false)); cTgainshape->setIdentityValue(0.); - cTgainshape->setResetCurve(FlatCurveType(LocallabParams::DEF_RET_CURVE.at(0)), LocallabParams::DEF_RET_CURVE); + cTgainshape->setResetCurve(FlatCurveType(defSpot.localTgaincurve.at(0)), defSpot.localTgaincurve); if (showtooltip) { cTgainshape->setTooltip(M("TP_RETINEX_GAINTRANSMISSION_TOOLTIP")); @@ -579,43 +903,221 @@ LocallabRetinex::LocallabRetinex(): LocalcurveEditorgainT->curveListComplete(); - inversretConn = inversret->signal_toggled().connect(sigc::mem_fun(*this, &LocallabRetinex::inversretChanged)); + if (showtooltip) { + expmaskreti->set_tooltip_markup(M("TP_LOCALLAB_MASK_TOOLTIP")); + } - pack_start(*retinexMethod); - pack_start(*fftwreti); - pack_start(*equilret); - pack_start(*str); - pack_start(*chrrt); - pack_start(*neigh); - pack_start(*vart); - pack_start(*scalereti); - pack_start(*limd); - pack_start(*darkness); - pack_start(*lightnessreti); - pack_start(*dehaz); - pack_start(*softradiusret); - pack_start(*sensih); - pack_start(*LocalcurveEditorgainT, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor - pack_start(*inversret); + setExpandAlignProperties(expmaskreti, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + showmaskretiMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskretiMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showmaskretiMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); + showmaskretiMethod->append(M("TP_LOCALLAB_SHOWMASK")); + showmaskretiMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); + showmaskretiMethod->set_active(0); + + if (showtooltip) { + showmaskretiMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmaskretiMethodConn = showmaskretiMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabRetinex::showmaskretiMethodChanged)); + + enaretiMaskConn = enaretiMask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabRetinex::enaretiMaskChanged)); + + if (showtooltip) { + enaretiMasktmap->set_tooltip_markup(M("TP_LOCALLAB_ENARETIMASKTMAP_TOOLTIP")); + } + + enaretiMasktmapConn = enaretiMasktmap->signal_toggled().connect(sigc::mem_fun(*this, &LocallabRetinex::enaretiMasktmapChanged)); + + maskretiCurveEditorG->setCurveListener(this); + + CCmaskretishape->setIdentityValue(0.); + CCmaskretishape->setResetCurve(FlatCurveType(defSpot.CCmaskreticurve.at(0)), defSpot.CCmaskreticurve); + + if (showtooltip) { + CCmaskretishape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + CCmaskretishape->setBottomBarColorProvider(this, 1); + + LLmaskretishape->setIdentityValue(0.); + LLmaskretishape->setResetCurve(FlatCurveType(defSpot.LLmaskreticurve.at(0)), defSpot.LLmaskreticurve); + + if (showtooltip) { + LLmaskretishape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + LLmaskretishape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + HHmaskretishape->setIdentityValue(0.); + HHmaskretishape->setResetCurve(FlatCurveType(defSpot.HHmaskreticurve.at(0)), defSpot.HHmaskreticurve); + + if (showtooltip) { + HHmaskretishape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + HHmaskretishape->setCurveColorProvider(this, 2); + HHmaskretishape->setBottomBarColorProvider(this, 2); + + maskretiCurveEditorG->curveListComplete(); + + blendmaskreti->setAdjusterListener(this); + + if (showtooltip) { + radmaskreti->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + radmaskreti->setAdjusterListener(this); + + if (showtooltip) { + lapmaskreti->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + lapmaskreti->setAdjusterListener(this); + + chromaskreti->setAdjusterListener(this); + + gammaskreti->setAdjusterListener(this); + + slomaskreti->setAdjusterListener(this); + + mask2retiCurveEditorG->setCurveListener(this); + + Lmaskretishape->setResetCurve(DiagonalCurveType(defSpot.Lmaskreticurve.at(0)), defSpot.Lmaskreticurve); + + if (showtooltip) { + Lmaskretishape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + } + + Lmaskretishape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + Lmaskretishape->setLeftBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + mask2retiCurveEditorG->curveListComplete(); + + inversretConn = inversret->signal_toggled().connect(sigc::mem_fun(*this, &LocallabRetinex::inversretChanged)); + + // Add Retinex specific widgets to GUI + ToolParamBlock* const auxBox = Gtk::manage(new ToolParamBlock()); + ToolParamBlock* const dehaBox = Gtk::manage(new ToolParamBlock()); + dehaBox->pack_start(*dehaz); + dehaBox->pack_start(*depth); + dehaBox->pack_start(*lumonly); + dehaFrame->add(*dehaBox); + auxBox->add(*dehaFrame); + ToolParamBlock* const deharetiBox = Gtk::manage(new ToolParamBlock()); + deharetiBox->pack_start(*str); + deharetiBox->pack_start(*loglin); + retiFrame->add(*deharetiBox); + + if (complexsoft < 1) { + auxBox->add(*retiFrame); + } + + ToolParamBlock* const scopeBox = Gtk::manage(new ToolParamBlock()); + scopeBox->pack_start(*sensih); + auxBox->add(*scopeBox); + pack_start(*auxBox); + retiBox->pack_start(*retinexMethod); + retiBox->pack_start(*fftwreti); + retiBox->pack_start(*equilret); + retiBox->pack_start(*neigh); + retiBox->pack_start(*vart); + retiBox->pack_start(*scalereti); + retiBox->pack_start(*limd); + retiBox->pack_start(*offs); + ToolParamBlock* const toolretiBox = Gtk::manage(new ToolParamBlock()); + toolretiBox->pack_start(*chrrt); + toolretiBox->pack_start(*darkness); + toolretiBox->pack_start(*lightnessreti); + toolretiBox->pack_start(*cliptm); + toolretiBox->pack_start(*softradiusret); + toolretiBox->pack_start(*LocalcurveEditortransT, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + toolretiBox->pack_start(*mMLabels); + toolretiBox->pack_start(*transLabels); + toolretiBox->pack_start(*transLabels2); + toolretiBox->pack_start(*LocalcurveEditorgainT, Gtk::PACK_SHRINK, 4); + expretitools->add(*toolretiBox, false); + retiBox->pack_start(*expretitools, false, false); + maskretiBox->pack_start(*showmaskretiMethod, Gtk::PACK_SHRINK, 4); + maskretiBox->pack_start(*enaretiMask, Gtk::PACK_SHRINK, 0); + maskretiBox->pack_start(*enaretiMasktmap, Gtk::PACK_SHRINK, 0); + maskretiBox->pack_start(*maskretiCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + maskretiBox->pack_start(*blendmaskreti, Gtk::PACK_SHRINK, 0); + maskretiBox->pack_start(*radmaskreti, Gtk::PACK_SHRINK, 0); + maskretiBox->pack_start(*lapmaskreti, Gtk::PACK_SHRINK, 0); + maskretiBox->pack_start(*chromaskreti, Gtk::PACK_SHRINK, 0); + maskretiBox->pack_start(*gammaskreti, Gtk::PACK_SHRINK, 0); + maskretiBox->pack_start(*slomaskreti, Gtk::PACK_SHRINK, 0); + maskretiBox->pack_start(*mask2retiCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + expmaskreti->add(*maskretiBox, false); + retiBox->pack_start(*expmaskreti, false, false); + // retiBox->pack_start(*inversret); + retitoolFrame->add(*retiBox); + pack_start(*retitoolFrame); } LocallabRetinex::~LocallabRetinex() { + delete LocalcurveEditortransT; delete LocalcurveEditorgainT; + delete maskretiCurveEditorG; + delete mask2retiCurveEditorG; } -void LocallabRetinex::getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask) +void LocallabRetinex::updateMinMax(const double cdma, const double cdmin, const double mini, const double maxi, const double Tmean, const double Tsigma, const double Tmin, const double Tmax) { - retiMask = showMaskMethod->get_active_row_number(); + idle_register.add( + [this, cdma, cdmin, mini, maxi, Tmean, Tsigma, Tmin, Tmax]() -> bool { + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected + + mMLabels->set_text( + Glib::ustring::compose(M("TP_LOCALLAB_MLABEL"), + Glib::ustring::format(std::fixed, std::setprecision(0), cdmin), + Glib::ustring::format(std::fixed, std::setprecision(0), cdma)) + ); + transLabels->set_text( + Glib::ustring::compose(M("TP_LOCALLAB_TLABEL"), + Glib::ustring::format(std::fixed, std::setprecision(1), mini), + Glib::ustring::format(std::fixed, std::setprecision(1), maxi), + Glib::ustring::format(std::fixed, std::setprecision(1), Tmean), + Glib::ustring::format(std::fixed, std::setprecision(1), Tsigma)) + ); + transLabels2->set_text( + Glib::ustring::compose(M("TP_RETINEX_TLABEL2"), + Glib::ustring::format(std::fixed, std::setprecision(1), Tmin), + Glib::ustring::format(std::fixed, std::setprecision(1), Tmax)) + ); + + return false; + } + ); +} + +void LocallabRetinex::resetMaskView() +{ + showmaskretiMethodConn.block(true); + showmaskretiMethod->set_active(0); + showmaskretiMethodConn.block(false); +} + +void LocallabRetinex::getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask) +{ + retiMask = showmaskretiMethod->get_active_row_number(); } void LocallabRetinex::disableListener() { LocallabTool::disableListener(); + lumonlyConn.block(true); + loglinConn.block(true); retinexMethodConn.block(true); fftwretiConn.block(true); equilretConn.block(true); + showmaskretiMethodConn.block(true); + enaretiMaskConn.block(true); + enaretiMasktmapConn.block(true); inversretConn.block(true); } @@ -623,14 +1125,21 @@ void LocallabRetinex::enableListener() { LocallabTool::enableListener(); + lumonlyConn.block(false); + loglinConn.block(false); retinexMethodConn.block(false); fftwretiConn.block(false); equilretConn.block(false); + showmaskretiMethodConn.block(false); + enaretiMaskConn.block(false); + enaretiMasktmapConn.block(false); inversretConn.block(false); } void LocallabRetinex::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { + const int complexsoft = options.complexity; + // Disable all listeners disableListener(); @@ -641,9 +1150,21 @@ void LocallabRetinex::read(const rtengine::procparams::ProcParams* pp, const Par spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot exp->set_visible(pp->locallab.spots.at(index).visireti); - exp->setEnabled(pp->locallab.spots.at(index).expreti); + dehaz->setValue((double)pp->locallab.spots.at(index).dehaz); + depth->setValue((double)pp->locallab.spots.at(index).depth); + lumonly->set_active(pp->locallab.spots.at(index).lumonly); + + if (complexsoft < 2) { + str->setValue(pp->locallab.spots.at(index).str); + } else { + str->setValue(0.); + } + + loglin->set_active(pp->locallab.spots.at(index).loglin); + sensih->setValue((double)pp->locallab.spots.at(index).sensih); + if (pp->locallab.spots.at(index).retinexMethod == "low") { retinexMethod->set_active(0); } else if (pp->locallab.spots.at(index).retinexMethod == "uni") { @@ -654,40 +1175,45 @@ void LocallabRetinex::read(const rtengine::procparams::ProcParams* pp, const Par fftwreti->set_active(pp->locallab.spots.at(index).fftwreti); equilret->set_active(pp->locallab.spots.at(index).equilret); - str->setValue(pp->locallab.spots.at(index).str); - chrrt->setValue(pp->locallab.spots.at(index).chrrt); neigh->setValue(pp->locallab.spots.at(index).neigh); vart->setValue(pp->locallab.spots.at(index).vart); scalereti->setValue(pp->locallab.spots.at(index).scalereti); limd->setValue(pp->locallab.spots.at(index).limd); + offs->setValue(pp->locallab.spots.at(index).offs); + chrrt->setValue(pp->locallab.spots.at(index).chrrt); darkness->setValue(pp->locallab.spots.at(index).darkness); lightnessreti->setValue(pp->locallab.spots.at(index).lightnessreti); - dehaz->setValue(pp->locallab.spots.at(index).dehaz); + cliptm->setValue(pp->locallab.spots.at(index).cliptm); softradiusret->setValue(pp->locallab.spots.at(index).softradiusret); - sensih->setValue(pp->locallab.spots.at(index).sensih); + cTtransshape->setCurve(pp->locallab.spots.at(index).localTtranscurve); cTgainshape->setCurve(pp->locallab.spots.at(index).localTgaincurve); + enaretiMask->set_active(pp->locallab.spots.at(index).enaretiMask); + enaretiMasktmap->set_active(pp->locallab.spots.at(index).enaretiMasktmap); + CCmaskretishape->setCurve(pp->locallab.spots.at(index).CCmaskreticurve); + LLmaskretishape->setCurve(pp->locallab.spots.at(index).LLmaskreticurve); + HHmaskretishape->setCurve(pp->locallab.spots.at(index).HHmaskreticurve); + blendmaskreti->setValue((double)pp->locallab.spots.at(index).blendmaskreti); + radmaskreti->setValue(pp->locallab.spots.at(index).radmaskreti); + lapmaskreti->setValue(pp->locallab.spots.at(index).lapmaskreti); + chromaskreti->setValue(pp->locallab.spots.at(index).chromaskreti); + gammaskreti->setValue(pp->locallab.spots.at(index).gammaskreti); + slomaskreti->setValue(pp->locallab.spots.at(index).slomaskreti); + Lmaskretishape->setCurve(pp->locallab.spots.at(index).Lmaskreticurve); inversret->set_active(pp->locallab.spots.at(index).inversret); - enaMask->set_active(pp->locallab.spots.at(index).enaretiMask); - enaMaskTrMap->set_active(pp->locallab.spots.at(index).enaretiMasktmap); - CCMaskShape->setCurve(pp->locallab.spots.at(index).CCmaskreticurve); - LLMaskShape->setCurve(pp->locallab.spots.at(index).LLmaskreticurve); - HHMaskShape->setCurve(pp->locallab.spots.at(index).HHmaskreticurve); - blendMask->setValue(pp->locallab.spots.at(index).blendmaskreti); - radMask->setValue(pp->locallab.spots.at(index).radmaskreti); - chroMask->setValue(pp->locallab.spots.at(index).chromaskreti); - gamMask->setValue(pp->locallab.spots.at(index).gammaskreti); - sloMask->setValue(pp->locallab.spots.at(index).slomaskreti); } // Enable all listeners enableListener(); // Update Retinex GUI according to scalereti adjuster value - updateRetinexGUI(); + updateRetinexGUI1(); // Update Retinex GUI according to inversret button state updateRetinexGUI2(); + // Update Retinex GUI according to str adjuster value + updateRetinexGUI3(); + // Note: No need to manage pedited as batch mode is deactivated for Locallab } @@ -697,9 +1223,15 @@ void LocallabRetinex::write(rtengine::procparams::ProcParams* pp, ParamsEdited* if (index < (int)pp->locallab.spots.size()) { pp->locallab.spots.at(index).expreti = exp->getEnabled(); - pp->locallab.spots.at(index).visireti = exp->get_visible(); + pp->locallab.spots.at(index).dehaz = dehaz->getIntValue(); + pp->locallab.spots.at(index).depth = depth->getIntValue(); + pp->locallab.spots.at(index).lumonly = lumonly->get_active(); + pp->locallab.spots.at(index).str = str->getValue(); + pp->locallab.spots.at(index).loglin = loglin->get_active(); + pp->locallab.spots.at(index).sensih = sensih->getIntValue(); + if (retinexMethod->get_active_row_number() == 0) { pp->locallab.spots.at(index).retinexMethod = "low"; } else if (retinexMethod->get_active_row_number() == 1) { @@ -710,29 +1242,31 @@ void LocallabRetinex::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pp->locallab.spots.at(index).fftwreti = fftwreti->get_active(); pp->locallab.spots.at(index).equilret = equilret->get_active(); - pp->locallab.spots.at(index).str = str->getValue(); - pp->locallab.spots.at(index).chrrt = chrrt->getValue(); pp->locallab.spots.at(index).neigh = neigh->getValue(); pp->locallab.spots.at(index).vart = vart->getValue(); pp->locallab.spots.at(index).scalereti = scalereti->getValue(); pp->locallab.spots.at(index).limd = limd->getValue(); + pp->locallab.spots.at(index).offs = offs->getValue(); + pp->locallab.spots.at(index).chrrt = chrrt->getValue(); pp->locallab.spots.at(index).darkness = darkness->getValue(); pp->locallab.spots.at(index).lightnessreti = lightnessreti->getValue(); - pp->locallab.spots.at(index).dehaz = dehaz->getIntValue(); + pp->locallab.spots.at(index).cliptm = cliptm->getValue(); pp->locallab.spots.at(index).softradiusret = softradiusret->getValue(); - pp->locallab.spots.at(index).sensih = sensih->getIntValue(); + pp->locallab.spots.at(index).localTtranscurve = cTtransshape->getCurve(); pp->locallab.spots.at(index).localTgaincurve = cTgainshape->getCurve(); + pp->locallab.spots.at(index).enaretiMask = enaretiMask->get_active(); + pp->locallab.spots.at(index).enaretiMasktmap = enaretiMasktmap->get_active(); + pp->locallab.spots.at(index).CCmaskreticurve = CCmaskretishape->getCurve(); + pp->locallab.spots.at(index).LLmaskreticurve = LLmaskretishape->getCurve(); + pp->locallab.spots.at(index).HHmaskreticurve = HHmaskretishape->getCurve(); + pp->locallab.spots.at(index).blendmaskreti = blendmaskreti->getIntValue(); + pp->locallab.spots.at(index).radmaskreti = radmaskreti->getValue(); + pp->locallab.spots.at(index).lapmaskreti = lapmaskreti->getValue(); + pp->locallab.spots.at(index).chromaskreti = chromaskreti->getValue(); + pp->locallab.spots.at(index).gammaskreti = gammaskreti->getValue(); + pp->locallab.spots.at(index).slomaskreti = slomaskreti->getValue(); + pp->locallab.spots.at(index).Lmaskreticurve = Lmaskretishape->getCurve(); pp->locallab.spots.at(index).inversret = inversret->get_active(); - pp->locallab.spots.at(index).enaretiMask = enaMask->get_active(); - pp->locallab.spots.at(index).enaretiMasktmap = enaMaskTrMap->get_active(); - pp->locallab.spots.at(index).LLmaskreticurve = LLMaskShape->getCurve(); - pp->locallab.spots.at(index).CCmaskreticurve = CCMaskShape->getCurve(); - pp->locallab.spots.at(index).HHmaskreticurve = HHMaskShape->getCurve(); - pp->locallab.spots.at(index).blendmaskreti = blendMask->getIntValue(); - pp->locallab.spots.at(index).radmaskreti = radMask->getValue(); - pp->locallab.spots.at(index).chromaskreti = chroMask->getValue(); - pp->locallab.spots.at(index).gammaskreti = gamMask->getValue(); - pp->locallab.spots.at(index).slomaskreti = sloMask->getValue(); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -746,22 +1280,26 @@ void LocallabRetinex::setDefaults(const rtengine::procparams::ProcParams* defPar const LocallabParams::LocallabSpot defSpot = defParams->locallab.spots.at(index); // Set default values for adjuster widgets + dehaz->setDefault((double)defSpot.dehaz); + depth->setDefault((double)defSpot.depth); str->setDefault(defSpot.str); - chrrt->setDefault(defSpot.chrrt); + sensih->setDefault((double)defSpot.sensih); neigh->setDefault(defSpot.neigh); vart->setDefault(defSpot.vart); scalereti->setDefault(defSpot.scalereti); limd->setDefault(defSpot.limd); + offs->setDefault(defSpot.offs); + chrrt->setDefault(defSpot.chrrt); darkness->setDefault(defSpot.darkness); lightnessreti->setDefault(defSpot.lightnessreti); - dehaz->setDefault((double)defSpot.dehaz); + cliptm->setDefault(defSpot.cliptm); softradiusret->setDefault(defSpot.softradiusret); - sensih->setDefault((double)defSpot.sensih); - blendMask->setDefault((double)defSpot.blendmaskreti); - radMask->setDefault(defSpot.radmaskreti); - chroMask->setDefault(defSpot.chromaskreti); - gamMask->setDefault(defSpot.gammaskreti); - sloMask->setDefault(defSpot.slomaskreti); + blendmaskreti->setDefault((double)defSpot.blendmaskreti); + radmaskreti->setDefault(defSpot.radmaskreti); + lapmaskreti->setDefault(defSpot.lapmaskreti); + chromaskreti->setDefault(defSpot.chromaskreti); + gammaskreti->setDefault(defSpot.gammaskreti); + slomaskreti->setDefault(defSpot.slomaskreti); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -771,10 +1309,29 @@ void LocallabRetinex::adjusterChanged(Adjuster* a, double newval) { // Update Retinex GUI according to scalereti adjuster value if (a == scalereti) { - updateRetinexGUI(); + updateRetinexGUI1(); + } + + // Update Retinex GUI according to str adjuster value + if (a == str) { + updateRetinexGUI3(); } if (isLocActivated && exp->getEnabled()) { + if (a == dehaz) { + if (listener) { + listener->panelChanged(Evlocallabdehaz, + dehaz->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == depth) { + if (listener) { + listener->panelChanged(Evlocallabdepth, + depth->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + if (a == str) { if (listener) { listener->panelChanged(Evlocallabstr, @@ -782,10 +1339,10 @@ void LocallabRetinex::adjusterChanged(Adjuster* a, double newval) } } - if (a == chrrt) { + if (a == sensih) { if (listener) { - listener->panelChanged(Evlocallabchrrt, - chrrt->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + listener->panelChanged(Evlocallabsensih, + sensih->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } @@ -817,6 +1374,20 @@ void LocallabRetinex::adjusterChanged(Adjuster* a, double newval) } } + if (a == offs) { + if (listener) { + listener->panelChanged(Evlocallaboffs, + offs->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chrrt) { + if (listener) { + listener->panelChanged(Evlocallabchrrt, + chrrt->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + if (a == darkness) { if (listener) { listener->panelChanged(Evlocallabdarkness, @@ -831,10 +1402,10 @@ void LocallabRetinex::adjusterChanged(Adjuster* a, double newval) } } - if (a == dehaz) { + if (a == cliptm) { if (listener) { - listener->panelChanged(Evlocallabdehaz, - dehaz->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + listener->panelChanged(Evlocallabcliptm, + cliptm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } @@ -845,45 +1416,45 @@ void LocallabRetinex::adjusterChanged(Adjuster* a, double newval) } } - if (a == sensih) { - if (listener) { - listener->panelChanged(Evlocallabsensih, - sensih->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); - } - } - - if (a == blendMask) { + if (a == blendmaskreti) { if (listener) { listener->panelChanged(Evlocallabblendmaskreti, - blendMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + blendmaskreti->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == radMask) { + if (a == radmaskreti) { if (listener) { listener->panelChanged(Evlocallabradmaskreti, - radMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + radmaskreti->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == chroMask) { + if (a == lapmaskreti) { + if (listener) { + listener->panelChanged(Evlocallablapmaskreti, + lapmaskreti->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chromaskreti) { if (listener) { listener->panelChanged(Evlocallabchromaskreti, - chroMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + chromaskreti->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == gamMask) { + if (a == gammaskreti) { if (listener) { listener->panelChanged(Evlocallabgammaskreti, - gamMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + gammaskreti->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == sloMask) { + if (a == slomaskreti) { if (listener) { listener->panelChanged(Evlocallabslomaskreti, - sloMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + slomaskreti->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } } @@ -892,6 +1463,13 @@ void LocallabRetinex::adjusterChanged(Adjuster* a, double newval) void LocallabRetinex::curveChanged(CurveEditor* ce) { if (isLocActivated && exp->getEnabled()) { + if (ce == cTtransshape) { + if (listener) { + listener->panelChanged(EvlocallabCTtransCurve, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + if (ce == cTgainshape) { if (listener) { listener->panelChanged(EvlocallabCTgainCurve, @@ -899,26 +1477,33 @@ void LocallabRetinex::curveChanged(CurveEditor* ce) } } - if (ce == CCMaskShape) { + if (ce == CCmaskretishape) { if (listener) { listener->panelChanged(EvlocallabCCmaskretishape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } - if (ce == LLMaskShape) { + if (ce == LLmaskretishape) { if (listener) { listener->panelChanged(EvlocallabLLmaskretishape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } - if (ce == HHMaskShape) { + if (ce == HHmaskretishape) { if (listener) { listener->panelChanged(EvlocallabHHmaskretishape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } + + if (ce == Lmaskretishape) { + if (listener) { + listener->panelChanged(EvlocallabLmaskretishape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } } } @@ -937,48 +1522,52 @@ void LocallabRetinex::enabledChanged() } } -void LocallabRetinex::enaMaskChanged() +void LocallabRetinex::updateMaskBackground(const double normChromar, const double normLumar, const double normHuer) +{ + idle_register.add( + [this, normHuer, normLumar, normChromar]() -> bool { + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected + + // Update mask background + CCmaskretishape->updateLocallabBackground(normChromar); + LLmaskretishape->updateLocallabBackground(normLumar); + HHmaskretishape->updateLocallabBackground(normHuer); + + return false; + } + ); +} + +void LocallabRetinex::lumonlyChanged() { if (isLocActivated && exp->getEnabled()) { if (listener) { - if (enaMask->get_active()) { - listener->panelChanged(EvLocallabEnaretiMask, + if (lumonly->get_active()) { + listener->panelChanged(Evlocallablumonly, M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); } else { - listener->panelChanged(EvLocallabEnaretiMask, + listener->panelChanged(Evlocallablumonly, M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); } } } } -void LocallabRetinex::enaMaskTrMapChanged() +void LocallabRetinex::loglinChanged() { if (isLocActivated && exp->getEnabled()) { if (listener) { - if (enaMaskTrMap->get_active()) { - listener->panelChanged(EvLocallabEnaretiMasktmap, + if (loglin->get_active()) { + listener->panelChanged(Evlocallabloglin, M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); } else { - listener->panelChanged(EvLocallabEnaretiMasktmap, + listener->panelChanged(Evlocallabloglin, M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); } } } } -void LocallabRetinex::showMaskMethodChanged() -{ - // If mask preview is activated, deactivate all other tool mask preview - if (locToolListener) { - locToolListener->resetOtherMaskView(this); - } - - if (listener) { - listener->panelChanged(EvlocallabshowmaskMethod, ""); - } -} - void LocallabRetinex::retinexMethodChanged() { if (isLocActivated && exp->getEnabled()) { @@ -1019,6 +1608,48 @@ void LocallabRetinex::equilretChanged() } } +void LocallabRetinex::showmaskretiMethodChanged() +{ + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskMethod, ""); + } +} + +void LocallabRetinex::enaretiMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enaretiMask->get_active()) { + listener->panelChanged(EvLocallabEnaretiMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnaretiMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabRetinex::enaretiMasktmapChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enaretiMasktmap->get_active()) { + listener->panelChanged(EvLocallabEnaretiMasktmap, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnaretiMasktmap, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + void LocallabRetinex::inversretChanged() { // Update Retinex GUI according to inversret button state @@ -1037,17 +1668,19 @@ void LocallabRetinex::inversretChanged() } } -void LocallabRetinex::updateRetinexGUI() +void LocallabRetinex::updateRetinexGUI1() { // Update Retinex GUI according to scalereti adjuster value if (scalereti->getValue() == 1) { - // limd->hide(); - LocalcurveEditorgainT->hide(); retinexMethod->hide(); + softradiusret->hide(); + LocalcurveEditortransT->hide(); + LocalcurveEditorgainT->hide(); } else { - // limd->show(); - LocalcurveEditorgainT->show(); retinexMethod->show(); + softradiusret->show(); + LocalcurveEditortransT->show(); + LocalcurveEditorgainT->show(); } } @@ -1055,15 +1688,24 @@ void LocallabRetinex::updateRetinexGUI2() { // Update Retinex GUI according to inversret button state if (inversret->get_active()) { - maskExp->hide(); + expmaskreti->hide(); } else { - maskExp->show(); + expmaskreti->show(); + } +} + +void LocallabRetinex::updateRetinexGUI3() +{ + if (str->getValue() >= 0.1f) { + retitoolFrame->show(); + } else { + retitoolFrame->hide(); } } /* ==== LocallabSharp ==== */ LocallabSharp::LocallabSharp(): - LocallabTool(this, M("TP_LOCALLAB_SHARP_TOOLNAME"), M("TP_LOCALLAB_SHARP"), true, MaskNone), + LocallabTool(this, M("TP_LOCALLAB_SHARP_TOOLNAME"), M("TP_LOCALLAB_SHARP"), true), // Sharpening specific widgets sharcontrast(Gtk::manage(new Adjuster(M("TP_SHARPENING_CONTRAST"), 0, 200, 1, 20))), @@ -1073,9 +1715,17 @@ LocallabSharp::LocallabSharp(): shariter(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHARITER"), 5, 100, 1, 30))), sharblur(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHARBLUR"), 0.2, 2.0, 0.05, 0.2))), sensisha(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIS"), 0, 100, 1, 19))), - inverssha(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))) + inverssha(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))), + sharFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_SHARFRAME")))), + showmasksharMethod(Gtk::manage(new MyComboBoxText())) { const bool showtooltip = options.showtooltip; + const int complexsoft = options.complexity; + + // Parameter Sharpening specific widgets + if (showtooltip) { + exp->set_tooltip_text(M("TP_LOCALLAB_EXPSHARP_TOOLTIP")); + } sharcontrast->setAdjusterListener(this); @@ -1095,16 +1745,50 @@ LocallabSharp::LocallabSharp(): sensisha->setAdjusterListener(this); - inversshaConn = inverssha->signal_toggled().connect(sigc::mem_fun(*this, &LocallabSharp::inversshaChanged)); + inversshaConn = inverssha->signal_toggled().connect(sigc::mem_fun(*this, &LocallabSharp::inversshaChanged)); + sharFrame->set_label_align(0.025, 0.5); + + showmasksharMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmasksharMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showmasksharMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); + showmasksharMethod->set_active(0); + + if (showtooltip) { + showmasksharMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmasksharMethodConn = showmasksharMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabSharp::showmasksharMethodChanged)); + + // Add Sharpening specific widgets to GUI pack_start(*sharcontrast); pack_start(*sharradius); pack_start(*sharamount); - pack_start(*shardamping); - pack_start(*shariter); - pack_start(*sharblur); + + if (complexsoft < 2) { + pack_start(*shardamping); + pack_start(*shariter); + pack_start(*sharblur); + } + pack_start(*sensisha); pack_start(*inverssha); + ToolParamBlock* const sharfBox = Gtk::manage(new ToolParamBlock()); + sharfBox->pack_start(*showmasksharMethod); + sharFrame->add(*sharfBox); + pack_start(*sharFrame); +} + +void LocallabSharp::resetMaskView() +{ + showmasksharMethodConn.block(true); + showmasksharMethod->set_active(0); + showmasksharMethodConn.block(false); +} + +void LocallabSharp::getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask) +{ + sharMask = showmasksharMethod->get_active_row_number(); } void LocallabSharp::disableListener() @@ -1112,6 +1796,7 @@ void LocallabSharp::disableListener() LocallabTool::disableListener(); inversshaConn.block(true); + showmasksharMethodConn.block(true); } void LocallabSharp::enableListener() @@ -1119,10 +1804,13 @@ void LocallabSharp::enableListener() LocallabTool::enableListener(); inversshaConn.block(false); + showmasksharMethodConn.block(false); } void LocallabSharp::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { + const int complexsoft = options.complexity; + // Disable all listeners disableListener(); @@ -1133,15 +1821,23 @@ void LocallabSharp::read(const rtengine::procparams::ProcParams* pp, const Param spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot exp->set_visible(pp->locallab.spots.at(index).visisharp); - exp->setEnabled(pp->locallab.spots.at(index).expsharp); - sharcontrast->setValue(pp->locallab.spots.at(index).sharcontrast); + + sharcontrast->setValue((double)pp->locallab.spots.at(index).sharcontrast); sharradius->setValue(pp->locallab.spots.at(index).sharradius); - sharamount->setValue(pp->locallab.spots.at(index).sharamount); - shardamping->setValue(pp->locallab.spots.at(index).shardamping); - shariter->setValue(pp->locallab.spots.at(index).shariter); - sharblur->setValue(pp->locallab.spots.at(index).sharblur); - sensisha->setValue(pp->locallab.spots.at(index).sensisha); + sharamount->setValue((double)pp->locallab.spots.at(index).sharamount); + + if (complexsoft < 2) { + shardamping->setValue((double)pp->locallab.spots.at(index).shardamping); + shariter->setValue((double)pp->locallab.spots.at(index).shariter); + sharblur->setValue(pp->locallab.spots.at(index).sharblur); + } else { + shardamping->setValue(0.); + shariter->setValue(30.); + sharblur->setValue(0.2); + } + + sensisha->setValue((double)pp->locallab.spots.at(index).sensisha); inverssha->set_active(pp->locallab.spots.at(index).inverssha); } @@ -1157,7 +1853,6 @@ void LocallabSharp::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pe if (index < (int)pp->locallab.spots.size()) { pp->locallab.spots.at(index).expsharp = exp->getEnabled(); - pp->locallab.spots.at(index).visisharp = exp->get_visible(); pp->locallab.spots.at(index).sharcontrast = sharcontrast->getIntValue(); @@ -1277,34 +1972,125 @@ void LocallabSharp::inversshaChanged() } } +void LocallabSharp::showmasksharMethodChanged() +{ + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskMethod, ""); + } +} + /* ==== LocallabContrast ==== */ LocallabContrast::LocallabContrast(): - LocallabTool(this, M("TP_LOCALLAB_LC_TOOLNAME"), M("TP_LOCALLAB_LOC_CONTRAST"), false, MaskNone), + LocallabTool(this, M("TP_LOCALLAB_LC_TOOLNAME"), M("TP_LOCALLAB_LOC_CONTRAST"), true), // Local constrast specific widgets localcontMethod(Gtk::manage(new MyComboBoxText())), - lcradius(Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_RADIUS"), 20, 400, 1, 80))), + lcradius(Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_RADIUS"), 10, 100, 1, 80))), lcamount(Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_AMOUNT"), 0, 1.0, 0.01, 0))), lcdarkness(Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_DARKNESS"), 0, 3.0, 0.01, 1.0))), lclightness(Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_LIGHTNESS"), 0, 3.0, 0.01, 1.0))), LocalcurveEditorwav(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAV"))), - levelwav(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LEVELWAV"), 3, 9, 1, 4))), + wavshape(static_cast(LocalcurveEditorwav->addCurve(CT_Flat, "", nullptr, false, false))), + levelwav(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LEVELWAV"), 1, 9, 1, 4))), + csThreshold(Gtk::manage(new ThresholdAdjuster(M("TP_LOCALLAB_CSTHRESHOLD"), 0, 9, 0, 0, 6, 6, 0, false))), residcont(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RESIDCONT"), -100, 100, 1, 0))), - sensilc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIS"), 0, 100, 1, 19))), - fftwlc(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_FFTW")))) + residchro(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RESIDCHRO"), -100., 100., 1., 0.))), + sensilc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIS"), 0, 100, 1, 30))), + clariFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_CLARIFRA")))), + clarilres(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CLARILRES"), -20., 100., 0.5, 0.))), + claricres(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CLARICRES"), -20., 100., 0.5, 0.))), + clarisoft(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), -10.0, 1000.0, 0.5, 1.))), + origlc(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ORIGLC")))), + expcontrastpyr(Gtk::manage(new MyExpander(false, Gtk::manage(new Gtk::HBox())))), + gradwavFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_GRADWAVFRA")))), + wavgradl(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_GRALWFRA")))), + strwav(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -4.0, 4.0, 0.05, 0.))), + angwav(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))), + edgFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_EDGSHARPFRA")))), + wavedg(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_EDGFRA")))), + edgsBox(Gtk::manage(new ToolParamBlock())), + strengthw(Gtk::manage(new Adjuster(M("TP_WAVELET_EDVAL"), 0., 100.0, 0.5, 0.))), + LocalcurveEditorwavedg(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVEDG"))), + wavshapeedg(static_cast(LocalcurveEditorwavedg->addCurve(CT_Flat, "", nullptr, false, false))), + gradw(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGEDETECT"), 0., 100.0, 0.5, 90.))), + waveshow(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_EDGSHOW")))), + edgsBoxshow(Gtk::manage(new ToolParamBlock())), + radiusw(Gtk::manage(new Adjuster(M("TP_WAVELET_EDRAD"), 5., 100.0, 0.5, 15.))), + detailw(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGTHRESH"), -50., 100.0, 1., 10.))), + localedgMethod(Gtk::manage(new MyComboBoxText())), + tloww(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGEDETECTTHR"), 0., 100.0, 1., 20.))), + thigw(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGEDETECTTHR2"), -10., 100.0, 1., 0.))), + edgw(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGESENSI"), 0., 100.0, 1., 60.))), + basew(Gtk::manage(new Adjuster(M("TP_WAVELET_EDGEAMPLI"), 0., 100.0, 1., 10.))), + labmNP(Gtk::manage(new Gtk::Label(M("TP_WAVELET_NPTYPE") + ":"))), + localneiMethod(Gtk::manage(new MyComboBoxText())), + blurlevelFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_BLURLEVELFRA")))), + wavblur(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_BLURLEVELFRA")))), + levelblur(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LEVELBLUR"), 0., 100., 0.5, 0.))), + chromablu(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMABLU"), 0.01, 5., 0.01, 1.))), + LocalcurveEditorwavlev(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVLEV"))), + wavshapelev(static_cast(LocalcurveEditorwavlev->addCurve(CT_Flat, "", nullptr, false, false))), + residblur(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RESIDBLUR"), 0., 100., 0.5, 0.))), + blurlc(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_BLURLC")))), + expcontrastpyr2(Gtk::manage(new MyExpander(false, Gtk::manage(new Gtk::HBox())))), + contFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_CONTFRA")))), + wavcont(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_CONTFRA")))), + sigma(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SIGMAWAV"), 0.2, 2.5, 0.01, 1.))), + offset(Gtk::manage(new Adjuster(M("TP_LOCALLAB_OFFSETWAV"), 0.33, 1.66, 0.01, 1., Gtk::manage(new RTImage("circle-black-small.png")), Gtk::manage(new RTImage("circle-white-small.png"))))), + chromalev(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMALEV"), 0.01, 5., 0.01, 1.))), + LocalcurveEditorwavcon(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVCON"))), + wavshapecon(static_cast(LocalcurveEditorwavcon->addCurve(CT_Flat, "", nullptr, false, false))), + compreFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_COMPREFRA")))), + wavcompre(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_COMPREFRA")))), + LocalcurveEditorwavcompre(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVCOMPRE"))), + wavshapecompre(static_cast(LocalcurveEditorwavcompre->addCurve(CT_Flat, "", nullptr, false, false))), + threswav(Gtk::manage(new Adjuster(M("TP_LOCALLAB_THRESWAV"), 0.9, 2., 0.01, 1.4))), + residcomp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RESIDCOMP"), -1., 1., 0.01, 0.))), + compFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_COMPFRA")))), + wavcomp(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_COMPFRA")))), + fatdet(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATDETAIL"), -100., 300., 1., 0.))), + fatanch(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATANCHOR"), 1., 100., 1., 50., Gtk::manage(new RTImage("circle-black-small.png")), Gtk::manage(new RTImage("circle-white-small.png"))))), + LocalcurveEditorwavcomp(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVCOMP"))), + wavshapecomp(static_cast(LocalcurveEditorwavcomp->addCurve(CT_Flat, "", nullptr, false, false))), + fatres(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FATRES"), 0., 100., 1., 0.))), + fftwlc(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_FFTW")))), + expmasklc(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWLC")))), + showmasklcMethod(Gtk::manage(new MyComboBoxText())), + enalcMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), + masklcCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), + CCmasklcshape(static_cast(masklcCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false))), + LLmasklcshape(static_cast(masklcCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false))), + HHmasklcshape(static_cast(masklcCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true))), + blendmasklc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), + radmasklc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), -10.0, 1000.0, 0.1, 0.))), + chromasklc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), + mask2lcCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), + Lmasklcshape(static_cast(mask2lcCurveEditorG->addCurve(CT_Diagonal, "L(L)"))) { const bool showtooltip = options.showtooltip; + const int complexsoft = options.complexity; + + const LocallabParams::LocallabSpot defSpot; + + // Parameter Local contrast specific widgets + if (showtooltip) { + exp->set_tooltip_text(M("TP_LOCALLAB_EXPCONTRAST_TOOLTIP")); + } localcontMethod->append(M("TP_LOCALLAB_LOCCONT")); localcontMethod->append(M("TP_LOCALLAB_WAVE")); localcontMethod->set_active(0); - - if (showtooltip) { - // localcontMethod->set_tooltip_markup(M("TP_LOCALLAB_LOCMETHOD_TOOLTIP")); - } - localcontMethodConn = localcontMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabContrast::localcontMethodChanged)); + if (complexsoft == 2) { + lcradius->setLimits(20, 100, 1, 80); + } + lcradius->setAdjusterListener(this); lcamount->setAdjusterListener(this); @@ -1315,13 +2101,9 @@ LocallabContrast::LocallabContrast(): LocalcurveEditorwav->setCurveListener(this); - wavshape = static_cast(LocalcurveEditorwav->addCurve(CT_Flat, "", nullptr, false, false)); wavshape->setIdentityValue(0.); - wavshape->setResetCurve(FlatCurveType(LocallabParams::DEF_LC_CURVE.at(0)), LocallabParams::DEF_LC_CURVE); - - if (showtooltip) { - wavshape->setTooltip(M("TP_RETINEX_WAV_TOOLTIP")); - } + wavshape->setResetCurve(FlatCurveType(defSpot.locwavcurve.at(0)), defSpot.locwavcurve); + wavshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); LocalcurveEditorwav->curveListComplete(); @@ -1331,31 +2113,395 @@ LocallabContrast::LocallabContrast(): levelwav->setAdjusterListener(this); + csThreshold->setAdjusterListener(this); + residcont->setAdjusterListener(this); + residchro->setAdjusterListener(this); + sensilc->setAdjusterListener(this); + if (showtooltip) { + clariFrame->set_tooltip_markup(M("TP_LOCALLAB_CLARI_TOOLTIP")); + } + + clariFrame->set_label_align(0.025, 0.5); + + clarilres->setAdjusterListener(this); + + claricres->setAdjusterListener(this); + + clarisoft->setLogScale(10, -10); + clarisoft->setAdjusterListener(this); + + origlcConn = origlc->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::origlcChanged)); + + Gtk::HBox* const LCTitleHBox = Gtk::manage(new Gtk::HBox()); + Gtk::Label* const LCLabel = Gtk::manage(new Gtk::Label()); + LCLabel->set_markup(Glib::ustring("") + escapeHtmlChars(M("TP_LOCALLAB_LOC_CONTRASTPYR")) + Glib::ustring("") + escapeHtmlChars(M("TP_LOCALLAB_LOC_CONTRASTPYRLAB"))); + LCLabel->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + LCTitleHBox->pack_start(*LCLabel, Gtk::PACK_EXPAND_WIDGET, 0); + expcontrastpyr->setLabel(LCTitleHBox); + setExpandAlignProperties(expcontrastpyr, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + gradwavFrame->set_label_align(0.025, 0.5); + + wavgradlConn = wavgradl->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::wavgradlChanged)); + + strwav->setAdjusterListener(this); + + angwav->setAdjusterListener(this); + + edgFrame->set_label_align(0.025, 0.5); + + if (showtooltip) { + wavedg->set_tooltip_text(M("TP_LOCALLAB_WAVEEDG_TOOLTIP")); + } + + wavedgConn = wavedg->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::wavedgChanged)); + + strengthw->setAdjusterListener(this); + + LocalcurveEditorwavedg->setCurveListener(this); + + wavshapeedg->setIdentityValue(0.); + wavshapeedg->setResetCurve(FlatCurveType(defSpot.locedgwavcurve.at(0)), defSpot.locedgwavcurve); + + LocalcurveEditorwavedg->curveListComplete(); + + gradw->setAdjusterListener(this); + + waveshowConn = waveshow->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::waveshowChanged)); + + radiusw->setAdjusterListener(this); + + detailw->setAdjusterListener(this); + + localedgMethod->append(M("TP_WAVELET_RE1")); + localedgMethod->append(M("TP_WAVELET_RE2")); + localedgMethod->append(M("TP_WAVELET_RE3")); + localedgMethod->set_active(0); + localedgMethodConn = localedgMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabContrast::localedgMethodChanged)); + + tloww->setAdjusterListener(this); + + thigw->setAdjusterListener(this); + + edgw->setAdjusterListener(this); + + basew->setAdjusterListener(this); + + localneiMethod->append(M("TP_WAVELET_NPNONE")); + localneiMethod->append(M("TP_WAVELET_NPLOW")); + localneiMethod->append(M("TP_WAVELET_NPHIGH")); + localneiMethod->set_active(0); + localneiMethodConn = localneiMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabContrast::localneiMethodChanged)); + + blurlevelFrame->set_label_align(0.025, 0.5); + + wavblurConn = wavblur->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::wavblurChanged)); + + levelblur->setAdjusterListener(this); + + chromablu->setAdjusterListener(this); + + LocalcurveEditorwavlev->setCurveListener(this); + + wavshapelev->setIdentityValue(0.); + wavshapelev->setResetCurve(FlatCurveType(defSpot.loclevwavcurve.at(0)), defSpot.loclevwavcurve); + + LocalcurveEditorwavlev->curveListComplete(); + + residblur->setAdjusterListener(this); + + blurlcConn = blurlc->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::blurlcChanged)); + + Gtk::HBox* const LCTitleHBox2 = Gtk::manage(new Gtk::HBox()); + Gtk::Label* const LCLabel2 = Gtk::manage(new Gtk::Label()); + LCLabel2->set_markup(Glib::ustring("") + escapeHtmlChars(M("TP_LOCALLAB_LOC_CONTRASTPYR2")) + Glib::ustring("") + escapeHtmlChars(M("TP_LOCALLAB_LOC_CONTRASTPYR2LAB"))); + LCLabel2->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + LCTitleHBox2->pack_start(*LCLabel2, Gtk::PACK_EXPAND_WIDGET, 0); + expcontrastpyr2->setLabel(LCTitleHBox2); + setExpandAlignProperties(expcontrastpyr2, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + contFrame->set_label_align(0.025, 0.5); + + wavcontConn = wavcont->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::wavcontChanged)); + + sigma->setAdjusterListener(this); + + offset->setAdjusterListener(this); + + chromalev->setAdjusterListener(this); + + LocalcurveEditorwavcon->setCurveListener(this); + + wavshapecon->setIdentityValue(0.); + wavshapecon->setResetCurve(FlatCurveType(defSpot.locconwavcurve.at(0)), defSpot.locconwavcurve); + + LocalcurveEditorwavcon->curveListComplete(); + + compreFrame->set_label_align(0.025, 0.5); + + wavcompreConn = wavcompre->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::wavcompreChanged)); + + LocalcurveEditorwavcompre->setCurveListener(this); + + wavshapecompre->setIdentityValue(0.); + wavshapecompre->setResetCurve(FlatCurveType(defSpot.loccomprewavcurve.at(0)), defSpot.loccomprewavcurve); + + if (showtooltip) { + wavshapecompre->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP")); + } + + LocalcurveEditorwavcompre->curveListComplete(); + + threswav->setAdjusterListener(this); + + residcomp->setAdjusterListener(this); + + compFrame->set_label_align(0.025, 0.5); + + wavcompConn = wavcomp->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::wavcompChanged)); + + if (showtooltip) { + fatdet->set_tooltip_text(M("TP_LOCALLAB_COMPFRAME_TOOLTIP")); + } + + fatdet->setAdjusterListener(this); + + fatanch->setAdjusterListener(this); + + LocalcurveEditorwavcomp->setCurveListener(this); + + wavshapecomp->setIdentityValue(0.); + wavshapecomp->setResetCurve(FlatCurveType(defSpot.loccompwavcurve.at(0)), defSpot.loccompwavcurve); + + LocalcurveEditorwavcomp->curveListComplete(); + + fatres->setAdjusterListener(this); + if (showtooltip) { fftwlc->set_tooltip_text(M("TP_LOCALLAB_LC_FFTW_TOOLTIP")); } - fftwlcConn = fftwlc->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::fftwlcChanged)); + fftwlcConn = fftwlc->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::fftwlcChanged)); + + if (showtooltip) { + expmasklc->set_tooltip_markup(M("TP_LOCALLAB_MASK_TOOLTIP")); + } + + setExpandAlignProperties(expmasklc, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + showmasklcMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmasklcMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showmasklcMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); + showmasklcMethod->append(M("TP_LOCALLAB_SHOWMASK")); + showmasklcMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); + showmasklcMethod->set_active(0); + + if (showtooltip) { + showmasklcMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmasklcMethodConn = showmasklcMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabContrast::showmasklcMethodChanged)); + + enalcMaskConn = enalcMask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::enalcMaskChanged)); + + masklcCurveEditorG->setCurveListener(this); + + CCmasklcshape->setIdentityValue(0.); + CCmasklcshape->setResetCurve(FlatCurveType(defSpot.CCmasklccurve.at(0)), defSpot.CCmasklccurve); + + if (showtooltip) { + CCmasklcshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + CCmasklcshape->setBottomBarColorProvider(this, 1); + + LLmasklcshape->setIdentityValue(0.); + LLmasklcshape->setResetCurve(FlatCurveType(defSpot.LLmasklccurve.at(0)), defSpot.LLmasklccurve); + + if (showtooltip) { + LLmasklcshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + LLmasklcshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + HHmasklcshape->setIdentityValue(0.); + HHmasklcshape->setResetCurve(FlatCurveType(defSpot.HHmasklccurve.at(0)), defSpot.HHmasklccurve); + + if (showtooltip) { + HHmasklcshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + HHmasklcshape->setCurveColorProvider(this, 2); + HHmasklcshape->setBottomBarColorProvider(this, 2); + + masklcCurveEditorG->curveListComplete(); + + blendmasklc->setAdjusterListener(this); + + radmasklc->setLogScale(10, -10); + radmasklc->setAdjusterListener(this); + + chromasklc->setAdjusterListener(this); + + mask2lcCurveEditorG->setCurveListener(this); + + Lmasklcshape->setResetCurve(DiagonalCurveType(defSpot.Lmasklccurve.at(0)), defSpot.Lmasklccurve); + + if (showtooltip) { + Lmasklcshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + } + + Lmasklcshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + Lmasklcshape->setLeftBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + mask2lcCurveEditorG->curveListComplete(); + + // Add Local contrast specific widgets to GUI + if (complexsoft < 2) { + pack_start(*localcontMethod); + } - pack_start(*localcontMethod); pack_start(*lcradius); pack_start(*lcamount); pack_start(*lcdarkness); pack_start(*lclightness); - pack_start(*LocalcurveEditorwav, Gtk::PACK_SHRINK, 4); - pack_start(*levelwav); + pack_start(*LocalcurveEditorwav, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + // pack_start(*levelwav); + pack_start(*csThreshold); pack_start(*residcont); + pack_start(*residchro); pack_start(*sensilc); - pack_start(*fftwlc); + Gtk::HSeparator* const separatorcontr = Gtk::manage(new Gtk::HSeparator()); + pack_start(*separatorcontr); + ToolParamBlock* const clariBox = Gtk::manage(new ToolParamBlock()); + clariBox->pack_start(*clarilres); + clariBox->pack_start(*claricres); + clariBox->pack_start(*clarisoft); + clariBox->pack_start(*origlc); + clariFrame->add(*clariBox); + pack_start(*clariFrame); + ToolParamBlock* const blurcontBox = Gtk::manage(new ToolParamBlock()); + gradwavFrame->set_label_widget(*wavgradl); + ToolParamBlock* const gradwavBox = Gtk::manage(new ToolParamBlock()); + gradwavBox->pack_start(*strwav); + gradwavBox->pack_start(*angwav); + gradwavFrame->add(*gradwavBox); + blurcontBox->pack_start(*gradwavFrame); + edgFrame->set_label_widget(*wavedg); + edgsBox->pack_start(*strengthw); + edgsBox->pack_start(*LocalcurveEditorwavedg, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + edgsBox->pack_start(*gradw); + edgsBox->pack_start(*waveshow); + edgsBoxshow->pack_start(*radiusw); + edgsBoxshow->pack_start(*detailw); + Gtk::HBox* const edbox = Gtk::manage(new Gtk::HBox()); + Gtk::Label* const labmedgr = Gtk::manage(new Gtk::Label(M("TP_WAVELET_MEDGREINF") + ":")); + edbox->pack_start(*labmedgr, Gtk::PACK_SHRINK, 1); + edbox->pack_start(*localedgMethod); + edgsBoxshow->pack_start(*edbox); + Gtk::HSeparator* const separatoredg2 = Gtk::manage(new Gtk::HSeparator()); + edgsBoxshow->pack_start(*separatoredg2); + edgsBoxshow->pack_start(*tloww); + edgsBoxshow->pack_start(*thigw); + Gtk::HSeparator* const separatoredg = Gtk::manage(new Gtk::HSeparator()); + edgsBoxshow->pack_start(*separatoredg); + edgsBoxshow->pack_start(*edgw); + edgsBoxshow->pack_start(*basew); + Gtk::HBox* const ctboxNP = Gtk::manage(new Gtk::HBox()); + ctboxNP->pack_start(*labmNP, Gtk::PACK_SHRINK, 1); + ctboxNP->pack_start(*localneiMethod); + edgsBoxshow->pack_start(*ctboxNP); + edgsBox->pack_start(*edgsBoxshow); + edgFrame->add(*edgsBox); + blurcontBox->pack_start(*edgFrame); + blurlevelFrame->set_label_widget(*wavblur); + Gtk::VBox* const blurlevcontBox = Gtk::manage(new Gtk::VBox()); + blurlevcontBox->set_spacing(2); + blurlevcontBox->pack_start(*levelblur); + blurlevcontBox->pack_start(*chromablu); + blurlevcontBox->pack_start(*LocalcurveEditorwavlev, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + Gtk::HSeparator* const separatorblu = Gtk::manage(new Gtk::HSeparator()); + blurlevcontBox->pack_start(*separatorblu); + blurlevcontBox->pack_start(*residblur); + blurlevcontBox->pack_start(*blurlc); + blurlevelFrame->add(*blurlevcontBox); + blurcontBox->pack_start(*blurlevelFrame); + expcontrastpyr->add(*blurcontBox, false); + pack_start(*expcontrastpyr); + ToolParamBlock* const blurcontBox2 = Gtk::manage(new ToolParamBlock()); + Gtk::VBox* const contlevBox = Gtk::manage(new Gtk::VBox()); + contlevBox->set_spacing(2); + contFrame->set_label_widget(*wavcont); + contlevBox->pack_start(*sigma); + contlevBox->pack_start(*offset); + contlevBox->pack_start(*chromalev); + contlevBox->pack_start(*LocalcurveEditorwavcon, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + contFrame->add(*contlevBox); + blurcontBox2->pack_start(*contFrame); + Gtk::VBox* const compreBox = Gtk::manage(new Gtk::VBox()); + compreBox->set_spacing(2); + compreFrame->set_label_widget(*wavcompre); + compreBox->pack_start(*LocalcurveEditorwavcompre, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + compreBox->pack_start(*threswav); + compreBox->pack_start(*residcomp); + compreFrame->add(*compreBox); + blurcontBox2->pack_start(*compreFrame); + Gtk::VBox* const compBox = Gtk::manage(new Gtk::VBox()); + compBox->set_spacing(2); + compFrame->set_label_widget(*wavcomp); + compBox->pack_start(*fatdet); + compBox->pack_start(*fatanch); + compBox->pack_start(*LocalcurveEditorwavcomp, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + Gtk::HSeparator* const separatorcomp = Gtk::manage(new Gtk::HSeparator()); + compBox->pack_start(*separatorcomp); + compBox->pack_start(*fatres); + compFrame->add(*compBox); + blurcontBox2->pack_start(*compFrame); + expcontrastpyr2->add(*blurcontBox2, false); + pack_start(*expcontrastpyr2); + + if (complexsoft < 2) { + pack_start(*fftwlc); + } + + ToolParamBlock* const masklcBox = Gtk::manage(new ToolParamBlock()); + masklcBox->pack_start(*showmasklcMethod, Gtk::PACK_SHRINK, 4); + masklcBox->pack_start(*enalcMask, Gtk::PACK_SHRINK, 0); + masklcBox->pack_start(*masklcCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + masklcBox->pack_start(*blendmasklc, Gtk::PACK_SHRINK, 0); + masklcBox->pack_start(*radmasklc, Gtk::PACK_SHRINK, 0); + masklcBox->pack_start(*chromasklc, Gtk::PACK_SHRINK, 0); + masklcBox->pack_start(*mask2lcCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + expmasklc->add(*masklcBox, false); + pack_start(*expmasklc, false, false); } LocallabContrast::~LocallabContrast() { delete LocalcurveEditorwav; + delete LocalcurveEditorwavedg; + delete LocalcurveEditorwavlev; + delete LocalcurveEditorwavcon; + delete LocalcurveEditorwavcompre; + delete LocalcurveEditorwavcomp; + delete masklcCurveEditorG; + delete mask2lcCurveEditorG; +} + +void LocallabContrast::resetMaskView() +{ + showmasklcMethodConn.block(true); + showmasklcMethod->set_active(0); + showmasklcMethodConn.block(false); +} + +void LocallabContrast::getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask) +{ + lcMask = showmasklcMethod->get_active_row_number(); } void LocallabContrast::disableListener() @@ -1363,7 +2509,20 @@ void LocallabContrast::disableListener() LocallabTool::disableListener(); localcontMethodConn.block(true); + origlcConn.block(true); + wavgradlConn.block(true); + wavedgConn.block(true); + localedgMethodConn.block(true); + waveshowConn.block(true); + localneiMethodConn.block(true); + wavblurConn.block(true); + blurlcConn.block(true); + wavcontConn.block(true); + wavcompreConn.block(true); + wavcompConn.block(true); fftwlcConn.block(true); + showmasklcMethodConn.block(true); + enalcMaskConn.block(true); } void LocallabContrast::enableListener() @@ -1371,11 +2530,26 @@ void LocallabContrast::enableListener() LocallabTool::enableListener(); localcontMethodConn.block(false); + origlcConn.block(false); + wavgradlConn.block(false); + wavedgConn.block(false); + localedgMethodConn.block(false); + waveshowConn.block(false); + localneiMethodConn.block(false); + wavblurConn.block(false); + blurlcConn.block(false); + wavcontConn.block(false); + wavcompreConn.block(false); + wavcompConn.block(false); fftwlcConn.block(false); + showmasklcMethodConn.block(false); + enalcMaskConn.block(false); } void LocallabContrast::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { + const int complexsoft = options.complexity; + // Disable all listeners disableListener(); @@ -1386,31 +2560,115 @@ void LocallabContrast::read(const rtengine::procparams::ProcParams* pp, const Pa spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot exp->set_visible(pp->locallab.spots.at(index).visicontrast); - exp->setEnabled(pp->locallab.spots.at(index).expcontrast); - if (pp->locallab.spots.at(index).localcontMethod == "loc") { - localcontMethod->set_active(0); - } else if (pp->locallab.spots.at(index).localcontMethod == "wav") { + if (complexsoft < 2) { + if (pp->locallab.spots.at(index).localcontMethod == "loc") { + localcontMethod->set_active(0); + } else if (pp->locallab.spots.at(index).localcontMethod == "wav") { + localcontMethod->set_active(1); + } + } else { localcontMethod->set_active(1); } - lcradius->setValue(pp->locallab.spots.at(index).lcradius); + lcradius->setValue((double)pp->locallab.spots.at(index).lcradius); lcamount->setValue(pp->locallab.spots.at(index).lcamount); lcdarkness->setValue(pp->locallab.spots.at(index).lcdarkness); lclightness->setValue(pp->locallab.spots.at(index).lclightness); wavshape->setCurve(pp->locallab.spots.at(index).locwavcurve); - levelwav->setValue(pp->locallab.spots.at(index).levelwav); + levelwav->setValue((double)pp->locallab.spots.at(index).levelwav); + csThreshold->setValue(pp->locallab.spots.at(index).csthreshold); residcont->setValue(pp->locallab.spots.at(index).residcont); - sensilc->setValue(pp->locallab.spots.at(index).sensilc); - fftwlc->set_active(pp->locallab.spots.at(index).fftwlc); + residchro->setValue(pp->locallab.spots.at(index).residchro); + sensilc->setValue((double)pp->locallab.spots.at(index).sensilc); + clarilres->setValue(pp->locallab.spots.at(index).clarilres); + claricres->setValue(pp->locallab.spots.at(index).claricres); + clarisoft->setValue(pp->locallab.spots.at(index).clarisoft); + origlc->set_active(pp->locallab.spots.at(index).origlc); + wavgradl->set_active(pp->locallab.spots.at(index).wavgradl); + strwav->setValue(pp->locallab.spots.at(index).strwav); + angwav->setValue(pp->locallab.spots.at(index).angwav); + wavedg->set_active(pp->locallab.spots.at(index).wavedg); + strengthw->setValue(pp->locallab.spots.at(index).strengthw); + wavshapeedg->setCurve(pp->locallab.spots.at(index).locedgwavcurve); + gradw->setValue(pp->locallab.spots.at(index).gradw); + waveshow->set_active(pp->locallab.spots.at(index).waveshow); + radiusw->setValue(pp->locallab.spots.at(index).radiusw); + detailw->setValue(pp->locallab.spots.at(index).detailw); + + if (pp->locallab.spots.at(index).localedgMethod == "fir") { + localedgMethod->set_active(0); + } else if (pp->locallab.spots.at(index).localedgMethod == "sec") { + localedgMethod->set_active(1); + } else if (pp->locallab.spots.at(index).localedgMethod == "thr") { + localedgMethod->set_active(2); + } + + tloww->setValue(pp->locallab.spots.at(index).tloww); + thigw->setValue(pp->locallab.spots.at(index).thigw); + edgw->setValue(pp->locallab.spots.at(index).edgw); + basew->setValue(pp->locallab.spots.at(index).basew); + + if (pp->locallab.spots.at(index).localneiMethod == "none") { + localneiMethod->set_active(0); + } else if (pp->locallab.spots.at(index).localneiMethod == "low") { + localneiMethod->set_active(1); + } else if (pp->locallab.spots.at(index).localneiMethod == "high") { + localneiMethod->set_active(2); + } + + wavblur->set_active(pp->locallab.spots.at(index).wavblur); + levelblur->setValue(pp->locallab.spots.at(index).levelblur); + chromablu->setValue(pp->locallab.spots.at(index).chromablu); + wavshapelev->setCurve(pp->locallab.spots.at(index).loclevwavcurve); + residblur->setValue(pp->locallab.spots.at(index).residblur); + blurlc->set_active(pp->locallab.spots.at(index).blurlc); + wavcont->set_active(pp->locallab.spots.at(index).wavcont); + sigma->setValue(pp->locallab.spots.at(index).sigma); + offset->setValue(pp->locallab.spots.at(index).offset); + chromalev->setValue(pp->locallab.spots.at(index).chromalev); + wavshapecon->setCurve(pp->locallab.spots.at(index).locconwavcurve); + wavcompre->set_active(pp->locallab.spots.at(index).wavcompre); + wavshapecompre->setCurve(pp->locallab.spots.at(index).loccomprewavcurve); + threswav->setValue(pp->locallab.spots.at(index).threswav); + residcomp->setValue(pp->locallab.spots.at(index).residcomp); + wavcomp->set_active(pp->locallab.spots.at(index).wavcomp); + fatdet->setValue(pp->locallab.spots.at(index).fatdet); + fatanch->setValue(pp->locallab.spots.at(index).fatanch); + wavshapecomp->setCurve(pp->locallab.spots.at(index).loccompwavcurve); + fatres->setValue(pp->locallab.spots.at(index).fatres); + + if (complexsoft < 2) { + fftwlc->set_active(pp->locallab.spots.at(index).fftwlc); + } else { + fftwlc->set_active(false); + } + + enalcMask->set_active(pp->locallab.spots.at(index).enalcMask); + CCmasklcshape->setCurve(pp->locallab.spots.at(index).CCmasklccurve); + LLmasklcshape->setCurve(pp->locallab.spots.at(index).LLmasklccurve); + HHmasklcshape->setCurve(pp->locallab.spots.at(index).HHmasklccurve); + blendmasklc->setValue((double)pp->locallab.spots.at(index).blendmasklc); + radmasklc->setValue(pp->locallab.spots.at(index).radmasklc); + chromasklc->setValue(pp->locallab.spots.at(index).chromasklc); + Lmasklcshape->setCurve(pp->locallab.spots.at(index).Lmasklccurve); } // Enable all listeners enableListener(); - // Update Local constrast GUI according to localcontMethod combobox value - updateContrastGUI(); + // Update Local contrast GUI according to localcontMethod combobox value + updateContrastGUI1(); + + // Update Local contrast GUI according to wavedg button state + updateContrastGUI2(); + + // Update Local contrast GUI according to waveshow button state + updateContrastGUI3(); + + // Update Local contrast GUI according to fftwlc button state + updateContrastGUI4(); // Note: No need to manage pedited as batch mode is deactivated for Locallab } @@ -1421,7 +2679,6 @@ void LocallabContrast::write(rtengine::procparams::ProcParams* pp, ParamsEdited* if (index < (int)pp->locallab.spots.size()) { pp->locallab.spots.at(index).expcontrast = exp->getEnabled(); - pp->locallab.spots.at(index).visicontrast = exp->get_visible(); if (localcontMethod->get_active_row_number() == 0) { @@ -1436,9 +2693,75 @@ void LocallabContrast::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pp->locallab.spots.at(index).lclightness = lclightness->getValue(); pp->locallab.spots.at(index).locwavcurve = wavshape->getCurve(); pp->locallab.spots.at(index).levelwav = levelwav->getIntValue(); + pp->locallab.spots.at(index).csthreshold = csThreshold->getValue(); pp->locallab.spots.at(index).residcont = residcont->getValue(); + pp->locallab.spots.at(index).residchro = residchro->getValue(); pp->locallab.spots.at(index).sensilc = sensilc->getIntValue(); + pp->locallab.spots.at(index).clarilres = clarilres->getValue(); + pp->locallab.spots.at(index).claricres = claricres->getValue(); + pp->locallab.spots.at(index).clarisoft = clarisoft->getValue(); + pp->locallab.spots.at(index).origlc = origlc->get_active(); + pp->locallab.spots.at(index).wavgradl = wavgradl->get_active(); + pp->locallab.spots.at(index).strwav = strwav->getValue(); + pp->locallab.spots.at(index).angwav = angwav->getValue(); + pp->locallab.spots.at(index).wavedg = wavedg->get_active(); + pp->locallab.spots.at(index).strengthw = strengthw->getValue(); + pp->locallab.spots.at(index).locedgwavcurve = wavshapeedg->getCurve(); + pp->locallab.spots.at(index).gradw = gradw->getValue(); + pp->locallab.spots.at(index).waveshow = waveshow->get_active(); + pp->locallab.spots.at(index).radiusw = radiusw->getValue(); + pp->locallab.spots.at(index).detailw = detailw->getValue(); + + if (localedgMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).localedgMethod = "fir"; + } else if (localedgMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).localedgMethod = "sec"; + } else if (localedgMethod->get_active_row_number() == 2) { + pp->locallab.spots.at(index).localedgMethod = "thr"; + } + + pp->locallab.spots.at(index).tloww = tloww->getValue(); + pp->locallab.spots.at(index).thigw = thigw->getValue(); + pp->locallab.spots.at(index).edgw = edgw->getValue(); + pp->locallab.spots.at(index).basew = basew->getValue(); + + if (localneiMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).localneiMethod = "none"; + } else if (localneiMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).localneiMethod = "low"; + } else if (localneiMethod->get_active_row_number() == 2) { + pp->locallab.spots.at(index).localneiMethod = "high"; + } + + pp->locallab.spots.at(index).wavblur = wavblur->get_active(); + pp->locallab.spots.at(index).levelblur = levelblur->getValue(); + pp->locallab.spots.at(index).chromablu = chromablu->getValue(); + pp->locallab.spots.at(index).loclevwavcurve = wavshapelev->getCurve(); + pp->locallab.spots.at(index).residblur = residblur->getValue(); + pp->locallab.spots.at(index).blurlc = blurlc->get_active(); + pp->locallab.spots.at(index).wavcont = wavcont->get_active(); + pp->locallab.spots.at(index).sigma = sigma->getValue(); + pp->locallab.spots.at(index).offset = offset->getValue(); + pp->locallab.spots.at(index).chromalev = chromalev->getValue(); + pp->locallab.spots.at(index).locconwavcurve = wavshapecon->getCurve(); + pp->locallab.spots.at(index).wavcompre = wavcompre->get_active(); + pp->locallab.spots.at(index).loccomprewavcurve = wavshapecompre->getCurve(); + pp->locallab.spots.at(index).threswav = threswav->getValue(); + pp->locallab.spots.at(index).residcomp = residcomp->getValue(); + pp->locallab.spots.at(index).wavcomp = wavcomp->get_active(); + pp->locallab.spots.at(index).fatdet = fatdet->getValue(); + pp->locallab.spots.at(index).fatanch = fatanch->getValue(); + pp->locallab.spots.at(index).loccompwavcurve = wavshapecomp->getCurve(); + pp->locallab.spots.at(index).fatres = fatres->getValue(); pp->locallab.spots.at(index).fftwlc = fftwlc->get_active(); + pp->locallab.spots.at(index).enalcMask = enalcMask->get_active(); + pp->locallab.spots.at(index).CCmasklccurve = CCmasklcshape->getCurve(); + pp->locallab.spots.at(index).LLmasklccurve = LLmasklcshape->getCurve(); + pp->locallab.spots.at(index).HHmasklccurve = HHmasklcshape->getCurve(); + pp->locallab.spots.at(index).blendmasklc = blendmasklc->getIntValue(); + pp->locallab.spots.at(index).radmasklc = radmasklc->getValue(); + pp->locallab.spots.at(index).chromasklc = chromasklc->getValue(); + pp->locallab.spots.at(index).Lmasklccurve = Lmasklcshape->getCurve(); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -1451,14 +2774,43 @@ void LocallabContrast::setDefaults(const rtengine::procparams::ProcParams* defPa if (index < (int)defParams->locallab.spots.size()) { const LocallabParams::LocallabSpot defSpot = defParams->locallab.spots.at(index); - // Set default values for adjuster widgets + // Set default values for adjuster and threshold adjuster widgets lcradius->setDefault((double)defSpot.lcradius); lcamount->setDefault(defSpot.lcamount); lcdarkness->setDefault(defSpot.lcdarkness); lclightness->setDefault(defSpot.lclightness); - levelwav->setDefault(defSpot.levelwav); + levelwav->setDefault((double)defSpot.levelwav); + csThreshold->setDefault(defSpot.csthreshold); residcont->setDefault(defSpot.residcont); + residchro->setDefault(defSpot.residchro); sensilc->setDefault((double)defSpot.sensilc); + clarilres->setDefault(defSpot.clarilres); + claricres->setDefault(defSpot.claricres); + clarisoft->setDefault(defSpot.clarisoft); + strwav->setDefault(defSpot.strwav); + angwav->setDefault(defSpot.angwav); + strengthw->setDefault(defSpot.strengthw); + gradw->setDefault(defSpot.gradw); + radiusw->setDefault(defSpot.radiusw); + detailw->setDefault(defSpot.detailw); + tloww->setDefault(defSpot.tloww); + thigw->setDefault(defSpot.thigw); + edgw->setDefault(defSpot.edgw); + basew->setDefault(defSpot.basew); + levelblur->setDefault(defSpot.levelblur); + chromablu->setDefault(defSpot.chromablu); + residblur->setDefault(defSpot.residblur); + sigma->setDefault(defSpot.sigma); + offset->setDefault(defSpot.offset); + chromalev->setDefault(defSpot.chromalev); + threswav->setDefault(defSpot.threswav); + residcomp->setDefault(defSpot.residcomp); + fatdet->setDefault(defSpot.fatdet); + fatanch->setDefault(defSpot.fatanch); + fatres->setDefault(defSpot.fatres); + blendmasklc->setDefault((double)defSpot.blendmasklc); + radmasklc->setDefault(defSpot.radmasklc); + chromasklc->setDefault(defSpot.chromasklc); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -1509,12 +2861,218 @@ void LocallabContrast::adjusterChanged(Adjuster* a, double newval) } } + if (a == residchro) { + if (listener) { + listener->panelChanged(Evlocallabresidchro, + residchro->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + if (a == sensilc) { if (listener) { listener->panelChanged(Evlocallabsensilc, sensilc->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } + + if (a == clarilres) { + if (listener) { + listener->panelChanged(Evlocallabclarilres, + clarilres->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == claricres) { + if (listener) { + listener->panelChanged(Evlocallabclaricres, + claricres->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == clarisoft) { + if (listener) { + listener->panelChanged(Evlocallabclarisoft, + clarisoft->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strwav) { + if (listener) { + listener->panelChanged(Evlocallabstrwav, + strwav->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == angwav) { + if (listener) { + listener->panelChanged(Evlocallabangwav, + angwav->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strengthw) { + if (listener) { + listener->panelChanged(Evlocallabstrengthw, + strengthw->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == gradw) { + if (listener) { + listener->panelChanged(Evlocallabgradw, + gradw->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == radiusw) { + if (listener) { + listener->panelChanged(Evlocallabradiusw, + radiusw->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == detailw) { + if (listener) { + listener->panelChanged(Evlocallabdetailw, + detailw->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == tloww) { + if (listener) { + listener->panelChanged(Evlocallabtloww, + tloww->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == thigw) { + if (listener) { + listener->panelChanged(Evlocallabthigw, + thigw->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == edgw) { + if (listener) { + listener->panelChanged(Evlocallabedgw, + edgw->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == basew) { + if (listener) { + listener->panelChanged(Evlocallabbasew, + basew->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == levelblur) { + if (listener) { + listener->panelChanged(Evlocallablevelblur, + levelblur->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chromablu) { + if (listener) { + listener->panelChanged(Evlocallabchromablu, + chromablu->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == residblur) { + if (listener) { + listener->panelChanged(Evlocallabresidblur, + residblur->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sigma) { + if (listener) { + listener->panelChanged(Evlocallabsigma, + sigma->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == offset) { + if (listener) { + listener->panelChanged(Evlocallaboffset, + offset->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chromalev) { + if (listener) { + listener->panelChanged(Evlocallabchromalev, + chromalev->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == threswav) { + if (listener) { + listener->panelChanged(Evlocallabthreswav, + threswav->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == residcomp) { + if (listener) { + listener->panelChanged(Evlocallabresidcomp, + residcomp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == fatdet) { + if (listener) { + listener->panelChanged(Evlocallabfatdet, + fatdet->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == fatanch) { + if (listener) { + listener->panelChanged(Evlocallabfatanch, + fatanch->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == fatres) { + if (listener) { + listener->panelChanged(Evlocallabfatres, + fatres->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blendmasklc) { + if (listener) { + listener->panelChanged(Evlocallabblendmasklc, + blendmasklc->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == radmasklc) { + if (listener) { + listener->panelChanged(Evlocallabradmasklc, + radmasklc->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chromasklc) { + if (listener) { + listener->panelChanged(Evlocallabchromasklc, + chromasklc->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabcsThreshold, + csThreshold->getHistoryString() + " (" + escapeHtmlChars(spotName) + ")"); + } } } @@ -1527,6 +3085,69 @@ void LocallabContrast::curveChanged(CurveEditor* ce) M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } + + if (ce == wavshapeedg) { + if (listener) { + listener->panelChanged(EvlocallabwavCurveedg, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == wavshapelev) { + if (listener) { + listener->panelChanged(EvlocallabwavCurvelev, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == wavshapecon) { + if (listener) { + listener->panelChanged(EvlocallabwavCurvecon, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == wavshapecompre) { + if (listener) { + listener->panelChanged(EvlocallabwavCurvecompre, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == wavshapecomp) { + if (listener) { + listener->panelChanged(EvlocallabwavCurvecomp, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == CCmasklcshape) { + if (listener) { + listener->panelChanged(EvlocallabCCmasklcshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == LLmasklcshape) { + if (listener) { + listener->panelChanged(EvlocallabLLmasklcshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == HHmasklcshape) { + if (listener) { + listener->panelChanged(EvlocallabHHmasklcshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == Lmasklcshape) { + if (listener) { + listener->panelChanged(EvlocallabLmasklcshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } } } @@ -1545,10 +3166,26 @@ void LocallabContrast::enabledChanged() } } +void LocallabContrast::updateMaskBackground(const double normChromar, const double normLumar, const double normHuer) +{ + idle_register.add( + [this, normHuer, normLumar, normChromar]() -> bool { + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected + + // Update mask background + CCmasklcshape->updateLocallabBackground(normChromar); + LLmasklcshape->updateLocallabBackground(normLumar); + HHmasklcshape->updateLocallabBackground(normHuer); + + return false; + } + ); +} + void LocallabContrast::localcontMethodChanged() { - // Update Local constrast GUI according to localcontMethod combobox value - updateContrastGUI(); + // Update Local contrast GUI according to localcontMethod combobox value + updateContrastGUI1(); if (isLocActivated && exp->getEnabled()) { if (listener) { @@ -1558,8 +3195,172 @@ void LocallabContrast::localcontMethodChanged() } } +void LocallabContrast::origlcChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (origlc->get_active()) { + listener->panelChanged(Evlocallaboriglc, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallaboriglc, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::wavgradlChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (wavgradl->get_active()) { + listener->panelChanged(Evlocallabwavgradl, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabwavgradl, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::wavedgChanged() +{ + // Update Local contrast GUI according to wavedg button state + updateContrastGUI2(); + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (wavedg->get_active()) { + listener->panelChanged(Evlocallabwavedg, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabwavedg, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::localedgMethodChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallablocaledgMethod, + localedgMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +void LocallabContrast::waveshowChanged() +{ + // Update Local contrast GUI according to waveshow button state + updateContrastGUI3(); + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (waveshow->get_active()) { + listener->panelChanged(Evlocallabwaveshow, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabwaveshow, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::localneiMethodChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallablocalneiMethod, + localneiMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +void LocallabContrast::wavblurChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (wavblur->get_active()) { + listener->panelChanged(Evlocallabwavblur, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabwavblur, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::blurlcChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (blurlc->get_active()) { + listener->panelChanged(Evlocallabblurlc, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabblurlc, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::wavcontChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (wavcont->get_active()) { + listener->panelChanged(Evlocallabwavcont, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabwavcont, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::wavcompreChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (wavcompre->get_active()) { + listener->panelChanged(Evlocallabwavcompre, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabwavcompre, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::wavcompChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (wavcomp->get_active()) { + listener->panelChanged(Evlocallabwavcomp, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabwavcomp, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + void LocallabContrast::fftwlcChanged() { + // Update Local contrast GUI according to fftwlc button state + updateContrastGUI4(); + if (isLocActivated && exp->getEnabled()) { if (listener) { if (fftwlc->get_active()) { @@ -1573,9 +3374,36 @@ void LocallabContrast::fftwlcChanged() } } -void LocallabContrast::updateContrastGUI() +void LocallabContrast::showmasklcMethodChanged() { - // Update Local constrast GUI according to localcontMethod combobox value + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskMethod, ""); + } +} + +void LocallabContrast::enalcMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enalcMask->get_active()) { + listener->panelChanged(EvLocallabEnalcMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnalcMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::updateContrastGUI1() +{ + // Update Local contrast GUI according to localcontMethod combobox value if (localcontMethod->get_active_row_number() == 0) { lcradius->show(); lcamount->show(); @@ -1583,7 +3411,36 @@ void LocallabContrast::updateContrastGUI() lclightness->show(); LocalcurveEditorwav->hide(); levelwav->hide(); + csThreshold->hide(); residcont->hide(); + residchro->hide(); + clariFrame->hide(); + strwav->hide(); + angwav->hide(); + strengthw->hide(); + LocalcurveEditorwavedg->hide(); + gradw->hide(); + radiusw->hide(); + detailw->hide(); + tloww->hide(); + thigw->hide(); + edgw->hide(); + basew->hide(); + levelblur->hide(); + chromablu->hide(); + LocalcurveEditorwavlev->hide(); + residblur->hide(); + sigma->hide(); + offset->hide(); + chromalev->hide(); + LocalcurveEditorwavcon->hide(); + LocalcurveEditorwavcompre->hide(); + threswav->hide(); + residcomp->hide(); + fatdet->hide(); + fatanch->hide(); + LocalcurveEditorwavcomp->hide(); + fatres->hide(); fftwlc->show(); } else if (localcontMethod->get_active_row_number() == 1) { lcradius->hide(); @@ -1592,37 +3449,86 @@ void LocallabContrast::updateContrastGUI() lclightness->hide(); LocalcurveEditorwav->show(); levelwav->show(); + csThreshold->show(); residcont->show(); + residchro->show(); + clariFrame->show(); + strwav->show(); + angwav->show(); + strengthw->show(); + LocalcurveEditorwavedg->show(); + gradw->show(); + radiusw->show(); + detailw->show(); + tloww->show(); + thigw->show(); + edgw->show(); + basew->show(); + levelblur->show(); + chromablu->show(); + LocalcurveEditorwavlev->show(); + residblur->show(); + sigma->show(); + offset->show(); + chromalev->show(); + LocalcurveEditorwavcon->show(); + LocalcurveEditorwavcompre->show(); + threswav->show(); + residcomp->show(); + fatdet->show(); + fatanch->show(); + LocalcurveEditorwavcomp->show(); + fatres->show(); fftwlc->hide(); } } -/* ==== LocallabCBDL ==== */ -LocallabCBDL::LocallabCBDL(): - LocallabTool(this, M("TP_LOCALLAB_CBDL_TOOLNAME"), M("TP_LOCALLAB_CBDL"), true, MaskNormal), - - // CBDL specific widgets - chromacbdl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMACBDL"), 0., 1.5, 0.01, 0.))), - threshold(Gtk::manage(new Adjuster(M("TP_DIRPYREQUALIZER_THRESHOLD"), 0, 1., 0.01, 0.2))), - blurcbdl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURCBDL"), 0., 100., 0.1, 0.))), - clarityml(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CLARITYML"), 0.1, 100., 0.1, 0.1))), - contresid(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CONTRESID"), -100, 100, 1, 0))), - softradiuscb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.1, 0.))), - sensicb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSICB"), 0, 100, 1, 15))), - - lumacontrastMinusButton(Gtk::manage(new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_MINUS")))), - lumaneutralButton(Gtk::manage(new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMANEUTRAL")))), - lumacontrastPlusButton(Gtk::manage(new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_PLUS")))) +void LocallabContrast::updateContrastGUI2() { - const bool showtooltip = options.showtooltip; + // Update Local contrast GUI according to wavedg button state + if (wavedg->get_active()) { + edgsBox->show(); + } else { + edgsBox->hide(); + } +} - if (showtooltip) { - exp->set_tooltip_text(M("TP_LOCALLAB_EXPCBDL_TOOLTIP")); +void LocallabContrast::updateContrastGUI3() +{ + // Update Local contrast GUI according to waveshow button state + if (waveshow->get_active()) { + edgsBoxshow->show(); + } else { + edgsBoxshow->hide(); + } +} + +void LocallabContrast::updateContrastGUI4() +{ + // Update Local contrast GUI according to fftwlc button state + const double temp = lcradius->getValue(); + + if (fftwlc->get_active()) { + lcradius->setLimits(20, 1000, 1, 80); + } else { + lcradius->setLimits(20, 100, 1, 80); } - for (int i = 0; i < 6; i++) { - Glib::ustring ss; - ss = Glib::ustring::format(i); + lcradius->setValue(temp); +} + +/* ==== LocallabCBDL ==== */ +LocallabCBDL::LocallabCBDL(): + LocallabTool(this, M("TP_LOCALLAB_CBDL_TOOLNAME"), M("TP_LOCALLAB_CBDL"), true), + + // CBDL specific widgets + multiplier( + [this]() -> std::array + { + std::array res = {}; + + for (unsigned int i = 0; i < res.size(); ++i) { + Glib::ustring ss = Glib::ustring::format(i); if (i == 0) { ss += Glib::ustring::compose(" (%1)", M("TP_DIRPYREQUALIZER_LUMAFINEST")); @@ -1630,8 +3536,53 @@ LocallabCBDL::LocallabCBDL(): ss += Glib::ustring::compose(" (%1)", M("TP_DIRPYREQUALIZER_LUMACOARSEST")); } - multiplier[i] = Gtk::manage(new Adjuster(std::move(ss), 0.0, 4.0, 0.01, 1.0)); - multiplier[i]->setAdjusterListener(this); + res[i] = Gtk::manage(new Adjuster(std::move(ss), 0.0, 4.0, 0.01, 1.0)); + } + + return res; + } + () + ), + chromacbdl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMACBDL"), 0., 1.5, 0.01, 0.))), + threshold(Gtk::manage(new Adjuster(M("TP_DIRPYREQUALIZER_THRESHOLD"), 0, 1., 0.01, 0.2))), + blurcbdl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURCBDL"), 0., 100., 0.1, 0.))), + residFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_RESID")))), + clarityml(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CLARITYML"), 0.1, 100., 0.1, 0.1))), + contresid(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CONTRESID"), -100, 100, 1, 0))), + softradiuscb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), -10.0, 1000.0, 0.5, 0.))), + sensicb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSICB"), 0, 100, 1, 15))), + expmaskcb(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWCB")))), + showmaskcbMethod(Gtk::manage(new MyComboBoxText())), + enacbMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), + maskcbCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK"))), + CCmaskcbshape(static_cast(maskcbCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false))), + LLmaskcbshape(static_cast(maskcbCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false))), + HHmaskcbshape(static_cast(maskcbCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true))), + blendmaskcb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0))), + radmaskcb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), -10.0, 1000.0, 0.1, 0.))), + lapmaskcb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPMASKCOL"), 0.0, 100.0, 0.1, 0.))), + chromaskcb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.))), + gammaskcb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.25, 4.0, 0.01, 1.))), + slomaskcb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.))), + mask2cbCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK2"))), + Lmaskcbshape(static_cast(mask2cbCurveEditorG->addCurve(CT_Diagonal, "L(L)"))), + + lumacontrastMinusButton(Gtk::manage(new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_MINUS")))), + lumaneutralButton(Gtk::manage(new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMANEUTRAL")))), + lumacontrastPlusButton(Gtk::manage(new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_PLUS")))) +{ + const bool showtooltip = options.showtooltip; + const int complexsoft = options.complexity; + + const LocallabParams::LocallabSpot defSpot; + + // Parameter CBDL specific widgets + if (showtooltip) { + exp->set_tooltip_text(M("TP_LOCALLAB_EXPCBDL_TOOLTIP")); + } + + for (const auto adj : multiplier) { + adj->setAdjusterListener(this); } if (showtooltip) { @@ -1644,10 +3595,13 @@ LocallabCBDL::LocallabCBDL(): blurcbdl->setAdjusterListener(this); + residFrame->set_label_align(0.025, 0.5); + clarityml->setAdjusterListener(this); contresid->setAdjusterListener(this); + softradiuscb->setLogScale(10, -10); softradiuscb->setAdjusterListener(this); if (showtooltip) { @@ -1656,20 +3610,106 @@ LocallabCBDL::LocallabCBDL(): sensicb->setAdjusterListener(this); + if (showtooltip) { + expmaskcb->set_tooltip_markup(M("TP_LOCALLAB_MASK_TOOLTIP")); + } + + showmaskcbMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmaskcbMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showmaskcbMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); + showmaskcbMethod->append(M("TP_LOCALLAB_SHOWMASK")); + showmaskcbMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); + showmaskcbMethod->set_active(0); + + if (showtooltip) { + showmaskcbMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showmaskcbMethodConn = showmaskcbMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabCBDL::showmaskcbMethodChanged)); + + enacbMaskConn = enacbMask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabCBDL::enacbMaskChanged)); + + maskcbCurveEditorG->setCurveListener(this); + + CCmaskcbshape->setIdentityValue(0.); + CCmaskcbshape->setResetCurve(FlatCurveType(defSpot.CCmaskcbcurve.at(0)), defSpot.CCmaskcbcurve); + + if (showtooltip) { + CCmaskcbshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + CCmaskcbshape->setBottomBarColorProvider(this, 1); + + LLmaskcbshape->setIdentityValue(0.); + LLmaskcbshape->setResetCurve(FlatCurveType(defSpot.LLmaskcbcurve.at(0)), defSpot.LLmaskcbcurve); + + if (showtooltip) { + LLmaskcbshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + LLmaskcbshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + HHmaskcbshape->setIdentityValue(0.); + HHmaskcbshape->setResetCurve(FlatCurveType(defSpot.HHmaskcbcurve.at(0)), defSpot.HHmaskcbcurve); + + if (showtooltip) { + HHmaskcbshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + HHmaskcbshape->setCurveColorProvider(this, 2); + HHmaskcbshape->setBottomBarColorProvider(this, 2); + + maskcbCurveEditorG->curveListComplete(); + + blendmaskcb->setAdjusterListener(this); + + if (showtooltip) { + radmaskcb->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + radmaskcb->setLogScale(10, -10); + radmaskcb->setAdjusterListener(this); + + if (showtooltip) { + lapmaskcb->set_tooltip_text(M("TP_LOCALLAB_LAPRAD_TOOLTIP")); + } + + lapmaskcb->setAdjusterListener(this); + + chromaskcb->setAdjusterListener(this); + + gammaskcb->setAdjusterListener(this); + + slomaskcb->setAdjusterListener(this); + + mask2cbCurveEditorG->setCurveListener(this); + + Lmaskcbshape->setResetCurve(DiagonalCurveType(defSpot.Lmaskcbcurve.at(0)), defSpot.Lmaskcbcurve); + + if (showtooltip) { + Lmaskcbshape->setTooltip(M("TP_LOCALLAB_LMASK_LL_TOOLTIP")); + } + + Lmaskcbshape->setBottomBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + Lmaskcbshape->setLeftBarBgGradient({{0., 0., 0., 0.}, {1., 1., 1., 1.}}); + + mask2cbCurveEditorG->curveListComplete(); + lumacontrastMinusPressedConn = lumacontrastMinusButton->signal_pressed().connect(sigc::mem_fun(*this, &LocallabCBDL::lumacontrastMinusPressed)); lumaneutralPressedConn = lumaneutralButton->signal_pressed().connect(sigc::mem_fun(*this, &LocallabCBDL::lumaneutralPressed)); lumacontrastPlusPressedConn = lumacontrastPlusButton->signal_pressed().connect(sigc::mem_fun(*this, &LocallabCBDL::lumacontrastPlusPressed)); + // Add CBDL specific widgets to GUI Gtk::HBox* buttonBox = Gtk::manage(new Gtk::HBox(true, 10)); buttonBox->pack_start(*lumacontrastMinusButton); buttonBox->pack_start(*lumaneutralButton); buttonBox->pack_start(*lumacontrastPlusButton); pack_start(*buttonBox); - for (int i = 0; i < 6; i++) { - pack_start(*multiplier[i]); + for (const auto adj : multiplier) { + pack_start(*adj); } Gtk::HSeparator* const separator = Gtk::manage(new Gtk::HSeparator()); @@ -1677,8 +3717,6 @@ LocallabCBDL::LocallabCBDL(): pack_start(*chromacbdl); pack_start(*threshold); pack_start(*blurcbdl); - Gtk::Frame* const residFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_RESID"))); - residFrame->set_label_align(0.025, 0.5); ToolParamBlock* const residBox = Gtk::manage(new ToolParamBlock()); residBox->pack_start(*clarityml); residBox->pack_start(*contresid); @@ -1686,17 +3724,50 @@ LocallabCBDL::LocallabCBDL(): pack_start(*residFrame); pack_start(*softradiuscb); pack_start(*sensicb); + ToolParamBlock* const maskcbBox = Gtk::manage(new ToolParamBlock()); + maskcbBox->pack_start(*showmaskcbMethod, Gtk::PACK_SHRINK, 4); + maskcbBox->pack_start(*enacbMask, Gtk::PACK_SHRINK, 0); + maskcbBox->pack_start(*maskcbCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + maskcbBox->pack_start(*blendmaskcb, Gtk::PACK_SHRINK, 0); + maskcbBox->pack_start(*radmaskcb, Gtk::PACK_SHRINK, 0); + + if (complexsoft < 1) { + maskcbBox->pack_start(*lapmaskcb, Gtk::PACK_SHRINK, 0); + } + + maskcbBox->pack_start(*chromaskcb, Gtk::PACK_SHRINK, 0); + maskcbBox->pack_start(*gammaskcb, Gtk::PACK_SHRINK, 0); + maskcbBox->pack_start(*slomaskcb, Gtk::PACK_SHRINK, 0); + maskcbBox->pack_start(*mask2cbCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + expmaskcb->add(*maskcbBox, false); + pack_start(*expmaskcb, false, false); } -void LocallabCBDL::getMaskView(int &colorMask, int &expMask, int &shMask, int &softMask, int &tmMask, int &retiMask, int &cbMask) +LocallabCBDL::~LocallabCBDL() { - cbMask = showMaskMethod->get_active_row_number(); + delete maskcbCurveEditorG; + delete mask2cbCurveEditorG; +} + +void LocallabCBDL::resetMaskView() +{ + showmaskcbMethodConn.block(true); + showmaskcbMethod->set_active(0); + showmaskcbMethodConn.block(false); +} + +void LocallabCBDL::getMaskView(int &colorMask, int &colorMaskinv, int &expMask, int &expMaskinv, int &shMask, int &shMaskinv, int &vibMask, int &softMask, int &blMask, int &tmMask, int &retiMask, int &sharMask, int &lcMask, int &cbMask) +{ + cbMask = showmaskcbMethod->get_active_row_number(); } void LocallabCBDL::disableListener() { LocallabTool::disableListener(); + showmaskcbMethodConn.block(true); + enacbMaskConn.block(true); + lumacontrastMinusPressedConn.block(true); lumaneutralPressedConn.block(true); lumacontrastPlusPressedConn.block(true); @@ -1706,6 +3777,9 @@ void LocallabCBDL::enableListener() { LocallabTool::enableListener(); + showmaskcbMethodConn.block(false); + enacbMaskConn.block(false); + lumacontrastMinusPressedConn.block(false); lumaneutralPressedConn.block(false); lumacontrastPlusPressedConn.block(false); @@ -1713,6 +3787,8 @@ void LocallabCBDL::enableListener() void LocallabCBDL::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { + const int complexsoft = options.complexity; + // Disable all listeners disableListener(); @@ -1723,7 +3799,6 @@ void LocallabCBDL::read(const rtengine::procparams::ProcParams* pp, const Params spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot exp->set_visible(pp->locallab.spots.at(index).visicbdl); - exp->setEnabled(pp->locallab.spots.at(index).expcbdl); for (int i = 0; i < 6; i++) { @@ -1734,18 +3809,26 @@ void LocallabCBDL::read(const rtengine::procparams::ProcParams* pp, const Params threshold->setValue(pp->locallab.spots.at(index).threshold); blurcbdl->setValue(pp->locallab.spots.at(index).blurcbdl); clarityml->setValue(pp->locallab.spots.at(index).clarityml); - contresid->setValue(pp->locallab.spots.at(index).contresid); + contresid->setValue((double)pp->locallab.spots.at(index).contresid); softradiuscb->setValue(pp->locallab.spots.at(index).softradiuscb); - sensicb->setValue(pp->locallab.spots.at(index).sensicb); - enaMask->set_active(pp->locallab.spots.at(index).enacbMask); - CCMaskShape->setCurve(pp->locallab.spots.at(index).CCmaskcbcurve); - LLMaskShape->setCurve(pp->locallab.spots.at(index).LLmaskcbcurve); - HHMaskShape->setCurve(pp->locallab.spots.at(index).HHmaskcbcurve); - blendMask->setValue(pp->locallab.spots.at(index).blendmaskcb); - radMask->setValue(pp->locallab.spots.at(index).radmaskcb); - chroMask->setValue(pp->locallab.spots.at(index).chromaskcb); - gamMask->setValue(pp->locallab.spots.at(index).gammaskcb); - sloMask->setValue(pp->locallab.spots.at(index).slomaskcb); + sensicb->setValue((double)pp->locallab.spots.at(index).sensicb); + enacbMask->set_active(pp->locallab.spots.at(index).enacbMask); + CCmaskcbshape->setCurve(pp->locallab.spots.at(index).CCmaskcbcurve); + LLmaskcbshape->setCurve(pp->locallab.spots.at(index).LLmaskcbcurve); + HHmaskcbshape->setCurve(pp->locallab.spots.at(index).HHmaskcbcurve); + blendmaskcb->setValue((double)pp->locallab.spots.at(index).blendmaskcb); + radmaskcb->setValue(pp->locallab.spots.at(index).radmaskcb); + + if (complexsoft == 0) { + lapmaskcb->setValue(pp->locallab.spots.at(index).lapmaskcb); + } else { + lapmaskcb->setValue(0.); + } + + chromaskcb->setValue(pp->locallab.spots.at(index).chromaskcb); + gammaskcb->setValue(pp->locallab.spots.at(index).gammaskcb); + slomaskcb->setValue(pp->locallab.spots.at(index).slomaskcb); + Lmaskcbshape->setCurve(pp->locallab.spots.at(index).Lmaskcbcurve); } // Enable all listeners @@ -1760,7 +3843,6 @@ void LocallabCBDL::write(rtengine::procparams::ProcParams* pp, ParamsEdited* ped if (index < (int)pp->locallab.spots.size()) { pp->locallab.spots.at(index).expcbdl = exp->getEnabled(); - pp->locallab.spots.at(index).visicbdl = exp->get_visible(); for (int i = 0; i < 6; i++) { @@ -1774,15 +3856,17 @@ void LocallabCBDL::write(rtengine::procparams::ProcParams* pp, ParamsEdited* ped pp->locallab.spots.at(index).contresid = contresid->getIntValue(); pp->locallab.spots.at(index).softradiuscb = softradiuscb->getValue(); pp->locallab.spots.at(index).sensicb = sensicb->getIntValue(); - pp->locallab.spots.at(index).enacbMask = enaMask->get_active(); - pp->locallab.spots.at(index).LLmaskcbcurve = LLMaskShape->getCurve(); - pp->locallab.spots.at(index).CCmaskcbcurve = CCMaskShape->getCurve(); - pp->locallab.spots.at(index).HHmaskcbcurve = HHMaskShape->getCurve(); - pp->locallab.spots.at(index).blendmaskcb = blendMask->getIntValue(); - pp->locallab.spots.at(index).radmaskcb = radMask->getValue(); - pp->locallab.spots.at(index).chromaskcb = chroMask->getValue(); - pp->locallab.spots.at(index).gammaskcb = gamMask->getValue(); - pp->locallab.spots.at(index).slomaskcb = sloMask->getValue(); + pp->locallab.spots.at(index).enacbMask = enacbMask->get_active(); + pp->locallab.spots.at(index).LLmaskcbcurve = LLmaskcbshape->getCurve(); + pp->locallab.spots.at(index).CCmaskcbcurve = CCmaskcbshape->getCurve(); + pp->locallab.spots.at(index).HHmaskcbcurve = HHmaskcbshape->getCurve(); + pp->locallab.spots.at(index).blendmaskcb = blendmaskcb->getIntValue(); + pp->locallab.spots.at(index).radmaskcb = radmaskcb->getValue(); + pp->locallab.spots.at(index).lapmaskcb = lapmaskcb->getValue(); + pp->locallab.spots.at(index).chromaskcb = chromaskcb->getValue(); + pp->locallab.spots.at(index).gammaskcb = gammaskcb->getValue(); + pp->locallab.spots.at(index).slomaskcb = slomaskcb->getValue(); + pp->locallab.spots.at(index).Lmaskcbcurve = Lmaskcbshape->getCurve(); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -1807,11 +3891,12 @@ void LocallabCBDL::setDefaults(const rtengine::procparams::ProcParams* defParams contresid->setDefault((double)defSpot.contresid); softradiuscb->setDefault(defSpot.softradiuscb); sensicb->setDefault((double)defSpot.sensicb); - blendMask->setDefault((double)defSpot.blendmaskcb); - radMask->setDefault(defSpot.radmaskcb); - chroMask->setDefault(defSpot.chromaskcb); - gamMask->setDefault(defSpot.gammaskcb); - sloMask->setDefault(defSpot.slomaskcb); + blendmaskcb->setDefault((double)defSpot.blendmaskcb); + radmaskcb->setDefault(defSpot.radmaskcb); + lapmaskcb->setDefault(defSpot.lapmaskcb); + chromaskcb->setDefault(defSpot.chromaskcb); + gammaskcb->setDefault(defSpot.gammaskcb); + slomaskcb->setDefault(defSpot.slomaskcb); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -1883,38 +3968,45 @@ void LocallabCBDL::adjusterChanged(Adjuster* a, double newval) } } - if (a == blendMask) { + if (a == blendmaskcb) { if (listener) { listener->panelChanged(Evlocallabblendmaskcb, - blendMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + blendmaskcb->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == radMask) { + if (a == radmaskcb) { if (listener) { listener->panelChanged(Evlocallabradmaskcb, - radMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + radmaskcb->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == chroMask) { + if (a == lapmaskcb) { + if (listener) { + listener->panelChanged(Evlocallablapmaskcb, + lapmaskcb->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chromaskcb) { if (listener) { listener->panelChanged(Evlocallabchromaskcb, - chroMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + chromaskcb->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == gamMask) { + if (a == gammaskcb) { if (listener) { listener->panelChanged(Evlocallabgammaskcb, - gamMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + gammaskcb->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } - if (a == sloMask) { + if (a == slomaskcb) { if (listener) { listener->panelChanged(Evlocallabslomaskcb, - sloMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + slomaskcb->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); } } } @@ -1923,26 +4015,33 @@ void LocallabCBDL::adjusterChanged(Adjuster* a, double newval) void LocallabCBDL::curveChanged(CurveEditor* ce) { if (isLocActivated && exp->getEnabled()) { - if (ce == CCMaskShape) { + if (ce == CCmaskcbshape) { if (listener) { listener->panelChanged(EvlocallabCCmaskcbshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } - if (ce == LLMaskShape) { + if (ce == LLmaskcbshape) { if (listener) { listener->panelChanged(EvlocallabLLmaskcbshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } - if (ce == HHMaskShape) { + if (ce == HHmaskcbshape) { if (listener) { listener->panelChanged(EvlocallabHHmaskcbshape, M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); } } + + if (ce == Lmaskcbshape) { + if (listener) { + listener->panelChanged(EvlocallabLmaskcbshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } } } @@ -1961,22 +4060,23 @@ void LocallabCBDL::enabledChanged() } } -void LocallabCBDL::enaMaskChanged() +void LocallabCBDL::updateMaskBackground(const double normChromar, const double normLumar, const double normHuer) { - if (isLocActivated && exp->getEnabled()) { - if (listener) { - if (enaMask->get_active()) { - listener->panelChanged(EvLocallabEnacbMask, - M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); - } else { - listener->panelChanged(EvLocallabEnacbMask, - M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); - } - } + idle_register.add( + [this, normHuer, normLumar, normChromar]() -> bool { + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected + + // Update mask background + CCmaskcbshape->updateLocallabBackground(normChromar); + LLmaskcbshape->updateLocallabBackground(normLumar); + HHmaskcbshape->updateLocallabBackground(normHuer); + + return false; } + ); } -void LocallabCBDL::showMaskMethodChanged() +void LocallabCBDL::showmaskcbMethodChanged() { // If mask preview is activated, deactivate all other tool mask preview if (locToolListener) { @@ -1988,6 +4088,21 @@ void LocallabCBDL::showMaskMethodChanged() } } +void LocallabCBDL::enacbMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enacbMask->get_active()) { + listener->panelChanged(EvLocallabEnacbMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnacbMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + void LocallabCBDL::lumacontrastMinusPressed() { for (int i = 0; i < 6; i++) { @@ -2022,24 +4137,45 @@ void LocallabCBDL::lumacontrastPlusPressed() /* ==== LocallabDenoise ==== */ LocallabDenoise::LocallabDenoise(): - LocallabTool(this, M("TP_LOCALLAB_DEN_TOOLNAME"), M("TP_LOCALLAB_DENOIS"), true, MaskNone), + LocallabTool(this, M("TP_LOCALLAB_DEN_TOOLNAME"), M("TP_LOCALLAB_DENOIS"), true), // Denoise specific widgets - noiselumf0(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINEZERO"), MINCHRO, MAXCHRO, 1, 0))), - noiselumf(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINE"), MINCHRO, MAXCHRO, 1, 0))), - noiselumf2(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINETWO"), MINCHRO, MAXCHRO, 1, 0))), - noiselumc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMCOARSE"), MINCHRO, MAXCHROCC, 1, 0))), - noiselumdetail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMDETAIL"), 0, 100, 1, 0))), + LocalcurveEditorwavden(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAVDEN"))), + wavshapeden(static_cast(LocalcurveEditorwavden->addCurve(CT_Flat, "", nullptr, false, false))), + noiselumf0(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINEZERO"), MINCHRO, MAXCHRO, 0.01, 0.))), + noiselumf(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINE"), MINCHRO, MAXCHRO, 0.01, 0.))), + noiselumf2(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINETWO"), MINCHRO, MAXCHRO, 0.01, 0.))), + noiselumc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMCOARSE"), MINCHRO, MAXCHROCC, 0.01, 0.))), + noiselumdetail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMDETAIL"), 0., 100., 0.01, 0.))), noiselequal(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELEQUAL"), -2, 10, 1, 7, Gtk::manage(new RTImage("circle-white-small.png")), Gtk::manage(new RTImage("circle-black-small.png"))))), - noisechrof(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHROFINE"), MINCHRO, MAXCHRO, 1, 0))), - noisechroc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHROCOARSE"), MINCHRO, MAXCHROCC, 1, 0))), - noisechrodetail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHRODETAIL"), 0, 100, 1, 0))), + noisechrof(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHROFINE"), MINCHRO, MAXCHRO, 0.01, 0.))), + noisechroc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHROCOARSE"), MINCHRO, MAXCHROCC, 0.01, 0.))), + noisechrodetail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHRODETAIL"), 0., 100., 0.01, 0.))), + detailthr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DETAILTHR"), 0, 100, 1, 0))), adjblur(Gtk::manage(new Adjuster(M("TP_LOCALLAB_ADJ"), -100., 100., 1., 0., Gtk::manage(new RTImage("circle-blue-small.png")), Gtk::manage(new RTImage("circle-red-small.png"))))), bilateral(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BILATERAL"), 0, 100, 1, 0))), sensiden(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIDEN"), 0, 100, 1, 20))) { const bool showtooltip = options.showtooltip; + const LocallabParams::LocallabSpot defSpot; + + // Parameter Denoise specific widgets + if (showtooltip) { + exp->set_tooltip_markup(M("TP_LOCALLAB_DENOI_TOOLTIP")); + } + + LocalcurveEditorwavden->setCurveListener(this); + + wavshapeden->setIdentityValue(0.); + wavshapeden->setResetCurve(FlatCurveType(defSpot.locwavcurveden.at(0)), defSpot.locwavcurveden); + + if (showtooltip) { + wavshapeden->setTooltip(M("TP_LOCALLAB_WASDEN_TOOLTIP")); + } + + LocalcurveEditorwavden->curveListComplete(); + noiselumf0->setAdjusterListener(this); noiselumf->setAdjusterListener(this); @@ -2066,23 +4202,28 @@ LocallabDenoise::LocallabDenoise(): noisechrodetail->setAdjusterListener(this); + detailthr->setAdjusterListener(this); + adjblur->setAdjusterListener(this); bilateral->setAdjusterListener(this); sensiden->setAdjusterListener(this); + // Add Denoise specific widgets to GUI Gtk::Frame* const wavFrame = Gtk::manage(new Gtk::Frame()); ToolParamBlock* const wavBox = Gtk::manage(new ToolParamBlock()); - wavBox->pack_start(*noiselumf0); - wavBox->pack_start(*noiselumf); - wavBox->pack_start(*noiselumf2); - wavBox->pack_start(*noiselumc); + wavBox->pack_start(*LocalcurveEditorwavden, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + // wavBox->pack_start(*noiselumf0); + // wavBox->pack_start(*noiselumf); + // wavBox->pack_start(*noiselumf2); + // wavBox->pack_start(*noiselumc); wavBox->pack_start(*noiselumdetail); wavBox->pack_start(*noiselequal); wavBox->pack_start(*noisechrof); wavBox->pack_start(*noisechroc); - // wavBox->pack_start(*noisechrodetail); // Uncomment this line to use the noisechrodetail adjuster + wavBox->pack_start(*noisechrodetail); + wavBox->pack_start(*detailthr); wavBox->pack_start(*adjblur); wavFrame->add(*wavBox); pack_start(*wavFrame); @@ -2090,6 +4231,11 @@ LocallabDenoise::LocallabDenoise(): pack_start(*sensiden); } +LocallabDenoise::~LocallabDenoise() +{ + delete LocalcurveEditorwavden; +} + void LocallabDenoise::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { // Disable all listeners @@ -2102,20 +4248,22 @@ void LocallabDenoise::read(const rtengine::procparams::ProcParams* pp, const Par spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot exp->set_visible(pp->locallab.spots.at(index).visidenoi); - exp->setEnabled(pp->locallab.spots.at(index).expdenoi); + + wavshapeden->setCurve(pp->locallab.spots.at(index).locwavcurveden); noiselumf0->setValue(pp->locallab.spots.at(index).noiselumf0); noiselumf->setValue(pp->locallab.spots.at(index).noiselumf); noiselumf2->setValue(pp->locallab.spots.at(index).noiselumf2); noiselumc->setValue(pp->locallab.spots.at(index).noiselumc); noiselumdetail->setValue(pp->locallab.spots.at(index).noiselumdetail); - noiselequal->setValue(pp->locallab.spots.at(index).noiselequal); + noiselequal->setValue((double)pp->locallab.spots.at(index).noiselequal); noisechrof->setValue(pp->locallab.spots.at(index).noisechrof); noisechroc->setValue(pp->locallab.spots.at(index).noisechroc); noisechrodetail->setValue(pp->locallab.spots.at(index).noisechrodetail); - adjblur->setValue(pp->locallab.spots.at(index).adjblur); - bilateral->setValue(pp->locallab.spots.at(index).bilateral); - sensiden->setValue(pp->locallab.spots.at(index).sensiden); + detailthr->setValue((double)pp->locallab.spots.at(index).detailthr); + adjblur->setValue((double)pp->locallab.spots.at(index).adjblur); + bilateral->setValue((double)pp->locallab.spots.at(index).bilateral); + sensiden->setValue((double)pp->locallab.spots.at(index).sensiden); } // Enable all listeners @@ -2130,18 +4278,19 @@ void LocallabDenoise::write(rtengine::procparams::ProcParams* pp, ParamsEdited* if (index < (int)pp->locallab.spots.size()) { pp->locallab.spots.at(index).expdenoi = exp->getEnabled(); - pp->locallab.spots.at(index).visidenoi = exp->get_visible(); - pp->locallab.spots.at(index).noiselumf0 = noiselumf0->getIntValue(); - pp->locallab.spots.at(index).noiselumf = noiselumf->getIntValue(); - pp->locallab.spots.at(index).noiselumf2 = noiselumf2->getIntValue(); - pp->locallab.spots.at(index).noiselumc = noiselumc->getIntValue(); - pp->locallab.spots.at(index).noiselumdetail = noiselumdetail->getIntValue(); + pp->locallab.spots.at(index).locwavcurveden = wavshapeden->getCurve(); + pp->locallab.spots.at(index).noiselumf0 = noiselumf0->getValue(); + pp->locallab.spots.at(index).noiselumf = noiselumf->getValue(); + pp->locallab.spots.at(index).noiselumf2 = noiselumf2->getValue(); + pp->locallab.spots.at(index).noiselumc = noiselumc->getValue(); + pp->locallab.spots.at(index).noiselumdetail = noiselumdetail->getValue(); pp->locallab.spots.at(index).noiselequal = noiselequal->getIntValue(); - pp->locallab.spots.at(index).noisechrof = noisechrof->getIntValue(); - pp->locallab.spots.at(index).noisechroc = noisechroc->getIntValue(); - pp->locallab.spots.at(index).noisechrodetail = noisechrodetail->getIntValue(); + pp->locallab.spots.at(index).noisechrof = noisechrof->getValue(); + pp->locallab.spots.at(index).noisechroc = noisechroc->getValue(); + pp->locallab.spots.at(index).noisechrodetail = noisechrodetail->getValue(); + pp->locallab.spots.at(index).detailthr = detailthr->getIntValue(); pp->locallab.spots.at(index).adjblur = adjblur->getIntValue(); pp->locallab.spots.at(index).bilateral = bilateral->getIntValue(); pp->locallab.spots.at(index).sensiden = sensiden->getIntValue(); @@ -2158,15 +4307,16 @@ void LocallabDenoise::setDefaults(const rtengine::procparams::ProcParams* defPar const LocallabParams::LocallabSpot defSpot = defParams->locallab.spots.at(index); // Set default values for adjuster widgets - noiselumf0->setDefault((double)defSpot.noiselumf0); - noiselumf->setDefault((double)defSpot.noiselumf); - noiselumf2->setDefault((double)defSpot.noiselumf2); - noiselumc->setDefault((double)defSpot.noiselumc); - noiselumdetail->setDefault((double)defSpot.noiselumdetail); + noiselumf0->setDefault(defSpot.noiselumf0); + noiselumf->setDefault(defSpot.noiselumf); + noiselumf2->setDefault(defSpot.noiselumf2); + noiselumc->setDefault(defSpot.noiselumc); + noiselumdetail->setDefault(defSpot.noiselumdetail); noiselequal->setDefault((double)defSpot.noiselequal); - noisechrof->setDefault((double)defSpot.noisechrof); - noisechroc->setDefault((double)defSpot.noisechroc); - noisechrodetail->setDefault((double)defSpot.noisechrodetail); + noisechrof->setDefault(defSpot.noisechrof); + noisechroc->setDefault(defSpot.noisechroc); + noisechrodetail->setDefault(defSpot.noisechrodetail); + detailthr->setDefault((double)defSpot.detailthr); adjblur->setDefault((double)defSpot.adjblur); bilateral->setDefault((double)defSpot.bilateral); sensiden->setDefault((double)defSpot.sensiden); @@ -2241,6 +4391,13 @@ void LocallabDenoise::adjusterChanged(Adjuster* a, double newval) } } + if (a == detailthr) { + if (listener) { + listener->panelChanged(Evlocallabdetailthr, + detailthr->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + if (a == adjblur) { if (listener) { listener->panelChanged(Evlocallabadjblur, @@ -2264,6 +4421,18 @@ void LocallabDenoise::adjusterChanged(Adjuster* a, double newval) } } +void LocallabDenoise::curveChanged(CurveEditor* ce) +{ + if (isLocActivated && exp->getEnabled()) { + if (ce == wavshapeden) { + if (listener) { + listener->panelChanged(EvlocallabwavCurveden, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + void LocallabDenoise::enabledChanged() { if (isLocActivated) { @@ -2278,3 +4447,350 @@ void LocallabDenoise::enabledChanged() } } } + +/* ==== LocallabLog ==== */ +LocallabLog::LocallabLog(): + LocallabTool(this, M("TP_LOCALLAB_LOG_TOOLNAME"), M("TP_LOCALLAB_LOG"), false), + + // Log encoding specific widgets + logPFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LOGPFRA")))), + autocompute(Gtk::manage(new Gtk::ToggleButton(M("TP_LOCALLAB_LOGAUTO")))), + blackEv(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLACK_EV"), -16.0, 0.0, 0.1, -5.0))), + whiteEv(Gtk::manage(new Adjuster(M("TP_LOCALLAB_WHITE_EV"), 0.0, 32.0, 0.1, 10.0))), + fullimage(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_FULLIMAGE")))), + logFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LOGFRA")))), + Autogray(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_AUTOGRAY")))), + sourceGray(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOURCE_GRAY"), 1.0, 100.0, 0.1, 10.0))), + targetGray(Gtk::manage(new Adjuster(M("TP_LOCALLAB_TARGET_GRAY"), 5.0, 80.0, 0.1, 18.0))), + detail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DETAIL"), 0., 1., 0.01, 0.6))), + baselog(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BASELOG"), 1.3, 8., 0.05, 2., Gtk::manage(new RTImage("circle-black-small.png")), Gtk::manage(new RTImage("circle-white-small.png"))))), + sensilog(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSILOG"), 0, 100, 1, 50))), + gradlogFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_GRADLOGFRA")))), + strlog(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -2.0, 2.0, 0.05, 0.))), + anglog(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))) +{ + // Parameter Log encoding specific widgets + logPFrame->set_label_align(0.025, 0.5); + + autoconn = autocompute->signal_toggled().connect(sigc::mem_fun(*this, &LocallabLog::autocomputeToggled)); + + blackEv->setLogScale(2, -8); + blackEv->setAdjusterListener(this); + + whiteEv->setLogScale(16, 0); + whiteEv->setAdjusterListener(this); + + fullimageConn = fullimage->signal_toggled().connect(sigc::mem_fun(*this, &LocallabLog::fullimageChanged)); + + logFrame->set_label_align(0.025, 0.5); + + AutograyConn = Autogray->signal_toggled().connect(sigc::mem_fun(*this, &LocallabLog::AutograyChanged)); + + sourceGray->setAdjusterListener(this); + + targetGray->setAdjusterListener(this); + + detail->setAdjusterListener(this); + + baselog->setAdjusterListener(this); + + sensilog->setAdjusterListener(this); + + gradlogFrame->set_label_align(0.025, 0.5); + + strlog->setAdjusterListener(this); + + anglog->setAdjusterListener(this); + + // Add Log encoding specific widgets to HUI + ToolParamBlock* const logPBox = Gtk::manage(new ToolParamBlock()); + logPBox->pack_start(*autocompute); + logPBox->pack_start(*blackEv); + logPBox->pack_start(*whiteEv); + logPBox->pack_start(*fullimage); + logPFrame->add(*logPBox); + pack_start(*logPFrame); + ToolParamBlock* const logFBox = Gtk::manage(new ToolParamBlock()); + logFBox->pack_start(*Autogray); + logFBox->pack_start(*sourceGray); + logFrame->add(*logFBox); + pack_start(*logFrame); + pack_start(*targetGray); + pack_start(*detail); + pack_start(*baselog); + pack_start(*sensilog); + ToolParamBlock* const gradlogBox = Gtk::manage(new ToolParamBlock()); + gradlogBox->pack_start(*strlog); + gradlogBox->pack_start(*anglog); + gradlogFrame->add(*gradlogBox); + pack_start(*gradlogFrame); +} + +void LocallabLog::disableListener() +{ + LocallabTool::disableListener(); + + autoconn.block(true); + fullimageConn.block(true); + AutograyConn.block(true); +} + +void LocallabLog::enableListener() +{ + LocallabTool::enableListener(); + + autoconn.block(false); + fullimageConn.block(false); + AutograyConn.block(false); +} + +void LocallabLog::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + // Disable all listeners + disableListener(); + + // Update GUI to selected spot value + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot + + exp->set_visible(pp->locallab.spots.at(index).visilog); + exp->setEnabled(pp->locallab.spots.at(index).explog); + + autocompute->set_active(pp->locallab.spots.at(index).autocompute); + blackEv->setValue(pp->locallab.spots.at(index).blackEv); + whiteEv->setValue(pp->locallab.spots.at(index).whiteEv); + fullimage->set_active(pp->locallab.spots.at(index).fullimage); + Autogray->set_active(pp->locallab.spots.at(index).Autogray); + sourceGray->setValue(pp->locallab.spots.at(index).sourceGray); + targetGray->setValue(pp->locallab.spots.at(index).targetGray); + detail->setValue(pp->locallab.spots.at(index).detail); + baselog->setValue(pp->locallab.spots.at(index).baselog); + sensilog->setValue((double)pp->locallab.spots.at(index).sensilog); + strlog->setValue(pp->locallab.spots.at(index).strlog); + anglog->setValue(pp->locallab.spots.at(index).anglog); + } + + // Enable all listeners + enableListener(); + + // Update Log Encoding GUI according to autocompute button state + updateLogGUI(); + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabLog::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + pp->locallab.spots.at(index).explog = exp->getEnabled(); + pp->locallab.spots.at(index).visilog = exp->get_visible(); + + pp->locallab.spots.at(index).autocompute = autocompute->get_active(); + pp->locallab.spots.at(index).blackEv = blackEv->getValue(); + pp->locallab.spots.at(index).whiteEv = whiteEv->getValue(); + pp->locallab.spots.at(index).fullimage = fullimage->get_active(); + pp->locallab.spots.at(index).Autogray = Autogray->get_active(); + pp->locallab.spots.at(index).sourceGray = sourceGray->getValue(); + pp->locallab.spots.at(index).targetGray = targetGray->getValue(); + pp->locallab.spots.at(index).detail = detail->getValue(); + pp->locallab.spots.at(index).baselog = baselog->getValue(); + pp->locallab.spots.at(index).sensilog = sensilog->getIntValue(); + pp->locallab.spots.at(index).strlog = strlog->getValue(); + pp->locallab.spots.at(index).anglog = anglog->getValue(); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabLog::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + const int index = defParams->locallab.selspot; + + if (index < (int)defParams->locallab.spots.size()) { + const LocallabParams::LocallabSpot defSpot = defParams->locallab.spots.at(index); + + // Set default value for adjuster widgets + blackEv->setDefault(defSpot.blackEv); + whiteEv->setDefault(defSpot.whiteEv); + sourceGray->setDefault(defSpot.sourceGray); + targetGray->setDefault(defSpot.targetGray); + detail->setDefault(defSpot.detail); + baselog->setDefault(defSpot.baselog); + sensilog->setDefault((double)defSpot.sensilog); + strlog->setDefault(defSpot.strlog); + anglog->setDefault(defSpot.anglog); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabLog::adjusterChanged(Adjuster* a, double newval) +{ + if (isLocActivated && exp->getEnabled()) { + if (a == blackEv) { + if (listener) { + listener->panelChanged(EvlocallabblackEv, + blackEv->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == whiteEv) { + if (listener) { + listener->panelChanged(EvlocallabwhiteEv, + whiteEv->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sourceGray) { + if (listener) { + listener->panelChanged(EvlocallabsourceGray, + sourceGray->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == targetGray) { + if (listener) { + listener->panelChanged(EvlocallabtargetGray, + targetGray->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == detail) { + if (listener) { + listener->panelChanged(Evlocallabdetail, + detail->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == baselog) { + if (listener) { + listener->panelChanged(Evlocallabbaselog, + baselog->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sensilog) { + if (listener) { + listener->panelChanged(Evlocallabsensilog, + sensilog->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strlog) { + if (listener) { + listener->panelChanged(Evlocallabstrlog, + strlog->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == anglog) { + if (listener) { + listener->panelChanged(Evlocallabanglog, + anglog->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabLog::updateAutocompute(const float blackev, const float whiteev, const float sourceg, const float targetg) +{ + idle_register.add( + [this, blackev, whiteev, sourceg, targetg]() -> bool { + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected + + // Update adjuster values according to autocomputed ones + disableListener(); + + blackEv->setValue(blackev); + whiteEv->setValue(whiteev); + sourceGray->setValue(sourceg); + targetGray->setValue(targetg); + + enableListener(); + + return false; + } + ); +} + +void LocallabLog::enabledChanged() +{ + if (isLocActivated) { + if (listener) { + if (exp->getEnabled()) { + listener->panelChanged(EvLocenalog, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocenalog, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabLog::autocomputeToggled() +{ + // Update Log Encoding GUI according to autocompute button state + updateLogGUI(); + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (autocompute->get_active()) { + listener->panelChanged(EvLocallabAuto, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabAuto, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabLog::fullimageChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (fullimage->get_active()) { + listener->panelChanged(Evlocallabfullimage, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabfullimage, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabLog::AutograyChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (Autogray->get_active()) { + listener->panelChanged(EvlocallabAutogray, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvlocallabAutogray, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabLog::updateLogGUI() +{ + if (autocompute->get_active()) { + blackEv->set_sensitive(false); + whiteEv->set_sensitive(false); + sourceGray->set_sensitive(false); + targetGray->set_sensitive(false); + } else { + blackEv->set_sensitive(true); + whiteEv->set_sensitive(true); + sourceGray->set_sensitive(true); + targetGray->set_sensitive(true); + } +} diff --git a/rtgui/lockablecolorpicker.cc b/rtgui/lockablecolorpicker.cc index 859057e2c..071847424 100644 --- a/rtgui/lockablecolorpicker.cc +++ b/rtgui/lockablecolorpicker.cc @@ -14,19 +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 . */ #include "lockablecolorpicker.h" #include "options.h" #include "../rtengine/color.h" #include "../rtengine/rt_math.h" +#include "../rtengine/utils.h" #include "imagearea.h" #include "multilangmgr.h" #include "navigator.h" -extern Options options; - LockableColorPicker::LockableColorPicker (CropWindow* cropWindow, Glib::ustring *oProfile, Glib::ustring *wProfile) : cropWindow(cropWindow), displayedValues(ColorPickerType::RGB), position(0, 0), size(Size::S15), outputProfile(oProfile), workingProfile(wProfile), validity(Validity::OUTSIDE), @@ -241,7 +240,7 @@ void LockableColorPicker::updateBackBuffer () } -void LockableColorPicker::draw (Cairo::RefPtr &cr) +void LockableColorPicker::draw (const Cairo::RefPtr &cr) { if (validity == Validity::OUTSIDE) { return; @@ -285,12 +284,12 @@ void LockableColorPicker::setRGB (const float R, const float G, const float B, c } } -void LockableColorPicker::getImagePosition (rtengine::Coord &imgPos) +void LockableColorPicker::getImagePosition (rtengine::Coord &imgPos) const { imgPos = position; } -void LockableColorPicker::getScreenPosition (rtengine::Coord &screenPos) +void LockableColorPicker::getScreenPosition (rtengine::Coord &screenPos) const { if (cropWindow) { cropWindow->imageCoordToScreen(position.x, position.y, screenPos.x, screenPos.y); @@ -329,7 +328,7 @@ void LockableColorPicker::setSize (Size newSize) } } -LockableColorPicker::Size LockableColorPicker::getSize () +LockableColorPicker::Size LockableColorPicker::getSize () const { return size; } diff --git a/rtgui/lockablecolorpicker.h b/rtgui/lockablecolorpicker.h index cafea26be..baeea41ef 100644 --- a/rtgui/lockablecolorpicker.h +++ b/rtgui/lockablecolorpicker.h @@ -14,15 +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 . */ +#pragma once -#ifndef __COLORPICKER__ -#define __COLORPICKER__ - +#include "guiutils.h" #include "../rtengine/coord.h" -#include "guiutils.h" class CropWindow; @@ -35,7 +33,7 @@ public: virtual void switchPickerVisibility(bool isVisible) = 0; }; -class LockableColorPicker : BackBuffer +class LockableColorPicker final : BackBuffer { public: enum class Size { @@ -76,14 +74,14 @@ public: LockableColorPicker (CropWindow* cropWindow, Glib::ustring *oProfile, Glib::ustring *wProfile); - void draw (Cairo::RefPtr &cr); + void draw (const Cairo::RefPtr &cr); // Used to update the RGB color, the HSV values will be updated accordingly void setPosition (const rtengine::Coord &newPos); void setRGB (const float R, const float G, const float B, const float previewR, const float previewG, const float previewB); - void getImagePosition (rtengine::Coord &imgPos); - void getScreenPosition (rtengine::Coord &screenPos); - Size getSize (); + void getImagePosition (rtengine::Coord &imgPos) const; + void getScreenPosition (rtengine::Coord &screenPos) const; + Size getSize () const; bool isOver (int x, int y); void setValidity (Validity isValid); void setSize (Size newSize); @@ -93,5 +91,3 @@ public: bool cycleRGB (); bool cycleHSV (); }; - -#endif diff --git a/rtgui/lwbutton.cc b/rtgui/lwbutton.cc index 3c97ff6bb..26d36f9e0 100644 --- a/rtgui/lwbutton.cc +++ b/rtgui/lwbutton.cc @@ -14,10 +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 . */ #include "lwbutton.h" #include "guiutils.h" +#include "rtsurface.h" 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) @@ -152,7 +153,7 @@ bool LWButton::releaseNotify (int x, int y) { bool in = inside (x, y); - State nstate = state; + State nstate; bool action = false; if (in && (state == Pressed_In || state == Pressed_Out)) { diff --git a/rtgui/lwbutton.h b/rtgui/lwbutton.h index 12dbb6346..a98f1fe46 100644 --- a/rtgui/lwbutton.h +++ b/rtgui/lwbutton.h @@ -14,14 +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 _LWBUTTON_ -#define _LWBUTTON_ +#pragma once #include #include "rtsurface.h" - class LWButton; class LWButtonListener @@ -78,5 +76,3 @@ public: void redraw (Cairo::RefPtr context); }; - -#endif diff --git a/rtgui/lwbuttonset.cc b/rtgui/lwbuttonset.cc index d4d39bfe3..f475cf0b3 100644 --- a/rtgui/lwbuttonset.cc +++ b/rtgui/lwbuttonset.cc @@ -14,9 +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 . */ #include "lwbuttonset.h" +#include "lwbutton.h" +#include "rtscalable.h" LWButtonSet::LWButtonSet () : aw(0), ah(0), ax(-1), ay(-1) { diff --git a/rtgui/lwbuttonset.h b/rtgui/lwbuttonset.h index fa33620ae..63bc5a01b 100644 --- a/rtgui/lwbuttonset.h +++ b/rtgui/lwbuttonset.h @@ -14,14 +14,15 @@ * GNU General Public License for more details. * * 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 -#include "lwbutton.h" #include +class LWButton; +class LWButtonListener; class LWButtonSet { diff --git a/rtgui/main-cli.cc b/rtgui/main-cli.cc index cbea1d477..c60cba070 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__ @@ -33,6 +33,7 @@ #include #include "../rtengine/procparams.h" #include "../rtengine/profilestore.h" +#include "../rtengine/rtengine.h" #include "options.h" #include "soundman.h" #include "rtimage.h" @@ -55,8 +56,6 @@ // Set this to 1 to make RT work when started with Eclipse and arguments, at least on Windows platform #define ECLIPSE_ARGS 0 -extern Options options; - // stores path to data files Glib::ustring argv0; Glib::ustring creditsPath; @@ -256,7 +255,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 +270,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 b42baee11..abe431bde 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__ @@ -33,12 +33,17 @@ #include #include #include +#include "cachemanager.h" +#include "editorpanel.h" +#include "filecatalog.h" +#include "filepanel.h" #include "options.h" #include "soundman.h" #include "rtimage.h" #include "version.h" #include "extprog.h" #include "../rtengine/dynamicprofile.h" +#include "../rtengine/procparams.h" #ifndef WIN32 #include @@ -48,13 +53,12 @@ #else #include #include "conio.h" +#include "windows.h" #endif // Set this to 1 to make RT work when started with Eclipse and arguments, at least on Windows platform #define ECLIPSE_ARGS 0 -extern Options options; - // stores path to data files Glib::ustring argv0; Glib::ustring creditsPath; @@ -221,7 +225,7 @@ bool init_rt() extProgStore->init(); SoundManager::init(); - if ( !options.rtSettings.verbose ) { + if (!rtengine::settings->verbose) { TIFFSetWarningHandler (nullptr); // avoid annoying message boxes } @@ -530,13 +534,13 @@ int main (int argc, char **argv) int ret = 0; if (options.pseudoHiDPISupport) { - // Reading/updating GDK_SCALE early if it exists - const gchar *gscale = g_getenv("GDK_SCALE"); - if (gscale && gscale[0] == '2') { - initialGdkScale = 2; - } - // HOMBRE: On Windows, if resolution is set to 200%, Gtk internal variables are SCALE=2 and DPI=96 - g_setenv("GDK_SCALE", "1", true); + // Reading/updating GDK_SCALE early if it exists + const gchar *gscale = g_getenv("GDK_SCALE"); + if (gscale && gscale[0] == '2') { + initialGdkScale = 2; + } + // HOMBRE: On Windows, if resolution is set to 200%, Gtk internal variables are SCALE=2 and DPI=96 + g_setenv("GDK_SCALE", "1", true); } gdk_threads_set_lock_functions (G_CALLBACK (myGdkLockEnter), (G_CALLBACK (myGdkLockLeave))); 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..902161eb2 100644 --- a/rtgui/multilangmgr.h +++ b/rtgui/multilangmgr.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 _MULTILANGMGR_ -#define _MULTILANGMGR_ +#pragma once #include #include @@ -45,5 +44,3 @@ inline Glib::ustring M (const std::string& key) { return langMgr.getStr (key); } - -#endif diff --git a/rtgui/mycurve.cc b/rtgui/mycurve.cc index 5684bec33..7401570c8 100644 --- a/rtgui/mycurve.cc +++ b/rtgui/mycurve.cc @@ -14,12 +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 "mycurve.h" #include "../rtengine/curves.h" #include #include +#include "rtscalable.h" MyCurve::MyCurve () : pipetteR(-1.f), diff --git a/rtgui/mycurve.h b/rtgui/mycurve.h index 82dd4a1a4..6bdfe4b66 100644 --- a/rtgui/mycurve.h +++ b/rtgui/mycurve.h @@ -14,20 +14,21 @@ * GNU General Public License for more details. * * 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_ +#pragma once + +#include #include -#include -#include "curvelistener.h" -#include "cursormanager.h" + #include "coloredbar.h" #include "coordinateadjuster.h" +#include "cursormanager.h" +#include "curvelistener.h" + #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) */ @@ -54,8 +55,9 @@ enum SnapToType { class MyCurveIdleHelper; class CurveEditor; +class EditDataProvider; -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; @@ -151,5 +153,3 @@ public: myCurve->setDirty(true); } }; - -#endif diff --git a/rtgui/mydiagonalcurve.cc b/rtgui/mydiagonalcurve.cc index a3e7b9375..abd339ce0 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 @@ -23,6 +23,7 @@ #include "mydiagonalcurve.h" #include "editcallbacks.h" +#include "rtscalable.h" #include "../rtengine/curves.h" @@ -591,7 +592,6 @@ bool MyDiagonalCurve::handleEvents (GdkEvent* event) curve.x.insert (itx, 0); curve.y.insert (ity, 0); - num++; // the graph is refreshed only if a new point is created curve.x.at(closest_point) = clampedX; @@ -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; } @@ -1512,7 +1503,7 @@ void MyDiagonalCurve::setActiveParam (int ac) queue_draw (); } -void MyDiagonalCurve::updateBackgroundHistogram (LUTu & hist) +void MyDiagonalCurve::updateBackgroundHistogram (const LUTu & hist) { if (hist) { //memcpy (bghist, hist, 256*sizeof(unsigned int)); diff --git a/rtgui/mydiagonalcurve.h b/rtgui/mydiagonalcurve.h index 5b0f6f01e..b2b83c02e 100644 --- a/rtgui/mydiagonalcurve.h +++ b/rtgui/mydiagonalcurve.h @@ -14,30 +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 _MYDIAGONALCURVE_ -#define _MYDIAGONALCURVE_ +#pragma once + +#include #include -#include -#include "curvelistener.h" + #include "cursormanager.h" +#include "curvelistener.h" #include "mycurve.h" -#include "../rtengine/LUT.h" +#include "../rtengine/diagonalcurvetypes.h" -// For compatibility and simplicity reason, order shouldn't change, and must be identical to the order specified in the curveType widget -enum DiagonalCurveType { - DCT_Empty = -1, // Also used for identity curves - DCT_Linear, // 0 - DCT_Spline, // 1 - DCT_Parametric, // 2 - DCT_NURBS, // 3 - DCT_CatumullRom, // 4 - // Insert new curve type above this line - DCT_Unchanged // Must remain the last of the enum -}; +template +class LUT; + +using LUTf = LUT; class DiagonalCurveDescr { @@ -47,7 +41,7 @@ public: std::vector x, y; // in case of parametric curves the curve parameters are stored in vector x. In other cases these vectors store the coordinates of the bullets. }; -class MyDiagonalCurve : public MyCurve +class MyDiagonalCurve final : public MyCurve { private: IdleRegister idle_register; @@ -91,7 +85,7 @@ public: bool handleEvents (GdkEvent* event) override; void setActiveParam (int ac); void reset (const std::vector &resetCurve, double identityValue = 0.5) override; - void updateBackgroundHistogram (LUTu & hist); + void updateBackgroundHistogram (const LUTu & hist); void pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey) override; bool pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) override; @@ -101,5 +95,3 @@ public: void setPos(double pos, int chanIdx) override; void stopNumericalAdjustment() override; }; - -#endif diff --git a/rtgui/myflatcurve.cc b/rtgui/myflatcurve.cc index 1a8a43b62..904b379c2 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 @@ -23,6 +23,7 @@ #include "myflatcurve.h" #include "editcallbacks.h" +#include "rtscalable.h" #include "../rtengine/curves.h" @@ -571,7 +572,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); @@ -667,7 +668,6 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) curve.y.insert (ity, 0); curve.leftTangent.insert (itlt, 0); curve.rightTangent.insert (itrt, 0); - num++; if (mod_type & GDK_CONTROL_MASK) { clampedY = point.getVal01(clampedX); @@ -760,7 +760,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 b24126068..f51586567 100644 --- a/rtgui/myflatcurve.h +++ b/rtgui/myflatcurve.h @@ -14,26 +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 _MYFLATCURVE_ -#define _MYFLATCURVE_ +#pragma once + +#include #include -#include -#include "curvelistener.h" -#include "cursormanager.h" -#include "mycurve.h" -// For compatibility and simplicity reason, order shouldn't change, and must be identical to the order specified in the curveType widget -enum FlatCurveType { - FCT_Empty = -1, // Also used for identity curves - FCT_Linear, // 0 - FCT_MinMaxCPoints, // 1 - //FCT_Parametric, // 2 - // Insert new curve type above this line - FCT_Unchanged // Must remain the last of the enum -}; +#include "cursormanager.h" +#include "curvelistener.h" +#include "mycurve.h" +#include "../rtengine/flatcurvetypes.h" enum MouseOverAreas { FCT_Area_None = 1 << 0, // over a zone that don't have any @@ -74,7 +66,7 @@ public: double centerY; }; -class MyFlatCurve : public MyCurve +class MyFlatCurve final : public MyCurve { private: IdleRegister idle_register; @@ -143,5 +135,3 @@ public: void updateLocallabBackground(double ref); }; - -#endif diff --git a/rtgui/navigator.cc b/rtgui/navigator.cc index 732b9f323..619ea0cfd 100644 --- a/rtgui/navigator.cc +++ b/rtgui/navigator.cc @@ -14,20 +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 "navigator.h" +#include "previewwindow.h" #include "toolpanel.h" -#include "../rtengine/iccmatrices.h" -#include "../rtengine/iccstore.h" -#include "../rtengine/curves.h" #include "../rtengine/color.h" #include "../rtengine/rt_math.h" #include "options.h" -extern Options options; - using namespace rtengine; Navigator::Navigator () : currentRGBUnit(options.navRGBUnit), currentHSVUnit(options.navHSVUnit) diff --git a/rtgui/navigator.h b/rtgui/navigator.h index 1b898f895..e9d40e309 100644 --- a/rtgui/navigator.h +++ b/rtgui/navigator.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 _NAVIGATOR_ -#define _NAVIGATOR_ +#pragma once #include -#include "previewwindow.h" -#include "pointermotionlistener.h" -#include "options.h" -#include "../rtengine/iccstore.h" -class Navigator : public Gtk::Frame, public PointerMotionListener +#include "options.h" +#include "pointermotionlistener.h" + +class PreviewWindow; + +class Navigator final : + public Gtk::Frame, + public PointerMotionListener { typedef const double (*TMatrix)[3]; @@ -63,5 +65,3 @@ public: void getLABText (float l, float a, float b, Glib::ustring &sL, Glib::ustring &sA, Glib::ustring &sB) override; }; - -#endif diff --git a/rtgui/options.cc b/rtgui/options.cc index c2ab3dd1f..5798b809b 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -14,18 +14,23 @@ * GNU General Public License for more details. * * 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 #include +#include +#include #include #include "multilangmgr.h" #include "addsetids.h" #include "guiutils.h" +#include "pathutils.h" #include "version.h" #include "../rtengine/procparams.h" +#include "../rtengine/rtengine.h" +#include "../rtengine/utils.h" #ifdef _OPENMP #include @@ -224,7 +229,7 @@ Glib::ustring Options::getPreferredProfilePath() * *@param profName path + filename of the procparam to look for. A filename without path can be provided for backward compatibility. * In this case, this parameter will be updated with the new format. - *@return Send back the absolute path of the given filename or "Neutral" if "Neutral" has been set to profName. Implementor will have + *@return Send back the absolute path of the given filename or "Neutral" if "Neutral" has been set to profName. Implementer will have * to test for this particular value. If the absolute path is invalid (e.g. the file doesn't exist), it will return an empty string. */ Glib::ustring Options::findProfilePath(Glib::ustring &profName) @@ -446,6 +451,7 @@ void Options::setDefaults() histogramHeight = 200; histogramDrawMode = 0; curvebboxpos = 1; + complexity = 2; prevdemo = PD_Sidecar; rgbDenoiseThreadLimit = 0; @@ -1295,7 +1301,7 @@ void Options::readFromFile(Glib::ustring fname) } if (keyFile.has_key("GUI", "PseudoHiDPISupport")) { - pseudoHiDPISupport = keyFile.get_boolean("GUI", "PseudoHiDPISupport"); + pseudoHiDPISupport = keyFile.get_boolean("GUI", "PseudoHiDPISupport"); } if (keyFile.has_key("GUI", "LastPreviewScale")) { @@ -1419,6 +1425,7 @@ void Options::readFromFile(Glib::ustring fname) navHSVUnit = (NavigatorUnit)keyFile.get_integer("GUI", "NavigatorHSVUnit"); } + if (keyFile.has_key("GUI", "ShowFilmStripToolBar")) { showFilmStripToolBar = keyFile.get_boolean("GUI", "ShowFilmStripToolBar"); } @@ -1442,6 +1449,11 @@ void Options::readFromFile(Glib::ustring fname) if (keyFile.has_key("GUI", "CurveBBoxPosition")) { curvebboxpos = keyFile.get_integer("GUI", "CurveBBoxPosition"); } + + if (keyFile.has_key("GUI", "Complexity")) { + complexity = keyFile.get_integer("GUI", "Complexity"); + } + } if (keyFile.has_group("Crop Settings")) { @@ -1639,6 +1651,7 @@ void Options::readFromFile(Glib::ustring fname) rtSettings.previewselection = keyFile.get_integer("Color Management", "Previewselection"); } + if (keyFile.has_key("Color Management", "Cbdlsensi")) {//sensibility to crash for cbdl rtSettings.cbdlsensi = keyFile.get_double("Color Management", "Cbdlsensi"); } @@ -2183,6 +2196,7 @@ void Options::saveToFile(Glib::ustring fname) keyFile.set_boolean("GUI", "HistogramWorking", rtSettings.HistogramWorking); keyFile.set_integer("GUI", "CurveBBoxPosition", curvebboxpos); keyFile.set_boolean("GUI", "Showtooltip", showtooltip); + keyFile.set_integer("GUI", "Complexity", complexity); //Glib::ArrayHandle crvopen = crvOpen; //keyFile.set_integer_list ("GUI", "CurvePanelsExpanded", crvopen); @@ -2552,6 +2566,18 @@ bool Options::has_retained_extention(const Glib::ustring& fname) return parsedExtensionsSet.find(getExtension(fname).lowercase()) != parsedExtensionsSet.end(); } +// 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; + + for (const auto& v : vs) { + vMajor.emplace_back(v, 0, v.find_first_not_of("0123456789.")); + } + + return vMajor.size() == 2 && vMajor[0] != vMajor[1]; +} + /* * return true if ext is an enabled extension */ diff --git a/rtgui/options.h b/rtgui/options.h index 3fd6b253c..b8858f9bd 100644 --- a/rtgui/options.h +++ b/rtgui/options.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 . */ -#ifndef _OPTIONS_ -#define _OPTIONS_ +#pragma once #include -#include -#include "../rtengine/rtengine.h" +#include +#include +#include "../rtengine/settings.h" #include #define STARTUPDIR_CURRENT 0 @@ -103,6 +103,13 @@ enum PPLoadLocation {PLL_Cache = 0, PLL_Input = 1}; enum CPBKeyType {CPBKT_TID = 0, CPBKT_NAME = 1, CPBKT_TID_NAME = 2}; enum prevdemo_t {PD_Sidecar = 1, PD_Fast = 0}; +namespace Glib +{ + +class KeyFile; + +} + class Options { public: @@ -273,6 +280,7 @@ public: bool renameUseTemplates; bool internalThumbIfUntouched; bool overwriteOutputFile; + int complexity; std::vector thumbnailZoomRatios; bool overlayedFileNames; @@ -427,6 +435,7 @@ public: Glib::ustring findProfilePath (Glib::ustring &profName); bool is_parse_extention (Glib::ustring fname); 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(); @@ -447,5 +456,3 @@ extern bool gimpPlugin; extern bool remote; extern Glib::ustring versionString; extern Glib::ustring paramFileExtension; - -#endif diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 6d1ea4571..134383cba 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.deconvradius = v; + pdsharpening.deconvradiusOffset = v; + pdsharpening.deconviter = v; + pdsharpening.deconvitercheck = v; prsharpening.enabled = v; prsharpening.contrast = v; prsharpening.radius = v; @@ -312,6 +321,7 @@ void ParamsEdited::set(bool v) coarse.rotate = v; coarse.hflip = v; coarse.vflip = v; + commonTrans.method = v; commonTrans.autofill = v; rotate.degree = v; distortion.amount = v; @@ -587,6 +597,7 @@ 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; @@ -744,6 +755,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; @@ -756,6 +768,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.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; + pdsharpening.deconvitercheck = pdsharpening.deconvitercheck && p.pdsharpening.deconvitercheck == other.pdsharpening.deconvitercheck; 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; @@ -900,6 +920,7 @@ void ParamsEdited::initFrom(const std::vector& coarse.rotate = coarse.rotate && p.coarse.rotate == other.coarse.rotate; coarse.hflip = coarse.hflip && p.coarse.hflip == other.coarse.hflip; coarse.vflip = coarse.vflip && p.coarse.vflip == other.coarse.vflip; + commonTrans.method = commonTrans.method && p.commonTrans.method == other.commonTrans.method; commonTrans.autofill = commonTrans.autofill && p.commonTrans.autofill == other.commonTrans.autofill; rotate.degree = rotate.degree && p.rotate.degree == other.rotate.degree; distortion.amount = distortion.amount && p.distortion.amount == other.distortion.amount; @@ -935,6 +956,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).isvisible = locallab.spots.at(j).isvisible && pSpot.isvisible == otherSpot.isvisible; locallab.spots.at(j).shape = locallab.spots.at(j).shape && pSpot.shape == otherSpot.shape; locallab.spots.at(j).spotMethod = locallab.spots.at(j).spotMethod && pSpot.spotMethod == otherSpot.spotMethod; + locallab.spots.at(j).wavMethod = locallab.spots.at(j).wavMethod && pSpot.wavMethod == otherSpot.wavMethod; locallab.spots.at(j).sensiexclu = locallab.spots.at(j).sensiexclu && pSpot.sensiexclu == otherSpot.sensiexclu; locallab.spots.at(j).structexclu = locallab.spots.at(j).structexclu && pSpot.structexclu == otherSpot.structexclu; locallab.spots.at(j).struc = locallab.spots.at(j).struc && pSpot.struc == otherSpot.struc; @@ -947,13 +969,24 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).centerY = locallab.spots.at(j).centerY && pSpot.centerY == otherSpot.centerY; locallab.spots.at(j).circrad = locallab.spots.at(j).circrad && pSpot.circrad == otherSpot.circrad; locallab.spots.at(j).qualityMethod = locallab.spots.at(j).qualityMethod && pSpot.qualityMethod == otherSpot.qualityMethod; + locallab.spots.at(j).complexMethod = locallab.spots.at(j).complexMethod && pSpot.complexMethod == otherSpot.complexMethod; locallab.spots.at(j).transit = locallab.spots.at(j).transit && pSpot.transit == otherSpot.transit; + locallab.spots.at(j).feather = locallab.spots.at(j).feather && pSpot.feather == otherSpot.feather; locallab.spots.at(j).thresh = locallab.spots.at(j).thresh && pSpot.thresh == otherSpot.thresh; locallab.spots.at(j).iter = locallab.spots.at(j).iter && pSpot.iter == otherSpot.iter; locallab.spots.at(j).balan = locallab.spots.at(j).balan && pSpot.balan == otherSpot.balan; + locallab.spots.at(j).balanh = locallab.spots.at(j).balanh && pSpot.balanh == otherSpot.balanh; + locallab.spots.at(j).colorde = locallab.spots.at(j).colorde && pSpot.colorde == otherSpot.colorde; locallab.spots.at(j).transitweak = locallab.spots.at(j).transitweak && pSpot.transitweak == otherSpot.transitweak; locallab.spots.at(j).transitgrad = locallab.spots.at(j).transitgrad && pSpot.transitgrad == otherSpot.transitgrad; locallab.spots.at(j).avoid = locallab.spots.at(j).avoid && pSpot.avoid == otherSpot.avoid; + locallab.spots.at(j).recurs = locallab.spots.at(j).recurs && pSpot.recurs == otherSpot.recurs; + locallab.spots.at(j).laplac = locallab.spots.at(j).laplac && pSpot.laplac == otherSpot.laplac; + locallab.spots.at(j).deltae = locallab.spots.at(j).deltae && pSpot.deltae == otherSpot.deltae; + locallab.spots.at(j).shortc = locallab.spots.at(j).shortc && pSpot.shortc == otherSpot.shortc; + locallab.spots.at(j).savrest = locallab.spots.at(j).savrest && pSpot.savrest == otherSpot.savrest; + locallab.spots.at(j).scopemask = locallab.spots.at(j).scopemask && pSpot.scopemask == otherSpot.scopemask; + locallab.spots.at(j).lumask = locallab.spots.at(j).lumask && pSpot.lumask == otherSpot.lumask; // Color & Light locallab.spots.at(j).visicolor = locallab.spots.at(j).visicolor && pSpot.visicolor == otherSpot.visicolor; locallab.spots.at(j).expcolor = locallab.spots.at(j).expcolor && pSpot.expcolor == otherSpot.expcolor; @@ -965,27 +998,57 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).labgridBLow = locallab.spots.at(j).labgridBLow && pSpot.labgridBLow == otherSpot.labgridBLow; locallab.spots.at(j).labgridAHigh = locallab.spots.at(j).labgridAHigh && pSpot.labgridAHigh == otherSpot.labgridAHigh; locallab.spots.at(j).labgridBHigh = locallab.spots.at(j).labgridBHigh && pSpot.labgridBHigh == otherSpot.labgridBHigh; + locallab.spots.at(j).labgridALowmerg = locallab.spots.at(j).labgridALowmerg && pSpot.labgridALowmerg == otherSpot.labgridALowmerg; + locallab.spots.at(j).labgridBLowmerg = locallab.spots.at(j).labgridBLowmerg && pSpot.labgridBLowmerg == otherSpot.labgridBLowmerg; + locallab.spots.at(j).labgridAHighmerg = locallab.spots.at(j).labgridAHighmerg && pSpot.labgridAHighmerg == otherSpot.labgridAHighmerg; + locallab.spots.at(j).labgridBHighmerg = locallab.spots.at(j).labgridBHighmerg && pSpot.labgridBHighmerg == otherSpot.labgridBHighmerg; locallab.spots.at(j).strengthgrid = locallab.spots.at(j).strengthgrid && pSpot.strengthgrid == otherSpot.strengthgrid; locallab.spots.at(j).sensi = locallab.spots.at(j).sensi && pSpot.sensi == otherSpot.sensi; locallab.spots.at(j).structcol = locallab.spots.at(j).structcol && pSpot.structcol == otherSpot.structcol; + locallab.spots.at(j).strcol = locallab.spots.at(j).strcol && pSpot.strcol == otherSpot.strcol; + locallab.spots.at(j).strcolab = locallab.spots.at(j).strcolab && pSpot.strcolab == otherSpot.strcolab; + locallab.spots.at(j).strcolh = locallab.spots.at(j).strcolh && pSpot.strcolh == otherSpot.strcolh; + locallab.spots.at(j).angcol = locallab.spots.at(j).angcol && pSpot.angcol == otherSpot.angcol; locallab.spots.at(j).blurcolde = locallab.spots.at(j).blurcolde && pSpot.blurcolde == otherSpot.blurcolde; + locallab.spots.at(j).blurcol = locallab.spots.at(j).blurcol && pSpot.blurcol == otherSpot.blurcol; + locallab.spots.at(j).contcol = locallab.spots.at(j).contcol && pSpot.contcol == otherSpot.contcol; locallab.spots.at(j).blendmaskcol = locallab.spots.at(j).blendmaskcol && pSpot.blendmaskcol == otherSpot.blendmaskcol; locallab.spots.at(j).radmaskcol = locallab.spots.at(j).radmaskcol && pSpot.radmaskcol == otherSpot.radmaskcol; locallab.spots.at(j).chromaskcol = locallab.spots.at(j).chromaskcol && pSpot.chromaskcol == otherSpot.chromaskcol; locallab.spots.at(j).gammaskcol = locallab.spots.at(j).gammaskcol && pSpot.gammaskcol == otherSpot.gammaskcol; locallab.spots.at(j).slomaskcol = locallab.spots.at(j).slomaskcol && pSpot.slomaskcol == otherSpot.slomaskcol; + locallab.spots.at(j).shadmaskcol = locallab.spots.at(j).shadmaskcol && pSpot.shadmaskcol == otherSpot.shadmaskcol; + locallab.spots.at(j).strumaskcol = locallab.spots.at(j).strumaskcol && pSpot.strumaskcol == otherSpot.strumaskcol; + locallab.spots.at(j).lapmaskcol = locallab.spots.at(j).lapmaskcol && pSpot.lapmaskcol == otherSpot.lapmaskcol; locallab.spots.at(j).qualitycurveMethod = locallab.spots.at(j).qualitycurveMethod && pSpot.qualitycurveMethod == otherSpot.qualitycurveMethod; locallab.spots.at(j).gridMethod = locallab.spots.at(j).gridMethod && pSpot.gridMethod == otherSpot.gridMethod; + locallab.spots.at(j).merMethod = locallab.spots.at(j).merMethod && pSpot.merMethod == otherSpot.merMethod; + locallab.spots.at(j).toneMethod = locallab.spots.at(j).toneMethod && pSpot.toneMethod == otherSpot.toneMethod; + locallab.spots.at(j).mergecolMethod = locallab.spots.at(j).mergecolMethod && pSpot.mergecolMethod == otherSpot.mergecolMethod; locallab.spots.at(j).llcurve = locallab.spots.at(j).llcurve && pSpot.llcurve == otherSpot.llcurve; + locallab.spots.at(j).lccurve = locallab.spots.at(j).lccurve && pSpot.lccurve == otherSpot.lccurve; locallab.spots.at(j).cccurve = locallab.spots.at(j).cccurve && pSpot.cccurve == otherSpot.cccurve; + locallab.spots.at(j).clcurve = locallab.spots.at(j).clcurve && pSpot.cccurve == otherSpot.clcurve; + locallab.spots.at(j).rgbcurve = locallab.spots.at(j).rgbcurve && pSpot.rgbcurve == otherSpot.rgbcurve; locallab.spots.at(j).LHcurve = locallab.spots.at(j).LHcurve && pSpot.LHcurve == otherSpot.LHcurve; locallab.spots.at(j).HHcurve = locallab.spots.at(j).HHcurve && pSpot.HHcurve == otherSpot.HHcurve; locallab.spots.at(j).invers = locallab.spots.at(j).invers && pSpot.invers == otherSpot.invers; + locallab.spots.at(j).special = locallab.spots.at(j).special && pSpot.special == otherSpot.special; + locallab.spots.at(j).toolcol = locallab.spots.at(j).toolcol && pSpot.toolcol == otherSpot.toolcol; locallab.spots.at(j).enaColorMask = locallab.spots.at(j).enaColorMask && pSpot.enaColorMask == otherSpot.enaColorMask; + locallab.spots.at(j).fftColorMask = locallab.spots.at(j).fftColorMask && pSpot.fftColorMask == otherSpot.fftColorMask; locallab.spots.at(j).CCmaskcurve = locallab.spots.at(j).CCmaskcurve && pSpot.CCmaskcurve == otherSpot.CCmaskcurve; locallab.spots.at(j).LLmaskcurve = locallab.spots.at(j).LLmaskcurve && pSpot.LLmaskcurve == otherSpot.LLmaskcurve; locallab.spots.at(j).HHmaskcurve = locallab.spots.at(j).HHmaskcurve && pSpot.HHmaskcurve == otherSpot.HHmaskcurve; + locallab.spots.at(j).HHhmaskcurve = locallab.spots.at(j).HHhmaskcurve && pSpot.HHhmaskcurve == otherSpot.HHhmaskcurve; locallab.spots.at(j).softradiuscol = locallab.spots.at(j).softradiuscol && pSpot.softradiuscol == otherSpot.softradiuscol; + locallab.spots.at(j).opacol = locallab.spots.at(j).opacol && pSpot.opacol == otherSpot.opacol; + locallab.spots.at(j).mercol = locallab.spots.at(j).mercol && pSpot.mercol == otherSpot.mercol; + locallab.spots.at(j).merlucol = locallab.spots.at(j).merlucol && pSpot.merlucol == otherSpot.merlucol; + locallab.spots.at(j).conthrcol = locallab.spots.at(j).conthrcol && pSpot.conthrcol == otherSpot.conthrcol; + locallab.spots.at(j).Lmaskcurve = locallab.spots.at(j).Lmaskcurve && pSpot.Lmaskcurve == otherSpot.Lmaskcurve; + locallab.spots.at(j).LLmaskcolcurvewav = locallab.spots.at(j).LLmaskcolcurvewav && pSpot.LLmaskcolcurvewav == otherSpot.LLmaskcolcurvewav; + locallab.spots.at(j).csthresholdcol = locallab.spots.at(j).csthresholdcol && pSpot.csthresholdcol == otherSpot.csthresholdcol; // Exposure locallab.spots.at(j).visiexpose = locallab.spots.at(j).visiexpose && pSpot.visiexpose == otherSpot.visiexpose; locallab.spots.at(j).expexpose = locallab.spots.at(j).expexpose && pSpot.expexpose == otherSpot.expexpose; @@ -996,13 +1059,15 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).shadex = locallab.spots.at(j).shadex && pSpot.shadex == otherSpot.shadex; locallab.spots.at(j).shcompr = locallab.spots.at(j).shcompr && pSpot.shcompr == otherSpot.shcompr; locallab.spots.at(j).expchroma = locallab.spots.at(j).expchroma && pSpot.expchroma == otherSpot.expchroma; - locallab.spots.at(j).warm = locallab.spots.at(j).warm && pSpot.warm == otherSpot.warm; locallab.spots.at(j).sensiex = locallab.spots.at(j).sensiex && pSpot.sensiex == otherSpot.sensiex; locallab.spots.at(j).structexp = locallab.spots.at(j).structexp && pSpot.structexp == otherSpot.structexp; locallab.spots.at(j).blurexpde = locallab.spots.at(j).blurexpde && pSpot.blurexpde == otherSpot.blurexpde; + locallab.spots.at(j).strexp = locallab.spots.at(j).strexp && pSpot.strexp == otherSpot.strexp; + locallab.spots.at(j).angexp = locallab.spots.at(j).angexp && pSpot.angexp == otherSpot.angexp; locallab.spots.at(j).excurve = locallab.spots.at(j).excurve && pSpot.excurve == otherSpot.excurve; locallab.spots.at(j).inversex = locallab.spots.at(j).inversex && pSpot.inversex == otherSpot.inversex; locallab.spots.at(j).enaExpMask = locallab.spots.at(j).enaExpMask && pSpot.enaExpMask == otherSpot.enaExpMask; + locallab.spots.at(j).enaExpMaskaft = locallab.spots.at(j).enaExpMaskaft && pSpot.enaExpMaskaft == otherSpot.enaExpMaskaft; locallab.spots.at(j).CCmaskexpcurve = locallab.spots.at(j).CCmaskexpcurve && pSpot.CCmaskexpcurve == otherSpot.CCmaskexpcurve; locallab.spots.at(j).LLmaskexpcurve = locallab.spots.at(j).LLmaskexpcurve && pSpot.LLmaskexpcurve == otherSpot.LLmaskexpcurve; locallab.spots.at(j).HHmaskexpcurve = locallab.spots.at(j).HHmaskexpcurve && pSpot.HHmaskexpcurve == otherSpot.HHmaskexpcurve; @@ -1011,14 +1076,30 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).chromaskexp = locallab.spots.at(j).chromaskexp && pSpot.chromaskexp == otherSpot.chromaskexp; locallab.spots.at(j).gammaskexp = locallab.spots.at(j).gammaskexp && pSpot.gammaskexp == otherSpot.gammaskexp; locallab.spots.at(j).slomaskexp = locallab.spots.at(j).slomaskexp && pSpot.slomaskexp == otherSpot.slomaskexp; + locallab.spots.at(j).lapmaskexp = locallab.spots.at(j).lapmaskexp && pSpot.lapmaskexp == otherSpot.lapmaskexp; + locallab.spots.at(j).strmaskexp = locallab.spots.at(j).strmaskexp && pSpot.strmaskexp == otherSpot.strmaskexp; + locallab.spots.at(j).angmaskexp = locallab.spots.at(j).angmaskexp && pSpot.angmaskexp == otherSpot.angmaskexp; locallab.spots.at(j).softradiusexp = locallab.spots.at(j).softradiusexp && pSpot.softradiusexp == otherSpot.softradiusexp; + locallab.spots.at(j).Lmaskexpcurve = locallab.spots.at(j).Lmaskexpcurve && pSpot.Lmaskexpcurve == otherSpot.Lmaskexpcurve; locallab.spots.at(j).expMethod = locallab.spots.at(j).expMethod && pSpot.expMethod == otherSpot.expMethod; + locallab.spots.at(j).exnoiseMethod = locallab.spots.at(j).exnoiseMethod && pSpot.exnoiseMethod == otherSpot.exnoiseMethod; locallab.spots.at(j).laplacexp = locallab.spots.at(j).laplacexp && pSpot.laplacexp == otherSpot.laplacexp; locallab.spots.at(j).balanexp = locallab.spots.at(j).balanexp && pSpot.balanexp == otherSpot.balanexp; locallab.spots.at(j).linear = locallab.spots.at(j).linear && pSpot.linear == otherSpot.linear; + locallab.spots.at(j).gamm = locallab.spots.at(j).gamm && pSpot.gamm == otherSpot.gamm; + locallab.spots.at(j).fatamount = locallab.spots.at(j).fatamount && pSpot.fatamount == otherSpot.fatamount; + locallab.spots.at(j).fatdetail = locallab.spots.at(j).fatdetail && pSpot.fatdetail == otherSpot.fatdetail; + locallab.spots.at(j).fatanchor = locallab.spots.at(j).fatanchor && pSpot.fatanchor == otherSpot.fatanchor; + locallab.spots.at(j).fatlevel = locallab.spots.at(j).fatlevel && pSpot.fatlevel == otherSpot.fatlevel; // Shadow highlight locallab.spots.at(j).visishadhigh = locallab.spots.at(j).visishadhigh && pSpot.visishadhigh == otherSpot.visishadhigh; locallab.spots.at(j).expshadhigh = locallab.spots.at(j).expshadhigh && pSpot.expshadhigh == otherSpot.expshadhigh; + locallab.spots.at(j).shMethod = locallab.spots.at(j).shMethod && pSpot.shMethod == otherSpot.shMethod; + + for (int k = 0; k < 5; k++) { + locallab.spots.at(j).multsh[k] = locallab.spots.at(j).multsh[k] && pSpot.multsh[k] == otherSpot.multsh[k]; + } + locallab.spots.at(j).highlights = locallab.spots.at(j).highlights && pSpot.highlights == otherSpot.highlights; locallab.spots.at(j).h_tonalwidth = locallab.spots.at(j).h_tonalwidth && pSpot.h_tonalwidth == otherSpot.h_tonalwidth; locallab.spots.at(j).shadows = locallab.spots.at(j).shadows && pSpot.shadows == otherSpot.shadows; @@ -1032,21 +1113,46 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).blendmaskSH = locallab.spots.at(j).blendmaskSH && pSpot.blendmaskSH == otherSpot.blendmaskSH; locallab.spots.at(j).radmaskSH = locallab.spots.at(j).radmaskSH && pSpot.radmaskSH == otherSpot.radmaskSH; locallab.spots.at(j).blurSHde = locallab.spots.at(j).blurSHde && pSpot.blurSHde == otherSpot.blurSHde; + locallab.spots.at(j).strSH = locallab.spots.at(j).strSH && pSpot.strSH == otherSpot.strSH; + locallab.spots.at(j).angSH = locallab.spots.at(j).angSH && pSpot.angSH == otherSpot.angSH; locallab.spots.at(j).inverssh = locallab.spots.at(j).inverssh && pSpot.inverssh == otherSpot.inverssh; locallab.spots.at(j).chromaskSH = locallab.spots.at(j).chromaskSH && pSpot.chromaskSH == otherSpot.chromaskSH; locallab.spots.at(j).gammaskSH = locallab.spots.at(j).gammaskSH && pSpot.gammaskSH == otherSpot.gammaskSH; locallab.spots.at(j).slomaskSH = locallab.spots.at(j).slomaskSH && pSpot.slomaskSH == otherSpot.slomaskSH; + locallab.spots.at(j).lapmaskSH = locallab.spots.at(j).lapmaskSH && pSpot.lapmaskSH == otherSpot.lapmaskSH; + locallab.spots.at(j).detailSH = locallab.spots.at(j).detailSH && pSpot.detailSH == otherSpot.detailSH; + locallab.spots.at(j).LmaskSHcurve = locallab.spots.at(j).LmaskSHcurve && pSpot.LmaskSHcurve == otherSpot.LmaskSHcurve; + locallab.spots.at(j).fatamountSH = locallab.spots.at(j).fatamountSH && pSpot.fatamountSH == otherSpot.fatamountSH; + locallab.spots.at(j).fatanchorSH = locallab.spots.at(j).fatanchorSH && pSpot.fatanchorSH == otherSpot.fatanchorSH; + locallab.spots.at(j).gamSH = locallab.spots.at(j).gamSH && pSpot.gamSH == otherSpot.gamSH; + locallab.spots.at(j).sloSH = locallab.spots.at(j).sloSH && pSpot.sloSH == otherSpot.sloSH; // Vibrance locallab.spots.at(j).visivibrance = locallab.spots.at(j).visivibrance && pSpot.visivibrance == otherSpot.visivibrance; locallab.spots.at(j).expvibrance = locallab.spots.at(j).expvibrance && pSpot.expvibrance == otherSpot.expvibrance; locallab.spots.at(j).saturated = locallab.spots.at(j).saturated && pSpot.saturated == otherSpot.saturated; locallab.spots.at(j).pastels = locallab.spots.at(j).pastels && pSpot.pastels == otherSpot.pastels; + locallab.spots.at(j).warm = locallab.spots.at(j).warm && pSpot.warm == otherSpot.warm; locallab.spots.at(j).psthreshold = locallab.spots.at(j).psthreshold && pSpot.psthreshold == otherSpot.psthreshold; locallab.spots.at(j).protectskins = locallab.spots.at(j).protectskins && pSpot.protectskins == otherSpot.protectskins; locallab.spots.at(j).avoidcolorshift = locallab.spots.at(j).avoidcolorshift && pSpot.avoidcolorshift == otherSpot.avoidcolorshift; locallab.spots.at(j).pastsattog = locallab.spots.at(j).pastsattog && pSpot.pastsattog == otherSpot.pastsattog; locallab.spots.at(j).sensiv = locallab.spots.at(j).sensiv && pSpot.sensiv == otherSpot.sensiv; locallab.spots.at(j).skintonescurve = locallab.spots.at(j).skintonescurve && pSpot.skintonescurve == otherSpot.skintonescurve; + locallab.spots.at(j).CCmaskvibcurve = locallab.spots.at(j).CCmaskvibcurve && pSpot.CCmaskvibcurve == otherSpot.CCmaskvibcurve; + locallab.spots.at(j).LLmaskvibcurve = locallab.spots.at(j).LLmaskvibcurve && pSpot.LLmaskvibcurve == otherSpot.LLmaskvibcurve; + locallab.spots.at(j).HHmaskvibcurve = locallab.spots.at(j).HHmaskvibcurve && pSpot.HHmaskvibcurve == otherSpot.HHmaskvibcurve; + locallab.spots.at(j).enavibMask = locallab.spots.at(j).enavibMask && pSpot.enavibMask == otherSpot.enavibMask; + locallab.spots.at(j).blendmaskvib = locallab.spots.at(j).blendmaskvib && pSpot.blendmaskvib == otherSpot.blendmaskvib; + locallab.spots.at(j).radmaskvib = locallab.spots.at(j).radmaskvib && pSpot.radmaskvib == otherSpot.radmaskvib; + locallab.spots.at(j).chromaskvib = locallab.spots.at(j).chromaskvib && pSpot.chromaskvib == otherSpot.chromaskvib; + locallab.spots.at(j).gammaskvib = locallab.spots.at(j).gammaskvib && pSpot.gammaskvib == otherSpot.gammaskvib; + locallab.spots.at(j).slomaskvib = locallab.spots.at(j).slomaskvib && pSpot.slomaskvib == otherSpot.slomaskvib; + locallab.spots.at(j).lapmaskvib = locallab.spots.at(j).lapmaskvib && pSpot.lapmaskvib == otherSpot.lapmaskvib; + locallab.spots.at(j).strvib = locallab.spots.at(j).strvib && pSpot.strvib == otherSpot.strvib; + locallab.spots.at(j).strvibab = locallab.spots.at(j).strvibab && pSpot.strvibab == otherSpot.strvibab; + locallab.spots.at(j).strvibh = locallab.spots.at(j).strvibh && pSpot.strvibh == otherSpot.strvibh; + locallab.spots.at(j).angvib = locallab.spots.at(j).angvib && pSpot.angvib == otherSpot.angvib; + locallab.spots.at(j).Lmaskvibcurve = locallab.spots.at(j).Lmaskvibcurve && pSpot.Lmaskvibcurve == otherSpot.Lmaskvibcurve; // Soft Light locallab.spots.at(j).visisoft = locallab.spots.at(j).visisoft && pSpot.visisoft == otherSpot.visisoft; locallab.spots.at(j).expsoft = locallab.spots.at(j).expsoft && pSpot.expsoft == otherSpot.expsoft; @@ -1060,8 +1166,35 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).radius = locallab.spots.at(j).radius && pSpot.radius == otherSpot.radius; locallab.spots.at(j).strength = locallab.spots.at(j).strength && pSpot.strength == otherSpot.strength; locallab.spots.at(j).sensibn = locallab.spots.at(j).sensibn && pSpot.sensibn == otherSpot.sensibn; + locallab.spots.at(j).itera = locallab.spots.at(j).itera && pSpot.itera == otherSpot.itera; + locallab.spots.at(j).guidbl = locallab.spots.at(j).guidbl && pSpot.guidbl == otherSpot.guidbl; + locallab.spots.at(j).strbl = locallab.spots.at(j).strbl && pSpot.strbl == otherSpot.strbl; + locallab.spots.at(j).isogr = locallab.spots.at(j).isogr && pSpot.isogr == otherSpot.isogr; + locallab.spots.at(j).strengr = locallab.spots.at(j).strengr && pSpot.strengr == otherSpot.strengr; + locallab.spots.at(j).scalegr = locallab.spots.at(j).scalegr && pSpot.scalegr == otherSpot.scalegr; + locallab.spots.at(j).epsbl = locallab.spots.at(j).epsbl && pSpot.epsbl == otherSpot.epsbl; + locallab.spots.at(j).blMethod = locallab.spots.at(j).blMethod && pSpot.blMethod == otherSpot.blMethod; + locallab.spots.at(j).chroMethod = locallab.spots.at(j).chroMethod && pSpot.chroMethod == otherSpot.chroMethod; locallab.spots.at(j).blurMethod = locallab.spots.at(j).blurMethod && pSpot.blurMethod == otherSpot.blurMethod; + locallab.spots.at(j).medMethod = locallab.spots.at(j).medMethod && pSpot.medMethod == otherSpot.medMethod; locallab.spots.at(j).activlum = locallab.spots.at(j).activlum && pSpot.activlum == otherSpot.activlum; + locallab.spots.at(j).CCmaskblcurve = locallab.spots.at(j).CCmaskblcurve && pSpot.CCmaskblcurve == otherSpot.CCmaskblcurve; + locallab.spots.at(j).LLmaskblcurve = locallab.spots.at(j).LLmaskblcurve && pSpot.LLmaskblcurve == otherSpot.LLmaskblcurve; + locallab.spots.at(j).HHmaskblcurve = locallab.spots.at(j).HHmaskblcurve && pSpot.HHmaskblcurve == otherSpot.HHmaskblcurve; + locallab.spots.at(j).enablMask = locallab.spots.at(j).enablMask && pSpot.enablMask == otherSpot.enablMask; + locallab.spots.at(j).fftwbl = locallab.spots.at(j).fftwbl && pSpot.fftwbl == otherSpot.fftwbl; + locallab.spots.at(j).toolbl = locallab.spots.at(j).toolbl && pSpot.toolbl == otherSpot.toolbl; + locallab.spots.at(j).blendmaskbl = locallab.spots.at(j).blendmaskbl && pSpot.blendmaskbl == otherSpot.blendmaskbl; + locallab.spots.at(j).radmaskbl = locallab.spots.at(j).radmaskbl && pSpot.radmaskbl == otherSpot.radmaskbl; + locallab.spots.at(j).chromaskbl = locallab.spots.at(j).chromaskbl && pSpot.chromaskbl == otherSpot.chromaskbl; + locallab.spots.at(j).gammaskbl = locallab.spots.at(j).gammaskbl && pSpot.gammaskbl == otherSpot.gammaskbl; + locallab.spots.at(j).slomaskbl = locallab.spots.at(j).slomaskbl && pSpot.slomaskbl == otherSpot.slomaskbl; + locallab.spots.at(j).lapmaskbl = locallab.spots.at(j).lapmaskbl && pSpot.lapmaskbl == otherSpot.lapmaskbl; + locallab.spots.at(j).shadmaskbl = locallab.spots.at(j).shadmaskbl && pSpot.shadmaskbl == otherSpot.shadmaskbl; + locallab.spots.at(j).strumaskbl = locallab.spots.at(j).strumaskbl && pSpot.strumaskbl == otherSpot.strumaskbl; + locallab.spots.at(j).Lmaskblcurve = locallab.spots.at(j).Lmaskblcurve && pSpot.Lmaskblcurve == otherSpot.Lmaskblcurve; + locallab.spots.at(j).LLmaskblcurvewav = locallab.spots.at(j).LLmaskblcurvewav && pSpot.LLmaskblcurvewav == otherSpot.LLmaskblcurvewav; + locallab.spots.at(j).csthresholdblur = locallab.spots.at(j).csthresholdblur && pSpot.csthresholdblur == otherSpot.csthresholdblur; // Tone Mapping locallab.spots.at(j).visitonemap = locallab.spots.at(j).visitonemap && pSpot.visitonemap == otherSpot.visitonemap; locallab.spots.at(j).exptonemap = locallab.spots.at(j).exptonemap && pSpot.exptonemap == otherSpot.exptonemap; @@ -1079,11 +1212,14 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).LLmasktmcurve = locallab.spots.at(j).LLmasktmcurve && pSpot.LLmasktmcurve == otherSpot.LLmasktmcurve; locallab.spots.at(j).HHmasktmcurve = locallab.spots.at(j).HHmasktmcurve && pSpot.HHmasktmcurve == otherSpot.HHmasktmcurve; locallab.spots.at(j).enatmMask = locallab.spots.at(j).enatmMask && pSpot.enatmMask == otherSpot.enatmMask; + locallab.spots.at(j).enatmMaskaft = locallab.spots.at(j).enatmMaskaft && pSpot.enatmMaskaft == otherSpot.enatmMaskaft; locallab.spots.at(j).blendmasktm = locallab.spots.at(j).blendmasktm && pSpot.blendmasktm == otherSpot.blendmasktm; locallab.spots.at(j).radmasktm = locallab.spots.at(j).radmasktm && pSpot.radmasktm == otherSpot.radmasktm; locallab.spots.at(j).chromasktm = locallab.spots.at(j).chromasktm && pSpot.chromasktm == otherSpot.chromasktm; locallab.spots.at(j).gammasktm = locallab.spots.at(j).gammasktm && pSpot.gammasktm == otherSpot.gammasktm; locallab.spots.at(j).slomasktm = locallab.spots.at(j).slomasktm && pSpot.slomasktm == otherSpot.slomasktm; + locallab.spots.at(j).lapmasktm = locallab.spots.at(j).lapmasktm && pSpot.lapmasktm == otherSpot.lapmasktm; + locallab.spots.at(j).Lmasktmcurve = locallab.spots.at(j).Lmasktmcurve && pSpot.Lmasktmcurve == otherSpot.Lmasktmcurve; // Retinex locallab.spots.at(j).visireti = locallab.spots.at(j).visireti && pSpot.visireti == otherSpot.visireti; locallab.spots.at(j).expreti = locallab.spots.at(j).expreti && pSpot.expreti == otherSpot.expreti; @@ -1092,11 +1228,16 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).chrrt = locallab.spots.at(j).chrrt && pSpot.chrrt == otherSpot.chrrt; locallab.spots.at(j).neigh = locallab.spots.at(j).neigh && pSpot.neigh == otherSpot.neigh; locallab.spots.at(j).vart = locallab.spots.at(j).vart && pSpot.vart == otherSpot.vart; + locallab.spots.at(j).offs = locallab.spots.at(j).offs && pSpot.offs == otherSpot.offs; locallab.spots.at(j).dehaz = locallab.spots.at(j).dehaz && pSpot.dehaz == otherSpot.dehaz; + locallab.spots.at(j).depth = locallab.spots.at(j).depth && pSpot.depth == otherSpot.depth; locallab.spots.at(j).sensih = locallab.spots.at(j).sensih && pSpot.sensih == otherSpot.sensih; locallab.spots.at(j).localTgaincurve = locallab.spots.at(j).localTgaincurve && pSpot.localTgaincurve == otherSpot.localTgaincurve; + locallab.spots.at(j).localTtranscurve = locallab.spots.at(j).localTtranscurve && pSpot.localTtranscurve == otherSpot.localTtranscurve; locallab.spots.at(j).inversret = locallab.spots.at(j).inversret && pSpot.inversret == otherSpot.inversret; locallab.spots.at(j).equilret = locallab.spots.at(j).equilret && pSpot.equilret == otherSpot.equilret; + locallab.spots.at(j).loglin = locallab.spots.at(j).loglin && pSpot.loglin == otherSpot.loglin; + locallab.spots.at(j).lumonly = locallab.spots.at(j).lumonly && pSpot.lumonly == otherSpot.lumonly; locallab.spots.at(j).softradiusret = locallab.spots.at(j).softradiusret && pSpot.softradiusret == otherSpot.softradiusret; locallab.spots.at(j).CCmaskreticurve = locallab.spots.at(j).CCmaskreticurve && pSpot.CCmaskreticurve == otherSpot.CCmaskreticurve; locallab.spots.at(j).LLmaskreticurve = locallab.spots.at(j).LLmaskreticurve && pSpot.LLmaskreticurve == otherSpot.LLmaskreticurve; @@ -1108,11 +1249,14 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).chromaskreti = locallab.spots.at(j).chromaskreti && pSpot.chromaskreti == otherSpot.chromaskreti; locallab.spots.at(j).gammaskreti = locallab.spots.at(j).gammaskreti && pSpot.gammaskreti == otherSpot.gammaskreti; locallab.spots.at(j).slomaskreti = locallab.spots.at(j).slomaskreti && pSpot.slomaskreti == otherSpot.slomaskreti; + locallab.spots.at(j).lapmaskreti = locallab.spots.at(j).lapmaskreti && pSpot.lapmaskreti == otherSpot.lapmaskreti; locallab.spots.at(j).scalereti = locallab.spots.at(j).scalereti && pSpot.scalereti == otherSpot.scalereti; locallab.spots.at(j).darkness = locallab.spots.at(j).darkness && pSpot.darkness == otherSpot.darkness; locallab.spots.at(j).lightnessreti = locallab.spots.at(j).lightnessreti && pSpot.lightnessreti == otherSpot.lightnessreti; locallab.spots.at(j).limd = locallab.spots.at(j).limd && pSpot.limd == otherSpot.limd; + locallab.spots.at(j).cliptm = locallab.spots.at(j).cliptm && pSpot.cliptm == otherSpot.cliptm; locallab.spots.at(j).fftwreti = locallab.spots.at(j).fftwreti && pSpot.fftwreti == otherSpot.fftwreti; + locallab.spots.at(j).Lmaskreticurve = locallab.spots.at(j).Lmaskreticurve && pSpot.Lmaskreticurve == otherSpot.Lmaskreticurve; // Sharpening locallab.spots.at(j).visisharp = locallab.spots.at(j).visisharp && pSpot.visisharp == otherSpot.visisharp; locallab.spots.at(j).expsharp = locallab.spots.at(j).expsharp && pSpot.expsharp == otherSpot.expsharp; @@ -1133,10 +1277,60 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).lclightness = locallab.spots.at(j).lclightness && pSpot.lclightness == otherSpot.lclightness; locallab.spots.at(j).levelwav = locallab.spots.at(j).levelwav && pSpot.levelwav == otherSpot.levelwav; locallab.spots.at(j).residcont = locallab.spots.at(j).residcont && pSpot.residcont == otherSpot.residcont; + locallab.spots.at(j).residblur = locallab.spots.at(j).residblur && pSpot.residblur == otherSpot.residblur; + locallab.spots.at(j).levelblur = locallab.spots.at(j).levelblur && pSpot.levelblur == otherSpot.levelblur; + locallab.spots.at(j).residchro = locallab.spots.at(j).residchro && pSpot.residchro == otherSpot.residchro; + locallab.spots.at(j).residcomp = locallab.spots.at(j).residcomp && pSpot.residcomp == otherSpot.residcomp; + locallab.spots.at(j).sigma = locallab.spots.at(j).sigma && pSpot.sigma == otherSpot.sigma; + locallab.spots.at(j).offset = locallab.spots.at(j).offset && pSpot.offset == otherSpot.offset; + locallab.spots.at(j).threswav = locallab.spots.at(j).threswav && pSpot.threswav == otherSpot.threswav; + locallab.spots.at(j).chromalev = locallab.spots.at(j).chromalev && pSpot.chromalev == otherSpot.chromalev; + locallab.spots.at(j).chromablu = locallab.spots.at(j).chromablu && pSpot.chromablu == otherSpot.chromablu; + locallab.spots.at(j).fatdet = locallab.spots.at(j).fatdet && pSpot.fatdet == otherSpot.fatdet; + locallab.spots.at(j).fatanch = locallab.spots.at(j).fatanch && pSpot.fatanch == otherSpot.fatanch; + locallab.spots.at(j).fatres = locallab.spots.at(j).fatres && pSpot.fatres == otherSpot.fatres; + locallab.spots.at(j).clarilres = locallab.spots.at(j).clarilres && pSpot.clarilres == otherSpot.clarilres; + locallab.spots.at(j).claricres = locallab.spots.at(j).claricres && pSpot.claricres == otherSpot.claricres; + locallab.spots.at(j).clarisoft = locallab.spots.at(j).clarisoft && pSpot.clarisoft == otherSpot.clarisoft; + locallab.spots.at(j).strwav = locallab.spots.at(j).strwav && pSpot.strwav == otherSpot.strwav; + locallab.spots.at(j).angwav = locallab.spots.at(j).angwav && pSpot.angwav == otherSpot.angwav; + locallab.spots.at(j).strengthw = locallab.spots.at(j).strengthw && pSpot.strengthw == otherSpot.strengthw; + locallab.spots.at(j).radiusw = locallab.spots.at(j).radiusw && pSpot.radiusw == otherSpot.radiusw; + locallab.spots.at(j).detailw = locallab.spots.at(j).detailw && pSpot.detailw == otherSpot.detailw; + locallab.spots.at(j).gradw = locallab.spots.at(j).gradw && pSpot.gradw == otherSpot.gradw; + locallab.spots.at(j).tloww = locallab.spots.at(j).tloww && pSpot.tloww == otherSpot.tloww; + locallab.spots.at(j).thigw = locallab.spots.at(j).thigw && pSpot.thigw == otherSpot.thigw; + locallab.spots.at(j).edgw = locallab.spots.at(j).edgw && pSpot.edgw == otherSpot.edgw; + locallab.spots.at(j).basew = locallab.spots.at(j).basew && pSpot.basew == otherSpot.basew; locallab.spots.at(j).sensilc = locallab.spots.at(j).sensilc && pSpot.sensilc == otherSpot.sensilc; locallab.spots.at(j).fftwlc = locallab.spots.at(j).fftwlc && pSpot.fftwlc == otherSpot.fftwlc; + locallab.spots.at(j).blurlc = locallab.spots.at(j).blurlc && pSpot.blurlc == otherSpot.blurlc; + locallab.spots.at(j).wavblur = locallab.spots.at(j).wavblur && pSpot.wavblur == otherSpot.wavblur; + locallab.spots.at(j).wavedg = locallab.spots.at(j).wavedg && pSpot.wavedg == otherSpot.wavedg; + locallab.spots.at(j).waveshow = locallab.spots.at(j).waveshow && pSpot.waveshow == otherSpot.waveshow; + locallab.spots.at(j).wavcont = locallab.spots.at(j).wavcont && pSpot.wavcont == otherSpot.wavcont; + locallab.spots.at(j).wavcomp = locallab.spots.at(j).wavcomp && pSpot.wavcomp == otherSpot.wavcomp; + locallab.spots.at(j).wavgradl = locallab.spots.at(j).wavgradl && pSpot.wavgradl == otherSpot.wavgradl; + locallab.spots.at(j).wavcompre = locallab.spots.at(j).wavcompre && pSpot.wavcompre == otherSpot.wavcompre; + locallab.spots.at(j).origlc = locallab.spots.at(j).origlc && pSpot.origlc == otherSpot.origlc; locallab.spots.at(j).localcontMethod = locallab.spots.at(j).localcontMethod && pSpot.localcontMethod == otherSpot.localcontMethod; + locallab.spots.at(j).localedgMethod = locallab.spots.at(j).localedgMethod && pSpot.localedgMethod == otherSpot.localedgMethod; + locallab.spots.at(j).localneiMethod = locallab.spots.at(j).localneiMethod && pSpot.localneiMethod == otherSpot.localneiMethod; locallab.spots.at(j).locwavcurve = locallab.spots.at(j).locwavcurve && pSpot.locwavcurve == otherSpot.locwavcurve; + locallab.spots.at(j).csthreshold = locallab.spots.at(j).csthreshold && pSpot.csthreshold == otherSpot.csthreshold; + locallab.spots.at(j).loclevwavcurve = locallab.spots.at(j).loclevwavcurve && pSpot.loclevwavcurve == otherSpot.loclevwavcurve; + locallab.spots.at(j).locconwavcurve = locallab.spots.at(j).locconwavcurve && pSpot.locconwavcurve == otherSpot.locconwavcurve; + locallab.spots.at(j).loccompwavcurve = locallab.spots.at(j).loccompwavcurve && pSpot.loccompwavcurve == otherSpot.loccompwavcurve; + locallab.spots.at(j).loccomprewavcurve = locallab.spots.at(j).loccomprewavcurve && pSpot.loccomprewavcurve == otherSpot.loccomprewavcurve; + locallab.spots.at(j).locedgwavcurve = locallab.spots.at(j).locedgwavcurve && pSpot.locedgwavcurve == otherSpot.locedgwavcurve; + locallab.spots.at(j).CCmasklccurve = locallab.spots.at(j).CCmasklccurve && pSpot.CCmasklccurve == otherSpot.CCmasklccurve; + locallab.spots.at(j).LLmasklccurve = locallab.spots.at(j).LLmasklccurve && pSpot.LLmasklccurve == otherSpot.LLmasklccurve; + locallab.spots.at(j).HHmasklccurve = locallab.spots.at(j).HHmasklccurve && pSpot.HHmasklccurve == otherSpot.HHmasklccurve; + locallab.spots.at(j).enalcMask = locallab.spots.at(j).enalcMask && pSpot.enalcMask == otherSpot.enalcMask; + locallab.spots.at(j).blendmasklc = locallab.spots.at(j).blendmasklc && pSpot.blendmasklc == otherSpot.blendmasklc; + locallab.spots.at(j).radmasklc = locallab.spots.at(j).radmasklc && pSpot.radmaskcb == otherSpot.radmasklc; + locallab.spots.at(j).chromasklc = locallab.spots.at(j).chromasklc && pSpot.chromasklc == otherSpot.chromasklc; + locallab.spots.at(j).Lmasklccurve = locallab.spots.at(j).Lmasklccurve && pSpot.Lmasklccurve == otherSpot.Lmasklccurve; // Contrast by detail levels locallab.spots.at(j).visicbdl = locallab.spots.at(j).visicbdl && pSpot.visicbdl == otherSpot.visicbdl; locallab.spots.at(j).expcbdl = locallab.spots.at(j).expcbdl && pSpot.expcbdl == otherSpot.expcbdl; @@ -1151,16 +1345,18 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).clarityml = locallab.spots.at(j).clarityml && pSpot.clarityml == otherSpot.clarityml; locallab.spots.at(j).contresid = locallab.spots.at(j).contresid && pSpot.contresid == otherSpot.contresid; locallab.spots.at(j).blurcbdl = locallab.spots.at(j).blurcbdl && pSpot.blurcbdl == otherSpot.blurcbdl; - locallab.spots.at(j).blendmaskcb = locallab.spots.at(j).blendmaskcb && pSpot.blendmaskcb == otherSpot.blendmaskcb; - locallab.spots.at(j).radmaskcb = locallab.spots.at(j).radmaskcb && pSpot.radmaskcb == otherSpot.radmaskcb; - locallab.spots.at(j).chromaskcb = locallab.spots.at(j).chromaskcb && pSpot.chromaskcb == otherSpot.chromaskcb; - locallab.spots.at(j).gammaskcb = locallab.spots.at(j).gammaskcb && pSpot.gammaskcb == otherSpot.gammaskcb; - locallab.spots.at(j).slomaskcb = locallab.spots.at(j).slomaskcb && pSpot.slomaskcb == otherSpot.slomaskcb; locallab.spots.at(j).softradiuscb = locallab.spots.at(j).softradiuscb && pSpot.softradiuscb == otherSpot.softradiuscb; locallab.spots.at(j).enacbMask = locallab.spots.at(j).enacbMask && pSpot.enacbMask == otherSpot.enacbMask; locallab.spots.at(j).CCmaskcbcurve = locallab.spots.at(j).CCmaskcbcurve && pSpot.CCmaskcbcurve == otherSpot.CCmaskcbcurve; locallab.spots.at(j).LLmaskcbcurve = locallab.spots.at(j).LLmaskcbcurve && pSpot.LLmaskcbcurve == otherSpot.LLmaskcbcurve; locallab.spots.at(j).HHmaskcbcurve = locallab.spots.at(j).HHmaskcbcurve && pSpot.HHmaskcbcurve == otherSpot.HHmaskcbcurve; + locallab.spots.at(j).blendmaskcb = locallab.spots.at(j).blendmaskcb && pSpot.blendmaskcb == otherSpot.blendmaskcb; + locallab.spots.at(j).radmaskcb = locallab.spots.at(j).radmaskcb && pSpot.radmaskcb == otherSpot.radmaskcb; + locallab.spots.at(j).chromaskcb = locallab.spots.at(j).chromaskcb && pSpot.chromaskcb == otherSpot.chromaskcb; + locallab.spots.at(j).gammaskcb = locallab.spots.at(j).gammaskcb && pSpot.gammaskcb == otherSpot.gammaskcb; + locallab.spots.at(j).slomaskcb = locallab.spots.at(j).slomaskcb && pSpot.slomaskcb == otherSpot.slomaskcb; + locallab.spots.at(j).lapmaskcb = locallab.spots.at(j).lapmaskcb && pSpot.lapmaskcb == otherSpot.lapmaskcb; + locallab.spots.at(j).Lmaskcbcurve = locallab.spots.at(j).Lmaskcbcurve && pSpot.Lmaskcbcurve == otherSpot.Lmaskcbcurve; // Denoise locallab.spots.at(j).visidenoi = locallab.spots.at(j).visidenoi && pSpot.visidenoi == otherSpot.visidenoi; locallab.spots.at(j).expdenoi = locallab.spots.at(j).expdenoi && pSpot.expdenoi == otherSpot.expdenoi; @@ -1176,6 +1372,23 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).adjblur = locallab.spots.at(j).adjblur && pSpot.adjblur == otherSpot.adjblur; locallab.spots.at(j).bilateral = locallab.spots.at(j).bilateral && pSpot.bilateral == otherSpot.bilateral; locallab.spots.at(j).sensiden = locallab.spots.at(j).sensiden && pSpot.sensiden == otherSpot.sensiden; + locallab.spots.at(j).detailthr = locallab.spots.at(j).detailthr && pSpot.detailthr == otherSpot.detailthr; + locallab.spots.at(j).locwavcurveden = locallab.spots.at(j).locwavcurveden && pSpot.locwavcurveden == otherSpot.locwavcurveden; + // Log encoding + locallab.spots.at(j).visilog = locallab.spots.at(j).visilog && pSpot.visilog == otherSpot.visilog; + locallab.spots.at(j).explog = locallab.spots.at(j).explog && pSpot.explog == otherSpot.explog; + locallab.spots.at(j).autocompute = locallab.spots.at(j).autocompute && pSpot.autocompute == otherSpot.autocompute; + locallab.spots.at(j).sourceGray = locallab.spots.at(j).sourceGray && pSpot.sourceGray == otherSpot.sourceGray; + locallab.spots.at(j).targetGray = locallab.spots.at(j).targetGray && pSpot.targetGray == otherSpot.targetGray; + locallab.spots.at(j).Autogray = locallab.spots.at(j).Autogray && pSpot.Autogray == otherSpot.Autogray; + locallab.spots.at(j).fullimage = locallab.spots.at(j).fullimage && pSpot.fullimage == otherSpot.fullimage; + locallab.spots.at(j).blackEv = locallab.spots.at(j).blackEv && pSpot.blackEv == otherSpot.blackEv; + locallab.spots.at(j).whiteEv = locallab.spots.at(j).whiteEv && pSpot.whiteEv == otherSpot.whiteEv; + locallab.spots.at(j).detail = locallab.spots.at(j).detail && pSpot.detail == otherSpot.detail; + locallab.spots.at(j).sensilog = locallab.spots.at(j).sensilog && pSpot.sensilog == otherSpot.sensilog; + locallab.spots.at(j).baselog = locallab.spots.at(j).baselog && pSpot.baselog == otherSpot.baselog; + locallab.spots.at(j).strlog = locallab.spots.at(j).strlog && pSpot.strlog == otherSpot.strlog; + locallab.spots.at(j).anglog = locallab.spots.at(j).anglog && pSpot.anglog == otherSpot.anglog; } } @@ -1391,20 +1604,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; @@ -1424,6 +1634,7 @@ 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; @@ -1936,6 +2147,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng 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; } @@ -1984,6 +2199,38 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng 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.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 (pdsharpening.deconvitercheck) { + toEdit.pdsharpening.deconvitercheck = mods.pdsharpening.deconvitercheck; + } + if (prsharpening.enabled) { toEdit.prsharpening.enabled = mods.prsharpening.enabled; } @@ -2491,6 +2738,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.coarse.vflip = mods.coarse.vflip; } + if (commonTrans.method) { + toEdit.commonTrans.method = mods.commonTrans.method; + } + if (commonTrans.autofill) { toEdit.commonTrans.autofill = mods.commonTrans.autofill; } @@ -2598,6 +2849,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).spotMethod = mods.locallab.spots.at(i).spotMethod; } + if (locallab.spots.at(i).wavMethod) { + toEdit.locallab.spots.at(i).wavMethod = mods.locallab.spots.at(i).wavMethod; + } + if (locallab.spots.at(i).sensiexclu) { toEdit.locallab.spots.at(i).sensiexclu = mods.locallab.spots.at(i).sensiexclu; } @@ -2646,10 +2901,17 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).qualityMethod = mods.locallab.spots.at(i).qualityMethod; } + if (locallab.spots.at(i).complexMethod) { + toEdit.locallab.spots.at(i).complexMethod = mods.locallab.spots.at(i).complexMethod; + } + if (locallab.spots.at(i).transit) { toEdit.locallab.spots.at(i).transit = mods.locallab.spots.at(i).transit; } + if (locallab.spots.at(i).feather) { + toEdit.locallab.spots.at(i).feather = mods.locallab.spots.at(i).feather; + } if (locallab.spots.at(i).thresh) { toEdit.locallab.spots.at(i).thresh = mods.locallab.spots.at(i).thresh; @@ -2663,6 +2925,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).balan = mods.locallab.spots.at(i).balan; } + if (locallab.spots.at(i).balanh) { + toEdit.locallab.spots.at(i).balanh = mods.locallab.spots.at(i).balanh; + } + + if (locallab.spots.at(i).colorde) { + toEdit.locallab.spots.at(i).colorde = mods.locallab.spots.at(i).colorde; + } + if (locallab.spots.at(i).transitweak) { toEdit.locallab.spots.at(i).transitweak = mods.locallab.spots.at(i).transitweak; } @@ -2675,6 +2945,34 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).avoid = mods.locallab.spots.at(i).avoid; } + if (locallab.spots.at(i).recurs) { + toEdit.locallab.spots.at(i).recurs = mods.locallab.spots.at(i).recurs; + } + + if (locallab.spots.at(i).laplac) { + toEdit.locallab.spots.at(i).laplac = mods.locallab.spots.at(i).laplac; + } + + if (locallab.spots.at(i).deltae) { + toEdit.locallab.spots.at(i).deltae = mods.locallab.spots.at(i).deltae; + } + + if (locallab.spots.at(i).shortc) { + toEdit.locallab.spots.at(i).shortc = mods.locallab.spots.at(i).shortc; + } + + if (locallab.spots.at(i).savrest) { + toEdit.locallab.spots.at(i).savrest = mods.locallab.spots.at(i).savrest; + } + + if (locallab.spots.at(i).scopemask) { + toEdit.locallab.spots.at(i).scopemask = mods.locallab.spots.at(i).scopemask; + } + + if (locallab.spots.at(i).lumask) { + toEdit.locallab.spots.at(i).lumask = mods.locallab.spots.at(i).lumask; + } + // Color & Light if (locallab.spots.at(i).visicolor) { toEdit.locallab.spots.at(i).visicolor = mods.locallab.spots.at(i).visicolor; @@ -2716,6 +3014,22 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).labgridBHigh = mods.locallab.spots.at(i).labgridBHigh; } + if (locallab.spots.at(i).labgridALowmerg) { + toEdit.locallab.spots.at(i).labgridALowmerg = mods.locallab.spots.at(i).labgridALowmerg; + } + + if (locallab.spots.at(i).labgridBLowmerg) { + toEdit.locallab.spots.at(i).labgridBLowmerg = mods.locallab.spots.at(i).labgridBLowmerg; + } + + if (locallab.spots.at(i).labgridAHighmerg) { + toEdit.locallab.spots.at(i).labgridAHighmerg = mods.locallab.spots.at(i).labgridAHighmerg; + } + + if (locallab.spots.at(i).labgridBHighmerg) { + toEdit.locallab.spots.at(i).labgridBHighmerg = mods.locallab.spots.at(i).labgridBHighmerg; + } + if (locallab.spots.at(i).strengthgrid) { toEdit.locallab.spots.at(i).strengthgrid = mods.locallab.spots.at(i).strengthgrid; } @@ -2724,12 +3038,36 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).sensi = mods.locallab.spots.at(i).sensi; } + if (locallab.spots.at(i).structcol) { + toEdit.locallab.spots.at(i).structcol = mods.locallab.spots.at(i).structcol; + } + + if (locallab.spots.at(i).strcol) { + toEdit.locallab.spots.at(i).strcol = mods.locallab.spots.at(i).strcol; + } + + if (locallab.spots.at(i).strcolab) { + toEdit.locallab.spots.at(i).strcolab = mods.locallab.spots.at(i).strcolab; + } + + if (locallab.spots.at(i).strcolh) { + toEdit.locallab.spots.at(i).strcolh = mods.locallab.spots.at(i).strcolh; + } + + if (locallab.spots.at(i).angcol) { + toEdit.locallab.spots.at(i).angcol = mods.locallab.spots.at(i).angcol; + } + if (locallab.spots.at(i).blurcolde) { toEdit.locallab.spots.at(i).blurcolde = mods.locallab.spots.at(i).blurcolde; } - if (locallab.spots.at(i).structcol) { - toEdit.locallab.spots.at(i).structcol = mods.locallab.spots.at(i).structcol; + if (locallab.spots.at(i).blurcol) { + toEdit.locallab.spots.at(i).blurcol = mods.locallab.spots.at(i).blurcol; + } + + if (locallab.spots.at(i).contcol) { + toEdit.locallab.spots.at(i).contcol = mods.locallab.spots.at(i).contcol; } if (locallab.spots.at(i).blendmaskcol) { @@ -2752,6 +3090,18 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).slomaskcol = mods.locallab.spots.at(i).slomaskcol; } + if (locallab.spots.at(i).shadmaskcol) { + toEdit.locallab.spots.at(i).shadmaskcol = mods.locallab.spots.at(i).shadmaskcol; + } + + if (locallab.spots.at(i).strumaskcol) { + toEdit.locallab.spots.at(i).strumaskcol = mods.locallab.spots.at(i).strumaskcol; + } + + if (locallab.spots.at(i).lapmaskcol) { + toEdit.locallab.spots.at(i).lapmaskcol = mods.locallab.spots.at(i).lapmaskcol; + } + if (locallab.spots.at(i).qualitycurveMethod) { toEdit.locallab.spots.at(i).qualitycurveMethod = mods.locallab.spots.at(i).qualitycurveMethod; } @@ -2760,14 +3110,38 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).gridMethod = mods.locallab.spots.at(i).gridMethod; } + if (locallab.spots.at(i).merMethod) { + toEdit.locallab.spots.at(i).merMethod = mods.locallab.spots.at(i).merMethod; + } + + if (locallab.spots.at(i).toneMethod) { + toEdit.locallab.spots.at(i).toneMethod = mods.locallab.spots.at(i).toneMethod; + } + + if (locallab.spots.at(i).mergecolMethod) { + toEdit.locallab.spots.at(i).mergecolMethod = mods.locallab.spots.at(i).mergecolMethod; + } + if (locallab.spots.at(i).llcurve) { toEdit.locallab.spots.at(i).llcurve = mods.locallab.spots.at(i).llcurve; } + if (locallab.spots.at(i).lccurve) { + toEdit.locallab.spots.at(i).lccurve = mods.locallab.spots.at(i).lccurve; + } + if (locallab.spots.at(i).cccurve) { toEdit.locallab.spots.at(i).cccurve = mods.locallab.spots.at(i).cccurve; } + if (locallab.spots.at(i).clcurve) { + toEdit.locallab.spots.at(i).clcurve = mods.locallab.spots.at(i).clcurve; + } + + if (locallab.spots.at(i).rgbcurve) { + toEdit.locallab.spots.at(i).rgbcurve = mods.locallab.spots.at(i).rgbcurve; + } + if (locallab.spots.at(i).LHcurve) { toEdit.locallab.spots.at(i).LHcurve = mods.locallab.spots.at(i).LHcurve; } @@ -2780,10 +3154,22 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).invers = mods.locallab.spots.at(i).invers; } + if (locallab.spots.at(i).special) { + toEdit.locallab.spots.at(i).special = mods.locallab.spots.at(i).special; + } + + if (locallab.spots.at(i).toolcol) { + toEdit.locallab.spots.at(i).toolcol = mods.locallab.spots.at(i).toolcol; + } + if (locallab.spots.at(i).enaColorMask) { toEdit.locallab.spots.at(i).enaColorMask = mods.locallab.spots.at(i).enaColorMask; } + if (locallab.spots.at(i).fftColorMask) { + toEdit.locallab.spots.at(i).fftColorMask = mods.locallab.spots.at(i).fftColorMask; + } + if (locallab.spots.at(i).CCmaskcurve) { toEdit.locallab.spots.at(i).CCmaskcurve = mods.locallab.spots.at(i).CCmaskcurve; } @@ -2796,10 +3182,42 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).HHmaskcurve = mods.locallab.spots.at(i).HHmaskcurve; } + if (locallab.spots.at(i).HHhmaskcurve) { + toEdit.locallab.spots.at(i).HHhmaskcurve = mods.locallab.spots.at(i).HHhmaskcurve; + } + if (locallab.spots.at(i).softradiuscol) { toEdit.locallab.spots.at(i).softradiuscol = mods.locallab.spots.at(i).softradiuscol; } + if (locallab.spots.at(i).opacol) { + toEdit.locallab.spots.at(i).opacol = mods.locallab.spots.at(i).opacol; + } + + if (locallab.spots.at(i).mercol) { + toEdit.locallab.spots.at(i).mercol = mods.locallab.spots.at(i).mercol; + } + + if (locallab.spots.at(i).merlucol) { + toEdit.locallab.spots.at(i).merlucol = mods.locallab.spots.at(i).merlucol; + } + + if (locallab.spots.at(i).conthrcol) { + toEdit.locallab.spots.at(i).conthrcol = mods.locallab.spots.at(i).conthrcol; + } + + if (locallab.spots.at(i).Lmaskcurve) { + toEdit.locallab.spots.at(i).Lmaskcurve = mods.locallab.spots.at(i).Lmaskcurve; + } + + if (locallab.spots.at(i).LLmaskcolcurvewav) { + toEdit.locallab.spots.at(i).LLmaskcolcurvewav = mods.locallab.spots.at(i).LLmaskcolcurvewav; + } + + if (locallab.spots.at(i).csthresholdcol) { + toEdit.locallab.spots.at(i).csthresholdcol = mods.locallab.spots.at(i).csthresholdcol; + } + // Exposure if (locallab.spots.at(i).visiexpose) { toEdit.locallab.spots.at(i).visiexpose = mods.locallab.spots.at(i).visiexpose; @@ -2829,12 +3247,12 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).shadex = mods.locallab.spots.at(i).shadex; } - if (locallab.spots.at(i).expchroma) { - toEdit.locallab.spots.at(i).expchroma = mods.locallab.spots.at(i).expchroma; + if (locallab.spots.at(i).shcompr) { + toEdit.locallab.spots.at(i).shcompr = mods.locallab.spots.at(i).shcompr; } - if (locallab.spots.at(i).warm) { - toEdit.locallab.spots.at(i).warm = mods.locallab.spots.at(i).warm; + if (locallab.spots.at(i).expchroma) { + toEdit.locallab.spots.at(i).expchroma = mods.locallab.spots.at(i).expchroma; } if (locallab.spots.at(i).sensiex) { @@ -2849,6 +3267,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).blurexpde = mods.locallab.spots.at(i).blurexpde; } + if (locallab.spots.at(i).strexp) { + toEdit.locallab.spots.at(i).strexp = mods.locallab.spots.at(i).strexp; + } + + if (locallab.spots.at(i).angexp) { + toEdit.locallab.spots.at(i).angexp = mods.locallab.spots.at(i).angexp; + } + if (locallab.spots.at(i).excurve) { toEdit.locallab.spots.at(i).excurve = mods.locallab.spots.at(i).excurve; } @@ -2861,6 +3287,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).enaExpMask = mods.locallab.spots.at(i).enaExpMask; } + if (locallab.spots.at(i).enaExpMaskaft) { + toEdit.locallab.spots.at(i).enaExpMaskaft = mods.locallab.spots.at(i).enaExpMaskaft; + } + if (locallab.spots.at(i).CCmaskexpcurve) { toEdit.locallab.spots.at(i).CCmaskexpcurve = mods.locallab.spots.at(i).CCmaskexpcurve; } @@ -2893,14 +3323,34 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).slomaskexp = mods.locallab.spots.at(i).slomaskexp; } + if (locallab.spots.at(i).lapmaskexp) { + toEdit.locallab.spots.at(i).lapmaskexp = mods.locallab.spots.at(i).lapmaskexp; + } + + if (locallab.spots.at(i).strmaskexp) { + toEdit.locallab.spots.at(i).strmaskexp = mods.locallab.spots.at(i).strmaskexp; + } + + if (locallab.spots.at(i).angmaskexp) { + toEdit.locallab.spots.at(i).angmaskexp = mods.locallab.spots.at(i).angmaskexp; + } + if (locallab.spots.at(i).softradiusexp) { toEdit.locallab.spots.at(i).softradiusexp = mods.locallab.spots.at(i).softradiusexp; } + if (locallab.spots.at(i).Lmaskexpcurve) { + toEdit.locallab.spots.at(i).Lmaskexpcurve = mods.locallab.spots.at(i).Lmaskexpcurve; + } + if (locallab.spots.at(i).expMethod) { toEdit.locallab.spots.at(i).expMethod = mods.locallab.spots.at(i).expMethod; } + if (locallab.spots.at(i).exnoiseMethod) { + toEdit.locallab.spots.at(i).exnoiseMethod = mods.locallab.spots.at(i).exnoiseMethod; + } + if (locallab.spots.at(i).laplacexp) { toEdit.locallab.spots.at(i).laplacexp = mods.locallab.spots.at(i).laplacexp; } @@ -2913,6 +3363,26 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).linear = mods.locallab.spots.at(i).linear; } + if (locallab.spots.at(i).gamm) { + toEdit.locallab.spots.at(i).gamm = mods.locallab.spots.at(i).gamm; + } + + if (locallab.spots.at(i).fatamount) { + toEdit.locallab.spots.at(i).fatamount = mods.locallab.spots.at(i).fatamount; + } + + if (locallab.spots.at(i).fatdetail) { + toEdit.locallab.spots.at(i).fatdetail = mods.locallab.spots.at(i).fatdetail; + } + + if (locallab.spots.at(i).fatanchor) { + toEdit.locallab.spots.at(i).fatanchor = mods.locallab.spots.at(i).fatanchor; + } + + if (locallab.spots.at(i).fatlevel) { + toEdit.locallab.spots.at(i).fatlevel = mods.locallab.spots.at(i).fatlevel; + } + // Shadow highlight if (locallab.spots.at(i).visishadhigh) { toEdit.locallab.spots.at(i).visishadhigh = mods.locallab.spots.at(i).visishadhigh; @@ -2922,6 +3392,16 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).expshadhigh = mods.locallab.spots.at(i).expshadhigh; } + if (locallab.spots.at(i).shMethod) { + toEdit.locallab.spots.at(i).shMethod = mods.locallab.spots.at(i).shMethod; + } + + for (int j = 0; j < 5; j++) { + if (locallab.spots.at(i).multsh[j]) { + toEdit.locallab.spots.at(i).multsh[j] = mods.locallab.spots.at(i).multsh[j]; + } + } + if (locallab.spots.at(i).highlights) { toEdit.locallab.spots.at(i).highlights = mods.locallab.spots.at(i).highlights; } @@ -2974,6 +3454,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).blurSHde = mods.locallab.spots.at(i).blurSHde; } + if (locallab.spots.at(i).strSH) { + toEdit.locallab.spots.at(i).strSH = mods.locallab.spots.at(i).strSH; + } + + if (locallab.spots.at(i).angSH) { + toEdit.locallab.spots.at(i).angSH = mods.locallab.spots.at(i).angSH; + } + if (locallab.spots.at(i).inverssh) { toEdit.locallab.spots.at(i).inverssh = mods.locallab.spots.at(i).inverssh; } @@ -2990,6 +3478,34 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).slomaskSH = mods.locallab.spots.at(i).slomaskSH; } + if (locallab.spots.at(i).lapmaskSH) { + toEdit.locallab.spots.at(i).lapmaskSH = mods.locallab.spots.at(i).lapmaskSH; + } + + if (locallab.spots.at(i).detailSH) { + toEdit.locallab.spots.at(i).detailSH = mods.locallab.spots.at(i).detailSH; + } + + if (locallab.spots.at(i).LmaskSHcurve) { + toEdit.locallab.spots.at(i).LmaskSHcurve = mods.locallab.spots.at(i).LmaskSHcurve; + } + + if (locallab.spots.at(i).fatamountSH) { + toEdit.locallab.spots.at(i).fatamountSH = mods.locallab.spots.at(i).fatamountSH; + } + + if (locallab.spots.at(i).fatanchorSH) { + toEdit.locallab.spots.at(i).fatanchorSH = mods.locallab.spots.at(i).fatanchorSH; + } + + if (locallab.spots.at(i).gamSH) { + toEdit.locallab.spots.at(i).gamSH = mods.locallab.spots.at(i).gamSH; + } + + if (locallab.spots.at(i).sloSH) { + toEdit.locallab.spots.at(i).sloSH = mods.locallab.spots.at(i).sloSH; + } + // Vibrance if (locallab.spots.at(i).visivibrance) { toEdit.locallab.spots.at(i).visivibrance = mods.locallab.spots.at(i).visivibrance; @@ -3007,6 +3523,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).pastels = mods.locallab.spots.at(i).pastels; } + if (locallab.spots.at(i).warm) { + toEdit.locallab.spots.at(i).warm = mods.locallab.spots.at(i).warm; + } + if (locallab.spots.at(i).psthreshold) { toEdit.locallab.spots.at(i).psthreshold = mods.locallab.spots.at(i).psthreshold; } @@ -3031,6 +3551,66 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).skintonescurve = mods.locallab.spots.at(i).skintonescurve; } + if (locallab.spots.at(i).CCmaskvibcurve) { + toEdit.locallab.spots.at(i).CCmaskvibcurve = mods.locallab.spots.at(i).CCmaskvibcurve; + } + + if (locallab.spots.at(i).LLmaskvibcurve) { + toEdit.locallab.spots.at(i).LLmaskvibcurve = mods.locallab.spots.at(i).LLmaskvibcurve; + } + + if (locallab.spots.at(i).HHmaskvibcurve) { + toEdit.locallab.spots.at(i).HHmaskvibcurve = mods.locallab.spots.at(i).HHmaskvibcurve; + } + + if (locallab.spots.at(i).enavibMask) { + toEdit.locallab.spots.at(i).enavibMask = mods.locallab.spots.at(i).enavibMask; + } + + if (locallab.spots.at(i).blendmaskvib) { + toEdit.locallab.spots.at(i).blendmaskvib = mods.locallab.spots.at(i).blendmaskvib; + } + + if (locallab.spots.at(i).radmaskvib) { + toEdit.locallab.spots.at(i).radmaskvib = mods.locallab.spots.at(i).radmaskvib; + } + + if (locallab.spots.at(i).chromaskvib) { + toEdit.locallab.spots.at(i).chromaskvib = mods.locallab.spots.at(i).chromaskvib; + } + + if (locallab.spots.at(i).gammaskvib) { + toEdit.locallab.spots.at(i).gammaskvib = mods.locallab.spots.at(i).gammaskvib; + } + + if (locallab.spots.at(i).slomaskvib) { + toEdit.locallab.spots.at(i).slomaskvib = mods.locallab.spots.at(i).slomaskvib; + } + + if (locallab.spots.at(i).lapmaskvib) { + toEdit.locallab.spots.at(i).lapmaskvib = mods.locallab.spots.at(i).lapmaskvib; + } + + if (locallab.spots.at(i).strvib) { + toEdit.locallab.spots.at(i).strvib = mods.locallab.spots.at(i).strvib; + } + + if (locallab.spots.at(i).strvibab) { + toEdit.locallab.spots.at(i).strvibab = mods.locallab.spots.at(i).strvibab; + } + + if (locallab.spots.at(i).strvibh) { + toEdit.locallab.spots.at(i).strvibh = mods.locallab.spots.at(i).strvibh; + } + + if (locallab.spots.at(i).angvib) { + toEdit.locallab.spots.at(i).angvib = mods.locallab.spots.at(i).angvib; + } + + if (locallab.spots.at(i).Lmaskvibcurve) { + toEdit.locallab.spots.at(i).Lmaskvibcurve = mods.locallab.spots.at(i).Lmaskvibcurve; + } + // Soft Light if (locallab.spots.at(i).visisoft) { toEdit.locallab.spots.at(i).visisoft = mods.locallab.spots.at(i).visisoft; @@ -3077,14 +3657,122 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).sensibn = mods.locallab.spots.at(i).sensibn; } + if (locallab.spots.at(i).itera) { + toEdit.locallab.spots.at(i).itera = mods.locallab.spots.at(i).itera; + } + + if (locallab.spots.at(i).guidbl) { + toEdit.locallab.spots.at(i).guidbl = mods.locallab.spots.at(i).guidbl; + } + + if (locallab.spots.at(i).strbl) { + toEdit.locallab.spots.at(i).strbl = mods.locallab.spots.at(i).strbl; + } + + if (locallab.spots.at(i).isogr) { + toEdit.locallab.spots.at(i).isogr = mods.locallab.spots.at(i).isogr; + } + + if (locallab.spots.at(i).strengr) { + toEdit.locallab.spots.at(i).strengr = mods.locallab.spots.at(i).strengr; + } + + if (locallab.spots.at(i).scalegr) { + toEdit.locallab.spots.at(i).scalegr = mods.locallab.spots.at(i).scalegr; + } + + if (locallab.spots.at(i).epsbl) { + toEdit.locallab.spots.at(i).epsbl = mods.locallab.spots.at(i).epsbl; + } + + if (locallab.spots.at(i).blMethod) { + toEdit.locallab.spots.at(i).blMethod = mods.locallab.spots.at(i).blMethod; + } + + if (locallab.spots.at(i).chroMethod) { + toEdit.locallab.spots.at(i).chroMethod = mods.locallab.spots.at(i).chroMethod; + } + if (locallab.spots.at(i).blurMethod) { toEdit.locallab.spots.at(i).blurMethod = mods.locallab.spots.at(i).blurMethod; } + if (locallab.spots.at(i).medMethod) { + toEdit.locallab.spots.at(i).medMethod = mods.locallab.spots.at(i).medMethod; + } + if (locallab.spots.at(i).activlum) { toEdit.locallab.spots.at(i).activlum = mods.locallab.spots.at(i).activlum; } + if (locallab.spots.at(i).CCmaskblcurve) { + toEdit.locallab.spots.at(i).CCmaskblcurve = mods.locallab.spots.at(i).CCmaskblcurve; + } + + if (locallab.spots.at(i).LLmaskblcurve) { + toEdit.locallab.spots.at(i).LLmaskblcurve = mods.locallab.spots.at(i).LLmaskblcurve; + } + + if (locallab.spots.at(i).HHmaskblcurve) { + toEdit.locallab.spots.at(i).HHmaskblcurve = mods.locallab.spots.at(i).HHmaskblcurve; + } + + if (locallab.spots.at(i).enablMask) { + toEdit.locallab.spots.at(i).enablMask = mods.locallab.spots.at(i).enablMask; + } + + if (locallab.spots.at(i).fftwbl) { + toEdit.locallab.spots.at(i).fftwbl = mods.locallab.spots.at(i).fftwbl; + } + + if (locallab.spots.at(i).toolbl) { + toEdit.locallab.spots.at(i).toolbl = mods.locallab.spots.at(i).toolbl; + } + + if (locallab.spots.at(i).blendmaskbl) { + toEdit.locallab.spots.at(i).blendmaskbl = mods.locallab.spots.at(i).blendmaskbl; + } + + if (locallab.spots.at(i).radmaskbl) { + toEdit.locallab.spots.at(i).radmaskbl = mods.locallab.spots.at(i).radmaskbl; + } + + if (locallab.spots.at(i).chromaskbl) { + toEdit.locallab.spots.at(i).chromaskbl = mods.locallab.spots.at(i).chromaskbl; + } + + if (locallab.spots.at(i).gammaskbl) { + toEdit.locallab.spots.at(i).gammaskbl = mods.locallab.spots.at(i).gammaskbl; + } + + if (locallab.spots.at(i).slomaskbl) { + toEdit.locallab.spots.at(i).slomaskbl = mods.locallab.spots.at(i).slomaskbl; + } + + if (locallab.spots.at(i).lapmaskbl) { + toEdit.locallab.spots.at(i).lapmaskbl = mods.locallab.spots.at(i).lapmaskbl; + } + + if (locallab.spots.at(i).shadmaskbl) { + toEdit.locallab.spots.at(i).shadmaskbl = mods.locallab.spots.at(i).shadmaskbl; + } + + if (locallab.spots.at(i).strumaskbl) { + toEdit.locallab.spots.at(i).strumaskbl = mods.locallab.spots.at(i).strumaskbl; + } + + if (locallab.spots.at(i).Lmaskblcurve) { + toEdit.locallab.spots.at(i).Lmaskblcurve = mods.locallab.spots.at(i).Lmaskblcurve; + } + + if (locallab.spots.at(i).LLmaskblcurvewav) { + toEdit.locallab.spots.at(i).LLmaskblcurvewav = mods.locallab.spots.at(i).LLmaskblcurvewav; + } + + if (locallab.spots.at(i).csthresholdblur) { + toEdit.locallab.spots.at(i).csthresholdblur = mods.locallab.spots.at(i).csthresholdblur; + } + // Tone Mapping if (locallab.spots.at(i).visitonemap) { toEdit.locallab.spots.at(i).visitonemap = mods.locallab.spots.at(i).visitonemap; @@ -3102,10 +3790,6 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).gamma = mods.locallab.spots.at(i).gamma; } - if (locallab.spots.at(i).equiltm) { - toEdit.locallab.spots.at(i).equiltm = mods.locallab.spots.at(i).equiltm; - } - if (locallab.spots.at(i).estop) { toEdit.locallab.spots.at(i).estop = mods.locallab.spots.at(i).estop; } @@ -3134,6 +3818,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).amount = mods.locallab.spots.at(i).amount; } + if (locallab.spots.at(i).equiltm) { + toEdit.locallab.spots.at(i).equiltm = mods.locallab.spots.at(i).equiltm; + } + if (locallab.spots.at(i).CCmasktmcurve) { toEdit.locallab.spots.at(i).CCmasktmcurve = mods.locallab.spots.at(i).CCmasktmcurve; } @@ -3150,6 +3838,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).enatmMask = mods.locallab.spots.at(i).enatmMask; } + if (locallab.spots.at(i).enatmMaskaft) { + toEdit.locallab.spots.at(i).enatmMaskaft = mods.locallab.spots.at(i).enatmMaskaft; + } + if (locallab.spots.at(i).blendmasktm) { toEdit.locallab.spots.at(i).blendmasktm = mods.locallab.spots.at(i).blendmasktm; } @@ -3170,6 +3862,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).slomasktm = mods.locallab.spots.at(i).slomasktm; } + if (locallab.spots.at(i).lapmasktm) { + toEdit.locallab.spots.at(i).lapmasktm = mods.locallab.spots.at(i).lapmasktm; + } + + if (locallab.spots.at(i).Lmasktmcurve) { + toEdit.locallab.spots.at(i).Lmasktmcurve = mods.locallab.spots.at(i).Lmasktmcurve; + } + // Retinex if (locallab.spots.at(i).visireti) { toEdit.locallab.spots.at(i).visireti = mods.locallab.spots.at(i).visireti; @@ -3199,22 +3899,30 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).vart = mods.locallab.spots.at(i).vart; } + if (locallab.spots.at(i).offs) { + toEdit.locallab.spots.at(i).offs = mods.locallab.spots.at(i).offs; + } + if (locallab.spots.at(i).dehaz) { toEdit.locallab.spots.at(i).dehaz = mods.locallab.spots.at(i).dehaz; } + if (locallab.spots.at(i).depth) { + toEdit.locallab.spots.at(i).depth = mods.locallab.spots.at(i).depth; + } + if (locallab.spots.at(i).sensih) { toEdit.locallab.spots.at(i).sensih = mods.locallab.spots.at(i).sensih; } - if (locallab.spots.at(i).softradiusret) { - toEdit.locallab.spots.at(i).softradiusret = mods.locallab.spots.at(i).softradiusret; - } - if (locallab.spots.at(i).localTgaincurve) { toEdit.locallab.spots.at(i).localTgaincurve = mods.locallab.spots.at(i).localTgaincurve; } + if (locallab.spots.at(i).localTtranscurve) { + toEdit.locallab.spots.at(i).localTtranscurve = mods.locallab.spots.at(i).localTtranscurve; + } + if (locallab.spots.at(i).inversret) { toEdit.locallab.spots.at(i).inversret = mods.locallab.spots.at(i).inversret; } @@ -3223,6 +3931,18 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).equilret = mods.locallab.spots.at(i).equilret; } + if (locallab.spots.at(i).loglin) { + toEdit.locallab.spots.at(i).loglin = mods.locallab.spots.at(i).loglin; + } + + if (locallab.spots.at(i).lumonly) { + toEdit.locallab.spots.at(i).lumonly = mods.locallab.spots.at(i).lumonly; + } + + if (locallab.spots.at(i).softradiusret) { + toEdit.locallab.spots.at(i).softradiusret = mods.locallab.spots.at(i).softradiusret; + } + if (locallab.spots.at(i).CCmaskreticurve) { toEdit.locallab.spots.at(i).CCmaskreticurve = mods.locallab.spots.at(i).CCmaskreticurve; } @@ -3263,6 +3983,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).slomaskreti = mods.locallab.spots.at(i).slomaskreti; } + if (locallab.spots.at(i).lapmaskreti) { + toEdit.locallab.spots.at(i).lapmaskreti = mods.locallab.spots.at(i).lapmaskreti; + } + if (locallab.spots.at(i).scalereti) { toEdit.locallab.spots.at(i).scalereti = mods.locallab.spots.at(i).scalereti; } @@ -3279,10 +4003,18 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).limd = mods.locallab.spots.at(i).limd; } + if (locallab.spots.at(i).cliptm) { + toEdit.locallab.spots.at(i).cliptm = mods.locallab.spots.at(i).cliptm; + } + if (locallab.spots.at(i).fftwreti) { toEdit.locallab.spots.at(i).fftwreti = mods.locallab.spots.at(i).fftwreti; } + if (locallab.spots.at(i).Lmaskreticurve) { + toEdit.locallab.spots.at(i).Lmaskreticurve = mods.locallab.spots.at(i).Lmaskreticurve; + } + // Sharpening if (locallab.spots.at(i).visisharp) { toEdit.locallab.spots.at(i).visisharp = mods.locallab.spots.at(i).visisharp; @@ -3357,6 +4089,106 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).residcont = mods.locallab.spots.at(i).residcont; } + if (locallab.spots.at(i).residblur) { + toEdit.locallab.spots.at(i).residblur = mods.locallab.spots.at(i).residblur; + } + + if (locallab.spots.at(i).levelblur) { + toEdit.locallab.spots.at(i).levelblur = mods.locallab.spots.at(i).levelblur; + } + + if (locallab.spots.at(i).residchro) { + toEdit.locallab.spots.at(i).residchro = mods.locallab.spots.at(i).residchro; + } + + if (locallab.spots.at(i).residcomp) { + toEdit.locallab.spots.at(i).residcomp = mods.locallab.spots.at(i).residcomp; + } + + if (locallab.spots.at(i).sigma) { + toEdit.locallab.spots.at(i).sigma = mods.locallab.spots.at(i).sigma; + } + + if (locallab.spots.at(i).offset) { + toEdit.locallab.spots.at(i).offset = mods.locallab.spots.at(i).offset; + } + + if (locallab.spots.at(i).threswav) { + toEdit.locallab.spots.at(i).threswav = mods.locallab.spots.at(i).threswav; + } + + if (locallab.spots.at(i).chromalev) { + toEdit.locallab.spots.at(i).chromalev = mods.locallab.spots.at(i).chromalev; + } + + if (locallab.spots.at(i).chromablu) { + toEdit.locallab.spots.at(i).chromablu = mods.locallab.spots.at(i).chromablu; + } + + if (locallab.spots.at(i).fatdet) { + toEdit.locallab.spots.at(i).fatdet = mods.locallab.spots.at(i).fatdet; + } + + if (locallab.spots.at(i).fatanch) { + toEdit.locallab.spots.at(i).fatanch = mods.locallab.spots.at(i).fatanch; + } + + if (locallab.spots.at(i).fatres) { + toEdit.locallab.spots.at(i).fatres = mods.locallab.spots.at(i).fatres; + } + + if (locallab.spots.at(i).clarilres) { + toEdit.locallab.spots.at(i).clarilres = mods.locallab.spots.at(i).clarilres; + } + + if (locallab.spots.at(i).claricres) { + toEdit.locallab.spots.at(i).claricres = mods.locallab.spots.at(i).claricres; + } + + if (locallab.spots.at(i).clarisoft) { + toEdit.locallab.spots.at(i).clarisoft = mods.locallab.spots.at(i).clarisoft; + } + + if (locallab.spots.at(i).strwav) { + toEdit.locallab.spots.at(i).strwav = mods.locallab.spots.at(i).strwav; + } + + if (locallab.spots.at(i).angwav) { + toEdit.locallab.spots.at(i).angwav = mods.locallab.spots.at(i).angwav; + } + + if (locallab.spots.at(i).strengthw) { + toEdit.locallab.spots.at(i).strengthw = mods.locallab.spots.at(i).strengthw; + } + + if (locallab.spots.at(i).radiusw) { + toEdit.locallab.spots.at(i).radiusw = mods.locallab.spots.at(i).radiusw; + } + + if (locallab.spots.at(i).detailw) { + toEdit.locallab.spots.at(i).detailw = mods.locallab.spots.at(i).detailw; + } + + if (locallab.spots.at(i).gradw) { + toEdit.locallab.spots.at(i).gradw = mods.locallab.spots.at(i).gradw; + } + + if (locallab.spots.at(i).tloww) { + toEdit.locallab.spots.at(i).tloww = mods.locallab.spots.at(i).tloww; + } + + if (locallab.spots.at(i).thigw) { + toEdit.locallab.spots.at(i).thigw = mods.locallab.spots.at(i).thigw; + } + + if (locallab.spots.at(i).edgw) { + toEdit.locallab.spots.at(i).edgw = mods.locallab.spots.at(i).edgw; + } + + if (locallab.spots.at(i).basew) { + toEdit.locallab.spots.at(i).basew = mods.locallab.spots.at(i).basew; + } + if (locallab.spots.at(i).sensilc) { toEdit.locallab.spots.at(i).sensilc = mods.locallab.spots.at(i).sensilc; } @@ -3365,14 +4197,114 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).fftwlc = mods.locallab.spots.at(i).fftwlc; } + if (locallab.spots.at(i).blurlc) { + toEdit.locallab.spots.at(i).blurlc = mods.locallab.spots.at(i).blurlc; + } + + if (locallab.spots.at(i).wavblur) { + toEdit.locallab.spots.at(i).wavblur = mods.locallab.spots.at(i).wavblur; + } + + if (locallab.spots.at(i).wavedg) { + toEdit.locallab.spots.at(i).wavedg = mods.locallab.spots.at(i).wavedg; + } + + if (locallab.spots.at(i).waveshow) { + toEdit.locallab.spots.at(i).waveshow = mods.locallab.spots.at(i).waveshow; + } + + if (locallab.spots.at(i).wavcont) { + toEdit.locallab.spots.at(i).wavcont = mods.locallab.spots.at(i).wavcont; + } + + if (locallab.spots.at(i).wavcomp) { + toEdit.locallab.spots.at(i).wavcomp = mods.locallab.spots.at(i).wavcomp; + } + + if (locallab.spots.at(i).wavgradl) { + toEdit.locallab.spots.at(i).wavgradl = mods.locallab.spots.at(i).wavgradl; + } + + if (locallab.spots.at(i).wavcompre) { + toEdit.locallab.spots.at(i).wavcompre = mods.locallab.spots.at(i).wavcompre; + } + + if (locallab.spots.at(i).origlc) { + toEdit.locallab.spots.at(i).origlc = mods.locallab.spots.at(i).origlc; + } + if (locallab.spots.at(i).localcontMethod) { toEdit.locallab.spots.at(i).localcontMethod = mods.locallab.spots.at(i).localcontMethod; } + if (locallab.spots.at(i).localedgMethod) { + toEdit.locallab.spots.at(i).localedgMethod = mods.locallab.spots.at(i).localedgMethod; + } + + if (locallab.spots.at(i).localneiMethod) { + toEdit.locallab.spots.at(i).localneiMethod = mods.locallab.spots.at(i).localneiMethod; + } + if (locallab.spots.at(i).locwavcurve) { toEdit.locallab.spots.at(i).locwavcurve = mods.locallab.spots.at(i).locwavcurve; } + if (locallab.spots.at(i).csthreshold) { + toEdit.locallab.spots.at(i).csthreshold = mods.locallab.spots.at(i).csthreshold; + } + + if (locallab.spots.at(i).loclevwavcurve) { + toEdit.locallab.spots.at(i).loclevwavcurve = mods.locallab.spots.at(i).loclevwavcurve; + } + + if (locallab.spots.at(i).locconwavcurve) { + toEdit.locallab.spots.at(i).locconwavcurve = mods.locallab.spots.at(i).locconwavcurve; + } + + if (locallab.spots.at(i).loccompwavcurve) { + toEdit.locallab.spots.at(i).loccompwavcurve = mods.locallab.spots.at(i).loccompwavcurve; + } + + if (locallab.spots.at(i).loccomprewavcurve) { + toEdit.locallab.spots.at(i).loccomprewavcurve = mods.locallab.spots.at(i).loccomprewavcurve; + } + + if (locallab.spots.at(i).locedgwavcurve) { + toEdit.locallab.spots.at(i).locedgwavcurve = mods.locallab.spots.at(i).locedgwavcurve; + } + + if (locallab.spots.at(i).CCmasklccurve) { + toEdit.locallab.spots.at(i).CCmasklccurve = mods.locallab.spots.at(i).CCmasklccurve; + } + + if (locallab.spots.at(i).LLmasklccurve) { + toEdit.locallab.spots.at(i).LLmasklccurve = mods.locallab.spots.at(i).LLmasklccurve; + } + + if (locallab.spots.at(i).HHmasklccurve) { + toEdit.locallab.spots.at(i).HHmasklccurve = mods.locallab.spots.at(i).HHmasklccurve; + } + + if (locallab.spots.at(i).enalcMask) { + toEdit.locallab.spots.at(i).enalcMask = mods.locallab.spots.at(i).enalcMask; + } + + if (locallab.spots.at(i).blendmasklc) { + toEdit.locallab.spots.at(i).blendmasklc = mods.locallab.spots.at(i).blendmasklc; + } + + if (locallab.spots.at(i).radmasklc) { + toEdit.locallab.spots.at(i).radmasklc = mods.locallab.spots.at(i).radmasklc; + } + + if (locallab.spots.at(i).chromasklc) { + toEdit.locallab.spots.at(i).chromasklc = mods.locallab.spots.at(i).chromasklc; + } + + if (locallab.spots.at(i).Lmasklccurve) { + toEdit.locallab.spots.at(i).Lmasklccurve = mods.locallab.spots.at(i).Lmasklccurve; + } + // Contrast by detail levels if (locallab.spots.at(i).visicbdl) { toEdit.locallab.spots.at(i).visicbdl = mods.locallab.spots.at(i).visicbdl; @@ -3412,6 +4344,26 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).blurcbdl = mods.locallab.spots.at(i).blurcbdl; } + if (locallab.spots.at(i).softradiuscb) { + toEdit.locallab.spots.at(i).softradiuscb = mods.locallab.spots.at(i).softradiuscb; + } + + if (locallab.spots.at(i).enacbMask) { + toEdit.locallab.spots.at(i).enacbMask = mods.locallab.spots.at(i).enacbMask; + } + + if (locallab.spots.at(i).CCmaskcbcurve) { + toEdit.locallab.spots.at(i).CCmaskcbcurve = mods.locallab.spots.at(i).CCmaskcbcurve; + } + + if (locallab.spots.at(i).LLmaskcbcurve) { + toEdit.locallab.spots.at(i).LLmaskcbcurve = mods.locallab.spots.at(i).LLmaskcbcurve; + } + + if (locallab.spots.at(i).HHmaskcbcurve) { + toEdit.locallab.spots.at(i).HHmaskcbcurve = mods.locallab.spots.at(i).HHmaskcbcurve; + } + if (locallab.spots.at(i).blendmaskcb) { toEdit.locallab.spots.at(i).blendmaskcb = mods.locallab.spots.at(i).blendmaskcb; } @@ -3432,24 +4384,12 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).slomaskcb = mods.locallab.spots.at(i).slomaskcb; } - if (locallab.spots.at(i).enacbMask) { - toEdit.locallab.spots.at(i).enacbMask = mods.locallab.spots.at(i).enacbMask; + if (locallab.spots.at(i).lapmaskcb) { + toEdit.locallab.spots.at(i).lapmaskcb = mods.locallab.spots.at(i).lapmaskcb; } - if (locallab.spots.at(i).CCmaskcbcurve) { - toEdit.locallab.spots.at(i).CCmaskcbcurve = mods.locallab.spots.at(i).CCmaskcbcurve; - } - - if (locallab.spots.at(i).LLmaskcbcurve) { - toEdit.locallab.spots.at(i).LLmaskcbcurve = mods.locallab.spots.at(i).LLmaskcbcurve; - } - - if (locallab.spots.at(i).HHmaskcbcurve) { - toEdit.locallab.spots.at(i).HHmaskcbcurve = mods.locallab.spots.at(i).HHmaskcbcurve; - } - - if (locallab.spots.at(i).softradiuscb) { - toEdit.locallab.spots.at(i).softradiuscb = mods.locallab.spots.at(i).softradiuscb; + if (locallab.spots.at(i).Lmaskcbcurve) { + toEdit.locallab.spots.at(i).Lmaskcbcurve = mods.locallab.spots.at(i).Lmaskcbcurve; } // Denoise @@ -3508,6 +4448,71 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng if (locallab.spots.at(i).sensiden) { toEdit.locallab.spots.at(i).sensiden = mods.locallab.spots.at(i).sensiden; } + + if (locallab.spots.at(i).detailthr) { + toEdit.locallab.spots.at(i).detailthr = mods.locallab.spots.at(i).detailthr; + } + + if (locallab.spots.at(i).locwavcurveden) { + toEdit.locallab.spots.at(i).locwavcurveden = mods.locallab.spots.at(i).locwavcurveden; + } + + // Log encoding + if (locallab.spots.at(i).visilog) { + toEdit.locallab.spots.at(i).visilog = mods.locallab.spots.at(i).visilog; + } + + if (locallab.spots.at(i).explog) { + toEdit.locallab.spots.at(i).explog = mods.locallab.spots.at(i).explog; + } + + if (locallab.spots.at(i).autocompute) { + toEdit.locallab.spots.at(i).autocompute = mods.locallab.spots.at(i).autocompute; + } + + if (locallab.spots.at(i).sourceGray) { + toEdit.locallab.spots.at(i).sourceGray = mods.locallab.spots.at(i).sourceGray; + } + + if (locallab.spots.at(i).targetGray) { + toEdit.locallab.spots.at(i).targetGray = mods.locallab.spots.at(i).targetGray; + } + + if (locallab.spots.at(i).Autogray) { + toEdit.locallab.spots.at(i).Autogray = mods.locallab.spots.at(i).Autogray; + } + + if (locallab.spots.at(i).fullimage) { + toEdit.locallab.spots.at(i).fullimage = mods.locallab.spots.at(i).fullimage; + } + + if (locallab.spots.at(i).blackEv) { + toEdit.locallab.spots.at(i).blackEv = mods.locallab.spots.at(i).blackEv; + } + + if (locallab.spots.at(i).whiteEv) { + toEdit.locallab.spots.at(i).whiteEv = mods.locallab.spots.at(i).whiteEv; + } + + if (locallab.spots.at(i).detail) { + toEdit.locallab.spots.at(i).detail = mods.locallab.spots.at(i).detail; + } + + if (locallab.spots.at(i).sensilog) { + toEdit.locallab.spots.at(i).sensilog = mods.locallab.spots.at(i).sensilog; + } + + if (locallab.spots.at(i).baselog) { + toEdit.locallab.spots.at(i).baselog = mods.locallab.spots.at(i).baselog; + } + + if (locallab.spots.at(i).strlog) { + toEdit.locallab.spots.at(i).strlog = mods.locallab.spots.at(i).strlog; + } + + if (locallab.spots.at(i).anglog) { + toEdit.locallab.spots.at(i).anglog = mods.locallab.spots.at(i).anglog; + } } if (pcvignette.enabled) { @@ -4401,6 +5406,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.dehaze.showDepthMap = mods.dehaze.showDepthMap; } + if (dehaze.luminance) { + toEdit.dehaze.luminance = mods.dehaze.luminance; + } + if (metadata.mode) { toEdit.metadata.mode = mods.metadata.mode; } @@ -4476,6 +5485,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : isvisible(v), shape(v), spotMethod(v), + wavMethod(v), sensiexclu(v), structexclu(v), struc(v), @@ -4488,13 +5498,24 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : centerY(v), circrad(v), qualityMethod(v), + complexMethod(v), transit(v), + feather(v), thresh(v), iter(v), balan(v), + balanh(v), + colorde(v), transitweak(v), transitgrad(v), avoid(v), + recurs(v), + laplac(v), + deltae(v), + shortc(v), + savrest(v), + scopemask(v), + lumask(v), // Color & Light visicolor(v), expcolor(v), @@ -4506,27 +5527,57 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : labgridBLow(v), labgridAHigh(v), labgridBHigh(v), + labgridALowmerg(v), + labgridBLowmerg(v), + labgridAHighmerg(v), + labgridBHighmerg(v), strengthgrid(v), sensi(v), structcol(v), + strcol(v), + strcolab(v), + strcolh(v), + angcol(v), blurcolde(v), + blurcol(v), + contcol(v), blendmaskcol(v), radmaskcol(v), chromaskcol(v), gammaskcol(v), slomaskcol(v), + shadmaskcol(v), + strumaskcol(v), + lapmaskcol(v), qualitycurveMethod(v), gridMethod(v), + merMethod(v), + toneMethod(v), + mergecolMethod(v), llcurve(v), + lccurve(v), cccurve(v), + clcurve(v), + rgbcurve(v), LHcurve(v), HHcurve(v), invers(v), + special(v), + toolcol(v), enaColorMask(v), + fftColorMask(v), CCmaskcurve(v), LLmaskcurve(v), HHmaskcurve(v), + HHhmaskcurve(v), softradiuscol(v), + opacol(v), + mercol(v), + merlucol(v), + conthrcol(v), + Lmaskcurve(v), + LLmaskcolcurvewav(v), + csthresholdcol(v), // Exposure visiexpose(v), expexpose(v), @@ -4537,13 +5588,15 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : shadex(v), shcompr(v), expchroma(v), - warm(v), sensiex(v), structexp(v), blurexpde(v), + strexp(v), + angexp(v), excurve(v), inversex(v), enaExpMask(v), + enaExpMaskaft(v), CCmaskexpcurve(v), LLmaskexpcurve(v), HHmaskexpcurve(v), @@ -4552,14 +5605,26 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : chromaskexp(v), gammaskexp(v), slomaskexp(v), + lapmaskexp(v), + strmaskexp(v), + angmaskexp(v), softradiusexp(v), + Lmaskexpcurve(v), expMethod(v), + exnoiseMethod(v), laplacexp(v), balanexp(v), linear(v), + gamm(v), + fatamount(v), + fatdetail(v), + fatanchor(v), + fatlevel(v), // Shadow highlight visishadhigh(v), expshadhigh(v), + shMethod(v), + multsh{v, v, v, v, v, v}, highlights(v), h_tonalwidth(v), shadows(v), @@ -4573,21 +5638,46 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : blendmaskSH(v), radmaskSH(v), blurSHde(v), + strSH(v), + angSH(v), inverssh(v), chromaskSH(v), gammaskSH(v), slomaskSH(v), + lapmaskSH(v), + detailSH(v), + LmaskSHcurve(v), + fatamountSH(v), + fatanchorSH(v), + gamSH(v), + sloSH(v), // Vibrance visivibrance(v), expvibrance(v), saturated(v), pastels(v), + warm(v), psthreshold(v), protectskins(v), avoidcolorshift(v), pastsattog(v), sensiv(v), skintonescurve(v), + CCmaskvibcurve(v), + LLmaskvibcurve(v), + HHmaskvibcurve(v), + enavibMask(v), + blendmaskvib(v), + radmaskvib(v), + chromaskvib(v), + gammaskvib(v), + slomaskvib(v), + lapmaskvib(v), + strvib(v), + strvibab(v), + strvibh(v), + angvib(v), + Lmaskvibcurve(v), // Soft Light visisoft(v), expsoft(v), @@ -4601,8 +5691,35 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : radius(v), strength(v), sensibn(v), + itera(v), + guidbl(v), + strbl(v), + isogr(v), + strengr(v), + scalegr(v), + epsbl(v), + blMethod(v), + chroMethod(v), blurMethod(v), + medMethod(v), activlum(v), + CCmaskblcurve(v), + LLmaskblcurve(v), + HHmaskblcurve(v), + enablMask(v), + fftwbl(v), + toolbl(v), + blendmaskbl(v), + radmaskbl(v), + chromaskbl(v), + gammaskbl(v), + slomaskbl(v), + lapmaskbl(v), + shadmaskbl(v), + strumaskbl(v), + Lmaskblcurve(v), + LLmaskblcurvewav(v), + csthresholdblur(v), // Tone Mapping visitonemap(v), exptonemap(v), @@ -4620,11 +5737,14 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : LLmasktmcurve(v), HHmasktmcurve(v), enatmMask(v), + enatmMaskaft(v), blendmasktm(v), radmasktm(v), chromasktm(v), gammasktm(v), slomasktm(v), + lapmasktm(v), + Lmasktmcurve(v), // Retinex visireti(v), expreti(v), @@ -4633,11 +5753,16 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : chrrt(v), neigh(v), vart(v), + offs(v), dehaz(v), + depth(v), sensih(v), localTgaincurve(v), + localTtranscurve(v), inversret(v), equilret(v), + loglin(v), + lumonly(v), softradiusret(v), CCmaskreticurve(v), LLmaskreticurve(v), @@ -4649,11 +5774,14 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : chromaskreti(v), gammaskreti(v), slomaskreti(v), + lapmaskreti(v), scalereti(v), darkness(v), lightnessreti(v), limd(v), + cliptm(v), fftwreti(v), + Lmaskreticurve(v), // Sharpening visisharp(v), expsharp(v), @@ -4674,9 +5802,60 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : lclightness(v), levelwav(v), residcont(v), + residblur(v), + levelblur(v), + residchro(v), + residcomp(v), + sigma(v), + offset(v), + threswav(v), + chromalev(v), + chromablu(v), + fatdet(v), + fatanch(v), + fatres(v), + clarilres(v), + claricres(v), + clarisoft(v), + strwav(v), + angwav(v), + strengthw(v), + radiusw(v), + detailw(v), + gradw(v), + tloww(v), + thigw(v), + edgw(v), + basew(v), sensilc(v), fftwlc(v), + blurlc(v), + wavblur(v), + wavedg(v), + waveshow(v), + wavcont(v), + wavcomp(v), + wavgradl(v), + wavcompre(v), + origlc(v), localcontMethod(v), + localedgMethod(v), + localneiMethod(v), + locwavcurve(v), + csthreshold(v), + loclevwavcurve(v), + locconwavcurve(v), + loccompwavcurve(v), + loccomprewavcurve(v), + locedgwavcurve(v), + CCmasklccurve(v), + LLmasklccurve(v), + HHmasklccurve(v), + enalcMask(v), + blendmasklc(v), + radmasklc(v), + chromasklc(v), + Lmasklccurve(v), // Contrast by detail levels visicbdl(v), expcbdl(v), @@ -4687,16 +5866,18 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : clarityml(v), contresid(v), blurcbdl(v), - blendmaskcb(v), - radmaskcb(v), - chromaskcb(v), - gammaskcb(v), - slomaskcb(v), softradiuscb(v), enacbMask(v), CCmaskcbcurve(v), LLmaskcbcurve(v), HHmaskcbcurve(v), + blendmaskcb(v), + radmaskcb(v), + chromaskcb(v), + gammaskcb(v), + slomaskcb(v), + lapmaskcb(v), + Lmaskcbcurve(v), // Denoise visidenoi(v), expdenoi(v), @@ -4711,7 +5892,24 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : noisechrodetail(v), adjblur(v), bilateral(v), - sensiden(v) + sensiden(v), + detailthr(v), + locwavcurveden(v), + // Log encoding + visilog(v), + explog(v), + autocompute(v), + sourceGray(v), + targetGray(v), + Autogray(v), + fullimage(v), + blackEv(v), + whiteEv(v), + detail(v), + sensilog(v), + baselog(v), + strlog(v), + anglog(v) { } @@ -4721,6 +5919,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) isvisible = v; shape = v; spotMethod = v; + wavMethod = v; sensiexclu = v; structexclu = v; struc = v; @@ -4733,13 +5932,24 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) centerY = v; circrad = v; qualityMethod = v; + complexMethod = v; transit = v; + feather = v; thresh = v; iter = v; balan = v; + balanh = v; + colorde = v; transitweak = v; transitgrad = v; avoid = v; + recurs = v; + laplac = v; + deltae = v; + shortc = v; + savrest = v; + scopemask = v; + lumask = v; // Color & Light visicolor = v; expcolor = v; @@ -4751,27 +5961,57 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) labgridBLow = v; labgridAHigh = v; labgridBHigh = v; + labgridALowmerg = v; + labgridBLowmerg = v; + labgridAHighmerg = v; + labgridBHighmerg = v; strengthgrid = v; sensi = v; structcol = v; + strcol = v; + strcolab = v; + strcolh = v; + angcol = v; blurcolde = v; + blurcol = v; + contcol = v; blendmaskcol = v; radmaskcol = v; chromaskcol = v; gammaskcol = v; slomaskcol = v; + shadmaskcol = v; + strumaskcol = v; + lapmaskcol = v; qualitycurveMethod = v; gridMethod = v; + merMethod = v; + toneMethod = v; + mergecolMethod = v; llcurve = v; + lccurve = v; cccurve = v; + clcurve = v; + rgbcurve = v; LHcurve = v; HHcurve = v; invers = v; + special = v; + toolcol = v; enaColorMask = v; + fftColorMask = v; CCmaskcurve = v; LLmaskcurve = v; HHmaskcurve = v; + HHhmaskcurve = v; softradiuscol = v; + opacol = v; + mercol = v; + merlucol = v; + conthrcol = v; + Lmaskcurve = v; + LLmaskcolcurvewav = v; + csthresholdcol = v; // Exposure visiexpose = v; expexpose = v; @@ -4782,13 +6022,15 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) shadex = v; shcompr = v; expchroma = v; - warm = v; sensiex = v; structexp = v; blurexpde = v; + strexp = v; + angexp = v; excurve = v; inversex = v; enaExpMask = v; + enaExpMaskaft = v; CCmaskexpcurve = v; LLmaskexpcurve = v; HHmaskexpcurve = v; @@ -4797,14 +6039,30 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) chromaskexp = v; gammaskexp = v; slomaskexp = v; + lapmaskexp = v; + strmaskexp = v; + angmaskexp = v; softradiusexp = v; + Lmaskexpcurve = v; expMethod = v; + exnoiseMethod = v; laplacexp = v; balanexp = v; linear = v; + gamm = v; + fatamount = v; + fatdetail = v; + fatanchor = v; + fatlevel = v; // Shadow highlight visishadhigh = v; expshadhigh = v; + shMethod = v; + + for (int i = 0; i < 5; i++) { + multsh[i] = v; + } + highlights = v; h_tonalwidth = v; shadows = v; @@ -4818,21 +6076,46 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) blendmaskSH = v; radmaskSH = v; blurSHde = v; + strSH = v; + angSH = v; inverssh = v; chromaskSH = v; gammaskSH = v; slomaskSH = v; + lapmaskSH = v; + detailSH = v; + LmaskSHcurve = v; + fatamountSH = v; + fatanchorSH = v; + gamSH = v; + sloSH = v; // Vibrance visivibrance = v; expvibrance = v; saturated = v; pastels = v; + warm = v; psthreshold = v; protectskins = v; avoidcolorshift = v; pastsattog = v; sensiv = v; skintonescurve = v; + CCmaskvibcurve = v; + LLmaskvibcurve = v; + HHmaskvibcurve = v; + enavibMask = v; + blendmaskvib = v; + radmaskvib = v; + chromaskvib = v; + gammaskvib = v; + slomaskvib = v; + lapmaskvib = v; + strvib = v; + strvibab = v; + strvibh = v; + angvib = v; + Lmaskvibcurve = v; // Soft Light visisoft = v; expsoft = v; @@ -4846,8 +6129,35 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) radius = v; strength = v; sensibn = v; + itera = v; + guidbl = v; + strbl = v; + isogr = v; + strengr = v; + scalegr = v; + epsbl = v; + blMethod = v; + chroMethod = v; blurMethod = v; + medMethod = v; activlum = v; + CCmaskblcurve = v; + LLmaskblcurve = v; + HHmaskblcurve = v; + enablMask = v; + fftwbl = v; + toolbl = v; + blendmaskbl = v; + radmaskbl = v; + chromaskbl = v; + gammaskbl = v; + slomaskbl = v; + lapmaskbl = v; + shadmaskbl = v; + strumaskbl = v; + Lmaskblcurve = v; + LLmaskblcurvewav = v; + csthresholdblur = v; // Tone Mapping visitonemap = v; exptonemap = v; @@ -4865,11 +6175,14 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) LLmasktmcurve = v; HHmasktmcurve = v; enatmMask = v; + enatmMaskaft = v; blendmasktm = v; radmasktm = v; chromasktm = v; gammasktm = v; slomasktm = v; + lapmasktm = v; + Lmasktmcurve = v; // Retinex visireti = v; expreti = v; @@ -4878,11 +6191,16 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) chrrt = v; neigh = v; vart = v; + offs = v; dehaz = v; + depth = v; sensih = v; localTgaincurve = v; + localTtranscurve = v; inversret = v; equilret = v; + loglin = v; + lumonly = v; softradiusret = v; CCmaskreticurve = v; LLmaskreticurve = v; @@ -4894,11 +6212,14 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) chromaskreti = v; gammaskreti = v; slomaskreti = v; + lapmaskreti = v; scalereti = v; darkness = v; lightnessreti = v; limd = v; + cliptm = v; fftwreti = v; + Lmaskreticurve = v; // Sharpening visisharp = v; expsharp = v; @@ -4919,11 +6240,60 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) lclightness = v; levelwav = v; residcont = v; + residblur = v; + levelblur = v; + residchro = v; + residcomp = v; + sigma = v; + offset = v; + threswav = v; + chromalev = v; + chromablu = v; + fatdet = v; + fatanch = v; + fatres = v; + clarilres = v; + claricres = v; + clarisoft = v; + strwav = v; + angwav = v; + strengthw = v; + radiusw = v; + detailw = v; + gradw = v; + tloww = v; + thigw = v; + edgw = v; + basew = v; sensilc = v; fftwlc = v; + blurlc = v; + wavblur = v; + wavedg = v; + waveshow = v; + wavcont = v; + wavcomp = v; + wavgradl = v; + wavcompre = v; + origlc = v; localcontMethod = v; + localedgMethod = v; + localneiMethod = v; locwavcurve = v; - locwavcurve = v; + csthreshold = v; + loclevwavcurve = v; + locconwavcurve = v; + loccompwavcurve = v; + loccomprewavcurve = v; + locedgwavcurve = v; + CCmasklccurve = v; + LLmasklccurve = v; + HHmasklccurve = v; + enalcMask = v; + blendmasklc = v; + radmasklc = v; + chromasklc = v; + Lmasklccurve = v; // Contrast by detail levels visicbdl = v; expcbdl = v; @@ -4937,17 +6307,19 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) sensicb = v; clarityml = v; contresid = v; + softradiuscb = v; + enacbMask = v; + CCmaskcbcurve = v; + LLmaskcbcurve = v; + HHmaskcbcurve = v; blurcbdl = v; blendmaskcb = v; radmaskcb = v; chromaskcb = v; gammaskcb = v; slomaskcb = v; - softradiuscb = v; - enacbMask = v; - CCmaskcbcurve = v; - LLmaskcbcurve = v; - HHmaskcbcurve = v; + lapmaskcb = v; + Lmaskcbcurve = v; // Denoise visidenoi = v; expdenoi = v; @@ -4963,4 +6335,26 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) adjblur = v; bilateral = v; sensiden = v; + detailthr = v; + locwavcurveden = v; + // Log encoding + visilog = v; + explog = v; + autocompute = v; + sourceGray = v; + targetGray = v; + Autogray = v; + fullimage = v; + blackEv = v; + whiteEv = v; + detail = v; + sensilog = v; + baselog = v; + strlog = v; + anglog = v; +} + +bool CaptureSharpeningParamsEdited::isUnchanged() const +{ + return enabled && contrast && autoContrast && autoRadius && deconvradius && deconvradiusOffset && deconviter && deconvitercheck; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 0ec8efce6..41b16626e 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -14,13 +14,25 @@ * GNU General Public License for more details. * * 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 -#include "../rtengine/rtengine.h" +namespace rtengine +{ + +namespace procparams +{ + +class ProcParams; + +class PartialProfile; + +} + +} struct GeneralParamsEdited { bool rank; @@ -157,6 +169,10 @@ struct ColorToningEdited { bool labgridBLow; bool labgridAHigh; bool labgridBHigh; + bool labgridALowmerg; + bool labgridBLowmerg; + bool labgridAHighmerg; + bool labgridBHighmerg; bool labregions; bool labregionsShowMask; }; @@ -179,7 +195,9 @@ struct SharpenMicroParamsEdited { struct SharpeningParamsEdited { bool enabled; bool contrast; + bool autoContrast; bool blurradius; + bool gamma; bool radius; bool amount; bool threshold; @@ -196,6 +214,18 @@ struct SharpeningParamsEdited { bool deconvdamping; }; +struct CaptureSharpeningParamsEdited { + bool enabled; + bool contrast; + bool autoContrast; + bool autoRadius; + bool deconvradius; + bool deconvradiusOffset; + bool deconviter; + bool deconvitercheck; + bool isUnchanged() const; +}; + struct VibranceParamsEdited { bool enabled; bool pastels; @@ -339,6 +369,7 @@ struct CoarseTransformParamsEdited { }; struct CommonTransformParamsEdited { + bool method; bool autofill; }; @@ -358,6 +389,7 @@ public: bool isvisible; bool shape; bool spotMethod; + bool wavMethod; bool sensiexclu; bool structexclu; bool struc; @@ -370,13 +402,24 @@ public: bool centerY; bool circrad; bool qualityMethod; + bool complexMethod; bool transit; + bool feather; bool thresh; bool iter; bool balan; + bool balanh; + bool colorde; bool transitweak; bool transitgrad; bool avoid; + bool recurs; + bool laplac; + bool deltae; + bool shortc; + bool savrest; + bool scopemask; + bool lumask; // Color & Light bool visicolor; bool expcolor; @@ -388,27 +431,57 @@ public: bool labgridBLow; bool labgridAHigh; bool labgridBHigh; + bool labgridALowmerg; + bool labgridBLowmerg; + bool labgridAHighmerg; + bool labgridBHighmerg; bool strengthgrid; bool sensi; bool structcol; + bool strcol; + bool strcolab; + bool strcolh; + bool angcol; bool blurcolde; + bool blurcol; + bool contcol; bool blendmaskcol; bool radmaskcol; bool chromaskcol; bool gammaskcol; bool slomaskcol; + bool shadmaskcol; + bool strumaskcol; + bool lapmaskcol; bool qualitycurveMethod; bool gridMethod; + bool merMethod; + bool toneMethod; + bool mergecolMethod; bool llcurve; + bool lccurve; bool cccurve; + bool clcurve; + bool rgbcurve; bool LHcurve; bool HHcurve; bool invers; + bool special; + bool toolcol; bool enaColorMask; + bool fftColorMask; bool CCmaskcurve; bool LLmaskcurve; bool HHmaskcurve; + bool HHhmaskcurve; bool softradiuscol; + bool opacol; + bool mercol; + bool merlucol; + bool conthrcol; + bool Lmaskcurve; + bool LLmaskcolcurvewav; + bool csthresholdcol; // Exposure bool visiexpose; bool expexpose; @@ -419,13 +492,15 @@ public: bool shadex; bool shcompr; bool expchroma; - bool warm; bool sensiex; bool structexp; bool blurexpde; + bool strexp; + bool angexp; bool excurve; bool inversex; bool enaExpMask; + bool enaExpMaskaft; bool CCmaskexpcurve; bool LLmaskexpcurve; bool HHmaskexpcurve; @@ -434,14 +509,26 @@ public: bool chromaskexp; bool gammaskexp; bool slomaskexp; + bool lapmaskexp; + bool strmaskexp; + bool angmaskexp; bool softradiusexp; + bool Lmaskexpcurve; bool expMethod; + bool exnoiseMethod; bool laplacexp; bool balanexp; bool linear; + bool gamm; + bool fatamount; + bool fatdetail; + bool fatanchor; + bool fatlevel; // Shadow highlight bool visishadhigh; bool expshadhigh; + bool shMethod; + bool multsh[6]; bool highlights; bool h_tonalwidth; bool shadows; @@ -455,21 +542,46 @@ public: bool blendmaskSH; bool radmaskSH; bool blurSHde; + bool strSH; + bool angSH; bool inverssh; bool chromaskSH; bool gammaskSH; bool slomaskSH; + bool lapmaskSH; + bool detailSH; + bool LmaskSHcurve; + bool fatamountSH; + bool fatanchorSH; + bool gamSH; + bool sloSH; // Vibrance bool visivibrance; bool expvibrance; bool saturated; bool pastels; + bool warm; bool psthreshold; bool protectskins; bool avoidcolorshift; bool pastsattog; bool sensiv; bool skintonescurve; + bool CCmaskvibcurve; + bool LLmaskvibcurve; + bool HHmaskvibcurve; + bool enavibMask; + bool blendmaskvib; + bool radmaskvib; + bool chromaskvib; + bool gammaskvib; + bool slomaskvib; + bool lapmaskvib; + bool strvib; + bool strvibab; + bool strvibh; + bool angvib; + bool Lmaskvibcurve; // Soft Light bool visisoft; bool expsoft; @@ -483,8 +595,35 @@ public: bool radius; bool strength; bool sensibn; + bool itera; + bool guidbl; + bool strbl; + bool isogr; + bool strengr; + bool scalegr; + bool epsbl; + bool blMethod; + bool chroMethod; bool blurMethod; + bool medMethod; bool activlum; + bool CCmaskblcurve; + bool LLmaskblcurve; + bool HHmaskblcurve; + bool enablMask; + bool fftwbl; + bool toolbl; + bool blendmaskbl; + bool radmaskbl; + bool chromaskbl; + bool gammaskbl; + bool slomaskbl; + bool lapmaskbl; + bool shadmaskbl; + bool strumaskbl; + bool Lmaskblcurve; + bool LLmaskblcurvewav; + bool csthresholdblur; // Tone Mapping bool visitonemap; bool exptonemap; @@ -502,11 +641,14 @@ public: bool LLmasktmcurve; bool HHmasktmcurve; bool enatmMask; + bool enatmMaskaft; bool blendmasktm; bool radmasktm; bool chromasktm; bool gammasktm; bool slomasktm; + bool lapmasktm; + bool Lmasktmcurve; // Retinex bool visireti; bool expreti; @@ -515,11 +657,16 @@ public: bool chrrt; bool neigh; bool vart; + bool offs; bool dehaz; + bool depth; bool sensih; bool localTgaincurve; + bool localTtranscurve; bool inversret; bool equilret; + bool loglin; + bool lumonly; bool softradiusret; bool CCmaskreticurve; bool LLmaskreticurve; @@ -531,11 +678,14 @@ public: bool chromaskreti; bool gammaskreti; bool slomaskreti; + bool lapmaskreti; bool scalereti; bool darkness; bool lightnessreti; bool limd; + bool cliptm; bool fftwreti; + bool Lmaskreticurve; // Sharpening bool visisharp; bool expsharp; @@ -556,10 +706,60 @@ public: bool lclightness; bool levelwav; bool residcont; + bool residblur; + bool levelblur; + bool residchro; + bool residcomp; + bool sigma; + bool offset; + bool threswav; + bool chromalev; + bool chromablu; + bool fatdet; + bool fatanch; + bool fatres; + bool clarilres; + bool claricres; + bool clarisoft; + bool strwav; + bool angwav; + bool strengthw; + bool radiusw; + bool detailw; + bool gradw; + bool tloww; + bool thigw; + bool edgw; + bool basew; bool sensilc; bool fftwlc; + bool blurlc; + bool wavblur; + bool wavedg; + bool waveshow; + bool wavcont; + bool wavcomp; + bool wavgradl; + bool wavcompre; + bool origlc; bool localcontMethod; + bool localedgMethod; + bool localneiMethod; bool locwavcurve; + bool csthreshold; + bool loclevwavcurve; + bool locconwavcurve; + bool loccompwavcurve; + bool loccomprewavcurve; + bool locedgwavcurve; + bool CCmasklccurve; + bool LLmasklccurve; + bool HHmasklccurve; + bool enalcMask; + bool blendmasklc; + bool radmasklc; + bool chromasklc; + bool Lmasklccurve; // Contrast by detail levels bool visicbdl; bool expcbdl; @@ -570,16 +770,18 @@ public: bool clarityml; bool contresid; bool blurcbdl; - bool blendmaskcb; - bool radmaskcb; - bool chromaskcb; - bool gammaskcb; - bool slomaskcb; bool softradiuscb; bool enacbMask; bool CCmaskcbcurve; bool LLmaskcbcurve; bool HHmaskcbcurve; + bool blendmaskcb; + bool radmaskcb; + bool chromaskcb; + bool gammaskcb; + bool slomaskcb; + bool lapmaskcb; + bool Lmaskcbcurve; // Denoise bool visidenoi; bool expdenoi; @@ -595,6 +797,23 @@ public: bool adjblur; bool bilateral; bool sensiden; + bool detailthr; + bool locwavcurveden; + // Log encoding + bool visilog; + bool explog; + bool autocompute; + bool sourceGray; + bool targetGray; + bool Autogray; + bool fullimage; + bool blackEv; + bool whiteEv; + bool detail; + bool sensilog; + bool baselog; + bool strlog; + bool anglog; LocallabSpotEdited(bool v); @@ -839,6 +1058,7 @@ struct DehazeParamsEdited { bool strength; bool showDepthMap; bool depth; + bool luminance; }; struct RAWParamsEdited { @@ -940,6 +1160,7 @@ struct ParamsEdited { ColorToningEdited colorToning; RetinexParamsEdited retinex; SharpeningParamsEdited sharpening; + CaptureSharpeningParamsEdited pdsharpening; SharpeningParamsEdited prsharpening; SharpenEdgeParamsEdited sharpenEdge; SharpenMicroParamsEdited sharpenMicro; diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index d692d121a..d264b5187 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" @@ -304,8 +304,10 @@ 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")) ); + //--- + captureSharpening = Gtk::manage (new Gtk::CheckButton (M("TP_PDSHARPENING_LABEL")) ); Gtk::VBox* vboxes[9]; Gtk::HSeparator* hseps[9]; @@ -421,7 +423,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren vboxes[8]->pack_start (*ff_AutoSelect, Gtk::PACK_SHRINK, 2); vboxes[8]->pack_start (*ff_BlurType, Gtk::PACK_SHRINK, 2); vboxes[8]->pack_start (*ff_BlurRadius, Gtk::PACK_SHRINK, 2); - vboxes[8]->pack_start (*ff_ClipControl, Gtk::PACK_SHRINK, 2); + vboxes[8]->pack_start (*captureSharpening, Gtk::PACK_SHRINK, 2); vboxes[8]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); vboxes[8]->pack_start (*raw_ca_autocorrect, Gtk::PACK_SHRINK, 2); vboxes[8]->pack_start (*raw_caredblue, Gtk::PACK_SHRINK, 2); @@ -578,6 +580,8 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren 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)); + //--- + captureSharpeningConn = captureSharpening->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); @@ -653,6 +657,7 @@ void PartialPasteDlg::rawToggled () ConnectionBlocker raw_caredblueBlocker(raw_caredblueConn); ConnectionBlocker raw_ca_avoid_colourshiftBlocker(raw_ca_avoid_colourshiftconn); ConnectionBlocker filmNegativeBlocker(filmNegativeConn); + ConnectionBlocker captureSharpeningBlocker(captureSharpeningConn); raw->set_inconsistent (false); @@ -682,6 +687,7 @@ void PartialPasteDlg::rawToggled () raw_caredblue->set_active (raw->get_active ()); raw_ca_avoid_colourshift->set_active (raw->get_active ()); filmNegative->set_active (raw->get_active()); + captureSharpening->set_active (raw->get_active()); } void PartialPasteDlg::basicToggled () @@ -1173,6 +1179,17 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param filterPE.filmNegative.blueRatio = falsePE.filmNegative.blueRatio; } + if (!captureSharpening->get_active ()) { + filterPE.pdsharpening.enabled = falsePE.pdsharpening.enabled; + filterPE.pdsharpening.contrast = falsePE.pdsharpening.contrast; + filterPE.pdsharpening.autoContrast = falsePE.pdsharpening.autoContrast; + filterPE.pdsharpening.autoRadius = falsePE.pdsharpening.autoRadius; + filterPE.pdsharpening.deconvradius = falsePE.pdsharpening.deconvradius; + filterPE.pdsharpening.deconvradiusOffset = falsePE.pdsharpening.deconvradiusOffset; + filterPE.pdsharpening.deconviter = falsePE.pdsharpening.deconviter; + filterPE.pdsharpening.deconvitercheck = falsePE.pdsharpening.deconvitercheck; + } + // Locallab shall be kept in last position if (!locallab->get_active () && !locallab->get_inconsistent()) { filterPE.locallab = falsePE.locallab; @@ -1218,7 +1235,6 @@ void PartialPasteDlg::updateSpotWidget(const rtengine::procparams::ProcParams* p } else { spots->set_visible(false); // Hide widget if there is no locallab spot } - } void PartialPasteDlg::partialSpotUpdated(const UpdateStatus status) @@ -1236,4 +1252,3 @@ void PartialPasteDlg::partialSpotUpdated(const UpdateStatus status) locallab->set_inconsistent(true); } } - diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h index dc7f64c53..f675a7dca 100644 --- a/rtgui/partialpastedlg.h +++ b/rtgui/partialpastedlg.h @@ -14,13 +14,23 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include -#include "../rtengine/rtengine.h" + +namespace rtengine +{ +namespace procparams +{ + +class ProcParams; + + +} + +} struct ParamsEdited; @@ -96,7 +106,7 @@ private: }; /* ==== PartialPasteDlg ==== */ -class PartialPasteDlg: +class PartialPasteDlg final: public Gtk::Dialog, public PartialSpotWidgetListener { @@ -208,6 +218,7 @@ public: Gtk::CheckButton* ff_ClipControl; Gtk::CheckButton* filmNegative; + Gtk::CheckButton* captureSharpening; sigc::connection everythingConn, basicConn, detailConn, colorConn, lensConn, compositionConn, metaConn, rawConn, advancedConn; sigc::connection locallabConn; @@ -220,6 +231,7 @@ public: 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; + sigc::connection captureSharpeningConn; public: PartialPasteDlg (const Glib::ustring &title, Gtk::Window* parent); @@ -240,6 +252,3 @@ public: void updateSpotWidget(const rtengine::procparams::ProcParams* pp); void partialSpotUpdated(const UpdateStatus status); }; - -#endif - diff --git a/rtgui/pathutils.cc b/rtgui/pathutils.cc index 21c452d4c..fc47a0e25 100644 --- a/rtgui/pathutils.cc +++ b/rtgui/pathutils.cc @@ -13,9 +13,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 . */ +#include + #include "pathutils.h" diff --git a/rtgui/pathutils.h b/rtgui/pathutils.h index ce58103b9..482dfb82f 100644 --- a/rtgui/pathutils.h +++ b/rtgui/pathutils.h @@ -14,21 +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 __PATH_UTILS_ -#define __PATH_UTILS_ - -#include -#include -#include "../rtengine/rtengine.h" -#include "../rtengine/coord.h" -#include "rtimage.h" -#include -#include +#pragma once +#include // Removed from guiutils because used by rawtherapee-cli Glib::ustring removeExtension (const Glib::ustring& filename); Glib::ustring getExtension (const Glib::ustring& filename); - -#endif diff --git a/rtgui/pcvignette.h b/rtgui/pcvignette.h index ce41ab75f..87915703f 100644 --- a/rtgui/pcvignette.h +++ b/rtgui/pcvignette.h @@ -1,14 +1,17 @@ /* * This file is part of RawTherapee. */ -#ifndef _PCVIGNETTE_H_ -#define _PCVIGNETTE_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -class PCVignette : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class PCVignette final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -30,5 +33,3 @@ public: void setAdjusterBehavior (bool strengthadd, bool featheradd, bool roundnessadd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; - -#endif diff --git a/rtgui/pdsharpening.cc b/rtgui/pdsharpening.cc new file mode 100644 index 000000000..8bbf19620 --- /dev/null +++ b/rtgui/pdsharpening.cc @@ -0,0 +1,296 @@ +/* + * 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 "pdsharpening.h" + +#include "eventmapper.h" +#include "options.h" +#include "rtimage.h" + +#include "../rtengine/procparams.h" + +using namespace rtengine; +using namespace rtengine::procparams; + +PdSharpening::PdSharpening() : + FoldableToolPanel(this, "capturesharpening", M("TP_PDSHARPENING_LABEL"), false, true), + lastAutoContrast(true), + lastAutoRadius(true) +{ + auto m = ProcEventMapper::getInstance(); + EvPdShrContrast = m->newEvent(CAPTURESHARPEN, "HISTORY_MSG_PDSHARPEN_CONTRAST"); + EvPdShrCheckIter = m->newEvent(CAPTURESHARPEN, "HISTORY_MSG_PDSHARPEN_CHECKITER"); + 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()); + dradius = Gtk::manage(new Adjuster(M("TP_SHARPENING_RADIUS"), 0.4, 2.0, 0.01, 0.75)); + dradius->addAutoButton(); + dradius->setAutoValue(true); + dradiusOffset = Gtk::manage(new Adjuster(M("TP_SHARPENING_RADIUS_BOOST"), -0.5, 0.5, 0.01, 0.0)); + diter = Gtk::manage(new Adjuster(M("TP_SHARPENING_RLD_ITERATIONS"), 1, 100, 1, 20)); + itercheck = Gtk::manage(new CheckBox(M("TP_SHARPENING_ITERCHECK"), multiImage)); + itercheck->setCheckBoxListener(this); + + rld->pack_start(*dradius); + rld->pack_start(*dradiusOffset); + rld->pack_start(*diter); + rld->pack_start(*itercheck); + dradius->show(); + dradiusOffset->show(); + diter->show(); + itercheck->show(); + rld->show(); + pack_start(*rld); + + dradius->setAdjusterListener(this); + dradiusOffset->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); + 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); + dradius->setEditedState(pedited->pdsharpening.deconvradius ? Edited : UnEdited); + dradiusOffset->setEditedState(pedited->pdsharpening.deconvradiusOffset ? Edited : UnEdited); + diter->setEditedState(pedited->pdsharpening.deconviter ? Edited : UnEdited); + itercheck->setEdited(pedited->pdsharpening.deconvitercheck); + + set_inconsistent(multiImage && !pedited->pdsharpening.enabled); + } + + setEnabled(pp->pdsharpening.enabled); + + contrast->setValue(pp->pdsharpening.contrast); + contrast->setAutoValue(pp->pdsharpening.autoContrast); + dradius->setValue(pp->pdsharpening.deconvradius); + dradius->setAutoValue(pp->pdsharpening.autoRadius); + dradiusOffset->setValue(pp->pdsharpening.deconvradiusOffset); + diter->setValue(pp->pdsharpening.deconviter); + itercheck->setValue(pp->pdsharpening.deconvitercheck); + + 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.deconvradius = dradius->getValue(); + pp->pdsharpening.autoRadius = dradius->getAutoValue(); + pp->pdsharpening.deconvradiusOffset = dradiusOffset->getValue(); + pp->pdsharpening.deconviter =(int)diter->getValue(); + pp->pdsharpening.deconvitercheck = itercheck->getLastActive(); + + if (pedited) { + pedited->pdsharpening.contrast = contrast->getEditedState(); + pedited->pdsharpening.autoContrast = !contrast->getAutoInconsistent(); + pedited->pdsharpening.deconvradius = dradius->getEditedState(); + pedited->pdsharpening.autoRadius = !dradius->getAutoInconsistent(); + pedited->pdsharpening.deconvradiusOffset = dradiusOffset->getEditedState(); + pedited->pdsharpening.deconviter = diter->getEditedState(); + pedited->pdsharpening.deconvitercheck = !itercheck->get_inconsistent(); + pedited->pdsharpening.enabled = !get_inconsistent(); + } +} + +void PdSharpening::setDefaults(const ProcParams* defParams, const ParamsEdited* pedited) +{ + + contrast->setDefault(defParams->pdsharpening.contrast); + dradius->setDefault(defParams->pdsharpening.deconvradius); + dradiusOffset->setDefault(defParams->pdsharpening.deconvradiusOffset); + diter->setDefault(defParams->pdsharpening.deconviter); + + if (pedited) { + contrast->setDefaultEditedState(pedited->pdsharpening.contrast ? 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); + dradius->setDefaultEditedState(Irrelevant); + dradiusOffset->setDefaultEditedState(Irrelevant); + diter->setDefaultEditedState(Irrelevant); + } +} + +void PdSharpening::checkBoxToggled (CheckBox* c, CheckValue newval) +{ + if (listener) { + listener->panelChanged (EvPdShrCheckIter, itercheck->getLastActive() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } +} + +void PdSharpening::adjusterChanged(Adjuster* a, double newval) +{ + if (listener && (multiImage || getEnabled())) { + + Glib::ustring costr; + + if (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 == 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(); + dradius->showEditedCB(); + dradiusOffset->showEditedCB(); + diter->showEditedCB(); +} + +void PdSharpening::setAdjusterBehavior(bool contrastadd, bool radiusadd, bool iteradd) +{ + + contrast->setAddMode(contrastadd); + dradius->setAddMode(radiusadd); + dradiusOffset->setAddMode(radiusadd); + diter->setAddMode(iteradd); +} + +void PdSharpening::trimValues(rtengine::procparams::ProcParams* pp) +{ + + contrast->trimValue(pp->pdsharpening.contrast); + 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) +{ + if (multiImage) { + if (a->getAutoInconsistent()) { + a->setAutoInconsistent(false); + a->setAutoValue(false); + } else if (lastAutoRadius) { + a->setAutoInconsistent(true); + } + + (a == contrast ? lastAutoContrast : lastAutoRadius) = a->getAutoValue(); + } + + if (listener) { + const auto event = (a == contrast ? EvPdShrAutoContrast : EvPdShrAutoRadius); + if (a->getAutoInconsistent()) { + listener->panelChanged(event, M("GENERAL_UNCHANGED")); + } else if (a->getAutoValue()) { + listener->panelChanged(event, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(event, M("GENERAL_DISABLED")); + } + } +} diff --git a/rtgui/pdsharpening.h b/rtgui/pdsharpening.h new file mode 100644 index 000000000..eb0576ceb --- /dev/null +++ b/rtgui/pdsharpening.h @@ -0,0 +1,72 @@ +/* + * 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 "checkbox.h" +#include "toolpanel.h" + +class PdSharpening final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public rtengine::AutoContrastListener, + public rtengine::AutoRadiusListener, + public CheckBoxListener +{ + +protected: + Adjuster* contrast; + Adjuster* dradius; + Adjuster* dradiusOffset; + Adjuster* diter; + CheckBox* itercheck; + + bool lastAutoContrast; + bool lastAutoRadius; + rtengine::ProcEvent EvPdShrContrast; + rtengine::ProcEvent EvPdShrCheckIter; + rtengine::ProcEvent EvPdShrDRadius; + rtengine::ProcEvent EvPdShrDRadiusOffset; + 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) 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 radiusadd, bool iteradd); + void trimValues (rtengine::procparams::ProcParams* pp) override; + void checkBoxToggled(CheckBox* c, CheckValue newval) override; +}; diff --git a/rtgui/perspective.cc b/rtgui/perspective.cc index 752b2289b..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" diff --git a/rtgui/perspective.h b/rtgui/perspective.h index 77fedc84a..0564479de 100644 --- a/rtgui/perspective.h +++ b/rtgui/perspective.h @@ -14,16 +14,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 . */ -#ifndef _PERSPECTIVE_PANEL_H_ -#define _PERSPECTIVE_PANEL_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -class PerspCorrection : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class PerspCorrection final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -43,5 +46,3 @@ public: void setAdjusterBehavior (bool badd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; - -#endif diff --git a/rtgui/placesbrowser.cc b/rtgui/placesbrowser.cc index 9935064ee..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; } diff --git a/rtgui/placesbrowser.h b/rtgui/placesbrowser.h index b3bed867c..d4640fff4 100644 --- a/rtgui/placesbrowser.h +++ b/rtgui/placesbrowser.h @@ -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 . */ -#ifndef _PLACESBROWSER_ -#define _PLACESBROWSER_ +#pragma once #include -#include -#include "multilangmgr.h" -class PlacesBrowser : public Gtk::VBox +#include + +class PlacesBrowser : + public Gtk::VBox { public: typedef sigc::slot DirSelectionSlot; @@ -84,7 +84,3 @@ inline void PlacesBrowser::setDirSelector (const PlacesBrowser::DirSelectionSlot { this->selectDir = selectDir; } - -#endif - - diff --git a/rtgui/pointermotionlistener.h b/rtgui/pointermotionlistener.h index 88a4b2279..26ca994b0 100644 --- a/rtgui/pointermotionlistener.h +++ b/rtgui/pointermotionlistener.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 _POINTERMOTIONLISTENER_ -#define _POINTERMOTIONLISTENER_ +#pragma once class PointerMotionListener { @@ -26,7 +25,7 @@ protected: sigc::signal sig_cycle_hsv; public: - virtual ~PointerMotionListener() {} + virtual ~PointerMotionListener() = default; virtual void pointerMoved (bool validPos, const Glib::ustring &profile, const Glib::ustring &profileW, int x, int y, int r, int g, int b, bool isRaw = false) = 0; virtual void getRGBText (int r, int g, int b, Glib::ustring &sR, Glib::ustring &sG, Glib::ustring &sB, bool isRaw = false) { sR = "--"; sG = "--"; sB = "--"; } virtual void getHSVText (float h, float s, float v, Glib::ustring &sH, Glib::ustring &sS, Glib::ustring &sV) { sH = "--"; sS = "--"; sV = "--"; } @@ -41,5 +40,3 @@ public: return sig_cycle_hsv; } }; - -#endif 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..a67339a9f 100644 --- a/rtgui/popupbutton.h +++ b/rtgui/popupbutton.h @@ -14,17 +14,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 . * * Class created by Jean-Christophe FRISCH, aka 'Hombre' */ -#ifndef _POPUPBUTTON_ -#define _POPUPBUTTON_ +#pragma once #include + #include "popupcommon.h" -class PopUpButton : public Gtk::Button, public PopUpCommon +class PopUpButton final : + public Gtk::Button, + public PopUpCommon { public: @@ -40,5 +42,3 @@ private: bool nextOnClicked; }; - -#endif 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..b4cf4d7e0 100644 --- a/rtgui/popupcommon.h +++ b/rtgui/popupcommon.h @@ -14,23 +14,26 @@ * GNU General Public License for more details. * * 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' */ -#ifndef _POPUPCOMMON_ -#define _POPUPCOMMON_ +#pragma once #include + #include + #include namespace Gtk { + class Grid; class Menu; class Button; class ImageMenuItem; + } typedef struct _GdkEventButton GdkEventButton; @@ -47,7 +50,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; @@ -101,5 +104,3 @@ inline int PopUpCommon::getSelected () const { return posToIndex(selected); } - -#endif 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..a97c75fa2 100644 --- a/rtgui/popuptogglebutton.h +++ b/rtgui/popuptogglebutton.h @@ -14,17 +14,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 . * * Class created by Jean-Christophe FRISCH, aka 'Hombre' */ -#ifndef _POPUPTOGGLEBUTTON_ -#define _POPUPTOGGLEBUTTON_ +#pragma once #include + #include "popupcommon.h" -class PopUpToggleButton : public Gtk::ToggleButton, public PopUpCommon +class PopUpToggleButton : + public Gtk::ToggleButton, + public PopUpCommon { public: @@ -32,5 +34,3 @@ public: void show (); void set_tooltip_text (const Glib::ustring &text); }; - -#endif diff --git a/rtgui/pparamschangelistener.h b/rtgui/pparamschangelistener.h index c8338745e..e255b9657 100644 --- a/rtgui/pparamschangelistener.h +++ b/rtgui/pparamschangelistener.h @@ -14,14 +14,32 @@ * GNU General Public License for more details. * * 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_ +#pragma once -#include "../rtengine/rtengine.h" -#include -#include "paramsedited.h" +struct ParamsEdited; + +namespace Glib +{ + +class ustring; + +} +namespace rtengine +{ + +class ProcEvent; + +namespace procparams +{ + +class ProcParams; + + +} + +} class PParamsChangeListener { @@ -43,6 +61,3 @@ public: virtual void beginBatchPParamsChange(int numberOfEntries) = 0; virtual void endBatchPParamsChange() = 0; }; - -#endif - diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index da4cd564a..9fbb8c7ad 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" @@ -24,8 +24,11 @@ #include "addsetids.h" #include "../rtengine/dfmanager.h" #include "../rtengine/ffmanager.h" +#include "../rtengine/iccstore.h" +#include "../rtengine/procparams.h" #include #include "rtimage.h" +#include "rtwindow.h" #ifdef _OPENMP #include #endif @@ -49,13 +52,13 @@ void placeSpinBox(Gtk::Container* where, Gtk::SpinButton* &spin, const std::stri } } -extern Options options; extern Glib::ustring argv0; Glib::RefPtr themecss; 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 +66,6 @@ Preferences::Preferences(RTWindow *rtwindow) , newFont(false) , newCPFont(false) { - regex = Glib::Regex::create(THEMEREGEXSTR, Glib::RegexCompileFlags::REGEX_CASELESS); moptions.copyFrom(&options); @@ -126,7 +128,7 @@ Preferences::~Preferences() get_size(options.preferencesWidth, options.preferencesHeight); } -int Preferences::getThemeRowNumber(Glib::ustring& longThemeFName) +int Preferences::getThemeRowNumber (const Glib::ustring& longThemeFName) { if (regex->match(longThemeFName + ".css", matchInfo)) { @@ -929,16 +931,32 @@ Gtk::Widget* Preferences::getGeneralPanel() workflowGrid->attach_next_to(*curveBBoxPosC, *editorLayout, Gtk::POS_BOTTOM, 1, 1); workflowGrid->attach_next_to(*curveBBoxPosRestartL, *lNextStart, Gtk::POS_BOTTOM, 1, 1); + Gtk::Label* complexityL = Gtk::manage(new Gtk::Label(M("PREFERENCES_COMPLEXITYLOC") + ":")); + setExpandAlignProperties(complexityL, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); + complexitylocal = Gtk::manage(new Gtk::ComboBoxText()); + setExpandAlignProperties(complexitylocal, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); + complexitylocal->append(M("PREFERENCES_COMPLEXITY_EXP")); + complexitylocal->append(M("PREFERENCES_COMPLEXITY_CONF")); + complexitylocal->append(M("PREFERENCES_COMPLEXITY_NORM")); + complexitylocal->set_active(2); + Gtk::Label* complexitylocalRestartL = Gtk::manage(new Gtk::Label(Glib::ustring("(") + M("PREFERENCES_APPLNEXTSTARTUP") + ")")); + setExpandAlignProperties(complexitylocalRestartL, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); + workflowGrid->attach_next_to(*complexityL, *curveBBoxPosL, Gtk::POS_BOTTOM, 1, 1); + workflowGrid->attach_next_to(*complexitylocal, *curveBBoxPosC, Gtk::POS_BOTTOM, 1, 1); + workflowGrid->attach_next_to(*complexitylocalRestartL, *curveBBoxPosRestartL, Gtk::POS_BOTTOM, 1, 1); + + + ckbHistogramPositionLeft = Gtk::manage(new Gtk::CheckButton(M("PREFERENCES_HISTOGRAMPOSITIONLEFT"))); setExpandAlignProperties(ckbHistogramPositionLeft, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); - workflowGrid->attach_next_to(*ckbHistogramPositionLeft, *curveBBoxPosL, Gtk::POS_BOTTOM, 1, 1); + workflowGrid->attach_next_to(*ckbHistogramPositionLeft, *complexityL, Gtk::POS_BOTTOM, 1, 1); ckbFileBrowserToolbarSingleRow = Gtk::manage(new Gtk::CheckButton(M("PREFERENCES_FILEBROWSERTOOLBARSINGLEROW"))); setExpandAlignProperties(ckbFileBrowserToolbarSingleRow, false, false, Gtk::ALIGN_START, Gtk::ALIGN_START); ckbShowFilmStripToolBar = Gtk::manage(new Gtk::CheckButton(M("PREFERENCES_SHOWFILMSTRIPTOOLBAR"))); setExpandAlignProperties(ckbShowFilmStripToolBar, false, false, Gtk::ALIGN_START, Gtk::ALIGN_START); workflowGrid->attach_next_to(*ckbFileBrowserToolbarSingleRow, *ckbHistogramPositionLeft, Gtk::POS_BOTTOM, 1, 1); - workflowGrid->attach_next_to(*ckbShowFilmStripToolBar, *curveBBoxPosC, Gtk::POS_BOTTOM, 2, 1); + workflowGrid->attach_next_to(*ckbShowFilmStripToolBar, *complexitylocal, Gtk::POS_BOTTOM, 2, 1); Gtk::Label* hb4label = Gtk::manage(new Gtk::Label(M("PREFERENCES_TP_LABEL"))); setExpandAlignProperties(hb4label, false, false, Gtk::ALIGN_START, Gtk::ALIGN_BASELINE); @@ -1792,6 +1810,7 @@ void Preferences::storePreferences() moptions.mainNBVertical = editorMode == 1; moptions.curvebboxpos = curveBBoxPosC->get_active_row_number(); + moptions.complexity = complexitylocal->get_active_row_number(); moptions.histogramPosition = ckbHistogramPositionLeft->get_active() ? 1 : 2; moptions.FileBrowserToolbarSingleRow = ckbFileBrowserToolbarSingleRow->get_active(); moptions.showFilmStripToolBar = ckbShowFilmStripToolBar->get_active(); @@ -2005,6 +2024,8 @@ void Preferences::fillPreferences() } curveBBoxPosC->set_active(moptions.curvebboxpos); + complexitylocal->set_active(moptions.complexity); + ckbHistogramPositionLeft->set_active(moptions.histogramPosition == 1); ckbFileBrowserToolbarSingleRow->set_active(moptions.FileBrowserToolbarSingleRow); ckbShowFilmStripToolBar->set_active(moptions.showFilmStripToolBar); diff --git a/rtgui/preferences.h b/rtgui/preferences.h index c7f5c4983..3cf6b2043 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -14,22 +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 __PREFERENCES_H__ -#define __PREFERENCES_H__ +#pragma once + +#include #include -#include "adjuster.h" -#include "options.h" -#include -#include "rtwindow.h" -#include "dynamicprofilepanel.h" -class Preferences : public Gtk::Dialog, public ProfileStoreListener +#include "dynamicprofilepanel.h" +#include "options.h" +#include "../rtengine/profilestore.h" + +class RTWindow; +class Splash; + +class Preferences final : + public Gtk::Dialog, + public ProfileStoreListener { - class ExtensionColumns : public Gtk::TreeModel::ColumnRecord + class ExtensionColumns : + public Gtk::TreeModel::ColumnRecord { public: Gtk::TreeModelColumn enabled; @@ -140,6 +146,8 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener Gtk::CheckButton* ctiffserialize; Gtk::ComboBoxText* curveBBoxPosC; + Gtk::ComboBoxText* complexitylocal; + Gtk::ComboBoxText* themeCBT; Gtk::FontButton* mainFontFB; Gtk::FontButton* colorPickerFontFB; @@ -243,7 +251,7 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener void switchFontTo (const Glib::ustring &newFontFamily, const int newFontSize); bool splashClosed (GdkEventAny* event); - int getThemeRowNumber (Glib::ustring& longThemeFName); + int getThemeRowNumber (const Glib::ustring& longThemeFName); void appendBehavList (Gtk::TreeModel::iterator& parent, Glib::ustring label, int id, bool set); @@ -304,5 +312,3 @@ public: // void selectICCProfileDir (); // void selectMonitorProfile (); }; - -#endif diff --git a/rtgui/preprocess.cc b/rtgui/preprocess.cc index 07e378832..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 diff --git a/rtgui/preprocess.h b/rtgui/preprocess.h index ced119d7d..d10ff5223 100644 --- a/rtgui/preprocess.h +++ b/rtgui/preprocess.h @@ -14,19 +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 _PREPROCESS_H_ -#define _PREPROCESS_H_ +#pragma once #include -//#include "adjuster.h" -#include "toolpanel.h" + #include "adjuster.h" #include "guiutils.h" -#include "../rtengine/rawimage.h" +#include "toolpanel.h" -class PreProcess : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class PreProcess final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -54,5 +55,3 @@ public: //void setAdjusterBehavior (bool linedenoiseadd, bool greenequiladd); //void trimValues (rtengine::procparams::ProcParams* pp); }; - -#endif 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..4fd9a1e82 100644 --- a/rtgui/previewhandler.h +++ b/rtgui/previewhandler.h @@ -14,19 +14,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 . */ -#ifndef _PREVIEWHANDLER_ -#define _PREVIEWHANDLER_ +#pragma once #include #include #include -#include "threadutils.h" #include "guiutils.h" +#include "threadutils.h" +#include "../rtengine/noncopyable.h" #include "../rtengine/rtengine.h" class PreviewListener @@ -44,7 +44,7 @@ struct PreviewHandlerIdleHelper { int pending; }; -class PreviewHandler : public rtengine::PreviewImageListener +class PreviewHandler final : public rtengine::PreviewImageListener, public rtengine::NonCopyable { private: friend int setImageUI (void* data); @@ -85,5 +85,3 @@ public: Glib::RefPtr getRoughImage (int desiredW, int desiredH, double& zoom); rtengine::procparams::CropParams getCropParams (); }; - -#endif diff --git a/rtgui/previewloader.cc b/rtgui/previewloader.cc index 34b42dcb7..a808e1f71 100644 --- a/rtgui/previewloader.cc +++ b/rtgui/previewloader.cc @@ -14,10 +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 +#include "cachemanager.h" +#include "filebrowserentry.h" #include "previewloader.h" #include "guiutils.h" #include "threadutils.h" diff --git a/rtgui/previewloader.h b/rtgui/previewloader.h index 311d9d5ce..a8032fcaf 100644 --- a/rtgui/previewloader.h +++ b/rtgui/previewloader.h @@ -14,17 +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 . */ -#ifndef _PREVIEWLOADER_ -#define _PREVIEWLOADER_ +#pragma once #include -#include #include "../rtengine/noncopyable.h" -#include "filebrowserentry.h" +namespace Glib +{ + +class ustring; + +} + +class FileBrowserEntry; class PreviewLoaderListener { @@ -94,5 +99,3 @@ private: * To use: \c previewLoader->start() , */ #define previewLoader PreviewLoader::getInstance() - -#endif 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..4121dfb92 100644 --- a/rtgui/previewmodepanel.h +++ b/rtgui/previewmodepanel.h @@ -13,16 +13,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 . */ -#ifndef _PREVIEWMODEPANEL_ -#define _PREVIEWMODEPANEL_ +#pragma once #include -#include "adjuster.h"//dev class ImageArea; -class PreviewModePanel : public Gtk::HBox + +class PreviewModePanel : + public Gtk::HBox { protected: @@ -83,5 +83,3 @@ public: int GetbackColor(); }; - -#endif diff --git a/rtgui/previewwindow.cc b/rtgui/previewwindow.cc index 7688c0470..67fa87e0c 100644 --- a/rtgui/previewwindow.cc +++ b/rtgui/previewwindow.cc @@ -14,12 +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 . */ #include "previewwindow.h" #include "guiutils.h" #include "imagearea.h" #include "cursormanager.h" +#include "options.h" +#include "rtscalable.h" #include "../rtengine/procparams.h" @@ -88,7 +90,7 @@ void PreviewWindow::updatePreviewImage () cc->fill(); if (previewHandler->getCropParams().enabled) { - rtengine::CropParams cparams = previewHandler->getCropParams(); + rtengine::procparams::CropParams cparams = previewHandler->getCropParams(); switch (options.cropGuides) { case Options::CROP_GUIDE_NONE: cparams.guide = "None"; @@ -228,7 +230,7 @@ bool PreviewWindow::on_motion_notify_event (GdkEventMotion* event) if (x>imgX || y>imgY || w < imgW || h < imgH) { bool inside = event->x > x - 6 && event->x < x + w - 1 + 6 && event->y > y - 6 && event->y < y + h - 1 + 6; - CursorShape newType = cursor_type; + CursorShape newType; if (isMoving) { mainCropWin->remoteMove ((event->x - press_x) / zoom, (event->y - press_y) / zoom); diff --git a/rtgui/previewwindow.h b/rtgui/previewwindow.h index c89c89d4e..245f4a394 100644 --- a/rtgui/previewwindow.h +++ b/rtgui/previewwindow.h @@ -14,18 +14,21 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include -#include "previewhandler.h" -#include "cropwindow.h" -#include "guiutils.h" -#include "cursormanager.h" -class PreviewWindow : public Gtk::DrawingArea, public PreviewListener, public CropWindowListener +#include "cropwindow.h" +#include "cursormanager.h" +#include "guiutils.h" +#include "previewhandler.h" + +class PreviewWindow : + public Gtk::DrawingArea, + public PreviewListener, + public CropWindowListener { private: @@ -71,5 +74,3 @@ public: void cropZoomChanged(CropWindow* w) override; void initialImageArrived() override; }; - -#endif 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..656566867 100644 --- a/rtgui/profilechangelistener.h +++ b/rtgui/profilechangelistener.h @@ -14,21 +14,25 @@ * GNU General Public License for more details. * * 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_ +#pragma once -#include +namespace Glib +{ -#include "../rtengine/rtengine.h" +class ustring; + +} namespace rtengine { +class ProcEvent; namespace procparams { +class ProcParams; class PartialProfile; } @@ -48,6 +52,3 @@ public: ) = 0; virtual void setDefaults(const rtengine::procparams::ProcParams* defparams) = 0; }; - -#endif - diff --git a/rtgui/profilepanel.cc b/rtgui/profilepanel.cc index a2597c2d5..fff8b0584 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" @@ -22,9 +22,12 @@ #include "multilangmgr.h" #include "options.h" #include "profilestorecombobox.h" +#include "paramsedited.h" +#include "pathutils.h" #include "rtimage.h" #include "../rtengine/procparams.h" +#include "../rtengine/procevents.h" using namespace rtengine; using namespace rtengine::procparams; @@ -42,7 +45,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; @@ -270,14 +273,43 @@ void ProfilePanel::restoreValue () void ProfilePanel::save_clicked (GdkEventButton* event) { - if (event->button != 1) { return; } - Gtk::FileChooserDialog dialog (getToplevelWindow (this), M("PROFILEPANEL_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); - bindCurrentFolder (dialog, options.loadSaveProfilePath); - dialog.set_current_name (lastFilename); + const PartialProfile* toSave; + + if (isCustomSelected()) { + toSave = custom; + } else if (isLastSavedSelected()) { + toSave = lastsaved; + } else { + const auto entry = profiles->getSelectedEntry(); + toSave = entry ? ProfileStore::getInstance()->getProfile(entry) : nullptr; + } + + // If it's a partial profile, it's more intuitive to first allow the user + // to choose which parameters to save before showing the Save As dialog + // #5491 + const auto isPartial = event->state & Gdk::CONTROL_MASK; + if (isPartial) { + if (!partialProfileDlg) { + partialProfileDlg = new PartialPasteDlg(Glib::ustring(), parent); + } + + partialProfileDlg->set_title(M("PROFILEPANEL_SAVEPPASTE")); + partialProfileDlg->updateSpotWidget(toSave->pparams); + const auto response = partialProfileDlg->run(); + partialProfileDlg->hide(); + + if (response != Gtk::RESPONSE_OK) { + return; + } + } + + Gtk::FileChooserDialog dialog(getToplevelWindow(this), M("PROFILEPANEL_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); + bindCurrentFolder(dialog, options.loadSaveProfilePath); + dialog.set_current_name(lastFilename); //Add the user's default (or global if multiuser=false) profile path to the Shortcut list try { @@ -294,99 +326,60 @@ void ProfilePanel::save_clicked (GdkEventButton* event) dialog.add_button(M("GENERAL_SAVE"), Gtk::RESPONSE_OK); //Add filters, so that only certain file types can be selected: - - Glib::RefPtr filter_pp = Gtk::FileFilter::create(); + auto filter_pp = Gtk::FileFilter::create(); filter_pp->set_name(M("FILECHOOSER_FILTER_PP")); filter_pp->add_pattern("*" + paramFileExtension); dialog.add_filter(filter_pp); - Glib::RefPtr filter_any = Gtk::FileFilter::create(); + auto filter_any = Gtk::FileFilter::create(); filter_any->set_name(M("FILECHOOSER_FILTER_ANY")); filter_any->add_pattern("*"); dialog.add_filter(filter_any); -// dialog.set_do_overwrite_confirmation (true); - - bool done = false; + bool done = true; do { if (dialog.run() == Gtk::RESPONSE_OK) { std::string fname = dialog.get_filename(); - Glib::ustring ext = getExtension (fname); - if (("." + ext) != paramFileExtension) { + if (("." + getExtension(fname)) != paramFileExtension) { fname += paramFileExtension; } - if (!confirmOverwrite (dialog, fname)) { + if (!confirmOverwrite(dialog, fname)) { continue; } - lastFilename = Glib::path_get_basename (fname); - - const PartialProfile* toSave; - - if (isCustomSelected()) { - toSave = custom; - } else if (isLastSavedSelected()) { - toSave = lastsaved; - } else { - const ProfileStoreEntry* entry = profiles->getSelectedEntry(); - toSave = entry ? ProfileStore::getInstance()->getProfile (profiles->getSelectedEntry()) : nullptr; - } + lastFilename = Glib::path_get_basename(fname); if (toSave) { - if (event->state & Gdk::CONTROL_MASK) { - // opening the partial paste dialog window - if(!partialProfileDlg) { - partialProfileDlg = new PartialPasteDlg (Glib::ustring (), parent); - } - partialProfileDlg->set_title(M("PROFILEPANEL_SAVEPPASTE")); - partialProfileDlg->updateSpotWidget(toSave->pparams); - int i = partialProfileDlg->run(); - partialProfileDlg->hide(); + int retCode; - if (i != Gtk::RESPONSE_OK) { - return; - } - - // saving the partial profile + if (isPartial) { + // Build partial profile PartialProfile ppTemp(true); - partialProfileDlg->applyPaste (ppTemp.pparams, ppTemp.pedited, toSave->pparams, toSave->pedited); - int retCode = ppTemp.pparams->save (fname, "", true, ppTemp.pedited); + partialProfileDlg->applyPaste(ppTemp.pparams, ppTemp.pedited, toSave->pparams, toSave->pedited); + // Save partial profile + retCode = ppTemp.pparams->save(fname, "", true, ppTemp.pedited); + // Cleanup ppTemp.deleteInstance(); - - if (retCode) { - writeFailed(dialog, fname); - } else { - done = true; - bool ccPrevState = changeconn.block(true); - ProfileStore::getInstance()->parseProfiles(); - changeconn.block (ccPrevState); - } } else { - // saving a full profile - int retCode = toSave->pparams->save (fname); - - if (retCode) { - writeFailed(dialog, fname); - } else { - done = true; - bool ccPrevState = changeconn.block(true); - ProfileStore::getInstance()->parseProfiles(); - changeconn.block (ccPrevState); - } + // Save full profile + retCode = toSave->pparams->save(fname); + } + + if (!retCode) { + const auto ccPrevState = changeconn.block(true); + ProfileStore::getInstance()->parseProfiles(); + changeconn.block(ccPrevState); + } else { + done = false; + writeFailed(dialog, fname); } - } else { - done = true; } - } else { - done = true; } } while (!done); - - return; } /* @@ -467,7 +460,6 @@ void ProfilePanel::load_clicked (GdkEventButton* event) dialog.add_button(M("GENERAL_OPEN"), Gtk::RESPONSE_OK); //Add filters, so that only certain file types can be selected: - Glib::RefPtr filter_pp = Gtk::FileFilter::create(); filter_pp->set_name(M("FILECHOOSER_FILTER_PP")); filter_pp->add_pattern("*" + paramFileExtension); diff --git a/rtgui/profilepanel.h b/rtgui/profilepanel.h index b0fb42ab7..c3a125c49 100644 --- a/rtgui/profilepanel.h +++ b/rtgui/profilepanel.h @@ -14,22 +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 . */ -#ifndef _PROFILEPANEL_ -#define _PROFILEPANEL_ +#pragma once + +#include #include -#include -#include "../rtengine/rtengine.h" + +#include "guiutils.h" +#include "partialpastedlg.h" #include "pparamschangelistener.h" #include "profilechangelistener.h" -#include "partialpastedlg.h" -#include "guiutils.h" -#include "profilestorecombobox.h" -#include "rtimage.h" -class ProfilePanel : public Gtk::Grid, public PParamsChangeListener, public ProfileStoreListener +#include "../rtengine/profilestore.h" +#include "../rtengine/noncopyable.h" + +class ProfileStoreComboBox; + +namespace rtengine +{ + +class ProcEvent; + +namespace procparams +{ + +class ProcParams; + +class PartialProfile; + +} + +} +class RTImage; + +class ProfilePanel final : + public Gtk::Grid, + public PParamsChangeListener, + public ProfileStoreListener, + public rtengine::NonCopyable { private: @@ -105,5 +129,3 @@ public: void selection_changed (); void writeOptions(); }; - -#endif 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..bfd713235 100644 --- a/rtgui/profilestorecombobox.h +++ b/rtgui/profilestorecombobox.h @@ -14,28 +14,23 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include #include -#include -#include "../rtengine/rtengine.h" -#include "../rtengine/noncopyable.h" -#include "../rtengine/profilestore.h" +#include -#include "threadutils.h" -#include "paramsedited.h" #include "guiutils.h" +#include "threadutils.h" - +class ProfileStoreEntry; /** * @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 +39,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 +50,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,23 +69,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); }; - -#endif diff --git a/rtgui/progressconnector.h b/rtgui/progressconnector.h index 394ad3909..90c9f67f0 100644 --- a/rtgui/progressconnector.h +++ b/rtgui/progressconnector.h @@ -14,19 +14,21 @@ * GNU General Public License for more details. * * 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_ +#pragma once + +#include #include -#include -#include "../rtengine/rtengine.h" + #include "guiutils.h" +#include "multilangmgr.h" +#include "../rtengine/rtengine.h" #undef THREAD_PRIORITY_NORMAL -class PLDBridge : +class PLDBridge final : public rtengine::ProgressListener { public: @@ -77,9 +79,9 @@ class ProgressConnector static int emitEndSignalUI (void* data) { - sigc::signal0* opEnd = (sigc::signal0*) data; - int r = opEnd->emit (); - delete opEnd; + const sigc::signal0* lopEnd = reinterpret_cast*>(data); + const int r = lopEnd->emit (); + delete lopEnd; return r; } @@ -109,4 +111,3 @@ public: return retval; } }; -#endif diff --git a/rtgui/prsharpening.cc b/rtgui/prsharpening.cc index b12da977d..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" diff --git a/rtgui/prsharpening.h b/rtgui/prsharpening.h index d8a27c188..9738a5cd4 100644 --- a/rtgui/prsharpening.h +++ b/rtgui/prsharpening.h @@ -14,17 +14,21 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include + #include "adjuster.h" #include "thresholdadjuster.h" #include "toolpanel.h" -class PrSharpening : public ToolParamBlock, public ThresholdAdjusterListener, public AdjusterListener, public FoldableToolPanel +class PrSharpening final : + public ToolParamBlock, + public ThresholdAdjusterListener, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -79,5 +83,3 @@ public: void setAdjusterBehavior (bool contrastadd, bool radiusadd, bool amountadd, bool dampingadd, bool iteradd, bool edgetoladd, bool haloctrladd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; - -#endif diff --git a/rtgui/rawcacorrection.cc b/rtgui/rawcacorrection.cc index 003d8b629..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" diff --git a/rtgui/rawcacorrection.h b/rtgui/rawcacorrection.h index ab80bd3ea..3c95602a7 100644 --- a/rtgui/rawcacorrection.h +++ b/rtgui/rawcacorrection.h @@ -14,17 +14,21 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include + #include "adjuster.h" #include "checkbox.h" #include "toolpanel.h" -class RAWCACorr : public ToolParamBlock, public AdjusterListener, public CheckBoxListener, public FoldableToolPanel +class RAWCACorr final: + public ToolParamBlock, + public AdjusterListener, + public CheckBoxListener, + public FoldableToolPanel { protected: @@ -52,5 +56,3 @@ public: void adjusterChanged (Adjuster* a, double newval) override; void checkBoxToggled (CheckBox* c, CheckValue newval) override; }; - -#endif diff --git a/rtgui/rawexposure.cc b/rtgui/rawexposure.cc index f8885eb76..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 diff --git a/rtgui/rawexposure.h b/rtgui/rawexposure.h index 95a15ade2..33c897113 100644 --- a/rtgui/rawexposure.h +++ b/rtgui/rawexposure.h @@ -14,24 +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 _RAWEXPOSURE_H_ -#define _RAWEXPOSURE_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -#include "../rtengine/rawimage.h" -class RAWExposure : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class RAWExposure final: + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: Adjuster* PexPos; -private: -// Gtk::CheckButton* PextwoGreen; public: RAWExposure (); @@ -44,5 +44,3 @@ public: void setAdjusterBehavior (bool pexposadd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; - -#endif 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..bc8374087 100644 --- a/rtgui/recentbrowser.h +++ b/rtgui/recentbrowser.h @@ -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 . */ -#ifndef _RECENTBROWSER_ -#define _RECENTBROWSER_ +#pragma once #include -#include "multilangmgr.h" + #include "guiutils.h" -class RecentBrowser : public Gtk::VBox +class RecentBrowser : + public Gtk::VBox { public: typedef sigc::slot DirSelectionSlot; @@ -47,7 +47,3 @@ inline void RecentBrowser::setDirSelector (const RecentBrowser::DirSelectionSlot { this->selectDir = selectDir; } - -#endif - - diff --git a/rtgui/renamedlg.cc b/rtgui/renamedlg.cc index 14931817f..8908d3419 100644 --- a/rtgui/renamedlg.cc +++ b/rtgui/renamedlg.cc @@ -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 . */ #include "renamedlg.h" +#include "cacheimagedata.h" #include "multilangmgr.h" -#include "options.h" #include "rtimage.h" RenameDialog::RenameDialog (Gtk::Window* parent) diff --git a/rtgui/renamedlg.h b/rtgui/renamedlg.h index ab51a43c6..3c92965f8 100644 --- a/rtgui/renamedlg.h +++ b/rtgui/renamedlg.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 _RENAMEDLG_ -#define _RENAMEDLG_ +#pragma once #include -#include "cacheimagedata.h" + #include "guiutils.h" #define RESPONSE_ALL 100 -class RenameDialog : public Gtk::Dialog +class CacheImageData; + +class RenameDialog final : + public Gtk::Dialog { protected: @@ -43,6 +45,3 @@ public: Glib::ustring getNewName (); }; - -#endif - diff --git a/rtgui/resize.cc b/rtgui/resize.cc index 3789d4693..a65875426 100644 --- a/rtgui/resize.cc +++ b/rtgui/resize.cc @@ -14,8 +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 . */ + +#include + #include "resize.h" #include "eventmapper.h" @@ -91,14 +94,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); @@ -572,11 +574,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; @@ -584,6 +588,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; @@ -591,6 +596,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 3bcfe3f84..41b54509e 100644 --- a/rtgui/resize.h +++ b/rtgui/resize.h @@ -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 . */ -#ifndef _RESIZE_H_ -#define _RESIZE_H_ +#pragma once #include + #include "adjuster.h" #include "guiutils.h" -#include "toolpanel.h" #include "guiutils.h" +#include "toolpanel.h" class Resize final : public ToolParamBlock, @@ -86,5 +86,3 @@ private: static constexpr int MAX_SCALE = 16; // 16 to match the main preview max scale of 1600% }; - -#endif diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc index e074d7e9c..c78be375f 100644 --- a/rtgui/retinex.cc +++ b/rtgui/retinex.cc @@ -2,8 +2,13 @@ * This file is part of RawTherapee. */ #include "retinex.h" + +#include "curveeditor.h" +#include "curveeditorgroup.h" #include "mycurve.h" #include "rtimage.h" +#include "options.h" +#include "../rtengine/color.h" using namespace rtengine; using namespace rtengine::procparams; diff --git a/rtgui/retinex.h b/rtgui/retinex.h index 1be511cb3..ff524f854 100644 --- a/rtgui/retinex.h +++ b/rtgui/retinex.h @@ -1,21 +1,30 @@ /* * This file is part of RawTherapee. */ -#ifndef _RETINEX_H_ -#define _RETINEX_H_ +#pragma once #include + #include "adjuster.h" -#include "toolpanel.h" -#include "guiutils.h" -#include "curveeditor.h" -#include "curveeditorgroup.h" -#include "thresholdadjuster.h" #include "colorprovider.h" +#include "curvelistener.h" +#include "curveeditorgroup.h" +#include "guiutils.h" +#include "thresholdadjuster.h" +#include "toolpanel.h" -class Retinex : public ToolParamBlock, public FoldableToolPanel, public rtengine::RetinexListener, public CurveListener, - public AdjusterListener, public ColorProvider +class CurveEditor; +class CurveEditorGroup; +class DiagonalCurveEditor; +class FlatCurveEditor; +class Retinex final : + public ToolParamBlock, + public FoldableToolPanel, + public rtengine::RetinexListener, + public CurveListener, + public AdjusterListener, + public ColorProvider { private: IdleRegister idle_register; @@ -141,5 +150,3 @@ private: void foldAllButMe (GdkEventButton* event, MyExpander *expander); }; - -#endif diff --git a/rtgui/rgbcurves.cc b/rtgui/rgbcurves.cc index 560ee7e57..d501cf449 100644 --- a/rtgui/rgbcurves.cc +++ b/rtgui/rgbcurves.cc @@ -14,16 +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 . */ #include "rgbcurves.h" +#include "curveeditor.h" +#include "curveeditorgroup.h" +#include "options.h" + #include "../rtengine/procparams.h" 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..edc80eb41 100644 --- a/rtgui/rgbcurves.h +++ b/rtgui/rgbcurves.h @@ -14,19 +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 _RGBCURVES_H_ -#define _RGBCURVES_H_ +#pragma once #include -#include "adjuster.h" -#include "toolpanel.h" -#include "curveeditor.h" -#include "curveeditorgroup.h" -#include "colorprovider.h" -class RGBCurves : public ToolParamBlock, public FoldableToolPanel, public CurveListener, public ColorProvider +#include "colorprovider.h" +#include "curvelistener.h" +#include "toolpanel.h" + +class CurveEditorGroup; +class DiagonalCurveEditor; + +class RGBCurves final : + public ToolParamBlock, + public FoldableToolPanel, + public CurveListener, + public ColorProvider { protected: @@ -66,5 +71,3 @@ public: void lumamodeChanged (); void enabledChanged() override; }; - -#endif diff --git a/rtgui/rotate.cc b/rtgui/rotate.cc index 822443cf8..06c53cd4e 100644 --- a/rtgui/rotate.cc +++ b/rtgui/rotate.cc @@ -14,13 +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 . */ #include #include "rotate.h" #include "guiutils.h" +#include "lensgeomlistener.h" #include "rtimage.h" #include "../rtengine/procparams.h" diff --git a/rtgui/rotate.h b/rtgui/rotate.h index c3d18fecb..41e10eb4d 100644 --- a/rtgui/rotate.h +++ b/rtgui/rotate.h @@ -14,17 +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 _ROTATE_H_ -#define _ROTATE_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -#include "lensgeomlistener.h" -class Rotate : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class LensGeomListener; +class Rotate final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -52,5 +55,3 @@ public: rlistener = l; } }; - -#endif diff --git a/rtgui/rtimage.cc b/rtgui/rtimage.cc index cd687f252..44078ed3b 100644 --- a/rtgui/rtimage.cc +++ b/rtgui/rtimage.cc @@ -15,14 +15,15 @@ * GNU General Public License for more details. * * 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" +#include #include -#include "options.h" +#include "../rtengine/settings.h" namespace { @@ -37,12 +38,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 +170,7 @@ void RTImage::init() scaleBack = RTScalable::getScale(); } -void RTImage::cleanup() +void RTImage::cleanup(bool all) { for (auto& entry : pixbufCache) { entry.second.reset(); @@ -181,7 +178,7 @@ void RTImage::cleanup() for (auto& entry : surfaceCache) { entry.second.clear(); } - RTScalable::cleanup(); + RTScalable::cleanup(all); } void RTImage::updateImages() @@ -218,7 +215,7 @@ Cairo::RefPtr RTImage::createImgSurfFromFile (const Glib::u } */ } catch (const Glib::Exception& exception) { - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { std::cerr << "Failed to load image \"" << fileName << "\": " << exception.what() << std::endl; } } diff --git a/rtgui/rtimage.h b/rtgui/rtimage.h index 5679f6edc..eb1930d28 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 @@ -25,7 +25,7 @@ /** * @brief A derived class of Gtk::Image in order to handle theme-related icon sets. */ -class RTImage : public Gtk::Image, public RTScalable +class RTImage final : public Gtk::Image, public RTScalable { static double dpiBack; // used to keep track of master dpi change static int scaleBack; // used to keep track of master scale change @@ -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..a48a95fd2 100644 --- a/rtgui/rtscalable.cc +++ b/rtgui/rtscalable.cc @@ -14,22 +14,23 @@ * GNU General Public License for more details. * * 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" #include #include -#include +#include #include #include + +#include "../rtengine/rt_math.h" #include "options.h" double RTScalable::dpi = 0.; int RTScalable::scale = 0; extern Glib::ustring argv0; -extern Options options; extern unsigned char initialGdkScale; extern float fontScale; Gtk::TextDirection RTScalable::direction = Gtk::TextDirection::TEXT_DIR_NONE; @@ -37,9 +38,9 @@ Gtk::TextDirection RTScalable::direction = Gtk::TextDirection::TEXT_DIR_NONE; void RTScalable::setDPInScale (const double newDPI, const int newScale) { if (!options.pseudoHiDPISupport) { - scale = 1; - dpi = baseDPI; - return; + scale = 1; + dpi = baseDPI; + return; } if (scale != newScale || (scale == 1 && dpi != newDPI)) { @@ -101,7 +102,7 @@ void RTScalable::deleteDir(const Glib::ustring& path) error |= g_remove (Glib::build_filename (path, *entry).c_str()); } - if (error != 0 && options.rtSettings.verbose) { + if (error != 0 && rtengine::settings->verbose) { std::cerr << "Failed to delete all entries in '" << path << "': " << g_strerror(errno) << std::endl; } @@ -119,7 +120,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 +135,7 @@ void RTScalable::cleanup() continue; } - if (fileName != sDPI) { + if (all || fileName != sDPI) { deleteDir(filePath); } } @@ -220,7 +221,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 f7d06feb9..b63ad9297 100644 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -14,17 +14,25 @@ * GNU General Public License for more details. * * 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 "rtwindow.h" -#include "options.h" +#include "cachemanager.h" #include "preferences.h" #include "iccprofilecreator.h" #include "cursormanager.h" +#include "editwindow.h" #include "rtimage.h" +#include "thumbnail.h" #include "whitebalance.h" +#include "../rtengine/settings.h" +#include "batchqueuepanel.h" +#include "batchqueueentry.h" +#include "editorpanel.h" +#include "filepanel.h" +#include "filmsimulation.h" float fontScale = 1.f; Glib::RefPtr cssForced; @@ -36,14 +44,14 @@ extern unsigned char initialGdkScale; static gboolean osx_should_quit_cb (GtkosxApplication *app, gpointer data) { - RTWindow *rtWin = (RTWindow *)data; + RTWindow * const rtWin = static_cast(data); return rtWin->on_delete_event (0); } static void osx_will_quit_cb (GtkosxApplication *app, gpointer data) { - RTWindow *rtWin = (RTWindow *)data; + RTWindow *rtWin = static_cast(data); rtWin->on_delete_event (0); gtk_main_quit (); } @@ -67,7 +75,7 @@ bool RTWindow::osxFileOpenEvent (Glib::ustring path) static gboolean osx_open_file_cb (GtkosxApplication *app, gchar *path_, gpointer data) { - RTWindow *rtWin = (RTWindow *)data; + RTWindow *rtWin = static_cast(data); if (!argv1.empty()) { // skip handling if we have a file argument or else we get double open of same file @@ -95,6 +103,9 @@ RTWindow::RTWindow () , fpanel (nullptr) { + if (options.is_new_version()) { + RTImage::cleanup(true); + } cacheMgr->init (); ProfilePanel::init (this); @@ -165,16 +176,16 @@ RTWindow::RTWindow () #endif //GTK318 if (options.pseudoHiDPISupport) { - fontScale = options.fontSize / (float)RTScalable::baseFontSize; + fontScale = options.fontSize / (float)RTScalable::baseFontSize; } - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { printf("\"Non-Default\" font size(%d) * scale(%d) / fontScale(%.3f)\n", options.fontSize, (int)initialGdkScale, fontScale); } } 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(); @@ -193,18 +204,18 @@ RTWindow::RTWindow () pt = fontSize / Pango::SCALE; } if (options.pseudoHiDPISupport) { - fontScale = (float)pt / (float)RTScalable::baseFontSize; + fontScale = (float)pt / (float)RTScalable::baseFontSize; } if ((int)initialGdkScale > 1 || pt != RTScalable::baseFontSize) { css = Glib::ustring::compose ("* { font-size: %1pt}", pt * (int)initialGdkScale); - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { printf("\"Default\" font size(%d) * scale(%d) / fontScale(%.3f)\n", pt, (int)initialGdkScale, fontScale); } } } } if (!css.empty()) { - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { printf("CSS:\n%s\n\n", css.c_str()); } try { @@ -221,13 +232,6 @@ RTWindow::RTWindow () } } -#ifndef NDEBUG - else if (!screen) { - printf ("ERROR: Can't get default screen!\n"); - } - -#endif - // ------- end loading theme files RTScalable::init(this); @@ -254,8 +258,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); @@ -381,8 +383,13 @@ RTWindow::RTWindow () iccProfileCreator->set_tooltip_markup (M ("MAIN_BUTTON_ICCPROFCREATOR")); iccProfileCreator->signal_clicked().connect ( sigc::mem_fun (*this, &RTWindow::showICCProfileCreator) ); - //Gtk::LinkButton* rtWeb = Gtk::manage (new Gtk::LinkButton ("http://rawtherapee.com")); // unused... but fail to be linked anyway !? - //Gtk::Button* preferences = Gtk::manage (new Gtk::Button (M("MAIN_BUTTON_PREFERENCES")+"...")); + Gtk::Button* helpBtn = Gtk::manage (new Gtk::Button ()); + setExpandAlignProperties (helpBtn, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); + helpBtn->set_relief(Gtk::RELIEF_NONE); + helpBtn->set_image (*Gtk::manage (new RTImage ("questionmark.png"))); + helpBtn->set_tooltip_markup (M ("GENERAL_HELP")); + helpBtn->signal_clicked().connect (sigc::mem_fun (*this, &RTWindow::showRawPedia)); + Gtk::Button* preferences = Gtk::manage (new Gtk::Button ()); setExpandAlignProperties (preferences, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); preferences->set_relief(Gtk::RELIEF_NONE); @@ -390,7 +397,6 @@ RTWindow::RTWindow () preferences->set_tooltip_markup (M ("MAIN_BUTTON_PREFERENCES")); preferences->signal_clicked().connect ( sigc::mem_fun (*this, &RTWindow::showPreferences) ); - //btn_fullscreen = Gtk::manage( new Gtk::Button(M("MAIN_BUTTON_FULLSCREEN"))); btn_fullscreen = Gtk::manage ( new Gtk::Button()); setExpandAlignProperties (btn_fullscreen, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); btn_fullscreen->set_relief(Gtk::RELIEF_NONE); @@ -412,6 +418,7 @@ RTWindow::RTWindow () actionGrid->set_orientation (Gtk::ORIENTATION_VERTICAL); actionGrid->attach_next_to (prProgBar, Gtk::POS_BOTTOM, 1, 1); actionGrid->attach_next_to (*iccProfileCreator, Gtk::POS_BOTTOM, 1, 1); + actionGrid->attach_next_to (*helpBtn, Gtk::POS_BOTTOM, 1, 1); actionGrid->attach_next_to (*preferences, Gtk::POS_BOTTOM, 1, 1); actionGrid->attach_next_to (*btn_fullscreen, Gtk::POS_BOTTOM, 1, 1); mainNB->set_action_widget (actionGrid, Gtk::PACK_END); @@ -420,6 +427,7 @@ RTWindow::RTWindow () actionGrid->set_orientation (Gtk::ORIENTATION_HORIZONTAL); actionGrid->attach_next_to (prProgBar, Gtk::POS_RIGHT, 1, 1); actionGrid->attach_next_to (*iccProfileCreator, Gtk::POS_RIGHT, 1, 1); + actionGrid->attach_next_to (*helpBtn, Gtk::POS_RIGHT, 1, 1); actionGrid->attach_next_to (*preferences, Gtk::POS_RIGHT, 1, 1); actionGrid->attach_next_to (*btn_fullscreen, Gtk::POS_RIGHT, 1, 1); mainNB->set_action_widget (actionGrid, Gtk::PACK_END); @@ -455,10 +463,9 @@ RTWindow::~RTWindow() g_object_unref (osxApp); #endif - if (fpanel) { - delete fpanel; - } - + delete fpanel; + delete iFullscreen; + delete iFullscreen_exit; RTImage::cleanup(); } @@ -477,16 +484,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; @@ -659,8 +658,8 @@ void RTWindow::remEditorPanel (EditorPanel* ep) set_title_decorated (""); } else { - EditorPanel* ep = static_cast (mainNB->get_nth_page (mainNB->get_current_page())); - set_title_decorated (ep->getFileName()); + const EditorPanel* lep = static_cast (mainNB->get_nth_page (mainNB->get_current_page())); + set_title_decorated (lep->getFileName()); } // TODO: ask what to do: close & apply, close & apply selection, close & revert, cancel @@ -920,6 +919,12 @@ void RTWindow::writeToolExpandedStatus (std::vector &tpOpen) } +void RTWindow::showRawPedia() +{ + GError* gerror = nullptr; + gtk_show_uri(nullptr, "https://rawpedia.rawtherapee.com/", GDK_CURRENT_TIME, &gerror); +} + void RTWindow::showICCProfileCreator () { ICCProfileCreator *iccpc = new ICCProfileCreator (this); @@ -1174,3 +1179,8 @@ void RTWindow::createSetmEditor() mainNB->append_page (*epanel, *editorLabelGrid); } + +bool RTWindow::isSingleTabMode() const +{ + return !options.tabbedUI && ! (options.multiDisplayMode > 0); +} diff --git a/rtgui/rtwindow.h b/rtgui/rtwindow.h index e4ff285c1..2d4e390e8 100644 --- a/rtgui/rtwindow.h +++ b/rtgui/rtwindow.h @@ -13,24 +13,32 @@ * GNU General Public License for more details. * * 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_ +#pragma once + +#include #include -#include "filepanel.h" -#include "editorpanel.h" -#include "batchqueuepanel.h" -#include -#include "progressconnector.h" -#include "editwindow.h" -#include "splash.h" + #if defined(__APPLE__) #include #endif -class RTWindow : public Gtk::Window, public rtengine::ProgressListener +#include "progressconnector.h" +#include "splash.h" + +#include "../rtengine/noncopyable.h" + +class BatchQueueEntry; +class BatchQueuePanel; +class EditorPanel; +class FilePanel; +class PLDBridge; +class RTWindow final : + public Gtk::Window, + public rtengine::ProgressListener, + public rtengine::NonCopyable { private: @@ -48,11 +56,7 @@ private: Gtk::Image *iFullscreen, *iFullscreen_exit; - bool isSingleTabMode() - { - return !options.tabbedUI && ! (options.multiDisplayMode > 0); - }; - void findVerNumbers (int* numbers, Glib::ustring versionStr); + bool isSingleTabMode() const; bool on_expose_event_epanel (GdkEventExpose* event); bool on_expose_event_fpanel (GdkEventExpose* event); @@ -86,6 +90,7 @@ public: bool on_window_state_event (GdkEventWindowState* event) override; void on_mainNB_switch_page (Gtk::Widget* widget, guint page_num); + void showRawPedia(); void showICCProfileCreator (); void showPreferences (); void on_realize () override; @@ -126,5 +131,3 @@ public: void writeToolExpandedStatus (std::vector &tpOpen); }; - -#endif diff --git a/rtgui/saveasdlg.cc b/rtgui/saveasdlg.cc index f2a7206b9..ebf2f5b4a 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 @@ -22,12 +22,11 @@ #include "guiutils.h" #include "multilangmgr.h" +#include "pathutils.h" #include "rtimage.h" #include "../rtengine/utils.h" -extern Options options; - namespace { diff --git a/rtgui/saveasdlg.h b/rtgui/saveasdlg.h index e02be340f..445452a54 100644 --- a/rtgui/saveasdlg.h +++ b/rtgui/saveasdlg.h @@ -14,17 +14,17 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include -#include "adjuster.h" -#include "saveformatpanel.h" -#include "options.h" -class SaveAsDialog : public Gtk::Dialog, public FormatChangeListener +#include "saveformatpanel.h" + +class SaveAsDialog final : + public Gtk::Dialog, + public FormatChangeListener { protected: @@ -65,6 +65,3 @@ public: void formatChanged(const Glib::ustring& format) override; bool keyPressed (GdkEventKey* event); }; - - -#endif diff --git a/rtgui/saveformatpanel.cc b/rtgui/saveformatpanel.cc index 483565446..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 diff --git a/rtgui/saveformatpanel.h b/rtgui/saveformatpanel.h index e25210b97..af9baa58a 100644 --- a/rtgui/saveformatpanel.h +++ b/rtgui/saveformatpanel.h @@ -14,16 +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 __SAVEFORMATPANEL_H__ -#define __SAVEFORMATPANEL_H__ +#pragma once #include + #include "adjuster.h" #include "guiutils.h" #include "options.h" +#include "../rtengine/noncopyable.h" + class FormatChangeListener { public: @@ -31,7 +33,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: @@ -61,5 +63,3 @@ public: void formatChanged (); void adjusterChanged (Adjuster* a, double 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..2401bf760 100644 --- a/rtgui/sensorbayer.h +++ b/rtgui/sensorbayer.h @@ -14,15 +14,17 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include + #include "toolpanel.h" -class SensorBayer : public ToolParamBlock, public FoldableToolPanel +class SensorBayer final : + public ToolParamBlock, + public FoldableToolPanel { protected: @@ -37,5 +39,3 @@ public: return packBox; } }; - -#endif 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..eee014f6c 100644 --- a/rtgui/sensorxtrans.h +++ b/rtgui/sensorxtrans.h @@ -14,15 +14,17 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include + #include "toolpanel.h" -class SensorXTrans : public ToolParamBlock, public FoldableToolPanel +class SensorXTrans final: + public ToolParamBlock, + public FoldableToolPanel { protected: @@ -37,5 +39,3 @@ public: return packBox; } }; - -#endif diff --git a/rtgui/shadowshighlights.cc b/rtgui/shadowshighlights.cc index f58790051..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" diff --git a/rtgui/shadowshighlights.h b/rtgui/shadowshighlights.h index 5e56e0766..7bb0bb01c 100644 --- a/rtgui/shadowshighlights.h +++ b/rtgui/shadowshighlights.h @@ -14,16 +14,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 . */ -#ifndef _SHADOWSHIGHLIGHTS_H_ -#define _SHADOWSHIGHLIGHTS_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -class ShadowsHighlights : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class ShadowsHighlights final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -53,5 +56,3 @@ public: void colorspaceChanged(); }; - -#endif diff --git a/rtgui/sharpenedge.cc b/rtgui/sharpenedge.cc index 9d6466543..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 diff --git a/rtgui/sharpenedge.h b/rtgui/sharpenedge.h index a08c63b8a..a813d86e1 100644 --- a/rtgui/sharpenedge.h +++ b/rtgui/sharpenedge.h @@ -14,21 +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 . * * * Manuel Llorens' algorithm of edge sharpening * * */ -#ifndef _SHARPENEDGE_H_ -#define _SHARPENEDGE_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -class SharpenEdge : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class SharpenEdge final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -56,5 +59,3 @@ public: void chanthree_toggled (); }; - -#endif diff --git a/rtgui/sharpening.cc b/rtgui/sharpening.cc index e698872dd..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" diff --git a/rtgui/sharpening.h b/rtgui/sharpening.h index b9f093aae..bd5e6f1b7 100644 --- a/rtgui/sharpening.h +++ b/rtgui/sharpening.h @@ -14,17 +14,21 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include + #include "adjuster.h" #include "thresholdadjuster.h" #include "toolpanel.h" -class Sharpening : public ToolParamBlock, public ThresholdAdjusterListener, public AdjusterListener, public FoldableToolPanel +class Sharpening final: + public ToolParamBlock, + public ThresholdAdjusterListener, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -82,5 +86,3 @@ public: void setAdjusterBehavior (bool contrastadd, bool radiusadd, bool amountadd, bool dampingadd, bool iteradd, bool edgetoladd, bool haloctrladd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; - -#endif diff --git a/rtgui/sharpenmicro.cc b/rtgui/sharpenmicro.cc index 1d765652b..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 diff --git a/rtgui/sharpenmicro.h b/rtgui/sharpenmicro.h index 8cb95b806..23224dd60 100644 --- a/rtgui/sharpenmicro.h +++ b/rtgui/sharpenmicro.h @@ -14,21 +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 . * * * Manuel Llorens' algorithm of micro-contrast sharpening * * */ -#ifndef _SHARPENMICRO_H_ -#define _SHARPENMICRO_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -class SharpenMicro : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class SharpenMicro final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -60,5 +63,3 @@ public: }; - -#endif diff --git a/rtgui/shcselector.cc b/rtgui/shcselector.cc index d55ce30fd..e8aca4071 100644 --- a/rtgui/shcselector.cc +++ b/rtgui/shcselector.cc @@ -14,12 +14,15 @@ * GNU General Public License for more details. * * 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 "shcselector.h" #include "multilangmgr.h" #include "mycurve.h" +#include "rtscalable.h" SHCSelector::SHCSelector() : movingPosition(-1), tmpX(0.0), tmpPos(0.0), wslider(0.0), cl(nullptr), coloredBar(RTO_Left2Right) { diff --git a/rtgui/shcselector.h b/rtgui/shcselector.h index ac6c8afed..e03ca8e06 100644 --- a/rtgui/shcselector.h +++ b/rtgui/shcselector.h @@ -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 . */ -#ifndef _SHCSELECTOR_ -#define _SHCSELECTOR_ +#pragma once #include + #include "coloredbar.h" class SHCListener @@ -29,7 +29,7 @@ public: virtual void shcChanged() = 0; }; -class SHCSelector : public Gtk::DrawingArea, BackBuffer +class SHCSelector final : public Gtk::DrawingArea, BackBuffer { protected: @@ -82,6 +82,3 @@ public: bool reset (); void refresh(); }; - -#endif - diff --git a/rtgui/softlight.cc b/rtgui/softlight.cc index 90c3890cd..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 diff --git a/rtgui/softlight.h b/rtgui/softlight.h index f6ed8370d..710da4e34 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 @@ -23,7 +23,7 @@ #include "adjuster.h" #include "toolpanel.h" -class SoftLight: public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class SoftLight final : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { private: Adjuster *strength; 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..5eb6883e0 100644 --- a/rtgui/soundman.h +++ b/rtgui/soundman.h @@ -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 . * */ - -#ifndef _SOUNDMAN_ -#define _SOUNDMAN_ +#pragma once namespace Glib { + class ustring; + } class SoundManager @@ -32,5 +32,3 @@ public: static void init(); static void playSoundAsync(const Glib::ustring &sound); }; - -#endif 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..bc63cef91 100644 --- a/rtgui/splash.h +++ b/rtgui/splash.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 . */ -#ifndef __SPLASH__ -#define __SPLASH__ +#pragma once #include -class SplashImage : public Gtk::DrawingArea +class SplashImage final : + public Gtk::DrawingArea { private: @@ -39,7 +39,7 @@ public: }; //class Splash : public Gtk::Window { -class Splash : public Gtk::Dialog +class Splash final : public Gtk::Dialog { private: @@ -59,5 +59,3 @@ public: //virtual bool on_button_release_event (GdkEventButton* event); void closePressed(); }; - -#endif 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..eae4a9ad2 100644 --- a/rtgui/threadutils.h +++ b/rtgui/threadutils.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 _THREADUTILS_ -#define _THREADUTILS_ +#pragma once // Uncomment this if you want to bypass the CMakeList options and force the values, but do not commit! //#undef TRACE_MYRWMUTEX @@ -307,5 +306,3 @@ inline MyWriterLock::~MyWriterLock () #define MYREADERLOCK_RELEASE(ln) ln.release(); #define MYWRITERLOCK_RELEASE(ln) ln.release(); #endif - -#endif /* _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..b28f68dee 100644 --- a/rtgui/thresholdadjuster.h +++ b/rtgui/thresholdadjuster.h @@ -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 . */ -#ifndef _THRESHOLDADJUSTER_H_ -#define _THRESHOLDADJUSTER_H_ +#pragma once #include + #include "editedstate.h" #include "guiutils.h" #include "thresholdselector.h" @@ -160,5 +160,3 @@ public: // this set_tooltip_text method is to set_tooltip_markup, and text can contain markups void set_tooltip_text(const Glib::ustring& text); }; - -#endif diff --git a/rtgui/thresholdselector.cc b/rtgui/thresholdselector.cc index e1e6fc36f..35d08279c 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 @@ -24,13 +24,14 @@ #include "multilangmgr.h" #include "mycurve.h" +#include "rtscalable.h" #include "../rtengine/procparams.h" 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 +41,6 @@ ThresholdSelector::ThresholdSelector(double minValueBottom, double maxValueBotto this->precisionBottom = precisionBottom; doubleThresh = false; - separatedLabelBottom = labelBottom; - separatedLabelTop = labelTop; bgCurveProvider = curveProvider; separatedSliders = true; @@ -66,9 +65,6 @@ ThresholdSelector::ThresholdSelector(double minValue, double maxValue, double de this->precisionBottom = precision; doubleThresh = false; - separatedLabelBottom = ""; - separatedLabelTop = ""; - #ifndef NDEBUG if (startAtOne) { @@ -106,9 +102,6 @@ ThresholdSelector::ThresholdSelector(double minValue, double maxValue, double de this->precisionBottom = precision; doubleThresh = true; - separatedLabelBottom = ""; - separatedLabelTop = ""; - #ifndef NDEBUG if (startAtOne) { @@ -329,14 +322,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 +630,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 +644,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..4ae86560e 100644 --- a/rtgui/thresholdselector.h +++ b/rtgui/thresholdselector.h @@ -14,16 +14,17 @@ * GNU General Public License for more details. * * 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_ +#pragma once -#include "guiutils.h" -#include "../rtengine/procparams.h" -#include "coloredbar.h" #include +#include "coloredbar.h" +#include "guiutils.h" + +#include "../rtengine/procparams.h" + class ThresholdSelector; /* @@ -112,10 +113,10 @@ protected: void updateBackBuffer(); Gtk::SizeRequestMode get_request_mode_vfunc () const override; - void get_preferred_height_vfunc (int& minimum_height, int& natural_height) const override; - void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const override; - void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const override; - void get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const override; + void get_preferred_height_vfunc (int& minimum_height, int& natural_height) const final; + void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const final; + void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const final; + void get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const final; void on_realize () override; bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override; bool on_button_press_event (GdkEventButton* event) override; @@ -245,6 +246,3 @@ inline void ThresholdSelector::getPositions (Glib::ustring& botto bottomRight = Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), shapePositionValue(TS_BOTTOMRIGHT)); topRight = Glib::ustring::format(std::fixed, std::setprecision(precisionTop), shapePositionValue(TS_TOPRIGHT)); } - -#endif - diff --git a/rtgui/thumbbrowserbase.cc b/rtgui/thumbbrowserbase.cc index 20a7d3e44..c611b252d 100644 --- a/rtgui/thumbbrowserbase.cc +++ b/rtgui/thumbbrowserbase.cc @@ -12,23 +12,25 @@ * GNU General Public License for more details. * * 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 +#include "inspector.h" #include "multilangmgr.h" #include "options.h" +#include "rtscalable.h" #include "thumbbrowserbase.h" +#include "thumbbrowserentrybase.h" -#include "../rtengine/mytime.h" #include "../rtengine/rt_math.h" using namespace std; ThumbBrowserBase::ThumbBrowserBase () - : location(THLOC_FILEBROWSER), inspector(nullptr), isInspectorActive(false), eventTime(0), lastClicked(nullptr), anchor(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 +46,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,16 +81,34 @@ 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; + double scroll_unit; + if (arrangement == TB_Vertical) { + scroll_unit = vscroll.get_adjustment()->get_step_increment(); + } else { + scroll_unit = hscroll.get_adjustment()->get_step_increment(); + } + if(direction == GDK_SCROLL_SMOOTH) { +#ifdef GDK_WINDOWING_QUARTZ + scroll_unit = 1.0; +#endif + 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) { if (arrangement == TB_Vertical) { double currValue = vscroll.get_value(); - double newValue = rtengine::LIM(currValue + coef * vscroll.get_adjustment()->get_step_increment(), + double newValue = rtengine::LIM(currValue + coef * scroll_unit, vscroll.get_adjustment()->get_lower (), vscroll.get_adjustment()->get_upper()); if (newValue != currValue) { @@ -94,7 +116,7 @@ void ThumbBrowserBase::scroll (int direction, double deltaX, double deltaY) } } else { double currValue = hscroll.get_value(); - double newValue = rtengine::LIM(currValue + coef * hscroll.get_adjustment()->get_step_increment(), + double newValue = rtengine::LIM(currValue + coef * scroll_unit, hscroll.get_adjustment()->get_lower(), hscroll.get_adjustment()->get_upper()); if (newValue != currValue) { @@ -223,21 +245,21 @@ void ThumbBrowserBase::selectSet (ThumbBrowserEntryBase* 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; } } @@ -545,7 +567,6 @@ void ThumbBrowserBase::configScrollBars () auto ha = hscroll.get_adjustment(); int iw = internal.get_width(); ha->set_upper(inW); - ha->set_lower(0); ha->set_step_increment(!fd.empty() ? fd[0]->getEffectiveWidth() : 0); ha->set_page_increment(iw); ha->set_page_size(iw); @@ -560,7 +581,6 @@ void ThumbBrowserBase::configScrollBars () auto va = vscroll.get_adjustment(); va->set_upper(inH); - va->set_lower(0); const auto height = !fd.empty() ? fd[0]->getEffectiveHeight() : 0; va->set_step_increment(height); va->set_page_increment(height == 0 ? ih : (ih / height) * height); @@ -574,8 +594,22 @@ void ThumbBrowserBase::configScrollBars () } } -void ThumbBrowserBase::arrangeFiles(bool checkfilter) +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. @@ -583,17 +617,22 @@ void ThumbBrowserBase::arrangeFiles(bool checkfilter) //GThreadLock lock; int rowHeight = 0; - for (const auto entry : fd) { - if (checkfilter) { - // apply filter - entry->filtered = !checkFilter(entry); - } + if (entry) { + // we got the reference to the added entry, makes calculation of rowHeight O(1) + lastRowHeight = rowHeight = std::max(lastRowHeight, entry->getMinimalHeight()); + } else { - // compute size of the items - if (!entry->filtered) { - rowHeight = std::max(entry->getMinimalHeight(), rowHeight); + 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); + } } } + if (arrangement == TB_Horizontal) { numOfCols = 1; @@ -601,7 +640,6 @@ void ThumbBrowserBase::arrangeFiles(bool checkfilter) 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; @@ -610,10 +648,9 @@ void ThumbBrowserBase::arrangeFiles(bool checkfilter) 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; } } @@ -624,14 +661,16 @@ void ThumbBrowserBase::arrangeFiles(bool checkfilter) 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; } } @@ -667,8 +706,73 @@ void ThumbBrowserBase::arrangeFiles(bool checkfilter) // 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; @@ -691,7 +795,7 @@ void ThumbBrowserBase::arrangeFiles(bool checkfilter) MYREADERLOCK_RELEASE(l); // This will require a Writer access - resizeThumbnailArea (colsWidth, curry); + resizeThumbnailArea(colsWidth, curry); } } @@ -779,7 +883,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"); } @@ -873,7 +976,7 @@ void ThumbBrowserBase::buttonPressed (int x, int y, int button, GdkEventType typ } MYWRITERLOCK_RELEASE(l); - rightClicked (fileDescr); + rightClicked (); } } // end of MYWRITERLOCK(l, entryRW); @@ -985,11 +1088,11 @@ bool ThumbBrowserBase::Internal::on_scroll_event (GdkEventScroll* event) } -void ThumbBrowserBase::redraw (bool checkfilter) +void ThumbBrowserBase::redraw (ThumbBrowserEntryBase* entry) { GThreadLock lock; - arrangeFiles(checkfilter); + arrangeFiles(entry); queue_draw(); } diff --git a/rtgui/thumbbrowserbase.h b/rtgui/thumbbrowserbase.h index 953ec44ec..69017b183 100644 --- a/rtgui/thumbbrowserbase.h +++ b/rtgui/thumbbrowserbase.h @@ -14,25 +14,30 @@ * GNU General Public License for more details. * * 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_ +#pragma once + +#include #include -#include "thumbbrowserentrybase.h" -#include -#include "options.h" + #include "guiutils.h" -#include "inspector.h" +#include "options.h" /* * Class handling the list of ThumbBrowserEntry objects and their position in it's allocated space */ -class ThumbBrowserBase : public Gtk::Grid + +class Inspector; +class ThumbBrowserEntryBase; + +class ThumbBrowserBase : + public Gtk::Grid { - class Internal : public Gtk::DrawingArea + class Internal : + public Gtk::DrawingArea { //Cairo::RefPtr cc; int ofsX, ofsY; @@ -55,10 +60,10 @@ class ThumbBrowserBase : public Gtk::Grid bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override; Gtk::SizeRequestMode get_request_mode_vfunc () const override; - void get_preferred_height_vfunc (int &minimum_height, int &natural_height) const override; - void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const override; - void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const override; - void get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const override; + void get_preferred_height_vfunc (int &minimum_height, int &natural_height) const final; + void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const final; + void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const final; + void get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const final; bool on_button_press_event (GdkEventButton* event) override; bool on_button_release_event (GdkEventButton* event) override; @@ -175,12 +180,13 @@ protected: int previewHeight; int numOfCols; + int lastRowHeight; Arrangement arrangement; std::set editedFiles; - void arrangeFiles (bool checkfilter = true); + void arrangeFiles (ThumbBrowserEntryBase* entry = nullptr); void zoomChanged (bool zoomIn); public: @@ -202,7 +208,7 @@ public: return fd; } void on_style_updated () override; - void redraw (bool checkfilter = true); // 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); @@ -215,11 +221,11 @@ 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; } - virtual void rightClicked (ThumbBrowserEntryBase* entry) {} + virtual void rightClicked () = 0; virtual void doubleClicked (ThumbBrowserEntryBase* entry) {} virtual bool keyPressed (GdkEventKey* event) { @@ -252,5 +258,3 @@ public: } }; - -#endif diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index e660e794b..3840c8bf9 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -14,14 +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 "thumbbrowserentrybase.h" #include "options.h" #include "thumbbrowserbase.h" - -#include "../rtengine/mytime.h" +#include "../rtengine/rt_math.h" namespace { @@ -494,6 +493,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; @@ -555,9 +555,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 diff --git a/rtgui/thumbbrowserentrybase.h b/rtgui/thumbbrowserentrybase.h index 6cbcb37d0..dbc6cf73e 100644 --- a/rtgui/thumbbrowserentrybase.h +++ b/rtgui/thumbbrowserentrybase.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 @@ -26,8 +26,10 @@ #include "guiutils.h" #include "lwbuttonset.h" #include "threadutils.h" -#include "thumbnail.h" +#include "../rtengine/coord2d.h" + +class Thumbnail; class ThumbBrowserBase; class ThumbBrowserEntryBase { diff --git a/rtgui/thumbimageupdater.cc b/rtgui/thumbimageupdater.cc index c0df751a5..03606bb3d 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 @@ -23,9 +23,11 @@ #include #include "thumbimageupdater.h" +#include "thumbbrowserentrybase.h" #include "guiutils.h" #include "threadutils.h" +#include "thumbnail.h" #include "../rtengine/procparams.h" diff --git a/rtgui/thumbimageupdater.h b/rtgui/thumbimageupdater.h index a3be44d7c..a2e2ecb19 100644 --- a/rtgui/thumbimageupdater.h +++ b/rtgui/thumbimageupdater.h @@ -14,18 +14,29 @@ * GNU General Public License for more details. * * 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_ +#pragma once -#include #include -#include "../rtengine/rtengine.h" + #include "../rtengine/noncopyable.h" -#include "thumbbrowserentrybase.h" +namespace rtengine +{ + class IImage8; + +namespace procparams +{ + + struct CropParams; + +} + +} + +class ThumbBrowserEntryBase; class ThumbImageUpdateListener { @@ -101,5 +112,3 @@ private: * To use: \c thumbImageUpdater->start() , */ #define thumbImageUpdater ThumbImageUpdater::getInstance() - -#endif diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index a33b41fd4..bf043cf82 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -13,27 +13,35 @@ * GNU General Public License for more details. * * 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 WIN32 +#include +#endif + +#include "cachemanager.h" #include "multilangmgr.h" #include "thumbnail.h" #include #include -#include "options.h" -#include "../rtengine/mytime.h" #include #include -#include +#include "../rtengine/colortemp.h" #include "../rtengine/imagedata.h" #include "../rtengine/procparams.h" +#include "../rtengine/rtthumbnail.h" #include #include "../rtengine/dynamicprofile.h" +#include "../rtengine/profilestore.h" +#include "../rtengine/settings.h" +#include "../rtexif/rtexif.h" #include "guiutils.h" #include "batchqueue.h" #include "extprog.h" -#include "profilestorecombobox.h" #include "md5helper.h" +#include "pathutils.h" +#include "paramsedited.h" #include "procparamchangers.h" using namespace rtengine::procparams; @@ -233,8 +241,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; @@ -286,6 +292,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu imageMetaData = rtengine::FramesMetaData::fromFile (fname, nullptr, true); } + 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++)) ); const rtexif::TagDirectory* exifDir = nullptr; @@ -301,7 +308,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu // For the filename etc. do NOT use streams, since they are not UTF8 safe Glib::ustring cmdLine = options.CPBPath + Glib::ustring(" \"") + tmpFileName + Glib::ustring("\""); - if (options.rtSettings.verbose) { + if (rtengine::settings->verbose) { printf("Custom profile builder's command line: %s\n", Glib::ustring(cmdLine).c_str()); } @@ -335,34 +342,31 @@ void Thumbnail::notifylisterners_procParamsChanged(int whoChangedIt) * the Preferences). * * The result is a complete ProcParams with default values merged with the values - * from the default Raw or Image ProcParams, then with the values from the loaded - * ProcParams (sidecar or cache file). - */ + * from the loaded ProcParams (sidecar or cache file). +*/ void Thumbnail::loadProcParams () { MyMutex::MyLock lock(mutex); pparamsValid = false; pparams->setDefaults(); - const PartialProfile *defaultPP = ProfileStore::getInstance()->getDefaultPartialProfile(getType() == FT_Raw); - defaultPP->applyTo(pparams.get()); if (options.paramsLoadLocation == PLL_Input) { // try to load it from params file next to the image file - int ppres = pparams->load (fname + paramFileExtension); + const int ppres = pparams->load(fname + paramFileExtension); pparamsValid = !ppres && pparams->ppVersion >= 220; // if no success, try to load the cached version of the procparams if (!pparamsValid) { - pparamsValid = !pparams->load (getCacheFileName ("profiles", paramFileExtension)); + pparamsValid = !pparams->load(getCacheFileName("profiles", paramFileExtension)); } } else { // try to load it from cache - pparamsValid = !pparams->load (getCacheFileName ("profiles", paramFileExtension)); + pparamsValid = !pparams->load(getCacheFileName("profiles", paramFileExtension)); // if no success, try to load it from params file next to the image file if (!pparamsValid) { - int ppres = pparams->load (fname + paramFileExtension); + const int ppres = pparams->load(fname + paramFileExtension); pparamsValid = !ppres && pparams->ppVersion >= 220; } } @@ -476,6 +480,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; @@ -584,10 +589,8 @@ void Thumbnail::decreaseRef () cachemgr->closeThumbnail (this); } -void Thumbnail::getThumbnailSize (int &w, int &h, const rtengine::procparams::ProcParams *pparams) +int Thumbnail::getThumbnailWidth (const int h, const rtengine::procparams::ProcParams *pparams) const { - MyMutex::MyLock lock(mutex); - int tw_ = tw; int th_ = th; float imgRatio_ = imgRatio; @@ -607,20 +610,17 @@ void Thumbnail::getThumbnailSize (int &w, int &h, const rtengine::procparams::Pr if (thisCoarse != ppCoarse) { // different orientation -> swapping width & height - int tmp = th_; - th_ = tw_; - tw_ = tmp; - + std::swap(th_, tw_); if (imgRatio_ >= 0.0001f) { imgRatio_ = 1.f / imgRatio_; } } } - if (imgRatio_ > 0.) { - w = (int)(imgRatio_ * (float)h); + if (imgRatio_ > 0.f) { + return imgRatio_ * h; } else { - w = tw_ * h / th_; + return tw_ * h / th_; } } @@ -1021,9 +1021,7 @@ int Thumbnail::getRank () const void Thumbnail::setRank (int rank) { - if (pparams->rank != rank) { - pparams->rank = rank; - } + pparams->rank = rank; pparamsValid = true; } @@ -1154,3 +1152,48 @@ bool Thumbnail::imageLoad(bool loading) return false; } + +void Thumbnail::getCamWB(double& temp, double& green) const +{ + if (tpp) { + tpp->getCamWB (temp, green); + } else { + temp = green = -1.0; + } +} + +void Thumbnail::getSpotWB(int x, int y, int rect, double& temp, double& green) +{ + if (tpp) { + tpp->getSpotWB (getProcParams(), x, y, rect, temp, green); + } else { + temp = green = -1.0; + } +} + +void Thumbnail::applyAutoExp (rtengine::procparams::ProcParams& pparams) +{ + if (tpp) { + tpp->applyAutoExp (pparams); + } +} + +const CacheImageData* Thumbnail::getCacheImageData() +{ + return &cfs; +} + +std::string Thumbnail::getMD5() const +{ + return cfs.md5; +} + +bool Thumbnail::isQuick() const +{ + return cfs.thumbImgType == CacheImageData::QUICK_THUMBNAIL; +} + +bool Thumbnail::isPParamsValid() const +{ + return pparamsValid; +} diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index 0bcdd470a..c22c80cea 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -14,24 +14,33 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include #include -#include -#include "cachemanager.h" -#include "options.h" -#include "../rtengine/rtengine.h" -#include "../rtengine/rtthumbnail.h" -#include "cacheimagedata.h" -#include "thumbnaillistener.h" -#include "threadutils.h" +#include +#include "cacheimagedata.h" +#include "threadutils.h" +#include "thumbnaillistener.h" + +namespace rtengine +{ +class Thumbnail; + +namespace procparams +{ + +class ProcParams; + +} + +} class CacheManager; + struct ParamsEdited; class Thumbnail @@ -49,17 +58,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; @@ -97,14 +106,8 @@ public: void notifylisterners_procParamsChanged(int whoChangedIt); - bool isQuick() const - { - return cfs.thumbImgType == CacheImageData::QUICK_THUMBNAIL; - } - bool isPParamsValid() const - { - return pparamsValid; - } + bool isQuick() const; + bool isPParamsValid() const; bool isRecentlySaved () const; void imageDeveloped (); void imageEnqueued (); @@ -116,35 +119,16 @@ public: // unsigned char* getThumbnailImage (int &w, int &h, int fixwh=1); // fixwh = 0: fix w and calculate h, =1: fix h and calculate w rtengine::IImage8* processThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale); rtengine::IImage8* upgradeThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale); - void getThumbnailSize (int &w, int &h, const rtengine::procparams::ProcParams *pparams = nullptr); + int getThumbnailWidth (int h, const rtengine::procparams::ProcParams *pparams = nullptr) const; void getFinalSize (const rtengine::procparams::ProcParams& pparams, int& w, int& h); void getOriginalSize (int& w, int& h); const Glib::ustring& getExifString () const; const Glib::ustring& getDateTimeString () const; - void getCamWB (double& temp, double& green) const - { - if (tpp) { - tpp->getCamWB (temp, green); - } else { - temp = green = -1.0; - } - } + void getCamWB (double& temp, double& green) const; void getAutoWB (double& temp, double& green, double equal, double tempBias); - void getSpotWB (int x, int y, int rect, double& temp, double& green) - { - if (tpp) { - tpp->getSpotWB (getProcParams(), x, y, rect, temp, green); - } else { - temp = green = -1.0; - } - } - void applyAutoExp (rtengine::procparams::ProcParams& pparams) - { - if (tpp) { - tpp->applyAutoExp (pparams); - } - } + void getSpotWB (int x, int y, int rect, double& temp, double& green); + void applyAutoExp (rtengine::procparams::ProcParams& pparams); ThFileType getType (); Glib::ustring getFileName () const @@ -155,14 +139,8 @@ public: bool isSupported (); - const CacheImageData* getCacheImageData() - { - return &cfs; - } - std::string getMD5 () const - { - return cfs.md5; - } + const CacheImageData* getCacheImageData(); + std::string getMD5 () const; int getRank () const; void setRank (int rank); @@ -185,7 +163,3 @@ public: bool openDefaultViewer(int destination); bool imageLoad(bool loading); }; - - -#endif - diff --git a/rtgui/thumbnailbrowser.h b/rtgui/thumbnailbrowser.h deleted file mode 100644 index 0c2d6ebab..000000000 --- a/rtgui/thumbnailbrowser.h +++ /dev/null @@ -1,101 +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 . - */ -#ifndef _THUMBNAILBROWSER_ -#define _THUMBNAILBROWSER_ - -#include -#include "thumbnail.h" -#include "filecatalog.h" - -class ThumbBrowserEntry -{ - -public: -// set by arrangeFiles(): - int width; // minimal width - int height; // minimal height - int exp_width; // ararnged width - int startx; // x coord. in the widget - int starty; // y coord. in the widget -// thumbnail preview properties: - int prew; // width of the thumbnail - int preh; // height of the thumbnail - guint8* preview; -// file and directory attributes: - Glib::ustring filename; - Glib::ustring shortname; - Glib::ustring dirname; -// the associated thumbnail instance: - Thumbnail* thumbnail; - - ThumbBrowserEntry (Thumbnail* thm, Glib::ustring fname, Glib::ustring sname, Glib::ustring dname, int h) - : thumbnail(thm), filename(fname), shortname(sname), dirname(dname), preh(h) - { - preview = thumbnail ? (guint8*) thumbnail->getThumbnailImage (prew, preh) : NULL; - } - - bool operator< (FileDescr& other) - { - return shortname > other.shortname; - } -}; - -class ThumbBrowser : public Gtk::DrawingArea -{ - -protected: - int dx, dy, w, h; - - Gdk::RGBA black; - Gdk::RGBA white; - Gdk::RGBA blue; - Gdk::RGBA bluew; - - std::vector fd; - std::vector selected; - - int rowHeight; - int numOfRows; - - ThumbBrowserListener* tbl; - - void arrangeFiles (int rows); - -public: - - ThumbBrowser (); - - void addEntry (ThumbBrowserEntry* entry); - void setThumbBrowserListener (ThumbBrowserListener* l) - { - tbl = l; - } - - virtual void on_realize(); - virtual bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr); - virtual bool on_button_press_event (GdkEventButton* event); - virtual bool on_button_release_event (GdkEventButton* event); - virtual void previewReady (FileDescr* fdn); - - void resized (Gtk::Allocation& req); - void redraw (); - void styleChanged (const Glib::RefPtr& style); -}; - -#endif diff --git a/rtgui/thumbnaillistener.h b/rtgui/thumbnaillistener.h index 99a9a9286..18ac99dce 100644 --- a/rtgui/thumbnaillistener.h +++ b/rtgui/thumbnaillistener.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 _THUMBNAILLISTENER_ -#define _THUMBNAILLISTENER_ +#pragma once class Thumbnail; @@ -27,6 +26,3 @@ public: virtual ~ThumbnailListener() = default; virtual void procParamsChanged(Thumbnail* thm, int whoChangedIt) = 0; }; - -#endif - diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc index e0e475b4e..dc9b17fa9 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 @@ -23,10 +23,14 @@ #include "tonecurve.h" #include "adjuster.h" +#include "curveeditor.h" +#include "curveeditorgroup.h" #include "eventmapper.h" #include "ppversion.h" +#include "options.h" #include "../rtengine/procparams.h" +#include "../rtengine/utils.h" #include "editcallbacks.h" using namespace rtengine; diff --git a/rtgui/tonecurve.h b/rtgui/tonecurve.h index 512dd4d5f..e0482c5da 100644 --- a/rtgui/tonecurve.h +++ b/rtgui/tonecurve.h @@ -14,22 +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 _TONECURVE_H_ -#define _TONECURVE_H_ +#pragma once #include -#include "adjuster.h" -#include "toolpanel.h" -#include "curveeditor.h" -#include "curveeditorgroup.h" -#include "mycurve.h" -#include "guiutils.h" +#include "adjuster.h" +#include "curvelistener.h" +#include "guiutils.h" +#include "toolpanel.h" + +class CurveEditor; +class CurveEditorGroup; +class DiagonalCurveEditor; class EditDataProvider; -class ToneCurve : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoExpListener, public CurveListener +class ToneCurve final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public rtengine::AutoExpListener, + public CurveListener { private: IdleRegister idle_register; @@ -141,5 +147,3 @@ public: void methodChanged (); void clampOOGChanged(); }; - -#endif diff --git a/rtgui/toolbar.cc b/rtgui/toolbar.cc index f0a08b263..e642ae51b 100644 --- a/rtgui/toolbar.cc +++ b/rtgui/toolbar.cc @@ -15,11 +15,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 "toolbar.h" #include "multilangmgr.h" #include "guiutils.h" +#include "lockablecolorpicker.h" +#include "rtimage.h" ToolBar::ToolBar () : showColPickers(true), listener (nullptr), pickerListener(nullptr) { diff --git a/rtgui/toolbar.h b/rtgui/toolbar.h index b86aff6ca..c4ec4977b 100644 --- a/rtgui/toolbar.h +++ b/rtgui/toolbar.h @@ -14,15 +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 . */ -#ifndef __TOOLBAR_H__ -#define __TOOLBAR_H__ +#pragma once #include + #include "toolenum.h" -#include "rtimage.h" -#include "lockablecolorpicker.h" + +class RTImage; +class LockablePickerToolListener; class ToolBarListener { @@ -36,7 +37,7 @@ public: virtual void editModeSwitchedOff() = 0; }; -class ToolBar : public Gtk::HBox +class ToolBar final : public Gtk::HBox { private: std::unique_ptr handimg; @@ -105,5 +106,3 @@ public: blockEdit = cond; } }; - -#endif diff --git a/rtgui/toolenum.h b/rtgui/toolenum.h index 85a7b954a..c3bc873f1 100644 --- a/rtgui/toolenum.h +++ b/rtgui/toolenum.h @@ -14,11 +14,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 . */ -#ifndef _TOOLENUM_ -#define _TOOLENUM_ +#pragma once enum ToolMode {TMNone = -1, TMHand = 0, TMSpotWB = 1, TMCropSelect = 2, TMStraighten = 3, TMColorPicker = 4}; - -#endif diff --git a/rtgui/toolpanel.cc b/rtgui/toolpanel.cc index 1fe9808cd..b1282f523 100644 --- a/rtgui/toolpanel.cc +++ b/rtgui/toolpanel.cc @@ -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 . */ #include "toolpanel.h" #include "toolpanelcoord.h" #include "guiutils.h" +#include "rtimage.h" #include "../rtengine/procparams.h" diff --git a/rtgui/toolpanel.h b/rtgui/toolpanel.h index 2da5f1bba..12b3eebcc 100644 --- a/rtgui/toolpanel.h +++ b/rtgui/toolpanel.h @@ -14,21 +14,31 @@ * GNU General Public License for more details. * * 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__ +#pragma once #include -#include -#include "../rtengine/rtengine.h" -#include "editbuffer.h" + +#include + #include "guiutils.h" #include "multilangmgr.h" #include "paramsedited.h" -class ToolPanel; -class FoldableToolPanel; +#include "../rtengine/noncopyable.h" +#include "../rtengine/rtengine.h" + +namespace rtengine +{ + class ProcEvent; + +namespace procparams +{ + +class ProcParams; +} +} class ToolPanelListener { @@ -38,20 +48,23 @@ public: }; /// @brief This class control the space around the group of tools inside a tab, as well as the space separating each tool. */ -class ToolVBox : public Gtk::VBox +class ToolVBox : + public Gtk::VBox { public: ToolVBox(); }; /// @brief This class control the space around a tool's block of parameter. */ -class ToolParamBlock : public Gtk::VBox +class ToolParamBlock : + public Gtk::VBox { public: ToolParamBlock(); }; -class ToolPanel +class ToolPanel : + public rtengine::NonCopyable { protected: @@ -130,12 +143,13 @@ public: this->batchMode = batchMode; } - virtual Glib::ustring getToolName () { + Glib::ustring getToolName () { return toolName; } }; -class FoldableToolPanel : public ToolPanel +class FoldableToolPanel : + public ToolPanel { protected: @@ -150,11 +164,11 @@ public: FoldableToolPanel(Gtk::Box* content, Glib::ustring toolName, Glib::ustring UILabel, bool need11 = false, bool useEnabled = false); - MyExpander* getExpander() override + MyExpander* getExpander() final { return exp; } - void setExpanded (bool expanded) override + void setExpanded (bool expanded) final { if (exp) { exp->set_expanded( expanded ); @@ -172,7 +186,7 @@ public: exp->show(); } } - bool getExpanded () override + bool getExpanded () final { if (exp) { return exp->get_expanded(); @@ -180,11 +194,11 @@ public: return false; } - void setParent (Gtk::Box* parent) override + void setParent (Gtk::Box* parent) final { parentContainer = parent; } - Gtk::Box* getParent () override + Gtk::Box* getParent () final { return parentContainer; } @@ -217,5 +231,3 @@ public: return exp->signal_enabled_toggled(); } }; - -#endif diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index a22283abd..9e15db5e0 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -14,11 +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 . */ #include "multilangmgr.h" #include "toolpanelcoord.h" +#include "metadatapanel.h" #include "options.h" +#include "rtimage.h" + #include "../rtengine/imagesource.h" #include "../rtengine/dfmanager.h" #include "../rtengine/ffmanager.h" @@ -95,7 +98,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit 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 @@ -160,6 +163,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit addfavoritePanel (rawPanel, darkframe); addfavoritePanel (rawPanel, flatfield); addfavoritePanel (rawPanel, filmNegative); + addfavoritePanel (rawPanel, pdSharpening); int favoriteCount = 0; for(auto it = favorites.begin(); it != favorites.end(); ++it) { @@ -181,7 +185,6 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit rawPanelSW = Gtk::manage (new MyScrolledWindow ()); advancedPanelSW = Gtk::manage (new MyScrolledWindow ()); locallabPanelSW = Gtk::manage(new MyScrolledWindow()); - updateVScrollbars (options.hideTPVScrollbar); // load panel endings for (int i = 0; i < 8; i++) { @@ -197,6 +200,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit favoritePanel->pack_start(*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK, 0); favoritePanel->pack_start(*vbPanelEnd[0], Gtk::PACK_SHRINK, 4); } + updateVScrollbars(options.hideTPVScrollbar); exposurePanelSW->add (*exposurePanel); exposurePanel->pack_start (*Gtk::manage (new Gtk::HSeparator), Gtk::PACK_SHRINK, 0); @@ -349,12 +353,17 @@ void ToolPanelCoordinator::imageTypeChanged(bool isRaw, bool isBayer, bool isXtr { rawPanelSW->set_sensitive(true); sensorxtrans->FoldableToolPanel::hide(); + xtransprocess->FoldableToolPanel::hide(); + xtransrawexposure->FoldableToolPanel::hide(); sensorbayer->FoldableToolPanel::show(); + bayerprocess->FoldableToolPanel::show(); + bayerpreprocess->FoldableToolPanel::show(); + rawcacorrection->FoldableToolPanel::show(); preprocess->FoldableToolPanel::show(); flatfield->FoldableToolPanel::show(); filmNegative->FoldableToolPanel::show(); + pdSharpening->FoldableToolPanel::show(); retinex->FoldableToolPanel::setGrayedOut(false); - return false; } ); @@ -364,12 +373,17 @@ void ToolPanelCoordinator::imageTypeChanged(bool isRaw, bool isBayer, bool isXtr { rawPanelSW->set_sensitive(true); sensorxtrans->FoldableToolPanel::show(); + xtransprocess->FoldableToolPanel::show(); + xtransrawexposure->FoldableToolPanel::show(); sensorbayer->FoldableToolPanel::hide(); + bayerprocess->FoldableToolPanel::hide(); + bayerpreprocess->FoldableToolPanel::hide(); + rawcacorrection->FoldableToolPanel::hide(); preprocess->FoldableToolPanel::show(); flatfield->FoldableToolPanel::show(); filmNegative->FoldableToolPanel::show(); + pdSharpening->FoldableToolPanel::show(); retinex->FoldableToolPanel::setGrayedOut(false); - return false; } ); @@ -379,12 +393,17 @@ void ToolPanelCoordinator::imageTypeChanged(bool isRaw, bool isBayer, bool isXtr { rawPanelSW->set_sensitive(true); sensorbayer->FoldableToolPanel::hide(); + bayerprocess->FoldableToolPanel::hide(); + bayerpreprocess->FoldableToolPanel::hide(); + rawcacorrection->FoldableToolPanel::hide(); sensorxtrans->FoldableToolPanel::hide(); + xtransprocess->FoldableToolPanel::hide(); + xtransrawexposure->FoldableToolPanel::hide(); preprocess->FoldableToolPanel::hide(); flatfield->FoldableToolPanel::show(); filmNegative->FoldableToolPanel::hide(); + pdSharpening->FoldableToolPanel::show(); retinex->FoldableToolPanel::setGrayedOut(false); - return false; } ); @@ -394,12 +413,17 @@ void ToolPanelCoordinator::imageTypeChanged(bool isRaw, bool isBayer, bool isXtr { rawPanelSW->set_sensitive(true); sensorbayer->FoldableToolPanel::hide(); + bayerprocess->FoldableToolPanel::hide(); + bayerpreprocess->FoldableToolPanel::hide(); + rawcacorrection->FoldableToolPanel::hide(); sensorxtrans->FoldableToolPanel::hide(); + xtransprocess->FoldableToolPanel::hide(); + xtransrawexposure->FoldableToolPanel::hide(); preprocess->FoldableToolPanel::hide(); flatfield->FoldableToolPanel::hide(); filmNegative->FoldableToolPanel::hide(); + pdSharpening->FoldableToolPanel::hide(); retinex->FoldableToolPanel::setGrayedOut(false); - return false; } ); @@ -409,9 +433,18 @@ void ToolPanelCoordinator::imageTypeChanged(bool isRaw, bool isBayer, bool isXtr [this]() -> bool { rawPanelSW->set_sensitive(false); + sensorbayer->FoldableToolPanel::hide(); + bayerprocess->FoldableToolPanel::hide(); + bayerpreprocess->FoldableToolPanel::hide(); + rawcacorrection->FoldableToolPanel::hide(); + sensorxtrans->FoldableToolPanel::hide(); + xtransprocess->FoldableToolPanel::hide(); + xtransrawexposure->FoldableToolPanel::hide(); + preprocess->FoldableToolPanel::hide(); + flatfield->FoldableToolPanel::hide(); filmNegative->FoldableToolPanel::hide(); + pdSharpening->FoldableToolPanel::hide(); retinex->FoldableToolPanel::setGrayedOut(true); - return false; } ); @@ -485,12 +518,14 @@ void ToolPanelCoordinator::panelChanged(const rtengine::ProcEvent& event, const */ if (event == rtengine::EvlocallabshowmaskMethod) { const Locallab::llMaskVisibility maskStruc = locallab->getMaskVisibility(); - ipc->setLocallabMaskVisibility(maskStruc.colorMask, maskStruc.expMask, - maskStruc.SHMask, maskStruc.cbMask, maskStruc.retiMask, - maskStruc.softMask, maskStruc.tmMask); - } else if (event == rtengine::EvLocallabSpotCreated || event == rtengine::EvLocallabSpotSelectedWithMask || event == rtengine::EvLocallabSpotDeleted) { + ipc->setLocallabMaskVisibility(maskStruc.colorMask, maskStruc.colorMaskinv, maskStruc.expMask, maskStruc.expMaskinv, + maskStruc.SHMask, maskStruc.SHMaskinv, maskStruc.vibMask, maskStruc.softMask, + maskStruc.blMask, maskStruc.tmMask, maskStruc.retiMask, maskStruc.sharMask, + maskStruc.lcMask, maskStruc.cbMask); + } else if (event == rtengine::EvLocallabSpotCreated || event == rtengine::EvLocallabSpotSelectedWithMask || + event == rtengine::EvLocallabSpotDeleted || event == rtengine::Evlocallabshowreset) { locallab->resetMaskVisibility(); - ipc->setLocallabMaskVisibility(0, 0, 0, 0, 0, 0, 0); + ipc->setLocallabMaskVisibility(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } ipc->endUpdateParams(changeFlags); // starts the IPC processing @@ -561,7 +596,7 @@ void ToolPanelCoordinator::profileChange( lParams[1] = *mergedParams; pe.initFrom(lParams); - filterRawRefresh = pe.raw.isUnchanged() && pe.lensProf.isUnchanged() && pe.retinex.isUnchanged() && pe.filmNegative.isUnchanged(); + filterRawRefresh = pe.raw.isUnchanged() && pe.lensProf.isUnchanged() && pe.retinex.isUnchanged() && pe.filmNegative.isUnchanged() && pe.pdsharpening.isUnchanged(); } *params = *mergedParams; @@ -597,7 +632,7 @@ void ToolPanelCoordinator::profileChange( // Reset Locallab mask visibility locallab->resetMaskVisibility(); - ipc->setLocallabMaskVisibility(0, 0, 0, 0, 0, 0, 0); + ipc->setLocallabMaskVisibility(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // start the IPC processing if (filterRawRefresh) { @@ -666,6 +701,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); @@ -792,8 +829,7 @@ void ToolPanelCoordinator::sharpMaskSelected(bool sharpMask) } ipc->beginUpdateParams(); - ipc->setSharpMask(sharpMask); - ipc->endUpdateParams(rtengine::EvShrEnabled); + ipc->endUpdateParams (ipc->setSharpMask(sharpMask)); } int ToolPanelCoordinator::getSpotWBRectSize() const @@ -1025,7 +1061,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; diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index aa5a178be..93c4faee9 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -14,78 +14,82 @@ * GNU General Public License for more details. * * 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__ +#pragma once -#include "../rtengine/rtengine.h" -#include "toolpanel.h" #include -#include "pparamschangelistener.h" -#include "profilechangelistener.h" -#include "imageareatoollistener.h" + #include -#include "whitebalance.h" -#include "coarsepanel.h" -#include "tonecurve.h" -#include "vibrance.h" -#include "colorappearance.h" -#include "shadowshighlights.h" -#include "impulsedenoise.h" -#include "defringe.h" -#include "dirpyrdenoise.h" -#include "epd.h" -#include "sharpening.h" -#include "labcurve.h" -#include "metadatapanel.h" -#include "crop.h" -#include "icmpanel.h" -#include "resize.h" -#include "chmixer.h" -#include "blackwhite.h" -#include "cacorrection.h" -#include "lensprofile.h" -#include "distortion.h" -#include "perspective.h" -#include "rotate.h" -#include "vignetting.h" -#include "retinex.h" -#include "gradient.h" -#include "locallab.h" -#include "pcvignette.h" -#include "toolbar.h" -#include "lensgeom.h" -#include "lensgeomlistener.h" -#include "wavelet.h" -#include "dirpyrequalizer.h" -#include "hsvequalizer.h" -#include "preprocess.h" + #include "bayerpreprocess.h" #include "bayerprocess.h" -#include "xtransprocess.h" +#include "bayerrawexposure.h" +#include "blackwhite.h" +#include "cacorrection.h" +#include "chmixer.h" +#include "coarsepanel.h" +#include "colorappearance.h" +#include "colortoning.h" +#include "crop.h" #include "darkframe.h" +#include "defringe.h" +#include "dehaze.h" +#include "dirpyrdenoise.h" +#include "dirpyrequalizer.h" +#include "distortion.h" +#include "epd.h" +#include "fattaltonemap.h" +#include "filmnegative.h" +#include "filmsimulation.h" #include "flatfield.h" -#include "sensorbayer.h" -#include "sensorxtrans.h" +#include "gradient.h" +#include "guiutils.h" +#include "hsvequalizer.h" +#include "icmpanel.h" +#include "imageareatoollistener.h" +#include "impulsedenoise.h" +#include "labcurve.h" +#include "lensgeom.h" +#include "lensgeomlistener.h" +#include "lensprofile.h" +#include "localcontrast.h" +#include "locallab.h" +#include "pcvignette.h" +#include "pdsharpening.h" +#include "perspective.h" +#include "pparamschangelistener.h" +#include "preprocess.h" +#include "profilechangelistener.h" +#include "prsharpening.h" #include "rawcacorrection.h" #include "rawexposure.h" -#include "bayerrawexposure.h" -#include "xtransrawexposure.h" -#include "sharpenmicro.h" -#include "sharpenedge.h" +#include "resize.h" +#include "retinex.h" #include "rgbcurves.h" -#include "colortoning.h" -#include "filmsimulation.h" -#include "prsharpening.h" -#include "fattaltonemap.h" -#include "localcontrast.h" +#include "rotate.h" +#include "sensorbayer.h" +#include "sensorxtrans.h" +#include "shadowshighlights.h" +#include "sharpenedge.h" +#include "sharpening.h" +#include "sharpenmicro.h" #include "softlight.h" -#include "dehaze.h" -#include "guiutils.h" -#include "filmnegative.h" +#include "tonecurve.h" +#include "toolbar.h" +#include "toolpanel.h" +#include "vibrance.h" +#include "vignetting.h" +#include "wavelet.h" +#include "whitebalance.h" +#include "xtransprocess.h" +#include "xtransrawexposure.h" + +#include "../rtengine/noncopyable.h" +#include "../rtengine/rtengine.h" class ImageEditorCoordinator; +class MetaDataPanel; class ToolPanelCoordinator : public ToolPanelListener, @@ -100,7 +104,8 @@ class ToolPanelCoordinator : public ICMPanelListener, public ImageAreaToolListener, public rtengine::ImageTypeListener, - public FilmNegProvider + public FilmNegProvider, + public rtengine::NonCopyable { protected: WhiteBalance* whitebalance; @@ -157,7 +162,7 @@ protected: FattalToneMapping *fattal; MetaDataPanel* metadata; FilmNegative* filmNegative; - + PdSharpening* pdSharpening; std::vector paramcListeners; rtengine::StagedImageProcessor* ipc; @@ -248,7 +253,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, @@ -319,11 +323,11 @@ public: // imageareatoollistener interface void spotWBselected(int x, int y, Thumbnail* thm = nullptr) override; - void sharpMaskSelected(bool sharpMask) override; + void sharpMaskSelected(bool sharpMask) override final; int getSpotWBRectSize() const override; void cropSelectionReady() override; void rotateSelectionReady(double rotate_deg, Thumbnail* thm = nullptr) override; - ToolBar* getToolBar() const override; + ToolBar* getToolBar() const final; CropGUIListener* startCropEditing(Thumbnail* thm = nullptr) override; void updateTPVScrollbar(bool hide); @@ -331,12 +335,10 @@ public: // ToolBarListener interface void toolSelected (ToolMode tool) override; - void editModeSwitchedOff () override; + void editModeSwitchedOff () final; void setEditProvider(EditDataProvider *provider); private: IdleRegister idle_register; }; - -#endif diff --git a/rtgui/vibrance.cc b/rtgui/vibrance.cc index 82944bb81..4a9fab3d3 100644 --- a/rtgui/vibrance.cc +++ b/rtgui/vibrance.cc @@ -14,10 +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 . */ #include "vibrance.h" + +#include "curveeditor.h" +#include "curveeditorgroup.h" +#include "options.h" #include "../rtengine/color.h" using namespace rtengine; diff --git a/rtgui/vibrance.h b/rtgui/vibrance.h index 81d811f14..12acc7948 100644 --- a/rtgui/vibrance.h +++ b/rtgui/vibrance.h @@ -14,20 +14,27 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include + #include "adjuster.h" +#include "curvelistener.h" #include "thresholdadjuster.h" -#include "curveeditor.h" -#include "curveeditorgroup.h" #include "toolpanel.h" -class Vibrance : public ToolParamBlock, public AdjusterListener, public ThresholdCurveProvider, public ThresholdAdjusterListener, - public FoldableToolPanel, public CurveListener +class CurveEditorGroup; +class DiagonalCurveEditor; + +class Vibrance final : + public ToolParamBlock, + public AdjusterListener, + public ThresholdCurveProvider, + public ThresholdAdjusterListener, + public FoldableToolPanel, + public CurveListener { protected: @@ -76,6 +83,3 @@ public: void pastsattog_toggled (); std::vector getCurvePoints(ThresholdSelector* tAdjuster) const override; }; - - -#endif diff --git a/rtgui/vignetting.cc b/rtgui/vignetting.cc index 87a835625..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" diff --git a/rtgui/vignetting.h b/rtgui/vignetting.h index edd818431..be7765094 100644 --- a/rtgui/vignetting.h +++ b/rtgui/vignetting.h @@ -14,16 +14,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 . */ -#ifndef _VIGNETTING_H_ -#define _VIGNETTING_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -class Vignetting : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class Vignetting final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -46,5 +49,3 @@ public: void setAdjusterBehavior (bool amountadd, bool radiusadd, bool strengthadd, bool centeradd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; - -#endif diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index bc59de087..3981457e6 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 */ @@ -20,13 +20,16 @@ #include "wavelet.h" #include +#include "curveeditor.h" +#include "curveeditorgroup.h" #include "editcallbacks.h" #include "guiutils.h" #include "rtimage.h" +#include "options.h" +#include "../rtengine/color.h" using namespace rtengine; using namespace rtengine::procparams; -extern Options options; namespace { diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h index 4df743fa7..6551b58d4 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 */ @@ -22,16 +22,18 @@ #include #include "adjuster.h" #include "toolpanel.h" -#include "curveeditor.h" -#include "curveeditorgroup.h" +#include "curvelistener.h" #include "thresholdadjuster.h" #include "colorprovider.h" #include "guiutils.h" -#include "options.h" +class CurveEditor; +class CurveEditorGroup; +class DiagonalCurveEditor; class EditDataProvider; +class FlatCurveEditor; -class Wavelet : +class Wavelet final : public ToolParamBlock, public ThresholdAdjusterListener, public AdjusterListener, diff --git a/rtgui/wbprovider.h b/rtgui/wbprovider.h index df1329c84..a56d93cd3 100644 --- a/rtgui/wbprovider.h +++ b/rtgui/wbprovider.h @@ -14,11 +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 _WBPROVIDER_ -#define _WBPROVIDER_ - +#pragma once class WBProvider { @@ -29,5 +27,3 @@ public: virtual void getCamWB (double& temp, double& green) {} virtual void spotWBRequested (int size) {} }; - -#endif diff --git a/rtgui/whitebalance.cc b/rtgui/whitebalance.cc index 761dc5e04..2ab09c10a 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" @@ -55,7 +55,7 @@ void WhiteBalance::init () void WhiteBalance::cleanup () { - for (unsigned int i = 0; i < toUnderlying(WBEntry::Type::CUSTOM) + 1; i++) { + for (int i = 0; i < toUnderlying(WBEntry::Type::CUSTOM) + 1; i++) { wbPixbufs[i].reset(); } } @@ -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); diff --git a/rtgui/whitebalance.h b/rtgui/whitebalance.h index 52c4b7f8c..b4d09f119 100644 --- a/rtgui/whitebalance.h +++ b/rtgui/whitebalance.h @@ -14,17 +14,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 . */ -#ifndef _WB_H_ -#define _WB_H_ +#pragma once #include -#include "toolpanel.h" + #include "adjuster.h" #include "guiutils.h" +#include "toolpanel.h" #include "wbprovider.h" + #include "../rtengine/procparams.h" +#include "../rtengine/utils.h" class SpotWBListener { @@ -33,7 +35,7 @@ public: virtual void spotWBRequested(int size) = 0; }; -class WhiteBalance : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoWBListener +class WhiteBalance final : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoWBListener { enum WB_LabelType { @@ -123,5 +125,3 @@ public: void trimValues (rtengine::procparams::ProcParams* pp) override; void enabledChanged() override; }; - -#endif diff --git a/rtgui/xtransprocess.cc b/rtgui/xtransprocess.cc index 115fa3868..a371bad88 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" @@ -225,7 +225,7 @@ void XTransProcess::adjusterChanged(Adjuster* a, double newval) } } -void XTransProcess::adjusterAutoToggled(Adjuster* a, bool newval) +void XTransProcess::adjusterAutoToggled(Adjuster* a) { if (multiImage) { if (dualDemosaicContrast->getAutoInconsistent()) { diff --git a/rtgui/xtransprocess.h b/rtgui/xtransprocess.h index e5389b566..fc0dd7502 100644 --- a/rtgui/xtransprocess.h +++ b/rtgui/xtransprocess.h @@ -14,19 +14,23 @@ * GNU General Public License for more details. * * 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_ +#pragma once #include + #include "adjuster.h" #include "checkbox.h" #include "guiutils.h" #include "toolpanel.h" - -class XTransProcess : public ToolParamBlock, public AdjusterListener, public CheckBoxListener, public FoldableToolPanel, public rtengine::AutoContrastListener +class XTransProcess final : + public ToolParamBlock, + public AdjusterListener, + public CheckBoxListener, + public FoldableToolPanel, + public rtengine::AutoContrastListener { protected: @@ -62,7 +66,5 @@ public: void autoContrastChanged (double autoContrast) override; void adjusterChanged(Adjuster* a, double newval) override; void checkBoxToggled(CheckBox* c, CheckValue newval) override; - void adjusterAutoToggled(Adjuster* a, bool newval) override; + void adjusterAutoToggled(Adjuster* a) override; }; - -#endif diff --git a/rtgui/xtransrawexposure.cc b/rtgui/xtransrawexposure.cc index c4f7d7059..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 diff --git a/rtgui/xtransrawexposure.h b/rtgui/xtransrawexposure.h index 54b3de767..a8daf6972 100644 --- a/rtgui/xtransrawexposure.h +++ b/rtgui/xtransrawexposure.h @@ -14,17 +14,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 . */ -#ifndef _XTRANSRAWEXPOSURE_H_ -#define _XTRANSRAWEXPOSURE_H_ +#pragma once #include + #include "adjuster.h" #include "toolpanel.h" -#include "../rtengine/rawimage.h" -class XTransRAWExposure : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class XTransRAWExposure final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel { protected: @@ -46,5 +48,3 @@ public: void setAdjusterBehavior (bool pexblackadd); void trimValues (rtengine::procparams::ProcParams* pp) override; }; - -#endif 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..49e1e848d 100644 --- a/rtgui/zoompanel.h +++ b/rtgui/zoompanel.h @@ -14,15 +14,16 @@ * 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_ +#pragma once #include class ImageArea; -class ZoomPanel : public Gtk::Grid + +class ZoomPanel : + public Gtk::Grid { protected: @@ -48,6 +49,3 @@ public: void newCropClicked (); void refreshZoomLabel (); }; - -#endif - diff --git a/tools/RTProfileBuilderSample.cs b/tools/RTProfileBuilderSample.cs index a097e6883..80474b63b 100644 --- a/tools/RTProfileBuilderSample.cs +++ b/tools/RTProfileBuilderSample.cs @@ -1,293 +1,293 @@ -#region Usings -using System; -using System.Text; -using System.IO; -using System.Globalization; -using System.Diagnostics; -using System.Configuration; -using System.Collections; -using System.Collections.Specialized; -#endregion - -// *** Raw Therapee sample Custom Profile builder (version 2013-08-12) *** -// -// -// WARNING: The command line parameters has changed since this file has been created by Oduis. The new mechanism involves a -// temporary communication file (.ini style) to provide system parameters and metadata read by RawTherapee. This script has -// to be updated by some C# developer in order to work. -// -// -// WARNING: PP3 format may change in the future versions! If this happens there will probably be no automatic migration path, -// you'll have to adjust on your own. This is a sample, and therefore not supported by the RT team (just by oduis) -// -// -// How to use: -// 1. Modify the GetCorrectedSettings function below according to your needs. -// 2. Download and install Microsoft .Net Runtime (latest version is 4.0 as of writing), if it's not already on your machine. -// You can get it for free via Windows Update or from microsoft.com. No need for Visual Studio etc. -// 3. Open a command line and compile this CS-File using the C# 32bit compiler. It is usually installed somewhere here: -// C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe -// Call csc.exe (C#-Compiler) with your .CS file as parameter like this (one big line): -// -// C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc -// /r:C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.dll -// /r:C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Configuration.dll -// RTProfileBuilderSample.cs -// -// (On most machines it already works with "C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc RTProfileBuilderSample.cs") -// CSC will compile it and emit an EXE. -// 4. Open your RT options files and find the entry [Profiles]/CustomProfileBuilder -// 5. Enter the path to your newly built exe here. On Windows, don't forget double slashes (e.g. "C:\\MyDir\\Mybuilder.exe") -// And you're done! The EXE is only called on opening the image editor and there is no PP3 already -// -// If you want to use EXIFTOOL to gather more details information to build queries: -// 1. Download exiftool.exe from http://www.sno.phy.queensu.ca/~phil/exiftool/ -// 2. Rename it to exiftool.exe (NOT exiftool(-k).. or something!) -// 3. Copy the RTProfilerBuilder.exe.config next to your own EXE. If you renamed it, rename config to "(Yourname).exe.config" -// 4. Open the config with notepad (it's an XML file). Set ExifToolPath to your downloaded and renamed exe -// -// If you want to know what parameters are available, call "exiftool.exe -tab -short" -// -// This description is for Windows. The C# code does not use anything fancy, will probably work with MONO on Linux/OSX, too - -namespace RTProfilerBuilder { - /// Main class. Mostly change GetCorrectedSettings. - class RTProfileBuilder { - - /// Adds the Nikkor zoom distortion correction profile. - /// First array is list of focal lengths, second array is the RT setting that should correct the - /// distortion for the corresponding focal length. Values between these values are automatically interpolated. - /// The focal length values must already be ordered. The number of sample points is not limited. - static DistortionCorrectProf distNikkor24120f4 = new DistortionCorrectProf( - new double[] { 24, 28, 35, 50, 70, 85, 120 }, - new double[] { -0.1, -0.063, -0.012, 0.018, 0.034, 0.04, 0.048 } - ); - - - /// This is your personalisation function - /// Full EXIF from EXIFTOOL (if configured). - /// Entry, like "Sharpening/Radius" - /// Current value (from default file) - /// FNumberExposure in seconds - /// Focal length in MMISO value - /// Lens from EXIFCamera from EXIF - /// The value to be written. Simply take the current value if you have nothing to touch. - static string GetCorrectedSetting(NameValueCollection exif, string sectionEntry, string value, - double fNumber, double exposureSecs, double focalLength, long iso, string lens, string camera) { - - string s; - - // We don't do anything to the value if it's not our camera - if (camera.EndsWith("NIKON D700", StringComparison.InvariantCultureIgnoreCase) && lens.Contains("24.0-120.0 mm f/4.0")) { - switch (sectionEntry) { - // Here is the place to adjust your settings - // Pretty simple: "SectionName/EntryName" in options file - - case "Vignetting Correction/Amount": - value = (fNumber < 8 && focalLength < 30) ? "30" : "0"; - break; - - case "RAW/CA": - value = ToBool(fNumber < 11); // Means "Enabled if fnumber<11, otherwise disabled" - break; - - case "Impulse Denoising/Enabled": - value = ToBool(iso >= 3200); - break; - - case "HLRecovery/Enabled": - value = ToBool(iso >= 1600); // Dynamic range decreases, so we'll probably need it - break; - - case "Color Boost/Amount": - if (iso >= 6400) value = "0"; // Colors will get poppy anyway... - break; - - case "Distortion/Amount": - // we already checked in the IF upstairs that this is "our" lens - value = distNikkor24120f4.GetDistortionAmount(focalLength); - break; - - // Add other parameters here. Mention this is case sensitive! - - default: break; // we don't touch values we don't care about - } - } // end if camera=xxx - - - // This is for camera independent settings - switch (sectionEntry) { - // These are parsed from EXIFTOOL and XMP in DNG (see http://en.wikipedia.org/wiki/Extensible_Metadata_Platform) - case "IPTC/City": - s = exif.Get("City"); - if (!String.IsNullOrEmpty(s)) value = s; - break; - - case "IPTC/Country": - s = exif.Get("Country"); - if (!String.IsNullOrEmpty(s)) value = s; - break; - - case "IPTC/Caption": - case "IPTC/Title": - s = exif.Get("Headline"); - if (!String.IsNullOrEmpty(s)) value = s; - break; - - // Add other parameters here. Mention this is case sensitive! - - default: break; // we don't touch values we don't care about - } - return value; - } - - #region * Main and Helpers - static string ToBool(bool condition) { return condition ? "true" : "false"; } - static string ToFloat(float f) { return f.ToString(CultureInfo.InvariantCulture); } - - /// Reads default file and parses it. No need to touch it for your personal settings. - /// Command line args - /// 0 on all OK. - static int Main(string[] args) { - int exitCode = 0; - - try { - #region Parse input parameters - int argNo = 0; - - // Name of raw/JPG to process - string sourceFile = args[argNo++]; - - // What the user selected as his base profile - string defaultProfileFilePath = args[argNo++]; - - // Cache directory, for any logging file - string cachePath = args[argNo++]; - - - // True if the image is only being flagged as inTrash, rank or colorLabel but still need valid PP3 - actually not used by this script - bool forFlaggingPurpose = bool.Parse(args[argNo++], CultureInfo.InvariantCulture); - - // Note that old C++ has no automatic number globalization - double fNumber = double.Parse(args[argNo++], CultureInfo.InvariantCulture); - double exposureSecs = double.Parse(args[argNo++], CultureInfo.InvariantCulture); - double focalLength = double.Parse(args[argNo++], CultureInfo.InvariantCulture); - long iso = long.Parse(args[argNo++], CultureInfo.InvariantCulture); - - string lens = args[argNo++]; - string cameraMake = args[argNo++]; - string cameraModel = args[argNo++]; - string camera = cameraMake + " " + cameraModel; - #endregion - - // Read default file as basis - string[] lines = File.ReadAllLines(defaultProfileFilePath); - - NameValueCollection nvEXIF = ParseFullExifData(sourceFile); - - // File should be Windows ANSI - using (TextWriter tw = new StreamWriter(sourceFile + ".pp3", false, new UTF8Encoding(false))) { - string section = ""; - - foreach (string line in lines) { - string l = line.Trim(); - if (!String.IsNullOrEmpty(line)) { - - if (l.StartsWith("[")) - section = l.Trim(new char[] { '[', ']' }); - else if (char.IsLetterOrDigit(l[0]) && l.Contains("=")) { - int valPos = l.IndexOf("=") + 1; - - string newValue = GetCorrectedSetting(nvEXIF, section + "/" + l.Substring(0, valPos - 1), l.Substring(valPos).Trim(), - fNumber, exposureSecs, focalLength, iso, lens, camera); - - // Merge in new value - l = l.Substring(0, valPos) + (newValue ?? ""); - } - } - - tw.WriteLine(l); - } - } - - } catch (Exception ex) { - Console.WriteLine("Error: " + ex.ToString()); // can be seen in the RT console window - - exitCode = 1; - } - - return exitCode; - } - - - static NameValueCollection ParseFullExifData(string filePath) { - NameValueCollection nv = new NameValueCollection(); - - string exifToolPath = ConfigurationManager.AppSettings["ExifToolPath"]; - if (!String.IsNullOrEmpty(exifToolPath)) { - ProcessStartInfo psi = new ProcessStartInfo(exifToolPath, "\"" + filePath + "\" -tab -short"); - psi.CreateNoWindow = false; - psi.UseShellExecute = false; - psi.StandardOutputEncoding = System.Text.Encoding.UTF8; - psi.RedirectStandardOutput = true; - - Process p = Process.Start(psi); - - using (StreamReader sr = p.StandardOutput) { - while (!sr.EndOfStream) { - string line = sr.ReadLine(); - if (line.Contains("\t")) { - string[] split = line.Split('\t'); - nv.Add(split[0], split[1]); - } - } - } - - p.WaitForExit(); - } - - return nv; - } - - #endregion - } - - #region DistortionCorrectProf - /// Holds a distortion correction profile for one lens. Uses sample points (focal length vs. dist. correction) as input. - class DistortionCorrectProf { - double[] adFocLen, adCorrect; - - /// Parses array to internal structure - /// Focal lengths - /// Correction factors - public DistortionCorrectProf(double[] focLen, double[] correct) { - if (focLen == null || correct == null || focLen.Length != correct.Length || focLen.Length < 2) - throw new Exception("DistortionCorrectProf inputs must be valid and of the same lengths, at least 2 points"); - - adFocLen = focLen; adCorrect = correct; - - for (int i = 0; i < adFocLen.Length - 1; i++) - if (adFocLen[i] >= adFocLen[i + 1]) throw new Exception("The distortion correction focal length points must be ordered!"); - } - - /// Calculates regression value of RT distortion amount for the given focal length. - /// Input focal length. - /// Distortion in RT format. - public string GetDistortionAmount(double focalLength) { - // if it's out of area (which should just happen with e.g. rounding errors), return flat defaults. - if (focalLength <= adFocLen[0]) return adCorrect[0].ToString("G", CultureInfo.InvariantCulture); - if (focalLength >= adFocLen[adFocLen.Length - 1]) return adCorrect[adFocLen.Length - 1].ToString("G", CultureInfo.InvariantCulture); - - for (int i = 0; i < adFocLen.Length - 1; i++) { - if (focalLength >= adFocLen[i] && focalLength < adFocLen[i + 1]) { - // from the sample curves taken so far, it it safe to take a simple linear interpolation here - double corr = adCorrect[i] + (adCorrect[i + 1] - adCorrect[i]) * (focalLength - adFocLen[i]) / (adFocLen[i + 1] - adFocLen[i]); - return corr.ToString("G3", CultureInfo.InvariantCulture); - } - } - - return ""; // should never happen - } - } - #endregion -} +#region Usings +using System; +using System.Text; +using System.IO; +using System.Globalization; +using System.Diagnostics; +using System.Configuration; +using System.Collections; +using System.Collections.Specialized; +#endregion + +// *** Raw Therapee sample Custom Profile builder (version 2013-08-12) *** +// +// +// WARNING: The command line parameters has changed since this file has been created by Oduis. The new mechanism involves a +// temporary communication file (.ini style) to provide system parameters and metadata read by RawTherapee. This script has +// to be updated by some C# developer in order to work. +// +// +// WARNING: PP3 format may change in the future versions! If this happens there will probably be no automatic migration path, +// you'll have to adjust on your own. This is a sample, and therefore not supported by the RT team (just by oduis) +// +// +// How to use: +// 1. Modify the GetCorrectedSettings function below according to your needs. +// 2. Download and install Microsoft .Net Runtime (latest version is 4.0 as of writing), if it's not already on your machine. +// You can get it for free via Windows Update or from microsoft.com. No need for Visual Studio etc. +// 3. Open a command line and compile this CS-File using the C# 32bit compiler. It is usually installed somewhere here: +// C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe +// Call csc.exe (C#-Compiler) with your .CS file as parameter like this (one big line): +// +// C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc +// /r:C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.dll +// /r:C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Configuration.dll +// RTProfileBuilderSample.cs +// +// (On most machines it already works with "C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc RTProfileBuilderSample.cs") +// CSC will compile it and emit an EXE. +// 4. Open your RT options files and find the entry [Profiles]/CustomProfileBuilder +// 5. Enter the path to your newly built exe here. On Windows, don't forget double slashes (e.g. "C:\\MyDir\\Mybuilder.exe") +// And you're done! The EXE is only called on opening the image editor and there is no PP3 already +// +// If you want to use EXIFTOOL to gather more details information to build queries: +// 1. Download exiftool.exe from http://www.sno.phy.queensu.ca/~phil/exiftool/ +// 2. Rename it to exiftool.exe (NOT exiftool(-k).. or something!) +// 3. Copy the RTProfilerBuilder.exe.config next to your own EXE. If you renamed it, rename config to "(Yourname).exe.config" +// 4. Open the config with notepad (it's an XML file). Set ExifToolPath to your downloaded and renamed exe +// +// If you want to know what parameters are available, call "exiftool.exe -tab -short" +// +// This description is for Windows. The C# code does not use anything fancy, will probably work with MONO on Linux/OSX, too + +namespace RTProfilerBuilder { + /// Main class. Mostly change GetCorrectedSettings. + class RTProfileBuilder { + + /// Adds the Nikkor zoom distortion correction profile. + /// First array is list of focal lengths, second array is the RT setting that should correct the + /// distortion for the corresponding focal length. Values between these values are automatically interpolated. + /// The focal length values must already be ordered. The number of sample points is not limited. + static DistortionCorrectProf distNikkor24120f4 = new DistortionCorrectProf( + new double[] { 24, 28, 35, 50, 70, 85, 120 }, + new double[] { -0.1, -0.063, -0.012, 0.018, 0.034, 0.04, 0.048 } + ); + + + /// This is your personalisation function + /// Full EXIF from EXIFTOOL (if configured). + /// Entry, like "Sharpening/Radius" + /// Current value (from default file) + /// FNumberExposure in seconds + /// Focal length in MMISO value + /// Lens from EXIFCamera from EXIF + /// The value to be written. Simply take the current value if you have nothing to touch. + static string GetCorrectedSetting(NameValueCollection exif, string sectionEntry, string value, + double fNumber, double exposureSecs, double focalLength, long iso, string lens, string camera) { + + string s; + + // We don't do anything to the value if it's not our camera + if (camera.EndsWith("NIKON D700", StringComparison.InvariantCultureIgnoreCase) && lens.Contains("24.0-120.0 mm f/4.0")) { + switch (sectionEntry) { + // Here is the place to adjust your settings + // Pretty simple: "SectionName/EntryName" in options file + + case "Vignetting Correction/Amount": + value = (fNumber < 8 && focalLength < 30) ? "30" : "0"; + break; + + case "RAW/CA": + value = ToBool(fNumber < 11); // Means "Enabled if fnumber<11, otherwise disabled" + break; + + case "Impulse Denoising/Enabled": + value = ToBool(iso >= 3200); + break; + + case "HLRecovery/Enabled": + value = ToBool(iso >= 1600); // Dynamic range decreases, so we'll probably need it + break; + + case "Color Boost/Amount": + if (iso >= 6400) value = "0"; // Colors will get poppy anyway... + break; + + case "Distortion/Amount": + // we already checked in the IF upstairs that this is "our" lens + value = distNikkor24120f4.GetDistortionAmount(focalLength); + break; + + // Add other parameters here. Mention this is case sensitive! + + default: break; // we don't touch values we don't care about + } + } // end if camera=xxx + + + // This is for camera independent settings + switch (sectionEntry) { + // These are parsed from EXIFTOOL and XMP in DNG (see http://en.wikipedia.org/wiki/Extensible_Metadata_Platform) + case "IPTC/City": + s = exif.Get("City"); + if (!String.IsNullOrEmpty(s)) value = s; + break; + + case "IPTC/Country": + s = exif.Get("Country"); + if (!String.IsNullOrEmpty(s)) value = s; + break; + + case "IPTC/Caption": + case "IPTC/Title": + s = exif.Get("Headline"); + if (!String.IsNullOrEmpty(s)) value = s; + break; + + // Add other parameters here. Mention this is case sensitive! + + default: break; // we don't touch values we don't care about + } + return value; + } + +#region * Main and Helpers + static string ToBool(bool condition) { return condition ? "true" : "false"; } + static string ToFloat(float f) { return f.ToString(CultureInfo.InvariantCulture); } + + /// Reads default file and parses it. No need to touch it for your personal settings. + /// Command line args + /// 0 on all OK. + static int Main(string[] args) { + int exitCode = 0; + + try { +#region Parse input parameters + int argNo = 0; + + // Name of raw/JPG to process + string sourceFile = args[argNo++]; + + // What the user selected as his base profile + string defaultProfileFilePath = args[argNo++]; + + // Cache directory, for any logging file + string cachePath = args[argNo++]; + + + // True if the image is only being flagged as inTrash, rank or colorLabel but still need valid PP3 - actually not used by this script + bool forFlaggingPurpose = bool.Parse(args[argNo++], CultureInfo.InvariantCulture); + + // Note that old C++ has no automatic number globalization + double fNumber = double.Parse(args[argNo++], CultureInfo.InvariantCulture); + double exposureSecs = double.Parse(args[argNo++], CultureInfo.InvariantCulture); + double focalLength = double.Parse(args[argNo++], CultureInfo.InvariantCulture); + long iso = long.Parse(args[argNo++], CultureInfo.InvariantCulture); + + string lens = args[argNo++]; + string cameraMake = args[argNo++]; + string cameraModel = args[argNo++]; + string camera = cameraMake + " " + cameraModel; +#endregion + + // Read default file as basis + string[] lines = File.ReadAllLines(defaultProfileFilePath); + + NameValueCollection nvEXIF = ParseFullExifData(sourceFile); + + // File should be Windows ANSI + using (TextWriter tw = new StreamWriter(sourceFile + ".pp3", false, new UTF8Encoding(false))) { + string section = ""; + + foreach (string line in lines) { + string l = line.Trim(); + if (!String.IsNullOrEmpty(line)) { + + if (l.StartsWith("[")) + section = l.Trim(new char[] { '[', ']' }); + else if (char.IsLetterOrDigit(l[0]) && l.Contains("=")) { + int valPos = l.IndexOf("=") + 1; + + string newValue = GetCorrectedSetting(nvEXIF, section + "/" + l.Substring(0, valPos - 1), l.Substring(valPos).Trim(), + fNumber, exposureSecs, focalLength, iso, lens, camera); + + // Merge in new value + l = l.Substring(0, valPos) + (newValue ?? ""); + } + } + + tw.WriteLine(l); + } + } + + } catch (Exception ex) { + Console.WriteLine("Error: " + ex.ToString()); // can be seen in the RT console window + + exitCode = 1; + } + + return exitCode; + } + + + static NameValueCollection ParseFullExifData(string filePath) { + NameValueCollection nv = new NameValueCollection(); + + string exifToolPath = ConfigurationManager.AppSettings["ExifToolPath"]; + if (!String.IsNullOrEmpty(exifToolPath)) { + ProcessStartInfo psi = new ProcessStartInfo(exifToolPath, "\"" + filePath + "\" -tab -short"); + psi.CreateNoWindow = false; + psi.UseShellExecute = false; + psi.StandardOutputEncoding = System.Text.Encoding.UTF8; + psi.RedirectStandardOutput = true; + + Process p = Process.Start(psi); + + using (StreamReader sr = p.StandardOutput) { + while (!sr.EndOfStream) { + string line = sr.ReadLine(); + if (line.Contains("\t")) { + string[] split = line.Split('\t'); + nv.Add(split[0], split[1]); + } + } + } + + p.WaitForExit(); + } + + return nv; + } + +#endregion + } + +#region DistortionCorrectProf + /// Holds a distortion correction profile for one lens. Uses sample points (focal length vs. dist. correction) as input. + class DistortionCorrectProf { + double[] adFocLen, adCorrect; + + /// Parses array to internal structure + /// Focal lengths + /// Correction factors + public DistortionCorrectProf(double[] focLen, double[] correct) { + if (focLen == null || correct == null || focLen.Length != correct.Length || focLen.Length < 2) + throw new Exception("DistortionCorrectProf inputs must be valid and of the same lengths, at least 2 points"); + + adFocLen = focLen; adCorrect = correct; + + for (int i = 0; i < adFocLen.Length - 1; i++) + if (adFocLen[i] >= adFocLen[i + 1]) throw new Exception("The distortion correction focal length points must be ordered!"); + } + + /// Calculates regression value of RT distortion amount for the given focal length. + /// Input focal length. + /// Distortion in RT format. + public string GetDistortionAmount(double focalLength) { + // if it's out of area (which should just happen with e.g. rounding errors), return flat defaults. + if (focalLength <= adFocLen[0]) return adCorrect[0].ToString("G", CultureInfo.InvariantCulture); + if (focalLength >= adFocLen[adFocLen.Length - 1]) return adCorrect[adFocLen.Length - 1].ToString("G", CultureInfo.InvariantCulture); + + for (int i = 0; i < adFocLen.Length - 1; i++) { + if (focalLength >= adFocLen[i] && focalLength < adFocLen[i + 1]) { + // from the sample curves taken so far, it it safe to take a simple linear interpolation here + double corr = adCorrect[i] + (adCorrect[i + 1] - adCorrect[i]) * (focalLength - adFocLen[i]) / (adFocLen[i + 1] - adFocLen[i]); + return corr.ToString("G3", CultureInfo.InvariantCulture); + } + } + + return ""; // should never happen + } + } +#endregion +} diff --git a/tools/RTProfileBuilderSample.exe.config b/tools/RTProfileBuilderSample.exe.config index 2dbb6b973..c054fce6c 100644 --- a/tools/RTProfileBuilderSample.exe.config +++ b/tools/RTProfileBuilderSample.exe.config @@ -1,8 +1,8 @@ - - - - - - - + + + + + + + diff --git a/tools/camconst_creator.ods b/tools/camconst_creator.ods new file mode 100644 index 000000000..8930587ba 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..1956988d8 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 */ @@ -39,8 +39,8 @@ static const FileFormat file_formats[] = { { N_("Raw Canon"), - "image/x-canon-cr2,image/x-canon-crw", - "cr2,crw", + "image/x-canon-cr2,image/x-canon-cr3,image/x-canon-crw", + "cr2,cr3,crw", NULL, "file-rawtherapee-canon-load", 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" diff --git a/tools/osx/Info.plist-bin.in b/tools/osx/Info.plist-bin.in index 20ce5a741..33abd4f7a 100644 --- a/tools/osx/Info.plist-bin.in +++ b/tools/osx/Info.plist-bin.in @@ -1,10 +1,10 @@ - - CFBundleName - RawTherapee-bin - CFBundleIdentifier - com.rawtherapee.rawtherapee - + + CFBundleName + RawTherapee-bin + CFBundleIdentifier + com.rawtherapee.rawtherapee + diff --git a/tools/osx/Info.plist.in b/tools/osx/Info.plist.in index e78db0cc4..eec1ab490 100644 --- a/tools/osx/Info.plist.in +++ b/tools/osx/Info.plist.in @@ -1,167 +1,167 @@ - - CFBundleDevelopmentRegion - English - CFBundleDisplayName - RawTherapee - CFBundleDocumentTypes - - - CFBundleTypeExtensions - - pp3 - PP3 - - CFBundleTypeIconFile - profile.icns - CFBundleTypeName - RawTherapee Profile Data - CFBundleTypeRole - Editor - LSIsAppleDefaultForType - - LSItemContentTypes - - com.rawtherapee.pp3 - - - - CFBundleTypeExtensions - - 3FR - 3fr - ARW - arw - CR2 - cr2 - CRF - crf - CRW - crw - DCR - dcr - DNG - dng - FFF - fff - IIQ - iiq - KDC - kdc - MEF - mef - MOS - mos - MRW - mrw - NEF - nef - NRW - nrw - ORF - orf - PEF - pef - RAF - raf - RAW - raw - RW2 - rw2 - RWZ - rwz - SR2 - sr2 - SRF - srf - SRW - srw - - CFBundleTypeMIMETypes - - image/raw - - CFBundleTypeName - Camera Raw - CFBundleTypeRole - Viewer - - - CFBundleTypeExtensions - - JPEG - jpeg - JPG - jpg - PNG - png - TIF - tif - TIFF - tiff - - CFBundleTypeName - Image - CFBundleTypeRole - Viewer - - - CFBundleExecutable - rawtherapee - CFBundleGetInfoString - @version@, Copyright © 2004-2010 Gábor Horváth, 2010-2017 RawTherapee Development Team - CFBundleIconFile - rawtherapee.icns - CFBundleIdentifier - com.rawtherapee.rawtherapee - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - RawTherapee - CFBundlePackageType - APPL - CFBundleShortVersionString - @shortVersion@ - CFBundleSignature - ???? - CFBundleVersion - @shortVersion@ - LSExecutableArchitectures - - @arch@ - - NSHighResolutionCapable - - NSHumanReadableCopyright - Copyright © 2004-2010 Gábor Horváth, 2010-2017 RawTherapee Development Team - UTExportedTypeDeclarations - - - UTTypeConformsTo - - public.data - - UTTypeDescription - RawTherapee Profile Data - UTTypeIconFile - Icons.icns - UTTypeIdentifier - com.rawtherapee.pp3 - UTTypeReferenceURL - http://www.rawtherapee.com/ - UTTypeTagSpecification - - com.apple.ostype - PP3 - public.filename-extension - - pp3 - PP3 - - - - - + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + RawTherapee + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + pp3 + PP3 + + CFBundleTypeIconFile + profile.icns + CFBundleTypeName + RawTherapee Profile Data + CFBundleTypeRole + Editor + LSIsAppleDefaultForType + + LSItemContentTypes + + com.rawtherapee.pp3 + + + + CFBundleTypeExtensions + + 3FR + 3fr + ARW + arw + CR2 + cr2 + CRF + crf + CRW + crw + DCR + dcr + DNG + dng + FFF + fff + IIQ + iiq + KDC + kdc + MEF + mef + MOS + mos + MRW + mrw + NEF + nef + NRW + nrw + ORF + orf + PEF + pef + RAF + raf + RAW + raw + RW2 + rw2 + RWZ + rwz + SR2 + sr2 + SRF + srf + SRW + srw + + CFBundleTypeMIMETypes + + image/raw + + CFBundleTypeName + Camera Raw + CFBundleTypeRole + Viewer + + + CFBundleTypeExtensions + + JPEG + jpeg + JPG + jpg + PNG + png + TIF + tif + TIFF + tiff + + CFBundleTypeName + Image + CFBundleTypeRole + Viewer + + + CFBundleExecutable + rawtherapee + CFBundleGetInfoString + @version@, Copyright © 2004-2010 Gábor Horváth, 2010-2017 RawTherapee Development Team + CFBundleIconFile + rawtherapee.icns + CFBundleIdentifier + com.rawtherapee.rawtherapee + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + RawTherapee + CFBundlePackageType + APPL + CFBundleShortVersionString + @shortVersion@ + CFBundleSignature + ???? + CFBundleVersion + @shortVersion@ + LSExecutableArchitectures + + @arch@ + + NSHighResolutionCapable + + NSHumanReadableCopyright + Copyright © 2004-2010 Gábor Horváth, 2010-2017 RawTherapee Development Team + UTExportedTypeDeclarations + + + UTTypeConformsTo + + public.data + + UTTypeDescription + RawTherapee Profile Data + UTTypeIconFile + Icons.icns + UTTypeIdentifier + com.rawtherapee.pp3 + UTTypeReferenceURL + http://www.rawtherapee.com/ + UTTypeTagSpecification + + com.apple.ostype + PP3 + public.filename-extension + + pp3 + PP3 + + + + + diff --git a/tools/osx/executable_loader.in b/tools/osx/executable_loader.in index 429173d8e..5ee609043 100644 --- a/tools/osx/executable_loader.in +++ b/tools/osx/executable_loader.in @@ -1,19 +1,22 @@ #!/bin/sh +# GIMP has this next line regarding raising the number-of-open-files limit: +ulimit -n 7000 + cd "$(dirname "$0")" || exit 1 cwd="$(pwd)" -app="${cwd%/Contents/*}" +app="/Applications/RawTherapee.app" lib="${app}/Contents/Frameworks" resources="${app}/Contents/Resources" -etc="${resources}"/etc +etc="${resources}/etc" export XDG_DATA_DIRS="${resources}/share" -export DYLD_LIBRARY_PATH="${lib}" +export DYLD_FALLBACK_LIBRARY_PATH="${lib}" export GTK_PATH="${lib}/gtk-3.0/3.0.0" export XDG_DATA_HOME="${resources}/share" export GSETTINGS_SCHEMA_DIR="${resources}/share/glib-2.0/schemas" export GDK_PIXBUF_MODULE_FILE="${etc}/gtk-3.0/gdk-pixbuf.loaders" -export GDK_PIXBUF_MODULEDIR="${lib}/gdk-pixbuf-2.0/2.10.0/loaders" +export GDK_PIXBUF_MODULEDIR="${lib}" export RT_SETTINGS="${HOME}/Library/Application Support/RawTherapee/config" export RT_CACHE="${HOME}/Library/Application Support/RawTherapee/cache" @@ -27,4 +30,4 @@ esac AppleLocale=`defaults read -g AppleLocale` export LANG=${AppleLocale%@*}.UTF-8 -exec "${cwd}/bin/rawtherapee-bin" "$@" +exec "${app}/Contents/MacOS/bin/rawtherapee-bin" "$@" diff --git a/tools/osx/libiconv_1.16_rt.patch b/tools/osx/libiconv_1.16_rt.patch new file mode 100644 index 000000000..470f7780c --- /dev/null +++ b/tools/osx/libiconv_1.16_rt.patch @@ -0,0 +1,31 @@ +diff --git a/lib/iconv.c b/lib/iconv.c +index b7a04f8..41c5896 100644 +--- a/lib/iconv.c ++++ b/lib/iconv.c +@@ -610,5 +610,26 @@ strong_alias (libiconv_open, iconv_open) + strong_alias (libiconv, iconv) + strong_alias (libiconv_close, iconv_close) + #endif ++ ++#undef iconv_open ++#undef iconv ++#undef iconv_close ++ ++LIBICONV_DLL_EXPORTED iconv_t iconv_open (const char* tocode, const char* fromcode) ++{ ++ return libiconv_open(tocode, fromcode); ++} ++ ++LIBICONV_DLL_EXPORTED size_t iconv (iconv_t icd, ++ ICONV_CONST char * * inbuf, size_t *inbytesleft, ++ char * * outbuf, size_t *outbytesleft) ++{ ++ return libiconv(icd, inbuf, inbytesleft, outbuf, outbytesleft); ++} ++ ++LIBICONV_DLL_EXPORTED int iconv_close (iconv_t icd) ++{ ++ return libiconv_close(icd); ++} + + #endif diff --git a/tools/osx/macosx_bundle.sh b/tools/osx/macosx_bundle.sh index 2501e936b..08740f696 100644 --- a/tools/osx/macosx_bundle.sh +++ b/tools/osx/macosx_bundle.sh @@ -76,10 +76,7 @@ if [[ -z "${MINIMUM_SYSTEM_VERSION}" ]]; then MINIMUM_SYSTEM_VERSION="$(sw_vers -productVersion | cut -d. -f-2)" fi -case ${PROC_BIT_DEPTH} in - 64) arch=x86_64;; - 32) arch=i386;; -esac +arch=x86_64 cat <<__EOS__ PROJECT_NAME: ${PROJECT_NAME} @@ -92,6 +89,9 @@ GTK_PREFIX: ${GTK_PREFIX} PWD: ${PWD} __EOS__ +LOCAL_PREFIX="$(cmake .. -LA -N | grep "LOCAL_PREFIX" | cut -d "=" -f2)" +EXPATLIB="$(cmake .. -LA -N | grep "pkgcfg_lib_EXPAT_expat" | cut -d "=" -f2)" + APP="${PROJECT_NAME}.app" CONTENTS="${APP}/Contents" RESOURCES="${CONTENTS}/Resources" @@ -99,6 +99,7 @@ MACOS="${CONTENTS}/MacOS" LIB="${CONTENTS}/Frameworks" ETC="${RESOURCES}/etc" EXECUTABLE="${MACOS}/rawtherapee" +GDK_PREFIX="${LOCAL_PREFIX}/local/" msg "Removing old files:" rm -rf "${APP}" "${PROJECT_NAME}_*.dmg" "*zip" @@ -111,68 +112,82 @@ install -d "${RESOURCES}" \ msg "Copying release files:" ditto "${CMAKE_BUILD_TYPE}/MacOS" "${MACOS}" -ditto "${CMAKE_BUILD_TYPE}/Resources" "${RESOURCES}" +ditto "Resources" "${RESOURCES}" + +# Copy the Lensfun database into the app bundle +mkdir -p "${RESOURCES}/share/lensfun" +ditto ${LOCAL_PREFIX}/local/share/lensfun/version_2/* "${RESOURCES}/share/lensfun" + +# Copy liblensfun to Frameworks +ditto ${LOCAL_PREFIX}/local/lib/liblensfun.2.dylib "${CONTENTS}/Frameworks/liblensfun.2.dylib" + +# Copy libomp to Frameworks +ditto ${LOCAL_PREFIX}/local/lib/libomp.dylib "${CONTENTS}/Frameworks" msg "Copying dependencies from ${GTK_PREFIX}:" CheckLink "${EXECUTABLE}" -msg "Copying library modules from ${GTK_PREFIX}:" -ditto --arch "${arch}" {"${GTK_PREFIX}/lib","${LIB}"}/gdk-pixbuf-2.0 -ditto --arch "${arch}" {"${GTK_PREFIX}/lib","${LIB}"}/gtk-3.0 +# Copy libjpeg-turbo ("62") into the app bundle +ditto ${LOCAL_PREFIX}/local/lib/libjpeg.62.dylib "${CONTENTS}/Frameworks/libjpeg.62.dylib" -msg "Removing static libraries and cache files:" -find -E "${LIB}" -type f -regex '.*\.(a|la|cache)$' | while read -r; do rm "${REPLY}"; done - -msg "Copying configuration files from ${GTK_PREFIX}:" -install -d "${ETC}/gtk-3.0" - -# Make Frameworks folder flat -mv "${LIB}"/gdk-pixbuf-2.0/2*/loaders/*.so "${LIB}" -mv "${LIB}"/gtk-3.0/3*/immodules/*.so "${LIB}" -rm -r "${LIB}"/gtk-3.0 -rm -r "${LIB}"/gdk-pixbuf-2.0 - -"${GTK_PREFIX}/bin/gdk-pixbuf-query-loaders" "${LIB}"/libpix*.so > "${ETC}/gtk-3.0/gdk-pixbuf.loaders" -"${GTK_PREFIX}/bin/gtk-query-immodules-3.0" "${LIB}"/{im*.so,libprint*.so} > "${ETC}/gtk-3.0/gtk.immodules" -sed -i "" -e "s|${PWD}/RawTherapee.app/Contents/|/Applications/RawTherapee.app/Contents/|" "${ETC}/gtk-3.0/gdk-pixbuf.loaders" "${ETC}/gtk-3.0/gtk.immodules" - -ditto {"${GTK_PREFIX}","${RESOURCES}"}/share/glib-2.0/schemas -"${GTK_PREFIX}/bin/glib-compile-schemas" "${RESOURCES}/share/glib-2.0/schemas" - -msg "Copying shared files from ${GTK_PREFIX}:" -ditto {"${GTK_PREFIX}","${RESOURCES}"}/share/mime -# GTK3 themes -ditto {"${GTK_PREFIX}","${RESOURCES}"}/share/themes/Mac/gtk-3.0/gtk-keys.css -ditto {"${GTK_PREFIX}","${RESOURCES}"}/share/themes/Default/gtk-3.0/gtk-keys.css -# Adwaita icons -iconfolders=("16x16/actions" "16x16/devices" "16x16/mimetypes" "16x16/places" "16x16/status" "48x48/devices") -for f in "${iconfolders[@]}"; do - ditto {"${GTK_PREFIX}","${RESOURCES}"}/share/icons/Adwaita/"$f" -done -ditto {"${GTK_PREFIX}","${RESOURCES}"}/share/icons/Adwaita/index.theme -"${GTK_PREFIX}/bin/gtk-update-icon-cache-3.0" "${RESOURCES}/share/icons/Adwaita" - -# Copy libjpeg-turbo into the app bundle -cp /opt/local/lib/libjpeg.62.dylib "${RESOURCES}/../Frameworks" - -# Copy libexpat into the app bundle -cp /opt/local/lib/libexpat.1.dylib "${RESOURCES}/../Frameworks" +# Copy libexpat into the app bundle (which is keg-only) +if [[ -d /usr/local/Cellar/expat ]]; then ditto /usr/local/Cellar/expat/*/lib/libexpat.1.dylib "${CONTENTS}/Frameworks"; else ditto "${EXPATLIB}" "${CONTENTS}/Frameworks/libexpat.1.dylib"; fi # Copy libz into the app bundle -cp /opt/local/lib/libz.1.dylib "${RESOURCES}/../Frameworks" +ditto ${LOCAL_PREFIX}/local/lib/libz.1.dylib "${CONTENTS}/Frameworks" -# Copy libtiff into the app bundle -cp /opt/local/lib/libtiff.5.dylib "${RESOURCES}/../Frameworks" +# Copy libpng16 to the app bundle +ditto ${LOCAL_PREFIX}/local/lib/libpng16.16.dylib "${CONTENTS}/Frameworks/libpng16.16.dylib" + +# Copy libtiff 5 into the app bundle +ditto ${LOCAL_PREFIX}/local/lib/libtiff.5.dylib "${CONTENTS}/Frameworks/libtiff.5.dylib" # Copy the Lensfun database into the app bundle mkdir -p "${RESOURCES}/share/lensfun" -cp /opt/local/share/lensfun/version_2/* "${RESOURCES}/share/lensfun" +ditto ${LOCAL_PREFIX}/local/share/lensfun/version_2/* "${RESOURCES}/share/lensfun" # Copy liblensfun to Frameworks -cp /opt/local/lib/liblensfun.2.dylib "${RESOURCES}/../Frameworks" +ditto ${LOCAL_PREFIX}/local/lib/liblensfun.2.dylib "${CONTENTS}/Frameworks/liblensfun.2.dylib" # Copy libomp to Frameworks -cp /opt/local/lib/libomp.dylib "${RESOURCES}/../Frameworks" +ditto ${LOCAL_PREFIX}/local/lib/libomp.dylib "${CONTENTS}/Frameworks" + +# Prepare GTK+3 installation +msg "Copying configuration files from ${GTK_PREFIX}:" +install -d "${ETC}/gtk-3.0" +msg "Copying library modules from ${GTK_PREFIX}:" +ditto --arch "${arch}" {"${GTK_PREFIX}/lib","${LIB}"}/gdk-pixbuf-2.0 +ditto --arch "${arch}" {"${GTK_PREFIX}/lib","${LIB}"}/gtk-3.0 +msg "Removing static libraries and cache files:" +find -E "${LIB}" -type f -regex '.*\.(a|la|cache)$' | while read -r; do rm "${REPLY}"; done + +# Make Frameworks folder flat +msg "Flattening the Frameworks folder" +ditto "${LIB}"/gdk-pixbuf-2.0/2*/loaders/*.so "${LIB}" +ditto "${LIB}"/gtk-3.0/3*/immodules/*.{dylib,so} "${LIB}" +rm -r "${LIB}"/gtk-3.0 +rm -r "${LIB}"/gdk-pixbuf-2.0 + +msg "Build glib database:" +mkdir -p ${RESOURCES}/share/glib-2.0 +ditto {"${LOCAL_PREFIX}/local","${RESOURCES}"}/share/glib-2.0/schemas +"${LOCAL_PREFIX}/local/bin/glib-compile-schemas" "${RESOURCES}/share/glib-2.0/schemas" + +# GTK+3 themes +msg "Copy GTK+3 theme and icon resources:" +ditto {"${LOCAL_PREFIX}/local","${RESOURCES}"}/share/themes/Mac/gtk-3.0/gtk-keys.css +ditto {"${LOCAL_PREFIX}/local","${RESOURCES}"}/share/themes/Default/gtk-3.0/gtk-keys.css + +# Adwaita icons +msg "Copy Adwaita icons" +iconfolders=("16x16/actions" "16x16/devices" "16x16/mimetypes" "16x16/places" "16x16/status" "48x48/devices") +for f in "${iconfolders[@]}"; do + mkdir -p ${RESOURCES}/share/icons/Adwaita/${f} + ditto ${LOCAL_PREFIX}/local/share/icons/Adwaita/${f}/* "${RESOURCES}"/share/icons/Adwaita/${f} +done +ditto {"${LOCAL_PREFIX}/local","${RESOURCES}"}/share/icons/Adwaita/index.theme +"${LOCAL_PREFIX}/local/bin/gtk-update-icon-cache" "${RESOURCES}/share/icons/Adwaita" +ditto "${LOCAL_PREFIX}/local/share/icons/hicolor" "${RESOURCES}/share/icons/hicolor" # Install names find -E "${CONTENTS}" -type f -regex '.*/(rawtherapee-cli|rawtherapee|.*\.(dylib|so))' | while read -r x; do @@ -187,9 +202,23 @@ find -E "${CONTENTS}" -type f -regex '.*/(rawtherapee-cli|rawtherapee|.*\.(dylib } | bash -v done -msg "Registering @loader_path into the executable:" -echo " install_name_tool -add_rpath @executable_path/../../Frameworks '${EXECUTABLE}'" | bash -v -echo " install_name_tool -add_rpath @loader_path/../Frameworks '${EXECUTABLE}-cli'" | bash -v +# fix @rpath in Frameworks +msg "Registering @rpath in Frameworks folder:" +for frameworklibs in ${CONTENTS}/Frameworks/* ; do + echo " install_name_tool -delete_rpath /opt/local/lib '${frameworklibs}'" | bash -v + echo " install_name_tool -add_rpath /Applications/RawTherapee.app/Contents/Frameworks '${frameworklibs}'" | bash -v +done + +# pixbuf loaders & immodules +msg "Build GTK3 databases:" +"${LOCAL_PREFIX}"/local/bin/gdk-pixbuf-query-loaders "${LIB}"/libpix*.so > "${ETC}"/gtk-3.0/gdk-pixbuf.loaders +"${LOCAL_PREFIX}"/local/bin/gtk-query-immodules-3.0 "${LIB}"/im-* > "${ETC}"/gtk-3.0/gtk.immodules +sed -i "" -e "s|${PWD}/RawTherapee.app/Contents/|/Applications/RawTherapee.app/Contents/|" "${ETC}/gtk-3.0/gdk-pixbuf.loaders" "${ETC}/gtk-3.0/gtk.immodules" +sed -i "" -e "s|/opt/local/|/usr/|" "${ETC}/gtk-3.0/gtk.immodules" + +# Mime directory +msg "Copying shared files from ${GTK_PREFIX}:" +ditto {"${LOCAL_PREFIX}/local","${RESOURCES}"}/share/mime msg "Installing required application bundle files:" PROJECT_SOURCE_DATA_DIR="${PROJECT_SOURCE_DIR}/tools/osx" @@ -197,36 +226,49 @@ ditto "${PROJECT_SOURCE_DIR}/build/Resources" "${RESOURCES}" # Executable loader # Note: executable is renamed to 'rawtherapee-bin'. mkdir "${MACOS}/bin" -mv "${MACOS}/rawtherapee" "${MACOS}/bin/rawtherapee-bin" +ditto "${MACOS}/rawtherapee" "${MACOS}/bin/rawtherapee-bin" +rm "${MACOS}/rawtherapee" install -m 0755 "${PROJECT_SOURCE_DATA_DIR}/executable_loader.in" "${MACOS}/rawtherapee" # App bundle resources -cp "${PROJECT_SOURCE_DATA_DIR}/"{rawtherapee,profile}.icns "${RESOURCES}" -cp "${PROJECT_SOURCE_DATA_DIR}/PkgInfo" "${CONTENTS}" +ditto "${PROJECT_SOURCE_DATA_DIR}/"{rawtherapee,profile}.icns "${RESOURCES}" +ditto "${PROJECT_SOURCE_DATA_DIR}/PkgInfo" "${CONTENTS}" install -m 0644 "${PROJECT_SOURCE_DATA_DIR}/Info.plist.in" "${CONTENTS}/Info.plist" install -m 0644 "${PROJECT_SOURCE_DATA_DIR}/Info.plist-bin.in" "${CONTENTS}/MacOS/bin/Info.plist" sed -i "" -e "s|@version@|${PROJECT_FULL_VERSION}| s|@shortVersion@|${PROJECT_VERSION}| s|@arch@|${arch}|" \ "${CONTENTS}/Info.plist" -plutil -convert binary1 "${CONTENTS}/Info.plist" -plutil -convert binary1 "${CONTENTS}/MacOS/bin/Info.plist" +plutil -convert xml1 "${CONTENTS}/Info.plist" +plutil -convert xml1 "${CONTENTS}/MacOS/bin/Info.plist" +update-mime-database -V "${CONTENTS}/Resources/share/mime" + +# Append an LC_RPATH +msg "Registering @rpath into the executable:" +echo " install_name_tool -add_rpath /Applications/RawTherapee.app/Contents/Frameworks '${MACOS}/bin/rawtherapee-bin'" | bash -v +echo " install_name_tool -add_rpath /Applications/RawTherapee.app/Contents/Frameworks '${EXECUTABLE}-cli'" | bash -v + # Sign the app +msg "Codesigning:" CODESIGNID="$(cmake .. -LA -N | grep "CODESIGNID" | cut -d "=" -f2)" if ! test -z "$CODESIGNID" ; then install -m 0644 "${PROJECT_SOURCE_DATA_DIR}/rt.entitlements" "${CONTENTS}/Entitlements.plist" -plutil -convert binary1 "${CONTENTS}/Entitlements.plist" +plutil -convert xml1 "${CONTENTS}/Entitlements.plist" install -m 0644 "${PROJECT_SOURCE_DATA_DIR}/rt-bin.entitlements" "${CONTENTS}/MacOS/bin/Entitlements.plist" -plutil -convert binary1 "${CONTENTS}/MacOS/bin/Entitlements.plist" -codesign -v -s "${CODESIGNID}" -i "com.rawtherapee.rawtherapee-bin" --timestamp -o runtime --entitlements "${APP}/Contents/MacOS/bin/Entitlements.plist" "${APP}/Contents/MacOS/bin/rawtherapee-bin" -codesign --deep --preserve-metadata=identifier,entitlements,runtime --strict -v -s "${CODESIGNID}" -i "com.rawtherapee.rawtherapee" --timestamp -o runtime --entitlements "${APP}/Contents/Entitlements.plist" "${APP}" - spctl -a -vvvv "${APP}" +plutil -convert xml1 "${CONTENTS}/MacOS/bin/Entitlements.plist" +codesign -v -s "${CODESIGNID}" -i "com.rawtherapee.rawtherapee-bin" -o runtime --timestamp --entitlements "${APP}/Contents/MacOS/bin/Entitlements.plist" "${APP}/Contents/MacOS/bin/rawtherapee-bin" +for frameworklibs in ${CONTENTS}/Frameworks/* ; do + codesign -v -s "${CODESIGNID}" -i "com.rawtherapee.rawtherapee-bin" -o runtime --timestamp "${frameworklibs}" +done +codesign --deep --preserve-metadata=identifier,entitlements,runtime --timestamp --strict -v -s "${CODESIGNID}" -i "com.rawtherapee.RawTherapee" -o runtime --entitlements "${CONTENTS}/Entitlements.plist" "${APP}" +spctl -a -vvvv "${APP}" fi # Notarize the app NOTARY="$(cmake .. -LA -N | grep "NOTARY" | cut -d "=" -f2)" if ! test -z "$NOTARY" ; then + msg "Notarizing the application:" ditto -c -k --sequesterRsrc --keepParent "${APP}" "${APP}.zip" - uuid=`xcrun altool --notarize-app --primary-bundle-id "com.rawtherapee.rawtherapee" ${NOTARY} --file "${APP}.zip" 2>&1 | grep 'RequestUUID' | awk '{ print $3 }'` + uuid=`xcrun altool --notarize-app --primary-bundle-id "com.rawtherapee.RawTherapee" ${NOTARY} --file "${APP}.zip" 2>&1 | grep 'RequestUUID' | awk '{ print $3 }'` echo "Result= $uuid" # Display identifier string sleep 15 while : @@ -254,7 +296,7 @@ function CreateDmg { msg "Preparing disk image sources at ${srcDir}:" cp -R "${APP}" "${srcDir}" - cp AboutThisBuild.txt "${srcDir}" + ditto AboutThisBuild.txt "${srcDir}" ln -s /Applications "${srcDir}" # Web bookmarks @@ -281,7 +323,9 @@ function CreateDmg { fi # Notarize the dmg - if ! test -z "$NOTARY" ; then + + if ! test -z "$NOTARY" ; then + msg "Notarizing the dmg:" zip "${dmg_name}.dmg.zip" "${dmg_name}.dmg" uuid=`xcrun altool --notarize-app --primary-bundle-id "com.rawtherapee" ${NOTARY} --file "${dmg_name}.dmg.zip" 2>&1 | grep 'RequestUUID' | awk '{ print $3 }'` echo "dmg Result= $uuid" # Display identifier string @@ -305,9 +349,10 @@ function CreateDmg { fi done fi + +# Zip disk image for redistribution + msg "Zipping disk image for redistribution:" - - # Zip disk image for redistribution zip "${dmg_name}.zip" "${dmg_name}.dmg" AboutThisBuild.txt rm "${dmg_name}.dmg" @@ -315,3 +360,5 @@ function CreateDmg { rm -rf "${srcDir}" } CreateDmg +msg "Finishing build:" +echo "Script complete." diff --git a/tools/osx/rt.entitlements b/tools/osx/rt.entitlements index 2236af138..082661401 100644 --- a/tools/osx/rt.entitlements +++ b/tools/osx/rt.entitlements @@ -1,20 +1,20 @@ - - application-identifier - com.rawtherapee.rawtherapee - com.apple.security.temporary-exception.files.absolute-path.read-write - - "/" - - com.apple.security.cs.allow-dyld-environment-variables - - com.apple.security.files.user-selected.read-write - - com.apple.security.app-sandbox - - com.apple.security.files.downloads.read-write - - + + application-identifier + com.rawtherapee.rawtherapee + com.apple.security.temporary-exception.files.absolute-path.read-write + + "/" + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.files.user-selected.read-write + + com.apple.security.app-sandbox + + com.apple.security.files.downloads.read-write + +