Merge branch 'dev' into tone-equalizer

This commit is contained in:
Lawrence Lee 2023-02-05 18:39:23 -08:00
commit f236a7edb7
No known key found for this signature in database
GPG Key ID: 048FF2B76A63895F
271 changed files with 52609 additions and 8579 deletions

View File

@ -1,8 +1,9 @@
name: Build AppImage
name: AppImage Build
on:
push:
branches:
- dev
- releases
tags:
- '[0-9]+.*'
pull_request:
@ -76,6 +77,8 @@ jobs:
- name: Include Lensfun
run: |
echo "Patching lensfun-update-data script."
sudo sed -i 's/HTTPError\(, ValueError\)/URLError\1/' $(which lensfun-update-data)
echo "Updating Lensfun database."
lensfun-update-data
echo "Creating Lensfun directory in the build directory."
@ -87,7 +90,7 @@ jobs:
id: appimage-tools-cache
uses: actions/cache@v2
with:
key: appimage-tools
key: appimage-tools-1
path: |
./build/linuxdeploy-x86_64.AppImage
./build/linuxdeploy-plugin-gtk.sh
@ -99,7 +102,9 @@ jobs:
echo "Downloading linuxdeploy."
curl --location 'https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage' > linuxdeploy-x86_64.AppImage
echo "Downloading GTK plugin for linuxdeploy."
curl --location 'https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh' > linuxdeploy-plugin-gtk.sh
curl --location 'https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh' \
| sed 's/^\(export GTK_THEME\)/#\1/' \
> linuxdeploy-plugin-gtk.sh
echo "Setting execute bit on all AppImage tools."
chmod u+x linuxdeploy-*

89
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,89 @@
name: "CodeQL"
on:
push:
branches: [ 'dev' ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ 'dev' ]
schedule:
- cron: '56 5 * * 1'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
build_type: [release]
language: [ 'cpp', 'python' ]
steps:
- name: Checkout source
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Install dependencies
run: |
echo "Running apt update."
sudo apt update
echo "Installing dependencies with apt."
DEBIAN_FRONTEND=noninteractive sudo apt install -y cmake libgtk-3-dev libgtkmm-3.0-dev liblensfun-dev librsvg2-dev liblcms2-dev libfftw3-dev libiptcdata0-dev libtiff5-dev libcanberra-gtk3-dev liblensfun-bin
- name: Configure build
run: |
export REF_NAME_FILTERED="$(echo '${{github.ref_name}}' | sed 's/[^A-z0-9_.-]//g')"
echo "Setting cache suffix."
if [ '${{github.ref_type}}' == 'tag' ]; then
export CACHE_SUFFIX=""
else
export CACHE_SUFFIX="5-$REF_NAME_FILTERED"
fi
export CACHE_SUFFIX="$CACHE_SUFFIX-AppImage"
echo "Cache suffix is '$CACHE_SUFFIX'."
echo "Making build directory."
mkdir build
echo "Changing working directory to the build directory."
cd build
echo "Running CMake configure."
cmake \
-DCMAKE_BUILD_TYPE='${{matrix.build_type}}' \
-DCACHE_NAME_SUFFIX="$CACHE_SUFFIX" \
-DPROC_TARGET_NUMBER="1" \
-DBUILD_BUNDLE="ON" \
-DBUNDLE_BASE_INSTALL_DIR="/" \
-DOPTION_OMP="ON" \
-DWITH_LTO="OFF" \
-DWITH_PROF="OFF" \
-DWITH_SAN="OFF" \
-DWITH_SYSTEM_KLT="OFF" \
-DCMAKE_INSTALL_PREFIX=/usr \
-DLENSFUNDBDIR="../share/lensfun/version_1" \
..
echo "Recording filtered ref name."
echo "REF_NAME_FILTERED=$REF_NAME_FILTERED" >> $GITHUB_ENV
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
- name: Build RawTherapee
working-directory: ./build
run: |
echo "Running make install."
make -j$(nproc) install DESTDIR=AppDir/usr/bin
echo "Moving usr/bin/share to usr/share."
mv AppDir/usr/bin/share AppDir/usr/
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

View File

@ -1,20 +1,18 @@
name: macOS build
name: macOS Build
on:
push:
branches:
- dev
- patch**
- newlocallab
- releases
tags:
- '[0-9]+.*'
pull_request:
branches:
- dev
- newlocallab
release:
types:
- created
workflow_dispatch:
jobs:
build:
runs-on: macos-latest
runs-on: macos-11
steps:
- uses: actions/checkout@v2
- name: Install dependencies
@ -23,7 +21,7 @@ jobs:
mkdir build
date +%s > build/stamp
brew uninstall --ignore-dependencies libtiff
brew install libtiff gtk+3 gtkmm3 gtk-mac-integration adwaita-icon-theme libsigc++@2 little-cms2 libiptcdata fftw lensfun expat pkgconfig libomp shared-mime-info | tee -a depslog
brew install libtiff gtk+3 gtkmm3 gtk-mac-integration adwaita-icon-theme libsigc++@2 little-cms2 libiptcdata fftw lensfun expat pkgconfig llvm shared-mime-info | tee -a depslog
date -u
echo "----====Pourage====----"
cat depslog | grep Pouring
@ -52,8 +50,8 @@ jobs:
-DPROC_LABEL="generic processor" \
-DWITH_LTO="OFF" \
-DLENSFUNDBDIR="/Applications/RawTherapee.app/Contents/Resources/share/lensfun" \
-DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_FLAGS="-arch x86_64 -Wno-pass-failed -Wno-deprecated-register -Wno-unused-command-line-argument" \
-DCMAKE_CXX_FLAGS="-arch x86_64 -Wno-pass-failed -Wno-deprecated-register -Wno-unused-command-line-argument" \
-DOpenMP_C_FLAGS="${C_FLAGS}" \
@ -65,6 +63,7 @@ jobs:
-DCMAKE_RANLIB=/usr/bin/ranlib \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 \
..
curl -L https://github.com/Homebrew/homebrew-core/raw/679923b4eb48a8dc7ecc1f05d06063cd79b3fc00/Formula/libomp.rb -o libomp.rb && brew install libomp.rb
zsh -c 'echo "Configured in $(printf "%0.2f" $(($[$(date +%s)-$(cat configstamp)]/$((60.))))) minutes"'
- name: Compile RawTherapee
run: |
@ -85,6 +84,12 @@ jobs:
echo "ARTIFACT_PATH=${GITHUB_WORKSPACE}/build/${ARTIFACT}" >> $GITHUB_ENV
echo "ARTIFACT_FILE=${ARTIFACT}" >> $GITHUB_ENV
zsh -c 'echo "Bundled in $(printf "%0.2f" $(($[$(date +%s)-$(cat bundlestamp)]/$((60.))))) minutes"'
printf '%s\n' \
"REF: ${REF}" \
"ARTIFACT: ${ARTIFACT}" \
"ARTIFACT_PATH: ${ARTIFACT_PATH}" \
"ARTIFACT_FILE: ${ARTIFACT_FILE}" \
"PUBLISH_NAME: ${PUBLISH_NAME}"
exit
- uses: actions/upload-artifact@v2
with:
@ -94,3 +99,11 @@ jobs:
run: |
date -u
zsh -c 'echo "Build completed in $(printf "%0.2f" $(($[$(date +%s)-$(cat build/stamp)]/$((60.))))) minutes"'
- name: Publish artifacts
uses: softprops/action-gh-release@v1
if: ${{github.ref_type == 'tag' || github.ref_name == 'dev'}}
with:
tag_name: nightly-github-actions
files: |
${{env.ARTIFACT_PATH}}

View File

@ -3,6 +3,7 @@ on:
push:
branches:
- dev
- releases
tags:
- '[0-9]+.*'
pull_request:
@ -82,6 +83,8 @@ jobs:
- name: Include Lensfun
run: |
echo "Patching lensfun-update-data script."
sed -i 's/HTTPError\(, ValueError\)/URLError\1/' $(which lensfun-update-data)
echo "Updating Lensfun database."
lensfun-update-data
echo "Creating Lensfun directory in the build directory."
@ -115,7 +118,7 @@ jobs:
"libdeflate.dll" \
"libepoxy-0.dll" \
"libexpat-1.dll" \
"libffi-7.dll" \
libffi-*.dll \
"libfftw3f-3.dll" \
"libfontconfig-1.dll" \
"libfreetype-6.dll" \
@ -148,15 +151,16 @@ jobs:
"libpangoft2-1.0-0.dll" \
"libpangomm-1.4-1.dll" \
"libpangowin32-1.0-0.dll" \
"libpcre-1.dll" \
"libpcre2-8-0.dll" \
"libpixman-1-0.dll" \
"libpng16-16.dll" \
"librsvg-2-2.dll" \
"libsharpyuv-0.dll" \
"libsigc-2.0-0.dll" \
"libstdc++-6.dll" \
"libsystre-0.dll" \
"libthai-0.dll" \
"libtiff-5.dll" \
"libtiff-6.dll" \
"libtre-5.dll" \
"libwebp-7.dll" \
"libwinpthread-1.dll" \

View File

@ -6,6 +6,7 @@ Project initiator:
Development contributors, in last name alphabetical order:
Roel Baars
Richard E Barber
Martin Burri
Pierre Cabrera
Javier Celaya
@ -63,11 +64,13 @@ Other contributors (profiles, ideas, mockups, testing, forum activity, translati
Lebarhon
Karl Loncarek
Patrick Lopatto
Francisco Lorés
Jie Luo
Paul Matthijsse
Wim ter Meer
Alberto Righetto
Kostia (Kildor) Romanov
Henning Sidow
Kalle Söderman
Wayne Sutton
Johan Thor
@ -75,3 +78,4 @@ Other contributors (profiles, ideas, mockups, testing, forum activity, translati
TooWaBoo
Franz Trischberger
Colin Walker
Martin Werner

View File

@ -45,10 +45,14 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION
endif()
# Warning for GCC vectorization issues, which causes problems #5749 and #6384:
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND ((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "10.0" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10.2") OR (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "11.0")))
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "10.0" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10.2")
message(STATUS "WARNING: gcc ${CMAKE_CXX_COMPILER_VERSION} is known to miscompile RawTherapee when using -ftree-loop-vectorize, forcing the option to be off")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-tree-loop-vectorize")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-tree-loop-vectorize")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "11.0")
message(STATUS "WARNING: gcc ${CMAKE_CXX_COMPILER_VERSION} is known to miscompile RawTherapee when using --ffp-contract=fast, forcing the option to be off")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffp-contract=off")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffp-contract=off")
endif()
# We might want to build using the old C++ ABI, even when using a new GCC
@ -80,6 +84,24 @@ set(CACHE_NAME_SUFFIX
# being bundled. However, file access can be restricted for some folder.
option(OSX_DEV_BUILD "Generate macOS development builds" OFF)
# On macOS, optionally generate the final zip artifact file without version in the name for nightly upload purposes.
option(OSX_NIGHTLY "Generate a generically-named zip" OFF)
# Generate a universal macOS build
option(OSX_UNIVERSAL "Generate a universal app" OFF)
# On macOS: merge the app via a specific url to generate a universal bundle with both x86_64 and arm64
if(OSX_UNIVERSAL)
if(NOT "${OSX_UNIVERSAL_URL}")
if(CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
set(OSX_UNIVERSAL_URL "https://kd6kxr.keybase.pub/RawTherapee_macOS_x86_64_latest.zip" CACHE STRING "URL of x86_64 app for lipo")
else()
set(OSX_UNIVERSAL_URL "https://kd6kxr.keybase.pub/RawTherapee_macOS_arm64_latest.zip" CACHE STRING "URL of arm64 app for lipo")
endif()
endif()
endif()
# By default we don't use a specific processor target, so PROC_TARGET_NUMBER is
# set to 0. Specify other values to optimize for specific processor architecture
# as listed in ProcessorTargets.cmake:
@ -725,7 +747,7 @@ add_custom_target(
# End generating AboutThisBuild.txt
install(FILES AUTHORS.txt DESTINATION "${CREDITSDIR}")
install(FILES LICENSE.txt DESTINATION "${LICENCEDIR}")
install(FILES LICENSE DESTINATION "${LICENCEDIR}")
install(FILES "${CMAKE_BINARY_DIR}/AboutThisBuild.txt"
DESTINATION "${CREDITSDIR}")
install(

View File

@ -1,20 +1,3 @@
RawTherapee - A powerful, cross-platform raw image processing program.
Copyright (C) 2004-2012 Gabor Horvath <hgabor@rawtherapee.com>
Copyright (C) 2010-2021 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 this program. If not, see <https://www.gnu.org/licenses/>.
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007

View File

@ -38,5 +38,8 @@ set(PROC_TARGET_8_FLAGS "-march=athlon64" CACHE STRING "Processor-8 flags")
set(PROC_TARGET_9_LABEL phenomX4 CACHE STRING "Processor-9 label - use it to provide a phenomX4 optimized build, if you have this processor")
set(PROC_TARGET_9_FLAGS "-march=amdfam10" CACHE STRING "Processor-9 flags")
set(PROC_TARGET_10_LABEL sandybridge-ivybridge CACHE STRING "Processor set-10 label")
set(PROC_TARGET_10_FLAGS "-march=sandybridge -mtune=ivybridge" CACHE STRING "Processors set-10 flags")
#set(PROC_TARGET__LABEL procLabel CACHE STRING "Processor- label")
#set(PROC_TARGET__FLAGS "procFlags" CACHE STRING "Processor- flags")

View File

@ -1,4 +1,6 @@
![RawTherapee logo](https://www.rawtherapee.com/images/logos/rawtherapee_logo_discuss.png)
![RawTherapee logo](https://raw.githubusercontent.com/Beep6581/RawTherapee/dev/rtdata/images/rt-logo-text-black.svg)
![RawTherapee screenshot](http://rawtherapee.com/images/carousel/100_rt59_provence_local_maskxxx.jpg)
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.

View File

@ -1,21 +1,14 @@
RAWTHERAPEE 5.8-dev RELEASE NOTES
RAWTHERAPEE 5.9-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.
IN GENERAL
Start by reading the "Getting Started" article on RawPedia:
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
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.
NEWS RELEVANT TO PHOTOGRAPHERS
RawTherapee supports most raw formats, including Pentax and Sony Pixel Shift, Canon Dual-Pixel, and those from Foveon and X-Trans sensors.
If you're wondering whether it supports your camera's raw format, first download RawTherapee and try for yourself. If a raw format is not supported it will either not open, or the preview in the Editor tab will appear black, white, or have a strong color cast - usually magenta. In that case, read the "Adding Support for New Raw Formats" RawPedia article.
@ -25,15 +18,21 @@ In order to use RawTherapee efficiently you should know that:
- To change slider values or drop-down list items with the mouse scroll-wheel, hold the Shift key. This is so that you can safely scroll the panels without accidentally changing a slider or other tool setting.
- 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!
- All sliders support a fine-tuning mode which you can toggle by pressing the Shift key while dragging a slider.
NEW FEATURES SINCE 5.9
New features since 5.8:
- TODO
- Added or improved support for cameras, raw formats and color profiles:
- TODO
NEWS RELEVANT TO PACKAGE MAINTAINERS
New since 5.8:
New since 5.9:
- TODO
In general:
@ -74,18 +73,6 @@ https://discuss.pixls.us/c/software/rawtherapee
LIVE CHAT WITH USERS AND DEVELOPERS
Network: freenode
Server: chat.freenode.net
Channel: #rawtherapee
You can use freenode webchat to communicate without installing anything:
https://webchat.freenode.net/?randomnick=1&channels=rawtherapee&prompt=1
More information here: https://rawpedia.rawtherapee.com/IRC
REVISION HISTORY
The complete changelog is available at:

View File

@ -106,9 +106,9 @@ if(WIN32)
elseif(BIT_DEPTH EQUAL 8)
set(BUILD_BIT_DEPTH 64)
# Restricting the 64 bits builds to 64 bits systems only
set(ARCHITECTURE_ALLOWED "x64 ia64")
set(ARCHITECTURE_ALLOWED "x64 ia64 arm64")
# installing in 64 bits mode for all 64 bits processors, even for itanium architecture
set(INSTALL_MODE "x64 ia64")
set(INSTALL_MODE "x64 ia64 arm64")
endif()
# set part of the output archive name
set(SYSTEM_NAME "WinVista")

View File

@ -22,6 +22,7 @@
<url type="translate">https://rawpedia.rawtherapee.com/Main_Page#Localization</url>
<launchable type="desktop-id">rawtherapee.desktop</launchable>
<releases>
<release version="5.9" date="2022-11-27" type="stable"></release>
<release version="5.8" date="2020-02-04" type="stable"></release>
<release version="5.7" date="2019-09-10" type="stable"></release>
<release version="5.6" date="2019-04-20" type="stable"></release>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View File

@ -7,7 +7,7 @@
viewBox="0 0 160 99.999999"
version="1.1"
id="svg783"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)"
sodipodi:docname="splash_template.svg"
inkscape:export-filename="/tmp/splash.png"
inkscape:export-xdpi="96"
@ -151,10 +151,10 @@
style="stop-color:#feab27;stop-opacity:1;" />
</linearGradient>
<filter
width="1.481184"
width="1.4802108"
height="4.2913185"
y="-1.6456592"
x="-0.24059201"
x="-0.24010539"
inkscape:label="RawTherapee white"
id="filter4749"
style="color-interpolation-filters:sRGB"
@ -236,10 +236,10 @@
operator="in" />
</filter>
<filter
width="1.3101092"
width="1.3101085"
height="3.1717951"
y="-1.0858975"
x="-0.15505461"
x="-0.15505423"
inkscape:label="RawTherapee white"
id="filter4749-3"
style="color-interpolation-filters:sRGB"
@ -882,9 +882,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.8015102"
inkscape:cx="575.62815"
inkscape:cy="212.32186"
inkscape:zoom="2.6083441"
inkscape:cx="546.32363"
inkscape:cy="219.8713"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
@ -908,10 +908,10 @@
inkscape:object-nodes="false"
inkscape:snap-nodes="true"
inkscape:snap-global="false"
inkscape:window-width="3440"
inkscape:window-height="1387"
inkscape:window-x="3832"
inkscape:window-y="-8"
inkscape:window-width="3840"
inkscape:window-height="2075"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:measure-start="416.334,192.525"
inkscape:measure-end="422.317,192.368"
@ -920,14 +920,48 @@
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
width="157.40977mm" />
width="157.40977mm"
inkscape:showpageshadow="2"
inkscape:deskcolor="#d1d1d1">
<sodipodi:guide
position="13.081061,8.9833331"
orientation="0,1"
id="guide6595"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" />
<sodipodi:guide
position="153.15072,8.9833384"
orientation="-1,0"
id="guide15125"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" />
</sodipodi:namedview>
<metadata
id="metadata780">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:title>RawTherapee splash screen</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
@ -1120,7 +1154,7 @@
id="tspan40748"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:11.9944px;font-family:'ITC Eras Std';-inkscape-font-specification:'ITC Eras Std Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.537916"
x="64.642754"
y="252.72681">8</tspan></text>
y="252.72681">9</tspan></text>
<text
xml:space="preserve"
style="font-size:11.9944px;line-height:1.25;font-family:'Eras BQ';-inkscape-font-specification:'Eras BQ';opacity:1;fill:#ffffff;fill-opacity:1;stroke-width:0.537916"
@ -1138,160 +1172,162 @@
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333px;line-height:1.25;font-family:'Eras BQ';-inkscape-font-specification:'Eras BQ';letter-spacing:0px;word-spacing:-0.132292px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.0495763px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4749);enable-background:new"
x="5.3633847"
y="277.27142"
y="277.12344"
id="text45159"><tspan
sodipodi:role="line"
id="tspan45157"
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:4.23333px;font-family:'ITC Eras Std';-inkscape-font-specification:'ITC Eras Std Medium';fill:#ffffff;fill-opacity:1;stroke-width:0.0495763px"
x="5.3633847"
y="277.27142">GNU GPLv3</tspan></text>
y="277.12344">GNU GPLv3</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,-4.6433668,186.15341)"
id="text181036"
style="font-size:21.3333px;line-height:1.25;font-family:'Eras BQ';-inkscape-font-specification:'Eras BQ';white-space:pre;shape-inside:url(#rect181038)" />
style="font-size:21.3333px;line-height:1.25;font-family:'Eras BQ';-inkscape-font-specification:'Eras BQ';white-space:pre;shape-inside:url(#rect181038);display:inline" />
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,280.11612,189.68435)"
id="text183258"
style="font-size:16px;line-height:1.25;font-family:'Eras BQ';-inkscape-font-specification:'Eras BQ';white-space:pre;shape-inside:url(#rect183260)"><tspan
style="font-size:16px;line-height:1.25;font-family:'Eras BQ';-inkscape-font-specification:'Eras BQ';white-space:pre;shape-inside:url(#rect183260);display:inline"><tspan
x="-430.18945"
y="2.3808594"
id="tspan1665"><tspan
y="2.7826123"
id="tspan17773"><tspan
style="font-weight:bold;font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1661">Prerequisites</tspan><tspan
id="tspan17769">Prerequisites</tspan><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1663">
id="tspan17771">
</tspan></tspan><tspan
x="-430.18945"
y="22.380859"
id="tspan1669"><tspan
y="22.782612"
id="tspan17777"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1667">Obtain and install the font family ITC Eras Std.
id="tspan17775">Obtain and install the font family ITC Eras Std.
</tspan></tspan><tspan
x="-430.18945"
y="42.380859"
id="tspan1673"><tspan
y="42.782612"
id="tspan17781"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1671">
id="tspan17779">
</tspan></tspan><tspan
x="-430.18945"
y="62.380859"
id="tspan1679"><tspan
y="62.782612"
id="tspan17787"><tspan
style="font-weight:bold"
id="tspan1675">Details</tspan><tspan
id="tspan17783">Details</tspan><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1677">
id="tspan17785">
</tspan></tspan><tspan
x="-430.18945"
y="82.380859"
id="tspan1683"><tspan
y="82.782612"
id="tspan17791"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1681">The color wheel is copied from rt-logo.svg and a glow filter is added
id="tspan17789">The color wheel is copied from rt-logo.svg and a glow filter is added
</tspan></tspan><tspan
x="-430.18945"
y="102.38086"
id="tspan1687"><tspan
y="102.78261"
id="tspan17795"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1685">to each segment and the wheel as a whole.
id="tspan17793">to each segment and the wheel as a whole.
</tspan></tspan><tspan
x="-430.18945"
y="122.38086"
id="tspan1691"><tspan
y="122.78261"
id="tspan17799"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1689">&quot;Raw&quot;: font ITC Eras Ultra-Bold, 60 pt, -3 px letter spacing
id="tspan17797">&quot;Raw&quot;: font ITC Eras Ultra-Bold, 60 pt, -3 px letter spacing
</tspan></tspan><tspan
x="-430.18945"
y="142.38086"
id="tspan1695"><tspan
y="142.78261"
id="tspan17803"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1693">&quot;Therapee&quot;: font ITC Eras Medium, 60 pt, +1,5 pt letter spacing
id="tspan17801">&quot;Therapee&quot;: font ITC Eras Medium, 60 pt, +1,5 pt letter spacing
</tspan></tspan><tspan
x="-430.18945"
y="162.38086"
id="tspan1699"><tspan
y="162.78261"
id="tspan17807"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1697">Version (big number): ITC Eras Bold, 58 pt, skewed -3°
id="tspan17805">Version (big number): ITC Eras Bold, 58 pt, skewed -3°
</tspan></tspan><tspan
x="-430.18945"
y="182.38086"
id="tspan1703"><tspan
y="182.78261"
id="tspan17811"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1701">Version (period + small number): ITC Eras Bold, 34 pt, skewed -3°
id="tspan17809">Version (period + small number): ITC Eras Bold, 34 pt, skewed -3°
</tspan></tspan><tspan
x="-430.18945"
y="202.38086"
id="tspan1707"><tspan
y="202.78261"
id="tspan17815"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1705">Release-type: ITC Eras Bold, 16 pt, skewed -3°
id="tspan17813">Release-type: ITC Eras Bold, 16 pt, skewed -3°
</tspan></tspan><tspan
x="-430.18945"
y="222.38086"
id="tspan1711"><tspan
y="222.78261"
id="tspan17819"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1709">
id="tspan17817">
</tspan></tspan><tspan
x="-430.18945"
y="242.38086"
id="tspan1717"><tspan
y="242.78261"
id="tspan17825"><tspan
style="font-weight:bold"
id="tspan1713">Publishing</tspan><tspan
id="tspan17821">Publishing</tspan><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1715">
id="tspan17823">
</tspan></tspan><tspan
x="-430.18945"
y="262.38086"
id="tspan1721"><tspan
y="262.78261"
id="tspan17831"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1719">1. To prepare a splash screen for deployment, select all text and </tspan></tspan><tspan
id="tspan17827">1. To prepare a splash screen for deployment, select all text and </tspan><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan17829">choose </tspan></tspan><tspan
x="-430.18945"
y="282.38086"
id="tspan1725"><tspan
y="282.78261"
id="tspan17835"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1723">choose Path &gt; Object to Path.
id="tspan17833">Path &gt; Object to Path.
</tspan></tspan><tspan
x="-430.18945"
y="302.38086"
id="tspan1729"><tspan
y="302.78261"
id="tspan17839"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1727">2. Change release type text to whatever is required, or hide the layer </tspan></tspan><tspan
id="tspan17837">2. Change release type text to whatever is required, or hide the layer </tspan></tspan><tspan
x="-430.18945"
y="322.38086"
id="tspan1733"><tspan
y="322.78261"
id="tspan17843"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1731">&quot;Release type&quot; entirely.
id="tspan17841">&quot;Release type&quot; entirely.
</tspan></tspan><tspan
x="-430.18945"
y="342.38086"
id="tspan1737"><tspan
y="342.78261"
id="tspan17847"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1735">3. Remove this text field.
id="tspan17845">3. Remove this text field.
</tspan></tspan><tspan
x="-430.18945"
y="362.38086"
id="tspan1743"><tspan
y="362.78261"
id="tspan17853"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1739">4</tspan><tspan
id="tspan17849">4</tspan><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1741">. Save as &quot;splash.svg&quot; into &quot;./rtdata/images/svg&quot;.
id="tspan17851">. Save as &quot;splash.svg&quot; into &quot;./rtdata/images/svg&quot;.
</tspan></tspan><tspan
x="-430.18945"
y="382.38086"
id="tspan1747"><tspan
y="382.78261"
id="tspan17857"><tspan
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
id="tspan1745">
id="tspan17855">
</tspan></tspan><tspan
x="-430.18945"
y="402.38086"
id="tspan1751"><tspan
y="402.78261"
id="tspan17861"><tspan
style="font-style:italic"
id="tspan1749">RawTherapee splash screen design 1.5 (March 2022)
id="tspan17859">RawTherapee splash screen design 1.5 (March 2022)
</tspan></tspan><tspan
x="-430.18945"
y="422.38086"
id="tspan1755"><tspan
y="422.78261"
id="tspan17865"><tspan
style="font-style:italic"
id="tspan1753">www.rawtherapee.com</tspan></tspan></text>
id="tspan17863">www.rawtherapee.com</tspan></tspan></text>
</g>
<g
inkscape:groupmode="layer"
@ -1304,7 +1340,7 @@
x="99.720383"
y="268.50891"
id="text119139"
transform="matrix(1,0,0.05240778,1,4.4229627,-187.87494)"><tspan
transform="matrix(1,0,0.05240778,1,8.1272209,-177.55141)"><tspan
sodipodi:role="line"
id="tspan119137"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.93889px;font-family:'ITC Eras Std';-inkscape-font-specification:'ITC Eras Std Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.211231"

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 54 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4073
rtdata/languages/Dansk Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -760,6 +760,23 @@ button.radio#histButton:hover {
margin-right: 0.25em;
}
/* ExpanderContents is just a logical container. Don't add additional spacing. */
#ExpanderBox > .ExpanderContents > * {
margin: 0;
min-height: 0;
padding: 0;
}
/* For sub-tools containers that go below another widget, add some margin
* between them if the container has children. */
#MyExpander .SubToolsContainer:not(:first-child) > :first-child {
margin-top: 0.1666666666666666em;
}
#MyExpander .SubToolsContainer {
min-height: 0;
}
/* Tool background */
#ExpanderBox > box, #ExpanderBox > grid {
background-color: #363636;
@ -808,9 +825,11 @@ button.radio#histButton:hover {
}
#LocallabToolPanel > box > checkbutton, #LocallabToolPanel > box > box, #LocallabToolPanel > grid > checkbutton, #LocallabToolPanel > box > grid, #LocallabToolPanel > grid > grid, #LocallabToolPanel frame > box > grid, #LocallabToolPanel frame > grid > grid, #LocallabToolPanel frame > grid > box,
#ExpanderBox > box > checkbutton, #ExpanderBox > box > box, #ExpanderBox > grid > checkbutton, #ExpanderBox > box > grid, #ExpanderBox > grid > grid, #ExpanderBox frame > box > grid, #ExpanderBox frame > grid > grid, #ExpanderBox frame > grid > box,
#ExpanderBox2 > box > checkbutton, #ExpanderBox2 > box > box, #ExpanderBox2 > grid > checkbutton, #ExpanderBox2 > box > grid, #ExpanderBox2 > grid > grid, #ExpanderBox2 frame > box > grid, #ExpanderBox2 frame > grid > grid, #ExpanderBox2 frame > grid > box,
#ExpanderBox3 > box > checkbutton, #ExpanderBox3 > box > box, #ExpanderBox3 > grid > checkbutton, #ExpanderBox3 > box > grid, #ExpanderBox3 > grid > grid, #ExpanderBox3 frame > box > grid, #ExpanderBox3 frame > grid > grid, #ExpanderBox3 frame > grid > box {
#ExpanderBox > .ExpanderContents > box:not(.SubToolsContainer) > checkbutton, #ExpanderBox > .ExpanderContents > box:not(.SubToolsContainer) > box, #ExpanderBox > .ExpanderContents > grid > checkbutton, #ExpanderBox > .ExpanderContents > box:not(.SubToolsContainer) > grid, #ExpanderBox > .ExpanderContents > grid > grid, #ExpanderBox frame > box > grid, #ExpanderBox frame > grid > grid, #ExpanderBox frame > grid > box,
#ExpanderBox2 > .ExpanderContents > box:not(.SubToolsContainer) > checkbutton, #ExpanderBox2 > .ExpanderContents > box:not(.SubToolsContainer) > box, #ExpanderBox2 > .ExpanderContents > grid > checkbutton, #ExpanderBox2 > .ExpanderContents > box:not(.SubToolsContainer) > grid, #ExpanderBox2 > .ExpanderContents > grid > grid, #ExpanderBox2 frame > box > grid, #ExpanderBox2 frame > grid > grid, #ExpanderBox2 frame > grid > box,
#ExpanderBox2 > box:not(.ExpanderContents) > checkbutton, #ExpanderBox2 > box:not(.ExpanderContents) > box, #ExpanderBox2 > grid > checkbutton, #ExpanderBox2 > box:not(.ExpanderContents) > grid, #ExpanderBox2 > grid > grid, #ExpanderBox2 frame > box > grid, #ExpanderBox2 frame > grid > grid, #ExpanderBox2 frame > grid > box,
#ExpanderBox3 > .ExpanderContents > box:not(.SubToolsContainer) > checkbutton, #ExpanderBox3 > .ExpanderContents > box:not(.SubToolsContainer) > box, #ExpanderBox3 > .ExpanderContents > grid > checkbutton, #ExpanderBox3 > .ExpanderContents > box:not(.SubToolsContainer) > grid, #ExpanderBox3 > .ExpanderContents > grid > grid, #ExpanderBox3 frame > box > grid, #ExpanderBox3 frame > grid > grid, #ExpanderBox3 frame > grid > box,
#ExpanderBox3 > box:not(.ExpanderContents) > checkbutton, #ExpanderBox3 > box:not(.ExpanderContents) > box, #ExpanderBox3 > grid > checkbutton, #ExpanderBox3 > box:not(.ExpanderContents) > grid, #ExpanderBox3 > grid > grid, #ExpanderBox3 frame > box > grid, #ExpanderBox3 frame > grid > grid, #ExpanderBox3 frame > grid > box {
margin-top: 0.1666666666666666em;
}
@ -1099,6 +1118,10 @@ dialog frame > label:not(.dummy) {
min-width: 25em;
}
#ToolPanelNotebook .PanelEnding {
margin-top: 4px;
}
#ToolPanelNotebook header {
background-color: #383838;
border-color: #262626;

View File

@ -758,7 +758,7 @@ button.radio#histButton:hover {
#MyExpander:first-child {
border-top: none;
}
#MyExpander:nth-last-child(2),
#MyExpander:nth-last-child(1),
#MyExpander #MyExpander:nth-last-child(1) {
border-bottom: 0.0833333333333333em solid rgba(0,0,0,0.3);
}
@ -766,6 +766,29 @@ button.radio#histButton:hover {
border-bottom: none;
}
/* ExpanderContents is just a logical container. Don't add additional spacing. */
#ExpanderBox > .ExpanderContents > * {
margin: 0;
min-height: 0;
padding: 0;
}
/* For sub-tools containers that go below another widget, add some margin
* between them if the container has children. */
#MyExpander .SubToolsContainer:not(:first-child) > :first-child {
margin-top: 0.3333333333333333em;
}
#MyExpander .SubToolsContainer {
min-height: 0;
}
.SubToolsContainer > #MyExpander,
.ToolParamBlock > #MyExpander,
.ExpanderContents,
#MyExpander .ToolParamBlock {
margin: 0;
}
/* Tool background */
#ExpanderBox > box,
@ -1046,6 +1069,10 @@ dialog frame > label:not(.dummy) {
padding: 0;
}
#ToolPanelNotebook .PanelEnding {
margin-top: 4px;
}
#ToolPanelNotebook header tabs {
padding: 0.0833333333333333em;
background-color: #2A2A2A;

View File

@ -963,6 +963,9 @@ window.csd:not(.fullscreen) #MainNotebook > header.top {
#ToolPanelNotebook {
background-color: @bg-dark-grey;
}
#ToolPanelNotebook .PanelEnding {
margin-top: 4px;
}
#ToolPanelNotebook > header {
border-bottom: 0.083333333333333333em solid @view-grid-border;
margin-left: 0.083333333333333333em;
@ -1278,6 +1281,11 @@ menuitem:hover > * {
color: @text-hl-color;
}
menu menuitem > radio + * image:not(.dummy),
#MyExpander menu menuitem > radio + * image:not(.dummy) {
margin-left: 1pt;
}
menu image:not(.dummy),
#MyExpander menu image:not(.dummy) {
min-height: 2em;

View File

@ -383,6 +383,11 @@ menu arrow {
margin: 0 -0.25em 0 0;
}
menu menuitem > radio + * image:not(.dummy),
#MyExpander menu menuitem > radio + * image:not(.dummy) {
margin-left: 1pt;
}
menu image:not(.dummy),
#MyExpander menu image:not(.dummy) {
min-height: 2em;

View File

@ -351,6 +351,11 @@ menu arrow {
margin: 0 -0.25em 0 0;
}
menu menuitem > radio + * image:not(.dummy),
#MyExpander menu menuitem > radio + * image:not(.dummy) {
margin-left: 1pt;
}
menu image:not(.dummy),
#MyExpander menu image:not(.dummy) {
min-height: 2em;

View File

@ -177,6 +177,19 @@ if(LENSFUN_HAS_LOAD_DIRECTORY)
set_source_files_properties(rtlensfun.cc PROPERTIES COMPILE_DEFINITIONS RT_LENSFUN_HAS_LOAD_DIRECTORY)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.0")
# procparams.cc takes a long time to compile with optimizations starting
# with GCC 12.1 due to PTA (see issue #6548)
get_source_file_property(PROCPARAMS_COMPILE_OPTIONS procparams.cc COMPILE_OPTIONS)
if(PROCPARAMS_COMPILE_OPTIONS STREQUAL "NOTFOUND")
set(PROCPARAMS_COMPILE_OPTIONS "")
else()
set(PROCPARAMS_COMPILE_OPTIONS "${PROCPARAMS_COMPILE_OPTIONS};")
endif()
set(PROCPARAMS_COMPILE_OPTIONS "${PROCPARAMS_COMPILE_OPTIONS}-fno-tree-pta")
set_source_files_properties(procparams.cc PROPERTIES COMPILE_OPTIONS ${PROCPARAMS_COMPILE_OPTIONS})
endif()
if(WITH_BENCHMARK)
add_definitions(-DBENCHMARK)
endif()

View File

@ -248,6 +248,14 @@ public:
return *this;
}
// import from flat data
void operator()(std::size_t w, std::size_t h, const T* const copy)
{
ar_realloc(w, h);
for (std::size_t y = 0; y < h; ++y) {
std::copy(copy + y * w, copy + y * w + w, rows.data()[y]);
}
}
int getWidth() const
{

View File

@ -28,8 +28,6 @@ namespace rtengine
CameraConst::CameraConst() : pdafOffset(0)
{
memset(dcraw_matrix, 0, sizeof(dcraw_matrix));
memset(raw_crop, 0, sizeof(raw_crop));
memset(raw_mask, 0, sizeof(raw_mask));
white_max = 0;
globalGreenEquilibration = -1;
}
@ -192,6 +190,68 @@ CameraConst* CameraConst::parseEntry(const void *cJSON_, const char *make_model)
std::unique_ptr<CameraConst> cc(new CameraConst);
cc->make_model = make_model;
const auto get_raw_crop =
[](int w, int h, const cJSON *ji, CameraConst *cc) -> bool
{
std::array<int, 4> rc;
if (ji->type != cJSON_Array) {
//fprintf(stderr, "\"raw_crop\" must be an array\n");
return false;
}
int i;
for (i = 0, ji = ji->child; i < 4 && ji != nullptr; i++, ji = ji->next) {
if (ji->type != cJSON_Number) {
//fprintf(stderr, "\"raw_crop\" array must contain numbers\n");
return false;
}
//cc->raw_crop[i] = ji->valueint;
rc[i] = ji->valueint;
}
if (i != 4 || ji != nullptr) {
//fprintf(stderr, "\"raw_crop\" must contain 4 numbers\n");
return false;
}
cc->raw_crop[std::make_pair(w, h)] = rc;
return true;
};
const auto get_masked_areas =
[](int w, int h, const cJSON *ji, CameraConst *cc) -> bool
{
std::array<std::array<int, 4>, 2> rm;
if (ji->type != cJSON_Array) {
//fprintf(stderr, "\"masked_areas\" must be an array\n");
return false;
}
int i;
for (i = 0, ji = ji->child; i < 2 * 4 && ji != nullptr; i++, ji = ji->next) {
if (ji->type != cJSON_Number) {
//fprintf(stderr, "\"masked_areas\" array must contain numbers\n");
return false;
}
//cc->raw_mask[i / 4][i % 4] = ji->valueint;
rm[i / 4][i % 4] = ji->valueint;
}
if (i % 4 != 0) {
//fprintf(stderr, "\"masked_areas\" array length must be divisable by 4\n");
return false;
}
cc->raw_mask[std::make_pair(w, h)] = rm;
return true;
};
const cJSON *ji = cJSON_GetObjectItem(js, "dcraw_matrix");
if (ji) {
@ -216,24 +276,32 @@ CameraConst* CameraConst::parseEntry(const void *cJSON_, const char *make_model)
if (ji) {
if (ji->type != cJSON_Array) {
fprintf(stderr, "\"raw_crop\" must be an array\n");
fprintf(stderr, "invalid entry for raw_crop.\n");
return nullptr;
}
int i;
for (i = 0, ji = ji->child; i < 4 && ji; i++, ji = ji->next) {
if (ji->type != cJSON_Number) {
fprintf(stderr, "\"raw_crop\" array must contain numbers\n");
return nullptr;
} else if (!get_raw_crop(0, 0, ji, cc.get())) {
cJSON *je;
cJSON_ArrayForEach(je, ji) {
if (!cJSON_IsObject(je)) {
fprintf(stderr, "invalid entry for raw_crop.\n");
return nullptr;
} else {
auto js = cJSON_GetObjectItem(je, "frame");
if (!js || js->type != cJSON_Array ||
cJSON_GetArraySize(js) != 2 ||
!cJSON_IsNumber(cJSON_GetArrayItem(js, 0)) ||
!cJSON_IsNumber(cJSON_GetArrayItem(js, 1))) {
fprintf(stderr, "invalid entry for raw_crop.\n");
return nullptr;
}
int w = cJSON_GetArrayItem(js, 0)->valueint;
int h = cJSON_GetArrayItem(js, 1)->valueint;
js = cJSON_GetObjectItem(je, "crop");
if (!js || !get_raw_crop(w, h, js, cc.get())) {
fprintf(stderr, "invalid entry for raw_crop.\n");
return nullptr;
}
}
}
cc->raw_crop[i] = ji->valueint;
}
if (i != 4 || ji) {
fprintf(stderr, "\"raw_crop\" must contain 4 numbers\n");
return nullptr;
}
}
@ -241,24 +309,32 @@ CameraConst* CameraConst::parseEntry(const void *cJSON_, const char *make_model)
if (ji) {
if (ji->type != cJSON_Array) {
fprintf(stderr, "\"masked_areas\" must be an array\n");
fprintf(stderr, "invalid entry for masked_areas.\n");
return nullptr;
}
int i;
for (i = 0, ji = ji->child; i < 2 * 4 && ji; i++, ji = ji->next) {
if (ji->type != cJSON_Number) {
fprintf(stderr, "\"masked_areas\" array must contain numbers\n");
return nullptr;
} else if (!get_masked_areas(0, 0, ji, cc.get())) {
cJSON *je;
cJSON_ArrayForEach(je, ji) {
if (!cJSON_IsObject(je)) {
fprintf(stderr, "invalid entry for masked_areas.\n");
return nullptr;
} else {
auto js = cJSON_GetObjectItem(je, "frame");
if (!js || js->type != cJSON_Array ||
cJSON_GetArraySize(js) != 2 ||
!cJSON_IsNumber(cJSON_GetArrayItem(js, 0)) ||
!cJSON_IsNumber(cJSON_GetArrayItem(js, 1))) {
fprintf(stderr, "invalid entry for masked_areas.\n");
return nullptr;
}
int w = cJSON_GetArrayItem(js, 0)->valueint;
int h = cJSON_GetArrayItem(js, 1)->valueint;
js = cJSON_GetObjectItem(je, "areas");
if (!js || !get_masked_areas(w, h, js, cc.get())) {
fprintf(stderr, "invalid entry for masked_areas.\n");
return nullptr;
}
}
}
cc->raw_mask[i / 4][i % 4] = ji->valueint;
}
if (i % 4 != 0) {
fprintf(stderr, "\"masked_areas\" array length must be divisible by 4\n");
return nullptr;
}
}
@ -399,29 +475,41 @@ void CameraConst::update_pdafOffset(int other)
pdafOffset = other;
}
bool CameraConst::has_rawCrop() const
bool CameraConst::has_rawCrop(int raw_width, int raw_height) const
{
return raw_crop[0] != 0 || raw_crop[1] != 0 || raw_crop[2] != 0 || raw_crop[3] != 0;
return raw_crop.find(std::make_pair(raw_width, raw_height)) != raw_crop.end() || raw_crop.find(std::make_pair(0, 0)) != raw_crop.end();
}
void CameraConst::get_rawCrop(int& left_margin, int& top_margin, int& width, int& height) const
void CameraConst::get_rawCrop(int raw_width, int raw_height, int &left_margin, int &top_margin, int &width, int &height) const
{
left_margin = raw_crop[0];
top_margin = raw_crop[1];
width = raw_crop[2];
height = raw_crop[3];
auto it = raw_crop.find(std::make_pair(raw_width, raw_height));
if (it == raw_crop.end()) {
it = raw_crop.find(std::make_pair(0, 0));
}
if (it != raw_crop.end()) {
left_margin = it->second[0];
top_margin = it->second[1];
width = it->second[2];
height = it->second[3];
} else {
left_margin = top_margin = width = height = 0;
}
}
bool CameraConst::has_rawMask(int idx) const
bool CameraConst::has_rawMask(int raw_width, int raw_height, int idx) const
{
if (idx < 0 || idx > 1) {
return false;
}
return (raw_mask[idx][0] | raw_mask[idx][1] | raw_mask[idx][2] | raw_mask[idx][3]) != 0;
return raw_mask.find(std::make_pair(raw_width, raw_height)) != raw_mask.end() || raw_mask.find(std::make_pair(0, 0)) != raw_mask.end();
}
void CameraConst::get_rawMask(int idx, int& top, int& left, int& bottom, int& right) const
void CameraConst::get_rawMask(int raw_width, int raw_height, int idx, int &top, int &left, int &bottom, int &right) const
{
top = left = bottom = right = 0;
@ -429,10 +517,17 @@ void CameraConst::get_rawMask(int idx, int& top, int& left, int& bottom, int& ri
return;
}
top = raw_mask[idx][0];
left = raw_mask[idx][1];
bottom = raw_mask[idx][2];
right = raw_mask[idx][3];
auto it = raw_mask.find(std::make_pair(raw_width, raw_height));
if (it == raw_mask.end()) {
it = raw_mask.find(std::make_pair(0, 0));
}
if (it != raw_mask.end()) {
top = it->second[idx][0];
left = it->second[idx][1];
bottom = it->second[idx][2];
right = it->second[idx][3];
}
}
void CameraConst::update_Levels(const CameraConst *other)
@ -464,9 +559,7 @@ void CameraConst::update_Crop(CameraConst *other)
return;
}
if (other->has_rawCrop()) {
other->get_rawCrop(raw_crop[0], raw_crop[1], raw_crop[2], raw_crop[3]);
}
raw_crop.insert(other->raw_crop.begin(), other->raw_crop.end());
}
bool CameraConst::get_Levels(camera_const_levels & lvl, int bw, int iso, float fnumber) const

View File

@ -1,9 +1,11 @@
/*
/* -*- C++ -*-
*
* This file is part of RawTherapee.
*/
#pragma once
#include <map>
#include <array>
#include <string>
#include <vector>
@ -17,17 +19,17 @@ class ustring;
namespace rtengine
{
struct camera_const_levels {
int levels[4];
};
class CameraConst final
{
private:
struct camera_const_levels {
int levels[4];
};
std::string make_model;
short dcraw_matrix[12];
int raw_crop[4];
int raw_mask[2][4];
std::map<std::pair<int, int>, std::array<int, 4>> raw_crop;
std::map<std::pair<int, int>, std::array<std::array<int, 4>, 2>> raw_mask;
int white_max;
std::map<int, camera_const_levels> mLevels[2];
std::map<float, float> mApertureScaling;
@ -47,10 +49,10 @@ public:
const short *get_dcrawMatrix(void) const;
const std::vector<int>& get_pdafPattern() const;
int get_pdafOffset() const {return pdafOffset;};
bool has_rawCrop(void) const;
void get_rawCrop(int& left_margin, int& top_margin, int& width, int& height) const;
bool has_rawMask(int idx) const;
void get_rawMask(int idx, int& top, int& left, int& bottom, int& right) const;
bool has_rawCrop(int raw_width, int raw_height) const;
void get_rawCrop(int raw_width, int raw_height, int& left_margin, int& top_margin, int& width, int& height) const;
bool has_rawMask(int raw_width, int raw_height, int idx) const;
void get_rawMask(int raw_width, int raw_height, int idx, int& top, int& left, int& bottom, int& right) const;
int get_BlackLevel(int idx, int iso_speed) const;
int get_WhiteLevel(int idx, int iso_speed, float fnumber) const;
bool has_globalGreenEquilibration() const;
@ -77,4 +79,5 @@ public:
const CameraConst *get(const char make[], const char model[]) const;
};
}
} // namespace rtengine

View File

@ -70,6 +70,14 @@ Examples:
// cropped so the "negative number" way is not totally safe.
"raw_crop": [ 10, 20, 4000, 3000 ],
// multi-aspect support (added 2020-12-03)
// "frame" defines the full dimensions the crop applies to
// (with [0, 0] being the fallback crop if none of the other applies)
"raw_crop" : [
{ "frame" : [4100, 3050], "crop": [10, 20, 4050, 3020] },
{ "frame" : [0, 0], "crop": [10, 20, 4000, 3000] }
]
// Almost same as MaskedAreas DNG tag, used for black level measuring. Here up to two areas can be defined
// by tetrads of numbers:
"masked_areas": [ 51, 2, 3804, 156, 51, 5794, 3804, 5792 ],
@ -84,6 +92,14 @@ Examples:
// instead, to take care of possible light leaks from the light sensing area to the optically black (masked)
// area or sensor imperfections at the outer borders.
// multi-aspect support (added 2020-12-03)
// "frame" defines the full dimensions the masked areas apply to
// (with [0, 0] being the fallback crop if none of the other applies)
"masked_areas" : [
{ "frame" : [4100, 3050], "areas": [10, 20, 4050, 3020] },
{ "frame" : [0, 0], "areas": [10, 20, 4000, 3000] }
]
// list of indices of the rows with on-sensor PDAF pixels, for cameras that have such features. The indices here form a pattern that is repeated for the whole height of the sensor. The values are relative to the "pdaf_offset" value (see below)
"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 ],
// index of the first row of the PDAF pattern in the sensor (0 is the topmost row). Allowed to be negative for convenience (this means that the first repetition of the pattern doesn't start from the first row)
@ -1208,22 +1224,54 @@ Camera constants:
"ranges" : { "white" : 16367 } // Typically 16383 without LENR, with LENR safest value is 15800 for ISO 25600
},
{ // Quality C
"make_model": "Canon EOS R3",
"dcraw_matrix" : [ 9423, -2839, -1195, -4532, 12377, 2415, -483, 1374, 5276 ],
"raw_crop": [ 160, 120, 6024, 4024 ]
},
{ // Quality C
"make_model": "Canon EOS R5",
"dcraw_matrix" : [9766, -2953, -1254, -4276, 12116, 2433, -437, 1336, 5131],
"raw_crop" : [ 128, 96, 8224, 5490 ],
"masked_areas" : [ 94, 20, 5578, 122 ],
"raw_crop" : [
{ "frame" : [ 8352, 5586 ], "crop" : [ 128, 96, 8224, 5490 ] },
{ "frame" : [ 5248, 3510 ], "crop" : [ 128, 96, 5120, 3382 ] }
],
"masked_areas" : [
{ "frame" : [ 8352, 5586 ], "areas": [ 94, 20, 5578, 122 ] },
{ "frame" : [ 5248, 3510 ], "areas": [ 94, 20, 3510, 122 ] }
],
"ranges" : { "white" : 16382 }
},
{ // Quality C
"make_model": "Canon EOS R6",
"dcraw_matrix" : [8293, -1611, -1132, -4759, 12710, 2275, -1013, 2415, 5508],
"raw_crop": [ 72, 38, 5496, 3670 ],
"masked_areas" : [ 40, 10, 5534, 70 ],
"raw_crop": [
{ "frame": [5568, 3708], "crop" : [ 72, 38, 5496, 3670 ] },
{ "frame": [3584, 2386], "crop" : [ 156, 108, 3404, 2270 ] }
],
"masked_areas" : [
{ "frame": [5568, 3708], "areas": [ 40, 10, 5534, 70 ] },
{ "frame": [3584, 2386], "areas": [ 40, 10, 2374, 110 ] }
],
"ranges" : { "white" : 16382 }
},
{ // Quality C
"make_model": "Canon EOS R7",
"dcraw_matrix" : [10424, -3138, -1300, -4221, 11938, 2584, -547, 1658, 6183],
"raw_crop": [ 144, 72, 6984, 4660 ],
"masked_areas" : [ 70, 20, 4724, 138 ]
},
{ // Quality C
"make_model": "Canon EOS R10",
"dcraw_matrix" : [9269, -2012, -1107, -3990, 11762, 2527, -569, 2093, 4913],
"raw_crop": [ 144, 40, 6048, 4020 ],
"masked_areas" : [ 38, 20, 4052, 138 ]
},
{ // Quality C, CHDK DNGs, raw frame correction
"make_model": "Canon PowerShot A3100 IS",
"raw_crop": [ 24, 12, 4032, 3024 ] // full size 4036X3026
@ -1362,7 +1410,11 @@ Camera constants:
{ // Quality C
"make_model": [ "FUJIFILM GFX 100", "FUJIFILM GFX100S" ],
"dcraw_matrix" : [ 16212, -8423, -1583, -4336, 12583, 1937, -195, 726, 6199 ], // taken from ART
"raw_crop": [ 0, 2, 11664, 8734 ]
"raw_crop": [
// multi-aspect crop to account for 16-shot pixel shift images
{ "frame" : [11808, 8754], "crop" : [ 0, 2, 11664, 8734 ] },
{ "frame" : [23616, 17508], "crop" : [ 0, 4, 23328, 17468 ] }
]
},
{ // Quality B
@ -1528,6 +1580,18 @@ Camera constants:
"ranges": { "white": 4040 }
},
{ // Quality B
"make_model": [ "FUJIFILM X-T5", "FUJIFILM X-H2" ],
"dcraw_matrix": [ 11809, -5358, -1141, -4248, 12164, 2343, -514, 1097, 5848 ], // RawSpeed / DNG
"raw_crop": [ 0, 5, 7752, 5184 ]
},
{ // Quality C
"make_model": "FUJIFILM DBP for GX680",
"dcraw_matrix": [ 12741, -4916, -1420, -8510, 16791, 1715, -1767, 2302, 7771 ], // same as S2Pro as per LibRaw
"ranges": { "white": 4096, "black": 132 }
},
{ // Quality C, Leica C-Lux names can differ?
"make_model" : [ "LEICA C-LUX", "LEICA CAM-DC25" ],
"dcraw_matrix" : [7790, -2736, -755, -3452, 11870, 1769, -628, 1647, 4898]
@ -1545,11 +1609,12 @@ Camera constants:
"raw_crop": [ 4, 4, -4, -4 ] // full raw 6016x4016, Official 6000x4000
},
{ // Quality C
"make_model": "LEICA M8",
"dcraw_matrix": [ 7675, -2196, -305, -5860, 14119, 1855, -2425, 4006, 6578 ] // DNG
// Do not set white level, probably special handling by dcraw (see #6237)
},
// TODO: Temporary workaround for issues #6237 and #6498.
//{ // Quality C
// "make_model": "LEICA M8",
// "dcraw_matrix": [ 7675, -2196, -305, -5860, 14119, 1855, -2425, 4006, 6578 ], // DNG
// "ranges": { "white": 16383 }
//},
{ // Quality C
"make_model": "LEICA Q2",
@ -2128,7 +2193,8 @@ Camera constants:
{ // Quality C
"make_model": [ "Panasonic DC-G90", "Panasonic DC-G95", "Panasonic DC-G99" ],
"dcraw_matrix": [ 9657, -3963, -748, -3361, 11378, 2258, -568, 1414, 5158 ] // DNG
"dcraw_matrix": [ 9657, -3963, -748, -3361, 11378, 2258, -568, 1414, 5158 ], // DNG
"ranges": { "black": 15 } // see above: RT already reads a value from exif
},
{ // Quality C
@ -2965,7 +3031,10 @@ Camera constants:
{ // Quality B, correction for frame width
"make_model": [ "Sony ILCE-7S", "Sony ILCE-7SM2" ],
"dcraw_matrix": [ 5838,-1430,-246,-3497,11477,2297,-748,1885,5778 ], // DNG_v9.2 D65
"raw_crop": [ 0, 0, 4254, 2848 ],
"raw_crop" : [
{ "frame" : [ 2816, 1872 ], "crop" : [ 0, 0, 2792, 1872 ] },
{ "frame" : [ 4254, 2848 ], "crop" : [ 0, 0, 4254, 2848 ] }
],
"ranges": { "black": 512, "white": 16300 }
},

View File

@ -738,7 +738,7 @@ void Ciecam02::jzczhzxyz (double &x, double &y, double &z, double jz, double az,
Lp = Iz + 0.138605043271539 * az + 0.0580473161561189 * bz;
Mp = Iz - 0.138605043271539 * az - 0.0580473161561189 * bz;
Sp = Iz - 0.0960192420263189 * az - 0.811891896056039 * bz;
//I change optionnaly 10000 for pl function of la(absolute luminance) default 10000
//I change optionally 10000 for pl function of la(absolute luminance) default 10000
tmp = pow(Lp, Jzazbz_pi);
if(std::isnan(tmp)) {//to avoid crash

View File

@ -24,6 +24,7 @@
#include "sleef.h"
#include "opthelper.h"
#include "iccstore.h"
#include <iostream>
using namespace std;
@ -1910,6 +1911,152 @@ void Color::Lch2Luv(float c, float h, float &u, float &v)
v = c * sincosval.y;
}
void Color::primaries_to_xyz(double p[6], double Wx, double Wz, double *pxyz)
{
//calculate Xr, Xg, Xb, Yr, Yb, Tg, Zr,Zg Zb
double Wy = 1.0;
double Xr = p[0] / p[1];
double Yr = 1.0;
double Zr = (1.0 - p[0] - p[1]) / p[1];
double Xg = p[2] / p[3];
double Yg = 1.0;
double Zg = (1.0 - p[2] - p[3]) / p[3];
double Xb = p[4] / p[5];
double Yb = 1.0;
double Zb = (1.0 - p[4] - p[5]) / p[5];
using Triple = std::array<double, 3>;
using Matrix = std::array<Triple, 3>;
Matrix input_prim;
Matrix inv_input_prim = {};
input_prim[0][0] = Xr;
input_prim[0][1] = Yr;
input_prim[0][2] = Zr;
input_prim[1][0] = Xg;
input_prim[1][1] = Yg;
input_prim[1][2] = Zg;
input_prim[2][0] = Xb;
input_prim[2][1] = Yb;
input_prim[2][2] = Zb;
//invert matrix
if (!rtengine::invertMatrix(input_prim, inv_input_prim)) {
std::cout << "Matrix is not invertible, skipping" << std::endl;
}
//white point D50 used by LCMS
double Wdx = 0.96420;
double Wdy = 1.0;
double Wdz = 0.82490;
double Sr = Wx * inv_input_prim [0][0] + Wy * inv_input_prim [1][0] + Wz * inv_input_prim [2][0];
double Sg = Wx * inv_input_prim [0][1] + Wy * inv_input_prim [1][1] + Wz * inv_input_prim [2][1];
double Sb = Wx * inv_input_prim [0][2] + Wy * inv_input_prim [1][2] + Wz * inv_input_prim [2][2];
//XYZ matrix for primaries and temp
Matrix mat_xyz = {};
mat_xyz[0][0] = Sr * Xr;
mat_xyz[0][1] = Sr * Yr;
mat_xyz[0][2] = Sr * Zr;
mat_xyz[1][0] = Sg * Xg;
mat_xyz[1][1] = Sg * Yg;
mat_xyz[1][2] = Sg * Zg;
mat_xyz[2][0] = Sb * Xb;
mat_xyz[2][1] = Sb * Yb;
mat_xyz[2][2] = Sb * Zb;
//chromatic adaptation Bradford
Matrix MaBradford = {};
MaBradford[0][0] = 0.8951;
MaBradford[0][1] = -0.7502;
MaBradford[0][2] = 0.0389;
MaBradford[1][0] = 0.2664;
MaBradford[1][1] = 1.7135;
MaBradford[1][2] = -0.0685;
MaBradford[2][0] = -0.1614;
MaBradford[2][1] = 0.0367;
MaBradford[2][2] = 1.0296;
Matrix Ma_oneBradford = {};
Ma_oneBradford[0][0] = 0.9869929;
Ma_oneBradford[0][1] = 0.4323053;
Ma_oneBradford[0][2] = -0.0085287;
Ma_oneBradford[1][0] = -0.1470543;
Ma_oneBradford[1][1] = 0.5183603;
Ma_oneBradford[1][2] = 0.0400428;
Ma_oneBradford[2][0] = 0.1599627;
Ma_oneBradford[2][1] = 0.0492912;
Ma_oneBradford[2][2] = 0.9684867;
//R G B source
double Rs = Wx * MaBradford[0][0] + Wy * MaBradford[1][0] + Wz * MaBradford[2][0];
double Gs = Wx * MaBradford[0][1] + Wy * MaBradford[1][1] + Wz * MaBradford[2][1];
double Bs = Wx * MaBradford[0][2] + Wy * MaBradford[1][2] + Wz * MaBradford[2][2];
// R G B destination
double Rd = Wdx * MaBradford[0][0] + Wdy * MaBradford[1][0] + Wdz * MaBradford[2][0];
double Gd = Wdx * MaBradford[0][1] + Wdy * MaBradford[1][1] + Wdz * MaBradford[2][1];
double Bd = Wdx * MaBradford[0][2] + Wdy * MaBradford[1][2] + Wdz * MaBradford[2][2];
//cone destination
Matrix cone_dest_sourc = {};
cone_dest_sourc [0][0] = Rd / Rs;
cone_dest_sourc [0][1] = 0.;
cone_dest_sourc [0][2] = 0.;
cone_dest_sourc [1][0] = 0.;
cone_dest_sourc [1][1] = Gd / Gs;
cone_dest_sourc [1][2] = 0.;
cone_dest_sourc [2][0] = 0.;
cone_dest_sourc [2][1] = 0.;
cone_dest_sourc [2][2] = Bd / Bs;
//cone dest
Matrix cone_ma_one = {};
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
cone_ma_one[i][j] = 0;
for (int k = 0; k < 3; ++k) {
cone_ma_one[i][j] += cone_dest_sourc [i][k] * Ma_oneBradford[k][j];
}
}
}
//generate adaptation bradford matrix
Matrix adapt_chroma = {};
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
adapt_chroma [i][j] = 0;
for (int k = 0; k < 3; ++k) {
adapt_chroma[i][j] += MaBradford[i][k] * cone_ma_one[k][j];
}
}
}
Matrix mat_xyz_brad = {};
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
mat_xyz_brad[i][j] = 0;
for (int k = 0; k < 3; ++k) {
mat_xyz_brad[i][j] += mat_xyz[i][k] * adapt_chroma[k][j];
}
}
}
//push result in pxyz
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
pxyz[i * 3 + j] = mat_xyz_brad[i][j];
}
}
}
/*
* Gamut mapping algorithm
@ -1931,13 +2078,19 @@ void Color::Lch2Luv(float c, float h, float &u, float &v)
* columns of the matrix p=xyz_rgb are RGB tristimulus primaries in XYZ
* c is the color fixed on the boundary; and m=0 for c=0, m=1 for c=255
*/
void Color::gamutmap(float &X, float Y, float &Z, const double p[3][3])
{
float u = 4 * X / (X + 15 * Y + 3 * Z) - u0;
float v = 9 * Y / (X + 15 * Y + 3 * Z) - v0;
float epsil = 0.0001f;
float intermXYZ = X + 15 * Y + 3 * Z;
if(intermXYZ <= 0.f) {
intermXYZ = epsil;
}
float u = 4 * X / (intermXYZ) - u0;
float v = 9 * Y / (intermXYZ) - v0;
float lam[3][2];
float lam_min = 1.0;
float lam_min = 1.0f;
for (int c = 0; c < 3; c++)
for (int m = 0; m < 2; m++) {
@ -1955,17 +2108,24 @@ void Color::gamutmap(float &X, float Y, float &Z, const double p[3][3])
p[0][c] * (5 * Y * p[1][c1] + m * 65535 * p[1][c1] * p[2][c2] + Y * p[2][c1] - m * 65535 * p[1][c2] * p[2][c1]) +
m * 65535 * p[0][c2] * (p[1][c1] * p[2][c] - p[1][c] * p[2][c1])));
if (lam[c][m] < lam_min && lam[c][m] > 0) {
if (lam[c][m] < lam_min && lam[c][m] > 0.f) {
lam_min = lam[c][m];
}
}
u = u * lam_min + u0;
v = v * lam_min + v0;
u = u * (double) lam_min + u0;
v = v * (double) lam_min + v0;
X = (9 * u * Y) / (4 * v);
Z = (12 - 3 * u - 20 * v) * Y / (4 * v);
float intermuv = 12 - 3 * u - 20 * v;
if(intermuv < 0.f) {
intermuv = 0.f;
}
Z = (intermuv) * Y / (4 * v);
}
void Color::skinredfloat ( float J, float h, float sres, float Sp, float dred, float protect_red, int sk, float rstprotection, float ko, float &s)

View File

@ -1847,6 +1847,13 @@ static inline void Lab2XYZ(vfloat L, vfloat a, vfloat b, vfloat &x, vfloat &y, v
*/
static void gamutmap(float &X, float Y, float &Z, const double p[3][3]);
/**
* @brief Convert primaries in XYZ values in function of illuminant
* @param p primaries red, gree, blue
* @param Wx Wy white for illuminant
* @param pxyz return matrix XYZ
*/
static void primaries_to_xyz (double p[6], double Wx, double Wz, double *pxyz);
/**
* @brief Get HSV's hue from the Lab's hue

View File

@ -33,7 +33,7 @@
namespace rtengine
{
static const double cie_colour_match_jd2[97][3] = {//350nm to 830nm 5 nm J.Desmis 2° Standard Observer.
static double cie_colour_match_jd2[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},
{0.001368, 0.000039, 0.006450001}, {0.002236, 0.000064, 0.01054999}, {0.004243, 0.000120, 0.02005001},
@ -70,7 +70,7 @@ static const double cie_colour_match_jd2[97][3] = {//350nm to 830nm 5 nm J.Des
};
static double cie_colour_match_jd[97][3] = {//350nm to 830nm 5 nm J.Desmis 10° Standard Observer.
static const double cie_colour_match_jd[97][3] = {//350nm to 830nm 5 nm J.Desmis 10° Standard Observer.
{0.000000000000, 0.000000000000, 0.000000000000},
{0.000000000000, 0.000000000000, 0.000000000000},
{0.000000122200, 0.000000013398, 0.000000535027},
@ -3388,7 +3388,7 @@ The next 3 methods are inspired from:
this values are often called xBar yBar zBar and are characteristics of a color / illuminant
values cie_colour_match[][3] = 2° Standard Observer x2, y2, z2
values cie_colour_match2[][3] = 2° Standard Observer x2, y2, z2
E.g. for 380nm: x2=0.001368 y2=0.000039 z2=0.006451 round in J.Walker to 0.0014 0.0000 0.0065 above
I have increase precision used by J.Walker and pass to 350nm to 830nm
And also add 10° standard observer
@ -3401,9 +3401,9 @@ void ColorTemp::spectrum_to_xyz_daylight(double _m1, double _m2, double &x, doub
for (i = 0, lambda = 350.; lambda < 830.1; i++, lambda += 5.) {
double Me = daylight_spect(lambda, _m1, _m2);
X += Me * cie_colour_match_jd[i][0];
Y += Me * cie_colour_match_jd[i][1];
Z += Me * cie_colour_match_jd[i][2];
X += Me * cie_colour_match_jd2[i][0];
Y += Me * cie_colour_match_jd2[i][1];
Z += Me * cie_colour_match_jd2[i][2];
}
XYZ = (X + Y + Z);
@ -3419,9 +3419,9 @@ void ColorTemp::spectrum_to_xyz_blackbody(double _temp, double &x, double &y, do
for (i = 0, lambda = 350.; lambda < 830.1; i++, lambda += 5.) {
double Me = blackbody_spect(lambda, _temp);
X += Me * cie_colour_match_jd[i][0];
Y += Me * cie_colour_match_jd[i][1];
Z += Me * cie_colour_match_jd[i][2];
X += Me * cie_colour_match_jd2[i][0];
Y += Me * cie_colour_match_jd2[i][1];
Z += Me * cie_colour_match_jd2[i][2];
}
XYZ = (X + Y + Z);
@ -3447,16 +3447,16 @@ void ColorTemp::spectrum_to_xyz_preset(const double* spec_intens, double &x, dou
this values are often called xBar yBar zBar and are characteristics of a color / illuminant
values cie_colour_match[][3] = 2° Standard Observer x2, y2, z2
values cie_colour_match_jd2[][3] = 2° Standard Observer x2, y2, z2
E.g. for 380nm: x2=0.001368 y2=0.000039 z2=0.006451 round in J.Walker to 0.0014 0.0000 0.0065 above
I have increased the precision used by J.Walker and pass from 350nm to 830nm
And also add standard observer 10°
*/
for (i = 0, lambda = 350.; lambda < 830.1; i++, lambda += 5.) {
double Me = get_spectral_color(lambda, spec_intens);
X += Me * cie_colour_match_jd[i][0];
Y += Me * cie_colour_match_jd[i][1];
Z += Me * cie_colour_match_jd[i][2];
X += Me * cie_colour_match_jd2[i][0];
Y += Me * cie_colour_match_jd2[i][1];
Z += Me * cie_colour_match_jd2[i][2];
}
XYZ = (X + Y + Z);
@ -3478,9 +3478,9 @@ void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const dou
Me = get_spectral_color(lambda, spec_color);
Mc = get_spectral_color(lambda, spec_intens);
X += Mc * cie_colour_match_jd[i][0] * Me;
Y += Mc * cie_colour_match_jd[i][1] * Me;
Z += Mc * cie_colour_match_jd[i][2] * Me;
X += Mc * cie_colour_match_jd2[i][0] * Me;
Y += Mc * cie_colour_match_jd2[i][1] * Me;
Z += Mc * cie_colour_match_jd2[i][2] * Me;
}
for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) {
@ -3488,7 +3488,7 @@ void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const dou
double Ms;
Ms = get_spectral_color(lambda, spec_intens);
Yo += cie_colour_match_jd[i][1] * Ms;
Yo += cie_colour_match_jd2[i][1] * Ms;
}
xx = X / Yo;
@ -3505,9 +3505,9 @@ void ColorTemp::spectrum_to_color_xyz_daylight(const double* spec_color, double
for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) {
const double Me = spec_color[i];
const double Mc = daylight_spect(lambda, _m1, _m2);
X += Mc * cie_colour_match_jd[i][0] * Me;
Y += Mc * cie_colour_match_jd[i][1] * Me;
Z += Mc * cie_colour_match_jd[i][2] * Me;
X += Mc * cie_colour_match_jd2[i][0] * Me;
Y += Mc * cie_colour_match_jd2[i][1] * Me;
Z += Mc * cie_colour_match_jd2[i][2] * Me;
}
xx = X / Y;
@ -3524,9 +3524,9 @@ void ColorTemp::spectrum_to_color_xyz_blackbody(const double* spec_color, double
for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) {
const double Me = spec_color[i];
const double Mc = blackbody_spect(lambda, _temp);
X += Mc * cie_colour_match_jd[i][0] * Me;
Y += Mc * cie_colour_match_jd[i][1] * Me;
Z += Mc * cie_colour_match_jd[i][2] * Me;
X += Mc * cie_colour_match_jd2[i][0] * Me;
Y += Mc * cie_colour_match_jd2[i][1] * Me;
Z += Mc * cie_colour_match_jd2[i][2] * Me;
}
xx = X / Y;
@ -3544,14 +3544,14 @@ double ColorTemp::daylight_spect(double wavelength, double m1, double m2)
53.30, 56.10, 58.90, 60.40, 61.90
};
//s1
static const double s1[97] = {41.60, 39.80, 38.00, 40.70, 43.40, 40.95, 38.50, 36.75, 35.00, 39.20, 43.40, 44.85, 46.30, 45.10, 43.90, 40.50, 37.10, 36.90, 36.70, 36.30, 35.90, 34.25, 32.60, 30.25, 27.90, 26.10, 24.30, 22.20, 20.10, 18.15, 16.20, 14.70,
static const double s1[97] = {41.60, 39.80, 38.00, 40.20, 42.40, 40.45, 38.50, 36.75, 35.00, 39.20, 43.40, 44.85, 46.30, 45.10, 43.90, 40.50, 37.10, 36.90, 36.70, 36.30, 35.90, 34.25, 32.60, 30.25, 27.90, 26.10, 24.30, 22.20, 20.10, 18.15, 16.20, 14.70,
13.20, 10.90, 8.60, 7.35, 6.10, 5.15, 4.20, 3.05, 1.90, 0.95, 0.00, -0.80, -1.60, -2.55, -3.50, -3.50, -3.50, -4.65, -5.80, -6.50, -7.20, -7.90, -8.60, -9.05, -9.50, -10.20, -10.90, -10.80, -10.70, -11.35, -12.00, -13.00, -14.00,
-13.80, -13.60, -12.80, -12.00, -12.65, -13.30, -13.10, -12.90, -11.75, -10.60, -11.10, -11.60, -11.90, -12.20, -11.20, -10.20, -9.00, -7.80, -9.50, -11.20, -10.80, -10.50, -10.60, -10.15, -9.70, -9.00, -8.30,
-13.80, -13.60, -12.80, -12.00, -12.65, -13.30, -13.10, -12.90, -11.75, -10.60, -11.10, -11.60, -11.90, -12.20, -11.20, -10.20, -9.00, -7.80, -9.50, -11.20, -10.80, -10.40, -10.50, -10.60, -10.15, -9.70, -9.00, -8.30,
-8.80, -9.30, -9.55, -9.80
};
//s2
static const double s2[97] = {6.70, 6.00, 5.30, 5.70, 6.10, 4.55, 3.00, 2.10, 1.20, 0.05, -1.10, -0.80, -0.50, -0.60, -0.70, -0.95, -1.20, -1.90, -2.60, -2.75, -2.90, -2.85, -2.80, -2.70, -2.60, -2.60, -2.60, -2.20, -1.80, -1.65, -1.50, -1.40, -1.30,
-1.25, -1.20, -1.10, -1.00, -0.75, -0.50, -0.40, -0.30, -0.15, 0.00, 0.10, 0.20, 0.35, 0.50, 1.30, 2.10, 2.65, 3.65, 4.10, 4.40, 4.70, 4.90, 5.10, 5.90, 6.70, 7.00, 7.30, 7.95, 8.60, 9.20, 9.80, 10.00, 10.20, 9.25, 8.30, 8.95,
-1.25, -1.20, -1.10, -1.00, -0.75, -0.50, -0.40, -0.30, -0.15, 0.00, 0.10, 0.20, 0.35, 0.50, 1.30, 2.10, 2.65, 3.20, 3.65, 4.10, 4.40, 4.70, 4.90, 5.10, 5.90, 6.70, 7.00, 7.30, 7.95, 8.60, 9.20, 9.80, 10.00, 10.20, 9.25, 8.30, 8.95,
9.60, 9.05, 8.50, 7.75, 7.00, 7.30, 7.60, 7.80, 8.00, 7.35, 6.70, 5.95, 5.20, 6.30, 7.40, 7.10, 6.80, 6.90, 7.00, 6.70, 6.40, 5.95, 5.50, 5.80, 6.10, 6.30, 6.50
};
@ -3769,11 +3769,11 @@ void ColorTemp::tempxy(bool separated, int repref, float **Tx, float **Ty, float
}
}
if (settings->itcwb_stdobserver10 == false) {
if (settings->itcwb_stdobserver10 == true) {
for (int i = 0; i < 97; i++) {
cie_colour_match_jd[i][0] = cie_colour_match_jd2[i][0];
cie_colour_match_jd[i][1] = cie_colour_match_jd2[i][1];;
cie_colour_match_jd[i][2] = cie_colour_match_jd2[i][2];
cie_colour_match_jd2[i][0] = cie_colour_match_jd[i][0];
cie_colour_match_jd2[i][1] = cie_colour_match_jd[i][1];;
cie_colour_match_jd2[i][2] = cie_colour_match_jd[i][2];
}
}

View File

@ -2464,6 +2464,30 @@ void CLASS unpacked_load_raw()
}
}
// RT - from LibRaw
void CLASS unpacked_load_raw_FujiDBP()
/*
for Fuji DBP for GX680, aka DX-2000
DBP_tile_width = 688;
DBP_tile_height = 3856;
DBP_n_tiles = 8;
*/
{
int scan_line, tile_n;
int nTiles = 8;
tile_width = raw_width / nTiles;
ushort *tile;
tile = (ushort *) calloc(raw_height, tile_width * 2);
for (tile_n = 0; tile_n < nTiles; tile_n++) {
read_shorts(tile, tile_width * raw_height);
for (scan_line = 0; scan_line < raw_height; scan_line++) {
memcpy(&raw_image[scan_line * raw_width + tile_n * tile_width],
&tile[scan_line * tile_width], tile_width * 2);
}
}
free(tile);
fseek(ifp, -2, SEEK_CUR); // avoid EOF error
}
// RT
void CLASS sony_arq_load_raw()
@ -6091,13 +6115,26 @@ get2_256:
offsetChannelBlackLevel2 = save1 + (0x157 << 1);
offsetWhiteLevels = save1 + (0x32a << 1);
break;
case 3973: // R3; ColorDataSubVer: 34
case 3778: // R7, R10; ColorDataSubVer: 48
// imCanon.ColorDataVer = 11;
imCanon.ColorDataSubVer = get2();
fseek(ifp, save1 + ((0x0069+0x0064) << 1), SEEK_SET);
FORC4 cam_mul[c ^ (c >> 1)] = (float)get2();
offsetChannelBlackLevel2 = save1 + ((0x0069+0x0102) << 1);
offsetChannelBlackLevel = save1 + ((0x0069+0x0213) << 1);
offsetWhiteLevels = save1 + ((0x0069+0x0217) << 1);
break;
}
if (offsetChannelBlackLevel)
{
fseek(ifp, offsetChannelBlackLevel, SEEK_SET);
FORC4
bls += (cblack/*imCanon.ChannelBlackLevel*/[c ^ (c >> 1)] = get2());
bls += (RT_canon_levels_data.cblack/*imCanon.ChannelBlackLevel*/[c ^ (c >> 1)] = get2());
RT_canon_levels_data.black_ok = true;
imCanon.AverageBlackLevel = bls / 4;
// RT_blacklevel_from_constant = ThreeValBool::F;
}
@ -6109,7 +6146,8 @@ get2_256:
imCanon.SpecularWhiteLevel = get2();
// FORC4
// imgdata.color.linear_max[c] = imCanon.SpecularWhiteLevel;
maximum = imCanon.SpecularWhiteLevel;
RT_canon_levels_data.white = imCanon.SpecularWhiteLevel;
RT_canon_levels_data.white_ok = true;
// RT_whitelevel_from_constant = ThreeValBool::F;
}
@ -6117,7 +6155,8 @@ get2_256:
{
fseek(ifp, offsetChannelBlackLevel2, SEEK_SET);
FORC4
bls += (cblack/*imCanon.ChannelBlackLevel*/[c ^ (c >> 1)] = get2());
bls += (RT_canon_levels_data.cblack/*imCanon.ChannelBlackLevel*/[c ^ (c >> 1)] = get2());
RT_canon_levels_data.black_ok = true;
imCanon.AverageBlackLevel = bls / 4;
// RT_blacklevel_from_constant = ThreeValBool::F;
}
@ -6304,12 +6343,13 @@ void CLASS parse_mos (int offset)
void CLASS linear_table (unsigned len)
{
int i;
if (len > 0x1000) len = 0x1000;
read_shorts (curve, len);
for (i=len; i < 0x1000; i++)
curve[i] = curve[i-1];
maximum = curve[0xfff];
const unsigned maxLen = std::min(0x10000ull, 1ull << tiff_bps);
len = std::min(len, maxLen);
read_shorts(curve, len);
maximum = curve[len - 1];
for (std::size_t i = len; i < maxLen; ++i) {
curve[i] = maximum;
}
}
void CLASS parse_kodak_ifd (int base)
@ -6898,7 +6938,6 @@ it under the terms of the one of two licenses as you choose:
unsigned oldOrder = order;
order = 0x4d4d; // always big endian per definition in https://www.adobe.com/content/dam/acom/en/products/photoshop/pdfs/dng_spec_1.4.0.0.pdf chapter 7
unsigned ntags = get4(); // read the number of opcodes
if (ntags < ifp->size / 12) { // rough check for wrong value (happens for example with DNG files from DJI FC6310)
while (ntags-- && !ifp->eof) {
unsigned opcode = get4();
@ -6917,8 +6956,48 @@ it under the terms of the one of two licenses as you choose:
break;
}
case 51009: /* OpcodeList2 */
meta_offset = ftell(ifp);
break;
{
meta_offset = ftell(ifp);
const unsigned oldOrder = order;
order = 0x4d4d; // always big endian per definition in https://www.adobe.com/content/dam/acom/en/products/photoshop/pdfs/dng_spec_1.4.0.0.pdf chapter 7
unsigned ntags = get4(); // read the number of opcodes
if (ntags < ifp->size / 12) { // rough check for wrong value (happens for example with DNG files from DJI FC6310)
while (ntags-- && !ifp->eof) {
unsigned opcode = get4();
if (opcode == 9 && gainMaps.size() < 4) {
fseek(ifp, 4, SEEK_CUR); // skip 4 bytes as we know that the opcode 4 takes 4 byte
fseek(ifp, 8, SEEK_CUR); // skip 8 bytes as they don't interest us currently
GainMap gainMap;
gainMap.Top = get4();
gainMap.Left = get4();
gainMap.Bottom = get4();
gainMap.Right = get4();
gainMap.Plane = get4();
gainMap.Planes = get4();
gainMap.RowPitch = get4();
gainMap.ColPitch = get4();
gainMap.MapPointsV = get4();
gainMap.MapPointsH = get4();
gainMap.MapSpacingV = getreal(12);
gainMap.MapSpacingH = getreal(12);
gainMap.MapOriginV = getreal(12);
gainMap.MapOriginH = getreal(12);
gainMap.MapPlanes = get4();
const std::size_t n = static_cast<std::size_t>(gainMap.MapPointsV) * static_cast<std::size_t>(gainMap.MapPointsH) * static_cast<std::size_t>(gainMap.MapPlanes);
gainMap.MapGain.reserve(n);
for (std::size_t i = 0; i < n; ++i) {
gainMap.MapGain.push_back(getreal(11));
}
gainMaps.push_back(std::move(gainMap));
} else {
fseek(ifp, 8, SEEK_CUR); // skip 8 bytes as they don't interest us currently
fseek(ifp, get4(), SEEK_CUR);
}
}
}
order = oldOrder;
break;
}
case 64772: /* Kodak P-series */
if (len < 13) break;
fseek (ifp, 16, SEEK_CUR);
@ -9067,8 +9146,21 @@ void CLASS adobe_coeff (const char *make, const char *model)
for (i=0; i < sizeof table / sizeof *table; i++)
if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) {
if (RT_blacklevel_from_constant == ThreeValBool::T && table[i].black) black = (ushort) table[i].black;
if (RT_whitelevel_from_constant == ThreeValBool::T && table[i].maximum) maximum = (ushort) table[i].maximum;
if (RT_blacklevel_from_constant == ThreeValBool::T && table[i].black) {
if (RT_canon_levels_data.black_ok) {
unsigned c;
FORC4 RT_canon_levels_data.cblack[c] = (ushort) table[i].black;
} else {
black = (ushort) table[i].black;
}
}
if (RT_whitelevel_from_constant == ThreeValBool::T && table[i].maximum) {
if (RT_canon_levels_data.white_ok) {
RT_canon_levels_data.white = (ushort) table[i].maximum;
} else {
maximum = (ushort) table[i].maximum;
}
}
if (RT_matrix_from_constant == ThreeValBool::T && table[i].trans[0]) {
for (raw_color = j=0; j < 12; j++)
((double *)cam_xyz)[j] = table[i].trans[j] / 10000.0;
@ -9748,6 +9840,8 @@ void CLASS identify()
if(!dng_version) {top_margin = 18; height -= top_margin; }
if (height == 3014 && width == 4096) /* Ricoh GX200 */
width = 4014;
if (height == 3280 && width == 4992 && !strncmp(model, "D5100", 5))
{ --height; } // Last row contains corrupt data. See issue #5654.
if (dng_version) {
if (filters == UINT_MAX) filters = 0;
if (filters) is_raw *= tiff_samples;
@ -9852,7 +9946,8 @@ void CLASS identify()
filters = 0;
tiff_samples = colors = 3;
load_raw = &CLASS canon_sraw_load_raw;
FORC4 cblack[c] = 0; // ALB
//FORC4 cblack[c] = 0; // ALB
RT_canon_levels_data.black_ok = RT_canon_levels_data.white_ok = false;
} else if (!strcmp(model,"PowerShot 600")) {
height = 613;
width = 854;
@ -10035,6 +10130,9 @@ canon_a5:
} else if (!strcmp(model, "X-Pro3") || !strcmp(model, "X-T3") || !strcmp(model, "X-T30") || !strcmp(model, "X-T4") || !strcmp(model, "X100V") || !strcmp(model, "X-S10")) {
width = raw_width = 6384;
height = raw_height = 4182;
} else if (!strcmp(model, "DBP for GX680")) { // Special case for #4204
width = raw_width = 5504;
height = raw_height = 3856;
}
top_margin = (raw_height - height) >> 2 << 1;
left_margin = (raw_width - width ) >> 2 << 1;
@ -10042,6 +10140,16 @@ canon_a5:
if (width == 4032 || width == 4952 || width == 6032 || width == 8280) left_margin = 0;
if (width == 3328 && (width -= 66)) left_margin = 34;
if (width == 4936) left_margin = 4;
if (width == 5504) { // #4204, taken from LibRaw
left_margin = 32;
top_margin = 8;
width = raw_width - 2*left_margin;
height = raw_height - 2*top_margin;
load_raw = &CLASS unpacked_load_raw_FujiDBP;
filters = 0x16161616;
load_flags = 0;
flip = 6;
}
if (!strcmp(model,"HS50EXR") ||
!strcmp(model,"F900EXR")) {
width += 2;
@ -10518,6 +10626,14 @@ bw: colors = 1;
}
}
dng_skip:
if (!dng_version && is_raw) {
if (RT_canon_levels_data.black_ok) {
FORC4 cblack[c] = RT_canon_levels_data.cblack[c];
}
if (RT_canon_levels_data.white_ok) {
maximum = RT_canon_levels_data.white;
}
}
if ((use_camera_matrix & (use_camera_wb || dng_version))
&& cmatrix[0][0] > 0.125
&& strncmp(RT_software.c_str(), "Adobe DNG Converter", 19) != 0
@ -11002,6 +11118,70 @@ void CLASS nikon_14bit_load_raw()
free(buf);
}
bool CLASS isGainMapSupported() const {
if (!(dng_version && isBayer())) {
return false;
}
const auto n = gainMaps.size();
if (n != 4) { // we need 4 gainmaps for bayer files
if (rtengine::settings->verbose) {
std::cout << "GainMap has " << n << " maps, but 4 are needed" << std::endl;
}
return false;
}
unsigned int check = 0;
bool noOp = true;
for (const auto &m : gainMaps) {
if (m.MapGain.size() < 1) {
if (rtengine::settings->verbose) {
std::cout << "GainMap has invalid size of " << m.MapGain.size() << std::endl;
}
return false;
}
if (m.MapGain.size() != static_cast<std::size_t>(m.MapPointsV) * static_cast<std::size_t>(m.MapPointsH) * static_cast<std::size_t>(m.MapPlanes)) {
if (rtengine::settings->verbose) {
std::cout << "GainMap has size of " << m.MapGain.size() << ", but needs " << m.MapPointsV * m.MapPointsH * m.MapPlanes << std::endl;
}
return false;
}
if (m.RowPitch != 2 || m.ColPitch != 2) {
if (rtengine::settings->verbose) {
std::cout << "GainMap needs Row/ColPitch of 2/2, but has " << m.RowPitch << "/" << m.ColPitch << std::endl;
}
return false;
}
if (m.Top == 0){
if (m.Left == 0) {
check += 1;
} else if (m.Left == 1) {
check += 2;
}
} else if (m.Top == 1) {
if (m.Left == 0) {
check += 4;
} else if (m.Left == 1) {
check += 8;
}
}
for (size_t i = 0; noOp && i < m.MapGain.size(); ++i) {
if (m.MapGain[i] != 1.f) { // we have at least one value != 1.f => map is not a nop
noOp = false;
}
}
}
if (noOp || check != 15) { // all maps are nops or the structure of the combination of 4 maps is not correct
if (rtengine::settings->verbose) {
if (noOp) {
std::cout << "GainMap is a nop" << std::endl;
} else {
std::cout << "GainMap has unsupported type : " << check << std::endl;
}
}
return false;
}
return true;
}
/* RT: Delete from here */
/*RT*/#undef SQR
/*RT*/#undef MAX

View File

@ -19,9 +19,13 @@
#pragma once
#include <cstdint>
#include <iostream>
#include "myfile.h"
#include <csetjmp>
#include "dnggainmap.h"
#include "settings.h"
class DCraw
{
@ -165,6 +169,8 @@ protected:
PanasonicRW2Info(): bpp(0), encoding(0) {}
};
PanasonicRW2Info RT_pana_info;
std::vector<GainMap> gainMaps;
public:
struct CanonCR3Data {
// contents of tag CMP1 for relevant track in CR3 file
@ -193,9 +199,31 @@ public:
int crx_track_selected;
short CR3_CTMDtag;
};
bool isBayer() const
{
return (filters != 0 && filters != 9);
}
const std::vector<GainMap>& getGainMaps() const {
return gainMaps;
}
bool isGainMapSupported() const;
struct CanonLevelsData {
unsigned cblack[4];
unsigned white;
bool black_ok;
bool white_ok;
CanonLevelsData(): cblack{0}, white{0}, black_ok(false), white_ok(false) {}
};
protected:
CanonCR3Data RT_canon_CR3_data;
CanonLevelsData RT_canon_levels_data;
float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4];
void (DCraw::*write_thumb)();
@ -423,6 +451,7 @@ void parse_hasselblad_gain();
void hasselblad_load_raw();
void leaf_hdr_load_raw();
void unpacked_load_raw();
void unpacked_load_raw_FujiDBP();
void sinar_4shot_load_raw();
void imacon_full_load_raw();
void packed_load_raw();

View File

@ -17,28 +17,82 @@
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
*/
#include <sstream>
#include <iostream>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <list>
#include <map>
#include <sstream>
#include <giomm.h>
#include <glibmm/ustring.h>
#include "dfmanager.h"
#include "../rtgui/options.h"
#include "rawimage.h"
#include "imagedata.h"
#include "jaggedarray.h"
#include "noncopyable.h"
#include "pixelsmap.h"
#include "rawimage.h"
#include "utils.h"
namespace rtengine
#include "../rtgui/options.h"
namespace
{
// *********************** class dfInfo **************************************
std::string toUppercase(const std::string& string)
{
return Glib::ustring(string).uppercase();
}
class dfInfo final
{
public:
Glib::ustring pathname; // filename of dark frame
std::list<Glib::ustring> pathNames; // other similar dark frames, used for average
std::string maker; // manufacturer
std::string model; // model
int iso; // ISO (gain)
double shutter; // shutter or exposure time in sec
time_t timestamp; // seconds since 1 Jan 1970
dfInfo(const Glib::ustring &name, const std::string &mak, const std::string &mod, int iso, double shut, time_t t)
: pathname(name), maker(mak), model(mod), iso(iso), shutter(shut), timestamp(t), ri(nullptr) {}
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();
dfInfo &operator =(const dfInfo &o);
// Calculate virtual distance between two shots; different model return infinite
double distance(const std::string &mak, const std::string &mod, int iso, double shutter) const;
static std::string key(const std::string &mak, const std::string &mod, int iso, double shut);
std::string key() const
{
return key(maker, model, iso, shutter);
}
const rtengine::RawImage* getRawImage();
const std::vector<rtengine::badPix>& getHotPixels();
private:
rtengine::RawImage* ri; // Dark Frame raw data
std::vector<rtengine::badPix> badPixels; // Extracted hot pixels
void updateBadPixelList(const rtengine::RawImage* df);
void updateRawImage();
};
dfInfo::~dfInfo()
{
delete ri;
}
inline dfInfo& dfInfo::operator =(const dfInfo &o)
inline dfInfo& dfInfo::operator = (const dfInfo &o)
{
if (this != &o) {
pathname = o.pathname;
@ -48,7 +102,7 @@ inline dfInfo& dfInfo::operator =(const dfInfo &o)
shutter = o.shutter;
timestamp = o.timestamp;
if( ri ) {
if (ri) {
delete ri;
ri = nullptr;
}
@ -57,38 +111,13 @@ inline dfInfo& dfInfo::operator =(const dfInfo &o)
return *this;
}
bool dfInfo::operator <(const dfInfo &e2) const
{
if( this->maker.compare( e2.maker) >= 0 ) {
return false;
}
if( this->model.compare( e2.model) >= 0 ) {
return false;
}
if( this->iso >= e2.iso ) {
return false;
}
if( this->shutter >= e2.shutter ) {
return false;
}
if( this->timestamp >= e2.timestamp ) {
return false;
}
return true;
}
std::string dfInfo::key(const std::string &mak, const std::string &mod, int iso, double shut )
std::string dfInfo::key(const std::string &mak, const std::string &mod, int iso, double shut)
{
std::ostringstream s;
s << mak << " " << mod << " ";
s.width(5);
s << iso << "ISO ";
s.precision( 2 );
s.precision(2);
s.width(4);
s << shut << "s";
return s.str();
@ -96,115 +125,106 @@ std::string dfInfo::key(const std::string &mak, const std::string &mod, int iso,
double dfInfo::distance(const std::string &mak, const std::string &mod, int iso, double shutter) const
{
if( this->maker.compare( mak) != 0 ) {
if (this->maker.compare(mak) != 0) {
return INFINITY;
}
if( this->model.compare( mod) != 0 ) {
if (this->model.compare(mod) != 0) {
return INFINITY;
}
double dISO = (log(this->iso / 100.) - log(iso / 100.)) / log(2);
double dShutter = (log(this->shutter) - log(shutter)) / log(2);
return sqrt( dISO * dISO + dShutter * dShutter);
const double dISO = (log(this->iso / 100.) - log(iso / 100.)) / log(2);
const double dShutter = (log(this->shutter) - log(shutter)) / log(2);
return std::sqrt(dISO * dISO + dShutter * dShutter);
}
RawImage* dfInfo::getRawImage()
const rtengine::RawImage* dfInfo::getRawImage()
{
if(ri) {
if (ri) {
return ri;
}
updateRawImage();
updateBadPixelList( ri );
updateBadPixelList(ri);
return ri;
}
std::vector<badPix>& dfInfo::getHotPixels()
const std::vector<rtengine::badPix>& dfInfo::getHotPixels()
{
if( !ri ) {
if (!ri) {
updateRawImage();
updateBadPixelList( ri );
updateBadPixelList(ri);
}
return badPixels;
}
/* updateRawImage() load into ri the actual pixel data from pathname if there is a single shot
* otherwise load each file from the pathNames list and extract a template from the media;
* the first file is used also for reading all information other than pixels
*/
void dfInfo::updateRawImage()
{
typedef unsigned int acc_t;
if( !pathNames.empty() ) {
std::list<Glib::ustring>::iterator iName = pathNames.begin();
ri = new RawImage(*iName); // First file used also for extra pixels information (width,height, shutter, filters etc.. )
if (!pathNames.empty()) {
std::list<Glib::ustring>::const_iterator iName = pathNames.begin();
ri = new rtengine::RawImage(*iName); // First file used also for extra pixels information (width,height, shutter, filters etc.. )
if( ri->loadRaw(true)) {
if (ri->loadRaw(true)) {
delete ri;
ri = nullptr;
} else {
int H = ri->get_height();
int W = ri->get_width();
const int H = ri->get_height();
const int W = ri->get_width();
ri->compress_image(0);
int rSize = W * ((ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS) ? 1 : 3);
acc_t **acc = new acc_t*[H];
for( int row = 0; row < H; row++) {
acc[row] = new acc_t[rSize ];
}
const int rSize = W * ((ri->getSensorType() == rtengine::ST_BAYER || ri->getSensorType() == rtengine::ST_FUJI_XTRANS) ? 1 : 3);
rtengine::JaggedArray<float> acc(W, H);
// copy first image into accumulators
for (int row = 0; row < H; row++)
for (int row = 0; row < H; row++) {
for (int col = 0; col < rSize; col++) {
acc[row][col] = ri->data[row][col];
}
}
int nFiles = 1; // First file data already loaded
for( ++iName; iName != pathNames.end(); ++iName) {
RawImage* temp = new RawImage(*iName);
for (++iName; iName != pathNames.end(); ++iName) {
rtengine::RawImage temp(*iName);
if( !temp->loadRaw(true)) {
temp->compress_image(0); //\ TODO would be better working on original, because is temporary
if (!temp.loadRaw(true)) {
temp.compress_image(0); //\ TODO would be better working on original, because is temporary
nFiles++;
if( ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS ) {
for( int row = 0; row < H; row++) {
for( int col = 0; col < W; col++) {
acc[row][col] += temp->data[row][col];
if (ri->getSensorType() == rtengine::ST_BAYER || ri->getSensorType() == rtengine::ST_FUJI_XTRANS) {
for (int row = 0; row < H; row++) {
for (int col = 0; col < W; col++) {
acc[row][col] += temp.data[row][col];
}
}
} else {
for( int row = 0; row < H; row++) {
for( int col = 0; col < W; col++) {
acc[row][3 * col + 0] += temp->data[row][3 * col + 0];
acc[row][3 * col + 1] += temp->data[row][3 * col + 1];
acc[row][3 * col + 2] += temp->data[row][3 * col + 2];
for (int row = 0; row < H; row++) {
for (int col = 0; col < W; col++) {
acc[row][3 * col + 0] += temp.data[row][3 * col + 0];
acc[row][3 * col + 1] += temp.data[row][3 * col + 1];
acc[row][3 * col + 2] += temp.data[row][3 * col + 2];
}
}
}
}
delete temp;
}
const float factor = 1.f / nFiles;
for (int row = 0; row < H; row++) {
for (int col = 0; col < rSize; col++) {
ri->data[row][col] = acc[row][col] / nFiles;
ri->data[row][col] = acc[row][col] * factor;
}
delete [] acc[row];
}
delete [] acc;
}
} else {
ri = new RawImage(pathname);
ri = new rtengine::RawImage(pathname);
if( ri->loadRaw(true)) {
if (ri->loadRaw(true)) {
delete ri;
ri = nullptr;
} else {
@ -213,35 +233,36 @@ void dfInfo::updateRawImage()
}
}
void dfInfo::updateBadPixelList( RawImage *df )
void dfInfo::updateBadPixelList(const rtengine::RawImage *df)
{
if(!df) {
if (!df) {
return;
}
const float threshold = 10.f / 8.f;
constexpr float threshold = 10.f / 8.f;
if( df->getSensorType() == ST_BAYER || df->getSensorType() == ST_FUJI_XTRANS ) {
std::vector<badPix> badPixelsTemp;
if (df->getSensorType() == rtengine::ST_BAYER || df->getSensorType() == rtengine::ST_FUJI_XTRANS) {
std::vector<rtengine::badPix> badPixelsTemp;
#ifdef _OPENMP
#pragma omp parallel
#endif
{
std::vector<badPix> badPixelsThread;
std::vector<rtengine::badPix> badPixelsThread;
#ifdef _OPENMP
#pragma omp for nowait
#endif
for( int row = 2; row < df->get_height() - 2; row++)
for( int col = 2; col < df->get_width() - 2; col++) {
float m = (df->data[row - 2][col - 2] + df->data[row - 2][col] + df->data[row - 2][col + 2] +
df->data[row][col - 2] + df->data[row][col + 2] +
df->data[row + 2][col - 2] + df->data[row + 2][col] + df->data[row + 2][col + 2]);
for (int row = 2; row < df->get_height() - 2; ++row) {
for (int col = 2; col < df->get_width() - 2; ++col) {
const float m = df->data[row - 2][col - 2] + df->data[row - 2][col] + df->data[row - 2][col + 2] +
df->data[row][col - 2] + df->data[row][col + 2] +
df->data[row + 2][col - 2] + df->data[row + 2][col] + df->data[row + 2][col + 2];
if( df->data[row][col] > m * threshold ) {
if (df->data[row][col] > m * threshold) {
badPixelsThread.emplace_back(col, row);
}
}
}
#ifdef _OPENMP
#pragma omp critical
@ -250,48 +271,78 @@ void dfInfo::updateBadPixelList( RawImage *df )
}
badPixels.insert(badPixels.end(), badPixelsTemp.begin(), badPixelsTemp.end());
} else {
for( int row = 1; row < df->get_height() - 1; row++)
for( int col = 1; col < df->get_width() - 1; col++) {
for (int row = 1; row < df->get_height() - 1; ++row) {
for (int col = 1; col < df->get_width() - 1; ++col) {
float m[3];
for( int c = 0; c < 3; c++) {
m[c] = (df->data[row - 1][3 * (col - 1) + c] + df->data[row - 1][3 * col + c] + df->data[row - 1][3 * (col + 1) + c] +
df->data[row] [3 * (col - 1) + c] + df->data[row] [3 * col + c] +
df->data[row + 1][3 * (col - 1) + c] + df->data[row + 1][3 * col + c] + df->data[row + 1][3 * (col + 1) + c]);
for (int c = 0; c < 3; c++) {
m[c] = df->data[row - 1][3 * (col - 1) + c] + df->data[row - 1][3 * col + c] + df->data[row - 1][3 * (col + 1) + c] +
df->data[row] [3 * (col - 1) + c] + df->data[row] [3 * col + c] +
df->data[row + 1][3 * (col - 1) + c] + df->data[row + 1][3 * col + c] + df->data[row + 1][3 * (col + 1) + c];
}
if( df->data[row][3 * col] > m[0]*threshold || df->data[row][3 * col + 1] > m[1]*threshold || df->data[row][3 * col + 2] > m[2]*threshold) {
if (df->data[row][3 * col] > m[0]*threshold || df->data[row][3 * col + 1] > m[1]*threshold || df->data[row][3 * col + 2] > m[2]*threshold) {
badPixels.emplace_back(col, row);
}
}
}
}
if( settings->verbose ) {
if (rtengine::settings->verbose) {
std::cout << "Extracted " << badPixels.size() << " pixels from darkframe:" << df->get_filename().c_str() << std::endl;
}
}
// ************************* class DFManager *********************************
}
void DFManager::init(const Glib::ustring& pathname)
class rtengine::DFManager::Implementation final :
public NonCopyable
{
public:
void init(const Glib::ustring& pathname);
Glib::ustring getPathname() const
{
return currentPath;
};
void getStat(int& totFiles, int& totTemplates) const;
const RawImage* searchDarkFrame(const std::string& mak, const std::string& mod, int iso, double shut, time_t t);
const RawImage* searchDarkFrame(const Glib::ustring& filename);
const std::vector<badPix>* getHotPixels(const std::string& mak, const std::string& mod, int iso, double shut, time_t t);
const std::vector<badPix>* getHotPixels(const Glib::ustring& filename);
const std::vector<badPix>* getBadPixels(const std::string& mak, const std::string& mod, const std::string& serial) const;
private:
typedef std::multimap<std::string, dfInfo> dfList_t;
typedef std::map<std::string, std::vector<badPix> > bpList_t;
dfList_t dfList;
bpList_t bpList;
bool initialized;
Glib::ustring currentPath;
dfInfo* addFileInfo(const Glib::ustring &filename, bool pool = true);
dfInfo* find(const std::string &mak, const std::string &mod, int isospeed, double shut, time_t t);
int scanBadPixelsFile(const Glib::ustring &filename);
};
void rtengine::DFManager::Implementation::init(const Glib::ustring& pathname)
{
if (pathname.empty()) {
return;
}
std::vector<Glib::ustring> names;
auto dir = Gio::File::create_for_path (pathname);
const auto dir = Gio::File::create_for_path(pathname);
if (!dir || !dir->query_exists()) {
return;
}
try {
auto enumerator = dir->enumerate_children ("standard::name");
const auto enumerator = dir->enumerate_children("standard::name");
while (auto file = enumerator->next_file ()) {
names.emplace_back (Glib::build_filename (pathname, file->get_name ()));
while (const auto file = enumerator->next_file()) {
names.emplace_back(Glib::build_filename(pathname, file->get_name()));
}
} catch (Glib::Exception&) {}
@ -299,40 +350,40 @@ void DFManager::init(const Glib::ustring& pathname)
dfList.clear();
bpList.clear();
for (size_t i = 0; i < names.size(); i++) {
size_t lastdot = names[i].find_last_of ('.');
for (const auto &name : names) {
const auto lastdot = name.find_last_of('.');
if (lastdot != Glib::ustring::npos && names[i].substr(lastdot) == ".badpixels" ) {
int n = scanBadPixelsFile( names[i] );
if (lastdot != Glib::ustring::npos && name.substr(lastdot) == ".badpixels") {
const int n = scanBadPixelsFile(name);
if( n > 0 && settings->verbose) {
printf("Loaded %s: %d pixels\n", names[i].c_str(), n);
if (n > 0 && settings->verbose) {
printf("Loaded %s: %d pixels\n", name.c_str(), n);
}
continue;
}
try {
addFileInfo(names[i]);
} catch( std::exception& e ) {}
addFileInfo(name);
} catch(std::exception& e) {}
}
// Where multiple shots exist for same group, move filename to list
for( dfList_t::iterator iter = dfList.begin(); iter != dfList.end(); ++iter ) {
dfInfo &i = iter->second;
for (auto &df : dfList) {
dfInfo &i = df.second;
if( !i.pathNames.empty() && !i.pathname.empty() ) {
i.pathNames.push_back( i.pathname );
if (!i.pathNames.empty() && !i.pathname.empty()) {
i.pathNames.push_back(i.pathname);
i.pathname.clear();
}
if( settings->verbose ) {
if( !i.pathname.empty() ) {
printf( "%s: %s\n", i.key().c_str(), i.pathname.c_str());
if (settings->verbose) {
if (!i.pathname.empty()) {
printf("%s: %s\n", i.key().c_str(), i.pathname.c_str());
} else {
printf( "%s: MEAN of \n ", i.key().c_str());
printf("%s: MEAN of \n ", i.key().c_str());
for(std::list<Glib::ustring>::iterator path = i.pathNames.begin(); path != i.pathNames.end(); ++path) {
for (std::list<Glib::ustring>::iterator path = i.pathNames.begin(); path != i.pathNames.end(); ++path) {
printf("%s, ", path->c_str());
}
@ -345,9 +396,140 @@ void DFManager::init(const Glib::ustring& pathname)
return;
}
dfInfo* DFManager::addFileInfo (const Glib::ustring& filename, bool pool)
void rtengine::DFManager::Implementation::getStat(int& totFiles, int& totTemplates) const
{
auto ext = getFileExtension(filename);
totFiles = 0;
totTemplates = 0;
for (const auto &df : dfList) {
const dfInfo &i = df.second;
if (i.pathname.empty()) {
totTemplates++;
totFiles += i.pathNames.size();
} else {
totFiles++;
}
}
}
/* The search for the best match is twofold:
* if perfect matches for iso and shutter are found, then the list is scanned for lesser distance in time
* otherwise if no match is found, the whole list is searched for lesser distance in iso and shutter
*/
const rtengine::RawImage* rtengine::DFManager::Implementation::searchDarkFrame(const std::string& mak, const std::string& mod, int iso, double shut, time_t t)
{
dfInfo* df = find(toUppercase(mak), toUppercase(mod), iso, shut, t);
if (df) {
return df->getRawImage();
} else {
return nullptr;
}
}
const rtengine::RawImage* rtengine::DFManager::Implementation::searchDarkFrame(const Glib::ustring& filename)
{
for (auto& df : dfList) {
if (df.second.pathname.compare(filename) == 0) {
return df.second.getRawImage();
}
}
dfInfo *df = addFileInfo(filename, false);
if (df) {
return df->getRawImage();
}
return nullptr;
}
const std::vector<rtengine::badPix>* rtengine::DFManager::Implementation::getHotPixels(const Glib::ustring& filename)
{
for (auto& df : dfList) {
if (df.second.pathname.compare(filename) == 0) {
return &df.second.getHotPixels();
}
}
return nullptr;
}
const std::vector<rtengine::badPix>* rtengine::DFManager::Implementation::getHotPixels(const std::string& mak, const std::string& mod, int iso, double shut, time_t t)
{
dfInfo* df = find(toUppercase(mak), toUppercase(mod), iso, shut, t);
if (df) {
if (settings->verbose) {
if (!df->pathname.empty()) {
printf("Searched hotpixels from %s\n", df->pathname.c_str());
} else {
if (!df->pathNames.empty()) {
printf("Searched hotpixels from template (first %s)\n", df->pathNames.begin()->c_str());
}
}
}
return &df->getHotPixels();
} else {
return nullptr;
}
}
const std::vector<rtengine::badPix>* rtengine::DFManager::Implementation::getBadPixels(const std::string& mak, const std::string& mod, const std::string& serial) const
{
bpList_t::const_iterator iter;
bool found = false;
if (!serial.empty()) {
// search with serial number first
std::ostringstream s;
s << mak << " " << mod << " " << serial;
iter = bpList.find(s.str());
if (iter != bpList.end()) {
found = true;
}
if (settings->verbose) {
if (found) {
printf("%s.badpixels found\n", s.str().c_str());
} else {
printf("%s.badpixels not found\n", s.str().c_str());
}
}
}
if (!found) {
// search without serial number
std::ostringstream s;
s << mak << " " << mod;
iter = bpList.find(s.str());
if (iter != bpList.end()) {
found = true;
}
if (settings->verbose) {
if (found) {
printf("%s.badpixels found\n", s.str().c_str());
} else {
printf("%s.badpixels not found\n", s.str().c_str());
}
}
}
if (!found) {
return nullptr;
} else {
return &(iter->second);
}
}
dfInfo* rtengine::DFManager::Implementation::addFileInfo(const Glib::ustring& filename, bool pool)
{
const auto ext = getFileExtension(filename);
if (ext.empty() || !options.is_extention_enabled(ext)) {
return nullptr;
@ -376,37 +558,34 @@ dfInfo* DFManager::addFileInfo (const Glib::ustring& filename, bool pool)
}
RawImage ri(filename);
int res = ri.loadRaw(false); // Read information about shot
if (res != 0) {
if (ri.loadRaw(false) != 0) { // Read information about shot
return nullptr;
}
dfList_t::iterator iter;
if(!pool) {
dfInfo n(filename, "", "", 0, 0, 0);
iter = dfList.emplace("", n);
if (!pool) {
const dfInfo n(filename, "", "", 0, 0, 0);
auto iter = dfList.emplace("", n);
return &(iter->second);
}
FramesData idata(filename, std::unique_ptr<RawMetaDataLocation>(new RawMetaDataLocation(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen())), true);
/* Files are added in the map, divided by same maker/model,ISO and shutter*/
std::string key(dfInfo::key(((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed()));
iter = dfList.find(key);
std::string key(dfInfo::key(toUppercase(idata.getMake()), toUppercase(idata.getModel()), idata.getISOSpeed(), idata.getShutterSpeed()));
auto iter = dfList.find(key);
if(iter == dfList.end()) {
dfInfo n(filename, ((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS());
if (iter == dfList.end()) {
dfInfo n(filename, toUppercase(idata.getMake()), toUppercase(idata.getModel()), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS());
iter = dfList.emplace(key, n);
} else {
while(iter != dfList.end() && iter->second.key() == key && ABS(iter->second.timestamp - idata.getDateTimeAsTS()) > 60 * 60 * 6) { // 6 hour difference
++iter;
}
if(iter != dfList.end()) {
if (iter != dfList.end()) {
iter->second.pathNames.push_back(filename);
} else {
dfInfo n(filename, ((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS());
dfInfo n(filename, toUppercase(idata.getMake()), toUppercase(idata.getModel()), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS());
iter = dfList.emplace(key, n);
}
}
@ -418,44 +597,23 @@ dfInfo* DFManager::addFileInfo (const Glib::ustring& filename, bool pool)
return nullptr;
}
void DFManager::getStat( int &totFiles, int &totTemplates)
dfInfo* rtengine::DFManager::Implementation::find(const std::string& mak, const std::string& mod, int isospeed, double shut, time_t t)
{
totFiles = 0;
totTemplates = 0;
for( dfList_t::iterator iter = dfList.begin(); iter != dfList.end(); ++iter ) {
dfInfo &i = iter->second;
if( i.pathname.empty() ) {
totTemplates++;
totFiles += i.pathNames.size();
} else {
totFiles++;
}
}
}
/* The search for the best match is twofold:
* if perfect matches for iso and shutter are found, then the list is scanned for lesser distance in time
* otherwise if no match is found, the whole list is searched for lesser distance in iso and shutter
*/
dfInfo* DFManager::find( const std::string &mak, const std::string &mod, int isospeed, double shut, time_t t )
{
if( dfList.empty() ) {
if (dfList.empty()) {
return nullptr;
}
std::string key( dfInfo::key(mak, mod, isospeed, shut) );
dfList_t::iterator iter = dfList.find( key );
const std::string key(dfInfo::key(mak, mod, isospeed, shut));
dfList_t::iterator iter = dfList.find(key);
if( iter != dfList.end() ) {
if (iter != dfList.end()) {
dfList_t::iterator bestMatch = iter;
time_t bestDeltaTime = ABS(iter->second.timestamp - t);
for(++iter; iter != dfList.end() && !key.compare( iter->second.key() ); ++iter ) {
time_t d = ABS(iter->second.timestamp - t );
for (++iter; iter != dfList.end() && !key.compare(iter->second.key()); ++iter) {
const time_t d = ABS(iter->second.timestamp - t);
if( d < bestDeltaTime ) {
if (d < bestDeltaTime) {
bestMatch = iter;
bestDeltaTime = d;
}
@ -465,12 +623,12 @@ dfInfo* DFManager::find( const std::string &mak, const std::string &mod, int iso
} else {
iter = dfList.begin();
dfList_t::iterator bestMatch = iter;
double bestD = iter->second.distance( mak, mod, isospeed, shut );
double bestD = iter->second.distance(mak, mod, isospeed, shut);
for( ++iter; iter != dfList.end(); ++iter ) {
double d = iter->second.distance( mak, mod, isospeed, shut );
for (++iter; iter != dfList.end(); ++iter) {
const double d = iter->second.distance(mak, mod, isospeed, shut);
if( d < bestD ) {
if (d < bestD) {
bestD = d;
bestMatch = iter;
}
@ -480,170 +638,107 @@ dfInfo* DFManager::find( const std::string &mak, const std::string &mod, int iso
}
}
RawImage* DFManager::searchDarkFrame( const std::string &mak, const std::string &mod, int iso, double shut, time_t t )
{
dfInfo *df = find( ((Glib::ustring)mak).uppercase(), ((Glib::ustring)mod).uppercase(), iso, shut, t );
if( df ) {
return df->getRawImage();
} else {
return nullptr;
}
}
RawImage* DFManager::searchDarkFrame( const Glib::ustring filename )
{
for ( dfList_t::iterator iter = dfList.begin(); iter != dfList.end(); ++iter ) {
if( iter->second.pathname.compare( filename ) == 0 ) {
return iter->second.getRawImage();
}
}
dfInfo *df = addFileInfo( filename, false );
if(df) {
return df->getRawImage();
}
return nullptr;
}
std::vector<badPix> *DFManager::getHotPixels ( const Glib::ustring filename )
{
for ( dfList_t::iterator iter = dfList.begin(); iter != dfList.end(); ++iter ) {
if( iter->second.pathname.compare( filename ) == 0 ) {
return &iter->second.getHotPixels();
}
}
return nullptr;
}
std::vector<badPix> *DFManager::getHotPixels ( const std::string &mak, const std::string &mod, int iso, double shut, time_t t )
{
dfInfo *df = find( ((Glib::ustring)mak).uppercase(), ((Glib::ustring)mod).uppercase(), iso, shut, t );
if( df ) {
if( settings->verbose ) {
if( !df->pathname.empty() ) {
printf( "Searched hotpixels from %s\n", df->pathname.c_str());
} else {
if( !df->pathNames.empty() ) {
printf( "Searched hotpixels from template (first %s)\n", df->pathNames.begin()->c_str());
}
}
}
return &df->getHotPixels();
} else {
return nullptr;
}
}
int DFManager::scanBadPixelsFile( Glib::ustring filename )
int rtengine::DFManager::Implementation::scanBadPixelsFile(const Glib::ustring& filename)
{
FILE *file = ::fopen( filename.c_str(), "r" );
if( !file ) {
return false;
if (!file) {
return 0;
}
size_t lastdot = filename.find_last_of ('.');
size_t dirpos1 = filename.find_last_of ('/');
size_t dirpos2 = filename.find_last_of ('\\');
const auto lastdot = filename.find_last_of('.');
auto dirpos1 = filename.find_last_of('/');
auto dirpos2 = filename.find_last_of('\\');
if( dirpos1 == Glib::ustring::npos && dirpos2 == Glib::ustring::npos ) {
if (dirpos1 == Glib::ustring::npos && dirpos2 == Glib::ustring::npos) {
dirpos1 = 0;
} else if( dirpos1 != Glib::ustring::npos && dirpos2 != Glib::ustring::npos ) {
} else if (dirpos1 != Glib::ustring::npos && dirpos2 != Glib::ustring::npos) {
dirpos1 = (dirpos1 > dirpos2 ? dirpos1 : dirpos2);
} else if( dirpos1 == Glib::ustring::npos ) {
} else if (dirpos1 == Glib::ustring::npos) {
dirpos1 = dirpos2;
}
std::string makmodel(filename, dirpos1 + 1, lastdot - (dirpos1 + 1) );
const std::string makmodel(filename, dirpos1 + 1, lastdot - (dirpos1 + 1));
std::vector<badPix> bp;
char line[256];
if(fgets(line, sizeof(line), file )) {
if (fgets(line, sizeof(line), file)) {
int x, y;
int offset = 0;
int numparms = sscanf(line, "%d %d", &x, &y);
if( numparms == 1 ) { // only one number in first line means, that this is the offset.
if (numparms == 1) { // only one number in first line means, that this is the offset.
offset = x;
} else if(numparms == 2) {
} else if (numparms == 2) {
bp.emplace_back(x + offset, y + offset);
}
while( fgets(line, sizeof(line), file ) ) {
if( sscanf(line, "%d %d", &x, &y) == 2 ) {
while(fgets(line, sizeof(line), file)) {
if (sscanf(line, "%d %d", &x, &y) == 2) {
bp.emplace_back(x + offset, y + offset);
}
}
}
int numPixels = bp.size();
const int numPixels = bp.size();
if( numPixels > 0 ) {
bpList[ makmodel ] = bp;
if (numPixels > 0) {
bpList[makmodel] = bp;
}
fclose(file);
return numPixels;
}
std::vector<badPix> *DFManager::getBadPixels ( const std::string &mak, const std::string &mod, const std::string &serial)
rtengine::DFManager& rtengine::DFManager::getInstance()
{
bpList_t::iterator iter;
bool found = false;
if( !serial.empty() ) {
// search with serial number first
std::ostringstream s;
s << mak << " " << mod << " " << serial;
iter = bpList.find( s.str() );
if( iter != bpList.end() ) {
found = true;
}
if( settings->verbose ) {
if(found) {
printf("%s.badpixels found\n", s.str().c_str());
} else {
printf("%s.badpixels not found\n", s.str().c_str());
}
}
}
if(!found) {
// search without serial number
std::ostringstream s;
s << mak << " " << mod;
iter = bpList.find( s.str() );
if( iter != bpList.end() ) {
found = true;
}
if( settings->verbose ) {
if(found) {
printf("%s.badpixels found\n", s.str().c_str());
} else {
printf("%s.badpixels not found\n", s.str().c_str());
}
}
}
if(!found) {
return nullptr;
} else {
return &(iter->second);
}
static DFManager instance;
return instance;
}
// Global variable
DFManager dfm;
void rtengine::DFManager::init(const Glib::ustring& pathname)
{
implementation->init(pathname);
}
Glib::ustring rtengine::DFManager::getPathname() const
{
return implementation->getPathname();
}
void rtengine::DFManager::getStat(int& totFiles, int& totTemplates) const
{
implementation->getStat(totFiles, totTemplates);
}
const rtengine::RawImage* rtengine::DFManager::searchDarkFrame(const std::string& mak, const std::string& mod, int iso, double shut, time_t t)
{
return implementation->searchDarkFrame(mak, mod, iso, shut, t);
}
const rtengine::RawImage* rtengine::DFManager::searchDarkFrame(const Glib::ustring& filename)
{
return implementation->searchDarkFrame(filename);
}
const std::vector<rtengine::badPix>* rtengine::DFManager::getHotPixels(const std::string& mak, const std::string& mod, int iso, double shut, time_t t)
{
return implementation->getHotPixels(mak, mod, iso, shut, t);
}
const std::vector<rtengine::badPix>* rtengine::DFManager::getHotPixels(const Glib::ustring& filename)
{
return implementation->getHotPixels(filename);
}
const std::vector<rtengine::badPix>* rtengine::DFManager::getBadPixels(const std::string& mak, const std::string& mod, const std::string& serial) const
{
return implementation->getBadPixels(mak, mod, serial);
}
rtengine::DFManager::DFManager() :
implementation(new Implementation)
{
}
rtengine::DFManager::~DFManager() = default;

View File

@ -18,89 +18,40 @@
*/
#pragma once
#include <cmath>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <glibmm/ustring.h>
#include "pixelsmap.h"
namespace rtengine
{
struct badPix;
class RawImage;
class dfInfo final
{
public:
Glib::ustring pathname; // filename of dark frame
std::list<Glib::ustring> pathNames; // other similar dark frames, used for average
std::string maker; ///< manufacturer
std::string model; ///< model
int iso; ///< ISO (gain)
double shutter; ///< shutter or exposure time in sec
time_t timestamp; ///< seconds since 1 Jan 1970
dfInfo(const Glib::ustring &name, const std::string &mak, const std::string &mod, int iso, double shut, time_t t)
: pathname(name), maker(mak), model(mod), iso(iso), shutter(shut), timestamp(t), ri(nullptr) {}
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();
dfInfo &operator =(const dfInfo &o);
bool operator <(const dfInfo &e2) const;
// Calculate virtual distance between two shots; different model return infinite
double distance(const std::string &mak, const std::string &mod, int iso, double shutter) const;
static std::string key(const std::string &mak, const std::string &mod, int iso, double shut );
std::string key()
{
return key( maker, model, iso, shutter);
}
RawImage *getRawImage();
std::vector<badPix> &getHotPixels();
protected:
RawImage *ri; ///< Dark Frame raw data
std::vector<badPix> badPixels; ///< Extracted hot pixels
void updateBadPixelList( RawImage *df );
void updateRawImage();
};
class DFManager final
{
public:
void init(const Glib::ustring &pathname);
Glib::ustring getPathname()
{
return currentPath;
};
void getStat( int &totFiles, int &totTemplate);
RawImage *searchDarkFrame( const std::string &mak, const std::string &mod, int iso, double shut, time_t t );
RawImage *searchDarkFrame( const Glib::ustring filename );
std::vector<badPix> *getHotPixels ( const std::string &mak, const std::string &mod, int iso, double shut, time_t t );
std::vector<badPix> *getHotPixels ( const Glib::ustring filename );
std::vector<badPix> *getBadPixels ( const std::string &mak, const std::string &mod, const std::string &serial);
static DFManager& getInstance();
protected:
typedef std::multimap<std::string, dfInfo> dfList_t;
typedef std::map<std::string, std::vector<badPix> > bpList_t;
dfList_t dfList;
bpList_t bpList;
bool initialized;
Glib::ustring currentPath;
dfInfo *addFileInfo(const Glib::ustring &filename, bool pool = true );
dfInfo *find( const std::string &mak, const std::string &mod, int isospeed, double shut, time_t t );
int scanBadPixelsFile( Glib::ustring filename );
void init(const Glib::ustring& pathname);
Glib::ustring getPathname() const;
void getStat(int& totFiles, int& totTemplates) const;
const RawImage* searchDarkFrame(const std::string& mak, const std::string& mod, int iso, double shut, time_t t);
const RawImage* searchDarkFrame(const Glib::ustring& filename);
const std::vector<badPix>* getHotPixels(const std::string& mak, const std::string& mod, int iso, double shut, time_t t);
const std::vector<badPix>* getHotPixels(const Glib::ustring& filename);
const std::vector<badPix>* getBadPixels(const std::string& mak, const std::string& mod, const std::string& serial) const;
private:
DFManager();
~DFManager();
class Implementation;
const std::unique_ptr<Implementation> implementation;
};
extern DFManager dfm;
}

43
rtengine/dnggainmap.h Normal file
View File

@ -0,0 +1,43 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <cstdint>
#include <vector>
struct GainMap
{
std::uint32_t Top;
std::uint32_t Left;
std::uint32_t Bottom;
std::uint32_t Right;
std::uint32_t Plane;
std::uint32_t Planes;
std::uint32_t RowPitch;
std::uint32_t ColPitch;
std::uint32_t MapPointsV;
std::uint32_t MapPointsH;
double MapSpacingV;
double MapSpacingH;
double MapOriginV;
double MapOriginH;
std::uint32_t MapPlanes;
std::vector<float> MapGain;
};

View File

@ -77,7 +77,7 @@ bool DynamicProfileRule::operator< (const DynamicProfileRule &other) const
}
bool DynamicProfileRule::matches (const rtengine::FramesMetaData *im) const
bool DynamicProfileRule::matches (const rtengine::FramesMetaData *im, const Glib::ustring& filename) const
{
return (iso (im->getISOSpeed())
&& fnumber (im->getFNumber())
@ -86,6 +86,7 @@ bool DynamicProfileRule::matches (const rtengine::FramesMetaData *im) const
&& expcomp (im->getExpComp())
&& camera (im->getCamera())
&& lens (im->getLens())
&& path (filename)
&& imagetype(im->getImageType(0)));
}
@ -214,6 +215,7 @@ bool DynamicProfileRules::loadRules()
get_double_range (rule.expcomp, kf, group, "expcomp");
get_optional (rule.camera, kf, group, "camera");
get_optional (rule.lens, kf, group, "lens");
get_optional (rule.path, kf, group, "path");
get_optional (rule.imagetype, kf, group, "imagetype");
try {
@ -247,6 +249,7 @@ bool DynamicProfileRules::storeRules()
set_double_range (kf, group, "expcomp", rule.expcomp);
set_optional (kf, group, "camera", rule.camera);
set_optional (kf, group, "lens", rule.lens);
set_optional (kf, group, "path", rule.path);
set_optional (kf, group, "imagetype", rule.imagetype);
kf.set_string (group, "profilepath", rule.profilepath);
}

View File

@ -51,7 +51,7 @@ public:
};
DynamicProfileRule();
bool matches (const rtengine::FramesMetaData *im) const;
bool matches (const rtengine::FramesMetaData *im, const Glib::ustring& filename) const;
bool operator< (const DynamicProfileRule &other) const;
int serial_number;
@ -62,6 +62,7 @@ public:
Range<double> expcomp;
Optional camera;
Optional lens;
Optional path;
Optional imagetype;
Glib::ustring profilepath;
};

View File

@ -19,6 +19,7 @@
#include <functional>
#include <strings.h>
#include <time.h>
#include <tiff.h>
@ -57,7 +58,8 @@ template<typename T>
T getFromFrame(
const std::vector<std::unique_ptr<FrameData>>& frames,
std::size_t frame,
const std::function<T (const FrameData&)>& function
const std::function<T (const FrameData&)>& function,
T defval = {}
)
{
if (frame < frames.size()) {
@ -66,7 +68,7 @@ T getFromFrame(
if (!frames.empty()) {
return function(*frames[0]);
}
return {};
return defval;
}
const std::string& validateUft8(const std::string& str, const std::string& on_error = "???")
@ -85,11 +87,21 @@ FramesMetaData* FramesMetaData::fromFile(const Glib::ustring& fname, std::unique
return new FramesData(fname, std::move(rml), firstFrameOnly);
}
FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* rootDir, rtexif::TagDirectory* firstRootDir) :
static struct tm timeFromTS(const time_t ts)
{
#if !defined(WIN32)
struct tm tm;
return *gmtime_r(&ts, &tm);
#else
return *gmtime(&ts);
#endif
}
FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* rootDir, rtexif::TagDirectory* firstRootDir, time_t ts) :
frameRootDir(frameRootDir_),
iptc(nullptr),
time{},
timeStamp{},
time(timeFromTS(ts)),
timeStamp(ts),
iso_speed(0),
aperture(0.),
focal_len(0.),
@ -1068,7 +1080,8 @@ tm FramesData::getDateTime(unsigned int frame) const
[](const FrameData& frame_data)
{
return frame_data.getDateTime();
}
},
modTime
);
}
@ -1080,7 +1093,8 @@ time_t FramesData::getDateTimeAsTS(unsigned int frame) const
[](const FrameData& frame_data)
{
return frame_data.getDateTimeAsTS();
}
},
modTimeStamp
);
}
@ -1366,6 +1380,11 @@ failure:
FramesData::FramesData(const Glib::ustring& fname, std::unique_ptr<RawMetaDataLocation> rml, bool firstFrameOnly) :
iptc(nullptr), dcrawFrameCount(0)
{
GStatBuf statbuf = {};
g_stat(fname.c_str(), &statbuf);
modTimeStamp = statbuf.st_mtime;
modTime = timeFromTS(modTimeStamp);
if (rml && (rml->exifBase >= 0 || rml->ciffBase >= 0)) {
FILE* f = g_fopen(fname.c_str(), "rb");
@ -1384,7 +1403,7 @@ FramesData::FramesData(const Glib::ustring& fname, std::unique_ptr<RawMetaDataLo
// creating FrameData
for (auto currFrame : exifManager.frames) {
frames.push_back(std::unique_ptr<FrameData>(new FrameData(currFrame, currFrame->getRoot(), roots.at(0))));
frames.push_back(std::unique_ptr<FrameData>(new FrameData(currFrame, currFrame->getRoot(), roots.at(0), modTimeStamp)));
}
for (auto currRoot : roots) {
@ -1410,7 +1429,7 @@ FramesData::FramesData(const Glib::ustring& fname, std::unique_ptr<RawMetaDataLo
roots = exifManager.roots;
for (auto currFrame : exifManager.frames) {
frames.push_back(std::unique_ptr<FrameData>(new FrameData(currFrame, currFrame->getRoot(), roots.at(0))));
frames.push_back(std::unique_ptr<FrameData>(new FrameData(currFrame, currFrame->getRoot(), roots.at(0), modTimeStamp)));
}
rewind(exifManager.f); // Not sure this is necessary
@ -1430,7 +1449,7 @@ FramesData::FramesData(const Glib::ustring& fname, std::unique_ptr<RawMetaDataLo
// creating FrameData
for (auto currFrame : exifManager.frames) {
frames.push_back(std::unique_ptr<FrameData>(new FrameData(currFrame, currFrame->getRoot(), roots.at(0))));
frames.push_back(std::unique_ptr<FrameData>(new FrameData(currFrame, currFrame->getRoot(), roots.at(0), modTimeStamp)));
}
for (auto currRoot : roots) {

View File

@ -72,7 +72,7 @@ protected:
public:
FrameData (rtexif::TagDirectory* frameRootDir, rtexif::TagDirectory* rootDir, rtexif::TagDirectory* firstRootDir);
FrameData (rtexif::TagDirectory* frameRootDir, rtexif::TagDirectory* rootDir, rtexif::TagDirectory* firstRootDir, time_t ts = 0);
virtual ~FrameData ();
bool getPixelShift () const;
@ -109,6 +109,8 @@ private:
std::vector<rtexif::TagDirectory*> roots;
IptcData* iptc;
unsigned int dcrawFrameCount;
struct tm modTime;
time_t modTimeStamp;
public:
explicit FramesData (const Glib::ustring& fname, std::unique_ptr<RawMetaDataLocation> rml = nullptr, bool firstFrameOnly = false);

View File

@ -137,6 +137,7 @@ public:
virtual ImageMatrices* getImageMatrices () = 0;
virtual bool isRAW () const = 0;
virtual bool isGainMapSupported () const = 0;
virtual DCPProfile* getDCP (const procparams::ColorManagementParams &cmp, DCPProfileApplyState &as)
{
return nullptr;

View File

@ -407,7 +407,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
// If high detail (=100%) is newly selected, do a demosaic update, since the last was just with FAST
if (imageTypeListener) {
imageTypeListener->imageTypeChanged(imgsrc->isRAW(), imgsrc->getSensorType() == ST_BAYER, imgsrc->getSensorType() == ST_FUJI_XTRANS, imgsrc->isMono());
imageTypeListener->imageTypeChanged(imgsrc->isRAW(), imgsrc->getSensorType() == ST_BAYER, imgsrc->getSensorType() == ST_FUJI_XTRANS, imgsrc->isMono(), imgsrc->isGainMapSupported());
}
if ((todo & M_RAW)
@ -731,6 +731,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
// Remove transformation if unneeded
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))) {
// Forking the image
assert(oprevi);
@ -745,6 +746,14 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
}
for (int sp = 0; sp < (int)params->locallab.spots.size(); sp++) {
if(params->locallab.spots.at(sp).expsharp && params->dirpyrequalizer.cbdlMethod == "bef") {
if(params->locallab.spots.at(sp).shardamping < 1) {
params->locallab.spots.at(sp).shardamping = 1;
}
}
}
if ((todo & (M_TRANSFORM | M_RGBCURVE)) && params->dirpyrequalizer.cbdlMethod == "bef" && params->dirpyrequalizer.enabled && !params->colorappearance.enabled) {
const int W = oprevi->getWidth();
const int H = oprevi->getHeight();
@ -1904,7 +1913,9 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
adap = pow(2.0, E_V - 3.0); // cd / m2
// end calculation adaptation scene luminosity
}
if(params->colorappearance.catmethod == "symg") {//force abolute luminance scenescene to 400 in symmetric
adap = 400.;
}
float d, dj, yb;
bool execsharp = false;
@ -1926,24 +1937,60 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
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);
if ((params->colorappearance.autodegree || params->colorappearance.autodegreeout) && acListener && params->colorappearance.enabled && !params->colorappearance.presetcat02) {
acListener->autoCamChanged(100.* (double)d, 100.* (double)dj);
//call listener
if ((params->colorappearance.autodegree || params->colorappearance.autodegreeout) && acListener && params->colorappearance.enabled) {
if(params->colorappearance.catmethod == "symg") {//force chromatic adaptation to 90 in symmetric
d = 0.9;
dj = 0.9;
}
acListener->autoCamChanged(100.* (double)d, 100.* (double)dj);
}
if (params->colorappearance.autoadapscen && acListener && params->colorappearance.enabled && !params->colorappearance.presetcat02) {
acListener->adapCamChanged(adap); //real value of adapt scene
if (params->colorappearance.autoadapscen && acListener && params->colorappearance.enabled) {
acListener->adapCamChanged(adap); //real value of adapt scene, force to 400 in symmetric
}
if (params->colorappearance.autoybscen && acListener && params->colorappearance.enabled && !params->colorappearance.presetcat02) {
if (params->colorappearance.autoybscen && acListener && params->colorappearance.enabled) {
if(params->colorappearance.catmethod == "symg") {//force yb scene to 18 in symmetric
yb = 18;
}
acListener->ybCamChanged((int) yb); //real value Yb scene
}
double tempsym = 5003.;
int wmodel = 0;//wmodel allows - arbitrary - choice of illuminant and temp with choice
if (params->colorappearance.wbmodel == "RawT") {
wmodel = 0;
} else if (params->colorappearance.wbmodel == "RawTCAT02") {
wmodel = 1;
} else if (params->colorappearance.wbmodel == "free") {
wmodel = 2;//force white balance in symmetric
}
// if (params->colorappearance.enabled && params->colorappearance.presetcat02 && params->colorappearance.autotempout) {
// if (params->colorappearance.enabled && params->colorappearance.presetcat02) {
// acListener->wbCamChanged(params->wb.temperature, params->wb.green); //real temp and tint
// acListener->wbCamChanged(params->wb.temperature, 1.f); //real temp and tint = 1.
// }
if(params->colorappearance.catmethod == "symg" && wmodel == 2) {
tempsym = params->wb.temperature;//force white balance in symmetric
} else {
if (params->colorappearance.illum == "iA") {//otherwise force illuminant source
tempsym = 2856.;
} else if (params->colorappearance.illum == "i41") {
tempsym = 4100.;
} else if (params->colorappearance.illum == "i50") {
tempsym = 5003.;
} else if (params->colorappearance.illum == "i55") {
tempsym = 5503.;
} else if (params->colorappearance.illum == "i60") {
tempsym = 6000. ;
} else if (params->colorappearance.illum == "i65") {
tempsym = 6504.;
} else if (params->colorappearance.illum == "i75") {
tempsym = 7504.;
} else if (params->colorappearance.illum == "ifree") {
tempsym = params->wb.temperature;//force white balance in symmetric
}
}
if (params->colorappearance.enabled && params->colorappearance.autotempout) {
acListener->wbCamChanged(tempsym, 1.f); //real temp and tint = 1.
}
} else {
// CIECAM is disabled, we free up its image buffer to save some space
@ -2408,7 +2455,7 @@ bool ImProcCoordinator::getAutoWB(double& temp, double& green, double equal, dou
if (lastAwbEqual != equal || lastAwbTempBias != tempBias || lastAwbauto != params->wb.method) {
// Issue 2500 MyMutex::MyLock lock(minit); // Also used in crop window
double rm, gm, bm;
params->wb.method = "autold";//same result as before muliple Auto WB
params->wb.method = "autold";//same result as before multiple Auto WB
// imgsrc->getAutoWBMultipliers(rm, gm, bm);
double tempitc = 5000.;

View File

@ -54,7 +54,8 @@
#pragma GCC diagnostic warning "-Wextra"
#pragma GCC diagnostic warning "-Wdouble-promotion"
namespace {
namespace
{
using namespace rtengine;
@ -218,32 +219,37 @@ void proPhotoBlue(float *rtemp, float *gtemp, float *btemp, int istart, int tH,
}
}
void customToneCurve(const ToneCurve &customToneCurve, ToneCurveMode curveMode, float *rtemp, float *gtemp, float *btemp, int istart, int tH, int jstart, int tW, int tileSize, PerceptualToneCurveState ptcApplyState) {
void customToneCurve(const ToneCurve &customToneCurve, ToneCurveMode curveMode, float *rtemp, float *gtemp, float *btemp, int istart, int tH, int jstart, int tW, int tileSize, PerceptualToneCurveState ptcApplyState)
{
if (curveMode == ToneCurveMode::STD) { // Standard
const StandardToneCurve& userToneCurve = static_cast<const StandardToneCurve&> (customToneCurve);
const StandardToneCurve& userToneCurve = static_cast<const StandardToneCurve&>(customToneCurve);
for (int i = istart, ti = 0; i < tH; i++, ti++) {
userToneCurve.BatchApply(0, tW - jstart, &rtemp[ti * tileSize], &gtemp[ti * tileSize], &btemp[ti * tileSize]);
}
} else if (curveMode == ToneCurveMode::FILMLIKE) { // Adobe like
const AdobeToneCurve& userToneCurve = static_cast<const AdobeToneCurve&> (customToneCurve);
const AdobeToneCurve& userToneCurve = static_cast<const AdobeToneCurve&>(customToneCurve);
for (int i = istart, ti = 0; i < tH; i++, ti++) {
userToneCurve.BatchApply(0, tW - jstart, &rtemp[ti * tileSize], &gtemp[ti * tileSize], &btemp[ti * tileSize]);
}
} else if (curveMode == ToneCurveMode::SATANDVALBLENDING) { // apply the curve on the saturation and value channels
const SatAndValueBlendingToneCurve& userToneCurve = static_cast<const SatAndValueBlendingToneCurve&> (customToneCurve);
const SatAndValueBlendingToneCurve& userToneCurve = static_cast<const SatAndValueBlendingToneCurve&>(customToneCurve);
for (int i = istart, ti = 0; i < tH; i++, ti++) {
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
userToneCurve.Apply(rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]);
}
}
} else if (curveMode == ToneCurveMode::WEIGHTEDSTD) { // apply the curve to the rgb channels, weighted
const WeightedStdToneCurve& userToneCurve = static_cast<const WeightedStdToneCurve&> (customToneCurve);
const WeightedStdToneCurve& userToneCurve = static_cast<const WeightedStdToneCurve&>(customToneCurve);
for (int i = istart, ti = 0; i < tH; i++, ti++) {
userToneCurve.BatchApply(0, tW - jstart, &rtemp[ti * tileSize], &gtemp[ti * tileSize], &btemp[ti * tileSize]);
}
} else if (curveMode == ToneCurveMode::LUMINANCE) { // apply the curve to the luminance channel
const LuminanceToneCurve& userToneCurve = static_cast<const LuminanceToneCurve&> (customToneCurve);
const LuminanceToneCurve& userToneCurve = static_cast<const LuminanceToneCurve&>(customToneCurve);
for (int i = istart, ti = 0; i < tH; i++, ti++) {
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
@ -251,7 +257,8 @@ void customToneCurve(const ToneCurve &customToneCurve, ToneCurveMode curveMode,
}
}
} else if (curveMode == ToneCurveMode::PERCEPTUAL) { // apply curve while keeping color appearance constant
const PerceptualToneCurve& userToneCurve = static_cast<const PerceptualToneCurve&> (customToneCurve);
const PerceptualToneCurve& userToneCurve = static_cast<const PerceptualToneCurve&>(customToneCurve);
for (int i = istart, ti = 0; i < tH; i++, ti++) {
userToneCurve.BatchApply(0, tW - jstart, &rtemp[ti * tileSize], &gtemp[ti * tileSize], &btemp[ti * tileSize], ptcApplyState);
}
@ -277,7 +284,7 @@ namespace rtengine
using namespace procparams;
ImProcFunctions::~ImProcFunctions ()
ImProcFunctions::~ImProcFunctions()
{
if (monitorTransform) {
cmsDeleteTransform(monitorTransform);
@ -307,7 +314,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 (settings->srgb);
monitor = ICCStore::getInstance()->getProfile(settings->srgb);
#endif
}
@ -334,9 +341,11 @@ void ImProcFunctions::updateColorProfiles(const Glib::ustring& monitorProfile, R
if (settings->printerBPC) {
flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
}
outIntent = RenderingIntent(settings->printerIntent);
} else {
oprof = ICCStore::getInstance()->getProfile(params->icm.outputProfile);
if (params->icm.outputBPC) {
flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
}
@ -352,20 +361,23 @@ void ImProcFunctions::updateColorProfiles(const Glib::ustring& monitorProfile, R
// }
const auto make_gamma_table =
[](cmsHPROFILE prof, cmsTagSignature tag) -> void
[](cmsHPROFILE prof, cmsTagSignature tag) -> void {
cmsToneCurve *tc = static_cast<cmsToneCurve *>(cmsReadTag(prof, tag));
if (tc)
{
cmsToneCurve *tc = static_cast<cmsToneCurve *>(cmsReadTag(prof, tag));
if (tc) {
const cmsUInt16Number *table = cmsGetToneCurveEstimatedTable(tc);
cmsToneCurve *tc16 = cmsBuildTabulatedToneCurve16(nullptr, cmsGetToneCurveEstimatedTableEntries(tc), table);
if (tc16) {
cmsWriteTag(prof, tag, tc16);
cmsFreeToneCurve(tc16);
}
const cmsUInt16Number *table = cmsGetToneCurveEstimatedTable(tc);
cmsToneCurve *tc16 = cmsBuildTabulatedToneCurve16(nullptr, cmsGetToneCurveEstimatedTableEntries(tc), table);
if (tc16) {
cmsWriteTag(prof, tag, tc16);
cmsFreeToneCurve(tc16);
}
};
}
};
cmsHPROFILE softproof = ProfileContent(oprof).toProfile();
if (softproof) {
make_gamma_table(softproof, cmsSigRedTRCTag);
make_gamma_table(softproof, cmsSigGreenTRCTag);
@ -439,7 +451,7 @@ void ImProcFunctions::updateColorProfiles(const Glib::ustring& monitorProfile, R
void ImProcFunctions::firstAnalysis(const Imagefloat* const original, const ProcParams &params, LUTu & histogram)
{
TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params.icm.workingProfile);
TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix(params.icm.workingProfile);
lumimul[0] = wprof[1][0];
lumimul[1] = wprof[1][1];
@ -956,18 +968,20 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
float cz, wh, pfl;
int c16 = 1;
if (params->colorappearance.modelmethod == "02") {
c16 = 1;
}else if (params->colorappearance.modelmethod == "16") {
} else if (params->colorappearance.modelmethod == "16") {
c16 = 16;
} //I don't use PQ here...hence no 21
float plum = 100.f;
Ciecam02::initcam1float (yb, pilot, f, la, xw, yw, zw, n, d, nbb, ncb, cz, aw, wh, pfl, fl, c, c16, plum);
Ciecam02::initcam1float(yb, pilot, f, la, xw, yw, zw, n, d, nbb, ncb, cz, aw, wh, pfl, fl, c, c16, plum);
//printf ("wh=%f \n", wh);
const float pow1 = pow_F(1.64f - pow_F(0.29f, n), 0.73f);
float nj, nbbj, ncbj, czj, awj, flj;
Ciecam02::initcam2float (yb2, pilotout, f2, la2, xw2, yw2, zw2, nj, dj, nbbj, ncbj, czj, awj, flj, c16, plum);
Ciecam02::initcam2float(yb2, pilotout, f2, la2, xw2, yw2, zw2, nj, dj, nbbj, ncbj, czj, awj, flj, c16, plum);
#ifdef __SSE2__
const float reccmcz = 1.f / (c2 * czj);
#endif
@ -1011,7 +1025,7 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
//matrix for current working space
TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params->icm.workingProfile);
TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix(params->icm.workingProfile);
const float wip[3][3] = {
{ (float)wiprof[0][0], (float)wiprof[0][1], (float)wiprof[0][2]},
{ (float)wiprof[1][0], (float)wiprof[1][1], (float)wiprof[1][2]},
@ -1084,7 +1098,7 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
Q, M, s, aw, fl, wh,
x, y, z,
xw1, yw1, zw1,
c, nc, pow1, nbb, ncb, pfl, cz, d, c16, plum);
c, nc, pow1, nbb, ncb, pfl, cz, d, c16, plum);
Jbuffer[k] = J;
Cbuffer[k] = C;
hbuffer[k] = h;
@ -1122,7 +1136,7 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
Q, M, s, aw, fl, wh,
x, y, z,
xw1, yw1, zw1,
c, nc, pow1, nbb, ncb, pfl, cz, d, c16, plum);
c, nc, pow1, nbb, ncb, pfl, cz, d, c16, plum);
#endif
float Jpro, Cpro, hpro, Qpro, Mpro, spro;
Jpro = J;
@ -1132,6 +1146,7 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
Mpro = M;
spro = s;
bool jp = false;
if ((hasColCurve1) && (curveMode == ColorAppearanceParams::TcMode::BRIGHT)) {
jp = true;
float Qq = Qpro * coefQ;
@ -1141,6 +1156,7 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
Qq = Qq / coefQ;
Qpro = 0.2f * (Qq - Qold) + Qold;
}
if ((hasColCurve2) && (curveMode2 == ColorAppearanceParams::TcMode::BRIGHT)) {
jp = true;
float Qq2 = Qpro * coefQ;
@ -1149,10 +1165,12 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
userColCurveB2.Apply(Qq2);
Qq2 = Qq2 / coefQ;
Qpro = 0.2f * (Qq2 - Qold2) + Qold2;
}
if(jp) {
}
if (jp) {
Jpro = SQR((10.f * Qpro) / wh);
}
// we cannot have all algorithms with all chroma curves
if (alg == 0) {
Jpro = CAMBrightCurveJ[Jpro * 327.68f]; //lightness CIECAM02 + contrast
@ -1240,73 +1258,73 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
}
if (hasColCurve1 && (curveMode == ColorAppearanceParams::TcMode::LIGHT)) {
float Jj = (float) Jpro * 327.68f;
float Jold = Jj;
float Jold100 = (float) Jpro;
float redu = 25.f;
float reduc = 1.f;
const Lightcurve& userColCurveJ1 = static_cast<const Lightcurve&>(customColCurve1);
userColCurveJ1.Apply(Jj);
float Jj = (float) Jpro * 327.68f;
float Jold = Jj;
float Jold100 = (float) Jpro;
float redu = 25.f;
float reduc = 1.f;
const Lightcurve& userColCurveJ1 = static_cast<const Lightcurve&>(customColCurve1);
userColCurveJ1.Apply(Jj);
if (Jj > Jold) {
if (Jj < 65535.f) {
if (Jold < 327.68f * redu) {
Jj = 0.3f * (Jj - Jold) + Jold; //divide sensibility
} else {
reduc = LIM((100.f - Jold100) / (100.f - redu), 0.f, 1.f);
Jj = 0.3f * reduc * (Jj - Jold) + Jold; //reduct sensibility in highlights
}
if (Jj > Jold) {
if (Jj < 65535.f) {
if (Jold < 327.68f * redu) {
Jj = 0.3f * (Jj - Jold) + Jold; //divide sensibility
} else {
reduc = LIM((100.f - Jold100) / (100.f - redu), 0.f, 1.f);
Jj = 0.3f * reduc * (Jj - Jold) + Jold; //reduct sensibility in highlights
}
} else if (Jj > 10.f) {
Jj = 0.8f * (Jj - Jold) + Jold;
} else if (Jj >= 0.f) {
Jj = 0.90f * (Jj - Jold) + Jold; // not zero ==>artifacts
}
} else if (Jj > 10.f) {
Jj = 0.8f * (Jj - Jold) + Jold;
} else if (Jj >= 0.f) {
Jj = 0.90f * (Jj - Jold) + Jold; // not zero ==>artifacts
}
Jpro = (float)(Jj / 327.68f);
Jpro = (float)(Jj / 327.68f);
if (Jpro < 1.f) {
Jpro = 1.f;
}
if (Jpro < 1.f) {
Jpro = 1.f;
}
}
if (hasColCurve2 && (curveMode2 == ColorAppearanceParams::TcMode::LIGHT)) {
float Jj = (float) Jpro * 327.68f;
float Jold = Jj;
float Jold100 = (float) Jpro;
float redu = 25.f;
float reduc = 1.f;
const Lightcurve& userColCurveJ2 = static_cast<const Lightcurve&>(customColCurve2);
userColCurveJ2.Apply(Jj);
if (hasColCurve2 && (curveMode2 == ColorAppearanceParams::TcMode::LIGHT)) {
float Jj = (float) Jpro * 327.68f;
float Jold = Jj;
float Jold100 = (float) Jpro;
float redu = 25.f;
float reduc = 1.f;
const Lightcurve& userColCurveJ2 = static_cast<const Lightcurve&>(customColCurve2);
userColCurveJ2.Apply(Jj);
if (Jj > Jold) {
if (Jj < 65535.f) {
if (Jold < 327.68f * redu) {
Jj = 0.3f * (Jj - Jold) + Jold; //divide sensibility
} else {
reduc = LIM((100.f - Jold100) / (100.f - redu), 0.f, 1.f);
Jj = 0.3f * reduc * (Jj - Jold) + Jold; //reduct sensibility in highlights
}
}
} else if (Jj > 10.f) {
if (!t1L) {
Jj = 0.8f * (Jj - Jold) + Jold;
} else {
Jj = 0.4f * (Jj - Jold) + Jold;
}
} else if (Jj >= 0.f) {
if (!t1L) {
Jj = 0.90f * (Jj - Jold) + Jold; // not zero ==>artifacts
} else {
Jj = 0.5f * (Jj - Jold) + Jold;
if (Jj > Jold) {
if (Jj < 65535.f) {
if (Jold < 327.68f * redu) {
Jj = 0.3f * (Jj - Jold) + Jold; //divide sensibility
} else {
reduc = LIM((100.f - Jold100) / (100.f - redu), 0.f, 1.f);
Jj = 0.3f * reduc * (Jj - Jold) + Jold; //reduct sensibility in highlights
}
}
Jpro = (float)(Jj / 327.68f);
if (Jpro < 1.f) {
Jpro = 1.f;
} else if (Jj > 10.f) {
if (!t1L) {
Jj = 0.8f * (Jj - Jold) + Jold;
} else {
Jj = 0.4f * (Jj - Jold) + Jold;
}
} else if (Jj >= 0.f) {
if (!t1L) {
Jj = 0.90f * (Jj - Jold) + Jold; // not zero ==>artifacts
} else {
Jj = 0.5f * (Jj - Jold) + Jold;
}
}
Jpro = (float)(Jj / 327.68f);
if (Jpro < 1.f) {
Jpro = 1.f;
}
}
if (hasColCurve3) {//curve 3 with chroma saturation colorfullness
@ -1456,47 +1474,33 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
#else
float xx, yy, zz;
//process normal==> viewing
TMatrix wprofc = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile);
const double wpc[3][3] = {//improve precision with double
{wprofc[0][0], wprofc[0][1], wprofc[0][2]},
{wprofc[1][0], wprofc[1][1], wprofc[1][2]},
{wprofc[2][0], wprofc[2][1], wprofc[2][2]}
};
Ciecam02::jch2xyz_ciecam02float(xx, yy, zz,
J, C, h,
xw2, yw2, zw2,
c2, nc2, pow1n, nbbj, ncbj, flj, czj, dj, awj, c16, plum);
c2, nc2, pow1n, nbbj, ncbj, flj, czj, dj, awj, c16, plum);
float x, y, z;
x = xx * 655.35f;
y = yy * 655.35f;
z = zz * 655.35f;
float Ll, aa, bb;
//convert xyz=>lab
Color::XYZ2Lab(x, y, z, Ll, aa, bb);
// gamut control in Lab mode; I must study how to do with cIECAM only
if (gamu == 1) {
float Lprov1, Chprov1;
Lprov1 = Ll / 327.68f;
Chprov1 = sqrtf(SQR(aa) + SQR(bb)) / 327.68f;
float2 sincosval;
if (Chprov1 == 0.0f) {
sincosval.y = 1.f;
sincosval.x = 0.0f;
} else {
sincosval.y = aa / (Chprov1 * 327.68f);
sincosval.x = bb / (Chprov1 * 327.68f);
}
//gamut control : Lab values are in gamut
Color::gamutLchonly(sincosval, Lprov1, Chprov1, wip, highlight, 0.15f, 0.96f);
lab->L[i][j] = Lprov1 * 327.68f;
lab->a[i][j] = 327.68f * Chprov1 * sincosval.y;
lab->b[i][j] = 327.68f * Chprov1 * sincosval.x;
} else {
lab->L[i][j] = Ll;
lab->a[i][j] = aa;
lab->b[i][j] = bb;
Color::gamutmap(x, y, z, wpc);
}
Color::XYZ2Lab(x, y, z, Ll, aa, bb);
lab->L[i][j] = Ll;
lab->a[i][j] = aa;
lab->b[i][j] = bb;
#endif
}
}
@ -1592,7 +1596,7 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
if (params->defringe.enabled)
if (execsharp) {
lab->deleteLab();
defringecam (ncie);//defringe adapted to CIECAM
defringecam(ncie); //defringe adapted to CIECAM
lab->reallocLab();
}
@ -1603,7 +1607,7 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
const bool hotbad = params->dirpyrequalizer.skinprotect != 0.0;
lab->deleteLab();
badpixcam (ncie, artifact / scale, 5, 2, chrom, hotbad); //enabled remove artifacts for cbDL
badpixcam(ncie, artifact / scale, 5, 2, chrom, hotbad); //enabled remove artifacts for cbDL
lab->reallocLab();
}
@ -1611,7 +1615,7 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
if (params->colorappearance.badpixsl > 0 && execsharp) {
int mode = params->colorappearance.badpixsl;
lab->deleteLab();
badpixcam (ncie, 3.0, 10, mode, 0, true);//for bad pixels CIECAM
badpixcam(ncie, 3.0, 10, mode, 0, true); //for bad pixels CIECAM
lab->reallocLab();
}
@ -1620,17 +1624,17 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
buffers[0] = lab->L;
buffers[1] = lab->a;
buffers[2] = lab->b;
impulsedenoisecam (ncie, buffers); //impulse adapted to CIECAM
impulsedenoisecam(ncie, buffers); //impulse adapted to CIECAM
}
if (params->sharpenMicro.enabled)if (execsharp) {
MLmicrocontrastcam (ncie);
MLmicrocontrastcam(ncie);
}
if (params->sharpening.enabled)
if (execsharp) {
float **buffer = lab->L; // We can use the L-buffer from lab as buffer to save some memory
sharpeningcam (ncie, buffer, showSharpMask); // sharpening adapted to CIECAM
sharpeningcam(ncie, buffer, showSharpMask); // sharpening adapted to CIECAM
}
//if(params->dirpyrequalizer.enabled) if(execsharp) {
@ -1643,7 +1647,7 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
float t_l = static_cast<float>(params->dirpyrequalizer.hueskin.getTopLeft()) / 100.0f;
float t_r = static_cast<float>(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, 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();
}
@ -1666,6 +1670,7 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
#ifdef _OPENMP
#pragma omp for schedule(dynamic, 10)
#endif
for (int i = 0; i < height; i++) // update CieImages with new values after sharpening, defringe, contrast by detail level
for (int j = 0; j < width; j++) {
float interm = fabsf(ncie->sh_p[i][j] / (32768.f));
@ -1685,7 +1690,7 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
if (epdEnabled && params->colorappearance.tonecie && algepd) {
lab->deleteLab();
EPDToneMapCIE (ncie, a_w, c_, width, height, minQ, maxQ, Iterates, scale );
EPDToneMapCIE(ncie, a_w, c_, width, height, minQ, maxQ, Iterates, scale);
lab->reallocLab();
}
@ -1769,7 +1774,7 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
Ciecam02::jch2xyz_ciecam02float(xx, yy, zz,
ncie->J_p[i][j], ncie_C_p, ncie->h_p[i][j],
xw2, yw2, zw2,
c2, nc2, pow1n, nbbj, ncbj, flj, czj, dj, awj, c16, plum);
c2, nc2, pow1n, nbbj, ncbj, flj, czj, dj, awj, c16, plum);
float x = (float)xx * 655.35f;
float y = (float)yy * 655.35f;
float z = (float)zz * 655.35f;
@ -1894,7 +1899,7 @@ void ImProcFunctions::moyeqt(Imagefloat* working, float &moyS, float &eqty)
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
const double s = Color::rgb2s(CLIP(working->r (i, j)), CLIP(working->g (i, j)), CLIP(working->b (i, j)));
const double s = Color::rgb2s(CLIP(working->r(i, j)), CLIP(working->g(i, j)), CLIP(working->b(i, j)));
moy += s;
sqrs += SQR(s);
}
@ -1946,12 +1951,12 @@ filmlike_clip(float *r, float *g, float *b)
}
}
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)
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,
@ -1959,12 +1964,12 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
}
// Process RGB image and convert to LAB space
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)
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<StopWatch> stop;
@ -1995,8 +2000,8 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
}
}
TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params->icm.workingProfile);
TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params->icm.workingProfile);
TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile);
TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix(params->icm.workingProfile);
float toxyz[3][3] = {
{
@ -2150,13 +2155,13 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
PerceptualToneCurveState ptc1ApplyState, ptc2ApplyState;
if (hasToneCurve1 && curveMode == ToneCurveMode::PERCEPTUAL) {
const PerceptualToneCurve& userToneCurve = static_cast<const PerceptualToneCurve&> (customToneCurve1);
userToneCurve.initApplyState (ptc1ApplyState, params->icm.workingProfile);
const PerceptualToneCurve& userToneCurve = static_cast<const PerceptualToneCurve&>(customToneCurve1);
userToneCurve.initApplyState(ptc1ApplyState, params->icm.workingProfile);
}
if (hasToneCurve2 && curveMode2 == ToneCurveMode::PERCEPTUAL) {
const PerceptualToneCurve& userToneCurve = static_cast<const PerceptualToneCurve&> (customToneCurve2);
userToneCurve.initApplyState (ptc2ApplyState, params->icm.workingProfile);
const PerceptualToneCurve& userToneCurve = static_cast<const PerceptualToneCurve&>(customToneCurve2);
userToneCurve.initApplyState(ptc2ApplyState, params->icm.workingProfile);
}
bool hasColorToning = params->colorToning.enabled && bool (ctOpacityCurve) && bool (ctColorCurve) && params->colorToning.method != "LabGrid";
@ -2357,6 +2362,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
}
highlightToneCurve(hltonecurve, rtemp, gtemp, btemp, istart, tH, jstart, tW, TS, exp_scale, comp, hlrange);
if (params->toneCurve.black != 0.0) {
shadowToneCurve(shtonecurve, rtemp, gtemp, btemp, istart, tH, jstart, tW, TS);
}
@ -2408,7 +2414,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
float tmpg[4] ALIGNED16;
float tmpb[4] ALIGNED16;
for (; j < tW - 3; j+=4, tj+=4) {
for (; j < tW - 3; j += 4, tj += 4) {
//brightness/contrast
STVF(tmpr[0], tonecurve(LVF(rtemp[ti * TS + tj])));
STVF(tmpg[0], tonecurve(LVF(gtemp[ti * TS + tj])));
@ -2689,6 +2695,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
else if (params->colorToning.method == "Splitco") {
constexpr float reducac = 0.3f;
constexpr int mode = 0;
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];
@ -3119,9 +3126,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
Color::RGB2Lab(&rtemp[ti * TS], &gtemp[ti * TS], &btemp[ti * TS], &(lab->L[i][jstart]), &(lab->a[i][jstart]), &(lab->b[i][jstart]), toxyz, tW - jstart);
}
// if (hasColorToningLabGrid) {
// colorToningLabGrid(lab, jstart, tW, istart, tH, false);
// }
// if (hasColorToningLabGrid) {
// colorToningLabGrid(lab, jstart, tW, istart, tH, false);
// }
} else { // black & white
// Auto channel mixer needs whole image, so we now copy to tmpImage and close the tiled processing
for (int i = istart, ti = 0; i < tH; i++, ti++) {
@ -3500,9 +3507,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
for (int i = 0; i < tH; i++) {
Color::RGB2Lab(tmpImage->r(i), tmpImage->g(i), tmpImage->b(i), lab->L[i], lab->a[i], lab->b[i], toxyz, tW);
// if (hasColorToningLabGrid) {
// colorToningLabGrid(lab, 0, tW, i, i + 1, false);
// }
// if (hasColorToningLabGrid) {
// colorToningLabGrid(lab, 0, tW, i, i + 1, false);
// }
}
@ -3961,7 +3968,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, const LUTf & clToningcurve, const 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);
@ -4020,7 +4027,7 @@ void ImProcFunctions::labtoning (float r, float g, float b, float &ro, float &go
}
void ImProcFunctions::luminanceCurve (LabImage* lold, LabImage* lnew, const LUTf& curve)
void ImProcFunctions::luminanceCurve(LabImage* lold, LabImage* lnew, const LUTf& curve)
{
int W = lold->W;
@ -4040,7 +4047,7 @@ void ImProcFunctions::luminanceCurve (LabImage* lold, LabImage* lnew, const LUTf
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)
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;
@ -4075,7 +4082,8 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW
// !params->labCurve.enabled. It is ugly, but it's the smallest code
// change that I could find
//-------------------------------------------------------------------------
class TempParams {
class TempParams
{
const ProcParams **p_;
const ProcParams *old_;
ProcParams tmp_;
@ -4097,11 +4105,13 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW
bool pipette_for_colortoning_labregions =
editPipette &&
params->colorToning.enabled && params->colorToning.method == "LabRegions";
if (!params->labCurve.enabled && pipette_for_colortoning_labregions) {
utili = autili = butili = ccutili = cclutili = clcutili = false;
tempparams.reset(new TempParams(&params));
curve.makeIdentity();
}
//-------------------------------------------------------------------------
@ -4110,6 +4120,7 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW
// fill pipette buffer with zeros to avoid crashes
editWhatever->fill(0.f);
}
if (params->blackwhite.enabled && !params->colorToning.enabled) {
for (int i = 0; i < lnew->H; ++i) {
for (int j = 0; j < lnew->W; ++j) {
@ -4117,6 +4128,7 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW
}
}
}
return;
}
@ -4178,7 +4190,7 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW
// if(params->labCurve.avoidclip ){
// parameter to adapt curve C=f(C) to gamut
if (params->icm.workingProfile == "ProPhoto") {
if (params->icm.workingProfile == "ProPhoto") {
adjustr = 1.2f; // 1.2 instead 1.0 because it's very rare to have C>170..
} else if (params->icm.workingProfile == "Adobe RGB") {
adjustr = 1.8f;
@ -4209,7 +4221,22 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW
const bool clut = clcutili;
const double rstprotection = 100. - params->labCurve.rstprotection; // Red and Skin Tones Protection
// avoid color shift is disabled when bwToning is activated and enabled if gamut is true in colorappearanace
const bool avoidColorShift = (params->labCurve.avoidcolorshift || (params->colorappearance.gamut && params->colorappearance.enabled)) && !bwToning ;
// const bool avoidColorShift = (params->labCurve.avoidcolorshift || (params->colorappearance.gamut && params->colorappearance.enabled)) && !bwToning ;
//const bool avoidColorS = params->labCurve.avoidcolorshift;
int gamutmuns = 0;
if (params->labCurve.gamutmunselmethod == "NONE") {
gamutmuns = 0;
} else if (params->labCurve.gamutmunselmethod == "LAB") {
gamutmuns = 1;
} else if (params->labCurve.gamutmunselmethod == "XYZ") {
gamutmuns = 2;
} else if (params->labCurve.gamutmunselmethod == "XYZREL") {
gamutmuns = 3;
} else if (params->labCurve.gamutmunselmethod == "MUN") {
gamutmuns = 4;
}
const float protectRed = (float)settings->protectred;
const double protectRedH = settings->protectredh;
const float protect_red = rtengine::LIM<float>(protectRed, 20.f, 180.f); //default=60 chroma: one can put more or less if necessary...in 'option' 40...160
@ -4234,17 +4261,17 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW
const float scaleConst = 100.0f / 100.1f;
const bool gamutLch = settings->gamutLch;
//const bool gamutLch = settings->gamutLch;
const float amountchroma = (float) settings->amchroma;
TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params->icm.workingProfile);
TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix(params->icm.workingProfile);
const double wip[3][3] = {
{wiprof[0][0], wiprof[0][1], wiprof[0][2]},
{wiprof[1][0], wiprof[1][1], wiprof[1][2]},
{wiprof[2][0], wiprof[2][1], wiprof[2][2]}
};
TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params->icm.workingProfile);
TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile);
const double wp[3][3] = {
{wprof[0][0], wprof[0][1], wprof[0][2]},
{wprof[1][0], wprof[1][1], wprof[1][2]},
@ -4264,12 +4291,12 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW
#endif
for (int i = 0; i < H; i++) {
if (avoidColorShift)
// if (avoidColorShift)
// only if user activate Lab adjustments
if (autili || butili || ccutili || cclutili || chutili || lhutili || hhutili || clcutili || utili || chromaticity) {
Color::LabGamutMunsell(lold->L[i], lold->a[i], lold->b[i], W, /*corMunsell*/true, /*lumaMuns*/false, params->toneCurve.hrenabled, /*gamut*/true, wip);
}
// only if user activate Lab adjustments
// if (autili || butili || ccutili || cclutili || chutili || lhutili || hhutili || clcutili || utili || chromaticity) {
// Color::LabGamutMunsell(lold->L[i], lold->a[i], lold->b[i], W, /*corMunsell*/true, /*lumaMuns*/false, params->toneCurve.hrenabled, /*gamut*/true, wip);
// }
#ifdef __SSE2__
@ -4283,7 +4310,7 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW
av = LVFU(lold->a[i][k]);
bv = LVFU(lold->b[i][k]);
STVF(HHBuffer[k], xatan2f(bv, av));
STVF (CCBuffer[k], vsqrtf (SQRV (av) + SQRV (bv)) / c327d68v);
STVF(CCBuffer[k], vsqrtf(SQRV(av) + SQRV(bv)) / c327d68v);
}
for (; k < W; k++) {
@ -4437,8 +4464,8 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW
float fx = (0.002f * aprov1) + fy;
float fz = fy - (0.005f * bprov1);
float x_ = 65535.f * Color::f2xyz (fx) * Color::D50x;
float z_ = 65535.f * Color::f2xyz (fz) * Color::D50z;
float x_ = 65535.f * Color::f2xyz(fx) * Color::D50x;
float z_ = 65535.f * Color::f2xyz(fz) * Color::D50z;
float y_ = Lprov1 > Color::epskapf ? 65535.f * fy * fy * fy : 65535.f * Lprov1 / Color::kappaf;
float R, G, B;
Color::xyz2rgb(x_, y_, z_, R, G, B, wip);
@ -4710,24 +4737,57 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW
btmp -= lold->b[i][j];
}
if (avoidColorShift) {
//gamutmap Lch ==> preserve Hue,but a little slower than gamutbdy for high values...and little faster for low values
if (gamutLch) {
float R, G, B;
//gamut control : Lab values are in gamut
Color::gamutLchonly(HH, sincosval, Lprov1, Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f);
lnew->L[i][j] = Lprov1 * 327.68f;
lnew->a[i][j] = 327.68f * Chprov1 * sincosval.y;
lnew->b[i][j] = 327.68f * Chprov1 * sincosval.x;
} else {
//use gamutbdy
//Luv limiter
float Y, u, v;
Color::Lab2Yuv(lnew->L[i][j], atmp, btmp, Y, u, v);
//Yuv2Lab includes gamut restriction map
Color::Yuv2Lab(Y, u, v, lnew->L[i][j], lnew->a[i][j], lnew->b[i][j], wp);
lnew->L[i][j] = Lprov1 * 327.68f;
lnew->a[i][j] = 327.68f * Chprov1 * sincosval.y;
lnew->b[i][j] = 327.68f * Chprov1 * sincosval.x;
//gamutmap Lch ==> preserve Hue,but a little slower than gamutbdy for high values...and little faster for low values
if (gamutmuns == 1) {
float R, G, B;
//gamut control : Lab values are in gamut
Color::gamutLchonly(HH, sincosval, Lprov1, Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f);
lnew->L[i][j] = Lprov1 * 327.68f;
lnew->a[i][j] = 327.68f * Chprov1 * sincosval.y;
lnew->b[i][j] = 327.68f * Chprov1 * sincosval.x;
}
if (gamutmuns == 2 || gamutmuns == 3) {
float xg, yg, zg;
Color::Lab2XYZ(lnew->L[i][j], atmp, btmp, xg, yg, zg);
float x0 = xg;
float y0 = yg;
float z0 = zg;
Color::gamutmap(xg, yg, zg, wp);
if (gamutmuns == 3) {//0.5f arbitrary coeff
xg = xg + 0.5f * (x0 - xg);
yg = yg + 0.5f * (y0 - yg);
zg = zg + 0.5f * (z0 - zg);
}
float Lag, aag2, bbg2;
Color::XYZ2Lab(xg, yg, zg, Lag, aag2, bbg2);
Lprov1 = Lag / 327.68f;
HH = xatan2f(bbg2, aag2);
Chprov1 = std::sqrt(SQR(aag2) + SQR(bbg2)) / 327.68f;
if (Chprov1 == 0.0f) {
sincosval.y = 1.f;
sincosval.x = 0.0f;
} else {
sincosval.y = aag2 / (Chprov1 * 327.68f);
sincosval.x = bbg2 / (Chprov1 * 327.68f);
}
lnew->L[i][j] = Lprov1 * 327.68f;
lnew->a[i][j] = 327.68f * Chprov1 * sincosval.y;
lnew->b[i][j] = 327.68f * Chprov1 * sincosval.x;
}
if (gamutmuns > 0) {
if (utili || autili || butili || ccut || clut || cclutili || chutili || lhutili || hhutili || clcutili || chromaticity) {
float correctionHue = 0.f; // Munsell's correction
float correctlum = 0.f;
@ -4753,7 +4813,10 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW
lnew->a[i][j] = 327.68f * Chprov * sincosval.y; // apply Munsell
lnew->b[i][j] = 327.68f * Chprov * sincosval.x;
}
} else {
}
if (gamutmuns == 0) {
// if(Lprov1 > maxlp) maxlp=Lprov1;
// if(Lprov1 < minlp) minlp=Lprov1;
if (!bwToning) {
@ -4946,11 +5009,12 @@ 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;
}
*/
/*
if (params->wavelet.enabled && params->wavelet.tmrs != 0) {
return;
}
*/
float stren = params->epd.strength;
const float edgest = std::min(params->epd.edgeStopping, params->localContrast.enabled ? 3.0 : 4.0);
float sca = params->epd.scale;
@ -4960,7 +5024,7 @@ void ImProcFunctions::EPDToneMapCIE(CieImage *ncie, float a_w, float c_, int Wid
float *Qpr = ncie->Q_p[0];
if (settings->verbose) {
printf ("minQ=%f maxQ=%f Qpro=%f\n", static_cast<double>(minQ), static_cast<double>(maxQ), static_cast<double>(Qpro));
printf("minQ=%f maxQ=%f Qpro=%f\n", static_cast<double>(minQ), static_cast<double>(maxQ), static_cast<double>(Qpro));
}
if (maxQ > Qpro) {
@ -4999,6 +5063,7 @@ void ImProcFunctions::EPDToneMapCIE(CieImage *ncie, float a_w, float c_, int Wid
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,10)
#endif
for (int i = 0; i < Hei; i++)
for (int j = 0; j < Wid; j++) {
ncie->Q_p[i][j] = (ncie->Q_p[i][j] * Qpro) / gamm;
@ -5070,6 +5135,7 @@ void ImProcFunctions::EPDToneMaplocal(int sp, LabImage *lab, LabImage *tmp1, uns
#ifdef _OPENMP
#pragma omp parallel for reduction(max:maxL) reduction(min:minL) schedule(dynamic,16)
#endif
for (std::size_t i = 0; i < N; i++) {
minL = rtengine::min(minL, L[i]);
maxL = rtengine::max(maxL, L[i]);
@ -5087,8 +5153,8 @@ void ImProcFunctions::EPDToneMaplocal(int sp, LabImage *lab, LabImage *tmp1, uns
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (std::size_t i = 0; i < N; i++)
{
for (std::size_t i = 0; i < N; i++) {
L[i] = (L[i] - minL) * mult;
}
@ -5117,8 +5183,12 @@ 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);
if(sat == 1.f) sat = 1.001f;
if (sat == 1.f) {
sat = 1.001f;
}
#ifdef _OPENMP
#pragma omp parallel for // removed schedule(dynamic,10)
#endif
@ -5165,6 +5235,7 @@ void ImProcFunctions::EPDToneMap(LabImage *lab, unsigned int Iterates, int skip)
#ifdef _OPENMP
#pragma omp parallel for reduction(min:minL) reduction(max:maxL)
#endif
for (size_t i = 1; i < N; i++) {
minL = std::min(minL, L[i]);
maxL = std::max(maxL, L[i]);
@ -5179,6 +5250,7 @@ void ImProcFunctions::EPDToneMap(LabImage *lab, unsigned int Iterates, int skip)
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (size_t i = 0; i < N; ++i) {
L[i] = (L[i] - minL) * (gamm / maxL);
}
@ -5192,7 +5264,7 @@ void ImProcFunctions::EPDToneMap(LabImage *lab, unsigned int Iterates, int skip)
Iterates = edgest * 15.f;
}
epd.CompressDynamicRange (L, sca / skip, edgest, Compression, DetailBoost, Iterates, rew);
epd.CompressDynamicRange(L, sca / skip, edgest, Compression, DetailBoost, Iterates, rew);
//Restore past range, also desaturate a bit per Mantiuk's Color correction for tone mapping.
const float s = (1.f + 38.7889f) * std::pow(Compression, 1.5856f) / (1.f + 38.7889f * std::pow(Compression, 1.5856f));
@ -5201,6 +5273,7 @@ void ImProcFunctions::EPDToneMap(LabImage *lab, unsigned int Iterates, int skip)
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (size_t ii = 0; ii < N; ++ii) {
a[ii] *= s;
b[ii] *= s;
@ -5248,7 +5321,7 @@ void ImProcFunctions::getAutoExp(const LUTu &histogram, int histcompr, double cl
int j = 0;
for (; j < min ((int)ave, imax); ++j) {
for (; j < min((int)ave, imax); ++j) {
if (count < 8) {
octile[count] += histogram[j];
@ -5341,7 +5414,7 @@ void ImProcFunctions::getAutoExp(const LUTu &histogram, int histcompr, double cl
}
//compute clipped white point
unsigned int clippable = (int) (static_cast<double>(sum) * clip / 100.0 );
unsigned int clippable = (int)(static_cast<double>(sum) * clip / 100.0);
clipped = 0;
int whiteclip = (imax) - 1;
@ -5420,7 +5493,7 @@ void ImProcFunctions::getAutoExp(const LUTu &histogram, int histcompr, double cl
contr = (int) 50.0f * (1.1f - ospread);
contr = max(0, min(100, contr));
//take gamma into account
double whiteclipg = (int) (CurveFactory::gamma2(whiteclip * static_cast<double>(corr) / 65536.0) * 65536.0);
double whiteclipg = (int)(CurveFactory::gamma2(whiteclip * static_cast<double>(corr) / 65536.0) * 65536.0);
float gavg = 0.;
@ -5600,7 +5673,8 @@ void ImProcFunctions::rgb2lab(const Imagefloat &src, LabImage &dst, const Glib::
}
void ImProcFunctions::rgb2lab(const Image8 &src, int x, int y, int w, int h, float L[], float a[], float b[], const procparams::ColorManagementParams &icm, bool consider_histogram_settings) const
{ // Adapted from ImProcFunctions::lab2rgb
{
// Adapted from ImProcFunctions::lab2rgb
const int src_width = src.getWidth();
const int src_height = src.getHeight();
@ -5632,6 +5706,7 @@ void ImProcFunctions::rgb2lab(const Image8 &src, int x, int y, int w, int h, flo
if (icm.outputProfile.empty() || icm.outputProfile == ColorManagementParams::NoICMString) {
profile = "sRGB";
}
oprof = ICCStore::getInstance()->getProfile(profile);
}
@ -5644,7 +5719,7 @@ void ImProcFunctions::rgb2lab(const Image8 &src, int x, int y, int w, int h, flo
lcmsMutex->lock();
cmsHPROFILE LabIProf = cmsCreateLab4Profile(nullptr);
cmsHTRANSFORM hTransform = cmsCreateTransform (oprof, TYPE_RGB_8, LabIProf, TYPE_Lab_FLT, icm.outputIntent, flags);
cmsHTRANSFORM hTransform = cmsCreateTransform(oprof, TYPE_RGB_8, LabIProf, TYPE_Lab_FLT, icm.outputIntent, flags);
cmsCloseProfile(LabIProf);
lcmsMutex->unlock();
@ -5668,7 +5743,7 @@ void ImProcFunctions::rgb2lab(const Image8 &src, int x, int y, int w, int h, flo
float* ra = a + (i - y) * w;
float* rb = b + (i - y) * w;
cmsDoTransform (hTransform, src.data + ix, outbuffer, w);
cmsDoTransform(hTransform, src.data + ix, outbuffer, w);
for (int j = 0; j < w; j++) {
rL[j] = outbuffer[iy++] * 327.68f;
@ -5697,6 +5772,7 @@ void ImProcFunctions::rgb2lab(const Image8 &src, int x, int y, int w, int h, flo
for (int i = y; i < y2; i++) {
int offset = (i - y) * w;
for (int j = x; j < x2; j++) {
float X, Y, Z;
// lab2rgb uses gamma2curve, which is gammatab_srgb.
@ -5788,7 +5864,7 @@ void ImProcFunctions::colorToningLabGrid(LabImage *lab, int xstart, int xend, in
float b_scale = (params->colorToning.labgridBHigh - params->colorToning.labgridBLow) / factor / scaling;
float b_base = params->colorToning.labgridBLow / scaling;
#ifdef _OPENMP
#ifdef _OPENMP
#pragma omp parallel for if (MultiThread)
#endif

View File

@ -258,7 +258,7 @@ enum class BlurType {
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, bool fftt, float blu_ma, float cont_ma, int indic, float &fab);
void avoidcolshi(const struct local_params& lp, int sp, LabImage * original, LabImage *transformed, int cy, int cx, int sk);
void avoidcolshi(const struct local_params& lp, int sp, LabImage *transformed, LabImage *reserved, int cy, int cx, int sk);
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);

View File

@ -58,10 +58,20 @@ int init (const Settings* s, const Glib::ustring& baseDir, const Glib::ustring&
#pragma omp section
#endif
{
bool ok;
if (s->lensfunDbDirectory.empty() || Glib::path_is_absolute(s->lensfunDbDirectory)) {
LFDatabase::init(s->lensfunDbDirectory);
ok = LFDatabase::init(s->lensfunDbDirectory);
} else {
LFDatabase::init(Glib::build_filename(baseDir, s->lensfunDbDirectory));
ok = LFDatabase::init(Glib::build_filename(baseDir, s->lensfunDbDirectory));
}
if (!ok && !s->lensfunDbBundleDirectory.empty() && s->lensfunDbBundleDirectory != s->lensfunDbDirectory) {
if (Glib::path_is_absolute(s->lensfunDbBundleDirectory)) {
LFDatabase::init(s->lensfunDbBundleDirectory);
} else {
LFDatabase::init(Glib::build_filename(baseDir, s->lensfunDbBundleDirectory));
}
}
}
#ifdef _OPENMP
@ -92,7 +102,7 @@ int init (const Settings* s, const Glib::ustring& baseDir, const Glib::ustring&
#pragma omp section
#endif
{
dfm.init(s->darkFramesPath);
DFManager::getInstance().init(s->darkFramesPath);
}
#ifdef _OPENMP
#pragma omp section

View File

@ -416,6 +416,8 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
{
const TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile);
double wprofprim[3][3];//store primaries to XYZ
bool gamutcontrol = params->icm.gamut;
const float toxyz[3][3] = {
{
static_cast<float>(wprof[0][0] / ((normalizeIn ? 65535.0 : 1.0))), //I have suppressed / Color::D50x
@ -440,54 +442,61 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
if (settings->verbose) {
printf("profile not accepted\n");
}
return;
}
if (mul == -5 && gampos == 2.4 && slpos == 12.92310) {//must be change if we change settings RT sRGB
//only in this case we can shortcut..all process..no gamut control..because we reduce...leads to very small differences, but big speedup
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic, 16) if (multiThread)
#pragma omp parallel for schedule(dynamic, 16) if (multiThread)
#endif
for (int i = 0; i < ch; ++i)
for (int j = 0; j < cw; ++j) {
float r = src->r(i, j);
float g = src->g(i, j);
float b = src->b(i, j);
r = (Color::igammatab_srgb[r]) / 65535.f;
g = (Color::igammatab_srgb[g]) / 65535.f;
b = (Color::igammatab_srgb[b]) / 65535.f;
dst->r(i, j) = r;
dst->g(i, j) = g;
dst->b(i, j) = b;
}
return;
for (int i = 0; i < ch; ++i)
for (int j = 0; j < cw; ++j) {
float r = src->r(i, j);
float g = src->g(i, j);
float b = src->b(i, j);
r = (Color::igammatab_srgb[r]) / 65535.f;
g = (Color::igammatab_srgb[g]) / 65535.f;
b = (Color::igammatab_srgb[b]) / 65535.f;
dst->r(i, j) = r;
dst->g(i, j) = g;
dst->b(i, j) = b;
}
return;
}
if (mul == 1 ||(params->icm.wprim == ColorManagementParams::Primaries::DEFAULT && params->icm.will == ColorManagementParams::Illuminant::DEFAULT)) {//shortcut and speedup when no call primaries and illuminant - no gamut control...in this case be careful
if (mul == 1 || (params->icm.wprim == ColorManagementParams::Primaries::DEFAULT && params->icm.will == ColorManagementParams::Illuminant::DEFAULT)) { //shortcut and speedup when no call primaries and illuminant - no gamut control...in this case be careful
GammaValues g_a; //gamma parameters
double pwr = 1.0 / static_cast<double>(gampos);
Color::calcGamma(pwr, slpos, g_a); // call to calcGamma with selected gamma and slope
#ifdef _OPENMP
# pragma omp parallel for schedule(dynamic,16) if (multiThread)
# pragma omp parallel for schedule(dynamic,16) if (multiThread)
#endif
for (int y = 0; y < ch; ++y) {
int x = 0;
#ifdef __SSE2__
for (; x < cw - 3; x += 4) {
STVFU(dst->r(y,x), F2V(65536.f) * gammalog(LVFU(src->r(y,x)), F2V(gampos), F2V(slpos), F2V(g_a[3]), F2V(g_a[4])));
STVFU(dst->g(y,x), F2V(65536.f) * gammalog(LVFU(src->g(y,x)), F2V(gampos), F2V(slpos), F2V(g_a[3]), F2V(g_a[4])));
STVFU(dst->b(y,x), F2V(65536.f) * gammalog(LVFU(src->b(y,x)), F2V(gampos), F2V(slpos), F2V(g_a[3]), F2V(g_a[4])));
}
STVFU(dst->r(y, x), F2V(65536.f) * gammalog(LVFU(src->r(y, x)), F2V(gampos), F2V(slpos), F2V(g_a[3]), F2V(g_a[4])));
STVFU(dst->g(y, x), F2V(65536.f) * gammalog(LVFU(src->g(y, x)), F2V(gampos), F2V(slpos), F2V(g_a[3]), F2V(g_a[4])));
STVFU(dst->b(y, x), F2V(65536.f) * gammalog(LVFU(src->b(y, x)), F2V(gampos), F2V(slpos), F2V(g_a[3]), F2V(g_a[4])));
}
#endif
for (; x < cw; ++x) {
dst->r(y,x) = 65536.f * gammalog(src->r(y,x), gampos, slpos, g_a[3], g_a[4]);
dst->g(y,x) = 65536.f * gammalog(src->g(y,x), gampos, slpos, g_a[3], g_a[4]);
dst->b(y,x) = 65536.f * gammalog(src->b(y,x), gampos, slpos, g_a[3], g_a[4]);
dst->r(y, x) = 65536.f * gammalog(src->r(y, x), gampos, slpos, g_a[3], g_a[4]);
dst->g(y, x) = 65536.f * gammalog(src->g(y, x), gampos, slpos, g_a[3], g_a[4]);
dst->b(y, x) = 65536.f * gammalog(src->b(y, x), gampos, slpos, g_a[3], g_a[4]);
}
}
return;
}
@ -498,6 +507,7 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
float bluyy = params->icm.bluy;
float grexx = params->icm.grex;
float greyy = params->icm.grey;
float epsil = 0.0001f;
if (prim == 12) {//convert datas area to xy
float redgraphx = params->icm.labgridcieALow;
@ -519,11 +529,34 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
greyy = 0.55f * (gregraphy + 1.f) - 0.1f;
greyy = rtengine::LIM(greyy, 0.5f, 1.f);
}
//fixed crash when there is no space or too small..just a line...Possible if bx, by aligned with Gx,Gy Rx,Ry
float ac = (greyy - redyy) / (grexx - redxx);
//fix crash if user select 0 for redyy, bluyy, greyy
if (redyy == 0.f) {
redyy = epsil;
}
if (bluyy == 0.f) {
bluyy = epsil;
}
if (greyy == 0.f) {
greyy = epsil;
}
//fix crash if grexx - redxx = 0
float grered = 1.f;
grered = grexx - redxx;
if (grered == 0.f) {
grered = epsil;
}
float ac = (greyy - redyy) / grered;
float bc = greyy - ac * grexx;
float yc = ac * bluxx + bc;
if ((bluyy < yc + 0.0004f) && (bluyy > yc - 0.0004f)) {//under 0.0004 in some case crash because space too small
if ((bluyy < yc + 0.0004f) && (bluyy > yc - 0.0004f)) { //under 0.0004 in some case crash because space too small
return;
}
@ -564,7 +597,6 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
}
case ColorManagementParams::Primaries::ACES_P0: {
profile = "ACESp0";
break;
}
@ -594,10 +626,12 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
}
}
if (settings->verbose && prim != 0) {
printf("prim=%i Profile Destination=%s\n", prim, profile.c_str());
}
if (settings->verbose && prim != 0) {
printf("prim=%i Profile Destination=%s\n", prim, profile.c_str());
}
cmsHTRANSFORM hTransform = nullptr;
if (transform) {
hTransform = transform;
} else {
@ -622,7 +656,9 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
};
double tempv4 = 5003.;
float p[6]; //primaries
double p[6]; //primaries
double Wx = 1.0;
double Wz = 1.0;
//primaries for 10 working profiles ==> output profiles
if (profile == "WideGamut") {
@ -633,6 +669,9 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[4] = 0.1570;
p[5] = 0.0180;
illum = toUnderlying(ColorManagementParams::Illuminant::D50);
Wx = 0.964295676;
Wz = 0.825104603;
} else if (profile == "Adobe RGB") {
p[0] = 0.6400; //Adobe primaries
p[1] = 0.3300;
@ -642,6 +681,9 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[5] = 0.0600;
tempv4 = 6504.;
illum = toUnderlying(ColorManagementParams::Illuminant::D65);
Wx = 0.95045471;
Wz = 1.08905029;
} else if (profile == "sRGB") {
p[0] = 0.6400; // sRGB primaries
p[1] = 0.3300;
@ -651,6 +693,9 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[5] = 0.0600;
tempv4 = 6504.;
illum = toUnderlying(ColorManagementParams::Illuminant::D65);
Wx = 0.95045471;
Wz = 1.08905029;
} else if (profile == "BruceRGB") {
p[0] = 0.6400; // Bruce primaries
p[1] = 0.3300;
@ -660,7 +705,10 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[5] = 0.0600;
tempv4 = 6504.;
illum = toUnderlying(ColorManagementParams::Illuminant::D65);
} else if (profile == "Beta RGB") {
Wx = 0.95045471;
Wz = 1.08905029;
} else if (profile == "Beta RGB") {
p[0] = 0.6888; // Beta primaries
p[1] = 0.3112;
p[2] = 0.1986;
@ -668,6 +716,9 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[4] = 0.1265;
p[5] = 0.0352;
illum = toUnderlying(ColorManagementParams::Illuminant::D50);
Wx = 0.964295676;
Wz = 0.825104603;
} else if (profile == "BestRGB") {
p[0] = 0.7347; // Best primaries
p[1] = 0.2653;
@ -676,6 +727,9 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[4] = 0.1300;
p[5] = 0.0350;
illum = toUnderlying(ColorManagementParams::Illuminant::D50);
Wx = 0.964295676;
Wz = 0.825104603;
} else if (profile == "Rec2020") {
p[0] = 0.7080; // Rec2020 primaries
p[1] = 0.2920;
@ -685,6 +739,9 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[5] = 0.0460;
tempv4 = 6504.;
illum = toUnderlying(ColorManagementParams::Illuminant::D65);
Wx = 0.95045471;
Wz = 1.08905029;
} else if (profile == "ACESp0") {
p[0] = 0.7347; // ACES P0 primaries
p[1] = 0.2653;
@ -694,6 +751,9 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[5] = -0.0770;
tempv4 = 6004.;
illum = toUnderlying(ColorManagementParams::Illuminant::D60);
Wx = 0.952646075;
Wz = 1.008825184;
} else if (profile == "ACESp1") {
p[0] = 0.713; // ACES P1 primaries
p[1] = 0.293;
@ -703,6 +763,9 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[5] = 0.044;
tempv4 = 6004.;
illum = toUnderlying(ColorManagementParams::Illuminant::D60);
Wx = 0.952646075;
Wz = 1.008825184;
} else if (profile == "ProPhoto") {
p[0] = 0.7347; //ProPhoto and default primaries
p[1] = 0.2653;
@ -711,6 +774,9 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
p[4] = 0.0366;
p[5] = 0.0001;
illum = toUnderlying(ColorManagementParams::Illuminant::D50);
Wx = 0.964295676;
Wz = 0.825104603;
} else if (profile == "Custom") {
p[0] = redxx;
p[1] = redyy;
@ -743,11 +809,13 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
gammaParams[3] = 1. / slpos;
gammaParams[5] = 0.0;
gammaParams[6] = 0.0;
// printf("ga0=%f ga1=%f ga2=%f ga3=%f ga4=%f\n", ga0, ga1, ga2, ga3, ga4);
// printf("ga0=%f ga1=%f ga2=%f ga3=%f ga4=%f\n", ga0, ga1, ga2, ga3, ga4);
// 7 parameters for smoother curves
cmsCIExyY xyD;
Glib::ustring ills = "D50";
switch (ColorManagementParams::Illuminant(illum)) {
case ColorManagementParams::Illuminant::DEFAULT:
case ColorManagementParams::Illuminant::STDA:
@ -802,55 +870,95 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
cmsWhitePointFromTemp(&xyD, tempv4);
switch (ColorManagementParams::Illuminant(illum)) {
case ColorManagementParams::Illuminant::DEFAULT:
case ColorManagementParams::Illuminant::D55:
case ColorManagementParams::Illuminant::DEFAULT: {
break;
}
case ColorManagementParams::Illuminant::D55: {
Wx = 0.956565934;
Wz = 0.920253249;
break;
}
case ColorManagementParams::Illuminant::D80: {
Wx = 0.950095542;
Wz = 1.284213976;
break;
}
case ColorManagementParams::Illuminant::D41: {
Wx = 0.991488263;
Wz = 0.631604625;
break;
}
case ColorManagementParams::Illuminant::D50: {
xyD = {0.3457, 0.3585, 1.0}; // near LCMS values but not perfect... it's a compromise!!
Wx = 0.964295676;
Wz = 0.825104603;
break;
}
case ColorManagementParams::Illuminant::D60: {
Wx = 0.952646075;
Wz = 1.008825184;
xyD = {0.32168, 0.33767, 1.0};
break;
}
case ColorManagementParams::Illuminant::D65: {
Wx = 0.95045471;
Wz = 1.08905029;
xyD = {0.312700492, 0.329000939, 1.0};
break;
}
case ColorManagementParams::Illuminant::D120: {
Wx = 0.979182;
Wz = 1.623623;
xyD = {0.269669, 0.28078, 1.0};
break;
}
case ColorManagementParams::Illuminant::STDA: {
Wx = 1.098500393;
Wz = 0.355848714;
xyD = {0.447573, 0.407440, 1.0};
ills = "stdA 2875K";
break;
}
case ColorManagementParams::Illuminant::TUNGSTEN_2000K: {
Wx = 1.274335;
Wz = 0.145233;
xyD = {0.526591, 0.41331, 1.0};
ills = "Tungsten 2000K";
break;
}
case ColorManagementParams::Illuminant::TUNGSTEN_1500K: {
Wx = 1.489921;
Wz = 0.053826;
xyD = {0.585703, 0.393157, 1.0};
ills = "Tungsten 1500K";
break;
}
}
double wprofpri[9];
if (gamutcontrol) {
//xyz in functiuon primaries and illuminant
Color::primaries_to_xyz(p, Wx, Wz, wprofpri);
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
wprofprim[i][j] = (double) wprofpri[j * 3 + i];
//xyz in TMatrix format
}
}
}
//D41 0.377984 0.381229
//D55 0.332424 0.347426
//D80 0.293755 0.309185
@ -869,7 +977,7 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
cmsWriteTag(oprofdef, cmsSigGreenTRCTag, GammaTRC[1]);
cmsWriteTag(oprofdef, cmsSigBlueTRCTag, GammaTRC[2]);
//to read XYZ values and illuminant
//to read XYZ values and illuminant
if (rtengine::settings->verbose) {
cmsCIEXYZ *redT = static_cast<cmsCIEXYZ*>(cmsReadTag(oprofdef, cmsSigRedMatrixColumnTag));
cmsCIEXYZ *greenT = static_cast<cmsCIEXYZ*>(cmsReadTag(oprofdef, cmsSigGreenMatrixColumnTag));
@ -881,6 +989,7 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
}
cmsFreeToneCurve(GammaTRC[0]);
if (oprofdef) {
constexpr cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE | cmsFLAGS_BLACKPOINTCOMPENSATION | cmsFLAGS_GAMUTCHECK;
const cmsHPROFILE iprof = ICCStore::getInstance()->getXYZProfile();
@ -889,7 +998,10 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
lcmsMutex->unlock();
}
}
if (hTransform) {
#ifdef _OPENMP
#pragma omp parallel if (multiThread)
#endif
@ -901,19 +1013,30 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
#pragma omp for schedule(dynamic, 16) nowait
#endif
for (int i = 0; i < ch; ++i) {
for (int i = 0; i < ch; ++i)
{
float *p = pBuf.data;
for (int j = 0; j < cw; ++j) {
const float r = src->r(i, j);
const float g = src->g(i, j);
const float b = src->b(i, j);
float X = toxyz[0][0] * r + toxyz[0][1] * g + toxyz[0][2] * b;
float Y = toxyz[1][0] * r + toxyz[1][1] * g + toxyz[1][2] * b;
float Z = toxyz[2][0] * r + toxyz[2][1] * g + toxyz[2][2] * b;
*(p++) = toxyz[0][0] * r + toxyz[0][1] * g + toxyz[0][2] * b;
*(p++) = toxyz[1][0] * r + toxyz[1][1] * g + toxyz[1][2] * b;
*(p++) = toxyz[2][0] * r + toxyz[2][1] * g + toxyz[2][2] * b;
if (gamutcontrol) {
Color::gamutmap(X, Y, Z, wprofprim);//gamut control
}
*(p++) = X;
*(p++) = Y;
*(p++) = Z;
}
p = pBuf.data;
cmsDoTransform(hTransform, p, p, cw);
for (int j = 0; j < cw; ++j) {
dst->r(i, j) = *(p++) * normalize;
dst->g(i, j) = *(p++) * normalize;
@ -921,10 +1044,12 @@ void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw,
}
}
}
if (!keepTransForm) {
cmsDeleteTransform(hTransform);
hTransform = nullptr;
}
transform = hTransform;
}
}

View File

@ -617,6 +617,7 @@ struct local_params {
float laplacexp;
float balanexp;
float linear;
int fullim;
int expmet;
int softmet;
int blurmet;
@ -896,6 +897,14 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
lp.laplacexp = locallab.spots.at(sp).laplacexp;
lp.balanexp = locallab.spots.at(sp).balanexp;
lp.linear = locallab.spots.at(sp).linear;
if (locallab.spots.at(sp).spotMethod == "norm") {
lp.fullim = 0;
} else if(locallab.spots.at(sp).spotMethod == "exc"){
lp.fullim = 1;
} else if (locallab.spots.at(sp).spotMethod == "full"){
lp.fullim = 2;
}
// printf("Lpfullim=%i\n", lp.fullim);
lp.fftColorMask = locallab.spots.at(sp).fftColorMask;
lp.prevdE = prevDeltaE;
@ -918,22 +927,22 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
lp.showmask_met = ll_Mask;
lp.showmaskciemet = llcieMask;
//printf("CIEmask=%i\n", lp.showmaskciemet);
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 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 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 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 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 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 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 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 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 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 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 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 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 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 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 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 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&& lllogMask == 0 && ll_Mask == 0 && llcieMask == 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 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 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 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 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 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 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 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.ena_Mask = locallab.spots.at(sp).enamask && lllcMask == 0 && llcbMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && lllogMask == 0 && llvibMask == 0 && llcieMask == 0;
lp.enaLMask = locallab.spots.at(sp).enaLMask && lllogMask == 0 && llColorMask == 0 && lllcMask == 0 && llsharMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && ll_Mask == 0 && llcieMask == 0;// Exposure mask is deactivated if Color & Light mask is visible
lp.enacieMask = locallab.spots.at(sp).enacieMask && llcieMask == 0 && llColorMask == 0 && llsoftMask == 0 && lllcMask == 0 && llsharMask == 0 && llExpMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0;
lp.enaColorMask = locallab.spots.at(sp).enaColorMask && llsoftMask == 0 && llColorMaskinv == 0 && llSHMaskinv == 0 && llColorMask == 0 && llExpMaskinv == 0 && lllcMask == 0 && llsharMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;// Exposure mask is deactivated if Color & Light mask is visible
lp.enaColorMaskinv = locallab.spots.at(sp).enaColorMask && llColorMaskinv == 0 && llSHMaskinv == 0 && llsoftMask == 0 && lllcMask == 0 && llsharMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;// Exposure mask is deactivated if Color & Light mask is visible
lp.enaExpMask = locallab.spots.at(sp).enaExpMask && llExpMask == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llColorMask == 0 && llColorMaskinv == 0 && llsoftMask == 0 && lllcMask == 0 && llsharMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;// Exposure mask is deactivated if Color & Light mask is visible
lp.enaExpMaskinv = locallab.spots.at(sp).enaExpMask && llExpMaskinv == 0 && llColorMask == 0 && llSHMaskinv == 0 && llColorMaskinv == 0 && llsoftMask == 0 && lllcMask == 0 && llsharMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;// Exposure mask is deactivated if Color & Light mask is visible
lp.enaSHMask = locallab.spots.at(sp).enaSHMask && llSHMask == 0 && llColorMask == 0 && llColorMaskinv == 0 && llSHMaskinv == 0 && llExpMaskinv == 0 && llsoftMask == 0 && lllcMask == 0 && llsharMask == 0 && llExpMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.enaSHMaskinv = locallab.spots.at(sp).enaSHMask && llColorMaskinv == 0 && llSHMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && lllcMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.enacbMask = locallab.spots.at(sp).enacbMask && llColorMaskinv == 0 && llcbMask == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && lllcMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.enaretiMask = locallab.spots.at(sp).enaretiMask && llColorMaskinv == 0 && lllcMask == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llsharMask == 0 && llsoftMask == 0 && llretiMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.enatmMask = locallab.spots.at(sp).enatmMask && llColorMaskinv == 0 && lltmMask == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && lllcMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && llblMask == 0 && llvibMask == 0&& lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.enablMask = locallab.spots.at(sp).enablMask && llColorMaskinv == 0 && llblMask == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && lllcMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.enavibMask = locallab.spots.at(sp).enavibMask && llvibMask == 0 && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && lllcMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llSHMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.enalcMask = locallab.spots.at(sp).enalcMask && lllcMask == 0 && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llcbMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.enasharMask = lllcMask == 0 && llcbMask == 0 && llsharMask == 0 && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llsoftMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.ena_Mask = locallab.spots.at(sp).enamask && lllcMask == 0 && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llcbMask == 0 && llsoftMask == 0 && llsharMask == 0 && llColorMask == 0 && llExpMask == 0 && llSHMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && lllogMask == 0 && llvibMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.enaLMask = locallab.spots.at(sp).enaLMask && lllogMask == 0 && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llColorMask == 0 && llsoftMask == 0 && lllcMask == 0 && llsharMask == 0 && llExpMask == 0 && llSHMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && ll_Mask == 0 && llcieMask == 0;// Exposure mask is deactivated if Color & Light mask is visible
lp.enacieMask = locallab.spots.at(sp).enacieMask && llcieMask == 0 && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llColorMask == 0 && llSHMask == 0 && llsoftMask == 0 && lllcMask == 0 && llsharMask == 0 && llExpMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llblMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0;
lp.thrlow = locallab.spots.at(sp).levelthrlow;
@ -1696,20 +1705,21 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
lp.threshol = thresho;
lp.chromacb = chromcbdl;
lp.expvib = locallab.spots.at(sp).expvibrance && lp.activspot ;
lp.colorena = locallab.spots.at(sp).expcolor && lp.activspot && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && lltmMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0; // Color & Light tool is deactivated if Exposure mask is visible or SHMask
lp.blurena = locallab.spots.at(sp).expblur && lp.activspot && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && llColorMask == 0 && lltmMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.tonemapena = locallab.spots.at(sp).exptonemap && lp.activspot && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && llColorMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.retiena = locallab.spots.at(sp).expreti && lp.activspot && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llColorMask == 0 && lltmMask == 0 && llvibMask == 0 && llSHMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.lcena = locallab.spots.at(sp).expcontrast && lp.activspot && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && llsharMask == 0 && llColorMask == 0 && lltmMask == 0 && llvibMask == 0 && llSHMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.cbdlena = locallab.spots.at(sp).expcbdl && lp.activspot && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llretiMask == 0 && lllcMask == 0 && llsharMask == 0 && lllcMask == 0 && llColorMask == 0 && lltmMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.exposena = locallab.spots.at(sp).expexpose && lp.activspot && llColorMask == 0 && llsoftMask == 0 && llSHMask == 0 && lllcMask == 0 && llsharMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0; // Exposure tool is deactivated if Color & Light mask SHmask is visible
lp.hsena = locallab.spots.at(sp).expshadhigh && lp.activspot && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && lltmMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;// Shadow Highlight tool is deactivated if Color & Light mask or SHmask is visible
lp.vibena = locallab.spots.at(sp).expvibrance && lp.activspot && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && llcbMask == 0 && lltmMask == 0 && llSHMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;// vibrance tool is deactivated if Color & Light mask or SHmask is visible
lp.sharpena = locallab.spots.at(sp).expsharp && lp.activspot && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llretiMask == 0 && llcbMask == 0 && lltmMask == 0 && llSHMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.sfena = locallab.spots.at(sp).expsoft && lp.activspot && llColorMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llretiMask == 0 && llcbMask == 0 && lltmMask == 0 && llSHMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.maskena = locallab.spots.at(sp).expmask && lp.activspot && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && llcbMask == 0 && lltmMask == 0 && lllogMask == 0 && llSHMask == 0 && llcieMask == 0;// vibrance tool is deactivated if Color & Light mask or SHmask is visible
lp.logena = locallab.spots.at(sp).explog && lp.activspot && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && llcbMask == 0 && lltmMask == 0 && llSHMask == 0 && ll_Mask == 0 && llcieMask == 0;// vibrance tool is deactivated if Color & Light mask or SHmask is visible
lp.cieena = locallab.spots.at(sp).expcie && lp.activspot && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && lltmMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0;// Shadow Highlight tool is deactivated if Color & Light mask or SHmask is visible
lp.colorena = locallab.spots.at(sp).expcolor && lp.activspot && llExpMaskinv == 0 && llSHMaskinv == 0 && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && lltmMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0; // Color & Light tool is deactivated if Exposure mask is visible or SHMask
lp.blurena = locallab.spots.at(sp).expblur && lp.activspot && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && llColorMask == 0 && lltmMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.tonemapena = locallab.spots.at(sp).exptonemap && lp.activspot && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && llColorMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.retiena = locallab.spots.at(sp).expreti && lp.activspot && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llColorMask == 0 && lltmMask == 0 && llvibMask == 0 && llSHMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.lcena = locallab.spots.at(sp).expcontrast && lp.activspot && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llcbMask == 0 && llsharMask == 0 && llColorMask == 0 && lltmMask == 0 && llvibMask == 0 && llSHMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.cbdlena = locallab.spots.at(sp).expcbdl && lp.activspot && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llExpMask == 0 && llsoftMask == 0 && llSHMask == 0 && llretiMask == 0 && lllcMask == 0 && llsharMask == 0 && lllcMask == 0 && llColorMask == 0 && lltmMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.exposena = locallab.spots.at(sp).expexpose && lp.activspot && llColorMaskinv == 0 && llSHMaskinv == 0 && llColorMask == 0 && llsoftMask == 0 && llSHMask == 0 && lllcMask == 0 && llsharMask == 0 && llcbMask == 0 && llretiMask == 0 && lltmMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0; // Exposure tool is deactivated if Color & Light mask SHmask is visible
lp.hsena = locallab.spots.at(sp).expshadhigh && lp.activspot && llColorMaskinv == 0 && llExpMaskinv == 0 && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && lltmMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;// Shadow Highlight tool is deactivated if Color & Light mask or SHmask is visible
lp.vibena = locallab.spots.at(sp).expvibrance && lp.activspot && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && llcbMask == 0 && lltmMask == 0 && llSHMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;// vibrance tool is deactivated if Color & Light mask or SHmask is visible
lp.sharpena = locallab.spots.at(sp).expsharp && lp.activspot && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llretiMask == 0 && llcbMask == 0 && lltmMask == 0 && llSHMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.sfena = locallab.spots.at(sp).expsoft && lp.activspot && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llColorMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llretiMask == 0 && llcbMask == 0 && lltmMask == 0 && llSHMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0 && llcieMask == 0;
lp.maskena = locallab.spots.at(sp).expmask && lp.activspot && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && llcbMask == 0 && lltmMask == 0 && lllogMask == 0 && llSHMask == 0 && llcieMask == 0;// vibrance tool is deactivated if Color & Light mask or SHmask is visible
lp.logena = locallab.spots.at(sp).explog && lp.activspot && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && llcbMask == 0 && lltmMask == 0 && llSHMask == 0 && ll_Mask == 0 && llcieMask == 0;// vibrance tool is deactivated if Color & Light mask or SHmask is visible
lp.cieena = locallab.spots.at(sp).expcie && lp.activspot && llColorMaskinv == 0 && llExpMaskinv == 0 && llSHMaskinv == 0 && llColorMask == 0 && llsoftMask == 0 && llExpMask == 0 && llcbMask == 0 && lllcMask == 0 && llsharMask == 0 && llretiMask == 0 && lltmMask == 0 && llvibMask == 0 && lllogMask == 0 && ll_Mask == 0;// Shadow Highlight tool is deactivated if Color & Light mask or SHmask is visible
lp.islocal = (lp.expvib || lp.colorena || lp.blurena || lp.tonemapena || lp.retiena || lp.lcena || lp.cbdlena || lp.exposena || lp.hsena || lp.vibena || lp.sharpena || lp.sfena || lp.maskena || lp.logena || lp.cieena);
@ -2976,7 +2986,7 @@ void ImProcFunctions::ciecamloc_02float(const struct local_params& lp, int sp, L
avgm + (1. - avgm) * (0.6 - contreal / 250.0), avgm + (1. - avgm) * (0.6 + contreal / 250.0),
1, 1
});
//all calculs in double to best results...but slow
//all calculations in double for best results...but slow
double lightreal = 0.2 * params->locallab.spots.at(sp).lightjzcie;
double chromz = params->locallab.spots.at(sp).chromjzcie;
double saturz = params->locallab.spots.at(sp).saturjzcie;
@ -3100,7 +3110,7 @@ void ImProcFunctions::ciecamloc_02float(const struct local_params& lp, int sp, L
}
}
}
//others "Lab" threatment...to adapt
//others "Lab" treatment...to adapt
if(wavcurvejz || mjjz != 0.f || lp.mCjz != 0.f) {//local contrast wavelet and clarity
#ifdef _OPENMP
@ -3464,7 +3474,7 @@ void ImProcFunctions::ciecamloc_02float(const struct local_params& lp, int sp, L
if(mocam == 0 || mocam == 1 || call == 1 || call == 2 || call == 10) {//call=2 vibrance warm-cool - call = 10 take into account "mean luminance Yb for Jz
//begin ciecam
if (settings->verbose && (mocam == 0 || mocam == 1 || call == 1)) {//display only if choice cam16
//informations on Cam16 scene conditions - allows user to see choices's incidences
//information on Cam16 scene conditions - allows user to see choices's incidences
float maxicam = -1000.f;
float maxicamq = -1000.f;
float maxisat = -1000.f;
@ -4019,7 +4029,7 @@ if(mocam == 3) {//Zcam not use but keep in case off
1, 1
});
//all calculs in double to best results...but slow
//all calculations in double for best results...but slow
double lqz = 0.4 * params->locallab.spots.at(sp).lightqzcam;
if(params->locallab.spots.at(sp).lightqzcam < 0) {
lqz = 0.2 * params->locallab.spots.at(sp).lightqzcam; //0.4 less effect, no need 1.
@ -5627,7 +5637,7 @@ float *ImProcFunctions::cos_table(size_t size)
const double pi_size = rtengine::RT_PI / size;
for (size_t i = 0; i < size; i++) {
table[i] = std::cos(pi_size * i);
table[i] = 1.0 - std::cos(pi_size * i);
}
return table;
@ -5673,7 +5683,7 @@ void ImProcFunctions::rex_poisson_dct(float * data, size_t nx, size_t ny, double
#endif
for (size_t i = 0; i < ny; ++i) {
for (size_t j = 0; j < nx; ++j) {
data[i * nx + j] *= m2 / (2.f - cosx[j] - cosy[i]);
data[i * nx + j] *= m2 / (cosx[j] + cosy[i]);
}
}
// handle the first value, data[0, 0] = 0
@ -7868,7 +7878,8 @@ void ImProcFunctions::InverseColorLight_Local(bool tonequ, bool tonecurv, int sp
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
// always calculate hueref, chromaref, lumaref before others operations
// use in normal mode for all modules except denoise
struct local_params lp;
calcLocalParams(sp, oW, oH, params->locallab, lp, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, locwavCurveden, locwavdenutili);
int begy = lp.yc - lp.lyT;
@ -8096,10 +8107,20 @@ const int fftw_size[] = {18144, 18000, 17920, 17836, 17820, 17640, 17600, 17550,
int N_fftwsize = sizeof(fftw_size) / sizeof(fftw_size[0]);
void optfft(int N_fftwsize, int &bfh, int &bfw, int &bfhr, int &bfwr, struct local_params& lp, int H, int W, int &xstart, int &ystart, int &xend, int &yend, int cx, int cy)
void optfft(int N_fftwsize, int &bfh, int &bfw, int &bfhr, int &bfwr, struct local_params& lp, int H, int W, int &xstart, int &ystart, int &xend, int &yend, int cx, int cy, int fulima)
{
int ftsizeH = 1;
int ftsizeW = 1;
int deltaw = 150;
int deltah = 150;
if(W < 4000) {
deltaw = 80;
}
if(H < 4000) {
deltah = 80;
}
for (int ft = 0; ft < N_fftwsize; ft++) { //find best values
if (fftw_size[ft] <= bfh) {
@ -8115,6 +8136,31 @@ void optfft(int N_fftwsize, int &bfh, int &bfw, int &bfhr, int &bfwr, struct loc
}
}
if(fulima == 2) {// if full image, the ftsizeH and ftsizeW is a bit larger (about 10 to 200 pixels) than the image dimensions so that it is fully processed (consumes a bit more resources)
for (int ftfu = 0; ftfu < N_fftwsize; ftfu++) { //find best values
if (fftw_size[ftfu] <= (H + deltah)) {
ftsizeH = fftw_size[ftfu];
break;
}
}
for (int ftfu = 0; ftfu < N_fftwsize; ftfu++) { //find best values
if (fftw_size[ftfu] <= (W + deltaw)) {
ftsizeW = fftw_size[ftfu];
break;
}
}
}
if (settings->verbose) {
if(fulima == 2) {
printf("Full image: ftsizeWF=%i ftsizeH=%i\n", ftsizeW, ftsizeH);
} else {
printf("ftsizeW=%i ftsizeH=%i\n", ftsizeW, ftsizeH);
}
}
//optimize with size fftw
bool reduW = false;
bool reduH = false;
@ -8152,7 +8198,6 @@ void optfft(int N_fftwsize, int &bfh, int &bfw, int &bfhr, int &bfwr, struct loc
reduW = true;
exec = false;
}
//new values optimized
ystart = rtengine::max(static_cast<int>(lp.yc - lp.lyT) - cy, 0);
yend = rtengine::min(static_cast<int>(lp.yc + lp.ly) - cy, H);
@ -8331,7 +8376,7 @@ void ImProcFunctions::transit_shapedetect2(int sp, float meantm, float stdtm, in
int bfhr = bfh;
int bfwr = bfw;
if (lp.blurcolmask >= 0.25f && lp.fftColorMask && call == 2) {
optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy);
optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy, lp.fullim);
}
bfh = bfhr;
@ -10274,7 +10319,7 @@ void ImProcFunctions::wavcontrast4(struct local_params& lp, float ** tmp, float
}
//gamma and slope residual image - be carefull memory
//gamma and slope residual image - be careful memory
bool tonecur = false;
const Glib::ustring profile = params->icm.workingProfile;
bool isworking = (profile == "sRGB" || profile == "Adobe RGB" || profile == "ProPhoto" || profile == "WideGamut" || profile == "BruceRGB" || profile == "Beta RGB" || profile == "BestRGB" || profile == "Rec2020" || profile == "ACESp0" || profile == "ACESp1");
@ -10321,7 +10366,7 @@ void ImProcFunctions::wavcontrast4(struct local_params& lp, float ** tmp, float
cmsHTRANSFORM dummy = nullptr;
int ill =0;
workingtrc(tmpImage, tmpImage, W_Level, H_Level, -5, prof, 2.4, 12.92310, ill, 0, dummy, true, false, false);
workingtrc(tmpImage, tmpImage, W_Level, H_Level, 1, prof, lp.residgam, lp.residslop, ill, 0, dummy, false, true, true);//be carefull no gamut control
workingtrc(tmpImage, tmpImage, W_Level, H_Level, 1, prof, lp.residgam, lp.residslop, ill, 0, dummy, false, true, true);//be careful no gamut control
rgb2lab(*tmpImage, *labresid, params->icm.workingProfile);
delete tmpImage;
@ -10704,7 +10749,7 @@ void ImProcFunctions::DeNoise(int call, float * slidL, float * slida, float * sl
float gamma = lp.noisegam;
rtengine::GammaValues g_a; //gamma parameters
double pwr = 1.0 / (double) lp.noisegam;//default 3.0 - gamma Lab
double ts = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope
if(gamma > 1.f) {
@ -11419,7 +11464,7 @@ void ImProcFunctions::DeNoise(int call, float * slidL, float * slida, float * sl
float gamma = lp.noisegam;
rtengine::GammaValues g_a; //gamma parameters
double pwr = 1.0 / (double) lp.noisegam;//default 3.0 - gamma Lab
double ts = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope
if(gamma > 1.f) {
#ifdef _OPENMP
@ -12275,12 +12320,31 @@ void ImProcFunctions::clarimerge(const struct local_params& lp, float &mL, float
}
}
void ImProcFunctions::avoidcolshi(const struct local_params& lp, int sp, LabImage * original, LabImage *transformed, int cy, int cx, int sk)
void ImProcFunctions::avoidcolshi(const struct local_params& lp, int sp, LabImage *transformed, LabImage *reserved, int cy, int cx, int sk)
{
if (params->locallab.spots.at(sp).avoid && lp.islocal) {
int avoidgamut = 0;
if (params->locallab.spots.at(sp).avoidgamutMethod == "NONE") {
avoidgamut = 0;
} else if (params->locallab.spots.at(sp).avoidgamutMethod == "LAB") {
avoidgamut = 1;
} else if (params->locallab.spots.at(sp).avoidgamutMethod == "XYZ") {
avoidgamut = 2;
} else if (params->locallab.spots.at(sp).avoidgamutMethod == "XYZREL") {
avoidgamut = 3;
} else if (params->locallab.spots.at(sp).avoidgamutMethod == "MUNS") {
avoidgamut = 4;
}
if (avoidgamut == 0) {
return;
}
if (avoidgamut > 0 && lp.islocal) {
const float ach = lp.trans / 100.f;
bool execmunsell = true;
if(params->locallab.spots.at(sp).expcie && (params->locallab.spots.at(sp).modecam == "all" || params->locallab.spots.at(sp).modecam == "jz" || params->locallab.spots.at(sp).modecam == "cam16")) {
if (params->locallab.spots.at(sp).expcie && (params->locallab.spots.at(sp).modecam == "all" || params->locallab.spots.at(sp).modecam == "jz" || params->locallab.spots.at(sp).modecam == "cam16")) {
execmunsell = false;
}
@ -12291,8 +12355,15 @@ void ImProcFunctions::avoidcolshi(const struct local_params& lp, int sp, LabImag
{wiprof[2][0], wiprof[2][1], wiprof[2][2]}
};
TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile);
const double wp[3][3] = {//improve precision with double
{wprof[0][0], wprof[0][1], wprof[0][2]},
{wprof[1][0], wprof[1][1], wprof[1][2]},
{wprof[2][0], wprof[2][1], wprof[2][2]}
};
const float softr = params->locallab.spots.at(sp).avoidrad;//max softr = 30
const bool muns = params->locallab.spots.at(sp).avoidmun;//Munsell control with 200 LUT
// const bool muns = params->locallab.spots.at(sp).avoidmun;//Munsell control with 200 LUT
//improve precision with mint and maxt
const float tr = std::min(2.f, softr);
const float mint = 0.15f - 0.06f * tr;//between 0.15f and 0.03f
@ -12316,6 +12387,7 @@ void ImProcFunctions::avoidcolshi(const struct local_params& lp, int sp, LabImag
#ifdef _OPENMP
#pragma omp for schedule(dynamic,16)
#endif
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
@ -12375,7 +12447,7 @@ void ImProcFunctions::avoidcolshi(const struct local_params& lp, int sp, LabImag
if (lp.shapmet == 0) {
calcTransition(lox, loy, ach, lp, zone, localFactor);
} else /*if (lp.shapmet == 1)*/ {
} else { /*if (lp.shapmet == 1)*/
calcTransitionrect(lox, loy, ach, lp, zone, localFactor);
}
@ -12410,42 +12482,103 @@ void ImProcFunctions::avoidcolshi(const struct local_params& lp, int sp, LabImag
sincosval.y = aa / (Chprov1 * 327.68f);
sincosval.x = bb / (Chprov1 * 327.68f);
}
#endif
float lnew = transformed->L[y][x];
float anew = transformed->a[y][x];
float bnew = transformed->b[y][x];
Lprov1 = lnew / 327.68f;
//HH = xatan2f(bnew, anew);
Color::pregamutlab(Lprov1, HH, chr);
Chprov1 = rtengine::min(Chprov1, chr);
if(!muns) {
float R, G, B;
if (avoidgamut == 1) { //Lab correction
Color::pregamutlab(Lprov1, HH, chr);
Chprov1 = rtengine::min(Chprov1, chr);
float R, G, B;
Color::gamutLchonly(HH, sincosval, Lprov1, Chprov1, R, G, B, wip, highlight, mint, maxt);//replace for best results
}
transformed->L[y][x] = Lprov1 * 327.68f;
transformed->a[y][x] = 327.68f * Chprov1 * sincosval.y;
transformed->b[y][x] = 327.68f * Chprov1 * sincosval.x;
lnew = Lprov1 * 327.68f;
anew = 327.68f * Chprov1 * sincosval.y;
bnew = 327.68f * Chprov1 * sincosval.x;
//HH = xatan2f(bnew, anew);
transformed->a[y][x] = anew;
transformed->b[y][x] = bnew;
if (needHH) {
const float Lprov2 = original->L[y][x] / 327.68f;
} else if (avoidgamut == 2 || avoidgamut == 3) { //XYZ correction
float xg, yg, zg;
const float aag = transformed->a[y][x];//anew
const float bbg = transformed->b[y][x];//bnew
float Lag = transformed->L[y][x];
Color::Lab2XYZ(Lag, aag, bbg, xg, yg, zg);
float x0 = xg;
float y0 = yg;
float z0 = zg;
Color::gamutmap(xg, yg, zg, wp);
if (avoidgamut == 3) {//0.5f arbitrary coeff
xg = xg + 0.5f * (x0 - xg);
yg = yg + 0.5f * (y0 - yg);
zg = zg + 0.5f * (z0 - zg);
}
//Color::gamutmap(xg, yg, zg, wp);//Put XYZ in gamut wp
float aag2, bbg2;
Color::XYZ2Lab(xg, yg, zg, Lag, aag2, bbg2);
Lprov1 = Lag / 327.68f;
HH = xatan2f(bbg2, aag2);//rebuild HH in case of...absolute colorimetry
Chprov1 = std::sqrt(SQR(aag2) + SQR(bbg2)) / 327.68f;
if (Chprov1 == 0.0f) {
sincosval.y = 1.f;
sincosval.x = 0.0f;
} else {
sincosval.y = aag2 / (Chprov1 * 327.68f);
sincosval.x = bbg2 / (Chprov1 * 327.68f);
}
lnew = Lprov1 * 327.68f;
anew = 327.68f * Chprov1 * sincosval.y;
bnew = 327.68f * Chprov1 * sincosval.x;
transformed->a[y][x] = anew;
transformed->b[y][x] = bnew;
}
if (needHH && avoidgamut <= 4) {//Munsell
Lprov1 = lnew / 327.68f;
float Chprov = sqrt(SQR(anew) + SQR(bnew)) / 327.68f;
const float Lprov2 = reserved->L[y][x] / 327.68f;
float correctionHue = 0.f; // Munsell's correction
float correctlum = 0.f;
const float memChprov = std::sqrt(SQR(original->a[y][x]) + SQR(original->b[y][x])) / 327.68f;
float Chprov = std::sqrt(SQR(transformed->a[y][x]) + SQR(transformed->b[y][x])) / 327.68f;
if(execmunsell) {
const float memChprov = std::sqrt(SQR(reserved->a[y][x]) + SQR(reserved->b[y][x])) / 327.68f;
if (execmunsell) {
Color::AllMunsellLch(true, Lprov1, Lprov2, HH, Chprov, memChprov, correctionHue, correctlum);
}
if (std::fabs(correctionHue) < 0.015f) {
HH += correctlum; // correct only if correct Munsell chroma very small.
if (correctionHue != 0.f || correctlum != 0.f) {
if (std::fabs(correctionHue) < 0.015f) {
HH += correctlum; // correct only if correct Munsell chroma very small.
}
sincosval = xsincosf(HH + correctionHue);
}
sincosval = xsincosf(HH + correctionHue);
transformed->a[y][x] = 327.68f * Chprov * sincosval.y; // apply Munsell
transformed->b[y][x] = 327.68f * Chprov * sincosval.x;
anew = 327.68f * Chprov * sincosval.y; // apply Munsell
bnew = 327.68f * Chprov * sincosval.x;
transformed->a[y][x] = anew; // apply Munsell
transformed->b[y][x] = bnew;
}
}
}
}
//Guidedfilter to reduce artifacts in transitions
if (softr != 0.f) {//soft for L a b because we change color...
//Guidedfilter to reduce artifacts in transitions : case Lab
if (softr != 0.f && avoidgamut == 1) {//soft for L a b because we change color...
const float tmpblur = softr < 0.f ? -1.f / softr : 1.f + softr;
const int r1 = rtengine::max<int>(6 / sk * tmpblur + 0.5f, 1);
const int r2 = rtengine::max<int>(10 / sk * tmpblur + 0.5f, 1);
@ -12469,13 +12602,15 @@ void ImProcFunctions::avoidcolshi(const struct local_params& lp, int sp, LabImag
for (int y = 0; y < bh ; y++) {
for (int x = 0; x < bw; x++) {
ble[y][x] = transformed->L[y][x] / 32768.f;
guid[y][x] = original->L[y][x] / 32768.f;
guid[y][x] = reserved->L[y][x] / 32768.f;
}
}
rtengine::guidedFilter(guid, ble, ble, r2, 0.2f * epsil, multiThread);
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
#endif
for (int y = 0; y < bh; y++) {
for (int x = 0; x < bw; x++) {
transformed->L[y][x] = 32768.f * ble[y][x];
@ -12492,11 +12627,13 @@ void ImProcFunctions::avoidcolshi(const struct local_params& lp, int sp, LabImag
blechro[y][x] = std::sqrt(SQR(transformed->b[y][x]) + SQR(transformed->a[y][x])) / 32768.f;
}
}
rtengine::guidedFilter(guid, blechro, blechro, r1, epsil, multiThread);
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
#endif
for (int y = 0; y < bh; y++) {
for (int x = 0; x < bw; x++) {
const float Chprov1 = std::sqrt(SQR(transformed->a[y][x]) + SQR(transformed->b[y][x]));
@ -13021,7 +13158,7 @@ void ImProcFunctions::Lab_Local(
struct local_params lp;
calcLocalParams(sp, oW, oH, params->locallab, lp, prevDeltaE, llColorMask, llColorMaskinv, llExpMask, llExpMaskinv, llSHMask, llSHMaskinv, llvibMask, lllcMask, llsharMask, llcbMask, llretiMask, llsoftMask, lltmMask, llblMask, lllogMask, ll_Mask, llcieMask, locwavCurveden, locwavdenutili);
avoidcolshi(lp, sp, original, transformed, cy, cx, sk);
//avoidcolshi(lp, sp, transformed, reserved, cy, cx, sk);
const float radius = lp.rad / (sk * 1.4); //0 to 70 ==> see skip
int levred;
@ -13107,7 +13244,7 @@ void ImProcFunctions::Lab_Local(
}
//encoding lab at the beginning
if (lp.logena && (lp.showmasklogmet == 2 || lp.enaLMask || lp.showmasklogmet == 3 || lp.showmasklogmet == 4)) {
if (lp.logena && (call <=3 || lp.prevdE || lp.showmasklogmet == 2 || lp.enaLMask || lp.showmasklogmet == 3 || lp.showmasklogmet == 4)) {
const int ystart = rtengine::max(static_cast<int>(lp.yc - lp.lyT) - cy, 0);
const int yend = rtengine::min(static_cast<int>(lp.yc + lp.ly) - cy, original->H);
@ -13439,7 +13576,7 @@ void ImProcFunctions::Lab_Local(
if (bfw >= mSP && bfh >= mSP) {
if (lp.blurmet == 0 && (fft || lp.rad > 30.0)) {
optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy);
optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy, lp.fullim);
}
const std::unique_ptr<LabImage> bufgbi(new LabImage(TW, TH));
@ -14756,7 +14893,7 @@ void ImProcFunctions::Lab_Local(
if (bfw >= mSP && bfh > mSP) {
if (lp.ftwreti) {
optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy);
optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy, lp.fullim);
}
array2D<float> buflight(bfw, bfh);
@ -15300,7 +15437,7 @@ void ImProcFunctions::Lab_Local(
//vibrance
float vibg = params->locallab.spots.at(sp).vibgam;
if (lp.expvib && (lp.past != 0.f || lp.satur != 0.f || lp.strvib != 0.f || vibg != 1.f || lp.war != 0 || lp.strvibab != 0.f || lp.strvibh != 0.f || lp.showmaskvibmet == 2 || lp.enavibMask || lp.showmaskvibmet == 3 || lp.showmaskvibmet == 4 || lp.prevdE) && lp.vibena) { //interior ellipse renforced lightness and chroma //locallutili
if (lp.expvib && (lp.past != 0.f || lp.satur != 0.f || lp.strvib != 0.f || vibg != 1.f || lp.war != 0 || lp.strvibab != 0.f || lp.strvibh != 0.f || lp.showmaskvibmet == 2 || lp.enavibMask || lp.showmaskvibmet == 3 || lp.showmaskvibmet == 4 || lp.prevdE) && lp.vibena) { //interior ellipse reinforced lightness and chroma //locallutili
if (call <= 3) { //simpleprocess, dcrop, improccoordinator
const int ystart = rtengine::max(static_cast<int>(lp.yc - lp.lyT) - cy, 0);
const int yend = rtengine::min(static_cast<int>(lp.yc + lp.ly) - cy, original->H);
@ -15511,7 +15648,7 @@ void ImProcFunctions::Lab_Local(
float gamma1 = params->locallab.spots.at(sp).vibgam;
rtengine::GammaValues g_a; //gamma parameters
double pwr1 = 1.0 / (double) gamma1;//default 3.0 - gamma Lab
double ts1 = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts1 = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr1, ts1, g_a); // call to calcGamma with selected gamma and slope
if(gamma1 != 1.f) {
#ifdef _OPENMP
@ -15536,7 +15673,7 @@ void ImProcFunctions::Lab_Local(
// float gamma = params->locallab.spots.at(sp).vibgam;
// rtengine::GammaValues g_a; //gamma parameters
// double pwr = 1.0 / (double) gamma;//default 3.0 - gamma Lab
// double ts = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
// double ts = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
// rtengine::Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope
if(gamma1 != 1.f) {
@ -15915,7 +16052,7 @@ void ImProcFunctions::Lab_Local(
if (bfw >= mSP && bfh >= mSP) {
if (lp.softmet == 1) {
optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy);
optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy, lp.fullim);
}
const std::unique_ptr<LabImage> bufexporig(new LabImage(bfw, bfh));
@ -16041,7 +16178,7 @@ void ImProcFunctions::Lab_Local(
if (bfw >= mSPwav && bfh >= mSPwav) {//avoid too small spot for wavelet
if (lp.ftwlc) {
optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy);
optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy, lp.fullim);
}
std::unique_ptr<LabImage> bufmaskblurlc;
@ -16257,7 +16394,7 @@ void ImProcFunctions::Lab_Local(
float gamma = lp.gamlc;
rtengine::GammaValues g_a; //gamma parameters
double pwr = 1.0 / (double) lp.gamlc;//default 3.0 - gamma Lab
double ts = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope
if(gamma != 1.f) {
@ -16523,23 +16660,36 @@ void ImProcFunctions::Lab_Local(
if (!lp.invshar && lp.shrad > 0.42 && call < 3 && lp.sharpena && sk == 1) { //interior ellipse for sharpening, call = 1 and 2 only with Dcrop and simpleprocess
int bfh = call == 2 ? int (lp.ly + lp.lyT) + del : original->H; //bfw bfh real size of square zone
int bfw = call == 2 ? int (lp.lx + lp.lxL) + del : original->W;
JaggedArray<float> 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<float> bufsh(bfw, bfh, true);
JaggedArray<float> hbuffer(bfw, bfh);
int begy = lp.yc - lp.lyT;
int begx = lp.xc - lp.lxL;
int yEn = lp.yc + lp.ly;
int xEn = lp.xc + lp.lx;
if(lp.fullim == 2) {//limit sharpening to image dimension...no more...to avoid a long treatment
begy = 0;
begx = 0;
yEn = original->H;
xEn = original->W;
lp.lxL = lp.xc;
lp.lyT = lp.yc;
lp.ly = yEn - lp.yc;
lp.lx = xEn - lp.xc;
bfh= yEn;
bfw = xEn;
}
//printf("begy=%i begx=%i yen=%i xen=%i\n", begy, begx, yEn, xEn);
JaggedArray<float> bufsh(bfw, bfh, true);
JaggedArray<float> hbuffer(bfw, bfh);
JaggedArray<float> loctemp2(bfw, bfh);
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
#endif
@ -16556,7 +16706,7 @@ void ImProcFunctions::Lab_Local(
float gamma1 = params->locallab.spots.at(sp).shargam;
rtengine::GammaValues g_a; //gamma parameters
double pwr1 = 1.0 / (double) gamma1;//default 3.0 - gamma Lab
double ts1 = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts1 = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr1, ts1, g_a); // call to calcGamma with selected gamma and slope
if(gamma1 != 1.f) {
#ifdef _OPENMP
@ -16576,13 +16726,12 @@ void ImProcFunctions::Lab_Local(
}
//sharpen only square area instead of all image
ImProcFunctions::deconvsharpeningloc(bufsh, hbuffer, bfw, bfh, loctemp, params->locallab.spots.at(sp).shardamping, (double)params->locallab.spots.at(sp).sharradius, params->locallab.spots.at(sp).shariter, params->locallab.spots.at(sp).sharamount, params->locallab.spots.at(sp).sharcontrast, (double)params->locallab.spots.at(sp).sharblur, 1);
//sharpen only square area instead of all image, but limited to image dimensions (full image)
ImProcFunctions::deconvsharpeningloc(bufsh, hbuffer, bfw, bfh, loctemp2, params->locallab.spots.at(sp).shardamping, (double)params->locallab.spots.at(sp).sharradius, params->locallab.spots.at(sp).shariter, params->locallab.spots.at(sp).sharamount, params->locallab.spots.at(sp).sharcontrast, (double)params->locallab.spots.at(sp).sharblur, 1);
/*
float gamma = params->locallab.spots.at(sp).shargam;
double pwr = 1.0 / (double) gamma;//default 3.0 - gamma Lab
double ts = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope
*/
if(gamma1 != 1.f) {
@ -16594,24 +16743,24 @@ void ImProcFunctions::Lab_Local(
#ifdef __SSE2__
for (; x < bfw - 3; x += 4) {
STVFU(bufsh[y][x], F2V(32768.f) * gammalog(LVFU(bufsh[y][x]) / F2V(32768.f), F2V(gamma1), F2V(ts1), F2V(g_a[3]), F2V(g_a[4])));
STVFU(loctemp[y][x], F2V(32768.f) * gammalog(LVFU(loctemp[y][x]) / F2V(32768.f), F2V(gamma1), F2V(ts1), F2V(g_a[3]), F2V(g_a[4])));
STVFU(loctemp2[y][x], F2V(32768.f) * gammalog(LVFU(loctemp2[y][x]) / F2V(32768.f), F2V(gamma1), F2V(ts1), F2V(g_a[3]), F2V(g_a[4])));
}
#endif
for (; x < bfw; ++x) {
bufsh[y][x] = 32768.f * gammalog(bufsh[y][x] / 32768.f, gamma1, ts1, g_a[3], g_a[4]);
loctemp[y][x] = 32768.f * gammalog(loctemp[y][x] / 32768.f, gamma1, ts1, g_a[3], g_a[4]);
loctemp2[y][x] = 32768.f * gammalog(loctemp2[y][x] / 32768.f, gamma1, ts1, g_a[3], g_a[4]);
}
}
}
//sharpen simpleprocess
Sharp_Local(call, loctemp2, 0, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
} else { //call from dcrop.cc
JaggedArray<float> loctemp(bfw, bfh);
float gamma1 = params->locallab.spots.at(sp).shargam;
rtengine::GammaValues g_a; //gamma parameters
double pwr1 = 1.0 / (double) gamma1;//default 3.0 - gamma Lab
double ts1 = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts1 = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr1, ts1, g_a); // call to calcGamma with selected gamma and slope
if(gamma1 != 1.f) {
#ifdef _OPENMP
@ -16635,7 +16784,7 @@ void ImProcFunctions::Lab_Local(
/*
float gamma = params->locallab.spots.at(sp).shargam;
double pwr = 1.0 / (double) gamma;//default 3.0 - gamma Lab
double ts = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope
*/
if(gamma1 != 1.f) {
@ -16656,12 +16805,10 @@ void ImProcFunctions::Lab_Local(
}
}
}
//sharpen dcrop
Sharp_Local(call, loctemp, 0, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
}
//sharpen ellipse and transition
Sharp_Local(call, loctemp, 0, hueref, chromaref, lumaref, lp, original, transformed, cx, cy, sk);
if (lp.recur) {
original->CopyFrom(transformed, multiThread);
@ -16677,7 +16824,7 @@ void ImProcFunctions::Lab_Local(
float gamma1 = params->locallab.spots.at(sp).shargam;
rtengine::GammaValues g_a; //gamma parameters
double pwr1 = 1.0 / (double) gamma1;//default 3.0 - gamma Lab
double ts1 = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts1 = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr1, ts1, g_a); // call to calcGamma with selected gamma and slope
if(gamma1 != 1.f) {
#ifdef _OPENMP
@ -16697,12 +16844,11 @@ void ImProcFunctions::Lab_Local(
}
ImProcFunctions::deconvsharpeningloc(original->L, shbuffer, GW, GH, loctemp, params->locallab.spots.at(sp).shardamping, (double)params->locallab.spots.at(sp).sharradius, params->locallab.spots.at(sp).shariter, params->locallab.spots.at(sp).sharamount, params->locallab.spots.at(sp).sharcontrast, (double)params->locallab.spots.at(sp).sharblur, sk);
/*
float gamma = params->locallab.spots.at(sp).shargam;
double pwr = 1.0 / (double) gamma;//default 3.0 - gamma Lab
double ts = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope
*/
if(gamma1 != 1.f) {
@ -16757,7 +16903,7 @@ void ImProcFunctions::Lab_Local(
if (bfw >= mSP && bfh >= mSP) {
if (lp.expmet == 1 || lp.expmet == 0) {
optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy);
optfft(N_fftwsize, bfh, bfw, bfhr, bfwr, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy, lp.fullim);
}
const std::unique_ptr<LabImage> bufexporig(new LabImage(bfw, bfh));
@ -16788,7 +16934,7 @@ void ImProcFunctions::Lab_Local(
float gamma1 = lp.gamex;
rtengine::GammaValues g_a; //gamma parameters
double pwr1 = 1.0 / (double) lp.gamex;//default 3.0 - gamma Lab
double ts1 = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts1 = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr1, ts1, g_a); // call to calcGamma with selected gamma and slope
if(gamma1 != 1.f) {
@ -17022,7 +17168,7 @@ void ImProcFunctions::Lab_Local(
evnoise *= 0.4f;
}
//soft denoise, user must use Local Denoise to best result
//soft denoise, user must use Local Denoise for best result
Median med;
if (evnoise < -18000.f) {
med = Median::TYPE_5X5_STRONG;
@ -17108,7 +17254,7 @@ void ImProcFunctions::Lab_Local(
float gamma = lp.gamex;
rtengine::GammaValues g_a; //gamma parameters
double pwr = 1.0 / (double) lp.gamex;//default 3.0 - gamma Lab
double ts = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope
*/
if(gamma1 != 1.f) {
@ -17275,7 +17421,7 @@ void ImProcFunctions::Lab_Local(
const float a_scalemerg = (lp.highAmerg - lp.lowAmerg) / factor / scaling;
const float b_scalemerg = (lp.highBmerg - lp.lowBmerg) / factor / scaling;
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.prevdE) && lp.colorena) { // || lllocalcurve)) { //interior ellipse renforced lightness and chroma //locallutili
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.prevdE) && lp.colorena) { // || lllocalcurve)) { //interior ellipse reinforced lightness and chroma //locallutili
int ystart = rtengine::max(static_cast<int>(lp.yc - lp.lyT) - cy, 0);
int yend = rtengine::min(static_cast<int>(lp.yc + lp.ly) - cy, original->H);
int xstart = rtengine::max(static_cast<int>(lp.xc - lp.lxL) - cx, 0);
@ -17287,7 +17433,7 @@ void ImProcFunctions::Lab_Local(
if (bfw >= mSP && bfh >= mSP) {
if (lp.blurcolmask >= 0.25f && lp.fftColorMask && call == 2) {
optfft(N_fftwsize, bfh, bfw, bfh, bfw, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy);
optfft(N_fftwsize, bfh, bfw, bfh, bfw, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy, lp.fullim);
}
std::unique_ptr<LabImage> bufcolorig;
@ -17347,7 +17493,7 @@ void ImProcFunctions::Lab_Local(
float gamma1 = lp.gamc;
rtengine::GammaValues g_a; //gamma parameters
double pwr1 = 1.0 / (double) lp.gamc;//default 3.0 - gamma Lab
double ts1 = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts1 = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr1, ts1, g_a); // call to calcGamma with selected gamma and slope
if(gamma1 != 1.f) {
@ -18375,7 +18521,7 @@ void ImProcFunctions::Lab_Local(
float gamma = lp.gamc;
rtengine::GammaValues g_a; //gamma parameters
double pwr = 1.0 / (double) lp.gamc;//default 3.0 - gamma Lab
double ts = 9.03296;//always the same 'slope' in the extrem shadows - slope Lab
double ts = 9.03296;//always the same 'slope' in the extreme shadows - slope Lab
rtengine::Color::calcGamma(pwr, ts, g_a); // call to calcGamma with selected gamma and slope
*/
if(gamma1 != 1.f) {
@ -18557,7 +18703,7 @@ void ImProcFunctions::Lab_Local(
if (bfw >= mSP && bfh >= mSP) {
if (lp.blurma >= 0.25f && lp.fftma && call == 2) {
optfft(N_fftwsize, bfh, bfw, bfh, bfw, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy);
optfft(N_fftwsize, bfh, bfw, bfh, bfw, lp, original->H, original->W, xstart, ystart, xend, yend, cx, cy, lp.fullim);
}
array2D<float> blechro(bfw, bfh);
array2D<float> ble(bfw, bfh);
@ -18909,7 +19055,7 @@ void ImProcFunctions::Lab_Local(
// Gamut and Munsell control - very important do not deactivated to avoid crash
avoidcolshi(lp, sp, original, transformed, cy, cx, sk);
avoidcolshi(lp, sp, transformed, reserved, cy, cx, sk);
}
}

View File

@ -209,7 +209,7 @@ std::unique_ptr<LUTf> ImProcFunctions::buildMeaLut(const float inVals[11], const
}
}
}
lutFactor = 1.f / lutDiff;
lutFactor = lutDiff == 0.f ? 0.f : 1.f / lutDiff;
return std::unique_ptr<LUTf>(new LUTf(lutVals));
}
@ -301,17 +301,18 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
if (params->wavelet.denmethod == "equ") {
cp.denmet = 0;
} else if (params->wavelet.denmethod == "high") {
cp.denmet = 1;
} else if (params->wavelet.denmethod == "low") {
cp.denmet = 2;
} else if (params->wavelet.denmethod == "12high") {
cp.denmet = 3;
} else if (params->wavelet.denmethod == "12low") {
cp.denmet = 4;
}
cp.denmet = 4;
//if (params->wavelet.denmethod == "equ") {
// cp.denmet = 0;
//} else if (params->wavelet.denmethod == "high") {
// cp.denmet = 1;
//} else if (params->wavelet.denmethod == "low") {
// cp.denmet = 2;
//} else if (params->wavelet.denmethod == "12high") {
// cp.denmet = 3;
//} else if (params->wavelet.denmethod == "12low") {
// cp.denmet = 4;
//}
if (params->wavelet.mixmethod == "nois") {
cp.mixmet = 0;
@ -658,7 +659,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
maxlevelcrop = 10;
}
// adap maximum level wavelet to size of crop
// adapt maximum level wavelet to size of crop
if (minwin * skip < 1024) {
maxlevelcrop = 9; //sampling wavelet 512
}
@ -694,7 +695,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
levwav = rtengine::min(maxlevelcrop, levwav);
// I suppress this fonctionality ==> crash for level < 3
// I suppress this functionality ==> crash for level < 3
if (levwav < 1) {
return; // nothing to do
}
@ -2031,7 +2032,7 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const
}
a = 327.68f * Chprov * sincosv.y; // apply Munsell
b = 327.68f * Chprov * sincosv.x; //aply Munsell
b = 327.68f * Chprov * sincosv.x; // apply Munsell
} else {//general case
L = labco->L[i1][j1];
const float Lin = std::max(0.f, L);

View File

@ -21,10 +21,14 @@
namespace rtengine
{
// Aligned so the first entry starts on line 30
enum ProcEventCode {
EvPhotoLoaded = 0,
EvProfileLoaded = 1,
obsolete_1 = 1,
EvProfileChanged = 2,
EvHistoryBrowsed = 3,
EvBrightness = 4,
@ -38,9 +42,9 @@ enum ProcEventCode {
EvClip = 12,
EvLBrightness = 13,
EvLContrast = 14,
EvLBlack = 15,
EvLHLCompr = 16,
EvLSHCompr = 17,
obsolete_15 = 15, // obsolete
obsolete_16 = 16, // obsolete
obsolete_17 = 17, // obsolete
EvLLCurve = 18,
EvShrEnabled = 19,
EvShrRadius = 20,
@ -77,7 +81,7 @@ enum ProcEventCode {
EvSHShadows = 51,
EvSHHLTonalW = 52,
EvSHSHTonalW = 53,
EvSHLContrast = 54,
obsolete_54 = 54, // obsolete
EvSHRadius = 55,
EvCTRotate = 56,
EvCTHFlip = 57,
@ -89,7 +93,7 @@ enum ProcEventCode {
EvCrop = 63,
EvCACorr = 64,
EvHREnabled = 65,
obsolete_66 = 66, //obsolete
obsolete_66 = 66, // obsolete
EvHRMethod = 67,
EvWProfile = 68,
EvOProfile = 69,
@ -100,12 +104,12 @@ enum ProcEventCode {
EvResizeMethod = 74,
EvExif = 75,
EvIPTC = 76,
EvResizeSpec = 77,
obsolete_77 = 77, // obsolete
EvResizeWidth = 78,
EvResizeHeight = 79,
EvResizeEnabled = 80,
EvProfileChangeNotification = 81,
EvSHHighQuality = 82,
obsolete_82 = 82, // obsolete
EvPerspCorr = 83,
EvLCPFile = 84,
EvRGBrCurveLumamode = 85,
@ -133,7 +137,7 @@ enum ProcEventCode {
EvHLComprThreshold = 107,
EvResizeBoundingBox = 108,
EvResizeAppliesTo = 109,
EvLAvoidColorShift = 110,
//EvLAvoidColorShift = 110,
obsolete_111 = 111, // obsolete
EvLRSTProtection = 112,
EvDemosaicDCBIter = 113,
@ -153,12 +157,12 @@ enum ProcEventCode {
EvFlatFieldBlurRadius = 127,
EvFlatFieldBlurType = 128,
EvAutoDIST = 129,
EvDPDNLumCurve = 130,
EvDPDNChromCurve = 131,
EvGAMMA = 132,
EvGAMPOS = 133,
EvGAMFREE = 134,
EvSLPOS = 135,
obsolete_130 = 130, // obsolete
obsolete_131 = 131, // obsolete
obsolete_132 = 132, // obsolete
obsolete_133 = 133, // obsolete
obsolete_134 = 134, // obsolete
obsolete_135 = 135, // obsolete
EvPreProcessExpBlackzero = 136,
EvPreProcessExpBlackone = 137,
EvPreProcessExpBlacktwo = 138,
@ -231,7 +235,7 @@ enum ProcEventCode {
EvCATAutoAdap = 205,
EvPFCurve = 206,
EvWBequal = 207,
EvWBequalbo = 208,
obsolete_208 = 208,
EvGradientDegree = 209,
EvGradientEnabled = 210,
EvPCVignetteStrength = 211,
@ -272,7 +276,7 @@ enum ProcEventCode {
EvLLHCurve = 246,
EvLHHCurve = 247,
EvDirPyrEqualizerThreshold = 248,
EvDPDNenhance = 249,
obsolete_249 = 249,
EvBWMethodalg = 250,
EvDirPyrEqualizerSkin = 251,
EvDirPyrEqlgamutlab = 252,
@ -296,8 +300,8 @@ enum ProcEventCode {
EvColorToningbluehigh = 270,
EvColorToningbalance = 271,
EvColorToningNeutral = 272,
EvColorToningsatlow = 273,
EvColorToningsathigh = 274,
obsolete_273 = 273,
obsolete_274 = 274,
EvColorToningTwocolor = 275,
EvColorToningNeutralcur = 276,
EvColorToningLumamode = 277,
@ -322,7 +326,7 @@ enum ProcEventCode {
EvDPDNsmet = 296,
EvPreProcessDeadPixel = 297,
EvDPDNCCCurve = 298,
EvDPDNautochroma = 299,
obsolete_299 = 299,
EvDPDNLmet = 300,
EvDPDNCmet = 301,
EvDPDNC2met = 302,
@ -431,7 +435,7 @@ enum ProcEventCode {
EvWavNPmet = 405,
EvretinexMethod = 406,
EvLneigh = 407,
EvLgain = 408,
obsolete_408 = 408,
EvLoffs = 409,
EvLstr = 410,
EvLscal = 411,
@ -495,7 +499,7 @@ enum ProcEventCode {
// EvPixelShiftMedian3 = 469,
EvPixelShiftMotionMethod = 470,
EvPixelShiftSmooth = 471,
EvPixelShiftLmmse = 472,
obsolete_472 = 472,
EvPixelShiftEqualBright = 473,
EvPixelShiftEqualBrightChannel = 474,
EvCATtempout = 475,
@ -613,7 +617,7 @@ enum ProcEventCode {
Evlocallabadjblur = 587,
Evlocallabbilateral = 588,
Evlocallabsensiden = 589,
Evlocallabavoid = 590,
// Evlocallabavoid = 590,
Evlocallabsharcontrast = 591,
EvLocenacontrast = 592,
Evlocallablcradius = 593,
@ -626,7 +630,7 @@ enum ProcEventCode {
Evlocallabstreng = 600,
Evlocallabsensisf = 601,
Evlocallabsharblur = 602,
EvLocenalabregion = 603,
obsolete_603 = 603,
EvlocallabshowmaskMethod = 604,
EvLocallabSpotSelectedWithMask = 605,
EvlocallabCCmaskshape = 606,
@ -870,7 +874,7 @@ enum ProcEventCode {
EvLocenalog = 844,
EvLocallabAuto = 845,
EvlocallabsourceGray = 846,
EvlocallabsourceGrayAuto = 847,
obsolete_847 = 847,
EvlocallabAutogray = 848,
EvlocallabblackEv = 849,
EvlocallabwhiteEv = 850,
@ -889,7 +893,7 @@ enum ProcEventCode {
Evlocallabsigmadc = 863,
Evlocallabdeltad = 864,
EvlocallabwavCurvecomp = 865,
Evlocallabfatres = 866,
//Evlocallabfatres = 866,
EvLocallabSpotbalanh = 867,
EvlocallabwavCurveden = 868,
EvlocallabHHmasklcshape = 869,
@ -918,7 +922,7 @@ enum ProcEventCode {
Evlocallabanglog = 892,
EvLocallabSpotcolorde = 893,
// EvlocallabshowmasksharMethod = 894,
Evlocallabshowreset = 895,
//Evlocallabshowreset = 895,
Evlocallabstrengthw = 896,
Evlocallabradiusw = 897,
Evlocallabdetailw = 898,
@ -998,7 +1002,7 @@ enum ProcEventCode {
EvLocallabchromaskL = 972,
EvlocallabLmaskshapeL = 973,
Evlocallablightl = 974,
EvlocallabLshapeL = 975,
//EvlocallabLshapeL = 975,
Evlocallabcontq = 976,
Evlocallabsursour = 977,
Evlocallablightq = 978,
@ -1063,7 +1067,7 @@ enum ProcEventCode {
Evlocallabnlgam = 1037,
Evlocallabdivgr = 1038,
EvLocallabSpotavoidrad = 1039,
EvLocallabSpotavoidmun = 1040,
//EvLocallabSpotavoidmun = 1040,
Evlocallabcontthres = 1041,
Evlocallabnorm = 1042,
Evlocallabreparw = 1043,
@ -1121,7 +1125,6 @@ enum ProcEventCode {
Evlocallabshjzcie = 1095,
Evlocallabshthjzcie = 1096,
Evlocallabradjzcie = 1097,
// EvlocallabHHshapejz = 1098,
EvlocallabCHshapejz = 1098,
Evlocallabjz100 = 1099,
Evlocallabpqremap = 1100,
@ -1136,14 +1139,6 @@ enum ProcEventCode {
Evlocallabshapecz = 1109,
Evlocallabshapeczjz = 1110,
Evlocallabforcejz = 1111,
//Evlocallablightlzcam = 1113,
//Evlocallablightqzcam = 1114,
//Evlocallabcontlzcam = 1115,
//Evlocallabcontqzcam = 1116,
//Evlocallabcontthreszcam = 1117,
//Evlocallabcolorflzcam = 1118,
//Evlocallabsaturzcam = 1119,
//Evlocallabchromzcam = 1120,
Evlocallabpqremapcam16 = 1112,
EvLocallabEnacieMask = 1113,
EvlocallabCCmaskcieshape = 1114,

View File

@ -608,7 +608,7 @@ LCurveParams::LCurveParams() :
brightness(0),
contrast(0),
chromaticity(0),
avoidcolorshift(false),
gamutmunselmethod("MUN"),
rstprotection(0),
lcredsk(true)
{
@ -630,7 +630,7 @@ bool LCurveParams::operator ==(const LCurveParams& other) const
&& brightness == other.brightness
&& contrast == other.contrast
&& chromaticity == other.chromaticity
&& avoidcolorshift == other.avoidcolorshift
&& gamutmunselmethod == other.gamutmunselmethod
&& rstprotection == other.rstprotection
&& lcredsk == other.lcredsk;
}
@ -1461,8 +1461,7 @@ ColorAppearanceParams::ColorAppearanceParams() :
ybout(18),
greenout(1.0),
tempsc(5003),
greensc(1.0),
presetcat02(false)
greensc(1.0)
{
}
@ -1512,8 +1511,7 @@ bool ColorAppearanceParams::operator ==(const ColorAppearanceParams& other) cons
&& ybout == other.ybout
&& greenout == other.greenout
&& tempsc == other.tempsc
&& greensc == other.greensc
&& presetcat02 == other.presetcat02;
&& greensc == other.greensc;
}
bool ColorAppearanceParams::operator !=(const ColorAppearanceParams& other) const
@ -2302,6 +2300,7 @@ ColorManagementParams::ColorManagementParams() :
bluy(0.0001),
preser(0.),
fbw(false),
gamut(false),
labgridcieALow(0.51763),//Prophoto red = (0.7347+0.1) * 1.81818 - 1
labgridcieBLow(-0.33582),
labgridcieAHigh(-0.75163),//Prophoto blue
@ -2348,6 +2347,7 @@ bool ColorManagementParams::operator ==(const ColorManagementParams& other) cons
&& labgridcieWy == other.labgridcieWy
&& preser == other.preser
&& fbw == other.fbw
&& gamut == other.gamut
&& aRendIntent == other.aRendIntent
&& outputProfile == other.outputProfile
&& outputIntent == other.outputIntent
@ -2444,41 +2444,41 @@ WaveletParams::WaveletParams() :
0.35,
0.35
},
opacityCurveSH{
static_cast<double>(FCT_MinMaxCPoints),
0.,
1.,
0.35,
0.35,
0.15,
0.9,
0.35,
0.35,
0.4,
0.8,
0.35,
0.35,
0.4,
0.5,
0.35,
0.35,
0.5,
0.5,
0.35,
0.35,
0.5,
0.2,
0.35,
0.35,
0.8,
0.1,
0.35,
0.35,
1.0,
0.,
0.35,
0.35
},
//opacityCurveSH{
// static_cast<double>(FCT_MinMaxCPoints),
// 0.,
// 1.,
// 0.35,
// 0.35,
// 0.15,
// 0.9,
// 0.35,
// 0.35,
// 0.4,
// 0.8,
// 0.35,
// 0.35,
// 0.4,
// 0.5,
// 0.35,
// 0.35,
// 0.5,
// 0.5,
// 0.35,
// 0.35,
// 0.5,
// 0.2,
// 0.35,
// 0.35,
// 0.8,
// 0.1,
// 0.35,
// 0.35,
// 1.0,
// 0.,
// 0.35,
// 0.35
//},
/*
opacityCurveSH{
static_cast<double>(FCT_MinMaxCPoints),
@ -2616,7 +2616,7 @@ WaveletParams::WaveletParams() :
Backmethod("grey"),
Tilesmethod("full"),
complexmethod("normal"),
denmethod("12low"),
//denmethod("12low"),
mixmethod("mix"),
slimethod("sli"),
quamethod("cons"),
@ -2690,7 +2690,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& wavdenoiseh == other.wavdenoiseh
&& blcurve == other.blcurve
&& opacityCurveRG == other.opacityCurveRG
&& opacityCurveSH == other.opacityCurveSH
//&& opacityCurveSH == other.opacityCurveSH
&& opacityCurveBY == other.opacityCurveBY
&& opacityCurveW == other.opacityCurveW
&& opacityCurveWL == other.opacityCurveWL
@ -2766,7 +2766,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const
&& Backmethod == other.Backmethod
&& Tilesmethod == other.Tilesmethod
&& complexmethod == other.complexmethod
&& denmethod == other.denmethod
//&& denmethod == other.denmethod
&& mixmethod == other.mixmethod
&& slimethod == other.slimethod
&& quamethod == other.quamethod
@ -2853,7 +2853,7 @@ void WaveletParams::getCurves(
wavdenoiseh.Set(this->wavdenoiseh);
tCurve.Set(this->blcurve);
opacityCurveLUTRG.Set(this->opacityCurveRG);
opacityCurveLUTSH.Set(this->opacityCurveSH);
//opacityCurveLUTSH.Set(this->opacityCurveSH);
opacityCurveLUTBY.Set(this->opacityCurveBY);
opacityCurveLUTW.Set(this->opacityCurveW);
opacityCurveLUTWL.Set(this->opacityCurveWL);
@ -2872,6 +2872,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
structexclu(0),
struc(4.0),
shapeMethod("IND"),
avoidgamutMethod("MUNS"),
loc{150, 150, 150, 150},
centerX(0),
centerY(0),
@ -2886,13 +2887,11 @@ LocallabParams::LocallabSpot::LocallabSpot() :
balanh(1.0),
colorde(5.0),
colorscope(30.0),
avoidrad(0.7),
avoidrad(0.),
transitweak(1.0),
transitgrad(0.0),
hishow(false),
activ(true),
avoid(false),
avoidmun(false),
blwh(false),
recurs(false),
laplac(true),
@ -4585,6 +4584,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& structexclu == other.structexclu
&& struc == other.struc
&& shapeMethod == other.shapeMethod
&& avoidgamutMethod == other.avoidgamutMethod
&& loc == other.loc
&& centerX == other.centerX
&& centerY == other.centerY
@ -4604,8 +4604,6 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& transitgrad == other.transitgrad
&& hishow == other.hishow
&& activ == other.activ
&& avoid == other.avoid
&& avoidmun == other.avoidmun
&& blwh == other.blwh
&& recurs == other.recurs
&& laplac == other.laplac
@ -5659,6 +5657,7 @@ bool RAWParams::PreprocessWB::operator !=(const PreprocessWB& other) const
RAWParams::RAWParams() :
df_autoselect(false),
ff_AutoSelect(false),
ff_FromMetaData(false),
ff_BlurRadius(32),
ff_BlurType(getFlatFieldBlurTypeString(FlatFieldBlurType::AREA)),
ff_AutoClipControl(false),
@ -5684,6 +5683,7 @@ bool RAWParams::operator ==(const RAWParams& other) const
&& df_autoselect == other.df_autoselect
&& ff_file == other.ff_file
&& ff_AutoSelect == other.ff_AutoSelect
&& ff_FromMetaData == other.ff_FromMetaData
&& ff_BlurRadius == other.ff_BlurRadius
&& ff_BlurType == other.ff_BlurType
&& ff_AutoClipControl == other.ff_AutoClipControl
@ -6071,7 +6071,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->labCurve.brightness, "Luminance Curve", "Brightness", labCurve.brightness, keyFile);
saveToKeyfile(!pedited || pedited->labCurve.contrast, "Luminance Curve", "Contrast", labCurve.contrast, keyFile);
saveToKeyfile(!pedited || pedited->labCurve.chromaticity, "Luminance Curve", "Chromaticity", labCurve.chromaticity, keyFile);
saveToKeyfile(!pedited || pedited->labCurve.avoidcolorshift, "Luminance Curve", "AvoidColorShift", labCurve.avoidcolorshift, keyFile);
saveToKeyfile(!pedited || pedited->labCurve.gamutmunselmethod, "Luminance Curve", "Gamutmunse", labCurve.gamutmunselmethod, keyFile);
saveToKeyfile(!pedited || pedited->labCurve.rstprotection, "Luminance Curve", "RedAndSkinTonesProtection", labCurve.rstprotection, keyFile);
saveToKeyfile(!pedited || pedited->labCurve.lcredsk, "Luminance Curve", "LCredsk", labCurve.lcredsk, keyFile);
saveToKeyfile(!pedited || pedited->labCurve.lcurve, "Luminance Curve", "LCurve", labCurve.lcurve, keyFile);
@ -6172,7 +6172,6 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->colorappearance.ybout, "Color appearance", "Ybout", colorappearance.ybout, keyFile);
saveToKeyfile(!pedited || pedited->colorappearance.datacie, "Color appearance", "Datacie", colorappearance.datacie, keyFile);
saveToKeyfile(!pedited || pedited->colorappearance.tonecie, "Color appearance", "Tonecie", colorappearance.tonecie, keyFile);
saveToKeyfile(!pedited || pedited->colorappearance.presetcat02, "Color appearance", "Presetcat02", colorappearance.presetcat02, keyFile);
const std::map<ColorAppearanceParams::TcMode, const char*> ca_mapping = {
{ColorAppearanceParams::TcMode::LIGHT, "Lightness"},
@ -6382,6 +6381,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->structexclu, "Locallab", "StructExclu_" + index_str, spot.structexclu, keyFile);
saveToKeyfile(!pedited || spot_edited->struc, "Locallab", "Struc_" + index_str, spot.struc, keyFile);
saveToKeyfile(!pedited || spot_edited->shapeMethod, "Locallab", "ShapeMethod_" + index_str, spot.shapeMethod, keyFile);
saveToKeyfile(!pedited || spot_edited->avoidgamutMethod, "Locallab", "AvoidgamutMethod_" + index_str, spot.avoidgamutMethod, keyFile);
saveToKeyfile(!pedited || spot_edited->loc, "Locallab", "Loc_" + index_str, spot.loc, keyFile);
saveToKeyfile(!pedited || spot_edited->centerX, "Locallab", "CenterX_" + index_str, spot.centerX, keyFile);
saveToKeyfile(!pedited || spot_edited->centerY, "Locallab", "CenterY_" + index_str, spot.centerY, keyFile);
@ -6401,8 +6401,6 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->transitgrad, "Locallab", "Transitgrad_" + index_str, spot.transitgrad, keyFile);
saveToKeyfile(!pedited || spot_edited->hishow, "Locallab", "Hishow_" + index_str, spot.hishow, keyFile);
saveToKeyfile(!pedited || spot_edited->activ, "Locallab", "Activ_" + index_str, spot.activ, keyFile);
saveToKeyfile(!pedited || spot_edited->avoid, "Locallab", "Avoid_" + index_str, spot.avoid, keyFile);
saveToKeyfile(!pedited || spot_edited->avoidmun, "Locallab", "Avoidmun_" + index_str, spot.avoidmun, keyFile);
saveToKeyfile(!pedited || spot_edited->blwh, "Locallab", "Blwh_" + index_str, spot.blwh, keyFile);
saveToKeyfile(!pedited || spot_edited->recurs, "Locallab", "Recurs_" + index_str, spot.recurs, keyFile);
saveToKeyfile(!pedited || spot_edited->laplac, "Locallab", "Laplac_" + index_str, spot.laplac, keyFile);
@ -7228,6 +7226,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->icm.labgridcieWy, "Color Management", "LabGridcieWy", icm.labgridcieWy, keyFile);
saveToKeyfile(!pedited || pedited->icm.preser, "Color Management", "Preser", icm.preser, keyFile);
saveToKeyfile(!pedited || pedited->icm.fbw, "Color Management", "Fbw", icm.fbw, keyFile);
saveToKeyfile(!pedited || pedited->icm.gamut, "Color Management", "Gamut", icm.gamut, keyFile);
saveToKeyfile(!pedited || pedited->icm.outputProfile, "Color Management", "OutputProfile", icm.outputProfile, keyFile);
saveToKeyfile(
!pedited || pedited->icm.aRendIntent,
@ -7272,7 +7271,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.thres, "Wavelet", "MaxLev", wavelet.thres, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.Tilesmethod, "Wavelet", "TilesMethod", wavelet.Tilesmethod, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.complexmethod, "Wavelet", "complexMethod", wavelet.complexmethod, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.denmethod, "Wavelet", "denMethod", wavelet.denmethod, keyFile);
//saveToKeyfile(!pedited || pedited->wavelet.denmethod, "Wavelet", "denMethod", wavelet.denmethod, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.mixmethod, "Wavelet", "mixMethod", wavelet.mixmethod, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.slimethod, "Wavelet", "sliMethod", wavelet.slimethod, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.quamethod, "Wavelet", "quaMethod", wavelet.quamethod, keyFile);
@ -7363,7 +7362,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wavelet.pastlev, "Wavelet", "Pastlev", wavelet.pastlev.toVector(), keyFile);
saveToKeyfile(!pedited || pedited->wavelet.satlev, "Wavelet", "Satlev", wavelet.satlev.toVector(), keyFile);
saveToKeyfile(!pedited || pedited->wavelet.opacityCurveRG, "Wavelet", "OpacityCurveRG", wavelet.opacityCurveRG, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.opacityCurveSH, "Wavelet", "Levalshc", wavelet.opacityCurveSH, keyFile);
//saveToKeyfile(!pedited || pedited->wavelet.opacityCurveSH, "Wavelet", "Levalshc", wavelet.opacityCurveSH, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.opacityCurveBY, "Wavelet", "OpacityCurveBY", wavelet.opacityCurveBY, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.wavdenoise, "Wavelet", "wavdenoise", wavelet.wavdenoise, keyFile);
saveToKeyfile(!pedited || pedited->wavelet.wavdenoiseh, "Wavelet", "wavdenoiseh", wavelet.wavdenoiseh, keyFile);
@ -7521,6 +7520,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->raw.df_autoselect, "RAW", "DarkFrameAuto", raw.df_autoselect, keyFile);
saveToKeyfile(!pedited || pedited->raw.ff_file, "RAW", "FlatFieldFile", relativePathIfInside(fname, fnameAbsolute, raw.ff_file), keyFile);
saveToKeyfile(!pedited || pedited->raw.ff_AutoSelect, "RAW", "FlatFieldAutoSelect", raw.ff_AutoSelect, keyFile);
saveToKeyfile(!pedited || pedited->raw.ff_FromMetaData, "RAW", "FlatFieldFromMetaData", raw.ff_FromMetaData, keyFile);
saveToKeyfile(!pedited || pedited->raw.ff_BlurRadius, "RAW", "FlatFieldBlurRadius", raw.ff_BlurRadius, keyFile);
saveToKeyfile(!pedited || pedited->raw.ff_BlurType, "RAW", "FlatFieldBlurType", raw.ff_BlurType, keyFile);
saveToKeyfile(!pedited || pedited->raw.ff_AutoClipControl, "RAW", "FlatFieldAutoClipControl", raw.ff_AutoClipControl, keyFile);
@ -7905,7 +7905,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
// if Saturation == 0, should we set BWToning on?
assignFromKeyfile(keyFile, "Luminance Curve", "Saturation", pedited, labCurve.chromaticity, pedited->labCurve.chromaticity);
// transform AvoidColorClipping into AvoidColorShift
assignFromKeyfile(keyFile, "Luminance Curve", "AvoidColorClipping", pedited, labCurve.avoidcolorshift, pedited->labCurve.avoidcolorshift);
// assignFromKeyfile(keyFile, "Luminance Curve", "AvoidColorClipping", pedited, labCurve.avoidcolorshift, pedited->labCurve.avoidcolorshift);
} else {
if (keyFile.has_key("Luminance Curve", "Chromaticity")) {
labCurve.chromaticity = keyFile.get_integer("Luminance Curve", "Chromaticity");
@ -7919,7 +7919,6 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
}
}
assignFromKeyfile(keyFile, "Luminance Curve", "AvoidColorShift", pedited, labCurve.avoidcolorshift, pedited->labCurve.avoidcolorshift);
assignFromKeyfile(keyFile, "Luminance Curve", "RedAndSkinTonesProtection", pedited, labCurve.rstprotection, pedited->labCurve.rstprotection);
}
@ -7948,6 +7947,25 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Luminance Curve", "hhCurve", pedited, labCurve.hhcurve, pedited->labCurve.hhcurve);
assignFromKeyfile(keyFile, "Luminance Curve", "LcCurve", pedited, labCurve.lccurve, pedited->labCurve.lccurve);
assignFromKeyfile(keyFile, "Luminance Curve", "ClCurve", pedited, labCurve.clcurve, pedited->labCurve.clcurve);
if (keyFile.has_key("Luminance Curve", "Gamutmunse")) {
assignFromKeyfile(keyFile, "Luminance Curve", "Gamutmunse", pedited, labCurve.gamutmunselmethod, pedited->labCurve.gamutmunselmethod);
} else {
if (ppVersion < 303) {
if (keyFile.has_key("Luminance Curve", "AvoidColorClipping")) {
labCurve.gamutmunselmethod =
keyFile.get_boolean("Luminance Curve", "AvoidColorClipping") ? "LAB" : "NONE";
if (pedited) {
pedited->labCurve.gamutmunselmethod = true;
}
}
} else if (keyFile.has_key("Luminance Curve", "AvoidColorShift")) {
labCurve.gamutmunselmethod =
keyFile.get_boolean("Luminance Curve", "AvoidColorShift") ? "LAB" : "NONE";
if (pedited) {
pedited->labCurve.gamutmunselmethod = true;
}
}
}
}
if (keyFile.has_group("Sharpening")) {
@ -8141,7 +8159,6 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Color appearance", "Ybout", pedited, colorappearance.ybout, pedited->colorappearance.ybout);
assignFromKeyfile(keyFile, "Color appearance", "Datacie", pedited, colorappearance.datacie, pedited->colorappearance.datacie);
assignFromKeyfile(keyFile, "Color appearance", "Tonecie", pedited, colorappearance.tonecie, pedited->colorappearance.tonecie);
assignFromKeyfile(keyFile, "Color appearance", "Presetcat02", pedited, colorappearance.presetcat02, pedited->colorappearance.presetcat02);
const std::map<std::string, ColorAppearanceParams::TcMode> tc_mapping = {
{"Lightness", ColorAppearanceParams::TcMode::LIGHT},
@ -8467,6 +8484,16 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "StructExclu_" + index_str, pedited, spot.structexclu, spotEdited.structexclu);
assignFromKeyfile(keyFile, "Locallab", "Struc_" + index_str, pedited, spot.struc, spotEdited.struc);
assignFromKeyfile(keyFile, "Locallab", "ShapeMethod_" + index_str, pedited, spot.shapeMethod, spotEdited.shapeMethod);
if (keyFile.has_key("Locallab", "AvoidgamutMethod_" + index_str)) {
assignFromKeyfile(keyFile, "Locallab", "AvoidgamutMethod_" + index_str, pedited, spot.avoidgamutMethod, spotEdited.avoidgamutMethod);
} else if (keyFile.has_key("Locallab", "Avoid_" + index_str)) {
const bool avoid = keyFile.get_boolean("Locallab", "Avoid_" + index_str);
const bool munsell = keyFile.has_key("Locallab", "Avoidmun_" + index_str) && keyFile.get_boolean("Locallab", "Avoidmun_" + index_str);
spot.avoidgamutMethod = avoid ? (munsell ? "MUNS" : "LAB") : "NONE";
if (pedited) {
spotEdited.avoidgamutMethod = true;
}
}
assignFromKeyfile(keyFile, "Locallab", "Loc_" + index_str, pedited, spot.loc, spotEdited.loc);
assignFromKeyfile(keyFile, "Locallab", "CenterX_" + index_str, pedited, spot.centerX, spotEdited.centerX);
assignFromKeyfile(keyFile, "Locallab", "CenterY_" + index_str, pedited, spot.centerY, spotEdited.centerY);
@ -8486,8 +8513,6 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "Transitgrad_" + index_str, pedited, spot.transitgrad, spotEdited.transitgrad);
assignFromKeyfile(keyFile, "Locallab", "Hishow_" + index_str, pedited, spot.hishow, spotEdited.hishow);
assignFromKeyfile(keyFile, "Locallab", "Activ_" + index_str, pedited, spot.activ, spotEdited.activ);
assignFromKeyfile(keyFile, "Locallab", "Avoid_" + index_str, pedited, spot.avoid, spotEdited.avoid);
assignFromKeyfile(keyFile, "Locallab", "Avoidmun_" + index_str, pedited, spot.avoidmun, spotEdited.avoidmun);
assignFromKeyfile(keyFile, "Locallab", "Blwh_" + index_str, pedited, spot.blwh, spotEdited.blwh);
assignFromKeyfile(keyFile, "Locallab", "Recurs_" + index_str, pedited, spot.recurs, spotEdited.recurs);
assignFromKeyfile(keyFile, "Locallab", "Laplac_" + index_str, pedited, spot.laplac, spotEdited.laplac);
@ -9503,6 +9528,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Color Management", "Bluy", pedited, icm.bluy, pedited->icm.bluy);
assignFromKeyfile(keyFile, "Color Management", "Preser", pedited, icm.preser, pedited->icm.preser);
assignFromKeyfile(keyFile, "Color Management", "Fbw", pedited, icm.fbw, pedited->icm.fbw);
assignFromKeyfile(keyFile, "Color Management", "Gamut", pedited, icm.gamut, pedited->icm.gamut);
assignFromKeyfile(keyFile, "Color Management", "LabGridcieALow", pedited, icm.labgridcieALow, pedited->icm.labgridcieALow);
assignFromKeyfile(keyFile, "Color Management", "LabGridcieBLow", pedited, icm.labgridcieBLow, pedited->icm.labgridcieBLow);
assignFromKeyfile(keyFile, "Color Management", "LabGridcieAHigh", pedited, icm.labgridcieAHigh, pedited->icm.labgridcieAHigh);
@ -9642,7 +9668,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
}
}
assignFromKeyfile(keyFile, "Wavelet", "denMethod", pedited, wavelet.denmethod, pedited->wavelet.denmethod);
//assignFromKeyfile(keyFile, "Wavelet", "denMethod", pedited, wavelet.denmethod, pedited->wavelet.denmethod);
assignFromKeyfile(keyFile, "Wavelet", "mixMethod", pedited, wavelet.mixmethod, pedited->wavelet.mixmethod);
assignFromKeyfile(keyFile, "Wavelet", "sliMethod", pedited, wavelet.slimethod, pedited->wavelet.slimethod);
assignFromKeyfile(keyFile, "Wavelet", "quaMethod", pedited, wavelet.quamethod, pedited->wavelet.quamethod);
@ -9692,7 +9718,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Wavelet", "ContrastCurve", pedited, wavelet.ccwcurve, pedited->wavelet.ccwcurve);
assignFromKeyfile(keyFile, "Wavelet", "blcurve", pedited, wavelet.blcurve, pedited->wavelet.blcurve);
assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveRG", pedited, wavelet.opacityCurveRG, pedited->wavelet.opacityCurveRG);
assignFromKeyfile(keyFile, "Wavelet", "Levalshc", pedited, wavelet.opacityCurveSH, pedited->wavelet.opacityCurveSH);
//assignFromKeyfile(keyFile, "Wavelet", "Levalshc", pedited, wavelet.opacityCurveSH, pedited->wavelet.opacityCurveSH);
assignFromKeyfile(keyFile, "Wavelet", "OpacityCurveBY", pedited, wavelet.opacityCurveBY, pedited->wavelet.opacityCurveBY);
assignFromKeyfile(keyFile, "Wavelet", "wavdenoise", pedited, wavelet.wavdenoise, pedited->wavelet.wavdenoise);
assignFromKeyfile(keyFile, "Wavelet", "wavdenoiseh", pedited, wavelet.wavdenoiseh, pedited->wavelet.wavdenoiseh);
@ -10177,6 +10203,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
}
assignFromKeyfile(keyFile, "RAW", "FlatFieldAutoSelect", pedited, raw.ff_AutoSelect, pedited->raw.ff_AutoSelect);
assignFromKeyfile(keyFile, "RAW", "FlatFieldFromMetaData", pedited, raw.ff_FromMetaData, pedited->raw.ff_FromMetaData);
assignFromKeyfile(keyFile, "RAW", "FlatFieldBlurRadius", pedited, raw.ff_BlurRadius, pedited->raw.ff_BlurRadius);
assignFromKeyfile(keyFile, "RAW", "FlatFieldBlurType", pedited, raw.ff_BlurType, pedited->raw.ff_BlurType);
assignFromKeyfile(keyFile, "RAW", "FlatFieldAutoClipControl", pedited, raw.ff_AutoClipControl, pedited->raw.ff_AutoClipControl);

View File

@ -377,7 +377,7 @@ struct LCurveParams {
int brightness;
int contrast;
int chromaticity;
bool avoidcolorshift;
Glib::ustring gamutmunselmethod;
double rstprotection;
bool lcredsk;
@ -710,7 +710,6 @@ struct ColorAppearanceParams {
double greenout;
int tempsc;
double greensc;
bool presetcat02;
ColorAppearanceParams();
@ -1037,6 +1036,8 @@ struct LocallabParams {
int structexclu;
double struc;
Glib::ustring shapeMethod; // IND, SYM, INDSL, SYMSL
Glib::ustring avoidgamutMethod; // NONE, LAB, XYZ
std::vector<int> loc; // For ellipse/rectangle: {locX, locXL, locY, locYT}
int centerX;
int centerY;
@ -1056,8 +1057,6 @@ struct LocallabParams {
double transitgrad;
bool hishow;
bool activ;
bool avoid;
bool avoidmun;
bool blwh;
bool recurs;
bool laplac;
@ -1955,6 +1954,7 @@ struct ColorManagementParams {
double bluy;
double preser;
bool fbw;
bool gamut;
double labgridcieALow;
double labgridcieBLow;
double labgridcieAHigh;
@ -2088,7 +2088,7 @@ struct WaveletParams {
std::vector<double> blcurve;
std::vector<double> levelshc;
std::vector<double> opacityCurveRG;
std::vector<double> opacityCurveSH;
//std::vector<double> opacityCurveSH;
std::vector<double> opacityCurveBY;
std::vector<double> opacityCurveW;
std::vector<double> opacityCurveWL;
@ -2161,7 +2161,7 @@ struct WaveletParams {
Glib::ustring Backmethod;
Glib::ustring Tilesmethod;
Glib::ustring complexmethod;
Glib::ustring denmethod;
//Glib::ustring denmethod;
Glib::ustring mixmethod;
Glib::ustring slimethod;
Glib::ustring quamethod;
@ -2458,6 +2458,7 @@ struct RAWParams {
Glib::ustring ff_file;
bool ff_AutoSelect;
bool ff_FromMetaData;
int ff_BlurRadius;
Glib::ustring ff_BlurType;
bool ff_AutoClipControl;

View File

@ -508,7 +508,7 @@ void ProfileStore::dumpFolderList()
printf ("\n");
}
PartialProfile *ProfileStore::loadDynamicProfile (const FramesMetaData *im)
PartialProfile *ProfileStore::loadDynamicProfile (const FramesMetaData *im, const Glib::ustring& filename)
{
if (storeState == STORESTATE_NOTINITIALIZED) {
parseProfilesOnce();
@ -521,7 +521,7 @@ PartialProfile *ProfileStore::loadDynamicProfile (const FramesMetaData *im)
}
for (auto rule : dynamicRules) {
if (rule.matches (im)) {
if (rule.matches (im, filename)) {
if (settings->verbose) {
printf ("found matching profile %s\n", rule.profilepath.c_str());
}

View File

@ -209,7 +209,7 @@ public:
void addListener (ProfileStoreListener *listener);
void removeListener (ProfileStoreListener *listener);
rtengine::procparams::PartialProfile* loadDynamicProfile (const rtengine::FramesMetaData *im);
rtengine::procparams::PartialProfile* loadDynamicProfile (const rtengine::FramesMetaData *im, const Glib::ustring& filename);
void dumpFolderList();
};

View File

@ -548,11 +548,18 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
CameraConstantsStore* ccs = CameraConstantsStore::getInstance();
const CameraConst *cc = ccs->get(make, model);
bool raw_crop_cc = false;
int orig_raw_width = width;
int orig_raw_height = height;
if (raw_image) {
if (cc && cc->has_rawCrop()) {
orig_raw_width = raw_width;
orig_raw_height = raw_height;
if (cc && cc->has_rawCrop(raw_width, raw_height)) {
raw_crop_cc = true;
int lm, tm, w, h;
cc->get_rawCrop(lm, tm, w, h);
cc->get_rawCrop(raw_width, raw_height, lm, tm, w, h);
if (isXtrans()) {
shiftXtransMatrix(6 - ((top_margin - tm) % 6), 6 - ((left_margin - lm) % 6));
@ -584,9 +591,9 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
}
}
if (cc && cc->has_rawMask(0)) {
for (int i = 0; i < 8 && cc->has_rawMask(i); i++) {
cc->get_rawMask(i, mask[i][0], mask[i][1], mask[i][2], mask[i][3]);
if (cc && cc->has_rawMask(orig_raw_width, orig_raw_height, 0)) {
for (int i = 0; i < 2 && cc->has_rawMask(orig_raw_width, orig_raw_height, i); i++) {
cc->get_rawMask(orig_raw_width, orig_raw_height, i, mask[i][0], mask[i][1], mask[i][2], mask[i][3]);
}
}
@ -594,9 +601,10 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
free(raw_image);
raw_image = nullptr;
} else {
if (get_maker() == "Sigma" && cc && cc->has_rawCrop()) { // foveon images
if (get_maker() == "Sigma" && cc && cc->has_rawCrop(width, height)) { // foveon images
raw_crop_cc = true;
int lm, tm, w, h;
cc->get_rawCrop(lm, tm, w, h);
cc->get_rawCrop(width, height, lm, tm, w, h);
left_margin = lm;
top_margin = tm;
@ -692,11 +700,12 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
printf("no constants in camconst.json exists for \"%s %s\" (relying only on dcraw defaults)\n", make, model);
}
printf("raw dimensions: %d x %d\n", orig_raw_width, orig_raw_height);
printf("black levels: R:%d G1:%d B:%d G2:%d (%s)\n", get_cblack(0), get_cblack(1), get_cblack(2), get_cblack(3),
black_from_cc ? "provided by camconst.json" : "provided by dcraw");
printf("white levels: R:%d G1:%d B:%d G2:%d (%s)\n", get_white(0), get_white(1), get_white(2), get_white(3),
white_from_cc ? "provided by camconst.json" : "provided by dcraw");
printf("raw crop: %d %d %d %d (provided by %s)\n", left_margin, top_margin, iwidth, iheight, (cc && cc->has_rawCrop()) ? "camconst.json" : "dcraw");
printf("raw crop: %d %d %d %d (provided by %s)\n", left_margin, top_margin, iwidth, iheight, raw_crop_cc ? "camconst.json" : "dcraw");
printf("color matrix provided by %s\n", (cc && cc->has_dcrawMatrix()) ? "camconst.json" : "dcraw");
}
}

View File

@ -245,11 +245,6 @@ public:
return zero_is_bad == 1;
}
bool isBayer() const
{
return (filters != 0 && filters != 9);
}
bool isXtrans() const
{
return filters == 9;

View File

@ -34,13 +34,16 @@
#include "median.h"
#include "mytime.h"
#include "pdaflinesfilter.h"
#include "pixelsmap.h"
#include "procparams.h"
#include "rawimage.h"
#include "rawimagesource_i.h"
#include "rawimagesource.h"
#include "rescale.h"
#include "rt_math.h"
#include "rtengine.h"
#include "rtlensfun.h"
#include "../rtgui/options.h"
#define BENCHMARK
@ -1307,14 +1310,14 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
Glib::ustring newDF = raw.dark_frame;
RawImage *rid = nullptr;
const RawImage* rid = nullptr;
if (!raw.df_autoselect) {
if (!raw.dark_frame.empty()) {
rid = dfm.searchDarkFrame(raw.dark_frame);
rid = DFManager::getInstance().searchDarkFrame(raw.dark_frame);
}
} else {
rid = dfm.searchDarkFrame(idata->getMake(), idata->getModel(), idata->getISOSpeed(), idata->getShutterSpeed(), idata->getDateTimeAsTS());
rid = DFManager::getInstance().searchDarkFrame(idata->getMake(), idata->getModel(), idata->getISOSpeed(), idata->getShutterSpeed(), idata->getDateTimeAsTS());
}
if (rid && settings->verbose) {
@ -1345,7 +1348,6 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
rif = ffm.searchFlatField(idata->getMake(), idata->getModel(), idata->getLens(), idata->getFocalLen(), idata->getFNumber(), idata->getDateTimeAsTS());
}
bool hasFlatField = (rif != nullptr);
if (hasFlatField && settings->verbose) {
@ -1385,9 +1387,12 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
}
//FLATFIELD end
if (raw.ff_FromMetaData && isGainMapSupported()) {
applyDngGainMap(c_black, ri->getGainMaps());
}
// Always correct camera badpixels from .badpixels file
std::vector<badPix> *bp = dfm.getBadPixels(ri->get_maker(), ri->get_model(), idata->getSerialNumber());
const std::vector<badPix> *bp = DFManager::getInstance().getBadPixels(ri->get_maker(), ri->get_model(), idata->getSerialNumber());
if (bp) {
if (!bitmapBads) {
@ -1405,9 +1410,9 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
bp = nullptr;
if (raw.df_autoselect) {
bp = dfm.getHotPixels(idata->getMake(), idata->getModel(), idata->getISOSpeed(), idata->getShutterSpeed(), idata->getDateTimeAsTS());
bp = DFManager::getInstance().getHotPixels(idata->getMake(), idata->getModel(), idata->getISOSpeed(), idata->getShutterSpeed(), idata->getDateTimeAsTS());
} else if (!raw.dark_frame.empty()) {
bp = dfm.getHotPixels(raw.dark_frame);
bp = DFManager::getInstance().getHotPixels(raw.dark_frame);
}
if (bp) {
@ -2453,7 +2458,7 @@ void RawImageSource::HLRecovery_Global(const ToneCurveParams &hrp)
/* 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<float> &rawData)
void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, const RawImage *riDark, RawImage *riFlatFile, array2D<float> &rawData)
{
const auto tmpfilters = ri->get_filters();
ri->set_filters(ri->prefilters); // we need 4 blacks for bayer processing
@ -6257,6 +6262,36 @@ void RawImageSource::getRawValues(int x, int y, int rotate, int &R, int &G, int
}
}
bool RawImageSource::isGainMapSupported() const {
return ri->isGainMapSupported();
}
void RawImageSource::applyDngGainMap(const float black[4], const std::vector<GainMap> &gainMaps) {
// now we can apply each gain map to raw_data
array2D<float> mvals[2][2];
for (auto &m : gainMaps) {
mvals[m.Top & 1][m.Left & 1](m.MapPointsH, m.MapPointsV, m.MapGain.data());
}
// now we assume, col_scale and row scale is the same for all maps
const float col_scale = float(gainMaps[0].MapPointsH-1) / float(W);
const float row_scale = float(gainMaps[0].MapPointsV-1) / float(H);
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic, 16)
#endif
for (std::size_t y = 0; y < static_cast<size_t>(H); ++y) {
const float rowBlack[2] = {black[FC(y,0)], black[FC(y,1)]};
const float ys = y * row_scale;
float xs = 0.f;
for (std::size_t x = 0; x < static_cast<std::size_t>(W); ++x, xs += col_scale) {
const float f = getBilinearValue(mvals[y & 1][x & 1], xs, ys);
const float b = rowBlack[x & 1];
rawData[y][x] = rtengine::max((rawData[y][x] - b) * f + b, 0.f);
}
}
}
void RawImageSource::cleanup ()
{
delete phaseOneIccCurve;

View File

@ -24,6 +24,7 @@
#include "array2D.h"
#include "colortemp.h"
#include "dnggainmap.h"
#include "iimage.h"
#include "imagesource.h"
#include "procparams.h"
@ -138,7 +139,7 @@ public:
}
void processFlatField(const procparams::RAWParams &raw, const RawImage *riFlatFile, array2D<float> &rawData, const float black[4]);
void copyOriginalPixels(const procparams::RAWParams &raw, RawImage *ri, RawImage *riDark, RawImage *riFlatFile, array2D<float> &rawData );
void copyOriginalPixels(const procparams::RAWParams &raw, RawImage *ri, const RawImage *riDark, RawImage *riFlatFile, array2D<float> &rawData );
void scaleColors (int winx, int winy, int winw, int winh, const procparams::RAWParams &raw, array2D<float> &rawData); // raw for cblack
void WBauto(double &tempref, double &greenref, array2D<float> &redloc, array2D<float> &greenloc, array2D<float> &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &studgood, bool &twotimes, const procparams::WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw) override;
void getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const procparams::WBParams & wbpar, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw) override;
@ -177,6 +178,8 @@ public:
return true;
}
bool isGainMapSupported() const override;
void setProgressListener (ProgressListener* pl) override
{
plistener = pl;
@ -304,6 +307,7 @@ protected:
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;
void applyDngGainMap(const float black[4], const std::vector<GainMap> &gainMaps);
};
}

View File

@ -28,7 +28,7 @@
// Aligned so the first entry starts on line 30.
int refreshmap[rtengine::NUMOFEVENTS] = {
ALL, // EvPhotoLoaded,
ALL, // EvProfileLoaded,
0, // EvProfileLoaded : obsolete,
ALL, // EvProfileChanged,
ALL, // EvHistoryBrowsed,
AUTOEXP, // EvBrightness,
@ -42,9 +42,9 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
AUTOEXP, // EvClip,
LUMINANCECURVE, // EvLBrightness,
LUMINANCECURVE, // EvLContrast,
LUMINANCECURVE, // EvLBlack,
LUMINANCECURVE, // EvLHLCompr,
LUMINANCECURVE, // EvLSHCompr,
0, // EvLBlack : obsolete,
0, // EvLHLCompr : obsolete,
0, // EvLSHCompr : obsolete,
LUMINANCECURVE, // EvLLCurve,
SHARPENING, // EvShrEnabled,
SHARPENING, // EvShrRadius,
@ -81,7 +81,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
LUMINANCECURVE, // EvSHShadows,
LUMINANCECURVE, // EvSHHLTonalW,
LUMINANCECURVE, // EvSHSHTonalW,
AUTOEXP, // EvSHLContrast,
0, // EvSHLContrast : obsolete,
LUMINANCECURVE, // EvSHRadius,
ALLNORAW, // EvCTRotate,
ALLNORAW, // EvCTHFlip,
@ -93,7 +93,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
CROP, // EvCrop,
HDR, // EvCACorr,
ALLNORAW, // EvHREnabled,
ALLNORAW, // EvHRAmount,
0, // EvHRAmount : obsolete,
ALLNORAW, // EvHRMethod,
DEMOSAIC, // EvWProfile,
OUTPUTPROFILE, // EvOProfile,
@ -104,12 +104,12 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
RESIZE, // EvResizeMethod,
EXIF, // EvExif,
IPTC, // EvIPTC
RESIZE, // EvResizeSpec,
0, // EvResizeSpec : obsolete,
RESIZE, // EvResizeWidth
RESIZE, // EvResizeHeight
RESIZE, // EvResizeEnabled
ALL, // EvProfileChangeNotification
RETINEX, // EvShrHighQuality
0, // EvSHHighQuality : obsolete
HDR, // EvPerspCorr
DARKFRAME, // EvLCPFile
AUTOEXP, // EvRGBrCurveLumamode
@ -157,12 +157,12 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
FLATFIELD, // EvFlatFieldBlurRadius,
FLATFIELD, // EvFlatFieldBlurType,
HDR, // EvAutoDIST,
ALLNORAW, // EvDPDNLumCurve,
ALLNORAW, // EvDPDNChromCurve,
GAMMA, // EvGAMMA
GAMMA, // EvGAMPOS
GAMMA, // EvGAMFREE
GAMMA, // EvSLPOS
0, // EvDPDNLumCurve : obsolete
0, // EvDPDNChromCurve : obsolete
0, // EvGAMMA : obsolete
0, // EvGAMPOS : obsolete
0, // EvGAMFREE : obsolete
0, // EvSLPOS : obsolete
DARKFRAME, // EvPreProcessExpBlackzero
DARKFRAME, // EvPreProcessExpBlackone
DARKFRAME, // EvPreProcessExpBlacktwo
@ -200,7 +200,6 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
LUMINANCECURVE, // EvLLCCurve
LUMINANCECURVE, // EvLLCredsk
ALLNORAW, // EvDPDNLdetail
//ALLNORAW, // EvCATEnabled
LUMINANCECURVE, // EvCATEnabled
LUMINANCECURVE, // EvCATDegree
LUMINANCECURVE, // EvCATMethodsur
@ -236,7 +235,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
LUMINANCECURVE, // EvCATAutoadap
DEFRINGE, // EvPFCurve
ALLNORAW, // EvWBequal
ALLNORAW, // EvWBequalbo
0, // EvWBequalbo : obsolete
HDR, // EvGradientDegree
HDR, // EvGradientEnabled
HDR, // EvPCVignetteStrength
@ -277,7 +276,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
LUMINANCECURVE, // EvLLHCurve
LUMINANCECURVE, // EvLHHCurve
ALLNORAW, // EvDirPyrEqualizerThreshold
ALLNORAW, // EvDPDNenhance
0, // EvDPDNenhance : obsolete
AUTOEXP, // EvBWMethodalg
ALLNORAW, // EvDirPyrEqualizerSkin
ALLNORAW, // EvDirPyrEqlgamutlab
@ -301,8 +300,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
AUTOEXP, // EvColorToningbluehigh
AUTOEXP, // EvColorToningbalance
AUTOEXP, // EvColorToningNeutral
AUTOEXP, // EvColorToningsatlow
AUTOEXP, // EvColorToningsathigh
0, // EvColorToningsatlow : obsolete
0, // EvColorToningsathigh : obsolete
AUTOEXP, // EvColorToningTwocolor
AUTOEXP, // EvColorToningNeutralcur
AUTOEXP, // EvColorToningLumamode
@ -327,7 +326,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
ALLNORAW, // EvDPDNsmet
DARKFRAME, // EvPreProcessDeadPixel
ALLNORAW, // EvDPDNCCCurve
ALLNORAW, // EvDPDNautochroma
0, // EvDPDNautochroma : obsolete
ALLNORAW, // EvDPDNLmet
ALLNORAW, // EvDPDNCmet
ALLNORAW, // EvDPDNC2met
@ -436,7 +435,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
DIRPYREQUALIZER, // EvWavNPmet
DEMOSAIC, // EvretinexMethod
RETINEX, // EvLneigh
RETINEX, // EvLgain
0, // EvLgain : obsolete
RETINEX, // EvLoffs
RETINEX, // EvLstr
RETINEX, // EvLscal
@ -500,7 +499,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
0, // unused
DEMOSAIC, // EvPixelShiftMotionMethod
DEMOSAIC, // EvPixelShiftSmooth
DEMOSAIC, // EvPixelShiftLmmse
0, // EvPixelShiftLmmse : obsolete
DEMOSAIC, // EvPixelShiftEqualBright
DEMOSAIC, // EvPixelShiftEqualBrightChannel
LUMINANCECURVE, // EvCATtempout
@ -631,7 +630,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
AUTOEXP, // EvLocallabstreng
AUTOEXP, // EvLocallabsensisf
AUTOEXP, // Evlocallabsharblur
AUTOEXP, // EvLocenalabregion
0, // EvLocenalabregion : obsolete
AUTOEXP, // EvlocallabshowmaskMethod
AUTOEXP, // EvLocallabSpotSelectedWithMask
AUTOEXP, // EvlocallabCCmaskshape
@ -875,7 +874,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
AUTOEXP | M_AUTOEXP, // EvLocenalog
HDR, // EvLocallabAuto
AUTOEXP, // EvlocallabsourceGray
HDR, // EvlocallabsourceGrayAuto
0, // EvlocallabsourceGrayAuto : obsolete
HDR, // EvlocallabAutoGray
AUTOEXP, // EvlocallabblackEv
AUTOEXP, // EvlocallabwhiteEv
@ -1187,7 +1186,6 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
AUTOEXP, //Evlocallabsigjz
AUTOEXP, //Evlocallabsigq
AUTOEXP //Evlocallablogcie
};

View File

@ -493,7 +493,7 @@ class ImageTypeListener
{
public:
virtual ~ImageTypeListener() = default;
virtual void imageTypeChanged(bool isRaw, bool isBayer, bool isXtrans, bool is_Mono = false) = 0;
virtual void imageTypeChanged(bool isRaw, bool isBayer, bool isXtrans, bool is_Mono = false, bool isGainMapSupported = false) = 0;
};
class AutoContrastListener

View File

@ -83,6 +83,7 @@ public:
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
Glib::ustring lensfunDbBundleDirectory;
int cropsleep;
double reduchigh;
double reduclow;

View File

@ -924,6 +924,14 @@ private:
//ImProcFunctions ipf (&params, true);
ImProcFunctions &ipf = * (ipf_p.get());
for (int sp = 0; sp < (int)params.locallab.spots.size(); sp++) {
if(params.locallab.spots.at(sp).expsharp && params.dirpyrequalizer.cbdlMethod == "bef") {
if(params.locallab.spots.at(sp).shardamping < 1) {
params.locallab.spots.at(sp).shardamping = 1;
}
}
}
if (params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) {
const int W = baseImg->getWidth();
const int H = baseImg->getHeight();

View File

@ -100,6 +100,11 @@ public:
return false;
}
bool isGainMapSupported() const override
{
return false;
}
void setProgressListener (ProgressListener* pl) override
{
plistener = pl;

124
rtengine/winutils.h Normal file
View File

@ -0,0 +1,124 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2021 Lawrence Lee
*
* 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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#ifdef WIN32
#include <aclapi.h>
#include <windows.h>
#include "noncopyable.h"
/**
* Wrapper for pointers to memory allocated by HeapAlloc.
*
* Memory is automatically freed when the object goes out of scope.
*/
template <typename T>
class WinHeapPtr : public rtengine::NonCopyable
{
private:
const T ptr;
public:
WinHeapPtr() = delete;
/** Allocates the specified number of bytes in the process heap. */
explicit WinHeapPtr(SIZE_T bytes): ptr(static_cast<T>(HeapAlloc(GetProcessHeap(), 0, bytes))) {};
~WinHeapPtr()
{
// HeapFree does a null check.
HeapFree(GetProcessHeap(), 0, static_cast<LPVOID>(ptr));
}
T operator ->() const
{
return ptr;
}
operator T() const
{
return ptr;
}
};
/**
* Wrapper for HLOCAL pointers to memory allocated by LocalAlloc.
*
* Memory is automatically freed when the object goes out of scope.
*/
template <typename T>
class WinLocalPtr : public rtengine::NonCopyable
{
private:
const T ptr;
public:
WinLocalPtr() = delete;
/** Wraps a raw pointer. */
WinLocalPtr(T pointer): ptr(pointer) {};
~WinLocalPtr()
{
// LocalFree does a null check.
LocalFree(static_cast<HLOCAL>(ptr));
}
T operator ->() const
{
return ptr;
}
operator T() const
{
return ptr;
}
};
/**
* Wrapper for HANDLEs.
*
* Handles are automatically closed when the object goes out of scope.
*/
class WinHandle : public rtengine::NonCopyable
{
private:
const HANDLE handle;
public:
WinHandle() = delete;
/** Wraps a HANDLE. */
WinHandle(HANDLE handle): handle(handle) {};
~WinHandle()
{
CloseHandle(handle);
}
operator HANDLE() const
{
return handle;
}
};
#endif

View File

@ -633,7 +633,7 @@ public:
{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"},
{38, "Canon EF 80-200mm f/4.5-5.6 II"},
{39, "Canon EF 75-300mm f/4-5.6"},
{40, "Canon EF 28-80mm f/3.5-5.6"},
{41, "Canon EF 28-90mm f/4-5.6"},
@ -654,6 +654,7 @@ public:
{53, "Canon EF-S 18-55mm f/3.5-5.6 III"},
{54, "Canon EF-S 55-250mm f/4-5.6 IS II"},
{60, "Irix 11mm f/4"},
{63, "Irix 30mm F1.4 Dragonfly"},
{80, "Canon TS-E 50mm f/2.8L Macro"},
{81, "Canon TS-E 90mm f/2.8L Macro"},
{82, "Canon TS-E 135mm f/4L Macro"},
@ -916,12 +917,13 @@ public:
{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"},
{254, "Canon EF 100mm f/2.8L Macro IS USM or Tamron Lens"},
{254, "Tamron SP 90mm f/2.8 Di VC USD 1:1 Macro (F017)"},
{255, "Sigma 24-105mm f/4 DG OS HSM | A or Other Lens"},
{255, "Sigma 180mm f/2.8 EX DG OS HSM APO Macro"},
{255, "Tamron SP 70-200mm f/2.8 Di VC USD"},
{368, "Sigma 14-24mm f/2.8 DG HSM | A or other Sigma Lens"},
{368, "Sigma 35mm f/1.4 DG HSM | A"},
{368, "Sigma 20mm f/1.4 DG HSM | A"},
{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"},
@ -930,7 +932,10 @@ public:
{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 35mm f/1.4 DG HSM | A"},
{368, "Sigma 70mm f/2.8 DG Macro"},
{368, "Sigma 18-35mm f/1.8 DC HSM | A"},
{368, "Sigma 24-105mm f/4 DG OS HSM | A"},
{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"},
@ -958,7 +963,8 @@ public:
{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 (B023)"},
{624, "Sigma 70-200mm f/2.8 DG OS HSM | S"},
{624, "Sigma 70-200mm f/2.8 DG OS HSM | S or other Sigma Lens"},
{624, "Sigma 150-600mm f/5-6.3 | C"},
{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"},
@ -994,7 +1000,8 @@ public:
{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"},
{4208, "Sigma 56mm f/1.4 DC DN | C or other Sigma Lens"},
{4208, "Sigma 30mm F1.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"},
@ -1002,9 +1009,41 @@ public:
{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 85mm F1.2L USM DS"},
{61182, "Canon RF 24-70mm F2.8L IS USM"},
{61182, "Canon RF 15-35mm F2.8L IS 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"},
{61182, "Canon RF 70-200mm F2.8L IS USM"},
{61182, "Canon RF 85mm F2 MACRO IS STM"},
{61182, "Canon RF 600mm F11 IS STM"},
{61182, "Canon RF 600mm F11 IS STM + RF1.4x"},
{61182, "Canon RF 600mm F11 IS STM + RF2x"},
{61182, "Canon RF 800mm F11 IS STM"},
{61182, "Canon RF 800mm F11 IS STM + RF1.4x"},
{61182, "Canon RF 800mm F11 IS STM + RF2x"},
{61182, "Canon RF 24-105mm F4-7.1 IS STM"},
{61182, "Canon RF 100-500mm F4.5-7.1L IS USM"},
{61182, "Canon RF 100-500mm F4.5-7.1L IS USM + RF1.4x"},
{61182, "Canon RF 100-500mm F4.5-7.1L IS USM + RF2x"},
{61182, "Canon RF 70-200mm F4L IS USM"},
{61182, "Canon RF 100mm F2.8L MACRO IS USM"},
{61182, "Canon RF 50mm F1.8 STM"},
{61182, "Canon RF 14-35mm F4L IS USM"},
{61182, "Canon RF-S 18-45mm F4.5-6.3 IS STM"},
{61182, "Canon RF 100-400mm F5.6-8 IS USM"},
{61182, "Canon RF 100-400mm F5.6-8 IS USM + RF1.4x"},
{61182, "Canon RF 100-400mm F5.6-8 IS USM + RF2x"},
{61182, "Canon RF-S 18-150mm F3.5-6.3 IS STM"},
{61182, "Canon RF 24mm F1.8 MACRO IS STM"},
{61182, "Canon RF 16mm F2.8 STM"},
{61182, "Canon RF 400mm F2.8L IS USM"},
{61182, "Canon RF 400mm F2.8L IS USM + RF1.4x"},
{61182, "Canon RF 400mm F2.8L IS USM + RF2x"},
{61182, "Canon RF 600mm F4L IS USM"},
{61182, "Canon RF 15-30mm F4.5-6.3 IS STM"},
{61182, "Canon RF 800mm F5.6L IS USM"},
{61182, "Canon RF 1200mm F8L IS USM"},
{61182, "Canon RF 5.2mm F2.8L Dual Fisheye 3D VR"},
{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"},
@ -1898,6 +1937,7 @@ public:
choices[2147484678] = "EOS 6D Mark II";
choices[2147484680] = "EOS 77D / 9000D";
choices[2147484695] = "EOS Rebel SL2 / 200D / Kiss X9";
choices[2147484705] = "EOS R5";
choices[2147484706] = "EOS Rebel T100 / 4000D / 3000D";
choices[2147484708] = "EOS R";
choices[2147484712] = "EOS-1D X Mark III";
@ -1906,6 +1946,12 @@ public:
choices[2147484725] = "EOS Rebel T8i / 850D / X10i";
choices[2147484726] = "EOS SL3 / 250D / Kiss X10";
choices[2147484727] = "EOS 90D";
choices[2147484752] = "EOS R3";
choices[2147484755] = "EOS R6";
choices[2147484772] = "EOS R7";
choices[2147484773] = "EOS R10";
choices[2147484775] = "PowerShot ZOOM";
choices[2147484776] = "EOS M50 Mark II / Kiss M2";
choices[2147484960] = "EOS D2000C";
choices[2147485024] = "EOS D6000C";
}

View File

@ -611,6 +611,7 @@ const std::map<std::string, std::string> NALensDataInterpreter::lenses = {
{"02 3A 37 50 31 3D 02 00", "Sigma 24-50mm f/4-5.6 UC"},
{"02 3A 5E 8E 32 3D 02 00", "Sigma 75-300mm f/4.0-5.6"},
{"02 3B 44 61 30 3D 02 00", "Sigma 35-80mm f/4-5.6"},
{"02 3B 5C 82 30 3C 02 00", "Sigma Zoom-K 70-210mm f/4-5.6"},
{"02 3C B0 B0 3C 3C 02 00", "Sigma APO 800mm f/5.6"},
{"02 3F 24 24 2C 2C 02 00", "Sigma 14mm f/3.5"},
{"02 3F 3C 5C 2D 35 02 00", "Sigma 28-70mm f/3.5-4.5 UC"},
@ -635,6 +636,7 @@ const std::map<std::string, std::string> NALensDataInterpreter::lenses = {
{"07 3E 30 43 2D 35 03 00", "Soligor AF Zoom 19-35mm 1:3.5-4.5 MC"},
{"07 40 2F 44 2C 34 03 02", "Tamron AF 19-35mm f/3.5-4.5 (A10)"},
{"07 40 30 45 2D 35 03 02", "Tamron AF 19-35mm f/3.5-4.5 (A10)"},
{"07 40 30 45 2D 35 03 02", "Voigtlander Ultragon 19-35mm f/3.5-4.5 VMV"},
{"07 40 3C 5C 2C 35 03 00", "Tokina AF 270 II (AF 28-70mm f/3.5-4.5)"},
{"07 40 3C 62 2C 34 03 00", "AF Zoom-Nikkor 28-85mm f/3.5-4.5"},
{"07 46 2B 44 24 30 03 02", "Tamron SP AF 17-35mm f/2.8-4 Di LD Aspherical (IF) (A05)"},
@ -719,6 +721,7 @@ const std::map<std::string, std::string> NALensDataInterpreter::lenses = {
{"26 40 7B A0 34 40 1C 02", "Sigma APO 170-500mm f/5-6.3 Aspherical RF"},
{"26 41 3C 8E 2C 40 1C 02", "Sigma 28-300mm f/3.5-6.3 DG Macro"},
{"26 44 73 98 34 3C 1C 02", "Sigma 135-400mm f/4.5-5.6 APO Aspherical"},
{"26 45 68 8E 34 42 1C 02", "Sigma 100-300mm f/4.5-6.7 DL"},
{"26 48 11 11 30 30 1C 02", "Sigma 8mm f/4 EX Circular Fisheye"},
{"26 48 27 27 24 24 1C 02", "Sigma 15mm f/2.8 EX Diagonal Fisheye"},
{"26 48 2D 50 24 24 1C 06", "Sigma 18-50mm f/2.8 EX DC"},
@ -874,6 +877,7 @@ const std::map<std::string, std::string> NALensDataInterpreter::lenses = {
{"6E 48 98 98 24 24 74 02", "AF-S Nikkor 400mm f/2.8D IF-ED II"},
{"6F 3C A0 A0 30 30 75 02", "AF-S Nikkor 500mm f/4D IF-ED II"},
{"70 3C A6 A6 30 30 76 02", "AF-S Nikkor 600mm f/4D IF-ED II"},
{"71 48 64 64 24 24 00 00", "Voigtlander APO-Skopar 90mm f/2.8 SL IIs"},
{"72 48 4C 4C 24 24 77 00", "Nikkor 45mm f/2.8 P"},
{"74 40 37 62 2C 34 78 06", "AF-S Zoom-Nikkor 24-85mm f/3.5-4.5G IF-ED"},
{"75 40 3C 68 2C 3C 79 06", "AF Zoom-Nikkor 28-100mm f/3.5-5.6G"},
@ -901,6 +905,7 @@ const std::map<std::string, std::string> NALensDataInterpreter::lenses = {
{"7A 48 2D 50 24 24 4B 06", "Sigma 18-50mm f/2.8 EX DC Macro"},
{"7A 48 5C 80 24 24 4B 06", "Sigma 70-200mm f/2.8 EX APO DG Macro HSM II"},
{"7A 54 6E 8E 24 24 4B 02", "Sigma APO 120-300mm f/2.8 EX DG HSM"},
{"7B 48 37 44 18 18 4B 06", "Sigma 24-35mm f/2.0 DG HSM | A"},
{"7B 48 80 98 30 30 80 0E", "AF-S VR Zoom-Nikkor 200-400mm f/4G IF-ED"},
{"7C 54 2B 50 24 24 00 06", "Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) (A16)"},
{"7D 48 2B 53 24 24 82 06", "AF-S DX Zoom-Nikkor 17-55mm f/2.8G IF-ED"},
@ -914,6 +919,7 @@ const std::map<std::string, std::string> NALensDataInterpreter::lenses = {
{"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"},
{"87 2C 2D 8E 2C 40 4B 0E", "Sigma 18-300mm f/3.5-6.3 DC Macro HSM"},
{"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"},
@ -921,8 +927,10 @@ const std::map<std::string, std::string> NALensDataInterpreter::lenses = {
{"8A 54 6A 6A 24 24 8C 0E", "AF-S VR Micro-Nikkor 105mm f/2.8G IF-ED"},
{"8B 40 2D 80 2C 3C 8D 0E", "AF-S DX VR Zoom-Nikkor 18-200mm f/3.5-5.6G IF-ED"},
{"8B 40 2D 80 2C 3C FD 0E", "AF-S DX VR Zoom-Nikkor 18-200mm f/3.5-5.6G IF-ED [II]"},
{"8B 48 1C 30 24 24 85 06", "Tokina AT-X 11-20 f/2.8 PRO DX (AF 11-20mm f/2.8)"},
{"8B 4C 2D 44 14 14 4B 06", "Sigma 18-35mm f/1.8 DC HSM"},
{"8C 40 2D 53 2C 3C 8E 06", "AF-S DX Zoom-Nikkor 18-55mm f/3.5-5.6G ED"},
{"8C 48 29 3C 24 24 86 06", "Tokina opera 16-28mm f/2.8 FF"},
{"8D 44 5C 8E 34 3C 8F 0E", "AF-S VR Zoom-Nikkor 70-300mm f/4.5-5.6G IF-ED"},
{"8D 48 6E 8E 24 24 4B 0E", "Sigma 120-300mm f/2.8 DG OS HSM Sports"},
{"8E 3C 2B 5C 24 30 4B 0E", "Sigma 17-70mm f/2.8-4 DC Macro OS HSM | C"},
@ -960,13 +968,17 @@ const std::map<std::string, std::string> NALensDataInterpreter::lenses = {
{"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 54 68 68 18 18 A2 06", "Yongnuo YN100mm f/2N"},
{"9F 58 44 44 14 14 A1 06", "AF-S DX Nikkor 35mm f/1.8G"},
{"A0 37 5C 8E 34 3C A2 06", "Sony FE 70-300mm f/4.5-5.6 G OSS"},
{"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"},
{"A0 40 2D 74 2C 3C BB 0E", "AF-S DX Nikkor 18-140mm f/3.5-5.6G ED VR"},
{"A0 48 2A 5C 24 30 4B 0E", "Sigma 17-70mm f/2.8-4 DC Macro OS HSM"},
{"A0 54 50 50 0C 0C A2 06", "AF-S Nikkor 50mm f/1.4G"},
{"A0 56 44 44 14 14 A2 06", "Sony FE 35mm f/1.8"},
{"A1 40 18 37 2C 34 A3 06", "AF-S DX Nikkor 10-24mm f/3.5-4.5G ED"},
{"A1 40 2D 53 2C 3C CB 86", "AF-P DX Nikkor 18-55mm f/3.5-5.6G"},
{"A1 41 19 31 2C 2C 4B 06", "Sigma 10-20mm f/3.5 EX DC HSM"},
{"A1 48 6E 8E 24 24 DB 4E", "AF-S Nikkor 120-300mm f/2.8E FL ED SR VR"},
{"A1 54 55 55 0C 0C BC 06", "AF-S Nikkor 58mm f/1.4G"},
@ -1040,6 +1052,7 @@ const std::map<std::string, std::string> NALensDataInterpreter::lenses = {
{"B6 48 37 56 24 24 1C 02", "Sigma 24-60mm f/2.8 EX DG"},
{"B7 44 60 98 34 3C B9 0E", "AF-S Nikkor 80-400mm f/4.5-5.6G ED VR"},
{"B8 40 2D 44 2C 34 BA 06", "AF-S Nikkor 18-35mm f/3.5-4.5G ED"},
{"BB 48 5C 80 24 24 4B 4E", "Sigma 70-200mm f/2.8 DG OS HSM | S"},
{"BF 3C 1B 1B 30 30 01 04", "Irix 11mm f/4 Firefly"},
{"BF 4E 26 26 1E 1E 01 04", "Irix 15mm f/2.4 Firefly"},
{"C1 48 24 37 24 24 4B 46", "Sigma 14-24mm f/2.8 DG HSM | A"},
@ -1051,8 +1064,10 @@ const std::map<std::string, std::string> NALensDataInterpreter::lenses = {
{"C8 54 62 62 0C 0C 4B 46", "Sigma 85mm f/1.4 DG HSM | A"},
{"C9 3C 44 76 25 31 DF 4E", "Tamron 35-150mm f/2.8-4 Di VC OSD (A043)"},
{"C9 48 37 5C 24 24 4B 4E", "Sigma 24-70mm f/2.8 DG OS HSM | A"},
{"CA 3C 1F 37 30 30 4B 46", "Sigma 12-24mm f/4 DG HSM | A"},
{"CA 48 27 3E 24 24 DF 4E", "Tamron SP 15-30mm f/2.8 Di VC USD G2 (A041)"},
{"CB 3C 2B 44 24 31 DF 46", "Tamron 17-35mm f/2.8-4 Di OSD (A037)"},
{"CC 44 68 98 34 41 DF 0E", "Tamron 100-400mm f/4.5-6.3 Di VC USD"},
{"CC 4C 50 68 14 14 4B 06", "Sigma 50-100mm f/1.8 DC HSM | A"},
{"CD 3D 2D 70 2E 3C 4B 0E", "Sigma 18-125mm f/3.8-5.6 DC OS HSM"},
{"CE 34 76 A0 38 40 4B 0E", "Sigma 150-500mm f/5-6.3 DG OS APO HSM"},
@ -1060,6 +1075,7 @@ const std::map<std::string, std::string> NALensDataInterpreter::lenses = {
{"CF 38 6E 98 34 3C 4B 0E", "Sigma APO 120-400mm f/4.5-5.6 DG OS HSM"},
{"CF 47 5C 8E 31 3D DF 0E", "Tamron SP 70-300mm f/4-5.6 Di VC USD (A030)"},
{"D2 3C 8E B0 3C 3C 4B 02", "Sigma APO 300-800mm f/5.6 EX DG HSM"},
{"DB 40 11 11 2C 2C 1C 06", "Sigma 8mm f/3.5 EX DG Circular Fisheye"},
{"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"},
@ -1067,6 +1083,7 @@ const std::map<std::string, std::string> NALensDataInterpreter::lenses = {
{"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 0E", "Tamron SP 150-600mm f/5-6.3 Di VC USD G2 (A022)"},
{"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)"},
@ -1081,6 +1098,7 @@ const std::map<std::string, std::string> NALensDataInterpreter::lenses = {
{"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)"},
{"EC 3E 3C 8E 2C 40 DF 0E", "Tamron 28-300mm f/3.5-6.3 Di VC PZD A010"},
{"ED 40 2D 80 2C 40 4B 0E", "Sigma 18-200mm f/3.5-6.3 DC OS HSM"},
{"EE 48 5C 80 24 24 4B 06", "Sigma 70-200mm f/2.8 EX APO DG Macro HSM II"},
{"F0 38 1F 37 34 3C 4B 06", "Sigma 12-24mm f/4.5-5.6 EX DG Aspherical HSM"},

View File

@ -130,9 +130,12 @@ public:
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 33 10"] = "Olympus M.Zuiko Digital 150-400mm f/4.5 TC1.25x IS Pro";
lenses["00 34 00"] = "Olympus Zuiko Digital ED 9-18mm f/4.0-5.6";
lenses["00 34 10"] = "Olympus M.Zuiko Digital ED 12-45mm f/4.0 Pro";
lenses["00 35 00"] = "Olympus Zuiko Digital 14-54mm f/2.8-3.5 II";
lenses["00 35 10"] = "Olympus M.Zuiko 100-400mm f/5.0-6.3";
lenses["00 36 10"] = "Olympus M.Zuiko Digital ED 8-25mm f/4 Pro";
lenses["01 01 00"] = "Sigma 18-50mm f/3.5-5.6 DC";
lenses["01 01 10"] = "Sigma 30mm f/2.8 EX DN";
lenses["01 02 00"] = "Sigma 55-200mm f/4.0-5.6 DC";
@ -200,6 +203,7 @@ public:
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["02 40 10"] = "Leica DG Vario-Summilux 25-50mm 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";

View File

@ -924,6 +924,7 @@ public:
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"));
choices.insert (p_t (256 * 8 + 24, "Sigma 17-70mm f/2.8-4 DC Macro OS HSM"));
choices.insert (p_t (256 * 8 + 25, "Sigma 17-50mm f/2.8 EX DC HSM"));
choices.insert (p_t (256 * 8 + 27, "Sigma 18-200mm f/3.5-6.3 II DC HSM"));
choices.insert (p_t (256 * 8 + 28, "Sigma 18-250mm f/3.5-6.3 DC Macro HSM"));
@ -940,6 +941,9 @@ public:
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 + 65, "HD PENTAX-D FA 70-210mm f/4 ED SDM WR"));
choices.insert (p_t (256 * 8 + 66, "HD PENTAX-D FA 85mm f/1.4 ED SDM AW"));
choices.insert (p_t (256 * 8 + 67, "HD PENTAX-D FA 21mm f/2.4 ED Limited DC WR"));
choices.insert (p_t (256 * 8 + 195, "HD PENTAX DA* 16-50mm f/2.8 ED PLM 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"));

View File

@ -1035,11 +1035,13 @@ public:
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 (7, "Sony LA-EA5 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 (24593, "LA-EA4r MonsterAdapter"));
choices.insert (p_t (32784, "Sony E 16mm f/2.8"));
choices.insert (p_t (32785, "Sony E 18-55mm f/3.5-5.6 OSS"));
choices.insert (p_t (32786, "Sony E 55-210mm f/4.5-6.3 OSS"));
@ -1097,8 +1099,23 @@ public:
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 (32855, "Sony FE C 16-35mm T3.1 G"));
choices.insert (p_t (32858, "Sony FE 35mm f/1.8"));
choices.insert (p_t (32859, "Sony FE 20mm f/1.8 G"));
choices.insert (p_t (32860, "Sony FE 12-24mm f/2.8 GM"));
choices.insert (p_t (32862, "Sony FE 50mm f/1.2 GM"));
choices.insert (p_t (32863, "Sony FE 14mm f/1.8 GM"));
choices.insert (p_t (32864, "Sony FE 28-60mm f/4-5.6"));
choices.insert (p_t (32865, "Sony FE 35mm f/1.4 GM"));
choices.insert (p_t (32866, "Sony FE 24mm f/2.8 G"));
choices.insert (p_t (32867, "Sony FE 40mm f/2.5 G"));
choices.insert (p_t (32868, "Sony FE 50mm f/2.5 G"));
choices.insert (p_t (32871, "Sony FE PZ 16-35mm f/4 G"));
choices.insert (p_t (32873, "Sony E PZ 10-20mm f/4 G"));
choices.insert (p_t (32874, "Sony FE 70-200mm f/2.8 GM OSS II"));
choices.insert (p_t (32875, "Sony FE 24-70mm f/2.8 GM II"));
choices.insert (p_t (32876, "Sony E 11mm f/1.8"));
choices.insert (p_t (32877, "Sony E 15mm f/1.4 G"));
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)"));
@ -1130,6 +1147,17 @@ public:
choices.insert (p_t (49461, "Tamron 20mm f/2.8 Di III OSD M1:2"));
choices.insert (p_t (49462, "Tamron 70-180mm f/2.8 Di III VXD"));
choices.insert (p_t (49463, "Tamron 28-200mm f/2.8-5.6 Di III RXD"));
choices.insert (p_t (49464, "Tamron 70-300mm f/4.5-6.3 Di III RXD"));
choices.insert (p_t (49465, "Tamron 17-70mm f/2.8 Di III-A VC RXD"));
choices.insert (p_t (49466, "Tamron 150-500mm f/5-6.7 Di III VC VXD"));
choices.insert (p_t (49467, "Tamron 11-20mm f/2.8 Di III-A RXD"));
choices.insert (p_t (49468, "Tamron 18-300mm f/3.5-6.3 Di III-A VC VXD"));
choices.insert (p_t (49469, "Tamron 35-150mm f/2-F2.8 Di III VXD"));
choices.insert (p_t (49470, "Tamron 28-75mm f/2.8 Di III VXD G2"));
choices.insert (p_t (49471, "Tamron 50-400mm f/4.5-6.3 Di III VC VXD"));
choices.insert (p_t (49473, "Tokina atx-m 85mm f/1.8 FE or Viltrox lens"));
choices.insert (p_t (49473, "Viltrox 23mm f/1.4 E"));
choices.insert (p_t (49473, "Viltrox 56mm f/1.4 E"));
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"));
@ -1157,7 +1185,20 @@ public:
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 (50517, "Sigma 24-70mm f/2.8 DG DN | A"));
choices.insert (p_t (50518, "Sigma 100-400mm f/5-6.3 DG DN OS"));
choices.insert (p_t (50518, "Sigma 100-400mm f/5-6.3 DG DN OS | C"));
choices.insert (p_t (50521, "Sigma 85mm f/1.4 DG DN | A"));
choices.insert (p_t (50522, "Sigma 105mm f/2.8 DG DN MACRO | A"));
choices.insert (p_t (50523, "Sigma 65mm f/2 DG DN | C"));
choices.insert (p_t (50524, "Sigma 35mm f/2 DG DN | C"));
choices.insert (p_t (50525, "Sigma 24mm f/3.5 DG DN | C"));
choices.insert (p_t (50526, "Sigma 28-70mm f/2.8 DG DN | C"));
choices.insert (p_t (50527, "Sigma 150-600mm f/5-6.3 DG DN OS | S"));
choices.insert (p_t (50528, "Sigma 35mm f/1.4 DG DN | A"));
choices.insert (p_t (50529, "Sigma 90mm f/2.8 DG DN | C"));
choices.insert (p_t (50530, "Sigma 24mm f/2 DG DN | C"));
choices.insert (p_t (50531, "Sigma 18-50mm f/2.8 DC DN | C"));
choices.insert (p_t (50532, "Sigma 20mm f/2 DG DN | C"));
choices.insert (p_t (50533, "Sigma 16-28mm f/2.8 DG DN | C"));
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"));
@ -1170,13 +1211,21 @@ public:
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 (51003, "Voigtlander NOKTON 35mm f/1.2 Aspherical SE"));
choices.insert (p_t (51006, "Voigtlander APO-LANTHAR 35mm 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"));
choices.insert (p_t (51510, "Samyang AF 18mm f/2.8 or Samyang AF 35mm f/1.8"));
choices.insert (p_t (51510, "Samyang AF 35mm f/1.8"));
choices.insert (p_t (51512, "Samyang AF 75mm f/1.8"));
choices.insert (p_t (51513, "Samyang AF 35mm f/1.8"));
choices.insert (p_t (51514, "Samyang AF 24mm f/1.8"));
choices.insert (p_t (51515, "Samyang AF 12mm f/2.0"));
choices.insert (p_t (51516, "Samyang AF 24-70mm f/2.8"));
choices.insert (p_t (51517, "Samyang AF 50mm f/1.4 II"));
choices.insert (p_t (51518, "Samyang AF 135mm f/1.8"));
}
std::string toString (const Tag* t) const override

View File

@ -62,6 +62,7 @@ set(NONCLISOURCEFILES
exiffiltersettings.cc
exifpanel.cc
exportpanel.cc
externaleditorpreferences.cc
extprog.cc
fattaltonemap.cc
filebrowser.cc
@ -134,6 +135,7 @@ set(NONCLISOURCEFILES
retinex.cc
rgbcurves.cc
rotate.cc
rtappchooserdialog.cc
rtimage.cc
rtscalable.cc
rtsurface.cc
@ -161,6 +163,7 @@ set(NONCLISOURCEFILES
tonecurve.cc
toneequalizer.cc
toolbar.cc
toollocationpref.cc
toolpanel.cc
toolpanelcoord.cc
vibrance.cc

View File

@ -199,7 +199,7 @@ void Adjuster::addAutoButton (const Glib::ustring &tooltip)
autoChange = automatic->signal_toggled().connect( sigc::mem_fun(*this, &Adjuster::autoToggled) );
if (grid) {
// Hombre, adding the checbox next to the reset button because adding it next to the spin button (as before)
// Hombre, adding the checkbox next to the reset button because adding it next to the spin button (as before)
// would diminish the available size for the label and would require a much heavier reorganization of the grid !
grid->attach_next_to(*automatic, *reset, Gtk::POS_RIGHT, 1, 1);
} else {

View File

@ -34,7 +34,7 @@ bool BatchQueueEntry::iconsLoaded(false);
Glib::RefPtr<Gdk::Pixbuf> BatchQueueEntry::savedAsIcon;
BatchQueueEntry::BatchQueueEntry (rtengine::ProcessingJob* pjob, const rtengine::procparams::ProcParams& pparams, Glib::ustring fname, int prevw, int prevh, Thumbnail* thm, bool overwrite) :
ThumbBrowserEntryBase(fname),
ThumbBrowserEntryBase(fname, thm),
opreview(nullptr),
origpw(prevw),
origph(prevh),

View File

@ -28,7 +28,9 @@
using namespace rtengine;
using namespace rtengine::procparams;
BayerPreProcess::BayerPreProcess() : FoldableToolPanel(this, "bayerpreprocess", M("TP_PREPROCESS_LABEL"), options.prevdemo != PD_Sidecar)
const Glib::ustring BayerPreProcess::TOOL_NAME = "bayerpreprocess";
BayerPreProcess::BayerPreProcess() : FoldableToolPanel(this, TOOL_NAME, M("TP_PREPROCESS_LABEL"), options.prevdemo != PD_Sidecar)
{
auto m = ProcEventMapper::getInstance();
EvLineDenoiseDirection = m->newEvent(DARKFRAME, "HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION");

View File

@ -37,6 +37,7 @@ protected:
rtengine::ProcEvent EvPDAFLinesFilter;
public:
static const Glib::ustring TOOL_NAME;
BayerPreProcess ();

View File

@ -28,9 +28,10 @@
using namespace rtengine;
using namespace rtengine::procparams;
const Glib::ustring BayerProcess::TOOL_NAME = "bayerprocess";
BayerProcess::BayerProcess () :
FoldableToolPanel(this, "bayerprocess", M("TP_RAW_LABEL"), options.prevdemo != PD_Sidecar),
FoldableToolPanel(this, TOOL_NAME, M("TP_RAW_LABEL"), options.prevdemo != PD_Sidecar),
oldMethod(-1)
{

Some files were not shown because too many files have changed in this diff Show More