Merge branch 'dev' into metadata-exiv2

This commit is contained in:
Lawrence Lee 2023-02-05 12:29:58 -08:00
commit 3833c6e634
No known key found for this signature in database
GPG Key ID: 048FF2B76A63895F
278 changed files with 74278 additions and 13534 deletions

169
.github/workflows/appimage.yml vendored Normal file
View File

@ -0,0 +1,169 @@
name: AppImage Build
on:
push:
branches:
- dev
- releases
tags:
- '[0-9]+.*'
pull_request:
branches:
- dev
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-18.04
strategy:
fail-fast: false
matrix:
build_type: [release]
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: 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: 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."
mkdir -p build/AppDir/usr/share/lensfun
echo "Copying Lensfun database to the build directory."
cp -R ~/.local/share/lensfun/updates/* build/AppDir/usr/share/lensfun/
- name: Restore AppImage tools from cache
id: appimage-tools-cache
uses: actions/cache@v2
with:
key: appimage-tools-1
path: |
./build/linuxdeploy-x86_64.AppImage
./build/linuxdeploy-plugin-gtk.sh
- name: Download AppImage tools
if: ${{steps.appimage-tools-cache.outputs.cache-hit != 'true'}}
working-directory: ./build
run: |
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' \
| sed 's/^\(export GTK_THEME\)/#\1/' \
> linuxdeploy-plugin-gtk.sh
echo "Setting execute bit on all AppImage tools."
chmod u+x linuxdeploy-*
- name: Package AppImage
working-directory: ./build
run: |
echo "Creating artifact name."
if [ '${{github.ref_type}}' == 'tag' ]; then
ARTIFACT_NAME="RawTherapee_${REF_NAME_FILTERED}_${{matrix.build_type}}"
else
echo "Getting RawTherapee version."
export VERSION="$(grep -m 1 '^Version: .*$' 'AboutThisBuild.txt' | sed 's/^Version: \(.\+\)$/\1/')"
echo "Version is '$VERSION'."
FILTERED_VERSION="$(echo "$VERSION" | sed 's/[^A-z0-9_.-]//g')"
ARTIFACT_NAME="RawTherapee_${REF_NAME_FILTERED}_${FILTERED_VERSION}_${{matrix.build_type}}"
fi
echo "Artifact name is '$ARTIFACT_NAME'."
echo "Generating AppImage file name."
export OUTPUT="$ARTIFACT_NAME.AppImage"
echo "AppImage file name will be '$OUTPUT'."
echo "Packaging AppImage."
./linuxdeploy-x86_64.AppImage \
--appimage-extract-and-run \
--appdir AppDir \
--plugin gtk \
--output appimage
echo "Recording artifact name."
echo "ARTIFACT_NAME=$ARTIFACT_NAME" >> $GITHUB_ENV
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: ${{env.ARTIFACT_NAME}}.AppImage
path: ${{github.workspace}}/build/${{env.ARTIFACT_NAME}}.AppImage
- name: Prepare for publishing
if: ${{github.ref_type == 'tag' || github.ref_name == 'dev'}}
run: |
echo "Setting publish name."
PUBLISH_NAME="RawTherapee_${REF_NAME_FILTERED}_${{matrix.build_type}}"
echo "Publish name is '$PUBLISH_NAME'."
echo "Renaming AppImage."
cp "build/$ARTIFACT_NAME.AppImage" "$PUBLISH_NAME.AppImage"
echo "Creating version file."
cp "build/AboutThisBuild.txt" "$PUBLISH_NAME-AboutThisBuild.txt"
echo "Recording publish name."
echo "PUBLISH_NAME=$PUBLISH_NAME" >> $GITHUB_ENV
- 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.PUBLISH_NAME}}.AppImage
${{env.PUBLISH_NAME}}-AboutThisBuild.txt

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}}

299
.github/workflows/windows.yml vendored Normal file
View File

@ -0,0 +1,299 @@
name: Windows Build
on:
push:
branches:
- dev
- releases
tags:
- '[0-9]+.*'
pull_request:
branches:
- dev
workflow_dispatch:
jobs:
build:
runs-on: windows-2022
defaults:
run:
shell: msys2 {0}
strategy:
fail-fast: false
matrix:
build_type: [release, debug]
steps:
- name: Checkout source
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Install dependencies
uses: msys2/setup-msys2@v2
with:
location: C:\msys2
update: true
install: |
gzip
git
intltool
mingw-w64-x86_64-gcc
mingw-w64-x86_64-make
mingw-w64-x86_64-pkg-config
mingw-w64-x86_64-cmake
mingw-w64-x86_64-ninja
mingw-w64-x86_64-gtkmm3
mingw-w64-x86_64-lcms2
mingw-w64-x86_64-fftw
mingw-w64-x86_64-lensfun
mingw-w64-x86_64-libiptcdata
- name: Configure build
run: |
export REF_NAME_FILTERED="$(echo '${{github.ref_name}}' | sed 's/[^A-z0-9_.-]//g')"
if [ '${{github.ref_type}}' == 'tag' ]; then
export CACHE_SUFFIX=""
else
echo "Setting cache suffix."
export CACHE_SUFFIX="5-$REF_NAME_FILTERED"
echo "Cache suffix is '$CACHE_SUFFIX'."
fi
echo "Making build directory."
mkdir build
echo "Changing working directory to the build directory."
cd build
echo "Running CMake configure."
cmake \
-G "Ninja" \
-DCMAKE_BUILD_TYPE='${{matrix.build_type}}' \
-DCACHE_NAME_SUFFIX="$CACHE_SUFFIX" \
-DPROC_TARGET_NUMBER="1" \
-DLENSFUNDBDIR="share/lensfun" \
..
echo "Recording filtered ref name."
echo "REF_NAME_FILTERED=$REF_NAME_FILTERED" >> "$(cygpath -u $GITHUB_ENV)"
- name: Build RawTherapee
working-directory: ./build
run: |
echo "Running CMake install."
cmake --build . --target install
- 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."
mkdir -p 'build/${{matrix.build_type}}/share'
echo "Copying Lensfun database to the build directory."
cp -R "/C/msys2/msys64/mingw64/var/lib/lensfun-updates/version_1" 'build/${{matrix.build_type}}/share/lensfun'
- name: Bundle dependencies
run: |
echo "Getting workspace path."
export BUILD_DIR="$(pwd)/build/${{matrix.build_type}}"
echo "Build directory is '$BUILD_DIR'."
echo "Changing working directory to MSYS2 MINGW64."
cd "/C/msys2/msys64/mingw64"
echo "Copying DLLs and EXEs."
cd ./bin
cp \
"gdbus.exe" \
"gspawn-win64-helper.exe" \
"gspawn-win64-helper-console.exe" \
"libatk-1.0-0.dll" \
"libatkmm-1.6-1.dll" \
"libbrotlicommon.dll" \
"libbrotlidec.dll" \
"libbz2-1.dll" \
"libcairo-2.dll" \
"libcairo-gobject-2.dll" \
"libcairomm-1.0-1.dll" \
"libdatrie-1.dll" \
"libdeflate.dll" \
"libepoxy-0.dll" \
"libexpat-1.dll" \
libffi-*.dll \
"libfftw3f-3.dll" \
"libfontconfig-1.dll" \
"libfreetype-6.dll" \
"libfribidi-0.dll" \
"libgcc_s_seh-1.dll" \
"libgdk_pixbuf-2.0-0.dll" \
"libgdk-3-0.dll" \
"libgdkmm-3.0-1.dll" \
"libgio-2.0-0.dll" \
"libgiomm-2.4-1.dll" \
"libglib-2.0-0.dll" \
"libglibmm-2.4-1.dll" \
"libgmodule-2.0-0.dll" \
"libgobject-2.0-0.dll" \
"libgomp-1.dll" \
"libgraphite2.dll" \
"libgtk-3-0.dll" \
"libgtkmm-3.0-1.dll" \
"libharfbuzz-0.dll" \
"libiconv-2.dll" \
"libintl-8.dll" \
"libjbig-0.dll" \
"libjpeg-8.dll" \
"liblcms2-2.dll" \
"liblensfun.dll" \
"libLerc.dll" \
"liblzma-5.dll" \
"libpango-1.0-0.dll" \
"libpangocairo-1.0-0.dll" \
"libpangoft2-1.0-0.dll" \
"libpangomm-1.4-1.dll" \
"libpangowin32-1.0-0.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-6.dll" \
"libtre-5.dll" \
"libwebp-7.dll" \
"libwinpthread-1.dll" \
"libxml2-2.dll" \
"libzstd.dll" \
"zlib1.dll" \
"$BUILD_DIR"
cd -
echo "Copying Adwaita theme."
mkdir -p "$BUILD_DIR/share/icons/Adwaita"
cd 'share/icons/Adwaita/'
mkdir -p "$BUILD_DIR/share/icons/Adwaita/scalable"
cp -r \
"scalable/actions" \
"scalable/devices" \
"scalable/mimetypes" \
"scalable/places" \
"scalable/status" \
"scalable/ui" \
"$BUILD_DIR/share/icons/Adwaita/scalable"
cp 'index.theme' "$BUILD_DIR/share/icons/Adwaita"
mkdir -p "$BUILD_DIR/share/icons/Adwaita/cursors"
cp -r \
"cursors/plus.cur" \
"cursors/sb_h_double_arrow.cur" \
"cursors/sb_left_arrow.cur" \
"cursors/sb_right_arrow.cur" \
"cursors/sb_v_double_arrow.cur" \
"$BUILD_DIR/share/icons/Adwaita/cursors"
cd -
echo "Copying GDK pixbuf."
mkdir -p "$BUILD_DIR/lib"
cp -r 'lib/gdk-pixbuf-2.0' "$BUILD_DIR/lib/gdk-pixbuf-2.0"
echo "Copying GLib schemas."
mkdir -p "$BUILD_DIR/share/glib-2.0/schemas"
cp 'share/glib-2.0/schemas/gschemas.compiled' "$BUILD_DIR/share/glib-2.0/schemas"
echo "Creating GTK settings.ini."
mkdir -p "$BUILD_DIR/share/gtk-3.0/"
echo '[Settings] gtk-button-images=1' > "$BUILD_DIR/share/gtk-3.0/settings.ini"
- name: Create installer
if: ${{matrix.build_type == 'release' && (github.ref_type == 'tag' || github.ref_name == 'dev')}}
working-directory: build/${{matrix.build_type}}
shell: pwsh
run: |
echo "Installing Inno Setup."
choco install innosetup
echo "Setup file:"
type "WindowsInnoSetup.iss"
echo "Creating installer from script."
iscc /F"installer" "WindowsInnoSetup.iss"
- name: Prepare artifact name
run: |
if [ '${{github.ref_type}}' == 'tag' ]; then
ARTIFACT_NAME="RawTherapee_${REF_NAME_FILTERED}_win64_${{matrix.build_type}}"
else
echo "Getting RawTherapee version."
export VERSION="$(grep -m 1 '^Version: .*$' './build/${{matrix.build_type}}/AboutThisBuild.txt' | sed 's/^Version: \(.\+\)$/\1/')"
echo "Version is '$VERSION'."
FILTERED_VERSION="$(echo "$VERSION" | sed 's/[^A-z0-9_.-]//g')"
ARTIFACT_NAME="RawTherapee_${REF_NAME_FILTERED}_${FILTERED_VERSION}_win64_${{matrix.build_type}}"
fi
echo "Artifact name is '$ARTIFACT_NAME'."
echo "Recording artifact name."
echo "ARTIFACT_NAME=$ARTIFACT_NAME" >> "$(cygpath -u $GITHUB_ENV)"
echo "Recording RawTherapee version."
echo "RT_VERSION=$VERSION" >> "$(cygpath -u $GITHUB_ENV)"
echo "Renaming artifact."
mv './build/${{matrix.build_type}}' "./build/$ARTIFACT_NAME"
if [ -e './build/installer.exe' ]; then
echo "Renaming installer."
mv './build/installer.exe' "./build/$ARTIFACT_NAME.exe"
fi
- name: Create ZIP archive
shell: cmd
working-directory: ./build
run: |
echo "Zipping artifact."
7z a -tzip "%ARTIFACT_NAME%.zip" "./%ARTIFACT_NAME%"
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: ${{env.ARTIFACT_NAME}}
path: build\${{env.ARTIFACT_NAME}}
- name: Upload installer
if: ${{matrix.build_type == 'release' && (github.ref_type == 'tag' || github.ref_name == 'dev')}}
uses: actions/upload-artifact@v2
with:
name: ${{env.ARTIFACT_NAME}}.exe
path: build\${{env.ARTIFACT_NAME}}.exe
- name: Prepare for publishing
if: ${{github.ref_type == 'tag' || github.ref_name == 'dev'}}
run: |
echo "Setting publish name."
PUBLISH_NAME="RawTherapee_${REF_NAME_FILTERED}_win64_${{matrix.build_type}}"
echo "Publish name is '$PUBLISH_NAME'."
if [ "$ARTIFACT_NAME" != "$PUBLISH_NAME" ]; then
echo "Renaming ZIP file."
cp "build/$ARTIFACT_NAME.zip" "build/$PUBLISH_NAME.zip"
if [ -e "./build/$ARTIFACT_NAME.exe" ]; then
echo "Renaming installer."
mv "./build/$ARTIFACT_NAME.exe" "./build/$PUBLISH_NAME.exe"
fi
fi
echo "Creating version file."
cp "build/$ARTIFACT_NAME/AboutThisBuild.txt" "build/$PUBLISH_NAME-AboutThisBuild.txt"
echo "Recording publish name."
echo "PUBLISH_NAME=$PUBLISH_NAME" >> "$(cygpath -u $GITHUB_ENV)"
- 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: |
build/${{env.PUBLISH_NAME}}.zip
build/${{env.PUBLISH_NAME}}-AboutThisBuild.txt
- name: Publish installer
uses: softprops/action-gh-release@v1
if: ${{matrix.build_type == 'release' && (github.ref_type == 'tag' || github.ref_name == 'dev')}}
with:
tag_name: nightly-github-actions
files: build/${{env.PUBLISH_NAME}}.exe

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
@ -33,6 +34,7 @@ Development contributors, in last name alphabetical order:
Jan Rinze
Alberto Romei
Ben S.
Simon Segerblom Rex
Andrey Skvortsov
Fabio Suprani
Anders Torger
@ -49,6 +51,7 @@ Other contributors (profiles, ideas, mockups, testing, forum activity, translati
Fernando Carello
Rodrigo Nuno Bragança da Cunha
Pat David
Jacques Dekker
Reine Edvardsson
Andrea Ferrero
André Gauthier
@ -61,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
@ -73,3 +78,4 @@ Other contributors (profiles, ideas, mockups, testing, forum activity, translati
TooWaBoo
Franz Trischberger
Colin Walker
Martin Werner

View File

@ -44,11 +44,15 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION
"Building RawTherapee requires using GCC version 4.9 or higher!")
endif()
# Warning for GCC 10, which causes problems #5749:
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "10.1")
# 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")
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:
@ -175,7 +197,7 @@ if(APPLE) # TODO make -mtune generic conditional and/or specifiable.
if(CMAKE_CXX_COMPILER MATCHES "g\\+\\+-mp-4.[5-8]"
OR CMAKE_CXX_COMPILER_ARG1 MATCHES "g\\+\\+-mp-4.[5-8]")
set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} /usr/lib/libstdc++.6.dylib -Wl,-headerpad_max_install_names -mtune=generic"
"${CMAKE_EXE_LINKER_FLAGS} /usr/lib/libstdc++.6.dylib -Wl,-headerpad_max_install_names -mtune=generic -framework Foundation"
)
message(
STATUS
@ -190,7 +212,7 @@ if(APPLE) # TODO make -mtune generic conditional and/or specifiable.
set(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} -Wl,-headerpad_max_install_names -mtune=generic"
"${CMAKE_EXE_LINKER_FLAGS} -Wl,-headerpad_max_install_names -mtune=generic -framework Foundation"
)
endif()
@ -304,7 +326,7 @@ endif()
if(NOT DEFINED CREDITSDIR)
if(BUILD_BUNDLE)
if(APPLE)
set(CREDITSDIR "${DATADIR}")
set(CREDITSDIR "${DATADIR}/..")
else()
set(CREDITSDIR "${DATADIR}")
endif()
@ -371,6 +393,8 @@ if(NOT APPLE)
if(DEFINED LENSFUNDBDIR AND NOT IS_ABSOLUTE "${LENSFUNDBDIR}")
set(LENSFUNDBDIR "${DATADIR}/${LENSFUNDBDIR}")
endif()
else()
set(LENSFUNDBDIR "${LENSFUNDBDIR}")
endif()
if(APPLE)
@ -387,11 +411,11 @@ if(APPLE)
if("${LOCAL_PREFIX}")
set(LOCAL_PREFIX
"${LOCAL_PREFIX}"
CACHE STRING "macos/gtk parent directory ie /usr or /opt")
CACHE STRING "macos/gtk parent directory ie /usr/local or /opt/local or /opt/homebrew (for arm64)")
else()
set(LOCAL_PREFIX
/usr
CACHE STRING "macos/gtk parent directory ie /usr or /opt")
/usr/local
CACHE STRING "macos/gtk parent directory ie /usr/local (default) or /opt/local (macports) or /opt/homebrew (for arm64)")
endif()
if("${FANCY_DMG}")
set(FANCY_DMG
@ -511,6 +535,12 @@ endif()
pkg_check_modules(LCMS REQUIRED lcms2>=2.6)
pkg_check_modules(EXPAT REQUIRED expat>=2.1)
pkg_check_modules(FFTW3F REQUIRED fftw3f)
#Set the appropriate FFTW flags on macOS
if(APPLE AND OPTION_OMP)
set(EXTRA_LIB "-L${LOCAL_PREFIX}/lib -lfftw3f_omp -lfftw3f -lm")
endif()
pkg_check_modules(IPTCDATA REQUIRED libiptcdata)
find_package(TIFF 4.0.4 REQUIRED)
find_package(JPEG REQUIRED)
@ -712,11 +742,18 @@ elseif(APPLE)
${CMAKE_COMMAND}
-DPROJECT_SOURCE_DIR:STRING=${PROJECT_SOURCE_DIR}
-DCACHE_NAME_SUFFIX:STRING=${CACHE_NAME_SUFFIX}
-P ${PROJECT_SOURCE_DIR}/UpdateInfo.cmake
-DSYSTEM:STRING=Apple
-DCXX_FLAGS:STRING=${CXX_FLAGS}
-DLFLAGS:STRING=${LFLAGS}
-DCOMPILER_INFO:STRING=${COMPILER_INFO})
-DCOMPILER_INFO:STRING=${COMPILER_INFO}
-DPROC_LABEL:STRING="${PROC_LABEL}"
-DPROC_BIT_DEPTH:STRING="${PROC_BIT_DEPTH}"
-DBUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
-DGTKMM_VERSION:STRING=${GTKMM_VERSION}
-DOPTION_OMP:STRING=${OPTION_OMP}
-DWITH_MYFILE_MMAP:STRING=${WITH_MYFILE_MMAP}
-DLENSFUN_VERSION:STRING=${LENSFUN_VERSION}
-P ${PROJECT_SOURCE_DIR}/UpdateInfo.cmake)
else()
list(APPEND ABOUT_COMMAND_WITH_ARGS -DSYSTEM:STRING=Linux
-DCXX_FLAGS:STRING=${CXX_FLAGS} -DLFLAGS:STRING=${LFLAGS}
@ -736,7 +773,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(
@ -807,7 +844,14 @@ if(ENABLE_TCMALLOC)
find_library(TCMALLOC_LIBRARIES tcmalloc PATHS ${TCMALLOC_LIB_DIR}
NO_DEFAULT_PATH)
else()
find_library(TCMALLOC_LIBRARIES tcmalloc)
# On Debian libtcmalloc-minimal4 has no .so symlink, so let's adjust for that
set(OLD_CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_FIND_LIBRARY_SUFFIXES}")
list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES ".so.4")
find_library(TCMALLOC_LIBRARIES NAMES tcmalloc tcmalloc_minimal)
set(CMAKE_FIND_LIBRARY_SUFFIXES "${OLD_CMAKE_FIND_LIBRARY_SUFFIXES}")
unset(OLD_CMAKE_FIND_LIBRARY_SUFFIXES)
endif()
if(TCMALLOC_LIBRARIES)
message(STATUS "using tcmalloc library in ${TCMALLOC_LIBRARIES}")

View File

@ -16,6 +16,7 @@ The most useful feedback is based on the latest development code, and in the cas
- Announce and discuss your plans in GitHub before starting work.
- Work in a new branch. Fork if necessary.
- Keep branches small so that completed and working features can be merged into the "dev" branch often, and so that they can be abandoned if they head in the wrong direction.
- Documentation for your work must be provided in order for your branch to be merged if it changes or adds anything the user should know about. The documentation can be provided in plain-text or markdown form as a comment in the issue or pull request.
- Use C++11.
- To break header dependencies use forward declarations as much as possible. See [#5197](https://github.com/Beep6581/RawTherapee/pull/5197#issuecomment-468938190) for some tips.
- The naming isn't homogeneous throughout the code but here is a rough guideline:

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>

View File

@ -34,7 +34,7 @@ if(UNIX)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/images/png/rawtherapee-logo-64.png" DESTINATION "${ICONSDIR}/hicolor/64x64/apps" RENAME rawtherapee.png)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/images/png/rawtherapee-logo-128.png" DESTINATION "${ICONSDIR}/hicolor/128x128/apps" RENAME rawtherapee.png)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/images/png/rawtherapee-logo-256.png" DESTINATION "${ICONSDIR}/hicolor/256x256/apps" RENAME rawtherapee.png)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/images/svg/rt-logo.svg" DESTINATION "${ICONSDIR}/hicolor/scalable/apps" RENAME rawtherapee.svg)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/images/rt-logo.svg" DESTINATION "${ICONSDIR}/hicolor/scalable/apps" RENAME rawtherapee.svg)
endif()
install(FILES ${LANGUAGEFILES} DESTINATION "${DATADIR}/languages")

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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 843 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 56 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 56 KiB

655
rtdata/images/rt-logo.svg Normal file
View File

@ -0,0 +1,655 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="52.187881mm"
height="52.187881mm"
viewBox="0 0 197.24555 197.24552"
version="1.1"
id="svg783"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
sodipodi:docname="rt-logo.svg"
inkscape:export-filename="C:\msys64\home\Roel\RawTherapee\rtdata\images\png\rawtherapee-logo-256.png"
inkscape:export-xdpi="124.59598"
inkscape:export-ydpi="124.59598"
style="enable-background:new"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<title
id="title89">RawTherapee Logo</title>
<defs
id="defs777">
<linearGradient
id="linearGradient3962-8">
<stop
id="stop3964-8"
offset="0"
style="stop-color:#38c102;stop-opacity:1" />
<stop
id="stop3966-8"
offset="1"
style="stop-color:#bced02;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3954-7">
<stop
id="stop3956-7"
offset="0"
style="stop-color:#009a01;stop-opacity:1" />
<stop
id="stop3958-6"
offset="1"
style="stop-color:#01d901;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient4002-3"
inkscape:collect="always">
<stop
id="stop4004-0"
offset="0"
style="stop-color:#5a1898;stop-opacity:1" />
<stop
id="stop4006-3"
offset="1"
style="stop-color:#971ec6;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient4024-9">
<stop
id="stop4026-2"
offset="0"
style="stop-color:#053980;stop-opacity:1" />
<stop
id="stop4028-5"
offset="1"
style="stop-color:#0293e4;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient4018-0"
inkscape:collect="always">
<stop
id="stop4020-5"
offset="0"
style="stop-color:#151b92;stop-opacity:1" />
<stop
id="stop4022-9"
offset="1"
style="stop-color:#1526c3;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient3978-6">
<stop
style="stop-color:#f18e01;stop-opacity:1;"
offset="0"
id="stop4040-9" />
<stop
id="stop3982-2"
offset="1"
style="stop-color:#ffd02b;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3994-4"
inkscape:collect="always">
<stop
id="stop3996-7"
offset="0"
style="stop-color:#d91566;stop-opacity:1" />
<stop
id="stop3998-7"
offset="1"
style="stop-color:#fc12aa;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient3970-4">
<stop
id="stop3972-8"
offset="0"
style="stop-color:#f8bc00;stop-opacity:1;" />
<stop
id="stop3974-1"
offset="1"
style="stop-color:#ffe309;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3946-8">
<stop
id="stop3948-9"
offset="0"
style="stop-color:#0193be;stop-opacity:1;" />
<stop
id="stop3950-3"
offset="1"
style="stop-color:#01d4ed;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3986-8">
<stop
id="stop3988-0"
offset="0"
style="stop-color:#fd4c0b;stop-opacity:1" />
<stop
id="stop3990-2"
offset="1"
style="stop-color:#feab27;stop-opacity:1;" />
</linearGradient>
<filter
id="filter4905-0"
x="0"
y="0"
width="1"
height="1"
inkscape:label="ring inset lightness-contrast"
inkscape:menu="Color"
inkscape:menu-tooltip="Increase or decrease lightness and contrast"
style="color-interpolation-filters:sRGB">
<feFlood
id="feFlood4907-7"
result="result1"
flood-opacity="0"
flood-color="rgb(255,255,255)" />
<feBlend
id="feBlend4909-8"
in2="SourceGraphic"
mode="normal"
result="result2" />
<feComposite
id="feComposite4911-6"
in2="SourceGraphic"
k2="1.2"
operator="arithmetic"
result="result3"
k1="0"
k4="0.2"
k3="0" />
<feComposite
id="feComposite4913-88"
in2="SourceGraphic"
operator="in" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3986-8"
id="linearGradient7477"
x1="226.75093"
y1="39.7075"
x2="188.64473"
y2="77.343597"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3978-6"
id="linearGradient7759"
x1="249.71877"
y1="79.683319"
x2="197.60223"
y2="93.622879"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3970-4"
id="linearGradient7767"
x1="249.90581"
y1="125.98007"
x2="197.72298"
y2="111.61357"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3962-8"
id="linearGradient10819"
x1="186.45189"
y1="188.78058"
x2="172.53987"
y2="136.40414"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3954-7"
id="linearGradient10827"
x1="140.57898"
y1="188.96413"
x2="154.49196"
y2="135.54562"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3946-8"
id="linearGradient10835"
x1="99.718773"
y1="165.33376"
x2="138.70259"
y2="126.9732"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4024-9"
id="linearGradient10843"
x1="76.875038"
y1="125.39568"
x2="129.98044"
y2="111.2607"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4018-0"
id="linearGradient10851"
x1="77.518173"
y1="79.568878"
x2="130.19432"
y2="93.55809"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4002-3"
id="linearGradient10859"
x1="100.42588"
y1="39.737522"
x2="138.96776"
y2="78.363228"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3994-4"
id="linearGradient10867"
x1="140.49059"
y1="16.437004"
x2="154.79814"
y2="69.879189"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3986-8"
id="linearGradient19153"
x1="208.75566"
y1="23.213453"
x2="243.28401"
y2="57.596519"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3978-6"
id="linearGradient19161"
x1="240.19098"
y1="48.687042"
x2="256.26306"
y2="106.95491"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3970-4"
id="linearGradient19169"
x1="254.64981"
y1="101.84784"
x2="242.17578"
y2="148.77542"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3962-8"
id="linearGradient19177"
x1="163.02301"
y1="193.83618"
x2="209.80595"
y2="181.05989"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3954-7"
id="linearGradient19185"
x1="117.51535"
y1="181.72815"
x2="164.49129"
y2="194.03969"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3946-8"
id="linearGradient19193"
x1="84.229202"
y1="147.87372"
x2="118.57832"
y2="182.1684"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4024-9"
id="linearGradient19201"
x1="71.600014"
y1="98.586967"
x2="86.637268"
y2="153.3033"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4018-0"
id="linearGradient19209"
x1="85.458618"
y1="53.097939"
x2="71.537453"
y2="106.59224"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4002-3"
id="linearGradient19217"
x1="80.822929"
y1="61.417603"
x2="120.4325"
y2="21.283628"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3994-4"
id="linearGradient19225"
x1="167.3401"
y1="10.365549"
x2="113.41623"
y2="24.735945"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-15,802.43241,-1.9489591)" />
<filter
width="1.0919776"
height="1.3006796"
y="-0.15033983"
x="-0.04598882"
inkscape:label="RawTherapee white"
id="filter4749"
style="color-interpolation-filters:sRGB">
<feFlood
result="flood"
flood-color="rgb(255,255,255)"
flood-opacity="0.40000000000000002"
id="feFlood4751" />
<feComposite
result="composite1"
operator="in"
in="flood"
in2="SourceGraphic"
id="feComposite4753" />
<feGaussianBlur
result="blur"
stdDeviation="3.5"
id="feGaussianBlur4755" />
<feComposite
result="composite2"
operator="over"
in="SourceGraphic"
in2="blur"
id="feComposite4757" />
</filter>
<filter
width="1.4157329"
height="1.5012363"
y="-0.25061816"
x="-0.20786646"
inkscape:label="RawTherapee white"
id="filter1105"
style="color-interpolation-filters:sRGB">
<feFlood
result="flood"
flood-color="rgb(255,255,255)"
flood-opacity="0.40000000000000002"
id="feFlood1097" />
<feComposite
result="composite1"
operator="in"
in="flood"
in2="SourceGraphic"
id="feComposite1099" />
<feGaussianBlur
result="blur"
stdDeviation="3.5"
id="feGaussianBlur1101" />
<feComposite
result="composite2"
operator="over"
in="SourceGraphic"
in2="blur"
id="feComposite1103" />
</filter>
<filter
inkscape:menu-tooltip="Increase or decrease lightness and contrast"
inkscape:menu="Color"
inkscape:label="ring inset lightness-contrast"
height="1.0019884"
width="1.0017145"
y="-0.0011311892"
x="-0.00085726596"
id="filter4905-0-1"
style="color-interpolation-filters:sRGB">
<feFlood
flood-color="rgb(255,255,255)"
flood-opacity="0"
result="result1"
id="feFlood4907-6" />
<feBlend
result="result2"
mode="normal"
in2="SourceGraphic"
id="feBlend4909-2" />
<feComposite
k3="0"
k4="0.2"
k1="0"
result="result3"
operator="arithmetic"
k2="1.2"
in2="SourceGraphic"
id="feComposite4911-6-0" />
<feComposite
operator="in"
in2="SourceGraphic"
id="feComposite4913-1" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.0000001"
inkscape:cx="128"
inkscape:cy="77.124998"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="mm"
inkscape:snap-bbox="true"
inkscape:bbox-nodes="true"
inkscape:snap-page="false"
inkscape:snap-text-baseline="false"
inkscape:snap-center="false"
inkscape:snap-object-midpoints="true"
inkscape:snap-midpoints="false"
inkscape:snap-smooth-nodes="false"
inkscape:snap-intersection-paths="false"
inkscape:object-paths="false"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-bbox-edge-midpoints="false"
inkscape:bbox-paths="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-others="true"
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-maximized="1"
inkscape:measure-start="416.334,192.525"
inkscape:measure-end="422.317,192.368"
fit-margin-top="1"
fit-margin-left="1"
fit-margin-right="1"
fit-margin-bottom="1"
scale-x="1"
inkscape:pagecheckerboard="true"
height="52.18788mm" />
<metadata
id="metadata780">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>RawTherapee Logo</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Maciej Dworak</dc:title>
</cc:Agent>
</dc:creator>
<dc:source>www.rawtherapee.com</dc:source>
<dc:date>2019-03-11</dc:date>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-113.83346,-165.7737)">
<g
id="g1471">
<path
id="path1157"
style="fill:url(#linearGradient19169);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter4905-0)"
d="m 294.18353,286.29588 8.89675,2.38406 a 93.821518,93.821518 0 0 0 2.4e-4,-48.56705 l -8.71031,2.33392 a 84.803757,84.803757 0 0 1 2.29016,11.88245 84.803757,84.803757 0 0 1 0.57521,12.08518 84.803757,84.803757 0 0 1 -1.14997,12.04599 84.803757,84.803757 0 0 1 -1.90208,7.83545 z" />
<path
id="path4829"
style="fill:url(#linearGradient7767);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round"
d="m 294.18353,286.29588 a 84.803757,84.803757 0 0 0 1.90208,-7.83545 84.803757,84.803757 0 0 0 1.14997,-12.04599 84.803757,84.803757 0 0 0 -0.57521,-12.08518 84.803757,84.803757 0 0 0 -2.29016,-11.88245 l -43.24405,11.5872 a 40.033501,40.033501 0 0 1 -0.0886,20.70095 z" />
<path
id="path1341"
style="fill:#fffb00;fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter4905-0)"
d="m 272.28532,324.2247 6.51303,6.51278 a 93.821518,93.821518 0 0 0 24.28193,-42.05754 l -8.89675,-2.38406 a 84.803757,84.803757 0 0 1 -0.95072,3.9227 84.803757,84.803757 0 0 1 -4.49616,11.23195 84.803757,84.803757 0 0 1 -6.05046,10.4797 84.803757,84.803757 0 0 1 -7.47908,9.50977 84.803757,84.803757 0 0 1 -2.92179,2.7847 z" />
<path
id="path4832"
style="fill:#fffb00;fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round"
d="m 272.28532,324.2247 a 84.803757,84.803757 0 0 0 2.92179,-2.7847 84.803757,84.803757 0 0 0 7.47908,-9.50977 84.803757,84.803757 0 0 0 6.05046,-10.4797 84.803757,84.803757 0 0 0 4.49616,-11.23195 84.803757,84.803757 0 0 0 0.95072,-3.9227 l -43.14595,-11.56092 a 40.033501,40.033501 0 0 1 -10.33729,17.90471 z" />
<path
id="path1547"
style="fill:url(#linearGradient19177);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter4905-0)"
d="m 234.40424,346.3109 2.33393,8.71032 a 93.821518,93.821518 0 0 0 42.06018,-24.28374 l -6.51303,-6.51278 a 84.803757,84.803757 0 0 1 -5.83466,5.56497 84.803757,84.803757 0 0 1 -9.85715,7.0189 84.803757,84.803757 0 0 1 -10.75367,5.54444 84.803757,84.803757 0 0 1 -11.4356,3.95789 z" />
<path
id="path4835"
style="fill:url(#linearGradient10819);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round"
d="m 234.40424,346.3109 a 84.803757,84.803757 0 0 0 11.4356,-3.95789 84.803757,84.803757 0 0 0 10.75367,-5.54444 84.803757,84.803757 0 0 0 9.85715,-7.0189 84.803757,84.803757 0 0 0 5.83466,-5.56497 l -31.58503,-31.58503 a 40.033501,40.033501 0 0 1 -17.88325,10.42719 z" />
<path
id="path1753"
style="fill:url(#linearGradient19185);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter4905-0)"
d="m 190.55705,346.12372 -2.38405,8.89675 a 93.821518,93.821518 0 0 0 48.56517,7.5e-4 l -2.33393,-8.71032 a 84.803757,84.803757 0 0 1 -11.88057,2.28966 84.803757,84.803757 0 0 1 -12.08519,0.57522 84.803757,84.803757 0 0 1 -12.04598,-1.14998 84.803757,84.803757 0 0 1 -7.83545,-1.90208 z" />
<path
id="path4838"
style="fill:url(#linearGradient10827);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round"
d="m 190.55705,346.12372 a 84.803757,84.803757 0 0 0 7.83545,1.90208 84.803757,84.803757 0 0 0 12.04598,1.14998 84.803757,84.803757 0 0 0 12.08519,-0.57522 84.803757,84.803757 0 0 0 11.88057,-2.28966 l -11.5872,-43.24404 a 40.033501,40.033501 0 0 1 -20.69907,-0.0891 z" />
<path
id="path1857"
style="fill:url(#linearGradient19193);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter4905-0)"
d="m 152.62823,324.22551 -6.51278,6.51303 a 93.821518,93.821518 0 0 0 42.05755,24.28193 l 2.38405,-8.89675 a 84.803757,84.803757 0 0 1 -3.9227,-0.95072 84.803757,84.803757 0 0 1 -11.23196,-4.49616 84.803757,84.803757 0 0 1 -10.4797,-6.05046 84.803757,84.803757 0 0 1 -9.50976,-7.47907 84.803757,84.803757 0 0 1 -2.7847,-2.9218 z" />
<path
id="path4841"
style="fill:url(#linearGradient10835);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round"
d="m 152.62823,324.22551 a 84.803757,84.803757 0 0 0 2.7847,2.9218 84.803757,84.803757 0 0 0 9.50976,7.47907 84.803757,84.803757 0 0 0 10.4797,6.05046 84.803757,84.803757 0 0 0 11.23196,4.49616 84.803757,84.803757 0 0 0 3.9227,0.95072 l 11.56092,-43.14594 a 40.033501,40.033501 0 0 1 -17.90472,-10.3373 z" />
<path
id="path1961"
style="fill:url(#linearGradient19201);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter4905-0)"
d="m 130.54202,286.34444 -8.71031,2.33392 a 93.821518,93.821518 0 0 0 24.28374,42.06018 l 6.51278,-6.51303 a 84.803757,84.803757 0 0 1 -5.56497,-5.83466 84.803757,84.803757 0 0 1 -7.0189,-9.85715 84.803757,84.803757 0 0 1 -5.54444,-10.75367 84.803757,84.803757 0 0 1 -3.9579,-11.43559 z" />
<path
id="path4844"
style="fill:url(#linearGradient10843);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round"
d="m 130.54202,286.34444 a 84.803757,84.803757 0 0 0 3.9579,11.43559 84.803757,84.803757 0 0 0 5.54444,10.75367 84.803757,84.803757 0 0 0 7.0189,9.85715 84.803757,84.803757 0 0 0 5.56497,5.83466 l 31.58502,-31.58503 a 40.033501,40.033501 0 0 1 -10.42718,-17.88325 z" />
<path
id="path2065"
style="fill:url(#linearGradient19209);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter4905-0)"
d="m 130.72921,242.49724 -8.89675,-2.38405 a 93.821518,93.821518 0 0 0 -7.5e-4,48.56517 l 8.71031,-2.33392 a 84.803757,84.803757 0 0 1 -2.28965,-11.88058 84.803757,84.803757 0 0 1 -0.57521,-12.08518 84.803757,84.803757 0 0 1 1.14997,-12.04599 84.803757,84.803757 0 0 1 1.90208,-7.83545 z" />
<path
id="path4847"
style="fill:url(#linearGradient10851);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round"
d="m 130.72921,242.49724 a 84.803757,84.803757 0 0 0 -1.90208,7.83545 84.803757,84.803757 0 0 0 -1.14997,12.04599 84.803757,84.803757 0 0 0 0.57521,12.08518 84.803757,84.803757 0 0 0 2.28965,11.88058 l 43.24405,-11.58721 a 40.033501,40.033501 0 0 1 0.0891,-20.69907 z" />
<path
id="path2169"
style="fill:url(#linearGradient19217);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter4905-0)"
d="m 152.62742,204.56842 -6.51302,-6.51278 a 93.821518,93.821518 0 0 0 -24.28194,42.05755 l 8.89675,2.38405 a 84.803757,84.803757 0 0 1 0.95072,-3.92269 84.803757,84.803757 0 0 1 4.49616,-11.23196 84.803757,84.803757 0 0 1 6.05045,-10.4797 84.803757,84.803757 0 0 1 7.47909,-9.50977 84.803757,84.803757 0 0 1 2.92179,-2.7847 z" />
<path
id="path4850"
style="fill:url(#linearGradient10859);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round"
d="m 152.62742,204.56842 a 84.803757,84.803757 0 0 0 -2.92179,2.7847 84.803757,84.803757 0 0 0 -7.47909,9.50977 84.803757,84.803757 0 0 0 -6.05045,10.4797 84.803757,84.803757 0 0 0 -4.49616,11.23196 84.803757,84.803757 0 0 0 -0.95072,3.92269 l 43.14594,11.56092 a 40.033501,40.033501 0 0 1 10.33729,-17.90471 z" />
<path
id="path2377"
style="fill:url(#linearGradient10867);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round"
d="m 190.50661,182.48272 a 84.803757,84.803757 0 0 0 -11.4337,3.95739 84.803757,84.803757 0 0 0 -10.75369,5.54444 84.803757,84.803757 0 0 0 -9.85714,7.0189 84.803757,84.803757 0 0 0 -5.83466,5.56497 l 31.58502,31.58503 a 40.033501,40.033501 0 0 1 17.88138,-10.42668 z" />
<path
id="path4853"
style="fill:url(#linearGradient19225);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter4905-0)"
d="m 188.17269,173.77241 a 93.821518,93.821518 0 0 0 -42.05829,24.28323 l 6.51302,6.51278 a 84.803757,84.803757 0 0 1 5.83466,-5.56497 84.803757,84.803757 0 0 1 9.85714,-7.0189 84.803757,84.803757 0 0 1 10.75369,-5.54444 84.803757,84.803757 0 0 1 11.4337,-3.95739 z" />
<path
id="path2481"
style="fill:#ff0b0d;fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round"
d="m 234.40028,182.50378 a 84.803757,84.803757 0 0 0 -2.68754,-0.69529 84.803757,84.803757 0 0 0 -4.07443,-0.84536 84.803757,84.803757 0 0 0 -4.11369,-0.64477 84.803757,84.803757 0 0 0 -4.13823,-0.44206 84.803757,84.803757 0 0 0 -4.15611,-0.23708 84.803757,84.803757 0 0 0 -4.16076,-0.0357 84.803757,84.803757 0 0 0 -4.16015,0.17042 84.803757,84.803757 0 0 0 -4.1458,0.37485 84.803757,84.803757 0 0 0 -4.12205,0.57675 84.803757,84.803757 0 0 0 -4.08833,0.77801 84.803757,84.803757 0 0 0 -4.04658,0.97913 l 11.58721,43.24405 a 40.033501,40.033501 0 0 1 20.72361,-4e-4 z" />
<path
id="path4798"
style="fill:#ff0b0d;fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter4905-0)"
d="m 188.17269,173.77241 2.33392,8.71031 a 84.803757,84.803757 0 0 1 4.04658,-0.97913 84.803757,84.803757 0 0 1 4.08833,-0.77801 84.803757,84.803757 0 0 1 4.12205,-0.57675 84.803757,84.803757 0 0 1 4.1458,-0.37485 84.803757,84.803757 0 0 1 4.16015,-0.17042 84.803757,84.803757 0 0 1 4.16076,0.0357 84.803757,84.803757 0 0 1 4.15611,0.23708 84.803757,84.803757 0 0 1 4.13823,0.44206 84.803757,84.803757 0 0 1 4.11369,0.64477 84.803757,84.803757 0 0 1 4.07443,0.84536 84.803757,84.803757 0 0 1 2.68754,0.69529 l 2.33947,-8.73113 a 93.821518,93.821518 0 0 0 -48.56706,-2.4e-4 z" />
<path
id="path2585"
style="fill:url(#linearGradient19153);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter4905-0)"
d="m 272.40565,204.44619 6.39164,-6.3916 a 93.821518,93.821518 0 0 0 -42.05754,-24.28194 l -2.33947,8.73113 a 84.803757,84.803757 0 0 1 1.34283,0.3479 84.803757,84.803757 0 0 1 3.97211,1.24078 84.803757,84.803757 0 0 1 3.90717,1.43612 84.803757,84.803757 0 0 1 3.83217,1.62405 84.803757,84.803757 0 0 1 3.74859,1.81022 84.803757,84.803757 0 0 1 3.65546,1.99088 84.803757,84.803757 0 0 1 3.55187,2.17028 84.803757,84.803757 0 0 1 3.44149,2.33938 84.803757,84.803757 0 0 1 3.32256,2.50673 84.803757,84.803757 0 0 1 3.19592,2.66804 84.803757,84.803757 0 0 1 3.06249,2.81905 84.803757,84.803757 0 0 1 0.97271,0.98898 z" />
<path
id="path4823"
style="fill:url(#linearGradient7477);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round"
d="m 272.40565,204.44619 a 84.803757,84.803757 0 0 0 -0.97271,-0.98898 84.803757,84.803757 0 0 0 -3.06249,-2.81905 84.803757,84.803757 0 0 0 -3.19592,-2.66804 84.803757,84.803757 0 0 0 -3.32256,-2.50673 84.803757,84.803757 0 0 0 -3.44149,-2.33938 84.803757,84.803757 0 0 0 -3.55187,-2.17028 84.803757,84.803757 0 0 0 -3.65546,-1.99088 84.803757,84.803757 0 0 0 -3.74859,-1.81022 84.803757,84.803757 0 0 0 -3.83217,-1.62405 84.803757,84.803757 0 0 0 -3.90717,-1.43612 84.803757,84.803757 0 0 0 -3.97211,-1.24078 84.803757,84.803757 0 0 0 -1.34283,-0.3479 l -11.58597,43.23354 a 40.033501,40.033501 0 0 1 17.94059,10.35801 z" />
<path
id="path2689"
style="fill:url(#linearGradient19161);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter4905-0)"
d="m 294.37021,242.44681 8.71031,-2.33392 a 93.821518,93.821518 0 0 0 -24.28323,-42.0583 l -6.39164,6.3916 a 84.803757,84.803757 0 0 1 1.94591,1.97984 84.803757,84.803757 0 0 1 2.76932,3.10587 84.803757,84.803757 0 0 1 2.61472,3.23829 84.803757,84.803757 0 0 1 2.45245,3.36467 84.803757,84.803757 0 0 1 2.28287,3.47886 84.803757,84.803757 0 0 1 2.11177,3.58739 84.803757,84.803757 0 0 1 1.93249,3.688 84.803757,84.803757 0 0 1 1.74777,3.77592 84.803757,84.803757 0 0 1 1.56204,3.86005 84.803757,84.803757 0 0 1 1.37039,3.92961 84.803757,84.803757 0 0 1 1.17483,3.99212 z" />
<path
id="path4826"
style="fill:url(#linearGradient7759);fill-opacity:1;stroke-width:0.682085;stroke-linecap:round;stroke-linejoin:round"
d="m 294.37021,242.44681 a 84.803757,84.803757 0 0 0 -1.17483,-3.99212 84.803757,84.803757 0 0 0 -1.37039,-3.92961 84.803757,84.803757 0 0 0 -1.56204,-3.86005 84.803757,84.803757 0 0 0 -1.74777,-3.77592 84.803757,84.803757 0 0 0 -1.93249,-3.688 84.803757,84.803757 0 0 0 -2.11177,-3.58739 84.803757,84.803757 0 0 0 -2.28287,-3.47886 84.803757,84.803757 0 0 0 -2.45245,-3.36467 84.803757,84.803757 0 0 0 -2.61472,-3.23829 84.803757,84.803757 0 0 0 -2.76932,-3.10587 84.803757,84.803757 0 0 0 -1.94591,-1.97984 l -31.64233,31.64284 a 40.033501,40.033501 0 0 1 10.36284,17.94498 z" />
<circle
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.33333;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle4294"
cx="136.78612"
cy="310.37509"
r="40.033501"
transform="rotate(-15)" />
<circle
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:2.66667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4028"
cx="136.78612"
cy="310.37509"
r="93.821518"
transform="rotate(-15)" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -1,609 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64.46769"
height="64.467697"
viewBox="0 0 64.46769 64.467696"
version="1.1"
id="svg783"
inkscape:version="0.92.2 2405546, 2018-03-11"
sodipodi:docname="rt-logo.svg"
inkscape:export-filename="/tmp/rawtherapee-logo-256.png"
inkscape:export-xdpi="381.21423"
inkscape:export-ydpi="381.21423"
style="enable-background:new">
<title
id="title89">RawTherapee logo</title>
<defs
id="defs777">
<linearGradient
id="linearGradient3962-8">
<stop
id="stop3964-8"
offset="0"
style="stop-color:#38c102;stop-opacity:1" />
<stop
id="stop3966-8"
offset="1"
style="stop-color:#bced02;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3954-7">
<stop
id="stop3956-7"
offset="0"
style="stop-color:#009a01;stop-opacity:1" />
<stop
id="stop3958-6"
offset="1"
style="stop-color:#01d901;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient4002-3"
inkscape:collect="always">
<stop
id="stop4004-0"
offset="0"
style="stop-color:#5a1898;stop-opacity:1" />
<stop
id="stop4006-3"
offset="1"
style="stop-color:#971ec6;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient4024-9">
<stop
id="stop4026-2"
offset="0"
style="stop-color:#053980;stop-opacity:1" />
<stop
id="stop4028-5"
offset="1"
style="stop-color:#0293e4;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient4018-0"
inkscape:collect="always">
<stop
id="stop4020-5"
offset="0"
style="stop-color:#151b92;stop-opacity:1" />
<stop
id="stop4022-9"
offset="1"
style="stop-color:#1526c3;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient3978-6">
<stop
style="stop-color:#f18e01;stop-opacity:1;"
offset="0"
id="stop4040-9" />
<stop
id="stop3982-2"
offset="1"
style="stop-color:#ffd02b;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3994-4"
inkscape:collect="always">
<stop
id="stop3996-7"
offset="0"
style="stop-color:#d91566;stop-opacity:1" />
<stop
id="stop3998-7"
offset="1"
style="stop-color:#fc12aa;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient3970-4">
<stop
id="stop3972-8"
offset="0"
style="stop-color:#f8bc00;stop-opacity:1;" />
<stop
id="stop3974-1"
offset="1"
style="stop-color:#ffe309;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3946-8">
<stop
id="stop3948-9"
offset="0"
style="stop-color:#0193be;stop-opacity:1;" />
<stop
id="stop3950-3"
offset="1"
style="stop-color:#01d4ed;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3986-8">
<stop
id="stop3988-0"
offset="0"
style="stop-color:#fd4c0b;stop-opacity:1" />
<stop
id="stop3990-2"
offset="1"
style="stop-color:#feab27;stop-opacity:1;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3978-6"
id="linearGradient6584"
x1="311.50415"
y1="170.17421"
x2="239.55922"
y2="172.53203"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3970-4"
id="linearGradient6592"
x1="309.89517"
y1="205.34961"
x2="250.14594"
y2="206.56822"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3962-8"
id="linearGradient6600"
x1="255.66684"
y1="289.47989"
x2="228.84343"
y2="242.79517"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3954-7"
id="linearGradient6536"
x1="226.94818"
y1="311.5441"
x2="203.56046"
y2="247.99712"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3946-8"
id="linearGradient6544"
x1="155.04362"
y1="291.98077"
x2="196.8688"
y2="242.92572"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4024-9"
id="linearGradient6552"
x1="121.99204"
y1="254.89784"
x2="172.34001"
y2="224.42828"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4018-0"
id="linearGradient6560"
x1="28.951002"
y1="87.129852"
x2="42.548061"
y2="86.547829"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(77.746712,77.956383)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4002-3"
id="linearGradient6568"
x1="127.4337"
y1="150.63391"
x2="164.38599"
y2="186.60429"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3994-4"
id="linearGradient6576"
x1="156.03696"
y1="121.53358"
x2="182.59938"
y2="166.47519"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3986-8"
id="linearGradient6506"
x1="254.73129"
y1="120.67714"
x2="221.8271"
y2="167.72273"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3978-6"
id="linearGradient6720"
x1="273.82266"
y1="127.06858"
x2="304.14511"
y2="182.71349"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<filter
id="filter4905-0"
x="-0.5"
y="-0.5"
width="2"
height="2"
inkscape:label="ring inset lightness-contrast"
inkscape:menu="Color"
inkscape:menu-tooltip="Increase or decrease lightness and contrast"
style="color-interpolation-filters:sRGB">
<feFlood
id="feFlood4907-7"
result="result1"
flood-opacity="0"
flood-color="rgb(255,255,255)" />
<feBlend
id="feBlend4909-8"
in2="SourceGraphic"
mode="normal"
result="result2" />
<feComposite
id="feComposite4911-6"
in2="SourceGraphic"
k2="1.2"
operator="arithmetic"
result="result3"
k1="0"
k4="0.2"
k3="0" />
<feComposite
id="feComposite4913-88"
in2="SourceGraphic"
operator="in" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3970-4"
id="linearGradient6718"
x1="304.40735"
y1="169.7298"
x2="305.57675"
y2="235.63695"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3962-8"
id="linearGradient6714"
x1="223.82266"
y1="301.22165"
x2="281.22165"
y2="272.06857"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3954-7"
id="linearGradient6712"
x1="170.31453"
y1="306.74612"
x2="244.40735"
y2="307.33081"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3946-8"
id="linearGradient6710"
x1="128.56046"
y1="269.99203"
x2="189.40738"
y2="308.23798"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4024-9"
id="linearGradient6708"
x1="108.82266"
y1="218.56042"
x2="142.97575"
y2="285.31448"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4018-0"
id="linearGradient6706"
x1="113.82269"
y1="240.89919"
x2="110.89922"
y2="173.23796"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4002-3"
id="linearGradient6704"
x1="108.23797"
y1="187.97572"
x2="140.31453"
y2="128.82266"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3994-4"
id="linearGradient6702"
x1="187.39107"
y1="105.89919"
x2="126.80637"
y2="140.89919"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3986-8"
id="linearGradient6698"
x1="222.65326"
y1="102.97572"
x2="287.33084"
y2="139.7298"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(293.84585,294.63829)" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="12.781595"
inkscape:cx="19.833202"
inkscape:cy="32.233849"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-nodes="true"
inkscape:snap-page="false"
inkscape:snap-text-baseline="false"
inkscape:snap-center="false"
inkscape:snap-object-midpoints="true"
inkscape:snap-midpoints="false"
inkscape:snap-smooth-nodes="false"
inkscape:snap-intersection-paths="false"
inkscape:object-paths="false"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-bbox-edge-midpoints="false"
inkscape:bbox-paths="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-others="true"
inkscape:object-nodes="false"
inkscape:snap-nodes="true"
inkscape:snap-global="false"
inkscape:window-width="1920"
inkscape:window-height="1021"
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"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
scale-x="1"
inkscape:pagecheckerboard="true" />
<metadata
id="metadata780">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>RawTherapee logo</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Maciej Dworak</dc:title>
</cc:Agent>
</dc:creator>
<dc:source>www.rawtherapee.com</dc:source>
<dc:date>2019-03-11</dc:date>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-40.854412,-228.47746)">
<g
id="g171">
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.945282,124.70558)"
id="path6498"
d="m 543.25,487.63477 48.31055,-12.94532 a 94.999997,94.999997 0 0 0 -0.0234,-0.10156 94.999997,94.999997 0 0 0 -2.99414,-9.01172 94.999997,94.999997 0 0 0 -3.87891,-8.66797 94.999997,94.999997 0 0 0 -4.72461,-8.23632 94.999997,94.999997 0 0 0 -5.52343,-7.72461 94.999997,94.999997 0 0 0 -6.26758,-7.13477 94.999997,94.999997 0 0 0 -1.69727,-1.58203 l -35.33398,35.33398 a 44.999999,44.999999 0 0 1 1.16406,1.08399 44.999999,44.999999 0 0 1 2.96875,3.3789 44.999999,44.999999 0 0 1 2.61719,3.65821 44.999999,44.999999 0 0 1 2.23633,3.90234 44.999999,44.999999 0 0 1 1.83789,4.10547 44.999999,44.999999 0 0 1 1.30859,3.94141 z"
style="fill:url(#linearGradient6584);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6496"
d="m 543.53906,511.14844 48.24024,12.92578 a 94.999997,94.999997 0 0 0 1.32617,-5.20117 94.999997,94.999997 0 0 0 1.41992,-9.38867 A 94.999997,94.999997 0 0 0 595,500 a 94.999997,94.999997 0 0 0 -0.23828,-6.7207 94.999997,94.999997 0 0 0 -1.14453,-9.42578 94.999997,94.999997 0 0 0 -2.05664,-9.16407 L 543.25,487.63477 a 44.999999,44.999999 0 0 1 0.10938,0.32812 44.999999,44.999999 0 0 1 0.98632,4.38867 44.999999,44.999999 0 0 1 0.54102,4.46485 A 44.999999,44.999999 0 0 1 545,500 a 44.999999,44.999999 0 0 1 -0.22461,4.49219 44.999999,44.999999 0 0 1 -0.67187,4.44726 44.999999,44.999999 0 0 1 -0.56446,2.20899 z"
style="fill:url(#linearGradient6592);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6494"
d="m 531.9707,531.61719 35.33399,35.33398 a 94.999997,94.999997 0 0 0 5.35547,-5.75 94.999997,94.999997 0 0 0 5.74609,-7.56055 94.999997,94.999997 0 0 0 4.96484,-8.0957 94.999997,94.999997 0 0 0 4.12891,-8.55078 94.999997,94.999997 0 0 0 3.25781,-8.91992 94.999997,94.999997 0 0 0 1.02149,-4 l -48.24024,-12.92578 a 44.999999,44.999999 0 0 1 -0.54883,2.15039 44.999999,44.999999 0 0 1 -1.54296,4.22461 44.999999,44.999999 0 0 1 -1.95508,4.05078 44.999999,44.999999 0 0 1 -2.35157,3.83398 44.999999,44.999999 0 0 1 -2.72265,3.58203 44.999999,44.999999 0 0 1 -2.44727,2.62696 z"
style="fill:#fffb00;fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6492"
d="m 511.70703,543.43359 12.93555,48.27539 a 94.999997,94.999997 0 0 0 0.76953,-0.17187 94.999997,94.999997 0 0 0 9.01172,-2.99414 94.999997,94.999997 0 0 0 8.66797,-3.87891 94.999997,94.999997 0 0 0 8.23632,-4.72461 94.999997,94.999997 0 0 0 7.72461,-5.52343 94.999997,94.999997 0 0 0 7.13477,-6.26758 94.999997,94.999997 0 0 0 1.11719,-1.19727 L 531.9707,531.61719 a 44.999999,44.999999 0 0 1 -0.61914,0.66406 44.999999,44.999999 0 0 1 -3.3789,2.96875 44.999999,44.999999 0 0 1 -3.65821,2.61523 44.999999,44.999999 0 0 1 -3.90234,2.23829 44.999999,44.999999 0 0 1 -4.10547,1.83789 44.999999,44.999999 0 0 1 -4.26953,1.41797 44.999999,44.999999 0 0 1 -0.33008,0.0742 z"
style="fill:url(#linearGradient6600);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6490"
d="m 488.36719,543.41602 -12.92578,48.23828 a 94.999997,94.999997 0 0 0 5.68554,1.45117 94.999997,94.999997 0 0 0 9.38867,1.41992 A 94.999997,94.999997 0 0 0 500,595 a 94.999997,94.999997 0 0 0 6.7207,-0.23828 94.999997,94.999997 0 0 0 9.42578,-1.14453 94.999997,94.999997 0 0 0 8.4961,-1.90821 l -12.93555,-48.27539 a 44.999999,44.999999 0 0 1 -4.05859,0.91211 44.999999,44.999999 0 0 1 -4.46485,0.54102 A 44.999999,44.999999 0 0 1 500,545 a 44.999999,44.999999 0 0 1 -4.49219,-0.22461 44.999999,44.999999 0 0 1 -4.44726,-0.67187 44.999999,44.999999 0 0 1 -2.69336,-0.6875 z"
style="fill:url(#linearGradient6536);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6488"
d="m 468.25,531.8457 -35.33398,35.33399 a 94.999997,94.999997 0 0 0 5.88281,5.48047 94.999997,94.999997 0 0 0 7.56055,5.74609 94.999997,94.999997 0 0 0 8.0957,4.96484 94.999997,94.999997 0 0 0 8.55078,4.12891 94.999997,94.999997 0 0 0 8.91992,3.25781 94.999997,94.999997 0 0 0 3.51563,0.89649 l 12.92578,-48.23828 a 44.999999,44.999999 0 0 1 -1.66602,-0.42579 44.999999,44.999999 0 0 1 -4.22461,-1.54296 44.999999,44.999999 0 0 1 -4.05078,-1.95704 44.999999,44.999999 0 0 1 -3.83398,-2.34961 44.999999,44.999999 0 0 1 -3.58203,-2.72265 44.999999,44.999999 0 0 1 -2.75977,-2.57227 z"
style="fill:url(#linearGradient6544);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6486"
d="m 456.60742,511.88672 -48.27734,12.93555 a 94.999997,94.999997 0 0 0 0.13281,0.58984 94.999997,94.999997 0 0 0 2.99414,9.01172 94.999997,94.999997 0 0 0 3.87891,8.66797 94.999997,94.999997 0 0 0 4.72461,8.23632 94.999997,94.999997 0 0 0 5.52343,7.72461 94.999997,94.999997 0 0 0 6.26758,7.13477 94.999997,94.999997 0 0 0 1.06446,0.99219 L 468.25,531.8457 a 44.999999,44.999999 0 0 1 -0.53125,-0.49414 44.999999,44.999999 0 0 1 -2.96875,-3.3789 44.999999,44.999999 0 0 1 -2.61523,-3.65821 44.999999,44.999999 0 0 1 -2.23829,-3.90234 44.999999,44.999999 0 0 1 -1.83789,-4.10547 44.999999,44.999999 0 0 1 -1.41797,-4.26953 44.999999,44.999999 0 0 1 -0.0332,-0.15039 z"
style="fill:url(#linearGradient6552);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
transform="matrix(1.0281074,0,0,1.0281074,-62.765085,91.449911)"
sodipodi:nodetypes="cccccccccccccccc"
inkscape:connector-curvature="0"
id="path6484"
d="m 120.55163,161.65957 -12.76356,-3.41994 c -0.1299,0.45532 -0.2469,0.91421 -0.35088,1.37614 -0.16656,0.82125 -0.29195,1.65032 -0.37569,2.48409 -0.0837,0.83385 -0.12557,1.67137 -0.12557,2.50941 1e-5,0.59328 0.021,1.18638 0.063,1.77818 0.0593,0.83583 0.16037,1.66817 0.30282,2.4939 0.13582,0.77278 0.32632,1.57591 0.53379,2.33261 l 12.79722,-3.42869 c -0.10207,-0.36951 -0.22863,-0.77472 -0.29459,-1.15235 -0.0674,-0.39114 -0.11515,-0.78541 -0.14315,-1.18133 -0.0199,-0.28033 -0.0299,-0.56128 -0.03,-0.84232 -2e-5,-0.39693 0.0198,-0.79361 0.0594,-1.18856 0.0396,-0.39494 0.0989,-0.78766 0.17777,-1.17667 0.0448,-0.19605 0.0946,-0.39094 0.14934,-0.58447 z"
style="fill:url(#linearGradient6560);fill-opacity:1;stroke:none;stroke-width:0.12867495;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6482"
d="m 467.68945,468.75 -35.33398,-35.33398 a 94.999997,94.999997 0 0 0 -5.01563,5.38281 94.999997,94.999997 0 0 0 -5.74609,7.56055 94.999997,94.999997 0 0 0 -4.96484,8.0957 94.999997,94.999997 0 0 0 -4.12891,8.55078 94.999997,94.999997 0 0 0 -3.25781,8.91992 94.999997,94.999997 0 0 0 -1.02149,4 l 48.24024,12.92578 a 44.999999,44.999999 0 0 1 0.54883,-2.15039 44.999999,44.999999 0 0 1 1.54296,-4.22461 44.999999,44.999999 0 0 1 1.95704,-4.05078 44.999999,44.999999 0 0 1 2.34961,-3.83398 44.999999,44.999999 0 0 1 2.72265,-3.58203 44.999999,44.999999 0 0 1 2.10742,-2.25977 z"
style="fill:url(#linearGradient6568);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6480"
d="m 487.45898,456.80859 -12.94531,-48.32031 a 94.999997,94.999997 0 0 0 -8.9375,2.96875 94.999997,94.999997 0 0 0 -8.66797,3.87891 94.999997,94.999997 0 0 0 -8.23632,4.72461 94.999997,94.999997 0 0 0 -7.72461,5.52343 94.999997,94.999997 0 0 0 -7.13477,6.26758 94.999997,94.999997 0 0 0 -1.45703,1.56446 L 467.68945,468.75 a 44.999999,44.999999 0 0 1 0.95899,-1.03125 44.999999,44.999999 0 0 1 3.3789,-2.96875 44.999999,44.999999 0 0 1 3.65821,-2.61523 44.999999,44.999999 0 0 1 3.90234,-2.23829 44.999999,44.999999 0 0 1 4.10547,-1.83789 44.999999,44.999999 0 0 1 3.76562,-1.25 z"
style="fill:url(#linearGradient6576);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6478"
d="m 523.58984,408.09766 a 94.999997,94.999997 0 0 0 -4.71679,-1.20313 94.999997,94.999997 0 0 0 -9.38867,-1.41992 A 94.999997,94.999997 0 0 0 500,405 a 94.999997,94.999997 0 0 0 -6.7207,0.23828 94.999997,94.999997 0 0 0 -9.42578,1.14453 94.999997,94.999997 0 0 0 -9.26563,2.08008 94.999997,94.999997 0 0 0 -0.0742,0.0254 L 487.459,456.8086 a 44.999999,44.999999 0 0 1 0.50391,-0.16797 44.999999,44.999999 0 0 1 4.38867,-0.98632 44.999999,44.999999 0 0 1 4.46485,-0.54102 A 44.999999,44.999999 0 0 1 500,455 a 44.999999,44.999999 0 0 1 4.49219,0.22461 44.999999,44.999999 0 0 1 4.44726,0.67187 44.999999,44.999999 0 0 1 1.72461,0.44141 z"
style="fill:#ff0b0d;fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6427"
d="m 523.58984,408.09766 -12.92578,48.24023 a 44.999999,44.999999 0 0 1 2.63477,0.67188 44.999999,44.999999 0 0 1 4.22461,1.54296 44.999999,44.999999 0 0 1 4.05078,1.95508 44.999999,44.999999 0 0 1 3.83398,2.35157 44.999999,44.999999 0 0 1 3.58203,2.72265 44.999999,44.999999 0 0 1 2.12696,1.98242 l 35.33398,-35.33398 a 94.999997,94.999997 0 0 0 -5.25,-4.89063 94.999997,94.999997 0 0 0 -7.56055,-5.74609 94.999997,94.999997 0 0 0 -8.0957,-4.96484 94.999997,94.999997 0 0 0 -8.55078,-4.12891 94.999997,94.999997 0 0 0 -8.91992,-3.25781 94.999997,94.999997 0 0 0 -4.48438,-1.14453 z"
style="fill:url(#linearGradient6506);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6475"
d="m 591.56055,474.68945 9.55664,-2.56054 a 105,105 0 0 0 -27.55274,-47.01172 l -7.11328,7.11328 a 94.999997,94.999997 0 0 1 1.69727,1.58203 94.999997,94.999997 0 0 1 6.26758,7.13477 94.999997,94.999997 0 0 1 5.52343,7.72461 94.999997,94.999997 0 0 1 4.72461,8.23632 94.999997,94.999997 0 0 1 3.87891,8.66797 94.999997,94.999997 0 0 1 2.99414,9.01172 94.999997,94.999997 0 0 1 0.0234,0.10156 z"
style="fill:url(#linearGradient6720);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4905-0)"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6473"
d="m 591.7793,524.07422 9.71093,2.60156 A 105,105 0 0 0 605,500 105,105 0 0 0 601.11719,472.12891 l -9.55664,2.56054 a 94.999997,94.999997 0 0 1 2.05664,9.16407 94.999997,94.999997 0 0 1 1.14453,9.42578 A 94.999997,94.999997 0 0 1 595,500 a 94.999997,94.999997 0 0 1 -0.47461,9.48438 94.999997,94.999997 0 0 1 -1.41992,9.38867 94.999997,94.999997 0 0 1 -1.32617,5.20117 z"
style="fill:url(#linearGradient6718);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4905-0)"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6471"
d="m 567.30469,566.95117 7.07812,7.07813 a 105,105 0 0 0 27.10742,-47.35352 l -9.71093,-2.60156 a 94.999997,94.999997 0 0 1 -1.02149,4 94.999997,94.999997 0 0 1 -3.25781,8.91992 94.999997,94.999997 0 0 1 -4.12891,8.55078 94.999997,94.999997 0 0 1 -4.96484,8.0957 94.999997,94.999997 0 0 1 -5.74609,7.56055 94.999997,94.999997 0 0 1 -5.35547,5.75 z"
style="fill:#fffb00;fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4905-0)"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6469"
d="m 524.64258,591.70898 2.5664,9.57618 a 105,105 0 0 0 47.17383,-27.25586 l -7.07812,-7.07813 a 94.999997,94.999997 0 0 1 -1.11719,1.19727 94.999997,94.999997 0 0 1 -7.13477,6.26758 94.999997,94.999997 0 0 1 -7.72461,5.52343 94.999997,94.999997 0 0 1 -8.23632,4.72461 94.999997,94.999997 0 0 1 -8.66797,3.87891 94.999997,94.999997 0 0 1 -9.01172,2.99414 94.999997,94.999997 0 0 1 -0.76953,0.17187 z"
style="fill:url(#linearGradient6714);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4905-0)"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6467"
d="m 475.44141,591.6543 -2.60547,9.72656 A 105,105 0 0 0 500,605 a 105,105 0 0 0 27.20898,-3.71484 l -2.5664,-9.57618 a 94.999997,94.999997 0 0 1 -8.4961,1.90821 94.999997,94.999997 0 0 1 -9.42578,1.14453 A 94.999997,94.999997 0 0 1 500,595 a 94.999997,94.999997 0 0 1 -9.48438,-0.47461 94.999997,94.999997 0 0 1 -9.38867,-1.41992 94.999997,94.999997 0 0 1 -5.68554,-1.45117 z"
style="fill:url(#linearGradient6712);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4905-0)"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6465"
d="M 432.91602,567.17969 425.8457,574.25 a 105,105 0 0 0 46.99024,27.13086 l 2.60547,-9.72656 a 94.999997,94.999997 0 0 1 -3.51563,-0.89649 94.999997,94.999997 0 0 1 -8.91992,-3.25781 94.999997,94.999997 0 0 1 -8.55078,-4.12891 94.999997,94.999997 0 0 1 -8.0957,-4.96484 94.999997,94.999997 0 0 1 -7.56055,-5.74609 94.999997,94.999997 0 0 1 -5.88281,-5.48047 z"
style="fill:url(#linearGradient6710);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4905-0)"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6463"
d="m 408.33008,524.82227 -9.57031,2.56445 A 105,105 0 0 0 425.8457,574.25 l 7.07032,-7.07031 a 94.999997,94.999997 0 0 1 -1.06446,-0.99219 94.999997,94.999997 0 0 1 -6.26758,-7.13477 94.999997,94.999997 0 0 1 -5.52343,-7.72461 94.999997,94.999997 0 0 1 -4.72461,-8.23632 94.999997,94.999997 0 0 1 -3.87891,-8.66797 94.999997,94.999997 0 0 1 -2.99414,-9.01172 94.999997,94.999997 0 0 1 -0.13281,-0.58984 z"
style="fill:url(#linearGradient6708);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4905-0)"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6461"
d="m 408.2207,475.92578 -9.71093,-2.60156 A 105,105 0 0 0 395,500 a 105,105 0 0 0 3.75977,27.38672 l 9.57031,-2.56445 a 94.999997,94.999997 0 0 1 -1.94727,-8.67579 94.999997,94.999997 0 0 1 -1.14453,-9.42578 A 94.999997,94.999997 0 0 1 405,500 a 94.999997,94.999997 0 0 1 0.47461,-9.48438 94.999997,94.999997 0 0 1 1.41992,-9.38867 94.999997,94.999997 0 0 1 1.32617,-5.20117 z"
style="fill:url(#linearGradient6706);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4905-0)"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6459"
d="m 432.35547,433.41602 -7.10352,-7.10352 a 105,105 0 0 0 -26.74218,47.01172 l 9.71093,2.60156 a 94.999997,94.999997 0 0 1 1.02149,-4 94.999997,94.999997 0 0 1 3.25781,-8.91992 94.999997,94.999997 0 0 1 4.12891,-8.55078 94.999997,94.999997 0 0 1 4.96484,-8.0957 94.999997,94.999997 0 0 1 5.74609,-7.56055 94.999997,94.999997 0 0 1 5.01563,-5.38281 z"
style="fill:url(#linearGradient6704);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4905-0)"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6457"
d="m 474.51367,408.48828 -2.5625,-9.56055 a 105,105 0 0 0 -46.69922,27.38477 l 7.10352,7.10352 a 94.999997,94.999997 0 0 1 1.45703,-1.56446 94.999997,94.999997 0 0 1 7.13477,-6.26758 94.999997,94.999997 0 0 1 7.72461,-5.52343 94.999997,94.999997 0 0 1 8.23632,-4.72461 94.999997,94.999997 0 0 1 8.66797,-3.87891 94.999997,94.999997 0 0 1 8.9375,-2.96875 z"
style="fill:url(#linearGradient6702);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4905-0)"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6455"
d="M 526.1875,398.40039 A 105,105 0 0 0 500,395 a 105,105 0 0 0 -28.04883,3.92773 l 2.5625,9.56055 a 94.999997,94.999997 0 0 1 0.0742,-0.0254 94.999997,94.999997 0 0 1 9.26563,-2.08008 94.999997,94.999997 0 0 1 9.42578,-1.14453 A 94.999997,94.999997 0 0 1 500,405 a 94.999997,94.999997 0 0 1 9.48438,0.47461 94.999997,94.999997 0 0 1 9.38867,1.41992 94.999997,94.999997 0 0 1 4.71679,1.20313 z"
style="fill:#ff0b0d;fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4905-0)"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27202007,0,0,0.27202007,-62.944889,124.70579)"
id="path6388"
d="m 526.1875,398.40039 -2.59766,9.69727 a 94.999997,94.999997 0 0 1 4.48438,1.14453 94.999997,94.999997 0 0 1 8.91992,3.25781 94.999997,94.999997 0 0 1 8.55078,4.12891 94.999997,94.999997 0 0 1 8.0957,4.96484 94.999997,94.999997 0 0 1 7.56055,5.74609 94.999997,94.999997 0 0 1 5.25,4.89063 l 7.11328,-7.11328 a 105,105 0 0 0 -47.37695,-26.7168 z"
style="fill:url(#linearGradient6698);fill-opacity:1;stroke:none;stroke-width:0.48633054;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4905-0)"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.27181121,0,0,0.27181121,36.997416,216.05244)"
sodipodi:nodetypes="sssss"
inkscape:connector-curvature="0"
id="path8371"
d="m 132.29165,59.401511 c -58.159346,0 -105.306798,47.147459 -105.306782,105.306819 4e-6,58.15933 47.147452,105.30679 105.306782,105.30679 58.15933,0 105.30677,-47.14746 105.30678,-105.30679 1e-5,-58.15936 -47.14744,-105.306819 -105.30678,-105.306819 z"
style="opacity:0.7;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.97340846;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
transform="matrix(0.27181121,0,0,0.27181121,36.997416,216.05244)"
style="opacity:0.7;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.97340846;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.93150689"
d="m 132.51082,119.61863 c -24.71711,0 -44.754267,20.03716 -44.75426,44.75428 2e-6,24.71711 20.03715,44.75427 44.75426,44.75427 24.71711,0 44.75428,-20.03716 44.75429,-44.75427 0,-24.71712 -20.03717,-44.75428 -44.75429,-44.75428 z"
id="path8773"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssss" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 34 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 65 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="11"
height="11"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="spot-active.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#a94a4a"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
inkscape:cx="1.6872889"
inkscape:cy="2.4074225"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1025"
inkscape:window-x="-2"
inkscape:window-y="-3"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1041.3622)">
<path
style="fill:#000000;fill-opacity:0.39215687;stroke:none"
d="M 6 2 L 6 5 L 7 5 L 7 2 L 6 2 z M 2 6 L 2 7 L 5 7 L 5 6 L 2 6 z M 6 6 L 6 7 L 6 10 L 6 11 L 7 11 L 7 7 L 11 7 L 11 6 L 10 6 L 7 6 L 6 6 z "
transform="translate(0,1041.3622)"
id="rect2987" />
<path
id="path3784"
d="m 5,1042.3622 0,4 -4,0 0,1 4,0 0,4 1,0 0,-4 4,0 0,-1 -4,0 0,-4 -1,0 z"
style="fill:#ffffff;fill-opacity:0.58823532;stroke:none"
inkscape:connector-curvature="0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none"
id="rect3788"
width="1"
height="3"
x="5"
y="1045.3622" />
<rect
y="4"
x="-1047.3622"
height="3"
width="1"
id="rect3790"
style="fill:#ffffff;fill-opacity:1;stroke:none"
transform="matrix(0,-1,1,0,0,0)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="11"
height="11"
id="svg2"
version="1.1"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="spot-normal.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#a94a4a"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
inkscape:cx="8.1603829"
inkscape:cy="7.1741798"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1005"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1041.3622)">
<path
style="fill:#000000;fill-opacity:0.66666667;stroke:none"
d="M 6,1043.3622 5.378906,1046.7411 2,1047.3622 v 1 l 3.378906,0.6211 L 6,1052.3622 H 7 L 7.621094,1048.9833 11,1048.3622 v -1 L 7.621094,1046.7411 7,1043.3622 Z"
id="path818"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 5,1042.3622 h 1 l 0.8286408,4.5 L 6,1051.3622 H 5 l -0.8286408,-4.5 z"
id="rect2989"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="path11"
d="m 1,1047.3622 v -1 l 4.5,-0.8286 4.5,0.8286 v 1 l -4.5,0.8286 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="11"
height="11"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="spot-prelight.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#a94a4a"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
inkscape:cx="1.6872889"
inkscape:cy="2.4074225"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1025"
inkscape:window-x="-2"
inkscape:window-y="-3"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1041.3622)">
<path
style="fill:#000000;fill-opacity:0.66666669;stroke:none"
d="m 6,1043.3622 0,4 -4,0 0,1 4,0 0,4 1,0 0,-4 4,0 0,-1 -4,0 0,-4 -1,0 z"
id="rect2987" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none"
id="rect2985"
width="9"
height="1"
x="1"
y="1046.3622" />
<rect
y="1042.3622"
x="5"
height="9"
width="1"
id="rect2989"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 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

0
rtdata/languages/LICENSE Executable file → Normal file
View 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

View File

@ -0,0 +1,41 @@
[Exposure]
Auto=false
Compensation=0
HistogramMatching=false
CurveFromHistogramMatching=false
ClampOOG=false
CurveMode=Standard
CurveMode2=Standard
Curve=1;0;0;0.88544601940051371;1;
Curve2=1;0;0;0.0397505754145333;0.020171771436200074;0.54669745433149319;0.69419974733677647;1;1;
[HLRecovery]
Enabled=false
Method=Blend
[Black & White]
Enabled=true
[Crop]
FixedRatio=false
[Color Management]
InputProfile=(camera)
ToneCurve=false
ApplyLookTable=false
ApplyHueSatMap=false
WorkingProfile=Rec2020
WorkingTRC=none
[RAW Bayer]
Method=rcd
[Film Negative]
Enabled=true
RedRatio=1.0
GreenExponent=1.5
BlueRatio=1.0
ColorSpace=1
RefInput=0;0;0;
RefOutput=0;0;0;
BackCompat=0

View File

@ -1278,6 +1278,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;
@ -1029,4 +1034,4 @@ messagedialog headerbar button.titlebutton {
min-height: 1.25em;
margin: 0;
}
/*** end ***************************************************************************************/
/*** end ***************************************************************************************/

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

@ -67,6 +67,7 @@ endif()
set(CAMCONSTSFILE "camconst.json")
set(RTENGINESOURCEFILES
alpha.cc
ahd_demosaic_RT.cc
amaze_demosaic_RT.cc
badpixels.cc
@ -142,7 +143,6 @@ set(RTENGINESOURCEFILES
jpeg_ijg/jpeg_memsrc.cc
labimage.cc
lcp.cc
lj92.c
lmmse_demosaic.cc
loadinitial.cc
metadata.cc
@ -168,6 +168,7 @@ set(RTENGINESOURCEFILES
rtthumbnail.cc
shmap.cc
simpleprocess.cc
spot.cc
stdimagesource.cc
tmo_fattal02.cc
utils.cc
@ -179,6 +180,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

@ -208,7 +208,7 @@ bool MultiDiagonalSymmetricMatrix::CreateDiagonal(int index, int StartRow)
return true;
}
inline int MultiDiagonalSymmetricMatrix::FindIndex(int StartRow)
inline int MultiDiagonalSymmetricMatrix::FindIndex(int StartRow) const
{
//There's GOT to be a better way to do this. "Bidirectional map?"
// Issue 1895 : Changed start of loop from zero to one

View File

@ -97,7 +97,7 @@ public:
int *StartRows;
bool CreateDiagonal(int index, int StartRow);
int n, m; //The matrix is n x n, with m diagonals on the lower triangle. Don't change these. They should be private but aren't for convenience.
inline int DiagonalLength(int StartRow) //Gives number of elements in a diagonal.
inline int DiagonalLength(int StartRow) const //Gives number of elements in a diagonal.
{
return n - StartRow;
};
@ -109,7 +109,7 @@ public:
void VectorProduct(float *Product, float *x);
//Given the start row, attempts to find the corresponding index, or -1 if the StartRow doesn't exist.
inline int FindIndex(int StartRow) __attribute__((always_inline));
inline int FindIndex(int StartRow) const __attribute__((always_inline));
//This is the same as above, but designed to take this class as a pass through variable. By this way you can feed
//the meat of this class into an independent function, such as SparseConjugateGradient.

View File

@ -667,7 +667,7 @@ BENCHFUN
const float gain = std::pow(2.0, expcomp);
const double params_Ldetail = std::min(dnparams.Ldetail, 99.9); // max out to avoid div by zero when using noisevar_Ldetail as divisor
const float noisevar_Ldetail = SQR(SQR(100. - params_Ldetail) + 50.0 * (100.0 - params_Ldetail) * TS * 0.5);
const float noisevar_Ldetail = SQR((SQR(100. - params_Ldetail) + 50.0 * (100.0 - params_Ldetail)) * TS * 0.5);
array2D<float> tilemask_in(TS, TS);
array2D<float> tilemask_out(TS, TS);

96
rtengine/alpha.cc Normal file
View File

@ -0,0 +1,96 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "alpha.h"
namespace rtengine
{
Alpha::Alpha () {}
Alpha::Alpha (int width, int height)
{
if (width > 0 && height > 0) {
surface = Cairo::ImageSurface::create (Cairo::FORMAT_A8, width, height);
}
}
/*
Alpha::~Alpha () {
surface->unreference();
}
*/
void Alpha::setSize (int width, int height)
{
if (width > 0 && height > 0) {
if (surface) {
if (width != getWidth() && height != getHeight()) {
surface.clear(); // does this delete the referenced object? Unreferencing doesn't work, since Cairo expect to have a non null refCount in the destructor!
} else {
return;
}
}
surface = Cairo::ImageSurface::create (Cairo::FORMAT_A8, width, height);
} else if (surface) {
surface.clear();
}
}
int Alpha::getWidth() const
{
if (surface) {
return surface->get_width();
}
return -1;
}
int Alpha::getHeight() const
{
if (surface) {
return surface->get_height();
}
return -1;
}
Cairo::RefPtr<Cairo::ImageSurface> Alpha::getSurface () const
{
return surface; // to be used in bitmap edition
}
unsigned char Alpha::operator () (unsigned row, unsigned col) const
{
return * (surface->get_data () + row * surface->get_width () + col);
}
unsigned char& Alpha::operator () (unsigned row, unsigned col)
{
return * (surface->get_data () + row * surface->get_width () + col);
}
unsigned char* Alpha::operator () (unsigned row) const
{
return surface->get_data () + row * surface->get_width ();
}
}

58
rtengine/alpha.h Normal file
View File

@ -0,0 +1,58 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef _ALPHA_H_
#define _ALPHA_H_
#include <gtkmm.h>
#include <assert.h>
#define CHECK_BOUNDS 0
namespace rtengine
{
/// Alpha channel class (8 bits)
class Alpha
{
protected:
Cairo::RefPtr<Cairo::ImageSurface> surface;
public:
Alpha ();
Alpha (int width, int height);
//~Alpha ();
void setSize (int width, int height);
int getWidth() const;
int getHeight() const;
Cairo::RefPtr<Cairo::ImageSurface> getSurface () const;
// TODO: to make the editing faster, we should add an iterator class
// Will send back the start of a row
unsigned char* operator () (unsigned row) const;
// Will send back a value at a given row, col position
unsigned char& operator () (unsigned row, unsigned col);
unsigned char operator () (unsigned row, unsigned col) const;
};
}
#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

@ -182,7 +182,7 @@ int RawImageSource::interpolateBadPixelsBayer(const PixelsMap &bitmapBads, array
/* interpolateBadPixelsNcolors: correct raw pixels looking at the bitmap
* takes into consideration if there are multiple bad pixels in the neighborhood
*/
int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, const int colors)
int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, const int colours)
{
constexpr float eps = 1.f;
int counter = 0;
@ -204,9 +204,9 @@ int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, co
continue;
}
float wtdsum[colors];
float norm[colors];
for (int c = 0; c < colors; ++c) {
float wtdsum[colours];
float norm[colours];
for (int c = 0; c < colours; ++c) {
wtdsum[c] = norm[c] = 0.f;
}
@ -216,41 +216,41 @@ int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, co
continue;
}
for (int c = 0; c < colors; ++c) {
const float dirwt = 0.70710678f / (fabsf(rawData[row - 1][(col + dx) * colors + c] - rawData[row + 1][(col - dx) * colors + c]) + eps);
wtdsum[c] += dirwt * (rawData[row - 1][(col + dx) * colors + c] + rawData[row + 1][(col - dx) * colors + c]);
for (int c = 0; c < colours; ++c) {
const float dirwt = 0.70710678f / (fabsf(rawData[row - 1][(col + dx) * colours + c] - rawData[row + 1][(col - dx) * colours + c]) + eps);
wtdsum[c] += dirwt * (rawData[row - 1][(col + dx) * colours + c] + rawData[row + 1][(col - dx) * colours + c]);
norm[c] += dirwt;
}
}
// horizontal interpolation
if (!(bitmapBads.get(col - 1, row) || bitmapBads.get(col + 1, row))) {
for (int c = 0; c < colors; ++c) {
const float dirwt = 1.f / (fabsf(rawData[row][(col - 1) * colors + c] - rawData[row][(col + 1) * colors + c]) + eps);
wtdsum[c] += dirwt * (rawData[row][(col - 1) * colors + c] + rawData[row][(col + 1) * colors + c]);
for (int c = 0; c < colours; ++c) {
const float dirwt = 1.f / (fabsf(rawData[row][(col - 1) * colours + c] - rawData[row][(col + 1) * colours + c]) + eps);
wtdsum[c] += dirwt * (rawData[row][(col - 1) * colours + c] + rawData[row][(col + 1) * colours + c]);
norm[c] += dirwt;
}
}
// vertical interpolation
if (!(bitmapBads.get(col, row - 1) || bitmapBads.get(col, row + 1))) {
for (int c = 0; c < colors; ++c) {
const float dirwt = 1.f / (fabsf(rawData[row - 1][col * colors + c] - rawData[row + 1][col * colors + c]) + eps);
wtdsum[c] += dirwt * (rawData[row - 1][col * colors + c] + rawData[row + 1][col * colors + c]);
for (int c = 0; c < colours; ++c) {
const float dirwt = 1.f / (fabsf(rawData[row - 1][col * colours + c] - rawData[row + 1][col * colours + c]) + eps);
wtdsum[c] += dirwt * (rawData[row - 1][col * colours + c] + rawData[row + 1][col * colours + c]);
norm[c] += dirwt;
}
}
if (LIKELY(norm[0] > 0.f)) { // This means, we found at least one pair of valid pixels in the steps above, likelihood of this case is about 99.999%
for (int c = 0; c < colors; ++c) {
rawData[row][col * colors + c] = wtdsum[c] / (2.f * norm[c]); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps
for (int c = 0; c < colours; ++c) {
rawData[row][col * colours + c] = wtdsum[c] / (2.f * norm[c]); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps
}
counter++;
} else { //backup plan -- simple average. Same method for all channels. We could improve this, but it's really unlikely that this case happens
int tot = 0;
float sum[colors];
for (int c = 0; c < colors; ++c) {
float sum[colours];
for (int c = 0; c < colours; ++c) {
sum[c] = 0.f;
}
@ -260,8 +260,8 @@ int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, co
continue;
}
for (int c = 0; c < colors; ++c) {
sum[c] += rawData[row + dy][(col + dx) * colors + c];
for (int c = 0; c < colours; ++c) {
sum[c] += rawData[row + dy][(col + dx) * colours + c];
}
tot++;
@ -269,8 +269,8 @@ int RawImageSource::interpolateBadPixelsNColours(const PixelsMap &bitmapBads, co
}
if (tot > 0) {
for (int c = 0; c < colors; ++c) {
rawData[row][col * colors + c] = sum[c] / tot;
for (int c = 0; c < colours; ++c) {
rawData[row][col * colours + c] = sum[c] / tot;
}
counter ++;

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,19 @@
#undef CLIPD
#define CLIPD(a) ((a)>0.f?((a)<1.f?(a):1.f):0.f)
#define MAXR(a,b) ((a) > (b) ? (a) : (b))
#define Jzazbz_b 1.15
#define Jzazbz_g 0.66
#define Jzazbz_c1 (3424/4096.0)
#define Jzazbz_c2 (2413/128.0)
#define Jzazbz_c3 (2392/128.0)
#define Jzazbz_n (2610/16384.0)
#define Jzazbz_p (1.7*2523/32.0)
#define Jzazbz_d (-0.56)
#define Jzazbz_d0 (1.6295499532821566e-11)
#define Jzazbz_ni (16384.0/2610.0)
#define Jzazbz_pi (32.0/4289.1) //4289.1 = 2523 * 1.7
namespace rtengine
{
@ -67,10 +80,12 @@ void Ciecam02::curveJfloat (float br, float contr, float thr, const LUTu & histo
brightcurvePoints[5] = 0.7f; // shoulder point
brightcurvePoints[6] = min (1.0f, 0.7f + br / 300.0f); //value at shoulder point
} else {
brightcurvePoints[3] = 0.1f - br / 150.0f; // toe point
brightcurvePoints[3] = max(0.0, 0.1 - (double) br / 150.0); // toe point
// brightcurvePoints[3] = 0.1f - br / 150.0f; // toe point
brightcurvePoints[4] = 0.1f; // value at toe point
brightcurvePoints[5] = min (1.0f, 0.7f - br / 300.0f); // shoulder point
// brightcurvePoints[5] = min (1.0f, 0.7f - br / 300.0f); // shoulder point
brightcurvePoints[5] = 0.7f - br / 300.0f; // shoulder point
brightcurvePoints[6] = 0.7f; // value at shoulder point
}
@ -109,6 +124,7 @@ void Ciecam02::curveJfloat (float br, float contr, float thr, const LUTu & histo
}
avg /= sum;
// printf("avg=%f \n", (double) avg);
float thrmin = (thr - contr / 250.0f);
float thrmax = (thr + contr / 250.0f);
@ -184,14 +200,14 @@ float Ciecam02::calculate_fl_from_la_ciecam02float ( float la )
return (0.2f * k * la5) + (0.1f * (1.0f - k) * (1.0f - k) * std::cbrt (la5));
}
float Ciecam02::achromatic_response_to_whitefloat ( float x, float y, float z, float d, float fl, float nbb, int c16)
float Ciecam02::achromatic_response_to_whitefloat ( float x, float y, float z, float d, float fl, float nbb, int c16, float plum)
{
float r, g, b;
float rc, gc, bc;
float rp, gp, bp;
float rpa, gpa, bpa;
// gamu = 1;
xyz_to_cat02float ( r, g, b, x, y, z, c16);
xyz_to_cat02float ( r, g, b, x, y, z, c16, plum);
rc = r * (((y * d) / r) + (1.0f - d));
gc = g * (((y * d) / g) + (1.0f - d));
@ -216,71 +232,253 @@ float Ciecam02::achromatic_response_to_whitefloat ( float x, float y, float z, f
return ((2.0f * rpa) + gpa + ((1.0f / 20.0f) * bpa) - 0.305f) * nbb;
}
void Ciecam02::xyz_to_cat02float ( float &r, float &g, float &b, float x, float y, float z, int c16)
{
void Ciecam02::xyz_to_cat02float ( float &r, float &g, float &b, float x, float y, float z, int c16, float plum)
{ //I use isnan() because I have tested others solutions with std::max(xxx,0) and in some cases crash
//original cat02
//r = ( 0.7328 * x) + (0.4296 * y) - (0.1624 * z);
//g = (-0.7036 * x) + (1.6975 * y) + (0.0061 * z);
//b = ( 0.0000 * x) + (0.0000 * y) + (1.0000 * z);
float peakLum = 1.f/ plum;
if(c16 == 1) {//cat02
r = ( 1.007245f * x) + (0.011136f * y) - (0.018381f * z); //Changjun Li
g = (-0.318061f * x) + (1.314589f * y) + (0.003471f * z);
b = ( 0.0000f * x) + (0.0000f * y) + (1.0000f * z);
} else {//cat16
} else if (c16 == 16) {//cat16
r = ( 0.401288f * x) + (0.650173f * y) - (0.051461f * z); //cat16
g = (-0.250268f * x) + (1.204414f * y) + (0.045854f * z);
b = ( -0.002079f * x) + (0.048952f * y) + (0.953127f * z);
} else if (c16 == 21) {//cam16 PQ
float rp = ( 0.401288f * x) + (0.650173f * y) - (0.051461f * z); //cat16
float gp = (-0.250268f * x) + (1.204414f * y) + (0.045854f * z);
float bp = ( -0.002079f * x) + (0.048952f * y) + (0.953127f * z);
rp *= 0.01f;
gp *= 0.01f;
bp *= 0.01f;
float tmp = pow_F(rp * peakLum, Jzazbz_n);
if(std::isnan(tmp)) {//to avoid crash
tmp = 0.f;
}
r = 100.f * pow((Jzazbz_c1 + Jzazbz_c2 * tmp) / (1. + Jzazbz_c3 * tmp), Jzazbz_p);
if(std::isnan(r) || r < 0.f) {
r = 0.f;
}
tmp = pow_F(gp * peakLum, Jzazbz_n);
if(std::isnan(tmp)) {//to avoid crash
tmp = 0.f;
}
g = 100.f * pow((Jzazbz_c1 + Jzazbz_c2 * tmp) / (1. + Jzazbz_c3 * tmp), Jzazbz_p);
if(std::isnan(g) || g < 0.f) {
g = 0.f;
}
tmp = pow_F(bp * peakLum, Jzazbz_n);
if(std::isnan(tmp)) {//to avoid crash
tmp = 0.f;
}
b = 100.f * pow((Jzazbz_c1 + Jzazbz_c2 * tmp) / (1. + Jzazbz_c3 * tmp), Jzazbz_p);
if(std::isnan(b) || b < 0.f) {
b = 0.f;
}
}
}
#ifdef __SSE2__
void Ciecam02::xyz_to_cat02float ( vfloat &r, vfloat &g, vfloat &b, vfloat x, vfloat y, vfloat z, int c16)
{
void Ciecam02::xyz_to_cat02float ( vfloat &r, vfloat &g, vfloat &b, vfloat x, vfloat y, vfloat z, int c16, vfloat plum)
{ //I use isnan() because I have tested others solutions with std::max(xxx,0) and in some cases crash
//gamut correction M.H.Brill S.Susstrunk
if(c16 == 1) {
r = ( F2V (1.007245f) * x) + (F2V (0.011136f) * y) - (F2V (0.018381f) * z); //Changjun Li
g = (F2V (-0.318061f) * x) + (F2V (1.314589f) * y) + (F2V (0.003471f) * z);
b = z;
} else {
} else if (c16 == 16) {
//cat16
r = ( F2V (0.401288f) * x) + (F2V (0.650173f) * y) - (F2V (0.051461f) * z); //Changjun Li
r = ( F2V (0.401288f) * x) + (F2V (0.650173f) * y) - (F2V (0.051461f) * z);
g = -(F2V (0.250268f) * x) + (F2V (1.204414f) * y) + (F2V (0.045854f) * z);
b = -(F2V(0.002079f) * x) + (F2V(0.048952f) * y) + (F2V(0.953127f) * z);
} else if (c16 == 21) {
vfloat rp = ( F2V (0.401288f) * x) + (F2V (0.650173f) * y) - (F2V (0.051461f) * z);
vfloat gp = -(F2V (0.250268f) * x) + (F2V (1.204414f) * y) + (F2V (0.045854f) * z);
vfloat bp = -(F2V(0.002079f) * x) + (F2V(0.048952f) * y) + (F2V(0.953127f) * z);
vfloat Jzazbz_c1v = F2V(Jzazbz_c1);
vfloat Jzazbz_c2v = F2V(Jzazbz_c2);
vfloat Jzazbz_nv = F2V(Jzazbz_n);
vfloat Jzazbz_c3v = F2V(Jzazbz_c3);
vfloat Jzazbz_pv = F2V(Jzazbz_p);
vfloat mulone = F2V(0.01f);
vfloat mulhund = F2V(100.f);
float RR, GG, BB;
vfloat one = F2V(1.);
vfloat peakLumv = one / plum;
rp *= mulone;
gp *= mulone;
bp *= mulone;
vfloat tmp = pow_F(rp * peakLumv, Jzazbz_nv );
STVF(RR, tmp);
if(std::isnan(RR)) {//to avoid crash
tmp = F2V(0.f);;
}
r = mulhund * pow_F((Jzazbz_c1v + Jzazbz_c2v * tmp) / (one + Jzazbz_c3v * tmp), Jzazbz_pv);
STVF(RR, r);
if(std::isnan(RR) || RR < 0.f) {//to avoid crash
r = F2V(0.f);;
}
tmp = pow_F(gp * peakLumv, Jzazbz_nv );
STVF(RR, tmp);
if(std::isnan(RR)) {//to avoid crash
tmp = F2V(0.f);;
}
g = mulhund * pow_F((Jzazbz_c1v + Jzazbz_c2v * tmp) / (one + Jzazbz_c3v * tmp), Jzazbz_pv);
STVF(GG, g);
if(std::isnan(GG) || GG < 0.f) {//to avoid crash
g = F2V(0.f);;
}
tmp = pow_F(bp * peakLumv, Jzazbz_nv );
STVF(RR, tmp);
if(std::isnan(RR)) {//to avoid crash
tmp = F2V(0.f);;
}
b = mulhund * pow_F((Jzazbz_c1v + Jzazbz_c2v * tmp) / (one + Jzazbz_c3v * tmp), Jzazbz_pv);
STVF(BB, b);
if(std::isnan(BB) || BB < 0.f) {//to avoid crash
b = F2V(0.f);;
}
}
}
#endif
void Ciecam02::cat02_to_xyzfloat ( float &x, float &y, float &z, float r, float g, float b, int c16)
{
void Ciecam02::cat02_to_xyzfloat ( float &x, float &y, float &z, float r, float g, float b, int c16, float plum)
{ //I use isnan() because I have tested others solutions with std::max(xxx,0) and in some cases crash
//original cat02
//x = ( 1.0978566 * r) - (0.277843 * g) + (0.179987 * b);
//y = ( 0.455053 * r) + (0.473938 * g) + (0.0710096* b);
//z = ( 0.000000 * r) - (0.000000 * g) + (1.000000 * b);
float pl = plum;
if(c16 == 1) {
x = ( 0.99015849f * r) - (0.00838772f * g) + (0.018229217f * b); //Changjun Li
y = ( 0.239565979f * r) + (0.758664642f * g) + (0.001770137f * b);
z = ( 0.000000f * r) - (0.000000f * g) + (1.000000f * b);
} else {//cat16
} else if(c16 == 16){//cat16
x = ( 1.86206786f * r) - (1.01125463f * g) + (0.14918677f * b); //Cat16
y = ( 0.38752654f * r) + (0.62144744f * g) + (-0.00897398f * b);
z = ( -0.0158415f * r) - (0.03412294f * g) + (1.04996444f * b);
}else if(c16 == 21){//cam16 PQ
float lp = ( 1.86206786f * r) - (1.01125463f * g) + (0.14918677f * b); //Cat16
float mp = ( 0.38752654f * r) + (0.62144744f * g) + (-0.00897398f * b);
float sp = ( -0.0158415f * r) - (0.03412294f * g) + (1.04996444f * b);
lp *= 0.01f;
float tmp = pow_F(lp, Jzazbz_pi);
if(std::isnan(tmp)) {//to avoid crash
tmp = 0.f;
}
float prov = (Jzazbz_c1 - tmp) / ((Jzazbz_c3 * tmp) - Jzazbz_c2);
x = pl * pow_F(prov, Jzazbz_ni);
if(std::isnan(x)) {//to avoid crash
x = 0.f;
}
x *= 100.f;
mp *= 0.01f;
tmp = pow_F(mp, Jzazbz_pi);
if(std::isnan(tmp)) {//to avoid crash
tmp = 0.f;
}
prov = (Jzazbz_c1 - tmp) / ((Jzazbz_c3 * tmp) - Jzazbz_c2);
y = pl * pow_F(prov, Jzazbz_ni);
if(std::isnan(y)) {
y = 0.f;
}
y *= 100.f;
sp *= 0.01f;
tmp = pow_F(sp, Jzazbz_pi);
if(std::isnan(tmp)) {//to avoid crash
tmp = 0.f;
}
prov = (Jzazbz_c1 - tmp) / ((Jzazbz_c3 * tmp) - Jzazbz_c2);
z = pl * pow_F(prov, Jzazbz_ni);
if(std::isnan(z)) {
z = 0.;
}
z *= 100.f;
}
}
#ifdef __SSE2__
void Ciecam02::cat02_to_xyzfloat ( vfloat &x, vfloat &y, vfloat &z, vfloat r, vfloat g, vfloat b, int c16 )
{
void Ciecam02::cat02_to_xyzfloat ( vfloat &x, vfloat &y, vfloat &z, vfloat r, vfloat g, vfloat b, int c16, vfloat plum )
{ //I use isnan() because I have tested others solutions with std::max(xxx,0) and in some cases crash
vfloat plv = plum;
//gamut correction M.H.Brill S.Susstrunk
if(c16 == 1) {//cat02
x = ( F2V (0.99015849f) * r) - (F2V (0.00838772f) * g) + (F2V (0.018229217f) * b); //Changjun Li
y = ( F2V (0.239565979f) * r) + (F2V (0.758664642f) * g) + (F2V (0.001770137f) * b);
z = b;
} else {
} else if(c16 == 16) {
//cat16
x = ( F2V (1.86206786f) * r) - (F2V (1.01125463f) * g) + (F2V (0.14918677f) * b);
y = ( F2V (0.38752654f) * r) + (F2V (0.621447744f) * g) - (F2V (0.00897398f) * b);
z = -(F2V(0.0158415f) * r) - (F2V(0.03412294f) * g) + (F2V(1.04996444f) * b);
}else if(c16 == 21){//cam16 PQ
vfloat lp = ( F2V (1.86206786f) * r) - (F2V (1.01125463f) * g) + (F2V (0.14918677f) * b);
vfloat mp = ( F2V (0.38752654f) * r) + (F2V (0.621447744f) * g) - (F2V (0.00897398f) * b);
vfloat sp = -(F2V(0.0158415f) * r) - (F2V(0.03412294f) * g) + (F2V(1.04996444f) * b);
float XX,YY,ZZ;
vfloat Jzazbz_c1v = F2V(Jzazbz_c1);
vfloat Jzazbz_c2v = F2V(Jzazbz_c2);
vfloat Jzazbz_c3v = F2V(Jzazbz_c3);
vfloat Jzazbz_piv = F2V(Jzazbz_pi);
vfloat Jzazbz_niv = F2V(Jzazbz_ni);
vfloat mulone = F2V(0.01f);
vfloat mulhund = F2V(100.f);
lp *= mulone;
float pro;
vfloat tmp = pow_F(lp, Jzazbz_piv);
STVF(XX, tmp);
if(std::isnan(XX)) {//to avoid crash
tmp = F2V(0.f);;
}
vfloat prov = (Jzazbz_c1v - tmp) / ((Jzazbz_c3v * tmp) - Jzazbz_c2v);
x = plv * pow_F(prov, Jzazbz_niv);
STVF(XX, x);
if(std::isnan(XX)) {//to avoid crash
x = F2V(0.f);;
}
x *= mulhund;
mp *= mulone;
tmp = pow_F(mp, Jzazbz_piv);
STVF(YY, tmp);
if(std::isnan(YY)) {//to avoid crash
tmp = F2V(0.f);;
}
prov = (Jzazbz_c1v - tmp) / ((Jzazbz_c3v * tmp) - Jzazbz_c2v);
y = plv * pow_F(prov, Jzazbz_niv);
STVF(YY, y);
if(std::isnan(YY)) {//to avoid crash
y = F2V(0.f);;
}
y *= mulhund;
sp *= mulone;
tmp = pow_F(sp, Jzazbz_piv);
STVF(ZZ, tmp);
if(std::isnan(ZZ)) {//to avoid crash
tmp = F2V(0.f);;
}
prov = (Jzazbz_c1v - tmp) / ((Jzazbz_c3v * tmp) - Jzazbz_c2v);
STVF(pro, prov);
z = plv * pow_F(prov, Jzazbz_niv);
STVF(ZZ, z);
if(std::isnan(ZZ)) {//to avoid crash
z = F2V(0.f);;
}
z *= mulhund;
}
}
#endif
@ -429,7 +627,7 @@ void Ciecam02::calculate_abfloat ( vfloat &aa, vfloat &bb, vfloat h, vfloat e, v
#endif
void Ciecam02::initcam1float (float yb, float pilotd, float f, float la, float xw, float yw, float zw, float &n, float &d, float &nbb, float &ncb,
float &cz, float &aw, float &wh, float &pfl, float &fl, float c, int c16)
float &cz, float &aw, float &wh, float &pfl, float &fl, float c, int c16, float plum)
{
n = yb / yw;
@ -442,13 +640,13 @@ void Ciecam02::initcam1float (float yb, float pilotd, float f, float la, float x
fl = calculate_fl_from_la_ciecam02float ( la );
nbb = ncb = 0.725f * pow_F ( 1.0f / n, 0.2f );
cz = 1.48f + sqrt ( n );
aw = achromatic_response_to_whitefloat ( xw, yw, zw, d, fl, nbb, c16);
aw = achromatic_response_to_whitefloat ( xw, yw, zw, d, fl, nbb, c16, plum);
wh = ( 4.0f / c ) * ( aw + 4.0f ) * pow_F ( fl, 0.25f );
pfl = pow_F ( fl, 0.25f );
}
void Ciecam02::initcam2float (float yb, float pilotd, float f, float la, float xw, float yw, float zw, float &n, float &d, float &nbb, float &ncb,
float &cz, float &aw, float &fl, int c16)
float &cz, float &aw, float &fl, int c16, float plum)
{
n = yb / yw;
@ -462,12 +660,135 @@ void Ciecam02::initcam2float (float yb, float pilotd, float f, float la, float x
fl = calculate_fl_from_la_ciecam02float ( la );
nbb = ncb = 0.725f * pow_F ( 1.0f / n, 0.2f );
cz = 1.48f + sqrt ( n );
aw = achromatic_response_to_whitefloat ( xw, yw, zw, d, fl, nbb, c16);
aw = achromatic_response_to_whitefloat ( xw, yw, zw, d, fl, nbb, c16, plum);
}
void Ciecam02::xyz2jzczhz ( double &Jz, double &az, double &bz, double x, double y, double z, double pl, double &Lp, double &Mp, double &Sp, bool zcam)
{ //from various web
double Xp, Yp, Zp, L, M, S, Iz;
double peakLum = 1. / pl;
//I change 10000 for peaklum function of la (absolute luminance)- default 10000
Xp = Jzazbz_b * x - ((Jzazbz_b - 1.) * z);
Yp = Jzazbz_g * y - ((Jzazbz_g - 1.) * x);
Zp = z;
L = 0.41478972 * Xp + 0.579999 * Yp + 0.0146480 * Zp;
M = -0.2015100 * Xp + 1.120649 * Yp + 0.0531008 * Zp;
S = -0.0166008 * Xp + 0.264800 * Yp + 0.6684799 * Zp;
//I use isnan() because I have tested others solutions with std::max(xxx,0) and in some cases crash
// Lp = pow((Jzazbz_c1 + Jzazbz_c2 * pow(std::max((L * peakLum), 0.), Jzazbz_n)) / (1. + Jzazbz_c3 * pow((L * peakLum), Jzazbz_n)), Jzazbz_p);
// Mp = pow((Jzazbz_c1 + Jzazbz_c2 * pow(std::max((M * peakLum),0.), Jzazbz_n)) / (1. + Jzazbz_c3 * pow((M * peakLum), Jzazbz_n)), Jzazbz_p);
// Sp = pow((Jzazbz_c1 + Jzazbz_c2 * pow(std::max((S * peakLum), 0.), Jzazbz_n)) / (1. + Jzazbz_c3 * pow((S * peakLum), Jzazbz_n)), Jzazbz_p);
double temp = pow(L * peakLum, Jzazbz_n);
if(std::isnan(temp)) {//to avoid crash
temp = 0.;
}
Lp = pow((Jzazbz_c1 + Jzazbz_c2 * temp) / (1. + Jzazbz_c3 * temp), Jzazbz_p);
if(std::isnan(Lp)) {//to avoid crash
Lp = 0.;
}
temp = pow(M * peakLum, Jzazbz_n);
if(std::isnan(temp)) {//to avoid crash
temp = 0.;
}
Mp = pow((Jzazbz_c1 + Jzazbz_c2 * temp) / (1. + Jzazbz_c3 * temp), Jzazbz_p);
if(std::isnan(Mp)) {//to avoid crash
Mp = 0.;
}
temp = pow(S * peakLum, Jzazbz_n);
if(std::isnan(temp)) {//to avoid crash
temp = 0.;
}
Sp = pow((Jzazbz_c1 + Jzazbz_c2 * temp) / (1. + Jzazbz_c3 * temp), Jzazbz_p);
if(std::isnan(Sp)) {//to avoid crash
Sp = 0.;
}
Iz = 0.5 * Lp + 0.5 * Mp;
az = 3.524000 * Lp - 4.066708 * Mp + 0.542708 * Sp;
bz = 0.199076 * Lp + 1.096799 * Mp - 1.295875 * Sp;
if(!zcam) {
Jz = (((1. + Jzazbz_d) * Iz) / (1. + Jzazbz_d * Iz)) - Jzazbz_d0;
// Jz = std::max((((1. + Jzazbz_d) * Iz) / (1. + Jzazbz_d * Iz)) - Jzazbz_d0, 0.);
} else {
//or if we use ZCAM Jz = Mp - Jzazbz_d0
Jz = Mp - Jzazbz_d0;
}
}
void Ciecam02::jzczhzxyz (double &x, double &y, double &z, double jz, double az, double bz, double pl, double &L, double &M, double &S, bool zcam)
{ //from various web
//I use isnan() because I have tested others solutions with std::max(xxx,0) and in some cases crash
double Xp, Yp, Zp, Lp, Mp, Sp, Iz, tmp;
if(!zcam) {
// Iz = std::max((jz + Jzazbz_d0) / (1. + Jzazbz_d - Jzazbz_d * (jz + Jzazbz_d0)), 0.);
Iz = (jz + Jzazbz_d0) / (1. + Jzazbz_d - Jzazbz_d * (jz + Jzazbz_d0));
} else {
//or if we use ZCAM Iz = Jz + Jzazbz_d0
Iz = jz + Jzazbz_d0;
}
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 optionally 10000 for pl function of la(absolute luminance) default 10000
tmp = pow(Lp, Jzazbz_pi);
if(std::isnan(tmp)) {//to avoid crash
tmp = 0.;
}
L = pl * pow((Jzazbz_c1 - tmp) / ((Jzazbz_c3 * tmp) - Jzazbz_c2), Jzazbz_ni);
if(std::isnan(L)) {//to avoid crash
L = 0.;
}
tmp = pow(Mp, Jzazbz_pi);
if(std::isnan(tmp)) {//to avoid crash
tmp = 0.;
}
M = pl * pow((Jzazbz_c1 - tmp) / ((Jzazbz_c3 * tmp) - Jzazbz_c2), Jzazbz_ni);
if(std::isnan(M)) {//to avoid crash
M = 0.;
}
tmp = pow(Sp, Jzazbz_pi);
if(std::isnan(tmp)) {//to avoid crash
tmp = 0.;
}
S = pl * pow((Jzazbz_c1 - tmp) / ((Jzazbz_c3 * tmp) - Jzazbz_c2), Jzazbz_ni);
if(std::isnan(S)) {//to avoid crash
S = 0.;
}
Xp = 1.9242264357876067 * L - 1.0047923125953657 * M + 0.0376514040306180 * S;
Yp = 0.3503167620949991 * L + 0.7264811939316552 * M - 0.0653844229480850 * S;
Zp = -0.0909828109828475 * L - 0.3127282905230739 * M + 1.5227665613052603 * S;
x = (Xp + (Jzazbz_b - 1.) * Zp) / Jzazbz_b;
if(std::isnan(x)) {//to avoid crash
x = 0.;
}
y = (Yp + (Jzazbz_g - 1.) * x) / Jzazbz_g;
if(std::isnan(y)) {
y = 0.;
}
z = Zp;
if(std::isnan(z)) {
z = 0.;
}
}
void Ciecam02::xyz2jchqms_ciecam02float ( float &J, float &C, float &h, float &Q, float &M, float &s, float aw, float fl, float wh,
float x, float y, float z, float xw, float yw, float zw,
float c, float nc, float pow1, float nbb, float ncb, float pfl, float cz, float d, int c16)
float c, float nc, float pow1, float nbb, float ncb, float pfl, float cz, float d, int c16, float plum)
{
float r, g, b;
@ -478,8 +799,8 @@ void Ciecam02::xyz2jchqms_ciecam02float ( float &J, float &C, float &h, float &Q
float a, ca, cb;
float e, t;
float myh;
xyz_to_cat02float ( r, g, b, x, y, z, c16);
xyz_to_cat02float ( rw, gw, bw, xw, yw, zw, c16);
xyz_to_cat02float ( r, g, b, x, y, z, c16, plum);
xyz_to_cat02float ( rw, gw, bw, xw, yw, zw, c16, plum);
rc = r * (((yw * d) / rw) + (1.f - d));
gc = g * (((yw * d) / gw) + (1.f - d));
bc = b * (((yw * d) / bw) + (1.f - d));
@ -530,7 +851,7 @@ void Ciecam02::xyz2jchqms_ciecam02float ( float &J, float &C, float &h, float &Q
#ifdef __SSE2__
void Ciecam02::xyz2jchqms_ciecam02float ( vfloat &J, vfloat &C, vfloat &h, vfloat &Q, vfloat &M, vfloat &s, vfloat aw, vfloat fl, vfloat wh,
vfloat x, vfloat y, vfloat z, vfloat xw, vfloat yw, vfloat zw,
vfloat c, vfloat nc, vfloat pow1, vfloat nbb, vfloat ncb, vfloat pfl, vfloat cz, vfloat d, int c16)
vfloat c, vfloat nc, vfloat pow1, vfloat nbb, vfloat ncb, vfloat pfl, vfloat cz, vfloat d, int c16, vfloat plum)
{
vfloat r, g, b;
@ -541,8 +862,8 @@ void Ciecam02::xyz2jchqms_ciecam02float ( vfloat &J, vfloat &C, vfloat &h, vfloa
vfloat a, ca, cb;
vfloat e, t;
xyz_to_cat02float ( r, g, b, x, y, z, c16);
xyz_to_cat02float ( rw, gw, bw, xw, yw, zw, c16);
xyz_to_cat02float ( r, g, b, x, y, z, c16, plum);
xyz_to_cat02float ( rw, gw, bw, xw, yw, zw, c16, plum);
vfloat onev = F2V (1.f);
rc = r * (((yw * d) / rw) + (onev - d));
gc = g * (((yw * d) / gw) + (onev - d));
@ -595,7 +916,7 @@ void Ciecam02::xyz2jchqms_ciecam02float ( vfloat &J, vfloat &C, vfloat &h, vfloa
void Ciecam02::xyz2jch_ciecam02float ( float &J, float &C, float &h, float aw, float fl,
float x, float y, float z, float xw, float yw, float zw,
float c, float nc, float pow1, float nbb, float ncb, float cz, float d, int c16)
float c, float nc, float pow1, float nbb, float ncb, float cz, float d, int c16, float plum)
{
float r, g, b;
@ -606,8 +927,8 @@ void Ciecam02::xyz2jch_ciecam02float ( float &J, float &C, float &h, float aw, f
float a, ca, cb;
float e, t;
float myh;
xyz_to_cat02float ( r, g, b, x, y, z, c16);
xyz_to_cat02float ( rw, gw, bw, xw, yw, zw, c16);
xyz_to_cat02float ( r, g, b, x, y, z, c16, plum);
xyz_to_cat02float ( rw, gw, bw, xw, yw, zw, c16, plum);
rc = r * (((yw * d) / rw) + (1.f - d));
gc = g * (((yw * d) / gw) + (1.f - d));
bc = b * (((yw * d) / bw) + (1.f - d));
@ -664,7 +985,7 @@ void Ciecam02::xyz2jch_ciecam02float ( float &J, float &C, float &h, float aw, f
void Ciecam02::jch2xyz_ciecam02float ( float &x, float &y, float &z, float J, float C, float h,
float xw, float yw, float zw,
float c, float nc, float pow1, float nbb, float ncb, float fl, float cz, float d, float aw, int c16)
float c, float nc, float pow1, float nbb, float ncb, float fl, float cz, float d, float aw, int c16, float plum)
{
float r, g, b;
float rc, gc, bc;
@ -673,7 +994,7 @@ void Ciecam02::jch2xyz_ciecam02float ( float &x, float &y, float &z, float J, fl
float rw, gw, bw;
float a, ca, cb;
float e, t;
xyz_to_cat02float(rw, gw, bw, xw, yw, zw, c16);
xyz_to_cat02float(rw, gw, bw, xw, yw, zw, c16, plum);
e = ((961.53846f) * nc * ncb) * (xcosf(h * rtengine::RT_PI_F_180 + 2.0f) + 3.8f);
#ifdef __SSE2__
@ -705,7 +1026,7 @@ void Ciecam02::jch2xyz_ciecam02float ( float &x, float &y, float &z, float J, fl
if(c16 == 1) {//cat02
hpe_to_xyzfloat(x, y, z, rp, gp, bp, c16);
xyz_to_cat02float(rc, gc, bc, x, y, z, c16);
xyz_to_cat02float(rc, gc, bc, x, y, z, c16, plum);
r = rc / (((yw * d) / rw) + (1.0f - d));
g = gc / (((yw * d) / gw) + (1.0f - d));
@ -716,13 +1037,13 @@ void Ciecam02::jch2xyz_ciecam02float ( float &x, float &y, float &z, float J, fl
b = bp / (((yw * d) / bw) + (1.0f - d));
}
cat02_to_xyzfloat(x, y, z, r, g, b, c16);
cat02_to_xyzfloat(x, y, z, r, g, b, c16, plum);
}
#ifdef __SSE2__
void Ciecam02::jch2xyz_ciecam02float ( vfloat &x, vfloat &y, vfloat &z, vfloat J, vfloat C, vfloat h,
vfloat xw, vfloat yw, vfloat zw,
vfloat nc, vfloat pow1, vfloat nbb, vfloat ncb, vfloat fl, vfloat d, vfloat aw, vfloat reccmcz, int c16)
vfloat nc, vfloat pow1, vfloat nbb, vfloat ncb, vfloat fl, vfloat d, vfloat aw, vfloat reccmcz, int c16, vfloat plum)
{
vfloat r, g, b;
vfloat rc, gc, bc;
@ -731,7 +1052,7 @@ void Ciecam02::jch2xyz_ciecam02float ( vfloat &x, vfloat &y, vfloat &z, vfloat J
vfloat rw, gw, bw;
vfloat a, ca, cb;
vfloat e, t;
xyz_to_cat02float ( rw, gw, bw, xw, yw, zw, c16);
xyz_to_cat02float ( rw, gw, bw, xw, yw, zw, c16, plum);
e = ((F2V (961.53846f)) * nc * ncb) * (xcosf ( ((h * F2V (rtengine::RT_PI)) / F2V (180.0f)) + F2V (2.0f) ) + F2V (3.8f));
a = pow_F ( J / F2V (100.0f), reccmcz ) * aw;
t = pow_F ( F2V (10.f) * C / (vsqrtf ( J ) * pow1), F2V (1.1111111f) );
@ -745,7 +1066,7 @@ void Ciecam02::jch2xyz_ciecam02float ( vfloat &x, vfloat &y, vfloat &z, vfloat J
if(c16 == 1) {//cat02
hpe_to_xyzfloat ( x, y, z, rp, gp, bp, c16);
xyz_to_cat02float ( rc, gc, bc, x, y, z, c16 );
xyz_to_cat02float ( rc, gc, bc, x, y, z, c16, plum );
r = rc / (((yw * d) / rw) + (F2V (1.0f) - d));
g = gc / (((yw * d) / gw) + (F2V (1.0f) - d));
@ -756,7 +1077,7 @@ void Ciecam02::jch2xyz_ciecam02float ( vfloat &x, vfloat &y, vfloat &z, vfloat J
b = bp / (((yw * d) / bw) + (F2V (1.0f) - d));
}
cat02_to_xyzfloat ( x, y, z, r, g, b, c16 );
cat02_to_xyzfloat ( x, y, z, r, g, b, c16, plum );
}
#endif

View File

@ -37,12 +37,12 @@ class Ciecam02
private:
static float d_factorfloat ( float f, float la );
static float calculate_fl_from_la_ciecam02float ( float la );
static float achromatic_response_to_whitefloat ( float x, float y, float z, float d, float fl, float nbb, int c16);
static void xyz_to_cat02float ( float &r, float &g, float &b, float x, float y, float z, int c16);
static float achromatic_response_to_whitefloat ( float x, float y, float z, float d, float fl, float nbb, int c16, float plum);
static void xyz_to_cat02float ( float &r, float &g, float &b, float x, float y, float z, int c16, float plum);
static void cat02_to_hpefloat ( float &rh, float &gh, float &bh, float r, float g, float b, int c16);
#ifdef __SSE2__
static void xyz_to_cat02float ( vfloat &r, vfloat &g, vfloat &b, vfloat x, vfloat y, vfloat z, int c16);
static void xyz_to_cat02float ( vfloat &r, vfloat &g, vfloat &b, vfloat x, vfloat y, vfloat z, int c16, vfloat plum);
static void cat02_to_hpefloat ( vfloat &rh, vfloat &gh, vfloat &bh, vfloat r, vfloat g, vfloat b, int c16);
static vfloat nonlinear_adaptationfloat ( vfloat c, vfloat fl );
#endif
@ -53,13 +53,13 @@ private:
static void calculate_abfloat ( float &aa, float &bb, float h, float e, float t, float nbb, float a );
static void Aab_to_rgbfloat ( float &r, float &g, float &b, float A, float aa, float bb, float nbb );
static void hpe_to_xyzfloat ( float &x, float &y, float &z, float r, float g, float b, int c16);
static void cat02_to_xyzfloat ( float &x, float &y, float &z, float r, float g, float b, int c16);
static void cat02_to_xyzfloat ( float &x, float &y, float &z, float r, float g, float b, int c16, float plum);
#ifdef __SSE2__
static vfloat inverse_nonlinear_adaptationfloat ( vfloat c, vfloat fl );
static void calculate_abfloat ( vfloat &aa, vfloat &bb, vfloat h, vfloat e, vfloat t, vfloat nbb, vfloat a );
static void Aab_to_rgbfloat ( vfloat &r, vfloat &g, vfloat &b, vfloat A, vfloat aa, vfloat bb, vfloat nbb );
static void hpe_to_xyzfloat ( vfloat &x, vfloat &y, vfloat &z, vfloat r, vfloat g, vfloat b, int c16);
static void cat02_to_xyzfloat ( vfloat &x, vfloat &y, vfloat &z, vfloat r, vfloat g, vfloat b, int c16);
static void cat02_to_xyzfloat ( vfloat &x, vfloat &y, vfloat &z, vfloat r, vfloat g, vfloat b, int c16, vfloat plum);
#endif
public:
@ -67,46 +67,52 @@ public:
static void curvecolorfloat (float satind, float satval, float &sres, float parsat);
static void curveJfloat (float br, float contr, float thr, const LUTu & histogram, LUTf & outCurve ) ;
static void xyz2jzczhz (double &Jz, double &az, double &bz, double x, double y, double z, double pl, double &Lp, double &Mp, double &Sp, bool zcam);
static void jzczhzxyz (double &x, double &y, double &z, double Jz, double az, double bz, double pl, double &L, double &M, double &S, bool zcam);
/**
* Inverse transform from CIECAM02 JCh to XYZ.
*/
static void jch2xyz_ciecam02float ( float &x, float &y, float &z,
float J, float C, float h,
float xw, float yw, float zw,
float c, float nc, float n, float nbb, float ncb, float fl, float cz, float d, float aw, int c16);
float c, float nc, float n, float nbb, float ncb, float fl, float cz, float d, float aw, int c16, float plum);
#ifdef __SSE2__
static void jch2xyz_ciecam02float ( vfloat &x, vfloat &y, vfloat &z,
vfloat J, vfloat C, vfloat h,
vfloat xw, vfloat yw, vfloat zw,
vfloat nc, vfloat n, vfloat nbb, vfloat ncb, vfloat fl, vfloat d, vfloat aw, vfloat reccmcz, int c16 );
vfloat nc, vfloat n, vfloat nbb, vfloat ncb, vfloat fl, vfloat d, vfloat aw, vfloat reccmcz, int c16, vfloat plum );
#endif
/**
* Forward transform from XYZ to CIECAM02 JCh.
*/
static void initcam1float (float yb, float pilotd, float f, float la, float xw, float yw, float zw, float &n, float &d, float &nbb, float &ncb,
float &cz, float &aw, float &wh, float &pfl, float &fl, float c, int c16);
float &cz, float &aw, float &wh, float &pfl, float &fl, float c, int c16, float plum);
static void initcam2float (float yb, float pilotd, float f, float la, float xw, float yw, float zw, float &n, float &d, float &nbb, float &ncb,
float &cz, float &aw, float &fl, int c16);
float &cz, float &aw, float &fl, int c16, float plum);
static void xyz2jch_ciecam02float ( float &J, float &C, float &h,
float aw, float fl,
float x, float y, float z,
float xw, float yw, float zw,
float c, float nc, float n, float nbb, float ncb, float cz, float d, int c16);
float c, float nc, float n, float nbb, float ncb, float cz, float d, int c16, float plum);
static void xyz2jchqms_ciecam02float ( float &J, float &C, float &h,
float &Q, float &M, float &s, float aw, float fl, float wh,
float x, float y, float z,
float xw, float yw, float zw,
float c, float nc, float n, float nbb, float ncb, float pfl, float cz, float d, int c16);
float c, float nc, float n, float nbb, float ncb, float pfl, float cz, float d, int c16, float plum);
#ifdef __SSE2__
static void xyz2jchqms_ciecam02float ( vfloat &J, vfloat &C, vfloat &h,
vfloat &Q, vfloat &M, vfloat &s, vfloat aw, vfloat fl, vfloat wh,
vfloat x, vfloat y, vfloat z,
vfloat xw, vfloat yw, vfloat zw,
vfloat c, vfloat nc, vfloat n, vfloat nbb, vfloat ncb, vfloat pfl, vfloat cz, vfloat d, int c16);
vfloat c, vfloat nc, vfloat n, vfloat nbb, vfloat ncb, vfloat pfl, vfloat cz, vfloat d, int c16, vfloat plum);
#endif

View File

@ -24,6 +24,7 @@
#include "sleef.h"
#include "opthelper.h"
#include "iccstore.h"
#include <iostream>
using namespace std;
@ -944,6 +945,7 @@ void Color::xyz2Prophoto (float x, float y, float z, float &r, float &g, float &
g = ((prophoto_xyz[1][0] * x + prophoto_xyz[1][1] * y + prophoto_xyz[1][2] * z)) ;
b = ((prophoto_xyz[2][0] * x + prophoto_xyz[2][1] * y + prophoto_xyz[2][2] * z)) ;
}
void Color::Prophotoxyz (float r, float g, float b, float &x, float &y, float &z)
{
x = ((xyz_prophoto[0][0] * r + xyz_prophoto[0][1] * g + xyz_prophoto[0][2] * b)) ;
@ -1909,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
@ -1930,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++) {
@ -1954,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
@ -1889,6 +1896,59 @@ static inline void Lab2XYZ(vfloat L, vfloat a, vfloat b, vfloat &x, vfloat &y, v
return (hr);
}
static inline double huejz_to_huehsv2 (float HH)
{
//hr=translate Hue Jz value (-Pi +Pi) in approximative hr (hsv values) (0 1)
// with multi linear correspondences (I expect another time with Jz there is no error !!)
double hr = 0.0;
//always put h between 0 and 1
// make with my chart 468 colors...
// HH ==> Hz value ; hr HSv value
if (HH >= 0.2f && HH < 0.75f) {
hr = 0.12727273 * double(HH) + 0.90454551;//hr 0.93 1.00 full red
} else if (HH >= 0.75f && HH < 1.35f) {
hr = 0.15 * double(HH) - 0.1125;//hr 0.00 0.09 red yellow orange
} else if (HH >= 1.35f && HH < 1.85f) {
hr = 0.32 * double(HH) - 0.342; //hr 0.09 0.25 orange yellow
} else if (HH >= 1.85f && HH < 2.46f) {
hr = 0.23442623 * double(HH) -0.18368853;//hr 0.25 0.393 yellow green green
} else if (HH >= 2.46f && HH < 3.14159f) {
hr = 0.177526 * double(HH) -0.043714;//hr 0.393 0.51315 green ==> 0.42 Lab
} else if (HH >= -3.14159f && HH < -2.89f) {
hr = 0.3009078 * double(HH) + 1.459329;//hr 0.51315 0.5897 green cyan ==> -2.30 Lab
} else if (HH >= -2.89f && HH < -2.7f) {
hr = 0.204542 * double(HH) + 1.1808264;//hr 0.5897 0.628563 cyan
} else if (HH >= -2.7f && HH < -2.17f) {
hr = 0.121547 * double(HH) + 0.956399;//hr 0.628563 0.692642 blue blue-sky
} else if (HH >= -2.17f && HH < -0.9f) {
hr = 0.044882 * double(HH) + 0.789901;//hr 0.692642 0.749563 blue blue-sky
} else if (HH >= -0.9f && HH < -0.1f) {
hr = 0.2125 * double(HH) + 0.940813;//hr 0.749563 0.919563 purple magenta
} else if (HH >= -0.1f && HH < 0.2f) {
hr = 0.03479 * double(HH) + 0.923042;//hr 0.919563 0.93 red
}
// in case of !
if (hr < 0.0) {
hr += 1.0;
} else if(hr > 1.0) {
hr -= 1.0;
}
return (hr);
}
// HSV 0.93 1.0 red - Lab 0.0 0.6 Jz 0.20 0.75
// HSV 0.00 0.9 red orange - Lab 0.6 1.4 Jz 0.50 1.35
// HSV 0.09 0.25 oran - yellow - Lab 1.4 2.0 Jz 1.35 1.85
// HSV 0.25 0.39 yellow - gree - Lab 2.0 3.0 Jz 1.85 2.40
// HSV 0.39 0.50 green - cyan Lab 3.0 -2.8 Jz 2.40 3.10
// HSV 0.50 0.58 cyan Lab-2.8 -2.3 Jz 3.10 -2.90
// HSV 0.58 0.69 blue - sky Lab-2.3 -1.3 Jz -2.90 -2.17
// HSV 0.69 0.75 blue - Lab-1.3 -0.9 Jz -2.17 -0.90
// HSV 0.75 0.92 purple - Lab-0.9 -0.1 Jz -0.9 -0.10
// HSV 0.92 0.93 magenta Lab-0.1 0.0 Jz -0.1 0.20
static inline void RGB2Y(const float* R, const float* G, const float* B, float* Y1, float * Y2, int W) {
int i = 0;
#ifdef __SSE2__

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

@ -3460,12 +3460,13 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float
Color::Prophotoxyz(r, g, b, x, y, z);
float J, C, h;
int c16 = 1;
int c16 = 1;//always Cat02....to reserve compatibility
float plum = 100.f;
Ciecam02::xyz2jch_ciecam02float(J, C, h,
aw, fl,
x * 0.0015259022f, y * 0.0015259022f, z * 0.0015259022f,
xw, yw, zw,
c, nc, pow1, nbb, ncb, cz, d, c16);
c, nc, pow1, nbb, ncb, cz, d, c16, plum);
if (!isfinite(J) || !isfinite(C) || !isfinite(h)) {
@ -3583,7 +3584,7 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float
Ciecam02::jch2xyz_ciecam02float(x, y, z,
J, C, h,
xw, yw, zw,
c, nc, pow1, nbb, ncb, fl, cz, d, aw, c16);
c, nc, pow1, nbb, ncb, fl, cz, d, aw, c16, plum);
if (!isfinite(x) || !isfinite(y) || !isfinite(z)) {
// can happen for colours on the rim of being outside gamut, that worked without chroma scaling but not with. Then we return only the curve's result.
@ -3699,8 +3700,9 @@ void PerceptualToneCurve::init()
c = 0.69f;
nc = 1.00f;
int c16 = 1;//with cat02 for compatibility
float plum = 100.f;
Ciecam02::initcam1float(yb, 1.f, f, la, xw, yw, zw, n, d, nbb, ncb,
cz, aw, wh, pfl, fl, c, c16);
cz, aw, wh, pfl, fl, c, c16, plum);
pow1 = pow_F(1.64f - pow_F(0.29f, n), 0.73f);
{

View File

@ -142,11 +142,19 @@ protected:
double lx = xlog(x);
return m2 * x + (1.0 - m2) * (2.0 - xexp(k * lx)) * xexp(l * lx);
}
static inline double basel_alt(double x)
{
return (2.0 - x) * x * x * x;
}
// basic concave function between (0,0) and (1,1). m1 and m2 controls the slope at the start and end point
static inline double baseu(double x, double m1, double m2)
{
return 1.0 - basel(1.0 - x, m1, m2);
}
static inline double baseu_alt(double x)
{
return x * (2.0 + (x - 2.0) * x * x);
}
// convex curve between (0,0) and (1,1) with slope m at (0,0). hr controls the highlight recovery
static inline double cupper(double x, double m, double hr)
{
@ -448,6 +456,13 @@ protected:
{
return (1 - sh) * (1 - hl) * p00(x, prot) + sh * hl * p11(x, prot) + (1 - sh) * hl * p01(x, prot) + sh * (1 - hl) * p10(x, prot);
}
static inline double pfull_alt(double x, double sh, double hl)
{
double t = (1.0 - sh) * (1.0 - hl) * CurveFactory::basel_alt(x) + sh * hl * CurveFactory::baseu_alt(x);
return x <= 0.5
? t + (1.0 - sh) * hl * CurveFactory::basel_alt(2.0 * x) * 0.5 + sh * (1.0 - hl) * CurveFactory::baseu_alt(2.0 * x) * 0.5
: t + (1.0 - sh) * hl * (0.5 + CurveFactory::baseu_alt(2.0 * x - 1.0) * 0.5) + sh * (1.0 - hl) * (0.5 + CurveFactory::basel_alt(2.0 * x - 1.0) * 0.5);
}
void fillHash();
void fillDyByDx();

View File

@ -2114,7 +2114,7 @@ inline void DCPProfile::hsdApply(const HsdTableInfo& table_info, const std::vect
}
}
bool DCPProfile::isValid()
bool DCPProfile::isValid() const
{
return valid;
}
@ -2196,7 +2196,7 @@ void DCPStore::init(const Glib::ustring& rt_profile_dir, bool loadAll)
}
}
bool DCPStore::isValidDCPFileName(const Glib::ustring& filename) const
bool DCPStore::isValidDCPFileName(const Glib::ustring& filename)
{
if (!Glib::file_test(filename, Glib::FILE_TEST_EXISTS) || Glib::file_test(filename, Glib::FILE_TEST_IS_DIR)) {
return false;

View File

@ -63,7 +63,7 @@ public:
bool getHasBaselineExposureOffset() const;
Illuminants getIlluminants() const;
bool isValid();
bool isValid() const;
void apply(
Imagefloat* img,
@ -159,7 +159,7 @@ public:
void init(const Glib::ustring& rt_profile_dir, bool loadAll = true);
bool isValidDCPFileName(const Glib::ustring& filename) const;
static bool isValidDCPFileName(const Glib::ustring& filename);
DCPProfile* getProfile(const Glib::ustring& filename) const;
DCPProfile* getStdProfile(const Glib::ustring& camShortName) const;

View File

@ -21,7 +21,6 @@
/*RT*/#define LOCALTIME
/*RT*/#define DJGPP
/*RT*/#include "jpeg.h"
/*RT*/#include "lj92.h"
/*RT*/#ifdef _OPENMP
/*RT*/#include <omp.h>
/*RT*/#endif
@ -923,7 +922,7 @@ ushort * CLASS ljpeg_row (int jrow, struct jhead *jh)
}
getbits(-1);
}
FORC3 row[c] = (jh->row + ((jrow & 1) + 1) * (jh->wide*jh->clrs*((jrow+c) & 1)));
FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
for (col=0; col < jh->wide; col++)
FORC(jh->clrs) {
diff = ljpeg_diff (jh->huff[c]);
@ -1126,61 +1125,6 @@ void CLASS ljpeg_idct (struct jhead *jh)
FORC(64) jh->idct[c] = CLIP(((float *)work[2])[c]+0.5);
}
void CLASS lossless_dnglj92_load_raw()
{
BENCHFUN
tiff_bps = 16;
int save = ifp->pos;
uint16_t *lincurve = !strncmp(make,"Blackmagic",10) ? curve : nullptr;
tile_width = tile_length < INT_MAX ? tile_width : raw_width;
size_t tileCount = raw_width / tile_width;
size_t dataOffset[tileCount];
if(tile_length < INT_MAX) {
for (size_t t = 0; t < tileCount; ++t) {
dataOffset[t] = get4();
}
} else {
dataOffset[0] = ifp->pos;
}
const int data_length = ifp->size;
const std::unique_ptr<uint8_t[]> data(new uint8_t[data_length]);
fseek(ifp, 0, SEEK_SET);
// read whole file
fread(data.get(), 1, data_length, ifp);
lj92 lj;
int newwidth, newheight, newbps;
lj92_open(&lj, &data[dataOffset[0]], data_length, &newwidth, &newheight, &newbps);
lj92_close(lj);
if (newwidth * newheight * tileCount != raw_width * raw_height) {
// not a lj92 file
fseek(ifp, save, SEEK_SET);
lossless_dng_load_raw();
return;
}
#ifdef _OPENMP
#pragma omp parallel for num_threads(std::min<int>(tileCount, omp_get_max_threads()))
#endif
for (size_t t = 0; t < tileCount; ++t) {
size_t tcol = t * tile_width;
lj92 lj;
int newwidth, newheight, newbps;
lj92_open(&lj, &data[dataOffset[t]], data_length, &newwidth, &newheight, &newbps);
const std::unique_ptr<uint16_t[]> target(new uint16_t[newwidth * newheight]);
lj92_decode(lj, target.get(), tile_width, 0, lincurve, 0x1000);
for (int y = 0; y < height; ++y) {
for(int x = 0; x < tile_width; ++x) {
RAW(y, x + tcol) = target[y * tile_width + x];
}
}
lj92_close(lj);
}
}
void CLASS lossless_dng_load_raw()
{
unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col, i, j;
@ -2019,7 +1963,7 @@ void CLASS phase_one_load_raw_c()
#endif
{
int len[2], pred[2];
IMFILE ifpthr = *ifp;
rtengine::IMFILE ifpthr = *ifp;
ifpthr.plistener = nullptr;
#ifdef _OPENMP
@ -2520,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()
@ -3373,7 +3341,7 @@ void CLASS sony_arw2_load_raw()
{
uchar *data = new (std::nothrow) uchar[raw_width + 1];
merror(data, "sony_arw2_load_raw()");
IMFILE ifpthr = *ifp;
rtengine::IMFILE ifpthr = *ifp;
int pos = ifpthr.pos;
ushort pix[16];
@ -4453,6 +4421,12 @@ void CLASS crop_masked_pixels()
}
}
} else {
if (height + top_margin > raw_height) {
top_margin = raw_height - height;
}
if (width + left_margin > raw_width) {
left_margin = raw_width - width;
}
#ifdef _OPENMP
#pragma omp parallel for
#endif
@ -6111,13 +6085,56 @@ get2_256:
offsetChannelBlackLevel2 = save1 + (0x0149 << 1);
offsetWhiteLevels = save1 + (0x031c << 1);
break;
case 2024: // 1D X Mark III, ColorDataSubVer 32
// imCanon.ColorDataVer = 10;
imCanon.ColorDataSubVer = get2();
fseek(ifp, save1 + (0x0055 << 1), SEEK_SET);
FORC4 cam_mul[c ^ (c >> 1)/*RGGB_2_RGBG(c)*/] = (float)get2();
// get2();
// FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = get2();
// get2();
// FORC4 icWBC[LIBRAW_WBI_Measured][RGGB_2_RGBG(c)] = get2();
// fseek(ifp, save1 + (0x0096 << 1), SEEK_SET);
// Canon_WBpresets(2, 12);
// fseek(ifp, save1 + (0x0118 << 1), SEEK_SET);
// Canon_WBCTpresets(0);
offsetChannelBlackLevel = save1 + (0x0326 << 1);
offsetChannelBlackLevel2 = save1 + (0x0157 << 1);
offsetWhiteLevels = save1 + (0x032a << 1);
break;
case 3656: // EOS R6, ColorDataSubVer 33
// imCanon.ColorDataVer = 10;
imCanon.ColorDataSubVer = get2();
// The constant 0x0055 was found in LibRaw; more specifically by
// spelunking in LibRaw:src/metadata/canon.cpp.
fseek(ifp, save1 + (0x0055 << 1), SEEK_SET);
FORC4 cam_mul[c ^ (c >> 1)] = (float)get2();
offsetChannelBlackLevel = save1 + (0x326 << 1);
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;
}
@ -6129,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;
}
@ -6137,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;
}
@ -6324,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)
@ -6387,7 +6407,7 @@ int CLASS parse_tiff_ifd (int base)
unsigned sony_curve[] = { 0,0,0,0,0,4095 };
unsigned *buf, sony_offset=0, sony_length=0, sony_key=0;
struct jhead jh;
/*RT*/ IMFILE *sfp;
/*RT*/ rtengine::IMFILE *sfp;
/*RT*/ int pana_raw = 0;
if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0])
@ -6454,6 +6474,9 @@ int CLASS parse_tiff_ifd (int base)
case 3: case 257: case 61442: /* ImageHeight */
tiff_ifd[ifd].height = getint(type);
break;
case 254:
tiff_ifd[ifd].new_sub_file_type = getint(type);
break;
case 258: /* BitsPerSample */
case 61443:
tiff_ifd[ifd].samples = len & 7;
@ -6787,14 +6810,17 @@ guess_cfa_pc:
linear_table (len);
break;
case 50713: /* BlackLevelRepeatDim */
if (tiff_ifd[ifd].new_sub_file_type != 0) continue;
cblack[4] = get2();
cblack[5] = get2();
if (cblack[4] * cblack[5] > sizeof cblack / sizeof *cblack - 6)
cblack[4] = cblack[5] = 1;
break;
case 61450:
if (tiff_ifd[ifd].new_sub_file_type != 0) continue;
cblack[4] = cblack[5] = MIN(sqrt(len),64);
case 50714: /* BlackLevel */
if (tiff_ifd[ifd].new_sub_file_type != 0) continue;
RT_blacklevel_from_constant = ThreeValBool::F;
//-----------------------------------------------------------------------------
// taken from LibRaw.
@ -6912,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();
@ -6931,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);
@ -6951,7 +7016,7 @@ it under the terms of the one of two licenses as you choose:
fread (buf, sony_length, 1, ifp);
sony_decrypt (buf, sony_length/4, 1, sony_key);
sfp = ifp;
/*RT*/ ifp = fopen (buf, sony_length);
/*RT*/ ifp = rtengine::fopen (buf, sony_length);
// if ((ifp = tmpfile())) {
// fwrite (buf, sony_length, 1, ifp);
// fseek (ifp, 0, SEEK_SET);
@ -7259,7 +7324,7 @@ void CLASS parse_external_jpeg()
{
const char *file, *ext;
char *jname, *jfile, *jext;
/*RT*/ IMFILE *save=ifp;
/*RT*/ rtengine::IMFILE *save=ifp;
ext = strrchr (ifname, '.');
file = strrchr (ifname, '/');
@ -7287,7 +7352,7 @@ void CLASS parse_external_jpeg()
*jext = '0';
}
if (strcmp (jname, ifname)) {
/*RT*/ if ((ifp = fopen (jname))) {
/*RT*/ if ((ifp = rtengine::fopen (jname))) {
// if ((ifp = fopen (jname, "rb"))) {
if (verbose)
fprintf (stderr,_("Reading metadata from %s ...\n"), jname);
@ -9078,11 +9143,24 @@ void CLASS adobe_coeff (const char *make, const char *model)
RT_matrix_from_constant = ThreeValBool::T;
}
// -- RT --------------------------------------------------------------------
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;
@ -9231,6 +9309,7 @@ void CLASS identify()
{ 3944, 2622, 30, 18, 6, 2 },
{ 3948, 2622, 42, 18, 0, 2 },
{ 3984, 2622, 76, 20, 0, 2, 14 },
{ 4032, 2656, 112, 44, 10, 0 },
{ 4104, 3048, 48, 12, 24, 12 },
{ 4116, 2178, 4, 2, 0, 0 },
{ 4152, 2772, 192, 12, 0, 0 },
@ -9761,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;
@ -9768,7 +9849,7 @@ void CLASS identify()
switch (tiff_compress) {
case 0:
case 1: load_raw = &CLASS packed_dng_load_raw; break;
case 7: load_raw = (!strncmp(make,"Blackmagic",10) || !strncmp(make,"Canon",5)) ? &CLASS lossless_dnglj92_load_raw : &CLASS lossless_dng_load_raw; break;
case 7: load_raw = &CLASS lossless_dng_load_raw; break;
case 8: load_raw = &CLASS deflate_dng_load_raw; break;
case 34892: load_raw = &CLASS lossy_dng_load_raw; break;
default: load_raw = 0;
@ -9865,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;
@ -10048,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;
@ -10055,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;
@ -10531,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
@ -11015,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
{
@ -73,7 +77,7 @@ public:
protected:
int exif_base, ciff_base, ciff_len;
IMFILE *ifp;
rtengine::IMFILE *ifp;
FILE *ofp;
short order;
const char *ifname;
@ -125,7 +129,7 @@ protected:
int cur_buf_size; // buffer size
uchar *cur_buf; // currently read block
int fillbytes; // Counter to add extra byte for block size N*16
IMFILE *input;
rtengine::IMFILE *input;
struct int_pair grad_even[3][41]; // tables of gradients
struct int_pair grad_odd[3][41];
ushort *linealloc;
@ -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
@ -182,18 +188,41 @@ public:
int32_t hasTileCols;
int32_t hasTileRows;
int32_t mdatHdrSize;
int32_t medianBits;
// Not from header, but from datastream
uint32_t MediaSize;
int64_t MediaOffset;
uint32_t MediaType; /* 1 -> /C/RAW, 2-> JPEG */
};
static constexpr size_t CRXTRACKS_MAXCOUNT = 16;
static constexpr int CRXTRACKS_MAXCOUNT = 16;
crx_data_header_t crx_header[CRXTRACKS_MAXCOUNT];
unsigned int crx_track_selected;
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];
@ -209,7 +238,7 @@ protected:
} first_decode[2048], *second_decode, *free_decode;
struct tiff_ifd {
int width, height, bps, comp, phint, offset, flip, samples, bytes;
int new_sub_file_type, width, height, bps, comp, phint, offset, flip, samples, bytes;
int tile_width, tile_length, sample_format, predictor;
float shutter;
} tiff_ifd[10];
@ -278,7 +307,7 @@ void parse_redcine();
class getbithuff_t
{
public:
getbithuff_t(DCraw *p,IMFILE *&i, unsigned &z):parent(p),bitbuf(0),vbits(0),reset(0),ifp(i),zero_after_ff(z){}
getbithuff_t(DCraw *p,rtengine::IMFILE *&i, unsigned &z):parent(p),bitbuf(0),vbits(0),reset(0),ifp(i),zero_after_ff(z){}
unsigned operator()(int nbits, ushort *huff);
private:
@ -288,7 +317,7 @@ private:
DCraw *parent;
unsigned bitbuf;
int vbits, reset;
IMFILE *&ifp;
rtengine::IMFILE *&ifp;
unsigned &zero_after_ff;
};
getbithuff_t getbithuff;
@ -296,7 +325,7 @@ getbithuff_t getbithuff;
class nikbithuff_t
{
public:
explicit nikbithuff_t(IMFILE *&i):bitbuf(0),errors(0),vbits(0),ifp(i){}
explicit nikbithuff_t(rtengine::IMFILE *&i):bitbuf(0),errors(0),vbits(0),ifp(i){}
void operator()() {bitbuf = vbits = 0;};
unsigned operator()(int nbits, ushort *huff);
unsigned errorCount() { return errors; }
@ -309,7 +338,7 @@ private:
}
unsigned bitbuf, errors;
int vbits;
IMFILE *&ifp;
rtengine::IMFILE *&ifp;
};
nikbithuff_t nikbithuff;
@ -329,7 +358,6 @@ void ljpeg_idct (struct jhead *jh);
void canon_sraw_load_raw();
void adobe_copy_pixel (unsigned row, unsigned col, ushort **rp);
void lossless_dng_load_raw();
void lossless_dnglj92_load_raw();
void packed_dng_load_raw();
void deflate_dng_load_raw();
void init_fuji_compr(struct fuji_compressed_params* info);
@ -378,7 +406,7 @@ void parse_qt (int end);
// ph1_bithuff(int nbits, ushort *huff);
class ph1_bithuff_t {
public:
ph1_bithuff_t(DCraw *p, IMFILE *i, short &o):order(o),ifp(i),bitbuf(0),vbits(0){}
ph1_bithuff_t(DCraw *p, rtengine::IMFILE *i, short &o):order(o),ifp(i),bitbuf(0),vbits(0){}
unsigned operator()(int nbits, ushort *huff);
unsigned operator()(int nbits);
unsigned operator()();
@ -412,7 +440,7 @@ private:
}
short &order;
IMFILE* const ifp;
rtengine::IMFILE* const ifp;
UINT64 bitbuf;
int vbits;
};
@ -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();
@ -430,11 +459,11 @@ void nokia_load_raw();
class pana_bits_t{
public:
pana_bits_t(IMFILE *i, unsigned &u, unsigned enc):
pana_bits_t(rtengine::IMFILE *i, unsigned &u, unsigned enc):
ifp(i), load_flags(u), vbits(0), encoding(enc) {}
unsigned operator()(int nbits, unsigned *bytes=nullptr);
private:
IMFILE *ifp;
rtengine::IMFILE *ifp;
unsigned &load_flags;
uchar buf[0x4000];
int vbits;
@ -566,13 +595,13 @@ void parse_canon_cr3();
void selectCRXTrack(unsigned short maxTrack);
int parseCR3(unsigned long long oAtomList,
unsigned long long szAtomList, short &nesting,
char *AtomNameStack, unsigned short &nTrack, short &TrackType);
char *AtomNameStack, short &nTrack, short &TrackType);
bool crxDecodePlane(void *p, uint32_t planeNumber);
void crxLoadDecodeLoop(void *img, int nPlanes);
void crxConvertPlaneLineDf(void *p, int imageRow);
void crxLoadFinalizeLoopE3(void *p, int planeHeight);
void crxLoadRaw();
bool crxParseImageHeader(uchar *cmp1TagData, unsigned int nTrack);
bool crxParseImageHeader(uchar *cmp1TagData, int nTrack, int size);
//-----------------------------------------------------------------------------
};

View File

@ -19,9 +19,11 @@
*/
#include "cieimage.h"
#include "color.h"
#include "curves.h"
#include "dcp.h"
#include "dcrop.h"
#include "guidedfilter.h"
#include "image8.h"
#include "imagefloat.h"
#include "improccoordinator.h"
@ -30,9 +32,9 @@
#include "procparams.h"
#include "refreshmap.h"
#include "rt_math.h"
#include "color.h"
#include "utils.h"
#include "../rtgui/editcallbacks.h"
#include "guidedfilter.h"
#pragma GCC diagnostic warning "-Wall"
#pragma GCC diagnostic warning "-Wextra"
@ -52,7 +54,7 @@ namespace rtengine
{
Crop::Crop(ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow)
: PipetteBuffer(editDataProvider), origCrop(nullptr), laboCrop(nullptr), labnCrop(nullptr),
: PipetteBuffer(editDataProvider), origCrop(nullptr), spotCrop(nullptr), laboCrop(nullptr), labnCrop(nullptr),
cropImg(nullptr), shbuf_real(nullptr), transCrop(nullptr), cieCrop(nullptr), shbuffer(nullptr),
updating(false), newUpdatePending(false), skip(10),
cropx(0), cropy(0), cropw(-1), croph(-1),
@ -96,7 +98,7 @@ void Crop::setListener(DetailedCropListener* il)
}
}
EditUniqueID Crop::getCurrEditID()
EditUniqueID Crop::getCurrEditID() const
{
const EditSubscriber *subscriber = PipetteBuffer::dataProvider ? PipetteBuffer::dataProvider->getCurrSubscriber() : nullptr;
return subscriber ? subscriber->getEditID() : EUID_None;
@ -151,6 +153,7 @@ void Crop::update(int todo)
// give possibility to the listener to modify crop window (as the full image dimensions are already known at this point)
int wx, wy, ww, wh, ws;
const bool overrideWindow = cropImageListener;
bool spotsDone = false;
if (overrideWindow) {
cropImageListener->getWindow(wx, wy, ww, wh, ws);
@ -278,7 +281,7 @@ void Crop::update(int todo)
crW = 250;
}
// if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview
// if (settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview
if (settings->leveldnv == 2) {
crW = int (tileWskip / 2);
}
@ -402,7 +405,7 @@ void Crop::update(int todo)
crH = 250;
}
// if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview
// if (settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview
if (settings->leveldnv == 2) {
crW = int (tileWskip / 2);
crH = int (tileHskip / 2);
@ -607,12 +610,19 @@ void Crop::update(int todo)
//end evaluate noise
}
// if(params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PON") {//reinit origCrop after Auto
// if (params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PON") {//reinit origCrop after Auto
if ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) { //reinit origCrop after Auto
PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip);
parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw);
}
if ((todo & M_SPOT) && params.spot.enabled && !params.spot.entries.empty()) {
spotsDone = true;
PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip);
//parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw);
parent->ipf.removeSpots(origCrop, parent->imgsrc, params.spot.entries, pp, parent->currWB, nullptr, tr);
}
DirPyrDenoiseParams denoiseParams = params.dirpyrDenoise;
if (params.dirpyrDenoise.Lmethod == "CUR") {
@ -695,6 +705,28 @@ void Crop::update(int todo)
// has to be called after setCropSizes! Tools prior to this point can't handle the Edit mechanism, but that shouldn't be a problem.
createBuffer(cropw, croph);
// Apply Spot removal
if ((todo & M_SPOT) && !spotsDone) {
if (params.spot.enabled && !params.spot.entries.empty()) {
if(!spotCrop) {
spotCrop = new Imagefloat (cropw, croph);
}
baseCrop->copyData (spotCrop);
PreviewProps pp (trafx, trafy, trafw * skip, trafh * skip, skip);
int tr = getCoarseBitMask(params.coarse);
parent->ipf.removeSpots (spotCrop, parent->imgsrc, params.spot.entries, pp, parent->currWB, &params.icm, tr);
} else {
if (spotCrop) {
delete spotCrop;
spotCrop = nullptr;
}
}
}
if (spotCrop) {
baseCrop = spotCrop;
}
std::unique_ptr<Imagefloat> fattalCrop;
if ((todo & M_HDR) && (params.fattal.enabled || params.dehaze.enabled)) {
@ -720,7 +752,7 @@ void Crop::update(int todo)
parent->imgsrc->getImage(parent->currWB, tr, f, pp, params.toneCurve, params.raw);
parent->imgsrc->convertColorSpace(f, params.icm, parent->currWB);
if (params.dirpyrDenoise.enabled) {
if (params.dirpyrDenoise.enabled || params.filmNegative.enabled || params.spot.enabled) {
// copy the denoised crop
int oy = trafy / skip;
int ox = trafx / skip;
@ -840,6 +872,12 @@ void Crop::update(int todo)
auto& lmaskbllocalcurve2 = parent->lmaskbllocalcurve;
auto& lmasklclocalcurve2 = parent->lmasklclocalcurve;
auto& lmaskloglocalcurve2 = parent->lmaskloglocalcurve;
auto& lmaskcielocalcurve2 = parent->lmaskcielocalcurve;
auto& cielocalcurve2 = parent->cielocalcurve;
auto& cielocalcurve22 = parent->cielocalcurve2;
auto& jzlocalcurve2 = parent->jzlocalcurve;
auto& czlocalcurve2 = parent->czlocalcurve;
auto& czjzlocalcurve2 = parent->czjzlocalcurve;
auto& hltonecurveloc2 = parent->hltonecurveloc;
auto& shtonecurveloc2 = parent->shtonecurveloc;
auto& tonecurveloc2 = parent->tonecurveloc;
@ -849,6 +887,9 @@ void Crop::update(int todo)
auto& loclhCurve = parent->loclhCurve;
auto& lochhCurve = parent->lochhCurve;
auto& locchCurve = parent->locchCurve;
auto& lochhCurvejz = parent->lochhCurvejz;
auto& locchCurvejz = parent->locchCurvejz;
auto& loclhCurvejz = parent->loclhCurvejz;
auto& locccmasCurve = parent->locccmasCurve;
auto& locllmasCurve = parent->locllmasCurve;
auto& lochhmasCurve = parent->lochhmasCurve;
@ -880,12 +921,16 @@ void Crop::update(int todo)
auto& locccmaslogCurve = parent->locccmaslogCurve;
auto& locllmaslogCurve = parent->locllmaslogCurve;
auto& lochhmaslogCurve = parent->lochhmaslogCurve;
auto& locccmascieCurve = parent->locccmascieCurve;
auto& locllmascieCurve = parent->locllmascieCurve;
auto& lochhmascieCurve = parent->lochhmascieCurve;
auto& locccmas_Curve = parent->locccmas_Curve;
auto& locllmas_Curve = parent->locllmas_Curve;
auto& lochhmas_Curve = parent->lochhmas_Curve;
auto& lochhhmas_Curve = parent->lochhhmas_Curve;
auto& locwavCurve = parent->locwavCurve;
auto& locwavCurvejz = parent->locwavCurvejz;
auto& loclmasCurveblwav = parent->loclmasCurveblwav;
auto& loclmasCurvecolwav = parent->loclmasCurvecolwav;
auto& loclevwavCurve = parent->loclevwavCurve;
@ -897,13 +942,25 @@ void Crop::update(int todo)
auto& locwavCurveden = parent->locwavCurveden;
auto& lmasklocal_curve2 = parent->lmasklocal_curve;
auto& loclmasCurve_wav = parent->loclmasCurve_wav;
// const int sizespot = (int)params.locallab.spots.size();
/* float *huerefp = nullptr;
huerefp = new float[sizespot];
float *chromarefp = nullptr;
chromarefp = new float[sizespot];
float *lumarefp = nullptr;
lumarefp = new float[sizespot];
float *fabrefp = nullptr;
fabrefp = new float[sizespot];
*/
for (int sp = 0; sp < (int)params.locallab.spots.size(); sp++) {
locRETgainCurve.Set(params.locallab.spots.at(sp).localTgaincurve);
locRETtransCurve.Set(params.locallab.spots.at(sp).localTtranscurve);
const bool LHutili = loclhCurve.Set(params.locallab.spots.at(sp).LHcurve);
const bool HHutili = lochhCurve.Set(params.locallab.spots.at(sp).HHcurve);
const bool CHutili = locchCurve.Set(params.locallab.spots.at(sp).CHcurve);
const bool HHutilijz = lochhCurvejz.Set(params.locallab.spots.at(sp).HHcurvejz);
const bool CHutilijz = locchCurvejz.Set(params.locallab.spots.at(sp).CHcurvejz);
const bool LHutilijz = loclhCurvejz.Set(params.locallab.spots.at(sp).LHcurvejz);
const bool lcmasutili = locccmasCurve.Set(params.locallab.spots.at(sp).CCmaskcurve);
const bool llmasutili = locllmasCurve.Set(params.locallab.spots.at(sp).LLmaskcurve);
const bool lhmasutili = lochhmasCurve.Set(params.locallab.spots.at(sp).HHmaskcurve);
@ -932,6 +989,9 @@ void Crop::update(int todo)
const bool lcmaslogutili = locccmaslogCurve.Set(params.locallab.spots.at(sp).CCmaskcurveL);
const bool llmaslogutili = locllmaslogCurve.Set(params.locallab.spots.at(sp).LLmaskcurveL);
const bool lhmaslogutili = lochhmaslogCurve.Set(params.locallab.spots.at(sp).HHmaskcurveL);
const bool lcmascieutili = locccmascieCurve.Set(params.locallab.spots.at(sp).CCmaskciecurve);
const bool llmascieutili = locllmascieCurve.Set(params.locallab.spots.at(sp).LLmaskciecurve);
const bool lhmascieutili = lochhmascieCurve.Set(params.locallab.spots.at(sp).HHmaskciecurve);
const bool lcmas_utili = locccmas_Curve.Set(params.locallab.spots.at(sp).CCmask_curve);
const bool llmas_utili = locllmas_Curve.Set(params.locallab.spots.at(sp).LLmask_curve);
@ -944,6 +1004,7 @@ void Crop::update(int todo)
const bool llmaslcutili = locllmaslcCurve.Set(params.locallab.spots.at(sp).LLmasklccurve);
const bool lhmaslcutili = lochhmaslcCurve.Set(params.locallab.spots.at(sp).HHmasklccurve);
const bool locwavutili = locwavCurve.Set(params.locallab.spots.at(sp).locwavcurve);
const bool locwavutilijz = locwavCurvejz.Set(params.locallab.spots.at(sp).locwavcurvejz);
const bool locwavhueutili = locwavCurvehue.Set(params.locallab.spots.at(sp).locwavcurvehue);
const bool locwavdenutili = locwavCurveden.Set(params.locallab.spots.at(sp).locwavcurveden);
const bool loclevwavutili = loclevwavCurve.Set(params.locallab.spots.at(sp).loclevwavcurve);
@ -968,6 +1029,12 @@ void Crop::update(int todo)
const bool localmaskblutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskblcurve, lmaskbllocalcurve2, skip);
const bool localmasklogutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).LmaskcurveL, lmaskloglocalcurve2, skip);
const bool localmask_utili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmask_curve, lmasklocal_curve2, skip);
const bool localmaskcieutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).Lmaskciecurve, lmaskcielocalcurve2, skip);
const bool localcieutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).ciecurve, cielocalcurve2, skip);
const bool localcieutili2 = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).ciecurve2, cielocalcurve22, skip);
const bool localjzutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).jzcurve, jzlocalcurve2, skip);
const bool localczutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).czcurve, czlocalcurve2, skip);
const bool localczjzutili = CurveFactory::diagonalCurve2Lut(params.locallab.spots.at(sp).czjzcurve, czjzlocalcurve2, skip);
double ecomp = params.locallab.spots.at(sp).expcomp;
double black = params.locallab.spots.at(sp).black;
@ -975,7 +1042,7 @@ void Crop::update(int todo)
double hlcomprthresh = params.locallab.spots.at(sp).hlcomprthresh;
double shcompr = params.locallab.spots.at(sp).shcompr;
double br = params.locallab.spots.at(sp).lightness;
if(black < 0. && params.locallab.spots.at(sp).expMethod == "pde" ) {
if (black < 0. && params.locallab.spots.at(sp).expMethod == "pde" ) {
black *= 1.5;
}
@ -993,7 +1060,7 @@ void Crop::update(int todo)
float stdtme = parent->stdtms[sp];
float meanretie = parent->meanretis[sp];
float stdretie = parent->stdretis[sp];
float fab = 1.f;
float minCD;
float maxCD;
float mini;
@ -1003,16 +1070,27 @@ void Crop::update(int todo)
float Tmin;
float Tmax;
int lastsav;
/* huerefp[sp] = huere;
chromarefp[sp] = chromare;
lumarefp[sp] = lumare;
*/
CurveFactory::complexCurvelocal(ecomp, black / 65535., hlcompr, hlcomprthresh, shcompr, br, cont, lumare,
hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2, avge,
skip);
// Locallab mask are only shown for selected spot
int fh = parent->fh;
int fw = parent->fw;
if (sp == params.locallab.selspot) {
parent->ipf.Lab_Local(1, sp, (float**)shbuffer, labnCrop, labnCrop, reservCrop.get(), savenormtmCrop.get(), savenormretiCrop.get(), lastorigCrop.get(), cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, locRETtransCurve,
parent->ipf.Lab_Local(1, sp, (float**)shbuffer, labnCrop, labnCrop, reservCrop.get(), savenormtmCrop.get(), savenormretiCrop.get(), lastorigCrop.get(), fw, fh, cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, locRETtransCurve,
lllocalcurve2,locallutili,
cllocalcurve2, localclutili,
lclocalcurve2, locallcutili,
loclhCurve, lochhCurve, locchCurve,
lochhCurvejz, locchCurvejz, loclhCurvejz,
lmasklocalcurve2, localmaskutili,
lmaskexplocalcurve2, localmaskexputili,
lmaskSHlocalcurve2, localmaskSHutili,
@ -1024,6 +1102,12 @@ void Crop::update(int todo)
lmasklclocalcurve2, localmasklcutili,
lmaskloglocalcurve2, localmasklogutili,
lmasklocal_curve2, localmask_utili,
lmaskcielocalcurve2, localmaskcieutili,
cielocalcurve2,localcieutili,
cielocalcurve22,localcieutili2,
jzlocalcurve2,localjzutili,
czlocalcurve2,localczutili,
czjzlocalcurve2,localczjzutili,
locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili, lochhhmasCurve, lhhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili,
locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili,
@ -1036,10 +1120,13 @@ void Crop::update(int todo)
locccmaslogCurve, lcmaslogutili, locllmaslogCurve, llmaslogutili, lochhmaslogCurve, lhmaslogutili,
locccmas_Curve, lcmas_utili, locllmas_Curve, llmas_utili, lochhmas_Curve, lhmas_utili,
locccmascieCurve, lcmascieutili, locllmascieCurve, llmasSHutili, lochhmascieCurve, lhmascieutili,
lochhhmas_Curve, lhhmas_utili,
loclmasCurveblwav,lmasutiliblwav,
loclmasCurvecolwav,lmasutilicolwav,
locwavCurve, locwavutili,
locwavCurvejz, locwavutilijz,
loclevwavCurve, loclevwavutili,
locconwavCurve, locconwavutili,
loccompwavCurve, loccompwavutili,
@ -1048,12 +1135,14 @@ void Crop::update(int todo)
locwavCurveden, locwavdenutili,
locedgwavCurve, locedgwavutili,
loclmasCurve_wav,lmasutili_wav,
LHutili, HHutili, CHutili, cclocalcurve2, localcutili, rgblocalcurve2, localrgbutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2,
LHutili, HHutili, CHutili, HHutilijz, CHutilijz, LHutilijz, cclocalcurve2, localcutili, rgblocalcurve2, localrgbutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2,
huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, lastsav,
parent->previewDeltaE, parent->locallColorMask, parent->locallColorMaskinv, parent->locallExpMask, parent->locallExpMaskinv, parent->locallSHMask, parent->locallSHMaskinv, parent->locallvibMask, parent->localllcMask, parent->locallsharMask, parent->locallcbMask, parent->locallretiMask, parent->locallsoftMask, parent->localltmMask, parent->locallblMask,
parent->localllogMask, parent->locall_Mask, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax,
meantme, stdtme, meanretie, stdretie);
if(parent->previewDeltaE || parent->locallColorMask == 5 || parent->locallvibMask == 4 || parent->locallExpMask == 5 || parent->locallSHMask == 4 || parent->localllcMask == 4 || parent->localltmMask == 4 || parent->localllogMask == 4 || parent->locallsoftMask == 6 || parent->localllcMask == 4) {
parent->localllogMask, parent->locall_Mask, parent->locallcieMask, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax,
meantme, stdtme, meanretie, stdretie, fab);
// fabrefp[sp] = fab;
if (parent->previewDeltaE || parent->locallColorMask == 5 || parent->locallvibMask == 4 || parent->locallExpMask == 5 || parent->locallSHMask == 4 || parent->localllcMask == 4 || parent->localltmMask == 4 || parent->localllogMask == 4 || parent->locallsoftMask == 6 || parent->localllcMask == 4 || parent->locallcieMask == 4) {
params.blackwhite.enabled = false;
params.colorToning.enabled = false;
params.rgbCurves.enabled = false;
@ -1076,12 +1165,20 @@ void Crop::update(int todo)
params.epd.enabled = false;
params.softlight.enabled = false;
}
/*
if (parent->locallListener) {
parent->locallListener->refChanged2(huerefp, chromarefp, lumarefp, fabrefp, params.locallab.selspot);
}
*/
} else {
parent->ipf.Lab_Local(1, sp, (float**)shbuffer, labnCrop, labnCrop, reservCrop.get(), savenormtmCrop.get(), savenormretiCrop.get(), lastorigCrop.get(), cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, locRETtransCurve,
parent->ipf.Lab_Local(1, sp, (float**)shbuffer, labnCrop, labnCrop, reservCrop.get(), savenormtmCrop.get(), savenormretiCrop.get(), lastorigCrop.get(), fw, fh, cropx / skip, cropy / skip, skips(parent->fw, skip), skips(parent->fh, skip), skip, locRETgainCurve, locRETtransCurve,
lllocalcurve2,locallutili,
cllocalcurve2, localclutili,
lclocalcurve2, locallcutili,
loclhCurve, lochhCurve, locchCurve,
lochhCurvejz, locchCurvejz, loclhCurvejz,
lmasklocalcurve2, localmaskutili,
lmaskexplocalcurve2, localmaskexputili,
lmaskSHlocalcurve2, localmaskSHutili,
@ -1093,6 +1190,12 @@ void Crop::update(int todo)
lmasklclocalcurve2, localmasklcutili,
lmaskloglocalcurve2, localmasklogutili,
lmasklocal_curve2, localmask_utili,
lmaskcielocalcurve2, localmaskcieutili,
cielocalcurve2,localcieutili,
cielocalcurve22,localcieutili2,
jzlocalcurve2,localjzutili,
czlocalcurve2,localczutili,
czjzlocalcurve2,localczjzutili,
locccmasCurve, lcmasutili, locllmasCurve, llmasutili, lochhmasCurve, lhmasutili,lochhhmasCurve, lhhmasutili, locccmasexpCurve, lcmasexputili, locllmasexpCurve, llmasexputili, lochhmasexpCurve, lhmasexputili,
locccmasSHCurve, lcmasSHutili, locllmasSHCurve, llmasSHutili, lochhmasSHCurve, lhmasSHutili,
@ -1105,11 +1208,13 @@ void Crop::update(int todo)
locccmaslogCurve, lcmaslogutili, locllmaslogCurve, llmaslogutili, lochhmaslogCurve, lhmaslogutili,
locccmas_Curve, lcmas_utili, locllmas_Curve, llmas_utili, lochhmas_Curve, lhmas_utili,
locccmascieCurve, lcmascieutili, locllmascieCurve, llmascieutili, lochhmascieCurve, lhmascieutili,
lochhhmas_Curve, lhhmas_utili,
loclmasCurveblwav,lmasutiliblwav,
loclmasCurvecolwav,lmasutilicolwav,
locwavCurve, locwavutili,
locwavCurvejz, locwavutilijz,
loclevwavCurve, loclevwavutili,
locconwavCurve, locconwavutili,
loccompwavCurve, loccompwavutili,
@ -1118,10 +1223,10 @@ void Crop::update(int todo)
locwavCurveden, locwavdenutili,
locedgwavCurve, locedgwavutili,
loclmasCurve_wav,lmasutili_wav,
LHutili, HHutili, CHutili, cclocalcurve2, localcutili, rgblocalcurve2, localrgbutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2,
huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, lastsav, false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
LHutili, HHutili, CHutili, HHutilijz, CHutilijz, LHutilijz, cclocalcurve2, localcutili, rgblocalcurve2, localrgbutili, localexutili, exlocalcurve2, hltonecurveloc2, shtonecurveloc2, tonecurveloc2, lightCurveloc2,
huerefblu, chromarefblu, lumarefblu, huere, chromare, lumare, sobelre, lastsav, false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax,
meantme, stdtme, meanretie, stdretie);
meantme, stdtme, meanretie, stdretie, fab);
}
if (sp + 1u < params.locallab.spots.size()) {
// do not copy for last spot as it is not needed anymore
@ -1132,38 +1237,26 @@ void Crop::update(int todo)
Glib::usleep(settings->cropsleep); //wait to avoid crash when crop 100% and move window
}
}
/*
delete [] huerefp;
delete [] chromarefp;
delete [] lumarefp;
delete [] fabrefp;
*/
parent->ipf.lab2rgb(*labnCrop, *baseCrop, params.icm.workingProfile);
}
if (todo & M_RGBCURVE) {
Imagefloat *workingCrop = baseCrop;
/*
if (params.icm.workingTRC == "Custom") { //exec TRC IN free
const Glib::ustring profile = params.icm.workingProfile;
if (profile == "sRGB" || profile == "Adobe RGB" || profile == "ProPhoto" || profile == "WideGamut" || profile == "BruceRGB" || profile == "Beta RGB" || profile == "BestRGB" || profile == "Rec2020" || profile == "ACESp0" || profile == "ACESp1") {
const int cw = baseCrop->getWidth();
const int ch = baseCrop->getHeight();
workingCrop = new Imagefloat(cw, ch);
//first put gamma TRC to 1
parent->ipf.workingtrc(baseCrop, workingCrop, cw, ch, -5, params.icm.workingProfile, 2.4, 12.92310, parent->getCustomTransformIn(), true, false, true);
//adjust gamma TRC
parent->ipf.workingtrc(workingCrop, workingCrop, cw, ch, 5, params.icm.workingProfile, params.icm.workingTRCGamma, params.icm.workingTRCSlope, parent->getCustomTransformOut(), false, true, true);
}
}
*/
double rrm, ggm, bbm;
DCPProfileApplyState as;
DCPProfile *dcpProf = parent->imgsrc->getDCP(params.icm, as);
LUTu histToneCurve;
parent->ipf.rgbProc (workingCrop, laboCrop, this, parent->hltonecurve, parent->shtonecurve, parent->tonecurve,
parent->ipf.rgbProc (baseCrop, laboCrop, this, parent->hltonecurve, parent->shtonecurve, parent->tonecurve,
params.toneCurve.saturation, parent->rCurve, parent->gCurve, parent->bCurve, parent->colourToningSatLimit, parent->colourToningSatLimitOpacity, parent->ctColorCurve, parent->ctOpacityCurve, parent->opautili, parent->clToningcurve, parent->cl2Toningcurve,
parent->customToneCurve1, parent->customToneCurve2, parent->beforeToneCurveBW, parent->afterToneCurveBW, rrm, ggm, bbm,
parent->bwAutoR, parent->bwAutoG, parent->bwAutoB, dcpProf, as, histToneCurve);
if (workingCrop != baseCrop) {
delete workingCrop;
}
}
// apply luminance operations
@ -1228,7 +1321,7 @@ void Crop::update(int todo)
int minwin = min(labnCrop->W, labnCrop->H);
int maxlevelcrop = 10;
// if(cp.mul[9]!=0)maxlevelcrop=10;
// if (cp.mul[9]!=0)maxlevelcrop=10;
// adap maximum level wavelet to size of crop
if (minwin * skip < 1024) {
maxlevelcrop = 9; //sampling wavelet 512
@ -1314,7 +1407,7 @@ void Crop::update(int todo)
bool proton = WaveParams.exptoning;
bool pronois = WaveParams.expnoise;
if(WaveParams.showmask) {
if (WaveParams.showmask) {
// WaveParams.showmask = false;
// WaveParams.expclari = true;
}
@ -1441,7 +1534,7 @@ void Crop::update(int todo)
}
float indic = 1.f;
if(WaveParams.showmask){
if (WaveParams.showmask){
mL0 = mC0 = -1.f;
indic = -1.f;
mL = fabs(mL);
@ -1476,6 +1569,50 @@ void Crop::update(int todo)
parent->ipf.softLight(labnCrop, params.softlight);
if (params.icm.workingTRC != ColorManagementParams::WorkingTrc::NONE) {
const int GW = labnCrop->W;
const int GH = labnCrop->H;
std::unique_ptr<LabImage> provis;
const float pres = 0.01f * params.icm.preser;
if (pres > 0.f && params.icm.wprim != ColorManagementParams::Primaries::DEFAULT) {
provis.reset(new LabImage(GW, GH));
provis->CopyFrom(labnCrop);
}
const std::unique_ptr<Imagefloat> tmpImage1(new Imagefloat(GW, GH));
parent->ipf.lab2rgb(*labnCrop, *tmpImage1, params.icm.workingProfile);
const float gamtone = parent->params->icm.workingTRCGamma;
const float slotone = parent->params->icm.workingTRCSlope;
int illum = rtengine::toUnderlying(params.icm.will);
const int prim = rtengine::toUnderlying(params.icm.wprim);
Glib::ustring prof = params.icm.workingProfile;
cmsHTRANSFORM cmsDummy = nullptr;
int ill = 0;
parent->ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, -5, prof, 2.4, 12.92310, ill, 0, cmsDummy, true, false, false);
parent->ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, 5, prof, gamtone, slotone, illum, prim, cmsDummy, false, true, true);
parent->ipf.rgb2lab(*tmpImage1, *labnCrop, params.icm.workingProfile);
//labnCrop and provis
if (provis) {
parent->ipf.preserv(labnCrop, provis.get(), GW, GH);
}
if (params.icm.fbw) {
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int x = 0; x < GH; x++)
for (int y = 0; y < GW; y++) {
labnCrop->a[x][y] = 0.f;
labnCrop->b[x][y] = 0.f;
}
}
}
if (params.colorappearance.enabled) {
float fnum = parent->imgsrc->getMetaData()->getFNumber(); // F number
float fiso = parent->imgsrc->getMetaData()->getISOSpeed() ; // ISO
@ -1487,8 +1624,9 @@ void Crop::update(int todo)
adap = 2000.;
} else {
double E_V = fcomp + log2(double ((fnum * fnum) / fspeed / (fiso / 100.f)));
E_V += params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV
E_V += log2(params.raw.expos); // exposure raw white point ; log2 ==> linear to EV
double kexp = 0.;
E_V += kexp * params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV
E_V += 0.5 * log2(params.raw.expos); // exposure raw white point ; log2 ==> linear to EV
adap = pow(2., E_V - 3.); // cd / m2
// end calculation adaptation scene luminosity
}
@ -1519,6 +1657,8 @@ void Crop::update(int todo)
// all pipette buffer processing should be finished now
PipetteBuffer::setReady();
// Computing the preview image, i.e. converting from lab->Monitor color space (soft-proofing disabled) or lab->Output profile->Monitor color space (soft-proofing enabled)
parent->ipf.lab2monitorRgb(labnCrop, cropImg);
@ -1620,7 +1760,7 @@ bool check_need_larger_crop_for_lcp_distortion(int fw, int fh, int x, int y, int
* If the scale changes, this method will free all buffers and reallocate ones of the new size.
* It will then tell to the SizeListener that size has changed (sizeChanged)
*/
bool Crop::setCropSizes(int rcx, int rcy, int rcw, int rch, int skip, bool internal)
bool Crop::setCropSizes(int cropX, int cropY, int cropW, int cropH, int skip, bool internal)
{
if (!internal) {
@ -1629,10 +1769,10 @@ bool Crop::setCropSizes(int rcx, int rcy, int rcw, int rch, int skip, bool inter
bool changed = false;
rqcropx = rcx;
rqcropy = rcy;
rqcropw = rcw;
rqcroph = rch;
rqcropx = cropX;
rqcropy = cropY;
rqcropw = cropW;
rqcroph = cropH;
// store and set requested crop size
int rqx1 = LIM(rqcropx, 0, parent->fullw - 1);

View File

@ -38,6 +38,7 @@ class Crop final : public DetailedCrop, public PipetteBuffer
protected:
// --- permanently allocated in RAM and only renewed on size changes
Imagefloat* origCrop; // "one chunk" allocation
Imagefloat* spotCrop; // "one chunk" allocation
LabImage* laboCrop; // "one chunk" allocation
LabImage* labnCrop; // "one chunk" allocation
Image8* cropImg; // "one chunk" allocation ; displayed image in monitor color space, showing the output profile as well (soft-proofing enabled, which then correspond to workimg) or not
@ -64,7 +65,7 @@ protected:
MyMutex cropMutex;
ImProcCoordinator* const parent;
const bool isDetailWindow;
EditUniqueID getCurrEditID();
EditUniqueID getCurrEditID() const;
bool setCropSizes(int cropX, int cropY, int cropW, int cropH, int skip, bool internal);
void freeAll();

View File

@ -878,7 +878,7 @@ void RawImageSource::nodemosaic(bool bw)
for (int j = 0; j < W; j++) {
if (bw) {
red[i][j] = green[i][j] = blue[i][j] = rawData[i][j];
} else if(ri->getSensorType() != ST_FUJI_XTRANS) {
} else if(ri->getSensorType() == ST_BAYER) {
switch( FC(i, j)) {
case 0:
red[i][j] = rawData[i][j];
@ -895,7 +895,7 @@ void RawImageSource::nodemosaic(bool bw)
red[i][j] = green[i][j] = 0;
break;
}
} else {
} else if(ri->getSensorType() == ST_FUJI_XTRANS) {
switch( ri->XTRANSFC(i, j)) {
case 0:
red[i][j] = rawData[i][j];
@ -912,6 +912,10 @@ void RawImageSource::nodemosaic(bool bw)
red[i][j] = green[i][j] = 0;
break;
}
} else {
red[i][j] = rawData[i][j * 3 + 0];
green[i][j] = rawData[i][j * 3 + 1];
blue[i][j] = rawData[i][j * 3 + 2];
}
}
}

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;
@ -367,7 +549,7 @@ dfInfo* DFManager::addFileInfo (const Glib::ustring& filename, bool pool)
auto info = file->query_info("standard::name,standard::type,standard::is-hidden");
if (!info && info->get_file_type() == Gio::FILE_TYPE_DIRECTORY) {
if (!info || info->get_file_type() == Gio::FILE_TYPE_DIRECTORY) {
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);
/* 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 )
int rtengine::DFManager::Implementation::scanBadPixelsFile(const Glib::ustring& filename)
{
dfInfo *df = find( ((Glib::ustring)mak).uppercase(), ((Glib::ustring)mod).uppercase(), iso, shut, t );
FILE *file = ::fopen( filename.c_str(), "r" );
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();
}
if (!file) {
return 0;
}
dfInfo *df = addFileInfo( filename, false );
const auto lastdot = filename.find_last_of('.');
auto dirpos1 = filename.find_last_of('/');
auto dirpos2 = filename.find_last_of('\\');
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 )
{
FILE *file = fopen( filename.c_str(), "r" );
if( !file ) {
return false;
}
size_t lastdot = filename.find_last_of ('.');
size_t dirpos1 = filename.find_last_of ('/');
size_t 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;
}

View File

@ -116,8 +116,8 @@ DiagonalCurve::DiagonalCurve (const std::vector<double>& p, int poly_pn)
}
mc = -xlog(2.0) / xlog(x[2]);
double mbase = pfull (0.5, x[8], x[6], x[5]);
mfc = mbase <= 1e-14 ? 0.0 : xexp(xlog(mbase) / mc); // value of the curve at the center point
double mbase = pfull_alt (0.5, x[6], x[5]);
mfc = xexp(xlog(mbase) / mc); // value of the curve at the center point
msc = -xlog(2.0) / xlog(x[1] / x[2]);
mhc = -xlog(2.0) / xlog((x[3] - x[2]) / (1 - x[2]));
}
@ -424,7 +424,6 @@ void DiagonalCurve::catmull_rom_set()
/*****************************************************************************/
double DiagonalCurve::getVal (double t) const
{
@ -435,20 +434,24 @@ double DiagonalCurve::getVal (double t) const
return 0.0;
}
double tv = xexp(mc * xlog(t));
double base = pfull (tv, x[8], x[6], x[5]);
double stretched = base <= 1e-14 ? 0.0 : xexp(xlog(base) / mc);
double tv = xexp(max(mc * xlog(t),-236.0)); // prevents numerical issues when calling pfull, at the cost of minor artifacts
double base = pfull_alt (tv, x[6], x[5]);
double stretched = xexp(xlog(base) / mc);
if (t < x[2]) {
// add shadows effect:
double stv = xexp(msc * xlog(stretched / mfc));
double sbase = pfull (stv, x[8], x[7], 0.5);
return mfc * (sbase <= 1e-14 ? 0.0 : xexp(xlog(sbase) / msc));
double stv = xexp(max(msc * xlog(stretched / mfc),-236.0));
double sbase = pfull_alt (stv, x[7], 0.5);
return mfc * xexp(xlog(sbase) / msc);
} else {
// add highlights effect:
double htv = xexp(mhc * xlog((stretched - mfc) / (1 - mfc)));
double hbase = pfull (htv, x[8], 0.5, x[4]);
return mfc + (1 - mfc) * (hbase <= 1e-14 ? 0.0 : xexp(xlog(hbase) / mhc));
double htv = xexp(max(mhc * xlog((stretched - mfc) / (1.0 - mfc)),-236.0));
if (htv < 1e-6) {
return stretched; // this part of the curve isn't affected by highlight, return the base curve
} else {
double hbase = pfull_alt (htv, 0.5, x[4]);
return mfc + (1.0 - mfc) * xexp(xlog(hbase) / mhc);
}
}
break;

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()));
}
@ -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

@ -347,6 +347,23 @@ public:
}
}
/** Copy the a sub-region of the data to another PlanarRGBData */
void copyData(PlanarWhateverData<T> *dest, int x, int y, int width, int height)
{
assert (dest != NULL);
// Make sure that the size is the same, reallocate if necessary
dest->allocate(width, height);
if (dest->width == -1) {
printf("ERROR: PlanarRGBData::copyData >>> allocation failed!\n");
return;
}
for (int i = y, j = 0; i < y + height; ++i, ++j) {
memcpy (dest->v(i) + x, v(j), width * sizeof(T));
}
}
void rotate (int deg) override
{
@ -756,6 +773,25 @@ public:
}
}
/** Copy the a sub-region of the data to another PlanarRGBData */
void copyData(PlanarRGBData<T> *dest, int x, int y, int width, int height)
{
assert (dest != NULL);
// Make sure that the size is the same, reallocate if necessary
dest->allocate(width, height);
if (dest->width == -1) {
printf("ERROR: PlanarRGBData::copyData >>> allocation failed!\n");
return;
}
for (int i = y, j = 0; i < y + height; ++i, ++j) {
memcpy (dest->r(i) + x, r(j), width * sizeof(T));
memcpy (dest->g(i) + x, g(j), width * sizeof(T));
memcpy (dest->b(i) + x, b(j), width * sizeof(T));
}
}
void rotate (int deg) final
{
@ -1392,6 +1428,23 @@ public:
memcpy (dest->data, data, 3 * width * height * sizeof(T));
}
/** Copy the a sub-region of the data to another PlanarRGBData */
void copyData(ChunkyRGBData<T> *dest, int x, int y, int width, int height)
{
assert (dest != NULL);
// Make sure that the size is the same, reallocate if necessary
dest->allocate(width, height);
if (dest->width == -1) {
printf("ERROR: PlanarRGBData::copyData >>> allocation failed!\n");
return;
}
for (int i = y, j = 0; i < y + height; ++i, ++j) {
memcpy (dest->r(i) + x, r(j), 3 * width * sizeof(T));
}
}
void rotate (int deg) final
{

View File

@ -134,7 +134,21 @@ Image16* Image16::copy() const
return cp;
}
void Image16::getStdImage(const ColorTemp &ctemp, int tran, Imagefloat* image, PreviewProps pp) const
Image16* Image16::copySubRegion (int x, int y, int width, int height)
{
Image16* cp = NULL;
int realWidth = LIM<int>(x + width, 0, this->width) - x;
int realHeight = LIM<int>(y + height, 0, this->height) - y;
if (realWidth > 0 && realHeight > 0) {
cp = new Image16 (realWidth, realHeight);
copyData(cp, x, y, realWidth, realHeight);
}
return cp;
}
void Image16::getStdImage(const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp) const
{
// compute channel multipliers

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