diff --git a/.travis.yml.fixme b/.travis.yml.fixme new file mode 100644 index 000000000..0aa85f3b4 --- /dev/null +++ b/.travis.yml.fixme @@ -0,0 +1,44 @@ +sudo: required +dist: trusty + +language: cpp + +compiler: + - gcc + +os: + - linux + +#branches: +# only: +# - master + +notifications: + irc: + channels: + - "chat.freenode.net#rawtherapee" + skip_join: true + template: + - "%{repository}/%{branch} (%{commit} - %{author}): %{build_url}: %{message}" + email: + on_success: change + on_failure: always + +env: + global: + - OMP_NUM_THREADS=4 + +before_install: + - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y + - sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ xenial main" + - sudo apt-get -qq update + - sudo apt-get install gcc-6 g++-6 + - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 60 --slave /usr/bin/g++ g++ /usr/bin/g++-6 + - sudo apt-get install build-essential cmake curl git libbz2-dev libcanberra-gtk3-dev libexiv2-dev libexpat-dev libfftw3-dev libglibmm-2.4-dev libgtk-3-dev libgtkmm-3.0-dev libiptcdata0-dev libjpeg8-dev liblcms2-dev libpng12-dev libsigc++-2.0-dev libtiff5-dev zlib1g-dev + +before_script: + - mkdir build + - cd build + - cmake -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" -DWITH_LTO="OFF" -DPROC_TARGET_NUMBER="2" .. + +script: make diff --git a/AUTHORS.txt b/AUTHORS.txt index 6aebfcf6e..0ad8438eb 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -15,6 +15,7 @@ Developement contributors, in last name alphabetical order: Flössie Jean-Christophe Frisch Ilias Giarimis + Alberto Griggio Steve Herrell Philippe Hupé Wolfgang Kuehnel @@ -45,6 +46,7 @@ Other contributors (profiles, ideas, mockups, testing, forum activity, translati André Gauthier Sébastien Guyader M. Dávid Gyurkó + JK Han (pinholecam) Arturs Jekabsons Marián Kyral Oscar de Lama @@ -55,6 +57,8 @@ Other contributors (profiles, ideas, mockups, testing, forum activity, translati Wim ter Meer Alberto Righetto Kostia (Kildor) Romanov + Kalle Söderman Johan Thor + Vitalis Tiknius TooWaBoo Colin Walker diff --git a/CMakeLists.txt b/CMakeLists.txt index 77c0997d7..31a04b569 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,8 +21,8 @@ endif () string (TOUPPER ${CMAKE_BUILD_TYPE} UPPER_CMAKE_BUILD_TYPE) # Set required C and C++ standards and check GCC version -SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11") -SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") +SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11") +SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9") message(FATAL_ERROR "Building RawTherapee requires using GCC version 4.9 or higher!") diff --git a/rtdata/dcpprofiles/FUJIFILM X100S.dcp b/rtdata/dcpprofiles/FUJIFILM X100S.dcp new file mode 100644 index 000000000..962d58469 Binary files /dev/null and b/rtdata/dcpprofiles/FUJIFILM X100S.dcp differ diff --git a/rtdata/dcpprofiles/NIKON D300.dcp b/rtdata/dcpprofiles/NIKON D300.dcp index 6aafdc616..008383c59 100644 Binary files a/rtdata/dcpprofiles/NIKON D300.dcp and b/rtdata/dcpprofiles/NIKON D300.dcp differ diff --git a/rtdata/dcpprofiles/NIKON D810.dcp b/rtdata/dcpprofiles/NIKON D810.dcp index a946c1be2..2a32a1376 100644 Binary files a/rtdata/dcpprofiles/NIKON D810.dcp and b/rtdata/dcpprofiles/NIKON D810.dcp differ diff --git a/rtdata/languages/Catala b/rtdata/languages/Catala index 5fc720cfa..df7cc515d 100644 --- a/rtdata/languages/Catala +++ b/rtdata/languages/Catala @@ -972,6 +972,15 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !CURVEEDITOR_AXIS_OUT;O: !CURVEEDITOR_AXIS_RIGHT_TAN;RT: !CURVEEDITOR_EDITPOINT_HINT;Enable edition of node in/out values.\n\nRight-click on a node to select it.\nRight-click on empty space to de-select the node. +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels @@ -1280,6 +1289,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. @@ -1436,6 +1446,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !PREFERENCES_SIMPLAUT;Tool mode !PREFERENCES_SMA;Small (250x287) !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TIMAX;High !PREFERENCES_TINB;Number of tiles @@ -1450,6 +1461,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !PROFILEPANEL_GLOBALPROFILES;Bundled profiles !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_MYPROFILES;My profiles +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROGRESSBAR_NOIMAGES;No images found !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added @@ -2033,6 +2045,8 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !TP_WAVELET_TON;Toning !TP_WBALANCE_EQBLUERED;Blue/Red equalizer !TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behavior of "white balance" by modulating the blue/red balance.\nThis can be useful when shooting conditions:\na) are far from the standard illuminant (e.g. underwater),\nb) are far from conditions where calibrations were performed,\nc) where the matrices or ICC profiles are unsuitable. +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_WATER1;UnderWater 1 !TP_WBALANCE_WATER2;UnderWater 2 !TP_WBALANCE_WATER_HEADER;UnderWater diff --git a/rtdata/languages/Chinese (Simplified) b/rtdata/languages/Chinese (Simplified) index 64631d2b8..01dd62cdf 100644 --- a/rtdata/languages/Chinese (Simplified) +++ b/rtdata/languages/Chinese (Simplified) @@ -802,6 +802,15 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !CURVEEDITOR_PARAMETRIC;Parametric !CURVEEDITOR_TOOLTIPCOPY;Copy current curve to clipboard. !CURVEEDITOR_TOOLTIPPASTE;Paste curve from clipboard. +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) @@ -1197,6 +1206,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. !IPTCPANEL_COPYRIGHT;Copyright notice @@ -1310,7 +1320,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !PREFERENCES_DIRDARKFRAMES;Dark-frames directory !PREFERENCES_EDITORLAYOUT;Editor Layout !PREFERENCES_EXPAUT;Expert -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELDSDIR;Flat-fields directory !PREFERENCES_FLATFIELDSHOTS;shots @@ -1380,7 +1390,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels !PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -!PREFERENCES_SELECTFONT;Select global font +!PREFERENCES_SELECTFONT;Select main font !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font !PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings !PREFERENCES_SERIALIZE_TIFF_READ_LABEL;Serialize read of tiff files @@ -1398,6 +1408,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !PREFERENCES_SND_LNGEDITPROCDONE;Editor processing done !PREFERENCES_SND_TRESHOLDSECS;After seconds !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TIMAX;High !PREFERENCES_TINB;Number of tiles @@ -1416,6 +1427,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !PROFILEPANEL_LOADPPASTE;Parameters to load !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_PASTEPPASTE;Parameters to paste +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_SAVEPPASTE;Parameters to save !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved @@ -2041,5 +2053,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !TP_WBALANCE_LED_LSI;LSI Lumelex 2040 !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TUNGSTEN;Tungsten !ZOOMPANEL_ZOOMFITCROPSCREEN;Fit crop to screen\nShortcut: Alt-f diff --git a/rtdata/languages/Chinese (Traditional) b/rtdata/languages/Chinese (Traditional) index 90933541f..5d188ba67 100644 --- a/rtdata/languages/Chinese (Traditional) +++ b/rtdata/languages/Chinese (Traditional) @@ -458,6 +458,15 @@ TP_WBALANCE_TEMPERATURE;色溫 !CURVEEDITOR_TOOLTIPCOPY;Copy current curve to clipboard. !CURVEEDITOR_TOOLTIPPASTE;Paste curve from clipboard. !CURVEEDITOR_TYPE;Type: +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDITWINDOW_TITLE;Image Edit !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -934,6 +943,7 @@ TP_WBALANCE_TEMPERATURE;色溫 !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. @@ -1116,7 +1126,7 @@ TP_WBALANCE_TEMPERATURE;色溫 !PREFERENCES_DIRDARKFRAMES;Dark-frames directory !PREFERENCES_EDITORLAYOUT;Editor Layout !PREFERENCES_EXPAUT;Expert -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELD;Flat-Field !PREFERENCES_FLATFIELDFOUND;Found @@ -1190,7 +1200,7 @@ TP_WBALANCE_TEMPERATURE;色溫 !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels !PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -!PREFERENCES_SELECTFONT;Select global font +!PREFERENCES_SELECTFONT;Select main font !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font !PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings !PREFERENCES_SERIALIZE_TIFF_READ_LABEL;Serialize read of tiff files @@ -1208,6 +1218,7 @@ TP_WBALANCE_TEMPERATURE;色溫 !PREFERENCES_SND_LNGEDITPROCDONE;Editor processing done !PREFERENCES_SND_TRESHOLDSECS;After seconds !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TAB_SOUND;Sounds !PREFERENCES_TIMAX;High @@ -1231,6 +1242,7 @@ TP_WBALANCE_TEMPERATURE;色溫 !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_MYPROFILES;My profiles !PROFILEPANEL_PASTEPPASTE;Parameters to paste +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_SAVEPPASTE;Parameters to save !PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... @@ -2030,6 +2042,8 @@ TP_WBALANCE_TEMPERATURE;色溫 !TP_WBALANCE_SOLUX41;Solux 4100K !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TUNGSTEN;Tungsten !TP_WBALANCE_WATER1;UnderWater 1 !TP_WBALANCE_WATER2;UnderWater 2 diff --git a/rtdata/languages/Czech b/rtdata/languages/Czech index 6fa1fa8f7..4a6aa685f 100644 --- a/rtdata/languages/Czech +++ b/rtdata/languages/Czech @@ -2070,3 +2070,21 @@ ZOOMPANEL_ZOOMFITSCREEN;Přizpůsobit obrázek obrazovce\nZkratka: f ZOOMPANEL_ZOOMIN;Přiblížit\nZkratka: + ZOOMPANEL_ZOOMOUT;Oddálit\nZkratka: - +!!!!!!!!!!!!!!!!!!!!!!!!! +! Untranslated keys follow; remove the ! prefix after an entry is translated. +!!!!!!!!!!!!!!!!!!!!!!!!! + +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile +!HISTORY_MSG_444;WB - Temp bias +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules +!PROFILEPANEL_PDYNAMIC;Dynamic +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". diff --git a/rtdata/languages/Dansk b/rtdata/languages/Dansk index 1aa0d3788..7ace0541a 100644 --- a/rtdata/languages/Dansk +++ b/rtdata/languages/Dansk @@ -450,6 +450,15 @@ TP_WBALANCE_TEMPERATURE;Temperatur !CURVEEDITOR_TOOLTIPCOPY;Copy current curve to clipboard. !CURVEEDITOR_TOOLTIPPASTE;Paste curve from clipboard. !CURVEEDITOR_TYPE;Type: +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDITWINDOW_TITLE;Image Edit !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -930,6 +939,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. @@ -1114,7 +1124,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !PREFERENCES_DIRDARKFRAMES;Dark-frames directory !PREFERENCES_EDITORLAYOUT;Editor Layout !PREFERENCES_EXPAUT;Expert -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELD;Flat-Field !PREFERENCES_FLATFIELDFOUND;Found @@ -1188,7 +1198,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels !PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -!PREFERENCES_SELECTFONT;Select global font +!PREFERENCES_SELECTFONT;Select main font !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font !PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings !PREFERENCES_SERIALIZE_TIFF_READ_LABEL;Serialize read of tiff files @@ -1206,6 +1216,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !PREFERENCES_SND_LNGEDITPROCDONE;Editor processing done !PREFERENCES_SND_TRESHOLDSECS;After seconds !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TAB_SOUND;Sounds !PREFERENCES_TIMAX;High @@ -1229,6 +1240,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_MYPROFILES;My profiles !PROFILEPANEL_PASTEPPASTE;Parameters to paste +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_SAVEPPASTE;Parameters to save !PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... @@ -2029,6 +2041,8 @@ TP_WBALANCE_TEMPERATURE;Temperatur !TP_WBALANCE_SOLUX41;Solux 4100K !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TUNGSTEN;Tungsten !TP_WBALANCE_WATER1;UnderWater 1 !TP_WBALANCE_WATER2;UnderWater 2 diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 13da1e9fc..1d1c8275e 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -33,6 +33,9 @@ #32 2016-12-29 Erweiterung/Korrekturen (TooWaBoo) RT4.2.1464 #33 2017-01-04 Erweiterung/Korrekturen/Soft-Proofing (TooWaBoo) RT4.2.1477 #34 2017-01-07 IPTC (TooWaBoo) RT4.2.1492 +#35 2017-02-18 AWB bias (TooWaBoo) RT 5.0 r1 +#36 2017-02-23 Korrekturen (TooWaBoo) RT 5.0 r1 +#37 2017-03-06 Dynamisches Profil (TooWaBoo) ABOUT_TAB_BUILD;Version ABOUT_TAB_CREDITS;Danksagungen @@ -68,6 +71,15 @@ CURVEEDITOR_TOOLTIPPASTE;Kurve aus Zwischenablage einfügen CURVEEDITOR_TOOLTIPSAVE;Kurve speichern CURVEEDITOR_TYPE;Typ: DIRBROWSER_FOLDERS;Ordner +DYNPROFILEEDITOR_DELETE;Löschen +DYNPROFILEEDITOR_EDIT;Ändern +DYNPROFILEEDITOR_EDIT_RULE;Profilregel ändern +DYNPROFILEEDITOR_ENTRY_TOOLTIP;Groß-/Kleinschreibung wird NICHT berücksichtigt.\nFür einen regulären Ausdruck benutzen Sie bitte\n"re:" als Prefix. +DYNPROFILEEDITOR_MOVE_DOWN;Runter +DYNPROFILEEDITOR_MOVE_UP;Hoch +DYNPROFILEEDITOR_NEW;Neu +DYNPROFILEEDITOR_NEW_RULE;Profilregel erstellen +DYNPROFILEEDITOR_PROFILE;Profil EDITWINDOW_TITLE;Bildbearbeitung EDIT_OBJECT_TOOLTIP;Schaltet das Einstellungswerkzeug\nim Vorschaubild ein/aus EDIT_PIPETTE_TOOLTIP;Um einen Punkt der Kurve hinzuzufügen, halten Sie die Strg-Taste gedrückt und klicken mit der linke Maustaste auf die gewünschte Stelle in der Vorschau.\nUm den Punkt anzupassen, halten Sie die Strg-Taste gedrückt und klicken Sie mit der linken Maustaste auf den entsprechenden Bereich in der Vorschau. Dann lassen Sie die Strg-Taste los (es sei denn, Sie möchten eine Feineinstellung vornehmen) und bewegen die Maus bei gedrückter linker Maustaste nach oben oder unten, um den Punkt auf der Kurve zu bewegen. @@ -707,6 +719,7 @@ HISTORY_MSG_440;(Detailebenenkontrast)\nProzessreihenfolge HISTORY_MSG_441;(Retinex) - Einstellungen\nVerstärkung und Ausgleich\nTransmissionsverstärkung HISTORY_MSG_442;(Retinex) - Einstellungen\nTransmission - Skalierung HISTORY_MSG_443;(Farbmanagement)\nAusgabeprofil\nSchwarzpunkt-Kompensation +HISTORY_MSG_444;(Weißabgleich)\nAWB-Temperatur-Korrektur HISTORY_NEWSNAPSHOT;Hinzufügen HISTORY_NEWSNAPSHOT_TOOLTIP;Taste: Alt + s HISTORY_SNAPSHOT;Schnappschuss @@ -1080,7 +1093,7 @@ PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Öffnen eines neuen Bildes mit den Zoom- und PREFERENCES_RGBDTL_LABEL;Maximale Anzahl Threads für Rauschreduzierung PREFERENCES_RGBDTL_TOOLTIP;Die Rauschreduzierung benötigt mindestens 128MB RAM für ein 10 Megapixel-Bild oder 512MB für ein 40 Megapixel-Bild, und zusätzlich 128MB RAM pro Thread. Je mehr Threads parallel ablaufen, desto schneller ist die Berechnung. Bei Einstellung "0" werden so viele Threads wie möglich benutzt. PREFERENCES_SELECTFONT;Schriftart -PREFERENCES_SELECTFONT_COLPICKER;Schriftart für den Farbwähler +PREFERENCES_SELECTFONT_COLPICKER;Schriftart für die Farbwähler PREFERENCES_SELECTLANG;Sprache PREFERENCES_SELECTTHEME;Oberflächendesign (erfordert Neustart) PREFERENCES_SERIALIZE_TIFF_READ;TIFF-Bilder @@ -1105,6 +1118,7 @@ PREFERENCES_STARTUPIMDIR;Bildverzeichnis beim Programmstart PREFERENCES_STDAUT;Standard PREFERENCES_TAB_BROWSER;Dateiverwaltung PREFERENCES_TAB_COLORMGR;Farbmanagement +PREFERENCES_TAB_DYNAMICPROFILE;Dynamisches Profil PREFERENCES_TAB_GENERAL;Allgemein PREFERENCES_TAB_IMPROC;Bildbearbeitung PREFERENCES_TAB_PERFORMANCE;Performance & Qualität @@ -1133,6 +1147,7 @@ PROFILEPANEL_MODE_TIP;Ist der Button aktiviert, werden Teilprofile\nals vollstä PROFILEPANEL_MYPROFILES;Meine Profile PROFILEPANEL_PASTEPPASTE;Einzufügende Parameter PROFILEPANEL_PCUSTOM;Benutzerdefiniert +PROFILEPANEL_PDYNAMIC;Dynamisches Profil PROFILEPANEL_PFILE;Aus Datei PROFILEPANEL_PINTERNAL;Neutral PROFILEPANEL_PLASTSAVED;Zuletzt gespeichert @@ -1185,7 +1200,7 @@ THRESHOLDSELECTOR_HINT;Umschalt-Taste halten, um individuelle\nKontrollpu THRESHOLDSELECTOR_T;Oben THRESHOLDSELECTOR_TL;Oben-Links THRESHOLDSELECTOR_TR;Oben-Rechts -TOOLBAR_TOOLTIP_COLORPICKER;Farbwähler\n\nWenn eingeschaltet:\n- Mit der linken Maustaste können Sie einen Farbwähler setzen.\n- Zum Verschieben, linke Maustaste festhalten.\n- Umschalttaste + Rechts-Klick entfernt alle Farbwähler.\n- Rechts-Klick in einen freien Bereich schaltet auf das Hand-Werkzeug zurück. +TOOLBAR_TOOLTIP_COLORPICKER;Farbwähler\n\nWenn eingeschaltet:\n- Mit der linken Maustaste können Sie einen Farbwähler setzen.\n- Zum Verschieben, linke Maustaste festhalten.\n- Umschalttaste + Rechts-Klick entfernt alle Farbwähler.\n- Rechts-Klick auf den Farbwählerbutton blendet die Farbwähler ein/aus\n- Rechts-Klick in einen freien Bereich schaltet auf das Hand-Werkzeug zurück. TOOLBAR_TOOLTIP_CROP;Ausschnitt wählen\nTaste: c\n\nZum Verschieben des Ausschnitts,\nUmschalttaste festhalten. TOOLBAR_TOOLTIP_HAND;Hand-Werkzeug\nTaste: h TOOLBAR_TOOLTIP_STRAIGHTEN;Ausrichten / Drehen\nTaste: s\n\nRichtet das Bild entlang einer Leitlinie aus. @@ -1753,7 +1768,7 @@ TP_RETINEX_MAP_METHOD_TOOLTIP;Keine: Wendet die Maske, die mit der gaußs TP_RETINEX_MAP_NONE;Keine TP_RETINEX_MEDIAN;Medianfilter TP_RETINEX_METHOD;Methode -TP_RETINEX_METHOD_TOOLTIP;Schatten wirkt sich auf dunkle Bereiche aus.\n\nSchatten & Lichter wirkt sich auf dunkle und helle Bereiche aus.\n\nLichter wirkt sich auf helle Bereiche aus.\n\nSpitzlichter wirkt sich auf sehr helle Bereiche aus und reduziert\nMagenta-Falschfarben. +TP_RETINEX_METHOD_TOOLTIP;Schatten wirkt sich auf dunkle Bereiche aus.\n\nSchatten / Lichter wirkt sich auf dunkle und helle Bereiche aus.\n\nLichter wirkt sich auf helle Bereiche aus.\n\nSpitzlichter wirkt sich auf sehr helle Bereiche aus und reduziert\nMagenta-Falschfarben. TP_RETINEX_MLABEL;Schleierred: Min = %1, Max = %2 TP_RETINEX_MLABEL_TOOLTIP;Sollte nahe bei Min = 0 und Max = 32768 sein TP_RETINEX_NEIGHBOR;Radius @@ -1774,7 +1789,7 @@ TP_RETINEX_TLABEL_TOOLTIP;Ergebnis der Transmissionskurve: Min, Max, Mittel und TP_RETINEX_TRANF;Transmission TP_RETINEX_TRANSMISSION;Transmissionskurve TP_RETINEX_TRANSMISSION_TOOLTIP;Transmission in Abhängigkeit der Transmission.\n\nx-Achse: Transmission negativer Werte (Min),\nMittel und positiver Werte (Max).\n\ny-Achse: Verstärkung oder Abschwächung. -TP_RETINEX_UNIFORM;Schatten & Lichter +TP_RETINEX_UNIFORM;Schatten / Lichter TP_RETINEX_VARIANCE;Kontrast TP_RETINEX_VARIANCE_TOOLTIP;Niedrige Werte erhöhen den lokalen\nKontrast und die Sättigung, können\naber zu Artefakten führen. TP_RETINEX_VIEW;Vorschau @@ -2054,6 +2069,8 @@ TP_WBALANCE_SOLUX41;Solux 4100K TP_WBALANCE_SOLUX47;Solux 4700K (Vendor) TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) TP_WBALANCE_SPOTWB;Manuell setzen +TP_WBALANCE_TEMPBIAS;AWB-Temperatur-Korrektur +TP_WBALANCE_TEMPBIAS_TOOLTIP;Prozentuale Korrektur der Farbtemperatur des automatischen\nWeißabgleichs in Richtung wärmer oder kälter.\nDer Korreturwert berechnet sich aus:\nAWB-Temperatur + AWB-Temperatur * AWB-Temperatur-Korrektur TP_WBALANCE_TEMPERATURE;Farbtemperatur TP_WBALANCE_TUNGSTEN;Glühlampe TP_WBALANCE_WATER1;Unterwasser 1 diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index bf4734453..9a4910be1 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -142,6 +142,15 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !CURVEEDITOR_TOOLTIPSAVE;Save current curve. !CURVEEDITOR_TYPE;Type: !DIRBROWSER_FOLDERS;Folders +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDITWINDOW_TITLE;Image Edit !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -758,6 +767,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT;Add !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !HISTORY_SNAPSHOT;Snapshot @@ -1018,7 +1028,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !PREFERENCES_EXPAUT;Expert !PREFERENCES_EXTERNALEDITOR;External Editor !PREFERENCES_FBROWSEROPTS;File Browser / Thumbnail Options -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILEFORMAT;File format !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELD;Flat-Field @@ -1112,7 +1122,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels !PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -!PREFERENCES_SELECTFONT;Select global font +!PREFERENCES_SELECTFONT;Select main font !PREFERENCES_SELECTLANG;Select language !PREFERENCES_SELECTTHEME;Select theme !PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings @@ -1136,6 +1146,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !PREFERENCES_STARTUPIMDIR;Image Directory at Startup !PREFERENCES_STDAUT;Standard !PREFERENCES_TAB_BROWSER;File Browser +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_GENERAL;General !PREFERENCES_TAB_IMPROC;Image Processing !PREFERENCES_TAB_PERFORMANCE;Performance & Quality @@ -1164,6 +1175,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !PROFILEPANEL_MYPROFILES;My profiles !PROFILEPANEL_PASTEPPASTE;Parameters to paste !PROFILEPANEL_PCUSTOM;Custom +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PFILE;From file !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_PLASTSAVED;Last Saved @@ -2023,6 +2035,8 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) !TP_WBALANCE_SPOTWB;Spot WB +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TEMPERATURE;Temperature !TP_WBALANCE_TUNGSTEN;Tungsten !TP_WBALANCE_WATER1;UnderWater 1 diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index d5a0e16f2..6a9ab689b 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -37,6 +37,15 @@ !CURVEEDITOR_TOOLTIPSAVE;Save current curve. !CURVEEDITOR_TYPE;Type: !DIRBROWSER_FOLDERS;Folders +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDITWINDOW_TITLE;Image Edit !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -676,6 +685,7 @@ !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT;Add !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !HISTORY_SNAPSHOT;Snapshot @@ -947,7 +957,7 @@ !PREFERENCES_EXPAUT;Expert !PREFERENCES_EXTERNALEDITOR;External Editor !PREFERENCES_FBROWSEROPTS;File Browser / Thumbnail Options -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILEFORMAT;File format !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELD;Flat-Field @@ -1048,7 +1058,7 @@ !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels !PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -!PREFERENCES_SELECTFONT;Select global font +!PREFERENCES_SELECTFONT;Select main font !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font !PREFERENCES_SELECTLANG;Select language !PREFERENCES_SELECTTHEME;Select theme @@ -1074,6 +1084,7 @@ !PREFERENCES_STDAUT;Standard !PREFERENCES_TAB_BROWSER;File Browser !PREFERENCES_TAB_COLORMGR;Color Management +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_GENERAL;General !PREFERENCES_TAB_IMPROC;Image Processing !PREFERENCES_TAB_PERFORMANCE;Performance & Quality @@ -1102,6 +1113,7 @@ !PROFILEPANEL_MYPROFILES;My profiles !PROFILEPANEL_PASTEPPASTE;Parameters to paste !PROFILEPANEL_PCUSTOM;Custom +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PFILE;From file !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_PLASTSAVED;Last Saved @@ -2023,6 +2035,8 @@ !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) !TP_WBALANCE_SPOTWB;Spot WB +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TEMPERATURE;Temperature !TP_WBALANCE_TUNGSTEN;Tungsten !TP_WBALANCE_WATER1;UnderWater 1 diff --git a/rtdata/languages/Espanol b/rtdata/languages/Espanol index f9763dadb..170213157 100644 --- a/rtdata/languages/Espanol +++ b/rtdata/languages/Espanol @@ -1514,6 +1514,15 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !CURVEEDITOR_AXIS_OUT;O: !CURVEEDITOR_AXIS_RIGHT_TAN;RT: !CURVEEDITOR_EDITPOINT_HINT;Enable edition of node in/out values.\n\nRight-click on a node to select it.\nRight-click on empty space to de-select the node. +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !FILEBROWSER_POPUPCOLORLABEL0;Label: None !FILEBROWSER_SHOWNOTTRASHHINT;Show only non-deleted images. @@ -1674,6 +1683,7 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. !IPTCPANEL_COPYRIGHT;Copyright notice @@ -1778,6 +1788,7 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !PREFERENCES_SIMPLAUT;Tool mode !PREFERENCES_SMA;Small (250x287) !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TIMAX;High !PREFERENCES_TINB;Number of tiles !PREFERENCES_TISTD;Standard @@ -1786,6 +1797,7 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !PREFERENCES_WLONE;One level !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No +!PROFILEPANEL_PDYNAMIC;Dynamic !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. !SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. !SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. @@ -2100,4 +2112,6 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image. When the value is different from 0, the Strength and Gamma sliders of the Tone Mapping tool in the Exposure tab will become grayed out. !TP_WAVELET_TMTYPE;Compression method !TP_WAVELET_TON;Toning +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !ZOOMPANEL_ZOOMFITCROPSCREEN;Fit crop to screen\nShortcut: Alt-f diff --git a/rtdata/languages/Euskara b/rtdata/languages/Euskara index fb1b452dc..404505e11 100644 --- a/rtdata/languages/Euskara +++ b/rtdata/languages/Euskara @@ -450,6 +450,15 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !CURVEEDITOR_TOOLTIPCOPY;Copy current curve to clipboard. !CURVEEDITOR_TOOLTIPPASTE;Paste curve from clipboard. !CURVEEDITOR_TYPE;Type: +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDITWINDOW_TITLE;Image Edit !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -930,6 +939,7 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. @@ -1114,7 +1124,7 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !PREFERENCES_DIRDARKFRAMES;Dark-frames directory !PREFERENCES_EDITORLAYOUT;Editor Layout !PREFERENCES_EXPAUT;Expert -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELD;Flat-Field !PREFERENCES_FLATFIELDFOUND;Found @@ -1188,7 +1198,7 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels !PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -!PREFERENCES_SELECTFONT;Select global font +!PREFERENCES_SELECTFONT;Select main font !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font !PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings !PREFERENCES_SERIALIZE_TIFF_READ_LABEL;Serialize read of tiff files @@ -1206,6 +1216,7 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !PREFERENCES_SND_LNGEDITPROCDONE;Editor processing done !PREFERENCES_SND_TRESHOLDSECS;After seconds !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TAB_SOUND;Sounds !PREFERENCES_TIMAX;High @@ -1229,6 +1240,7 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_MYPROFILES;My profiles !PROFILEPANEL_PASTEPPASTE;Parameters to paste +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_SAVEPPASTE;Parameters to save !PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... @@ -2029,6 +2041,8 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !TP_WBALANCE_SOLUX41;Solux 4100K !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TUNGSTEN;Tungsten !TP_WBALANCE_WATER1;UnderWater 1 !TP_WBALANCE_WATER2;UnderWater 2 diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 937ac0927..0a7ea0edd 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -2035,3 +2035,21 @@ ZOOMPANEL_ZOOMFITSCREEN;Affiche l'image entière\nRaccourci: f ZOOMPANEL_ZOOMIN;Zoom Avant\nRaccourci: + ZOOMPANEL_ZOOMOUT;Zoom Arrière\nRaccourci: - +!!!!!!!!!!!!!!!!!!!!!!!!! +! Untranslated keys follow; remove the ! prefix after an entry is translated. +!!!!!!!!!!!!!!!!!!!!!!!!! + +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile +!HISTORY_MSG_444;WB - Temp bias +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules +!PROFILEPANEL_PDYNAMIC;Dynamic +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". diff --git a/rtdata/languages/Greek b/rtdata/languages/Greek index f57acf41a..57ec0b394 100644 --- a/rtdata/languages/Greek +++ b/rtdata/languages/Greek @@ -449,6 +449,15 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !CURVEEDITOR_TOOLTIPCOPY;Copy current curve to clipboard. !CURVEEDITOR_TOOLTIPPASTE;Paste curve from clipboard. !CURVEEDITOR_TYPE;Type: +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDITWINDOW_TITLE;Image Edit !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -929,6 +938,7 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. @@ -1113,7 +1123,7 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !PREFERENCES_DIRDARKFRAMES;Dark-frames directory !PREFERENCES_EDITORLAYOUT;Editor Layout !PREFERENCES_EXPAUT;Expert -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELD;Flat-Field !PREFERENCES_FLATFIELDFOUND;Found @@ -1187,7 +1197,7 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels !PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -!PREFERENCES_SELECTFONT;Select global font +!PREFERENCES_SELECTFONT;Select main font !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font !PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings !PREFERENCES_SERIALIZE_TIFF_READ_LABEL;Serialize read of tiff files @@ -1205,6 +1215,7 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !PREFERENCES_SND_LNGEDITPROCDONE;Editor processing done !PREFERENCES_SND_TRESHOLDSECS;After seconds !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TAB_SOUND;Sounds !PREFERENCES_TIMAX;High @@ -1228,6 +1239,7 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_MYPROFILES;My profiles !PROFILEPANEL_PASTEPPASTE;Parameters to paste +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_SAVEPPASTE;Parameters to save !PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... @@ -2028,6 +2040,8 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !TP_WBALANCE_SOLUX41;Solux 4100K !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TUNGSTEN;Tungsten !TP_WBALANCE_WATER1;UnderWater 1 !TP_WBALANCE_WATER2;UnderWater 2 diff --git a/rtdata/languages/Hebrew b/rtdata/languages/Hebrew index 0ed0c41bf..54d165be1 100644 --- a/rtdata/languages/Hebrew +++ b/rtdata/languages/Hebrew @@ -450,6 +450,15 @@ TP_WBALANCE_TEMPERATURE;מידת חום !CURVEEDITOR_TOOLTIPCOPY;Copy current curve to clipboard. !CURVEEDITOR_TOOLTIPPASTE;Paste curve from clipboard. !CURVEEDITOR_TYPE;Type: +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDITWINDOW_TITLE;Image Edit !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -930,6 +939,7 @@ TP_WBALANCE_TEMPERATURE;מידת חום !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. @@ -1114,7 +1124,7 @@ TP_WBALANCE_TEMPERATURE;מידת חום !PREFERENCES_DIRDARKFRAMES;Dark-frames directory !PREFERENCES_EDITORLAYOUT;Editor Layout !PREFERENCES_EXPAUT;Expert -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELD;Flat-Field !PREFERENCES_FLATFIELDFOUND;Found @@ -1188,7 +1198,7 @@ TP_WBALANCE_TEMPERATURE;מידת חום !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels !PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -!PREFERENCES_SELECTFONT;Select global font +!PREFERENCES_SELECTFONT;Select main font !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font !PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings !PREFERENCES_SERIALIZE_TIFF_READ_LABEL;Serialize read of tiff files @@ -1206,6 +1216,7 @@ TP_WBALANCE_TEMPERATURE;מידת חום !PREFERENCES_SND_LNGEDITPROCDONE;Editor processing done !PREFERENCES_SND_TRESHOLDSECS;After seconds !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TAB_SOUND;Sounds !PREFERENCES_TIMAX;High @@ -1229,6 +1240,7 @@ TP_WBALANCE_TEMPERATURE;מידת חום !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_MYPROFILES;My profiles !PROFILEPANEL_PASTEPPASTE;Parameters to paste +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_SAVEPPASTE;Parameters to save !PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... @@ -2029,6 +2041,8 @@ TP_WBALANCE_TEMPERATURE;מידת חום !TP_WBALANCE_SOLUX41;Solux 4100K !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TUNGSTEN;Tungsten !TP_WBALANCE_WATER1;UnderWater 1 !TP_WBALANCE_WATER2;UnderWater 2 diff --git a/rtdata/languages/Italiano b/rtdata/languages/Italiano index 613a29301..a79d46555 100644 --- a/rtdata/languages/Italiano +++ b/rtdata/languages/Italiano @@ -1345,6 +1345,15 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !CURVEEDITOR_AXIS_OUT;O: !CURVEEDITOR_AXIS_RIGHT_TAN;RT: !CURVEEDITOR_EDITPOINT_HINT;Enable edition of node in/out values.\n\nRight-click on a node to select it.\nRight-click on empty space to de-select the node. +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !FILEBROWSER_SHOWNOTTRASHHINT;Show only non-deleted images. !FILEBROWSER_SHOWORIGINALHINT;Show only original images.\n\nWhen several images exist with the same filename but different extensions, the one considered original is the one whose extension is nearest the top of the parsed extensions list in Preferences > File Browser > Parsed Extensions. @@ -1547,6 +1556,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. !IPTCPANEL_COPYRIGHT;Copyright notice @@ -1649,6 +1659,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !PREFERENCES_SIMPLAUT;Tool mode !PREFERENCES_SMA;Small (250x287) !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TIMAX;High !PREFERENCES_TINB;Number of tiles !PREFERENCES_TISTD;Standard @@ -1657,6 +1668,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !PREFERENCES_WLONE;One level !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No +!PROFILEPANEL_PDYNAMIC;Dynamic !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. !SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. !SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. @@ -2041,4 +2053,6 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image. When the value is different from 0, the Strength and Gamma sliders of the Tone Mapping tool in the Exposure tab will become grayed out. !TP_WAVELET_TMTYPE;Compression method !TP_WAVELET_TON;Toning +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !ZOOMPANEL_ZOOMFITCROPSCREEN;Fit crop to screen\nShortcut: Alt-f diff --git a/rtdata/languages/Japanese b/rtdata/languages/Japanese index 0ba1b52e4..38050e140 100644 --- a/rtdata/languages/Japanese +++ b/rtdata/languages/Japanese @@ -1884,6 +1884,15 @@ ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - ! Untranslated keys follow; remove the ! prefix after an entry is translated. !!!!!!!!!!!!!!!!!!!!!!!!! +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !FILEBROWSER_SHOWORIGINALHINT;Show only original images.\n\nWhen several images exist with the same filename but different extensions, the one considered original is the one whose extension is nearest the top of the parsed extensions list in Preferences > File Browser > Parsed Extensions. !GENERAL_APPLY;Apply !GENERAL_OPEN;Open @@ -1925,6 +1934,7 @@ ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. !IPTCPANEL_COPYRIGHT;Copyright notice @@ -1966,7 +1976,9 @@ ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - !PREFERENCES_PRTINTENT;Rendering intent !PREFERENCES_PRTPROFILE;Color profile !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TUNNELMETADATA;Copy Exif/IPTC/XMP unchanged to output file +!PROFILEPANEL_PDYNAMIC;Dynamic !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. !SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. !SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. @@ -2071,3 +2083,5 @@ ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - !TP_RETINEX_VIEW_TRAN;Transmission - Auto !TP_RETINEX_VIEW_TRAN2;Transmission - Fixed !TP_RETINEX_VIEW_UNSHARP;Unsharp mask +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". diff --git a/rtdata/languages/Latvian b/rtdata/languages/Latvian index bb9c63ea4..72d49e307 100644 --- a/rtdata/languages/Latvian +++ b/rtdata/languages/Latvian @@ -450,6 +450,15 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !CURVEEDITOR_TOOLTIPCOPY;Copy current curve to clipboard. !CURVEEDITOR_TOOLTIPPASTE;Paste curve from clipboard. !CURVEEDITOR_TYPE;Type: +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDITWINDOW_TITLE;Image Edit !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -930,6 +939,7 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. @@ -1114,7 +1124,7 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !PREFERENCES_DIRDARKFRAMES;Dark-frames directory !PREFERENCES_EDITORLAYOUT;Editor Layout !PREFERENCES_EXPAUT;Expert -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELD;Flat-Field !PREFERENCES_FLATFIELDFOUND;Found @@ -1188,7 +1198,7 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels !PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -!PREFERENCES_SELECTFONT;Select global font +!PREFERENCES_SELECTFONT;Select main font !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font !PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings !PREFERENCES_SERIALIZE_TIFF_READ_LABEL;Serialize read of tiff files @@ -1206,6 +1216,7 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !PREFERENCES_SND_LNGEDITPROCDONE;Editor processing done !PREFERENCES_SND_TRESHOLDSECS;After seconds !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TAB_SOUND;Sounds !PREFERENCES_TIMAX;High @@ -1229,6 +1240,7 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_MYPROFILES;My profiles !PROFILEPANEL_PASTEPPASTE;Parameters to paste +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_SAVEPPASTE;Parameters to save !PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... @@ -2029,6 +2041,8 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !TP_WBALANCE_SOLUX41;Solux 4100K !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TUNGSTEN;Tungsten !TP_WBALANCE_WATER1;UnderWater 1 !TP_WBALANCE_WATER2;UnderWater 2 diff --git a/rtdata/languages/Magyar b/rtdata/languages/Magyar index b2ae35fbe..2e3ce1f40 100644 --- a/rtdata/languages/Magyar +++ b/rtdata/languages/Magyar @@ -887,6 +887,15 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !CURVEEDITOR_AXIS_OUT;O: !CURVEEDITOR_AXIS_RIGHT_TAN;RT: !CURVEEDITOR_EDITPOINT_HINT;Enable edition of node in/out values.\n\nRight-click on a node to select it.\nRight-click on empty space to de-select the node. +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels @@ -1209,6 +1218,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. @@ -1373,6 +1383,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !PREFERENCES_SIMPLAUT;Tool mode !PREFERENCES_SMA;Small (250x287) !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TIMAX;High !PREFERENCES_TINB;Number of tiles @@ -1387,6 +1398,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !PROFILEPANEL_GLOBALPROFILES;Bundled profiles !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_MYPROFILES;My profiles +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROGRESSBAR_NOIMAGES;No images found !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved @@ -2036,6 +2048,8 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !TP_WAVELET_TON;Toning !TP_WBALANCE_EQBLUERED;Blue/Red equalizer !TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behavior of "white balance" by modulating the blue/red balance.\nThis can be useful when shooting conditions:\na) are far from the standard illuminant (e.g. underwater),\nb) are far from conditions where calibrations were performed,\nc) where the matrices or ICC profiles are unsuitable. +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_WATER1;UnderWater 1 !TP_WBALANCE_WATER2;UnderWater 2 !TP_WBALANCE_WATER_HEADER;UnderWater diff --git a/rtdata/languages/Nederlands b/rtdata/languages/Nederlands index adb37a61f..04d5bd4d5 100644 --- a/rtdata/languages/Nederlands +++ b/rtdata/languages/Nederlands @@ -1998,12 +1998,22 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - ! Untranslated keys follow; remove the ! prefix after an entry is translated. !!!!!!!!!!!!!!!!!!!!!!!!! +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !GENERAL_APPLY;Apply !GENERAL_OPEN;Open !HISTORY_MSG_439;Retinex - Process !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. !IPTCPANEL_COPYRIGHT;Copyright notice @@ -2037,6 +2047,8 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !PREFERENCES_PRTINTENT;Rendering intent !PREFERENCES_PRTPROFILE;Color profile !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules +!PROFILEPANEL_PDYNAMIC;Dynamic !SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. !SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. !TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a color picker\nDrag it around while pressing the left mouse button\nDelete the color picker with a right mouse button click\nDelete all color pickers with Shift + Right mouse button click\nRight click away from any color picker to go back to the Hand tool @@ -2058,3 +2070,5 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !TP_RETINEX_GAINTRANSMISSION_TOOLTIP;Amplify or reduce transmission map to achieve luminance.\nAbscissa: transmission -min from 0, mean, and values (max).\nOrdinate: gain. !TP_RETINEX_SKAL;Scale !TP_WAVELET_CB_TOOLTIP;For strong values product color-toning by combining it or not with levels decomposition 'toning'\nFor low values you can change the white balance of the background (sky, ...) without changing that of the front plane, generally more contrasted +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". diff --git a/rtdata/languages/Norsk BM b/rtdata/languages/Norsk BM index 40ed600c9..3d93ba84d 100644 --- a/rtdata/languages/Norsk BM +++ b/rtdata/languages/Norsk BM @@ -449,6 +449,15 @@ TP_WBALANCE_TEMPERATURE;Temperatur !CURVEEDITOR_TOOLTIPCOPY;Copy current curve to clipboard. !CURVEEDITOR_TOOLTIPPASTE;Paste curve from clipboard. !CURVEEDITOR_TYPE;Type: +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDITWINDOW_TITLE;Image Edit !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -929,6 +938,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. @@ -1113,7 +1123,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !PREFERENCES_DIRDARKFRAMES;Dark-frames directory !PREFERENCES_EDITORLAYOUT;Editor Layout !PREFERENCES_EXPAUT;Expert -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELD;Flat-Field !PREFERENCES_FLATFIELDFOUND;Found @@ -1187,7 +1197,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels !PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -!PREFERENCES_SELECTFONT;Select global font +!PREFERENCES_SELECTFONT;Select main font !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font !PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings !PREFERENCES_SERIALIZE_TIFF_READ_LABEL;Serialize read of tiff files @@ -1205,6 +1215,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !PREFERENCES_SND_LNGEDITPROCDONE;Editor processing done !PREFERENCES_SND_TRESHOLDSECS;After seconds !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TAB_SOUND;Sounds !PREFERENCES_TIMAX;High @@ -1228,6 +1239,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_MYPROFILES;My profiles !PROFILEPANEL_PASTEPPASTE;Parameters to paste +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_SAVEPPASTE;Parameters to save !PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... @@ -2028,6 +2040,8 @@ TP_WBALANCE_TEMPERATURE;Temperatur !TP_WBALANCE_SOLUX41;Solux 4100K !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TUNGSTEN;Tungsten !TP_WBALANCE_WATER1;UnderWater 1 !TP_WBALANCE_WATER2;UnderWater 2 diff --git a/rtdata/languages/Polish b/rtdata/languages/Polish index bbe23f2fd..8aedbc0cb 100644 --- a/rtdata/languages/Polish +++ b/rtdata/languages/Polish @@ -1472,6 +1472,15 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !CURVEEDITOR_AXIS_OUT;O: !CURVEEDITOR_AXIS_RIGHT_TAN;RT: !CURVEEDITOR_EDITPOINT_HINT;Enable edition of node in/out values.\n\nRight-click on a node to select it.\nRight-click on empty space to de-select the node. +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !FILEBROWSER_SHOWNOTTRASHHINT;Show only non-deleted images. !FILEBROWSER_SHOWORIGINALHINT;Show only original images.\n\nWhen several images exist with the same filename but different extensions, the one considered original is the one whose extension is nearest the top of the parsed extensions list in Preferences > File Browser > Parsed Extensions. @@ -1631,6 +1640,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. !IPTCPANEL_COPYRIGHT;Copyright notice @@ -1726,6 +1736,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !PREFERENCES_SIMPLAUT;Tool mode !PREFERENCES_SMA;Small (250x287) !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TIMAX;High !PREFERENCES_TINB;Number of tiles !PREFERENCES_TISTD;Standard @@ -1734,6 +1745,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !PREFERENCES_WLONE;One level !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No +!PROFILEPANEL_PDYNAMIC;Dynamic !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. !SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. !SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. @@ -2047,3 +2059,5 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image. When the value is different from 0, the Strength and Gamma sliders of the Tone Mapping tool in the Exposure tab will become grayed out. !TP_WAVELET_TMTYPE;Compression method !TP_WAVELET_TON;Toning +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". diff --git a/rtdata/languages/Polish (Latin Characters) b/rtdata/languages/Polish (Latin Characters) index fd1205a7d..207fcd12b 100644 --- a/rtdata/languages/Polish (Latin Characters) +++ b/rtdata/languages/Polish (Latin Characters) @@ -1472,6 +1472,15 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !CURVEEDITOR_AXIS_OUT;O: !CURVEEDITOR_AXIS_RIGHT_TAN;RT: !CURVEEDITOR_EDITPOINT_HINT;Enable edition of node in/out values.\n\nRight-click on a node to select it.\nRight-click on empty space to de-select the node. +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !FILEBROWSER_SHOWNOTTRASHHINT;Show only non-deleted images. !FILEBROWSER_SHOWORIGINALHINT;Show only original images.\n\nWhen several images exist with the same filename but different extensions, the one considered original is the one whose extension is nearest the top of the parsed extensions list in Preferences > File Browser > Parsed Extensions. @@ -1631,6 +1640,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. !IPTCPANEL_COPYRIGHT;Copyright notice @@ -1726,6 +1736,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !PREFERENCES_SIMPLAUT;Tool mode !PREFERENCES_SMA;Small (250x287) !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TIMAX;High !PREFERENCES_TINB;Number of tiles !PREFERENCES_TISTD;Standard @@ -1734,6 +1745,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !PREFERENCES_WLONE;One level !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No +!PROFILEPANEL_PDYNAMIC;Dynamic !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. !SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. !SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. @@ -2047,3 +2059,5 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image. When the value is different from 0, the Strength and Gamma sliders of the Tone Mapping tool in the Exposure tab will become grayed out. !TP_WAVELET_TMTYPE;Compression method !TP_WAVELET_TON;Toning +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". diff --git a/rtdata/languages/Portugues (Brasil) b/rtdata/languages/Portugues (Brasil) index 4643008f1..dee162661 100644 --- a/rtdata/languages/Portugues (Brasil) +++ b/rtdata/languages/Portugues (Brasil) @@ -450,6 +450,15 @@ TP_WBALANCE_TEMPERATURE;Temperatura !CURVEEDITOR_TOOLTIPCOPY;Copy current curve to clipboard. !CURVEEDITOR_TOOLTIPPASTE;Paste curve from clipboard. !CURVEEDITOR_TYPE;Type: +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDITWINDOW_TITLE;Image Edit !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -930,6 +939,7 @@ TP_WBALANCE_TEMPERATURE;Temperatura !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. @@ -1114,7 +1124,7 @@ TP_WBALANCE_TEMPERATURE;Temperatura !PREFERENCES_DIRDARKFRAMES;Dark-frames directory !PREFERENCES_EDITORLAYOUT;Editor Layout !PREFERENCES_EXPAUT;Expert -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELD;Flat-Field !PREFERENCES_FLATFIELDFOUND;Found @@ -1188,7 +1198,7 @@ TP_WBALANCE_TEMPERATURE;Temperatura !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels !PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -!PREFERENCES_SELECTFONT;Select global font +!PREFERENCES_SELECTFONT;Select main font !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font !PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings !PREFERENCES_SERIALIZE_TIFF_READ_LABEL;Serialize read of tiff files @@ -1206,6 +1216,7 @@ TP_WBALANCE_TEMPERATURE;Temperatura !PREFERENCES_SND_LNGEDITPROCDONE;Editor processing done !PREFERENCES_SND_TRESHOLDSECS;After seconds !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TAB_SOUND;Sounds !PREFERENCES_TIMAX;High @@ -1229,6 +1240,7 @@ TP_WBALANCE_TEMPERATURE;Temperatura !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_MYPROFILES;My profiles !PROFILEPANEL_PASTEPPASTE;Parameters to paste +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_SAVEPPASTE;Parameters to save !PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... @@ -2029,6 +2041,8 @@ TP_WBALANCE_TEMPERATURE;Temperatura !TP_WBALANCE_SOLUX41;Solux 4100K !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TUNGSTEN;Tungsten !TP_WBALANCE_WATER1;UnderWater 1 !TP_WBALANCE_WATER2;UnderWater 2 diff --git a/rtdata/languages/Russian b/rtdata/languages/Russian index 120d17530..7f7953a35 100644 --- a/rtdata/languages/Russian +++ b/rtdata/languages/Russian @@ -1281,6 +1281,15 @@ ZOOMPANEL_ZOOMOUT;Удалить - !CURVEEDITOR_AXIS_OUT;O: !CURVEEDITOR_AXIS_RIGHT_TAN;RT: !CURVEEDITOR_EDITPOINT_HINT;Enable edition of node in/out values.\n\nRight-click on a node to select it.\nRight-click on empty space to de-select the node. +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels @@ -1490,6 +1499,7 @@ ZOOMPANEL_ZOOMOUT;Удалить - !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. !IPTCPANEL_COPYRIGHT;Copyright notice @@ -1606,6 +1616,7 @@ ZOOMPANEL_ZOOMOUT;Удалить - !PREFERENCES_SIMPLAUT;Tool mode !PREFERENCES_SMA;Small (250x287) !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TIMAX;High !PREFERENCES_TINB;Number of tiles !PREFERENCES_TISTD;Standard @@ -1614,6 +1625,7 @@ ZOOMPANEL_ZOOMOUT;Удалить - !PREFERENCES_WLONE;One level !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No +!PROFILEPANEL_PDYNAMIC;Dynamic !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. !SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. !SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. @@ -2043,4 +2055,6 @@ ZOOMPANEL_ZOOMOUT;Удалить - !TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image. When the value is different from 0, the Strength and Gamma sliders of the Tone Mapping tool in the Exposure tab will become grayed out. !TP_WAVELET_TMTYPE;Compression method !TP_WAVELET_TON;Toning +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !ZOOMPANEL_ZOOMFITCROPSCREEN;Fit crop to screen\nShortcut: Alt-f diff --git a/rtdata/languages/Serbian (Cyrilic Characters) b/rtdata/languages/Serbian (Cyrilic Characters) index 6797ab195..a6237816d 100644 --- a/rtdata/languages/Serbian (Cyrilic Characters) +++ b/rtdata/languages/Serbian (Cyrilic Characters) @@ -1437,6 +1437,15 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !CURVEEDITOR_AXIS_RIGHT_TAN;RT: !CURVEEDITOR_EDITPOINT_HINT;Enable edition of node in/out values.\n\nRight-click on a node to select it.\nRight-click on empty space to de-select the node. !DIRBROWSER_FOLDERS;Folders +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels @@ -1657,6 +1666,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. !IPTCPANEL_COPYRIGHT;Copyright notice @@ -1772,6 +1782,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !PREFERENCES_SIMPLAUT;Tool mode !PREFERENCES_SMA;Small (250x287) !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TIMAX;High !PREFERENCES_TINB;Number of tiles !PREFERENCES_TISTD;Standard @@ -1779,6 +1790,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !PREFERENCES_WLONE;One level !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No +!PROFILEPANEL_PDYNAMIC;Dynamic !SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. !SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. !THRESHOLDSELECTOR_BL;Bottom-left @@ -2176,4 +2188,6 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image. When the value is different from 0, the Strength and Gamma sliders of the Tone Mapping tool in the Exposure tab will become grayed out. !TP_WAVELET_TMTYPE;Compression method !TP_WAVELET_TON;Toning +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !ZOOMPANEL_ZOOMFITCROPSCREEN;Fit crop to screen\nShortcut: Alt-f diff --git a/rtdata/languages/Serbian (Latin Characters) b/rtdata/languages/Serbian (Latin Characters) index 1a86a552a..227267045 100644 --- a/rtdata/languages/Serbian (Latin Characters) +++ b/rtdata/languages/Serbian (Latin Characters) @@ -1437,6 +1437,15 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !CURVEEDITOR_AXIS_RIGHT_TAN;RT: !CURVEEDITOR_EDITPOINT_HINT;Enable edition of node in/out values.\n\nRight-click on a node to select it.\nRight-click on empty space to de-select the node. !DIRBROWSER_FOLDERS;Folders +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels @@ -1657,6 +1666,7 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. !IPTCPANEL_COPYRIGHT;Copyright notice @@ -1772,6 +1782,7 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !PREFERENCES_SIMPLAUT;Tool mode !PREFERENCES_SMA;Small (250x287) !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TIMAX;High !PREFERENCES_TINB;Number of tiles !PREFERENCES_TISTD;Standard @@ -1779,6 +1790,7 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !PREFERENCES_WLONE;One level !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No +!PROFILEPANEL_PDYNAMIC;Dynamic !SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. !SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. !THRESHOLDSELECTOR_BL;Bottom-left @@ -2176,4 +2188,6 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image. When the value is different from 0, the Strength and Gamma sliders of the Tone Mapping tool in the Exposure tab will become grayed out. !TP_WAVELET_TMTYPE;Compression method !TP_WAVELET_TON;Toning +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !ZOOMPANEL_ZOOMFITCROPSCREEN;Fit crop to screen\nShortcut: Alt-f diff --git a/rtdata/languages/Slovak b/rtdata/languages/Slovak index 8e7957cf4..ca1ad5bf7 100644 --- a/rtdata/languages/Slovak +++ b/rtdata/languages/Slovak @@ -532,6 +532,15 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !CURVEEDITOR_MINMAXCPOINTS;Equalizer !CURVEEDITOR_TOOLTIPCOPY;Copy current curve to clipboard. !CURVEEDITOR_TOOLTIPPASTE;Paste curve from clipboard. +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDITWINDOW_TITLE;Image Edit !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -993,6 +1002,7 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. @@ -1164,7 +1174,7 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !PREFERENCES_DAUB_TOOLTIP;The Noise Reduction and Wavelet Levels tools use a Debauchies mother wavelet. If you choose D6 instead of D4 you increase the number of orthogonal Daubechies coefficients and probably increase quality of small-scale levels. There is no memory or processing time difference between the two. !PREFERENCES_DIRDARKFRAMES;Dark-frames directory !PREFERENCES_EXPAUT;Expert -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELD;Flat-Field !PREFERENCES_FLATFIELDFOUND;Found @@ -1250,6 +1260,7 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !PREFERENCES_SND_LNGEDITPROCDONE;Editor processing done !PREFERENCES_SND_TRESHOLDSECS;After seconds !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TAB_SOUND;Sounds !PREFERENCES_TIMAX;High @@ -1271,6 +1282,7 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_MYPROFILES;My profiles !PROFILEPANEL_PASTEPPASTE;Parameters to paste +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_SAVEPPASTE;Parameters to save !PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... @@ -2037,6 +2049,8 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !TP_WBALANCE_SOLUX41;Solux 4100K !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TUNGSTEN;Tungsten !TP_WBALANCE_WATER1;UnderWater 1 !TP_WBALANCE_WATER2;UnderWater 2 diff --git a/rtdata/languages/Suomi b/rtdata/languages/Suomi index d92c71c88..0994e6d44 100644 --- a/rtdata/languages/Suomi +++ b/rtdata/languages/Suomi @@ -451,6 +451,15 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !CURVEEDITOR_TOOLTIPCOPY;Copy current curve to clipboard. !CURVEEDITOR_TOOLTIPPASTE;Paste curve from clipboard. !CURVEEDITOR_TYPE;Type: +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDITWINDOW_TITLE;Image Edit !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -931,6 +940,7 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. @@ -1115,7 +1125,7 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !PREFERENCES_DIRDARKFRAMES;Dark-frames directory !PREFERENCES_EDITORLAYOUT;Editor Layout !PREFERENCES_EXPAUT;Expert -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELD;Flat-Field !PREFERENCES_FLATFIELDFOUND;Found @@ -1189,7 +1199,7 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels !PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -!PREFERENCES_SELECTFONT;Select global font +!PREFERENCES_SELECTFONT;Select main font !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font !PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings !PREFERENCES_SERIALIZE_TIFF_READ_LABEL;Serialize read of tiff files @@ -1207,6 +1217,7 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !PREFERENCES_SND_LNGEDITPROCDONE;Editor processing done !PREFERENCES_SND_TRESHOLDSECS;After seconds !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TAB_SOUND;Sounds !PREFERENCES_TIMAX;High @@ -1230,6 +1241,7 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_MYPROFILES;My profiles !PROFILEPANEL_PASTEPPASTE;Parameters to paste +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_SAVEPPASTE;Parameters to save !PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... @@ -2029,6 +2041,8 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !TP_WBALANCE_SOLUX41;Solux 4100K !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TUNGSTEN;Tungsten !TP_WBALANCE_WATER1;UnderWater 1 !TP_WBALANCE_WATER2;UnderWater 2 diff --git a/rtdata/languages/Swedish b/rtdata/languages/Swedish index d98dabc24..ceeec013e 100644 --- a/rtdata/languages/Swedish +++ b/rtdata/languages/Swedish @@ -1895,6 +1895,15 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !CURVEEDITOR_AXIS_LEFT_TAN;LT: !CURVEEDITOR_AXIS_RIGHT_TAN;RT: !CURVEEDITOR_EDITPOINT_HINT;Enable edition of node in/out values.\n\nRight-click on a node to select it.\nRight-click on empty space to de-select the node. +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !HISTORY_MSG_257;Color Toning !HISTORY_MSG_288;Flat Field - Clip control !HISTORY_MSG_289;Flat Field - Clip control - Auto @@ -1918,6 +1927,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !HISTORY_MSG_425;Retinex - Log base !HISTORY_MSG_427;Output rendering intent !HISTORY_MSG_428;Monitor rendering intent +!HISTORY_MSG_444;WB - Temp bias !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. !IPTCPANEL_COPYRIGHT;Copyright notice @@ -1956,6 +1966,8 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !PREFERENCES_PRTINTENT;Rendering intent !PREFERENCES_PRTPROFILE;Color profile !PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules +!PROFILEPANEL_PDYNAMIC;Dynamic !TP_CBDL_METHOD;Process located !TP_COLORTONING_CURVEEDITOR_CL_TOOLTIP;Chroma opacity as a function of luminance oC=f(L) !TP_COLORTONING_LABEL;Color Toning @@ -2043,3 +2055,5 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !TP_WAVELET_TILES_TOOLTIP;Processing the full image leads to better quality and is the recommended option, while using tiles is a fall-back solution for users with little RAM. Refer to RawPedia for memory requirements. !TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image. When the value is different from 0, the Strength and Gamma sliders of the Tone Mapping tool in the Exposure tab will become grayed out. !TP_WAVELET_TON;Toning +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". diff --git a/rtdata/languages/Turkish b/rtdata/languages/Turkish index 2e64516f1..342363700 100644 --- a/rtdata/languages/Turkish +++ b/rtdata/languages/Turkish @@ -450,6 +450,15 @@ TP_WBALANCE_TEMPERATURE;Isı !CURVEEDITOR_TOOLTIPCOPY;Copy current curve to clipboard. !CURVEEDITOR_TOOLTIPPASTE;Paste curve from clipboard. !CURVEEDITOR_TYPE;Type: +!DYNPROFILEEDITOR_DELETE;Delete +!DYNPROFILEEDITOR_EDIT;Edit +!DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +!DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +!DYNPROFILEEDITOR_MOVE_DOWN;Move Down +!DYNPROFILEEDITOR_MOVE_UP;Move Up +!DYNPROFILEEDITOR_NEW;New +!DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +!DYNPROFILEEDITOR_PROFILE;Processing Profile !EDITWINDOW_TITLE;Image Edit !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -930,6 +939,7 @@ TP_WBALANCE_TEMPERATURE;Isı !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_442;Retinex - Scale !HISTORY_MSG_443;Output Black Point Compensation +!HISTORY_MSG_444;WB - Temp bias !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !IPTCPANEL_CATEGORYHINT;Identifies the subject of the image in the opinion of the provider. !IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. @@ -1114,7 +1124,7 @@ TP_WBALANCE_TEMPERATURE;Isı !PREFERENCES_DIRDARKFRAMES;Dark-frames directory !PREFERENCES_EDITORLAYOUT;Editor Layout !PREFERENCES_EXPAUT;Expert -!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) +!PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar\n(de-select for low resolution display) !PREFERENCES_FILMSIMULATION;Film Simulation !PREFERENCES_FLATFIELD;Flat-Field !PREFERENCES_FLATFIELDFOUND;Found @@ -1188,7 +1198,7 @@ TP_WBALANCE_TEMPERATURE;Isı !PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". !PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels !PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -!PREFERENCES_SELECTFONT;Select global font +!PREFERENCES_SELECTFONT;Select main font !PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font !PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings !PREFERENCES_SERIALIZE_TIFF_READ_LABEL;Serialize read of tiff files @@ -1206,6 +1216,7 @@ TP_WBALANCE_TEMPERATURE;Isı !PREFERENCES_SND_LNGEDITPROCDONE;Editor processing done !PREFERENCES_SND_TRESHOLDSECS;After seconds !PREFERENCES_STDAUT;Standard +!PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_TAB_PERFORMANCE;Performance & Quality !PREFERENCES_TAB_SOUND;Sounds !PREFERENCES_TIMAX;High @@ -1229,6 +1240,7 @@ TP_WBALANCE_TEMPERATURE;Isı !PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial profiles will be converted to full profiles; the missing values will be replaced with hard-coded defaults.\n\nButton released: profiles will be applied as they are, altering only those values which they contain. !PROFILEPANEL_MYPROFILES;My profiles !PROFILEPANEL_PASTEPPASTE;Parameters to paste +!PROFILEPANEL_PDYNAMIC;Dynamic !PROFILEPANEL_PINTERNAL;Neutral !PROFILEPANEL_SAVEPPASTE;Parameters to save !PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... @@ -2028,6 +2040,8 @@ TP_WBALANCE_TEMPERATURE;Isı !TP_WBALANCE_SOLUX41;Solux 4100K !TP_WBALANCE_SOLUX47;Solux 4700K (vendor) !TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) +!TP_WBALANCE_TEMPBIAS;AWB temperature bias +!TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". !TP_WBALANCE_TUNGSTEN;Tungsten !TP_WBALANCE_WATER1;UnderWater 1 !TP_WBALANCE_WATER2;UnderWater 2 diff --git a/rtdata/languages/default b/rtdata/languages/default index fc5aa8881..4d3bdab5c 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -36,6 +36,15 @@ CURVEEDITOR_TOOLTIPPASTE;Paste curve from clipboard. CURVEEDITOR_TOOLTIPSAVE;Save current curve. CURVEEDITOR_TYPE;Type: DIRBROWSER_FOLDERS;Folders +DYNPROFILEEDITOR_DELETE;Delete +DYNPROFILEEDITOR_EDIT;Edit +DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule +DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +DYNPROFILEEDITOR_MOVE_DOWN;Move Down +DYNPROFILEEDITOR_MOVE_UP;Move Up +DYNPROFILEEDITOR_NEW;New +DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule +DYNPROFILEEDITOR_PROFILE;Processing Profile EDITWINDOW_TITLE;Image Edit EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. @@ -675,6 +684,37 @@ HISTORY_MSG_440;CbDL - Method HISTORY_MSG_441;Retinex - Gain transmission HISTORY_MSG_442;Retinex - Scale HISTORY_MSG_443;Output Black Point Compensation +HISTORY_MSG_444;WB - Temp bias +HISTORY_MSG_445;Raw Sub-Image +HISTORY_MSG_446;EvPixelShiftMotion +HISTORY_MSG_447;EvPixelShiftMotionCorrection +HISTORY_MSG_448;EvPixelShiftStddevFactorGreen +HISTORY_MSG_449;PS ISO adaption +HISTORY_MSG_450;EvPixelShiftNreadIso +HISTORY_MSG_451;EvPixelShiftPrnu +HISTORY_MSG_452;PS Show motion +HISTORY_MSG_453;PS Show mask only +HISTORY_MSG_454;EvPixelShiftAutomatic +HISTORY_MSG_455;EvPixelShiftNonGreenHorizontal +HISTORY_MSG_456;EvPixelShiftNonGreenVertical +HISTORY_MSG_457;PS Check red/blue +HISTORY_MSG_458;EvPixelShiftStddevFactorRed +HISTORY_MSG_459;EvPixelShiftStddevFactorBlue +HISTORY_MSG_460;EvPixelShiftGreenAmaze +HISTORY_MSG_461;EvPixelShiftNonGreenAmaze +HISTORY_MSG_462;PS Check green +HISTORY_MSG_463;EvPixelShiftRedBlueWeight +HISTORY_MSG_464;PS Blur motion mask +HISTORY_MSG_465;PS Blur radius +HISTORY_MSG_466;EvPixelShiftSum +HISTORY_MSG_467;EvPixelShiftExp0 +HISTORY_MSG_468;PS Fill holes +HISTORY_MSG_469;PS Median +HISTORY_MSG_470;EvPixelShiftMedian3 +HISTORY_MSG_471;PS Motion correction +HISTORY_MSG_472;PS Smooth transitions +HISTORY_MSG_473;PS Use lmmse +HISTORY_MSG_474;PS Equalize HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOT;Snapshot @@ -865,6 +905,7 @@ PARTIALPASTE_RAW_DCBENHANCE;DCB enhancement PARTIALPASTE_RAW_DCBITERATIONS;DCB iterations PARTIALPASTE_RAW_DMETHOD;Demosaic method PARTIALPASTE_RAW_FALSECOLOR;False color suppression +PARTIALPASTE_RAW_IMAGENUM;Sub-image PARTIALPASTE_RAW_LMMSEITERATIONS;LMMSE enhancement steps PARTIALPASTE_RESIZE;Resize PARTIALPASTE_RETINEX;Retinex @@ -1073,6 +1114,7 @@ PREFERENCES_STARTUPIMDIR;Image Directory at Startup PREFERENCES_STDAUT;Standard PREFERENCES_TAB_BROWSER;File Browser PREFERENCES_TAB_COLORMGR;Color Management +PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules PREFERENCES_TAB_GENERAL;General PREFERENCES_TAB_IMPROC;Image Processing PREFERENCES_TAB_PERFORMANCE;Performance & Quality @@ -1101,6 +1143,7 @@ PROFILEPANEL_MODE_TIP;Processing profile fill mode.\n\nButton pressed: partial p PROFILEPANEL_MYPROFILES;My profiles PROFILEPANEL_PASTEPPASTE;Parameters to paste PROFILEPANEL_PCUSTOM;Custom +PROFILEPANEL_PDYNAMIC;Dynamic PROFILEPANEL_PFILE;From file PROFILEPANEL_PINTERNAL;Neutral PROFILEPANEL_PLASTSAVED;Last Saved @@ -1648,13 +1691,60 @@ TP_RAW_DCBITERATIONS;Number of DCB iterations TP_RAW_DMETHOD;Method TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... -TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look. +TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixelshift is for Pentax pixelshift files. It falls back to Amaze for non pixelshift files. TP_RAW_FALSECOLOR;False color suppression steps TP_RAW_HD;Threshold TP_RAW_HD_TOOLTIP;Lower values make hot/dead pixel detection more aggressive, but false positives may lead to artifacts. If you notice any artifacts appearing when enabling the Hot/Dead Pixel Filters, gradually increase the threshold value until they disappear. +TP_RAW_IMAGENUM;Sub-image +TP_RAW_IMAGENUM_TOOLTIP;Some raw files might embed several sub-images (HDR, Pixel-Shift, Dual Sensitivity). Use this button to select the sub-image.\n\nThe last sub-image will be used if you select a value beyond the real sub-image count. TP_RAW_LABEL;Demosaicing TP_RAW_LMMSEITERATIONS;LMMSE enhancement steps TP_RAW_LMMSE_TOOLTIP;Adds gamma (step 1), median (steps 2-4) and refinement (steps 5-6) to reduce artifacts and improve the signal-to-noise ratio. +TP_RAW_PIXELSHIFTADAPTIVE;Adaptive detection +TP_RAW_PIXELSHIFTNONGREENHORIZONTAL;Check red/blue horizontal +TP_RAW_PIXELSHIFTNONGREENVERTICAL;Check red/blue vertical +TP_RAW_PIXELSHIFTMEDIAN;Median +TP_RAW_PIXELSHIFTMEDIAN3;Exclude selected frame from median +TP_RAW_PIXELSHIFTHOLEFILL;Fill holes in motion mask +TP_RAW_PIXELSHIFTBLUR;Blur motion mask +TP_RAW_PIXELSHIFTSIGMA_TOOLTIP;Default radius of 1.0 usually fits good for base ISO. Increase value for high ISO shots,\n5.0 is a good starting point for high ISO shots.\nWatch motion mask while changing the value. +TP_RAW_PIXELSHIFTSMOOTH;Smooth transitions +TP_RAW_PIXELSHIFTLMMSE_TOOLTIP;Use lmmse instead of amaze for motion areas.\nUseful for High ISO images. +TP_RAW_PIXELSHIFTLMMSE;Use lmmse for motion parts +TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames +TP_RAW_PIXELSHIFTEQUALBRIGHT_TOOLTIP;Equalize the brightness of the frames to the brightness of the selected frame.\nIf there are overexposed areas in the frames select the brightest frame to avoid magenta colour cast in overexposed areas or enable motion correction. +TP_RAW_PIXELSHIFTEXP0;Experimental +TP_RAW_PIXELSHIFTGREEN;Check green channel for motion +TP_RAW_PIXELSHIFTNONGREENCROSS;Check red/blue channels for motion +TP_RAW_PIXELSHIFTNONGREENCROSS2;Check green amaze +TP_RAW_PIXELSHIFTNONGREENAMAZE;Check red/blue amaze +TP_RAW_PIXELSHIFTMOTION;Motion detection level (deprecated) +TP_RAW_PIXELSHIFTMOTION_TOOLTIP;0 means no motion detection\n1 - 99 means motion will be detected according to this value. Increase value to increase detection rate\n100 means the Amaze demosaiced frame will be used +TP_RAW_PIXELSHIFTHOLEFILL_TOOLTIP;Fill holes in motion mask +TP_RAW_PIXELSHIFTBLUR_TOOLTIP;Blur motion mask +TP_RAW_PIXELSHIFTSMOOTH_TOOLTIP;Smooth transitions between areas with and without motion.\nSet to 0 to disable smooth transitions\nSet to 1 to get Amaze/lmmse or Median +TP_RAW_PIXELSHIFTMEDIAN_TOOLTIP;Use median of all frames instead of selected frame for regions with motion.\nRemoves objects which are at different places in all frames.\nGives motion effect on slow moving (overlapping) objects. +TP_RAW_PIXELSHIFTMEDIAN3_TOOLTIP;Excludes selected frame from median.\nUseful if moving objects overlap in frame 2 and 3 +TP_RAW_PIXELSHIFTSHOWMOTION_TOOLTIP;Overlays the image with a mask showing the regions with motion +TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY_TOOLTIP;Shows the motion mask without the image +TP_RAW_PIXELSHIFTMOTIONCORRECTION;Green motion correction size +TP_RAW_PIXELSHIFTMOTIONCORRECTION_TOOLTIP;1 = 2 pixels\n3 = 3x3 grid\n5 = 5x5 grid +TP_RAW_PIXELSHIFTMOTIONMETHOD;Motion Correction +TP_RAW_PIXELSHIFTMM_OFF;Off +TP_RAW_PIXELSHIFTMM_AUTO;Automatic +TP_RAW_PIXELSHIFTMM_CUSTOM;Custom +TP_RAW_PIXELSHIFTSHOWMOTION;Show motion +TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY;Show mask only +TP_RAW_PIXELSHIFTSTDDEVFACTORGREEN;StdDev factor Green +TP_RAW_PIXELSHIFTSTDDEVFACTORRED;StdDev factor Red +TP_RAW_PIXELSHIFTSTDDEVFACTORBLUE;StdDev factor Blue +TP_RAW_PIXELSHIFTEPERISO;ISO adaption +TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value (0.0) should work fine for base ISO.\nIncrease the value to improve motion detection for higher ISO.\nIncrease in small steps and watch the motion mask while increasing. +TP_RAW_PIXELSHIFTNREADISO;nRead +TP_RAW_PIXELSHIFTPRNU;PRNU (%) +TP_RAW_PIXELSHIFTSIGMA;Blur radius +TP_RAW_PIXELSHIFTMASKTHRESHOLD;3x3 new threshold +TP_RAW_PIXELSHIFTREDBLUEWEIGHT;Red&Blue weight TP_RAW_SENSOR_BAYER_LABEL;Sensor with Bayer Matrix TP_RAW_SENSOR_XTRANS_DMETHOD_TOOLTIP;3-pass gives best results (recommended for low ISO images).\n1-pass is almost undistinguishable from 3-pass for high ISO images and is faster. TP_RAW_SENSOR_XTRANS_LABEL;Sensor with X-Trans Matrix @@ -2022,6 +2112,8 @@ TP_WBALANCE_SOLUX41;Solux 4100K TP_WBALANCE_SOLUX47;Solux 4700K (vendor) TP_WBALANCE_SOLUX47_NG;Solux 4700K (Nat. Gallery) TP_WBALANCE_SPOTWB;Spot WB +TP_WBALANCE_TEMPBIAS;AWB temperature bias +TP_WBALANCE_TEMPBIAS_TOOLTIP;Allows to alter the computation of the "auto white balance"\nby biasing it towards warmer or cooler temperatures. The bias\nis expressed as a percentage of the computed temperature,\nso that the result is given by "computedTemp + computedTemp * bias". TP_WBALANCE_TEMPERATURE;Temperature TP_WBALANCE_TUNGSTEN;Tungsten TP_WBALANCE_WATER1;UnderWater 1 diff --git a/rtdata/profiles/BW/BW 1.pp3 b/rtdata/profiles/Black-and-White/Black-and-White 1.pp3 similarity index 100% rename from rtdata/profiles/BW/BW 1.pp3 rename to rtdata/profiles/Black-and-White/Black-and-White 1.pp3 diff --git a/rtdata/profiles/BW/BW 2.pp3 b/rtdata/profiles/Black-and-White/Black-and-White 2.pp3 similarity index 100% rename from rtdata/profiles/BW/BW 2.pp3 rename to rtdata/profiles/Black-and-White/Black-and-White 2.pp3 diff --git a/rtdata/profiles/BW/BW 3.pp3 b/rtdata/profiles/Black-and-White/Black-and-White 3.pp3 similarity index 100% rename from rtdata/profiles/BW/BW 3.pp3 rename to rtdata/profiles/Black-and-White/Black-and-White 3.pp3 diff --git a/rtdata/profiles/BW/BW 4.pp3 b/rtdata/profiles/Black-and-White/Black-and-White 4.pp3 similarity index 100% rename from rtdata/profiles/BW/BW 4.pp3 rename to rtdata/profiles/Black-and-White/Black-and-White 4.pp3 diff --git a/rtdata/themes/RawTherapee-GTK3-20_.css b/rtdata/themes/RawTherapee-GTK3-20_.css index a672c66d8..27d2b5f13 100644 --- a/rtdata/themes/RawTherapee-GTK3-20_.css +++ b/rtdata/themes/RawTherapee-GTK3-20_.css @@ -50,31 +50,40 @@ window.background { background-color: #484848; } -headerbar { - box-shadow: none; - background-color: #262626; - padding: 0; - margin: 0; - border-radius: 0; - border-style: none none solid none; +/*** Window decoration *********************************************************/ +@define-color winHeaderbar rgb(50,50,50); + +:not(.popup):not(tooltip) > decoration { + background-color: #484848; background-image: none; -} - -/* Warning: maximized and fullscreen can be set at the same time ! */ -window.maximized > decoration, window.fullscreen > decoration { + border-radius: 5px 5px 0 0; + border: none; padding: 0; + box-shadow: 0 3px 9px 1px rgba(0, 0, 0, 0.5), 0 0 0 1px #242424; + margin: 10px; +} +headerbar { + background-color: shade(@winHeaderbar,1.12); + box-shadow: inset 0 1px rgba(200,200,200,.13); + background-image: linear-gradient(shade(@winHeaderbar,1.14), shade(@winHeaderbar,.86)); + border-bottom: 1px solid #242424; + border-radius: 5px 5px 0 0; + min-height: 26px; + padding: 1px 5px 0; margin: 0; } - -window > decoration, dialog > decoration { - box-shadow: none; - margin: 0px; - border-style: none; - border-radius: 0; - padding: 3px; - background-color: #262626; +.csd #MainNotebook > header.top { + border-top: 1px solid #484848; } +/* Window state */ +.maximized > headerbar { + border-radius: 0; +} +/**/ + +/*** End Window decoration *****************************************************/ + dialog.background { background-color: #484848; } @@ -196,6 +205,12 @@ button:hover , button.flat:hover, checkbutton:hover > check, radiobutton:hover > button.popupbutton-arrow { min-width: 18px; } +/* Save, Cancel, OK ... buttons */ +.dialog-action-area button { + min-height: 24px; + margin-top: 6px; +} +/**/ combobox { min-height: 5px; @@ -826,3 +841,15 @@ paned.vertical > separator { #RightNotebook scrolledwindow { padding: 4px; } + + +/* make the "partial profile" dialog a little bit more readable */ +#PartialPasteHeader { + margin: 1.5em 0 0 0; + padding: 0; + font-weight: bold; +} + +#PartialPasteHeaderSep { + background-color: #D8D8D8; +} diff --git a/rtdata/themes/RawTherapee-GTK3-_19.css b/rtdata/themes/RawTherapee-GTK3-_19.css index d9d61206b..8263dd857 100644 --- a/rtdata/themes/RawTherapee-GTK3-_19.css +++ b/rtdata/themes/RawTherapee-GTK3-_19.css @@ -487,3 +487,16 @@ GtkNotebook { .tooltip { padding: 0; } + + +/* make the "partial profile" dialog a little bit more readable */ +#PartialPasteHeader { + margin: 1.5em 0 0 0; + padding: 0; + font-weight: bold; + color: #363636; +} + +#PartialPasteHeaderSep { + color: #D8D8D8; +} diff --git a/rtdata/themes/TooWaBlue-Dark-GTK3-20_.css b/rtdata/themes/TooWaBlue-Dark-GTK3-20_.css index 43d9a3035..3832f5bcd 100644 --- a/rtdata/themes/TooWaBlue-Dark-GTK3-20_.css +++ b/rtdata/themes/TooWaBlue-Dark-GTK3-20_.css @@ -2,7 +2,7 @@ This file is part of RawTherapee. Copyright (c) 2016-2017 TooWaBoo - Version 2.42 - requires RT 5.0 + Version 2.49 - requires RT 5.0 RawTherapee is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -76,10 +76,10 @@ } #ToolPanelNotebook { - min-width: 23em; + min-width: 24.08334em; } #HistoryPanel { - min-width: 17.83334em; + min-width: 18em; } window.background { @@ -105,7 +105,7 @@ messagedialog { } tooltip { background-color: @bg-tooltip; - border: 1px solid @border-tooltip; + border: 0.08334em solid @border-tooltip; border-radius: 0.33334em; padding: 0; margin: 0; @@ -180,7 +180,7 @@ frame > border { dialog frame > border { padding: 0.5em; border-radius: 0; - border: 1px solid @border-color; + border: 0.08334em solid @border-color; background-color: transparent; margin: 0 -0.5em; } @@ -241,11 +241,11 @@ textview:selected, treeview:selected { } #RightNotebook > stack > :nth-child(3) treeview { - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; border-bottom: none; } -#PlacesPaned > :nth-child(1) treeview { +#PlacesPaned > box:nth-child(1) treeview { padding: 0.08334em 0 0.08334em 0.5em; -gtk-icon-style: symbolic; } @@ -275,15 +275,15 @@ textview:selected, treeview:selected { margin-bottom: 0.41667em; } -#PlacesPaned > box:nth-child(3) > :nth-child(2), +#PlacesPaned > box:nth-child(3) > box:nth-child(2), #PlacesPaned > box:nth-child(1) > :nth-child(1), #HistoryPanel > border, #Snapshots > box > :nth-child(1) { - padding: 1px; background-color: @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; } -/*Corrects the space for the snapshot view of the paned separator*/ +/*Corrects the space of the snapshot view to the paned separator*/ #Snapshots { margin-top: -0.33334em; } @@ -321,11 +321,11 @@ filechooser box { } filechooser > box > paned > box { - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; background-color: @bg-dark-grey; } filechooser placessidebar { - padding: 0 1px; + padding: 0 0.08334em; background-color: @bg-dark-grey; } @@ -362,7 +362,7 @@ filechooser list row:selected { } #HistogramArea, #HistogramRGBArea { - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; background-color: @bg-dark-grey; } @@ -372,7 +372,7 @@ filechooser list row:selected { margin: 0; border-color: @bg-light-grey; border-style: solid; - border-width: 0 0 0 1px; + border-width: 0 0 0 0.08334em; background-color: @bg-dark-grey; background-image: none; box-shadow: none; @@ -385,7 +385,7 @@ filechooser list row:selected { } #EditorLeftPaned #fullButton, #EditorLeftPaned #histButton { - border-width: 0 1px 0 0; + border-width: 0 0.08334em 0 0; } /*** end ***************************************************************************************/ @@ -467,8 +467,8 @@ menu separator { /*** PartialPaste ******************************************************************************/ #PartialPaste { - border-bottom: 1px solid @border-color; - border-top: 1px solid @border-color; + border-bottom: 0.08334em solid @border-color; + border-top: 0.08334em solid @border-color; padding-top: 0.5em; padding-bottom: 0.5em; } @@ -488,7 +488,8 @@ menu separator { } #PartialPasteHeader label { - color: @headline-frame; + color: @headline-big; + font-weight: bold; } #PartialPasteHeader { margin: 0.5em 0 0 0; @@ -518,10 +519,10 @@ scrollbar:not(.overlay-indicator) { background-color: rgba(0,0,0,.30); } scrollbar:not(.overlay-indicator).horizontal { - border-width: 0 1px 1px 1px; + border-width: 0 0.08334em 0.08334em 0.08334em; } scrollbar:not(.overlay-indicator).vertical { - border-width: 1px 1px 1px 0; + border-width: 0.08334em 0.08334em 0.08334em 0; } scrollbar:not(.overlay-indicator) slider { background-color: shade(@text-color, .9); @@ -593,7 +594,7 @@ scale slider { margin: calc(-0.33334em - 1px); border-radius: 0.83334em; background-image: linear-gradient(to bottom, shade (@accent-color4,1.15), shade (@accent-color4,.85)); - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; box-shadow: none; } scale slider:hover { @@ -603,14 +604,14 @@ scale slider:hover { scale trough { margin: 0.5em; /* has to be half of "scale slider / min-width min-height*/ background-color: @bg-scale-entry; - border-color: @bg-dark-grey; - box-shadow: inset 0 1px rgba(255, 255, 255, 0.11), 0 1px rgba(242, 242, 242, 0.11); + border: 0.08334em solid @bg-dark-grey; + box-shadow: inset 0 0.08334em rgba(255, 255, 255, 0.11), 0 0.08334em rgba(242, 242, 242, 0.11); border-radius: 0.5em; } scale:not(:disabled) trough highlight { background-color: @accent-color2; - border-color: @bg-dark-grey; - box-shadow: inset 0 1px shade(@accent-color2, 1.3); + border: 0.08334em solid @bg-dark-grey; + box-shadow: inset 0 0.08334em shade(@accent-color2, 1.3); border-radius: 0.5em; } @@ -671,7 +672,7 @@ progressbar.horizontal trough progress { #IopsPanel progressbar.horizontal trough { min-height: 0.5em; background-color: @bg-scale-entry; - border: 1px solid @bg-button-border; + border: 0.08334em solid @bg-button-border; margin-top: 0.25em; } #IopsPanel progressbar.horizontal trough progress { @@ -770,8 +771,9 @@ dialog notebook stack { #MainNotebook > stack { padding: 0.41667em; } -#MainNotebook > stack > :nth-child(2) > :nth-child(2) { - margin-bottom: 0.33334em; + +#MainNotebook > stack > :nth-child(2) > box:nth-child(3) { + margin-top: 0.41667em; } @@ -787,9 +789,18 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { margin-bottom: 0.33334em; } +#ToolPanelNotebook > header tab { + margin-left: 0; + margin-right: 0; + padding: 0 0.33334em; +} +#ToolPanelNotebook > header tab + tab { + margin-left: 0.33333em; +} + #ToolPanelNotebook > header tab image{ min-height: 2.5em; - min-width: calc(1.66667em + 6px); + min-width: 2em; padding: 0; margin: 0; } @@ -801,10 +812,11 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { background-color: @bg-grey; padding: 0; } -#RightNotebook > stack > :nth-child(3), -#RightNotebook > stack > :nth-child(4) { + +#RightNotebook > stack > :nth-child(3) > * > box, +#RightNotebook > stack > :nth-child(4) > * > box { padding: 0.5em; - border: 1px solid @bg-entry-border; + border: 0.08334em solid @bg-entry-border; } #PrefNotebook header { @@ -813,8 +825,9 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #AboutNotebook header { margin: -0.66667em -0.66667em 0.66667em; } -#AboutNotebook stack > * > * > * { - background-color: @dark-grey; + +#AboutNotebook stack text { + background-color: @bg-dark-grey; } /* All tool panels have a frame except for Meta which unlike the rest is a notebook itself. @@ -873,7 +886,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { margin: 0; } #MetaPanelNotebook .view { - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; padding: 0.16667em; margin: 0; } @@ -888,14 +901,19 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { margin: 0; } +#MetaPanelNotebook combobox button { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left: none; +} #MetaPanelNotebook combobox + button, #MetaPanelNotebook combobox + button + button { margin-left: 0.16667em; min-width: 1.66667em; } #MetaPanelNotebook > stack > box > grid > button { - margin-top: 1px; - margin-bottom: 1px; + margin-top: 0.08334em; + margin-bottom: 0.08334em; min-height: 2.16667em; } @@ -908,7 +926,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { /*** File Browser ******************************************************************************/ #FileCatalog { background-color: @bg-image; - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; } #FileCatalog:selected { background-color: @accent-color3; @@ -949,7 +967,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { min-width: 1.66667em; margin: 0 0 0 -1.66667em; border-radius: 0 0.2em 0.2em 0; - border: 1px solid transparent; + border: 0.08334em solid transparent; padding: 0; } #ToolBarPanelFileBrowser entry, @@ -972,25 +990,17 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #BeforeAfterContainer { background-color: @bg-grey; - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; border-radius: 0; padding: 0; margin: 0.41667em 0; } -#BeforeAfterContainer > box:nth-child(1) frame { - background-color: @bg-image; - border-top: 1px solid @bg-dark-grey; - border-radius: 0; - padding: 0; - margin: -1px 0 0 0; +#BeforeAfterContainer > box:nth-child(2) > box:nth-child(2), +#BeforeAfterContainer > box:nth-child(1) > box:nth-child(2){ + border-top: 0.08334em solid @bg-dark-grey; } -#BeforeAfterContainer > box:nth-child(2) frame { - background-color: @bg-image; - border-top: 1px solid @bg-dark-grey; - border-left: 1px solid @bg-dark-grey; - border-radius: 0; - padding: 0; - margin: -1px 0 0 0; +#BeforeAfterContainer > box:nth-child(2){ + border-left: 0.08334em solid @bg-dark-grey; } #BeforeAfterContainer label { @@ -1000,8 +1010,8 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { /* Small Lock Button */ #BeforeAfterContainer button { min-height: 1.66667em; - min-width: 1.66667em; - margin: 0.25em 0 0.33334em; + min-width: 1.75em; + margin: 0.25em; padding: 0 0 0 0.08334em; } /**/ @@ -1021,12 +1031,13 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { margin-right: 0; } -#EditorTopPanel > box > button.image-button:not(:nth-child(6)) { +#EditorTopPanel > box:nth-child(9) > button.image-button:not(:nth-child(6)) { min-width: 0; padding-left: 0.33334em; padding-right: 0.33334em; } -#EditorTopPanel > box > button.image-button:nth-child(6) { + +#EditorTopPanel > box:nth-child(9) > button.image-button:nth-child(6) { -gtk-icon-shadow: none; } #EditorTopPanel > box > box > button { @@ -1034,7 +1045,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { min-width: 0; margin: 0 0.16667em; padding: 0 0.16667em; - border: 1px solid transparent; + border: 0.08334em solid transparent; background-color: transparent; background-image: none; box-shadow: none; @@ -1042,13 +1053,13 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #EditorTopPanel > box > box > button:hover { background-color: transparent; background-image: none; - border: 1px solid transparent; + border: 0.08334em solid transparent; box-shadow: none; } #EditorTopPanel > box > box > button:checked { background-color: transparent; background-image: none; - border: 1px solid @bg-button-border; + border: 0.08334em solid @bg-button-border; box-shadow: none; } @@ -1077,19 +1088,22 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { } /**/ #MyExpander .drawingarea:not(.slider) { - border: 1px solid @bg-light-grey; + border: 0.08334em solid @bg-light-grey; } #MyExpander .slider, #MyExpander .drawingarea:nth-child(2) { background-image: linear-gradient(to bottom, shade (@accent-color4,1.15), shade (@accent-color4,.85)); background-color: @accent-color4; - border: 1px solid rgb(15,15,15); + border: 0.08334em solid rgb(15,15,15); } #MyExpander .drawingarea:disabled { background-color: shade(@bg-grey,.85); border-color: @bg-dark-grey; background-image: none; } +#ThresholdAdjuster { + margin: 0.08334em 0 0.16667em 0; +} #ToolPanelNotebook scrolledwindow viewport.frame { padding: 0 0.56em; @@ -1114,7 +1128,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { /* Sub-tool (MyExpander) */ #ExpanderBox2 > box, #ExpanderBox2 > grid { background-color: transparent; - border: 1px solid @border-color; + border: 0.08334em solid @border-color; border-radius: 0; margin: 0; padding: 0.5em; @@ -1143,13 +1157,13 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { border: none; padding: 0; margin: 0; - box-shadow: 0 3px 9px 1px rgba(0, 0, 0, 0.50), 0 0 0 1px @bg-dark-grey; + box-shadow: 0 0.25em 0.75em 0.08334em rgba(0, 0, 0, 0.50), 0 0 0 0.08334em @bg-dark-grey; } menu { background-color: @bg-dark-grey; - border: 1px solid @accent-color; - padding: 1px; + border: 0.08334em solid @accent-color; + padding: 0.08334em; margin: 0; } menu > .top, @@ -1159,12 +1173,12 @@ menu > .bottom:hover { background-color: transparent; border: none; padding: 0.5em; - min-height: 2em; + min-height: 1.5em; } menuitem { padding: 0 0.33334em; - margin: 1px; + margin: 0.08334em; min-height: 2em; } menuitem:hover { @@ -1187,11 +1201,11 @@ entry > window > frame { } entry > window > frame > border { background-color: @bg-dark-grey; - padding: 1px; - border: 1px solid @accent-color; + padding: 0.08334em; + border: 0.08334em solid @accent-color; } .csd entry > window > frame > border { - margin: 1px; + margin: 0.08334em; } /* end */ @@ -1203,7 +1217,7 @@ entry > window > frame > border { } popover.background { background-color: @bg-dark-grey; - border-color: @accent-color; + border: 0.08334em solid @accent-color; border-radius: 0; padding: 0; margin: 0; @@ -1236,9 +1250,9 @@ button { margin: 0; padding: 0; /* x */ border-radius: 0.2em; - border: 1px solid @bg-button-border; + border: 0.08334em solid @bg-button-border; background-color: transparent; - box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.1); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); } button.flat { @@ -1250,7 +1264,7 @@ button.text-button label { #MainNotebook > header > grid > button, button.flat { - border: 1px solid transparent; + border: 0.08334em solid transparent; box-shadow: none; background-image: none; background-color: transparent; @@ -1301,7 +1315,7 @@ scale + button.flat { button.flat:hover, button:hover { border-color: @bg-button-border; - box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.1); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); background-color: @bg-button-hover; } @@ -1313,7 +1327,7 @@ button.flat:checked, button:active, button:checked { border-color: @bg-button-border; - box-shadow: inset 0 1px rgba(242, 242, 242, 0.08); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.08); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); background-color: @bg-button-active; } @@ -1322,7 +1336,7 @@ button:checked { button.Right, button.MiddleH { margin-left: 0.16667em; - border: 1px solid @bg-button-border; + border: 0.08334em solid @bg-button-border; } /**/ @@ -1343,13 +1357,14 @@ button.MiddleH { } /**/ -/* Base format for Toolbox and dialogs */ +/* Button base format for Toolbox and dialogs */ dialog button, #MyExpander button, #BatchQueueButtonsMainContainer button { min-height: 1.66667em; min-width: 0; padding: 0 0.375em; + margin: 0.08334em 0; } combobox .combo, dialog combobox .combo, @@ -1364,9 +1379,10 @@ dialog combobox .combo, #MyExpander button:not(.flat).Left, #MyExpander button:not(.flat) + combobox, #MyExpander combobox + button:not(.flat), -#MyExpander combobox + combobox, +#MyExpander combobox + combobox +/* Crash #MyExpander button + label, -#MyExpander combobox + label { +#MyExpander combobox + label */ { margin-left: 0.16667em; } #MyExpander label + filechooserbutton, @@ -1376,6 +1392,13 @@ dialog combobox .combo, margin-left: 0.33334em; } +buttonbox:not(.dialog-action-area) button{ + margin: 0.08334em 0 0.33334em 0.16667em; +} +#PrefNotebook buttonbox:not(.dialog-action-area) { + margin-right: -5px; +} + /* Arrow toggle combo button */ #IopsPanel button:not(.flat).Left + button:not(.flat).Right, #MyExpander button:not(.flat).Left + button:not(.flat).Right { @@ -1394,13 +1417,6 @@ dialog combobox .combo, } /**/ -/* Add extra top and bottom space to buttons in toolbox & Preferences*/ -#PrefNotebook stack > box:nth-child(4) combobox, -#MyExpander button.flat, -#MyExpander button { - margin-top: 0.08334em; - margin-bottom: 0.08334em; -} /**/ #MyExpander button.text-button label { margin: 0;/* x */ @@ -1453,8 +1469,9 @@ window .view button { background-image: none; box-shadow: none; min-height: 2em; - min-width: 1.33334em; + min-width: 1.33334em; padding: 0 0.33334em; + margin: 0; } dialog .view button.text-button label, window .view button.text-button label { @@ -1462,25 +1479,26 @@ window .view button.text-button label { } window .view button { border: none; - border-bottom: 1px solid @border-color; + border-bottom: 0.08334em solid @border-color; } dialog .view button { - border-color: @border-color; + border: 0.08334em solid @border-color; } -.view button:checked label, .view button:checked, -.view button:hover:not(:active) label, .view button:hover:not(:active) { - color: @headline-hl; background-image: none; background-color: @bg-list-hover; } +.view button:checked label, +.view button:hover:not(:active) label { + color: @headline-hl; +} -dialog .view header button:not(:last-child):not(:only-child), -window .view header button:not(:last-child):not(:only-child), -.path-bar button:not(:last-child):not(:only-child) { - border-right: none; +dialog .view header button:not(:first-child):not(:only-child), +window .view header button:not(:first-child):not(:only-child), +.path-bar button:not(:first-child):not(:only-child) { + border-left: none; } dialog .view header button, window .view header button, @@ -1489,6 +1507,7 @@ window .view header button, } #pathbarbox button:last-child { + min-height: 2em; min-width: 2em; margin: 0; padding: 0; @@ -1517,10 +1536,10 @@ window .view header button, popover button.text-button { background-color: @bg-dark-grey; background-image: none; - border: 1px solid @border-color; + border: 0.08334em solid @border-color; box-shadow: none; background-image: none; - margin: 0; + margin: 0.083334em 0; min-height: 1.66667em; padding: 0 0.66667em; } @@ -1559,7 +1578,7 @@ headerbar button.titlebutton image { headerbar button.titlebutton { margin: 0 0 0 0.33334em; background-image: none; - border: 1px solid transparent; + border: 0.08334em solid transparent; background-color: transparent; box-shadow: none; min-width: 1.55em; @@ -1582,14 +1601,14 @@ messagedialog headerbar button.titlebutton { #MainNotebook tab #CloseButton:hover, headerbar button.titlebutton:hover{ border-color: rgba(0,0,0,.8); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.11); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.11); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); background-color: rgba(128, 128, 128,.20); } #MainNotebook > header > grid > button:active, headerbar button.titlebutton:active{ border-color: rgba(0,0,0,.8); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.15); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.15); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); background-color: rgba(128, 128, 128,.40); } @@ -1597,30 +1616,27 @@ headerbar button.titlebutton:active{ headerbar button.titlebutton.close:hover{ border-color: rgba(0,0,0,.8); background-image: linear-gradient(to bottom, rgb(180,0,0), rgb(160,0,0) 40%, rgb(130,0,0)); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.32); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.32); } #MainNotebook tab #CloseButton:active, headerbar button.titlebutton.close:active{ border-color: rgba(0,0,0,.8); background-image: linear-gradient(to bottom, rgb(215,0,0), rgb(185,0,0) 40%, rgb(150,0,0)); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.4); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.4); } /**/ /*** end ***************************************************************************************/ /*** Ckeckbox & Radio **************************************************************************/ -checkbox { - padding:0; - margin:0; - min-height: 2em; -} +checkbox, checkbutton, radiobutton { padding: 0; margin: 0; min-height: 2em; } + check, radio { border: calc(0.083334em + 0.18px) solid shade(@text-color, .9); @@ -1642,14 +1658,6 @@ checkbutton label { check { border-radius: 0.16667em; } -check:checked { - padding: 0 2px 0 0; - min-width: calc(1.16667em - 2px); -} -check:indeterminate { - min-width: 1.16667em; - padding: 0; -} radio{ border-radius: 1.16667em; @@ -1671,16 +1679,6 @@ frame > checkbutton check{ min-height: 1.4em; margin-left: 0.5em; } -#PrefNotebook checkbutton { - min-height: 1.16667em; -} -#PrefNotebook stack > box:nth-child(3) checkbutton, -#PrefNotebook stack > box:nth-child(4) checkbutton { - min-height: 2em; -} -#PrefNotebook radiobutton { - min-height: 2em; -} #MyExpander button + checkbutton:last-child { margin-left: 0.33334em; @@ -1691,25 +1689,25 @@ frame > checkbutton check{ /*** Entry & Spinbutton ************************************************************************/ #MyExpander entry, entry { - margin: 0; + margin: 0.08334em 0; padding: 0 0.33334em; min-height: 1.66667em; min-width: 0; border-radius: 0.2em; - box-shadow: inset 1px 1px rgba(0, 0, 0, 0.08), 0 1px rgba(242, 242, 242, 0.1); - border: 1px solid @bg-entry-border; + box-shadow: inset 0.08334em 0.08334em rgba(0, 0, 0, 0.08), 0 0.08334em rgba(242, 242, 242, 0.1); + border: 0.08334em solid @bg-entry-border; background-color: @bg-scale-entry; } spinbutton { - margin: 0; + margin: 0.08334em 0; padding: 0; min-height: 1.66667em; min-width: 0; border-radius: 0.2em; background-color: @bg-scale-entry; - border: 1px solid @bg-entry-border; - box-shadow: inset 1px 1px rgba(0, 0, 0, 0.08), 0 1px rgba(242, 242, 242, 0.1); + border: 0.08334em solid @bg-entry-border; + box-shadow: inset 0.08334em 0.08334em rgba(0, 0, 0, 0.08), 0 0.08334em rgba(242, 242, 242, 0.1); } #MyExpander spinbutton { @@ -1720,9 +1718,9 @@ spinbutton { border-top-left-radius: 1.83334em; border-bottom-left-radius: 1.83334em; background-color: shade(@bg-grey, 1.33); - border: 1px solid @bg-button-border; + border: 0.08334em solid @bg-button-border; color: @text-tbEntry; - box-shadow: inset 1px 1px rgba(0, 0, 0, .12), 0 1px rgba(255, 255, 255, 0.12); + box-shadow: inset 0.08334em 0.08334em rgba(0, 0, 0, .12), 0 0.08334em rgba(255, 255, 255, 0.12); } #MyExpander button + label + spinbutton { margin: 0.25em 0; /* Needed for Reset & and Auto button height*/ @@ -1808,7 +1806,7 @@ entry:focus > selection { .view entry { background-color: @bg-dark-grey; margin: 0 -2px; - border: 1px solid @accent-color; + border: 0.08334em solid @accent-color; box-shadow: none; } /* end*/ @@ -1822,14 +1820,14 @@ entry:focus > selection { border-radius: 0.41667em 0.41667em 0 0; border: none; padding: 0; - box-shadow: 0 0.25em 0.75em 1px rgba(0, 0, 0, 0.5), 0 0 0 1px @bg-dark-grey; + box-shadow: 0 0.25em 0.75em 0.08334em rgba(0, 0, 0, 0.5), 0 0 0 0.08334em @bg-dark-grey; margin: 0.83334em; } headerbar { background-color: shade(@winHeaderbar,1.12); - box-shadow: inset 0 1px rgba(200,200,200,.13); + box-shadow: inset 0 0.08334em rgba(200,200,200,.13); background-image: linear-gradient(shade(@winHeaderbar,1.14), shade(@winHeaderbar,.86)); - border-bottom: 1px solid @bg-dark-grey; + border-bottom: 0.08334em solid @bg-dark-grey; border-radius: 0.41667em 0.41667em 0 0; min-height: 2.16667em; padding: 0.08334em 0.41667em 0; @@ -1851,7 +1849,7 @@ headerbar .title{ /* Window in background */ :not(.popup):not(tooltip) > decoration:backdrop { - box-shadow: 0 0.25em 0.75em 1px rgba(0, 0, 0, 0.3), 0 0 0 1px @bg-dark-grey; + box-shadow: 0 0.25em 0.75em 0.08334em rgba(0, 0, 0, 0.3), 0 0 0 0.08334em @bg-dark-grey; } headerbar:backdrop { box-shadow: none; @@ -1861,5 +1859,4 @@ headerbar .title:backdrop { color: alpha(@winTitle,.60); } /**/ - /*** end ***************************************************************************************/ diff --git a/rtdata/themes/TooWaBlue-GTK3-20_.css b/rtdata/themes/TooWaBlue-GTK3-20_.css index e1a7e84c2..1741dc352 100644 --- a/rtdata/themes/TooWaBlue-GTK3-20_.css +++ b/rtdata/themes/TooWaBlue-GTK3-20_.css @@ -2,7 +2,7 @@ This file is part of RawTherapee. Copyright (c) 2016-2017 TooWaBoo - Version 2.42 - requires RT 5.0 + Version 2.49 - requires RT 5.0 RawTherapee is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -58,7 +58,7 @@ @define-color bg-button-border rgba(0,0,0,.60); @define-color bg-entry-border rgba(0,0,0,.40); @define-color view-grid-border rgba(255,255,255,0.15); -@define-color headline-big rgb(190,190,190); +@define-color headline-big rgb(195,195,195); @define-color headline-hl rgb(230,230,230); @define-color headline-frame rgb(215,215,215); /***********************************************************************************************/ @@ -76,10 +76,10 @@ } #ToolPanelNotebook { - min-width: 23em; + min-width: 24.08334em; } #HistoryPanel { - min-width: 17.83334em; + min-width: 18em; } window.background { @@ -105,7 +105,7 @@ messagedialog { } tooltip { background-color: @bg-tooltip; - border: 1px solid @border-tooltip; + border: 0.08334em solid @border-tooltip; border-radius: 0.33334em; padding: 0; margin: 0; @@ -180,7 +180,7 @@ frame > border { dialog frame > border { padding: 0.5em; border-radius: 0; - border: 1px solid @border-color; + border: 0.08334em solid @border-color; background-color: transparent; margin: 0 -0.5em; } @@ -241,11 +241,11 @@ textview:selected, treeview:selected { } #RightNotebook > stack > :nth-child(3) treeview { - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; border-bottom: none; } -#PlacesPaned > :nth-child(1) treeview { +#PlacesPaned > box:nth-child(1) treeview { padding: 0.08334em 0 0.08334em 0.5em; -gtk-icon-style: symbolic; } @@ -275,15 +275,15 @@ textview:selected, treeview:selected { margin-bottom: 0.41667em; } -#PlacesPaned > box:nth-child(3) > :nth-child(2), +#PlacesPaned > box:nth-child(3) > box:nth-child(2), #PlacesPaned > box:nth-child(1) > :nth-child(1), #HistoryPanel > border, #Snapshots > box > :nth-child(1) { - padding: 1px; background-color: @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; } -/*Corrects the space for the snapshot view of the paned separator*/ +/*Corrects the space of the snapshot view to the paned separator*/ #Snapshots { margin-top: -0.33334em; } @@ -321,11 +321,11 @@ filechooser box { } filechooser > box > paned > box { - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; background-color: @bg-dark-grey; } filechooser placessidebar { - padding: 0 1px; + padding: 0 0.08334em; background-color: @bg-dark-grey; } @@ -362,7 +362,7 @@ filechooser list row:selected { } #HistogramArea, #HistogramRGBArea { - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; background-color: @bg-dark-grey; } @@ -372,7 +372,7 @@ filechooser list row:selected { margin: 0; border-color: @bg-light-grey; border-style: solid; - border-width: 0 0 0 1px; + border-width: 0 0 0 0.08334em; background-color: @bg-dark-grey; background-image: none; box-shadow: none; @@ -385,7 +385,7 @@ filechooser list row:selected { } #EditorLeftPaned #fullButton, #EditorLeftPaned #histButton { - border-width: 0 1px 0 0; + border-width: 0 0.08334em 0 0; } /*** end ***************************************************************************************/ @@ -467,8 +467,8 @@ menu separator { /*** PartialPaste ******************************************************************************/ #PartialPaste { - border-bottom: 1px solid @border-color; - border-top: 1px solid @border-color; + border-bottom: 0.08334em solid @border-color; + border-top: 0.08334em solid @border-color; padding-top: 0.5em; padding-bottom: 0.5em; } @@ -488,7 +488,8 @@ menu separator { } #PartialPasteHeader label { - color: @headline-frame; + color: @headline-big; + font-weight: bold; } #PartialPasteHeader { margin: 0.5em 0 0 0; @@ -518,10 +519,10 @@ scrollbar:not(.overlay-indicator) { background-color: rgba(0,0,0,.30); } scrollbar:not(.overlay-indicator).horizontal { - border-width: 0 1px 1px 1px; + border-width: 0 0.08334em 0.08334em 0.08334em; } scrollbar:not(.overlay-indicator).vertical { - border-width: 1px 1px 1px 0; + border-width: 0.08334em 0.08334em 0.08334em 0; } scrollbar:not(.overlay-indicator) slider { background-color: shade(@text-color, .9); @@ -593,7 +594,7 @@ scale slider { margin: calc(-0.33334em - 1px); border-radius: 0.83334em; background-image: linear-gradient(to bottom, shade (@accent-color4,1.15), shade (@accent-color4,.85)); - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; box-shadow: none; } scale slider:hover { @@ -603,14 +604,14 @@ scale slider:hover { scale trough { margin: 0.5em; /* has to be half of "scale slider / min-width min-height*/ background-color: @bg-scale-entry; - border-color: @bg-dark-grey; - box-shadow: inset 0 1px rgba(255, 255, 255, 0.11), 0 1px rgba(242, 242, 242, 0.11); + border: 0.08334em solid @bg-dark-grey; + box-shadow: inset 0 0.08334em rgba(255, 255, 255, 0.11), 0 0.08334em rgba(242, 242, 242, 0.11); border-radius: 0.5em; } scale:not(:disabled) trough highlight { background-color: @accent-color2; - border-color: @bg-dark-grey; - box-shadow: inset 0 1px shade(@accent-color2, 1.3); + border: 0.08334em solid @bg-dark-grey; + box-shadow: inset 0 0.08334em shade(@accent-color2, 1.3); border-radius: 0.5em; } @@ -671,7 +672,7 @@ progressbar.horizontal trough progress { #IopsPanel progressbar.horizontal trough { min-height: 0.5em; background-color: @bg-scale-entry; - border: 1px solid @bg-button-border; + border: 0.08334em solid @bg-button-border; margin-top: 0.25em; } #IopsPanel progressbar.horizontal trough progress { @@ -770,8 +771,9 @@ dialog notebook stack { #MainNotebook > stack { padding: 0.41667em; } -#MainNotebook > stack > :nth-child(2) > :nth-child(2) { - margin-bottom: 0.33334em; + +#MainNotebook > stack > :nth-child(2) > box:nth-child(3) { + margin-top: 0.41667em; } @@ -787,9 +789,18 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { margin-bottom: 0.33334em; } +#ToolPanelNotebook > header tab { + margin-left: 0; + margin-right: 0; + padding: 0 0.33334em; +} +#ToolPanelNotebook > header tab + tab { + margin-left: 0.33333em; +} + #ToolPanelNotebook > header tab image{ min-height: 2.5em; - min-width: calc(1.66667em + 6px); + min-width: 2em; padding: 0; margin: 0; } @@ -801,10 +812,11 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { background-color: @bg-grey; padding: 0; } -#RightNotebook > stack > :nth-child(3), -#RightNotebook > stack > :nth-child(4) { + +#RightNotebook > stack > :nth-child(3) > * > box, +#RightNotebook > stack > :nth-child(4) > * > box { padding: 0.5em; - border: 1px solid @bg-entry-border; + border: 0.08334em solid @bg-entry-border; } #PrefNotebook header { @@ -813,8 +825,9 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #AboutNotebook header { margin: -0.66667em -0.66667em 0.66667em; } -#AboutNotebook stack > * > * > * { - background-color: @dark-grey; + +#AboutNotebook stack text { + background-color: @bg-dark-grey; } /* All tool panels have a frame except for Meta which unlike the rest is a notebook itself. @@ -873,7 +886,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { margin: 0; } #MetaPanelNotebook .view { - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; padding: 0.16667em; margin: 0; } @@ -888,14 +901,19 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { margin: 0; } +#MetaPanelNotebook combobox button { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left: none; +} #MetaPanelNotebook combobox + button, #MetaPanelNotebook combobox + button + button { margin-left: 0.16667em; min-width: 1.66667em; } #MetaPanelNotebook > stack > box > grid > button { - margin-top: 1px; - margin-bottom: 1px; + margin-top: 0.08334em; + margin-bottom: 0.08334em; min-height: 2.16667em; } @@ -908,7 +926,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { /*** File Browser ******************************************************************************/ #FileCatalog { background-color: @bg-image; - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; } #FileCatalog:selected { background-color: @accent-color3; @@ -949,7 +967,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { min-width: 1.66667em; margin: 0 0 0 -1.66667em; border-radius: 0 0.2em 0.2em 0; - border: 1px solid transparent; + border: 0.08334em solid transparent; padding: 0; } #ToolBarPanelFileBrowser entry, @@ -972,25 +990,17 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #BeforeAfterContainer { background-color: @bg-grey; - border: 1px solid @bg-dark-grey; + border: 0.08334em solid @bg-dark-grey; border-radius: 0; padding: 0; margin: 0.41667em 0; } -#BeforeAfterContainer > box:nth-child(1) frame { - background-color: @bg-image; - border-top: 1px solid @bg-dark-grey; - border-radius: 0; - padding: 0; - margin: -1px 0 0 0; +#BeforeAfterContainer > box:nth-child(2) > box:nth-child(2), +#BeforeAfterContainer > box:nth-child(1) > box:nth-child(2){ + border-top: 0.08334em solid @bg-dark-grey; } -#BeforeAfterContainer > box:nth-child(2) frame { - background-color: @bg-image; - border-top: 1px solid @bg-dark-grey; - border-left: 1px solid @bg-dark-grey; - border-radius: 0; - padding: 0; - margin: -1px 0 0 0; +#BeforeAfterContainer > box:nth-child(2){ + border-left: 0.08334em solid @bg-dark-grey; } #BeforeAfterContainer label { @@ -1000,8 +1010,8 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { /* Small Lock Button */ #BeforeAfterContainer button { min-height: 1.66667em; - min-width: 1.66667em; - margin: 0.25em 0 0.33334em; + min-width: 1.75em; + margin: 0.25em; padding: 0 0 0 0.08334em; } /**/ @@ -1021,12 +1031,13 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { margin-right: 0; } -#EditorTopPanel > box > button.image-button:not(:nth-child(6)) { +#EditorTopPanel > box:nth-child(9) > button.image-button:not(:nth-child(6)) { min-width: 0; padding-left: 0.33334em; padding-right: 0.33334em; } -#EditorTopPanel > box > button.image-button:nth-child(6) { + +#EditorTopPanel > box:nth-child(9) > button.image-button:nth-child(6) { -gtk-icon-shadow: none; } #EditorTopPanel > box > box > button { @@ -1034,7 +1045,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { min-width: 0; margin: 0 0.16667em; padding: 0 0.16667em; - border: 1px solid transparent; + border: 0.08334em solid transparent; background-color: transparent; background-image: none; box-shadow: none; @@ -1042,13 +1053,13 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #EditorTopPanel > box > box > button:hover { background-color: transparent; background-image: none; - border: 1px solid transparent; + border: 0.08334em solid transparent; box-shadow: none; } #EditorTopPanel > box > box > button:checked { background-color: transparent; background-image: none; - border: 1px solid @bg-button-border; + border: 0.08334em solid @bg-button-border; box-shadow: none; } @@ -1077,19 +1088,22 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { } /**/ #MyExpander .drawingarea:not(.slider) { - border: 1px solid @bg-light-grey; + border: 0.08334em solid @bg-light-grey; } #MyExpander .slider, #MyExpander .drawingarea:nth-child(2) { background-image: linear-gradient(to bottom, shade (@accent-color4,1.15), shade (@accent-color4,.85)); background-color: @accent-color4; - border: 1px solid rgb(15,15,15); + border: 0.08334em solid rgb(15,15,15); } #MyExpander .drawingarea:disabled { background-color: shade(@bg-grey,.85); border-color: @bg-dark-grey; background-image: none; } +#ThresholdAdjuster { + margin: 0.08334em 0 0.16667em 0; +} #ToolPanelNotebook scrolledwindow viewport.frame { padding: 0 0.56em; @@ -1114,7 +1128,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { /* Sub-tool (MyExpander) */ #ExpanderBox2 > box, #ExpanderBox2 > grid { background-color: transparent; - border: 1px solid @border-color; + border: 0.08334em solid @border-color; border-radius: 0; margin: 0; padding: 0.5em; @@ -1143,13 +1157,13 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { border: none; padding: 0; margin: 0; - box-shadow: 0 3px 9px 1px rgba(0, 0, 0, 0.50), 0 0 0 1px @bg-dark-grey; + box-shadow: 0 0.25em 0.75em 0.08334em rgba(0, 0, 0, 0.50), 0 0 0 0.08334em @bg-dark-grey; } menu { background-color: @bg-dark-grey; - border: 1px solid @accent-color; - padding: 1px; + border: 0.08334em solid @accent-color; + padding: 0.08334em; margin: 0; } menu > .top, @@ -1159,12 +1173,12 @@ menu > .bottom:hover { background-color: transparent; border: none; padding: 0.5em; - min-height: 2em; + min-height: 1.5em; } menuitem { padding: 0 0.33334em; - margin: 1px; + margin: 0.08334em; min-height: 2em; } menuitem:hover { @@ -1187,11 +1201,11 @@ entry > window > frame { } entry > window > frame > border { background-color: @bg-dark-grey; - padding: 1px; - border: 1px solid @accent-color; + padding: 0.08334em; + border: 0.08334em solid @accent-color; } .csd entry > window > frame > border { - margin: 1px; + margin: 0.08334em; } /* end */ @@ -1203,7 +1217,7 @@ entry > window > frame > border { } popover.background { background-color: @bg-dark-grey; - border-color: @accent-color; + border: 0.08334em solid @accent-color; border-radius: 0; padding: 0; margin: 0; @@ -1236,9 +1250,9 @@ button { margin: 0; padding: 0; /* x */ border-radius: 0.2em; - border: 1px solid @bg-button-border; + border: 0.08334em solid @bg-button-border; background-color: transparent; - box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.1); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); } button.flat { @@ -1250,7 +1264,7 @@ button.text-button label { #MainNotebook > header > grid > button, button.flat { - border: 1px solid transparent; + border: 0.08334em solid transparent; box-shadow: none; background-image: none; background-color: transparent; @@ -1301,7 +1315,7 @@ scale + button.flat { button.flat:hover, button:hover { border-color: @bg-button-border; - box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.1); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); background-color: @bg-button-hover; } @@ -1313,7 +1327,7 @@ button.flat:checked, button:active, button:checked { border-color: @bg-button-border; - box-shadow: inset 0 1px rgba(242, 242, 242, 0.08); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.08); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); background-color: @bg-button-active; } @@ -1322,7 +1336,7 @@ button:checked { button.Right, button.MiddleH { margin-left: 0.16667em; - border: 1px solid @bg-button-border; + border: 0.08334em solid @bg-button-border; } /**/ @@ -1343,13 +1357,14 @@ button.MiddleH { } /**/ -/* Base format for Toolbox and dialogs */ +/* Button base format for Toolbox and dialogs */ dialog button, #MyExpander button, #BatchQueueButtonsMainContainer button { min-height: 1.66667em; min-width: 0; padding: 0 0.375em; + margin: 0.08334em 0; } combobox .combo, dialog combobox .combo, @@ -1364,9 +1379,10 @@ dialog combobox .combo, #MyExpander button:not(.flat).Left, #MyExpander button:not(.flat) + combobox, #MyExpander combobox + button:not(.flat), -#MyExpander combobox + combobox, +#MyExpander combobox + combobox +/* Crash #MyExpander button + label, -#MyExpander combobox + label { +#MyExpander combobox + label */ { margin-left: 0.16667em; } #MyExpander label + filechooserbutton, @@ -1376,6 +1392,13 @@ dialog combobox .combo, margin-left: 0.33334em; } +buttonbox:not(.dialog-action-area) button{ + margin: 0.08334em 0 0.33334em 0.16667em; +} +#PrefNotebook buttonbox:not(.dialog-action-area) { + margin-right: -5px; +} + /* Arrow toggle combo button */ #IopsPanel button:not(.flat).Left + button:not(.flat).Right, #MyExpander button:not(.flat).Left + button:not(.flat).Right { @@ -1394,13 +1417,6 @@ dialog combobox .combo, } /**/ -/* Add extra top and bottom space to buttons in toolbox & Preferences*/ -#PrefNotebook stack > box:nth-child(4) combobox, -#MyExpander button.flat, -#MyExpander button { - margin-top: 0.08334em; - margin-bottom: 0.08334em; -} /**/ #MyExpander button.text-button label { margin: 0;/* x */ @@ -1453,8 +1469,9 @@ window .view button { background-image: none; box-shadow: none; min-height: 2em; - min-width: 1.33334em; + min-width: 1.33334em; padding: 0 0.33334em; + margin: 0; } dialog .view button.text-button label, window .view button.text-button label { @@ -1462,25 +1479,26 @@ window .view button.text-button label { } window .view button { border: none; - border-bottom: 1px solid @border-color; + border-bottom: 0.08334em solid @border-color; } dialog .view button { - border-color: @border-color; + border: 0.08334em solid @border-color; } -.view button:checked label, .view button:checked, -.view button:hover:not(:active) label, .view button:hover:not(:active) { - color: @headline-hl; background-image: none; background-color: @bg-list-hover; } +.view button:checked label, +.view button:hover:not(:active) label { + color: @headline-hl; +} -dialog .view header button:not(:last-child):not(:only-child), -window .view header button:not(:last-child):not(:only-child), -.path-bar button:not(:last-child):not(:only-child) { - border-right: none; +dialog .view header button:not(:first-child):not(:only-child), +window .view header button:not(:first-child):not(:only-child), +.path-bar button:not(:first-child):not(:only-child) { + border-left: none; } dialog .view header button, window .view header button, @@ -1489,6 +1507,7 @@ window .view header button, } #pathbarbox button:last-child { + min-height: 2em; min-width: 2em; margin: 0; padding: 0; @@ -1517,10 +1536,10 @@ window .view header button, popover button.text-button { background-color: @bg-dark-grey; background-image: none; - border: 1px solid @border-color; + border: 0.08334em solid @border-color; box-shadow: none; background-image: none; - margin: 0; + margin: 0.083334em 0; min-height: 1.66667em; padding: 0 0.66667em; } @@ -1559,7 +1578,7 @@ headerbar button.titlebutton image { headerbar button.titlebutton { margin: 0 0 0 0.33334em; background-image: none; - border: 1px solid transparent; + border: 0.08334em solid transparent; background-color: transparent; box-shadow: none; min-width: 1.55em; @@ -1582,14 +1601,14 @@ messagedialog headerbar button.titlebutton { #MainNotebook tab #CloseButton:hover, headerbar button.titlebutton:hover{ border-color: rgba(0,0,0,.8); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.11); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.11); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); background-color: rgba(128, 128, 128,.20); } #MainNotebook > header > grid > button:active, headerbar button.titlebutton:active{ border-color: rgba(0,0,0,.8); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.15); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.15); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); background-color: rgba(128, 128, 128,.40); } @@ -1597,30 +1616,27 @@ headerbar button.titlebutton:active{ headerbar button.titlebutton.close:hover{ border-color: rgba(0,0,0,.8); background-image: linear-gradient(to bottom, rgb(180,0,0), rgb(160,0,0) 40%, rgb(130,0,0)); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.32); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.32); } #MainNotebook tab #CloseButton:active, headerbar button.titlebutton.close:active{ border-color: rgba(0,0,0,.8); background-image: linear-gradient(to bottom, rgb(215,0,0), rgb(185,0,0) 40%, rgb(150,0,0)); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.4); + box-shadow: inset 0 0.08334em rgba(242, 242, 242, 0.4); } /**/ /*** end ***************************************************************************************/ /*** Ckeckbox & Radio **************************************************************************/ -checkbox { - padding:0; - margin:0; - min-height: 2em; -} +checkbox, checkbutton, radiobutton { padding: 0; margin: 0; min-height: 2em; } + check, radio { border: calc(0.083334em + 0.18px) solid shade(@text-color, .9); @@ -1642,14 +1658,6 @@ checkbutton label { check { border-radius: 0.16667em; } -check:checked { - padding: 0 2px 0 0; - min-width: calc(1.16667em - 2px); -} -check:indeterminate { - min-width: 1.16667em; - padding: 0; -} radio{ border-radius: 1.16667em; @@ -1671,16 +1679,6 @@ frame > checkbutton check{ min-height: 1.4em; margin-left: 0.5em; } -#PrefNotebook checkbutton { - min-height: 1.16667em; -} -#PrefNotebook stack > box:nth-child(3) checkbutton, -#PrefNotebook stack > box:nth-child(4) checkbutton { - min-height: 2em; -} -#PrefNotebook radiobutton { - min-height: 2em; -} #MyExpander button + checkbutton:last-child { margin-left: 0.33334em; @@ -1691,25 +1689,25 @@ frame > checkbutton check{ /*** Entry & Spinbutton ************************************************************************/ #MyExpander entry, entry { - margin: 0; + margin: 0.08334em 0; padding: 0 0.33334em; min-height: 1.66667em; min-width: 0; border-radius: 0.2em; - box-shadow: inset 1px 1px rgba(0, 0, 0, 0.08), 0 1px rgba(242, 242, 242, 0.1); - border: 1px solid @bg-entry-border; + box-shadow: inset 0.08334em 0.08334em rgba(0, 0, 0, 0.08), 0 0.08334em rgba(242, 242, 242, 0.1); + border: 0.08334em solid @bg-entry-border; background-color: @bg-scale-entry; } spinbutton { - margin: 0; + margin: 0.08334em 0; padding: 0; min-height: 1.66667em; min-width: 0; border-radius: 0.2em; background-color: @bg-scale-entry; - border: 1px solid @bg-entry-border; - box-shadow: inset 1px 1px rgba(0, 0, 0, 0.08), 0 1px rgba(242, 242, 242, 0.1); + border: 0.08334em solid @bg-entry-border; + box-shadow: inset 0.08334em 0.08334em rgba(0, 0, 0, 0.08), 0 0.08334em rgba(242, 242, 242, 0.1); } #MyExpander spinbutton { @@ -1720,9 +1718,9 @@ spinbutton { border-top-left-radius: 1.83334em; border-bottom-left-radius: 1.83334em; background-color: shade(@bg-grey, 1.33); - border: 1px solid @bg-button-border; + border: 0.08334em solid @bg-button-border; color: @text-tbEntry; - box-shadow: inset 1px 1px rgba(0, 0, 0, .12), 0 1px rgba(255, 255, 255, 0.12); + box-shadow: inset 0.08334em 0.08334em rgba(0, 0, 0, .12), 0 0.08334em rgba(255, 255, 255, 0.12); } #MyExpander button + label + spinbutton { margin: 0.25em 0; /* Needed for Reset & and Auto button height*/ @@ -1808,7 +1806,7 @@ entry:focus > selection { .view entry { background-color: @bg-dark-grey; margin: 0 -2px; - border: 1px solid @accent-color; + border: 0.08334em solid @accent-color; box-shadow: none; } /* end*/ @@ -1822,14 +1820,14 @@ entry:focus > selection { border-radius: 0.41667em 0.41667em 0 0; border: none; padding: 0; - box-shadow: 0 0.25em 0.75em 1px rgba(0, 0, 0, 0.5), 0 0 0 1px @bg-dark-grey; + box-shadow: 0 0.25em 0.75em 0.08334em rgba(0, 0, 0, 0.5), 0 0 0 0.08334em @bg-dark-grey; margin: 0.83334em; } headerbar { background-color: shade(@winHeaderbar,1.12); - box-shadow: inset 0 1px rgba(200,200,200,.13); + box-shadow: inset 0 0.08334em rgba(200,200,200,.13); background-image: linear-gradient(shade(@winHeaderbar,1.14), shade(@winHeaderbar,.86)); - border-bottom: 1px solid @bg-dark-grey; + border-bottom: 0.08334em solid @bg-dark-grey; border-radius: 0.41667em 0.41667em 0 0; min-height: 2.16667em; padding: 0.08334em 0.41667em 0; @@ -1851,7 +1849,7 @@ headerbar .title{ /* Window in background */ :not(.popup):not(tooltip) > decoration:backdrop { - box-shadow: 0 0.25em 0.75em 1px rgba(0, 0, 0, 0.3), 0 0 0 1px @bg-dark-grey; + box-shadow: 0 0.25em 0.75em 0.08334em rgba(0, 0, 0, 0.3), 0 0 0 0.08334em @bg-dark-grey; } headerbar:backdrop { box-shadow: none; @@ -1861,5 +1859,4 @@ headerbar .title:backdrop { color: alpha(@winTitle,.60); } /**/ - /*** end ***************************************************************************************/ diff --git a/rtdata/themes/TooWaBlue-GTK3-_19.css b/rtdata/themes/TooWaBlue-GTK3-_19.css index 24442aae3..530ae3d3a 100644 --- a/rtdata/themes/TooWaBlue-GTK3-_19.css +++ b/rtdata/themes/TooWaBlue-GTK3-_19.css @@ -1,7 +1,7 @@ /* This file is part of RawTherapee. - Copyright (c) 2016 TooWaBoo (v1.19.4) + Copyright (c) 2016 TooWaBoo (v1.19.5) Many thanks to the RawTherapee Developer Team for this great piece of software RawTherapee is free software: you can redistribute it and/or modify @@ -397,7 +397,7 @@ GtkDialog tab { padding: 9px; } #ToolPanelNotebook tab { - padding: 10px 4px 7px; + padding: 10px 2px 7px; } #MetaPanelNotebook tab { padding: 8px 4px; diff --git a/rtengine/CA_correct_RT.cc b/rtengine/CA_correct_RT.cc index 7c28801ae..fc9967619 100644 --- a/rtengine/CA_correct_RT.cc +++ b/rtengine/CA_correct_RT.cc @@ -112,7 +112,7 @@ bool LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* pfSolution) using namespace std; using namespace rtengine; -void RawImageSource::CA_correct_RT(const double cared, const double cablue, const double caautostrength) +void RawImageSource::CA_correct_RT(const bool autoCA, const double cared, const double cablue, const double caautostrength, array2D &rawData) { // multithreaded and partly vectorized by Ingo Weyrich constexpr int ts = 128; @@ -134,7 +134,6 @@ void RawImageSource::CA_correct_RT(const double cared, const double cablue, cons plistener->setProgress (progress); } - const bool autoCA = (cared == 0 && cablue == 0); // local variables const int width = W, height = H; //temporary array to store simple interpolation of G @@ -695,7 +694,7 @@ void RawImageSource::CA_correct_RT(const double cared, const double cablue, cons //fitparams[polyord*i+j] gives the coefficients of (vblock^i hblock^j) in a polynomial fit for i,j<=4 } //end of initialization for CA correction pass - //only executed if cared and cablue are zero + //only executed if autoCA is true } // Main algorithm: Tile loop diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 1b445a594..479534bec 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -24,6 +24,7 @@ set (RTENGINESOURCEFILES colortemp.cc curves.cc flatcurves.cc diagonalcurves.cc klt/storeFeatures.cc klt/trackFeatures.cc klt/writeFeatures.cc clutstore.cc ciecam02.cc + pixelshift.cc ) include_directories (BEFORE "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc index b50320631..d075ec5bc 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -495,8 +495,8 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef //printf("NL=%f \n",noisevarL); if (useNoiseLCurve || useNoiseCCurve) { - int hei = calclum->height; - int wid = calclum->width; + int hei = calclum->getHeight(); + int wid = calclum->getWidth(); TMatrix wprofi = ICCStore::getInstance()->workingSpaceMatrix (params->icm.working); const float wpi[3][3] = { @@ -573,7 +573,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef calclum = nullptr; } - const short int imheight = src->height, imwidth = src->width; + const short int imheight = src->getHeight(), imwidth = src->getWidth(); if (dnparams.luma != 0 || dnparams.chroma != 0 || dnparams.methodmed == "Lab" || dnparams.methodmed == "Lonly") { // gamma transform for input data @@ -622,13 +622,13 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef for (int i = 0; i < TS; ++i) { float i1 = abs((i > TS / 2 ? i - TS + 1 : i)); - float vmask = (i1 < border ? SQR(sin((M_PI * i1) / (2 * border))) : 1.0f); - float vmask2 = (i1 < 2 * border ? SQR(sin((M_PI * i1) / (2 * border))) : 1.0f); + float vmask = (i1 < border ? SQR(sin((rtengine::RT_PI * i1) / (2 * border))) : 1.0f); + float vmask2 = (i1 < 2 * border ? SQR(sin((rtengine::RT_PI * i1) / (2 * border))) : 1.0f); for (int j = 0; j < TS; ++j) { float j1 = abs((j > TS / 2 ? j - TS + 1 : j)); - tilemask_in[i][j] = (vmask * (j1 < border ? SQR(sin((M_PI * j1) / (2 * border))) : 1.0f)) + epsilon; - tilemask_out[i][j] = (vmask2 * (j1 < 2 * border ? SQR(sin((M_PI * j1) / (2 * border))) : 1.0f)) + epsilon; + tilemask_in[i][j] = (vmask * (j1 < border ? SQR(sin((rtengine::RT_PI * j1) / (2 * border))) : 1.0f)) + epsilon; + tilemask_out[i][j] = (vmask2 * (j1 < 2 * border ? SQR(sin((rtengine::RT_PI * j1) / (2 * border))) : 1.0f)) + epsilon; } } @@ -1512,7 +1512,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef } for (int i = 0; i < overlap; ++i) { - float mask = SQR(xsinf((M_PI * i) / (2 * overlap))); + float mask = SQR(xsinf((rtengine::RT_PI * i) / (2 * overlap))); if (tiletop > 0) { Vmask[i] = mask; @@ -1717,8 +1717,8 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef #pragma omp parallel for #endif - for (int i = 0; i < dst->height; ++i) { - for (int j = 0; j < dst->width; ++j) { + for (int i = 0; i < dst->getHeight(); ++i) { + for (int j = 0; j < dst->getWidth(); ++j) { dst->r(i, j) = Color::gammatab_srgb[ dst->r(i, j) ]; dst->g(i, j) = Color::gammatab_srgb[ dst->g(i, j) ]; dst->b(i, j) = Color::gammatab_srgb[ dst->b(i, j) ]; @@ -1746,7 +1746,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef //median 3x3 in complement on RGB if (dnparams.methodmed == "RGB" && dnparams.median) { //printf("RGB den\n"); - int wid = dst->width, hei = dst->height; + int wid = dst->getWidth(), hei = dst->getHeight(); float** tm; tm = new float*[hei]; @@ -3115,8 +3115,8 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat float** lumcalc; float** acalc; float** bcalc; - hei = provicalc->height; - wid = provicalc->width; + hei = provicalc->getHeight(); + wid = provicalc->getWidth(); TMatrix wprofi = ICCStore::getInstance()->workingSpaceMatrix (params->icm.working); const float wpi[3][3] = { @@ -3165,7 +3165,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - const int imheight = src->height, imwidth = src->width; + const int imheight = src->getHeight(), imwidth = src->getWidth(); bool denoiseMethodRgb = (dnparams.dmethod == "RGB"); diff --git a/rtengine/amaze_demosaic_RT.cc b/rtengine/amaze_demosaic_RT.cc index c5535493c..3cb0ee8de 100644 --- a/rtengine/amaze_demosaic_RT.cc +++ b/rtengine/amaze_demosaic_RT.cc @@ -38,7 +38,7 @@ namespace rtengine { -SSEFUNCTION void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) +SSEFUNCTION void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue) { BENCHFUN diff --git a/rtengine/cache.h b/rtengine/cache.h index f4c232673..ec284b2ae 100644 --- a/rtengine/cache.h +++ b/rtengine/cache.h @@ -19,11 +19,12 @@ #pragma once -#include -#include -#include -#include #include +#include +#include +#include +#include +#include #include "../rtgui/threadutils.h" @@ -87,9 +88,9 @@ public: lru_list.splice( lru_list.begin(), lru_list, - store_it->second.lru_list_it + store_it->second->lru_list_it ); - value = store_it->second.value; + value = store_it->second->value; } mutex.unlock(); @@ -139,7 +140,7 @@ public: mutex.lock(); if (hook) { for (const auto& entry : store) { - hook->onRemove(entry.first, entry.second.value); + hook->onRemove(entry.first, entry.second->value); } } lru_list.clear(); @@ -152,13 +153,13 @@ private: using Store = typename std::conditional< cache_helper::has_hash::value, - std::unordered_map, - std::map + std::unordered_map>, + std::map> >::type; using StoreIterator = typename Store::iterator; using StoreConstIterator = typename Store::const_iterator; - typedef std::list LruList; + using LruList = std::list; using LruListIterator = typename LruList::iterator; struct Value { @@ -176,7 +177,7 @@ private: { const StoreIterator store_it = lru_list.back(); if (hook) { - hook->onDiscard(store_it->first, store_it->second.value); + hook->onDiscard(store_it->first, store_it->second->value); } store.erase(store_it); lru_list.pop_back(); @@ -193,23 +194,25 @@ private: discard(); } lru_list.push_front(store.end()); - const Value v = { - value, - lru_list.begin() - }; - lru_list.front() = store.emplace(key, v).first; + std::unique_ptr v( + new Value{ + value, + lru_list.begin() + } + ); + lru_list.front() = store.emplace(key, std::move(v)).first; } } else { if (mode == Mode::UNCOND || mode == Mode::KNOWN) { if (hook) { - hook->onDisplace(key, store_it->second.value); + hook->onDisplace(key, store_it->second->value); } lru_list.splice( lru_list.begin(), lru_list, - store_it->second.lru_list_it + store_it->second->lru_list_it ); - store_it->second.value = value; + store_it->second->value = value; } } mutex.unlock(); @@ -220,9 +223,9 @@ private: void remove(const StoreIterator& store_it) { if (hook) { - hook->onRemove(store_it->first, store_it->second.value); + hook->onRemove(store_it->first, store_it->second->value); } - lru_list.erase(store_it->second.lru_list_it); + lru_list.erase(store_it->second->lru_list_it); store.erase(store_it); } diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 5d0898ee9..f506a190e 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -1072,6 +1072,14 @@ Camera constants: "ranges": { "white": 4050 } // nominal 4080-4093 }, + { // Quality C, color data guessed to be same with X-A3 + "make_model": "FUJIFILM GFX 50S", + "dcraw_matrix": [ 12407,-5222,-1086,-2971,11116,2120,-294,1029,5284 ], // copy from X-A3 DNGv9.8 D65 + "raw_crop": [ 0, 0, 8280, 6208 ], // full raw 9216X6210 - usefull 8280x6208 + // "raw_crop": [ 6, 6, 8264, 6200 ], // fuji official JPEG 8256X6192 10,11,9,8 - experimental crop to match with official + "ranges": { "white": 16300 } + }, + { // Quality A "make_model": "FUJIFILM S1", "dcraw_matrix": [ 12297,-4882,-1202,-2106,10691,1623,-88,1312,4790 ] // DNG_v8.5 D65 diff --git a/rtengine/ciecam02.cc b/rtengine/ciecam02.cc index f10ae4b31..08a9b3145 100644 --- a/rtengine/ciecam02.cc +++ b/rtengine/ciecam02.cc @@ -577,7 +577,7 @@ void Ciecam02::Aab_to_rgbfloat( vfloat &r, vfloat &g, vfloat &b, vfloat A, vfloa void Ciecam02::calculate_ab( double &aa, double &bb, double h, double e, double t, double nbb, double a ) { - double hrad = (h * M_PI) / 180.0; + double hrad = (h * rtengine::RT_PI) / 180.0; double sinh = sin( hrad ); double cosh = cos( hrad ); double x = (a / nbb) + 0.305; @@ -605,7 +605,7 @@ void Ciecam02::calculate_ab( double &aa, double &bb, double h, double e, double } void Ciecam02::calculate_abfloat( float &aa, float &bb, float h, float e, float t, float nbb, float a ) { - float2 sincosval = xsincosf((h * M_PI) / 180.0f); + float2 sincosval = xsincosf((h * rtengine::RT_PI) / 180.0f); float sinh = sincosval.x; float cosh = sincosval.y; float x = (a / nbb) + 0.305f; @@ -643,7 +643,7 @@ void Ciecam02::calculate_abfloat( float &aa, float &bb, float h, float e, float #ifdef __SSE2__ void Ciecam02::calculate_abfloat( vfloat &aa, vfloat &bb, vfloat h, vfloat e, vfloat t, vfloat nbb, vfloat a ) { - vfloat2 sincosval = xsincosf((h * F2V(M_PI)) / F2V(180.0f)); + vfloat2 sincosval = xsincosf((h * F2V(rtengine::RT_PI)) / F2V(180.0f)); vfloat sinh = sincosval.x; vfloat cosh = sincosval.y; vfloat x = (a / nbb) + F2V(0.305f); @@ -794,7 +794,7 @@ void Ciecam02::xyz2jchqms_ciecam02( double &J, double &C, double &h, double &Q, ca = rpa - ((12.0 * gpa) / 11.0) + (bpa / 11.0); cb = (1.0 / 9.0) * (rpa + gpa - (2.0 * bpa)); - myh = (180.0 / M_PI) * atan2( cb, ca ); + myh = (180.0 / rtengine::RT_PI) * atan2( cb, ca ); if ( myh < 0.0 ) { myh += 360.0; @@ -831,7 +831,7 @@ void Ciecam02::xyz2jchqms_ciecam02( double &J, double &C, double &h, double &Q, J = 100.0 * pow( a / aw, c * cz ); - e = ((12500.0 / 13.0) * nc * ncb) * (cos( ((myh * M_PI) / 180.0) + 2.0 ) + 3.8); + e = ((12500.0 / 13.0) * nc * ncb) * (cos( ((myh * rtengine::RT_PI) / 180.0) + 2.0 ) + 3.8); t = (e * sqrt( (ca * ca) + (cb * cb) )) / (rpa + gpa + ((21.0 / 20.0) * bpa)); C = pow( t, 0.9 ) * sqrt( J / 100.0 ) @@ -881,7 +881,7 @@ void Ciecam02::xyz2jchqms_ciecam02float( float &J, float &C, float &h, float &Q, myh = xatan2f( cb, ca ); if ( myh < 0.0f ) { - myh += (2.f * M_PI); + myh += (2.f * rtengine::RT_PI); } a = ((2.0f * rpa) + gpa + (0.05f * bpa) - 0.305f) * nbb; @@ -902,7 +902,7 @@ void Ciecam02::xyz2jchqms_ciecam02float( float &J, float &C, float &h, float &Q, M = C * pfl; Q = (Q == 0.f ? 0.0001f : Q); // avoid division by zero s = 100.0f * sqrtf( M / Q ); - h = (myh * 180.f) / (float)M_PI; + h = (myh * 180.f) / (float)rtengine::RT_PI; } #ifdef __SSE2__ void Ciecam02::xyz2jchqms_ciecam02float( vfloat &J, vfloat &C, vfloat &h, vfloat &Q, vfloat &M, vfloat &s, vfloat aw, vfloat fl, vfloat wh, @@ -938,7 +938,7 @@ void Ciecam02::xyz2jchqms_ciecam02float( vfloat &J, vfloat &C, vfloat &h, vfloat cb = F2V(0.11111111f) * (rpa + gpa - (bpa + bpa)); vfloat myh = xatan2f( cb, ca ); - vfloat temp = F2V(M_PI); + vfloat temp = F2V(rtengine::RT_PI); temp += temp; temp += myh; myh = vself(vmaskf_lt(myh, ZEROV), temp, myh); @@ -958,7 +958,7 @@ void Ciecam02::xyz2jchqms_ciecam02float( vfloat &J, vfloat &C, vfloat &h, vfloat M = C * pfl; Q = _mm_max_ps(Q, F2V(0.0001f)); // avoid division by zero s = F2V(100.0f) * _mm_sqrt_ps( M / Q ); - h = (myh * F2V(180.f)) / F2V(M_PI); + h = (myh * F2V(180.f)) / F2V(rtengine::RT_PI); } #endif @@ -1000,7 +1000,7 @@ void Ciecam02::xyz2jch_ciecam02float( float &J, float &C, float &h, float aw, fl myh = xatan2f( cb, ca ); if ( myh < 0.0f ) { - myh += (2.f * M_PI); + myh += (2.f * rtengine::RT_PI); } a = ((2.0f * rpa) + gpa + (0.05f * bpa) - 0.305f) * nbb; @@ -1017,7 +1017,7 @@ void Ciecam02::xyz2jch_ciecam02float( float &J, float &C, float &h, float aw, fl C = pow_F( t, 0.9f ) * J * pow1; J *= J * 100.0f; - h = (myh * 180.f) / (float)M_PI; + h = (myh * 180.f) / (float)rtengine::RT_PI; } @@ -1034,7 +1034,7 @@ void Ciecam02::jch2xyz_ciecam02( double &x, double &y, double &z, double J, doub double e, t; gamu = 1; xyz_to_cat02( rw, gw, bw, xw, yw, zw, gamu ); - e = ((12500.0 / 13.0) * nc * ncb) * (cos( ((h * M_PI) / 180.0) + 2.0 ) + 3.8); + e = ((12500.0 / 13.0) * nc * ncb) * (cos( ((h * rtengine::RT_PI) / 180.0) + 2.0 ) + 3.8); a = pow( J / 100.0, 1.0 / (c * cz) ) * aw; t = pow( C / (sqrt( J / 100) * pow( 1.64 - pow( 0.29, n ), 0.73 )), 10.0 / 9.0 ); @@ -1068,7 +1068,7 @@ void Ciecam02::jch2xyz_ciecam02float( float &x, float &y, float &z, float J, flo float e, t; gamu = 1; xyz_to_cat02float( rw, gw, bw, xw, yw, zw, gamu ); - e = ((961.53846f) * nc * ncb) * (xcosf( ((h * M_PI) / 180.0f) + 2.0f ) + 3.8f); + e = ((961.53846f) * nc * ncb) * (xcosf( ((h * rtengine::RT_PI) / 180.0f) + 2.0f ) + 3.8f); a = pow_F( J / 100.0f, 1.0f / (c * cz) ) * aw; t = pow_F( 10.f * C / (sqrtf( J ) * pow1), 1.1111111f ); @@ -1102,7 +1102,7 @@ void Ciecam02::jch2xyz_ciecam02float( vfloat &x, vfloat &y, vfloat &z, vfloat J, vfloat a, ca, cb; vfloat e, t; xyz_to_cat02float( rw, gw, bw, xw, yw, zw); - e = ((F2V(961.53846f)) * nc * ncb) * (xcosf( ((h * F2V(M_PI)) / F2V(180.0f)) + F2V(2.0f) ) + F2V(3.8f)); + 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 / (_mm_sqrt_ps( J ) * pow1), F2V(1.1111111f) ); diff --git a/rtengine/color.h b/rtengine/color.h index 77db1f4f7..6fda40f12 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -780,18 +780,18 @@ public: static inline T interpolatePolarHue_PI (T h1, T h2, U balance) { if (h1==h2) return h1; - if ((h1 > h2) && (h1-h2 > T(M_PI))){ - h1 -= T(2*M_PI); + if ((h1 > h2) && (h1-h2 > T(rtengine::RT_PI))){ + h1 -= T(2*rtengine::RT_PI); T value = h1 + T(balance) * (h2-h1); - if (value < T(-M_PI)) - value += T(2*M_PI); + if (value < T(-rtengine::RT_PI)) + value += T(2*rtengine::RT_PI); return value; } - else if (h2-h1 > T(M_PI)) { - h2 -= T(2*M_PI); + else if (h2-h1 > T(rtengine::RT_PI)) { + h2 -= T(2*rtengine::RT_PI); T value = h1 + T(balance) * (h2-h1); if (value < T(0)) - value += T(2*M_PI); + value += T(2*rtengine::RT_PI); return value; } else @@ -821,21 +821,21 @@ public: f = 1.f - f; } - if (d < T(-M_PI) || d < T(0) || d > T(M_PI)) { //there was an inversion here !! d > T(M_PI) - h1 += T(2 * M_PI); + if (d < T(-rtengine::RT_PI) || d < T(0) || d > T(rtengine::RT_PI)) { //there was an inversion here !! d > T(rtengine::RT_PI) + h1 += T(2 * rtengine::RT_PI); h = h1 + f * (h2 - h1); - h = std::fmod(h, 2 * M_PI); + h = std::fmod(h, 2 * rtengine::RT_PI); } else { h = h1 + f * d; } // not strictly necessary..but in case of - if(h < T(-M_PI)) { - h = T(2 * M_PI) - h; + if(h < T(-rtengine::RT_PI)) { + h = T(2 * rtengine::RT_PI) - h; } - if(h > T(M_PI)) { - h = h - T(2 * M_PI); + if(h > T(rtengine::RT_PI)) { + h = h - T(2 * rtengine::RT_PI); } return h; @@ -864,7 +864,7 @@ public: f = 1.f - f; } - if (d < T(0) || d < T(0.5) || d > T(1.)) { //there was an inversion here !! d > T(M_PI) + if (d < T(0) || d < T(0.5) || d > T(1.)) { //there was an inversion here !! d > T(rtengine::RT_PI) h1 += T(1.); h = h1 + f * (h2 - h1); h = std::fmod(h, 1.); diff --git a/rtengine/colortemp.h b/rtengine/colortemp.h index 33a2b1b04..2d346dd81 100644 --- a/rtengine/colortemp.h +++ b/rtengine/colortemp.h @@ -57,10 +57,13 @@ public: ColorTemp (double t, double g, double e, const Glib::ustring &m); ColorTemp (double mulr, double mulg, double mulb, double e); - void update (const double rmul, const double gmul, const double bmul, const double equal) + void update (const double rmul, const double gmul, const double bmul, const double equal, const double tempBias=0.0) { this->equal = equal; mul2temp (rmul, gmul, bmul, this->equal, temp, green); + if (tempBias != 0.0 && tempBias >= -1.0 && tempBias <= 1.0) { + temp += temp * tempBias; + } } void useDefaults (const double equal) { diff --git a/rtengine/coord.cc b/rtengine/coord.cc index 8a3d7d080..bf9ee816e 100644 --- a/rtengine/coord.cc +++ b/rtengine/coord.cc @@ -27,7 +27,7 @@ namespace rtengine Coord& Coord::operator= (const PolarCoord& other) { const auto radius = other.radius; - const auto angle = other.angle / 180.0 * M_PI; + const auto angle = other.angle / 180.0 * rtengine::RT_PI; x = radius * std::cos (angle); y = radius * std::sin (angle); @@ -41,7 +41,7 @@ PolarCoord& PolarCoord::operator= (const Coord& other) const double y = other.y; radius = rtengine::norm2 (x, y); - angle = std::atan2 (y, x) * 180.0 / M_PI; + angle = std::atan2 (y, x) * 180.0 / rtengine::RT_PI; return *this; } diff --git a/rtengine/curves.h b/rtengine/curves.h index 348772075..cd4384bb4 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -994,8 +994,9 @@ inline void LuminanceToneCurve::Apply(float &r, float &g, float &b) const assert (lutToneCurve); float currLuminance = r * 0.2126729f + g * 0.7151521f + b * 0.0721750f; - float newLuminance = lutToneCurve[currLuminance]; - float coef = newLuminance / currLuminance; + const float newLuminance = lutToneCurve[currLuminance]; + currLuminance = currLuminance == 0.f ? 0.00001f : currLuminance; + const float coef = newLuminance / currLuminance; r = LIM(r * coef, 0.f, 65535.f); g = LIM(g * coef, 0.f, 65535.f); b = LIM(b * coef, 0.f, 65535.f); diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index 2914fcd74..57e25691f 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -1024,8 +1024,8 @@ void DCPProfile::apply( #pragma omp parallel for #endif - for (int y = 0; y < img->height; ++y) { - for (int x = 0; x < img->width; x++) { + for (int y = 0; y < img->getHeight(); ++y) { + for (int x = 0; x < img->getWidth(); x++) { const float& newr = mat[0][0] * img->r(y, x) + mat[0][1] * img->g(y, x) + mat[0][2] * img->b(y, x); const float& newg = mat[1][0] * img->r(y, x) + mat[1][1] * img->g(y, x) + mat[1][2] * img->b(y, x); const float& newb = mat[2][0] * img->r(y, x) + mat[2][1] * img->g(y, x) + mat[2][2] * img->b(y, x); @@ -1062,8 +1062,8 @@ void DCPProfile::apply( #pragma omp parallel for schedule(dynamic,16) #endif - for (int y = 0; y < img->height; ++y) { - for (int x = 0; x < img->width; x++) { + for (int y = 0; y < img->getHeight(); ++y) { + for (int x = 0; x < img->getWidth(); x++) { float newr = pro_photo[0][0] * img->r(y, x) + pro_photo[0][1] * img->g(y, x) + pro_photo[0][2] * img->b(y, x); float newg = pro_photo[1][0] * img->r(y, x) + pro_photo[1][1] * img->g(y, x) + pro_photo[1][2] * img->b(y, x); float newb = pro_photo[2][0] * img->r(y, x) + pro_photo[2][1] * img->g(y, x) + pro_photo[2][2] * img->b(y, x); diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 3b6d98133..c1d2e670a 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -9,6 +9,7 @@ /*RT*/#define NO_JASPER /*RT*/#define LOCALTIME /*RT*/#define DJGPP +/*RT*/#include "jpeg.h" #include "opthelper.h" @@ -54,6 +55,7 @@ #include #include #include +#include #include #if defined(DJGPP) || defined(__MINGW32__) @@ -326,7 +328,7 @@ void CLASS read_shorts (ushort *pixel, int count) { if (fread (pixel, 2, count, ifp) < count) derror(); if ((order == 0x4949) == (ntohs(0x1234) == 0x1234)) - swab ((char*)pixel, (char*)pixel, count*2); + rtengine::swab ((char*)pixel, (char*)pixel, count*2); } void CLASS cubic_spline (const int *x_, const int *y_, const int len) @@ -1047,7 +1049,7 @@ void CLASS ljpeg_idct (struct jhead *jh) 47,55,62,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63 }; if (!cs[0]) - FORC(106) cs[c] = cos((c & 31)*M_PI/16)/2; + FORC(106) cs[c] = cos((c & 31)*rtengine::RT_PI/16)/2; memset (work, 0, sizeof work); work[0][0][0] = jh->vpred[0] += ljpeg_diff (jh->huff[0]) * jh->quant[0]; for (i=1; i < 64; i++ ) { @@ -1059,8 +1061,8 @@ void CLASS ljpeg_idct (struct jhead *jh) coef -= (1 << len) - 1; ((float *)work)[zigzag[i]] = coef * jh->quant[i]; } - FORC(8) work[0][0][c] *= M_SQRT1_2; - FORC(8) work[0][c][0] *= M_SQRT1_2; + FORC(8) work[0][0][c] *= rtengine::RT_SQRT1_2; + FORC(8) work[0][c][0] *= rtengine::RT_SQRT1_2; for (i=0; i < 8; i++) for (j=0; j < 8; j++) FORC(8) work[1][i][j] += work[0][i][c] * cs[(j*2+1)*c]; @@ -2604,7 +2606,7 @@ void CLASS kodak_radc_load_raw() #ifdef NO_JPEG void CLASS kodak_jpeg_load_raw() {} -void CLASS lossy_dng_load_raw() {} +// RT void CLASS lossy_dng_load_raw() {} #else METHODDEF(boolean) @@ -2614,7 +2616,7 @@ fill_input_buffer (j_decompress_ptr cinfo) size_t nbytes; nbytes = fread (jpeg_buffer, 1, 4096, ifp); - swab ((char*)jpeg_buffer, (char*)jpeg_buffer, nbytes); + rtengine::swab ((char*)jpeg_buffer, (char*)jpeg_buffer, nbytes); cinfo->src->next_input_byte = jpeg_buffer; cinfo->src->bytes_in_buffer = nbytes; return TRUE; @@ -2661,6 +2663,7 @@ void CLASS kodak_jpeg_load_raw() } void CLASS gamma_curve (double pwr, double ts, int mode, int imax); +/*RT*/#endif void CLASS lossy_dng_load_raw() { @@ -2704,7 +2707,8 @@ void CLASS lossy_dng_load_raw() fseek (ifp, save+=4, SEEK_SET); if (tile_length < INT_MAX) fseek (ifp, get4(), SEEK_SET); - jpeg_stdio_src (&cinfo, ifp); + /*RT jpeg_stdio_src (&cinfo, ifp); */ + /*RT*/jpeg_memory_src(&cinfo, fdata(ftell(ifp), ifp), ifp->size - ftell(ifp)); jpeg_read_header (&cinfo, TRUE); jpeg_start_decompress (&cinfo); buf = (*cinfo.mem->alloc_sarray) @@ -2724,7 +2728,7 @@ void CLASS lossy_dng_load_raw() jpeg_destroy_decompress (&cinfo); maximum = 0xffff; } -#endif +/*RT #endif */ void CLASS kodak_dc120_load_raw() { @@ -3627,7 +3631,7 @@ short * CLASS foveon_make_curve (double max, double mul, double filt) double x; if (!filt) filt = 0.8; - size = 4*M_PI*max / filt; + size = 4*rtengine::RT_PI*max / filt; if (size == UINT_MAX) size--; curve = (short *) calloc (size+1, sizeof *curve); merror (curve, "foveon_make_curve()"); @@ -8574,7 +8578,7 @@ void CLASS identify() parse_fuji (i); } load_raw = &CLASS unpacked_load_raw; - fseek (ifp, 100+28*(shot_select > 0), SEEK_SET); + fseek (ifp, 100+28*(shot_select > 0 && shot_select < is_raw), SEEK_SET); parse_tiff (data_offset = get4()); parse_tiff (thumb_offset+12); /*RT*/ exif_base = thumb_offset+12; @@ -9018,9 +9022,6 @@ canon_a5: if (filters == 9) FORC(36) ((char *)xtrans)[c] = xtrans_abs[(c/6+top_margin) % 6][(c+left_margin) % 6]; - if(filters == 9 && raw_height * raw_width * 2 != raw_size) { - xtransCompressed = true; - } } else if (!strcmp(model,"KD-400Z")) { height = 1712; width = 2312; @@ -9491,7 +9492,7 @@ dng_skip: adobe_coeff (make, model); if(!strncmp(make, "Samsung", 7) && !strncmp(model, "NX1",3)) adobe_coeff (make, model); - if(!strncmp(make, "Pentax", 6) && (!strncmp(model, "K10D",4) || !strncmp(model, "K-70",4))) + if(!strncmp(make, "Pentax", 6) && (!strncmp(model, "K10D",4) || !strncmp(model, "K-70",4) || !strncmp(model, "K-1",3))) adobe_coeff (make, model); if(!strncmp(make, "Leica", 5) && !strncmp(model, "Q",1)) adobe_coeff (make, model); @@ -9525,8 +9526,8 @@ dng_skip: } #endif #ifdef NO_JPEG - if (load_raw == &CLASS kodak_jpeg_load_raw || - load_raw == &CLASS lossy_dng_load_raw) { + if (load_raw == &CLASS kodak_jpeg_load_raw /* RT || + load_raw == &CLASS lossy_dng_load_raw*/) { fprintf (stderr,_("%s: You must link dcraw with %s!!\n"), ifname, "libjpeg"); is_raw = 0; @@ -9870,7 +9871,7 @@ struct tiff_hdr { char desc[512], make[64], model[64], soft[32], date[20], artist[64]; }; -#include "xtranscompressed.cc" +#include "fujicompressed.cc" /* RT: Delete from here */ /*RT*/#undef SQR diff --git a/rtengine/dcraw.h b/rtengine/dcraw.h index 1ea938cc7..3c5719db8 100644 --- a/rtengine/dcraw.h +++ b/rtengine/dcraw.h @@ -90,7 +90,7 @@ protected: unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error; unsigned tile_width, tile_length, gpsdata[32], load_flags; bool xtransCompressed = false; - struct xtrans_params + struct fuji_compressed_params { char *q_table; /* quantization table */ int q_point[5]; /* quantization points */ @@ -115,13 +115,14 @@ protected: _ltotal }; - struct xtrans_block { + struct fuji_compressed_block { int cur_bit; // current bit being read (from left to right) int cur_pos; // current position in a buffer INT64 cur_buf_offset; // offset of this buffer in a file unsigned max_read_size; // Amount of data to be read 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; struct int_pair grad_even[3][41]; // tables of gradients struct int_pair grad_odd[3][41]; @@ -129,7 +130,7 @@ protected: ushort *linebuf[_ltotal]; }; - int fuji_total_lines, fuji_total_blocks, fuji_block_width, fuji_bits; + int fuji_total_lines, fuji_total_blocks, fuji_block_width, fuji_bits, fuji_raw_type; ushort raw_height, raw_width, height, width, top_margin, left_margin; ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; @@ -269,25 +270,27 @@ void adobe_copy_pixel (unsigned row, unsigned col, ushort **rp); void lossless_dng_load_raw(); void packed_dng_load_raw(); void deflate_dng_load_raw(); -void init_xtrans(struct xtrans_params* info); -void fuji_fill_buffer(struct xtrans_block *info); -void init_xtrans_block(struct xtrans_block* info, const struct xtrans_params *params, INT64 raw_offset, unsigned dsize); -void copy_line_to_xtrans(struct xtrans_block* info, int cur_line, int cur_block, int cur_block_width); -void fuji_zerobits(struct xtrans_block* info, int *count); -void fuji_read_code(struct xtrans_block* info, int *data, int bits_to_read); +void init_fuji_compr(struct fuji_compressed_params* info); +void fuji_fill_buffer(struct fuji_compressed_block *info); +void init_fuji_block(struct fuji_compressed_block* info, const struct fuji_compressed_params *params, INT64 raw_offset, unsigned dsize); +void copy_line_to_xtrans(struct fuji_compressed_block* info, int cur_line, int cur_block, int cur_block_width); +void copy_line_to_bayer(struct fuji_compressed_block* info, int cur_line, int cur_block, int cur_block_width); +void fuji_zerobits(struct fuji_compressed_block* info, int *count); +void fuji_read_code(struct fuji_compressed_block* info, int *data, int bits_to_read); int bitDiff(int value1, int value2); -int fuji_decode_sample_even(struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads); -int fuji_decode_sample_odd(struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads); +int fuji_decode_sample_even(struct fuji_compressed_block* info, const struct fuji_compressed_params * params, ushort* line_buf, int pos, struct int_pair* grads); +int fuji_decode_sample_odd(struct fuji_compressed_block* info, const struct fuji_compressed_params * params, ushort* line_buf, int pos, struct int_pair* grads); void fuji_decode_interpolation_even(int line_width, ushort* line_buf, int pos); -void xtrans_extend_generic(ushort *linebuf[_ltotal], int line_width, int start, int end); -void xtrans_extend_red(ushort *linebuf[_ltotal], int line_width); -void xtrans_extend_green(ushort *linebuf[_ltotal], int line_width); -void xtrans_extend_blue(ushort *linebuf[_ltotal], int line_width); -void xtrans_decode_block(struct xtrans_block* info, const struct xtrans_params *params, int cur_line); -void xtrans_decode_strip(const struct xtrans_params* info_common, int cur_block, INT64 raw_offset, unsigned dsize); -void xtrans_compressed_load_raw(); -void xtrans_decode_loop(const struct xtrans_params* common_info, int count, INT64* raw_block_offsets, unsigned *block_sizes); -void parse_xtrans_header(); +void fuji_extend_generic(ushort *linebuf[_ltotal], int line_width, int start, int end); +void fuji_extend_red(ushort *linebuf[_ltotal], int line_width); +void fuji_extend_green(ushort *linebuf[_ltotal], int line_width); +void fuji_extend_blue(ushort *linebuf[_ltotal], int line_width); +void xtrans_decode_block(struct fuji_compressed_block* info, const struct fuji_compressed_params *params, int cur_line); +void fuji_bayer_decode_block(struct fuji_compressed_block* info, const struct fuji_compressed_params *params, int cur_line); +void fuji_decode_strip(const struct fuji_compressed_params* info_common, int cur_block, INT64 raw_offset, unsigned dsize); +void fuji_compressed_load_raw(); +void fuji_decode_loop(const struct fuji_compressed_params* common_info, int count, INT64* raw_block_offsets, unsigned *block_sizes); +void parse_fuji_compressed_header(); void pentax_load_raw(); void nikon_load_raw(); int nikon_is_compressed(); diff --git a/rtengine/dcraw.patch b/rtengine/dcraw.patch index 22c53d831..43f9e12eb 100644 --- a/rtengine/dcraw.patch +++ b/rtengine/dcraw.patch @@ -1,5 +1,5 @@ ---- dcraw.c 2016-10-28 13:45:27 +0000 -+++ dcraw.cc 2016-10-31 13:35:15 +0000 +--- dcraw.c 2016-11-01 01:07:55 +0000 ++++ dcraw.cc 2016-11-01 14:54:02 +0000 @@ -1,3 +1,16 @@ +/*RT*/#include +/*RT*/#include @@ -2892,8 +2892,12 @@ parse_ciff (hlen, flen-hlen, 0); load_raw = &CLASS canon_load_raw; } else if (parse_tiff(0)) apply_tiff(); -@@ -8494,6 +8575,7 @@ - fseek (ifp, 100+28*(shot_select > 0), SEEK_SET); +@@ -8491,9 +8572,10 @@ + parse_fuji (i); + } + load_raw = &CLASS unpacked_load_raw; +- fseek (ifp, 100+28*(shot_select > 0), SEEK_SET); ++ fseek (ifp, 100+28*(shot_select > 0 && shot_select < is_raw), SEEK_SET); parse_tiff (data_offset = get4()); parse_tiff (thumb_offset+12); +/*RT*/ exif_base = thumb_offset+12; diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index bf4d1b194..ffce66ed9 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -113,7 +113,7 @@ void Crop::setEditSubscriber(EditSubscriber* newSubscriber) PipetteBuffer::LabBuffer = nullptr; } - if (PipetteBuffer::singlePlaneBuffer.getW() != -1) { + if (PipetteBuffer::singlePlaneBuffer.getWidth() != -1) { PipetteBuffer::singlePlaneBuffer.flushData(); } } diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index e641ed777..877df35a4 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -1,3 +1,4 @@ +/* /* * This file is part of RawTherapee. * @@ -1315,7 +1316,7 @@ void RawImageSource::jdl_interpolate_omp() // from "Lassus" // Adapted to RawTherapee by Jacques Desmis 3/2013 // Improved speed and reduced memory consumption by Ingo Weyrich 2/2015 //TODO Tiles to reduce memory consumption -SSEFUNCTION void RawImageSource::lmmse_interpolate_omp(int winw, int winh, int iterations) +SSEFUNCTION void RawImageSource::lmmse_interpolate_omp(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations) { const int width = winw, height = winh; const int ba = 10; @@ -3251,7 +3252,7 @@ void RawImageSource::refinement_lassus(int PassCount) * the code is open source (BSD licence) */ -#define TILESIZE 256 +#define TILESIZE 192 #define TILEBORDER 10 #define CACHESIZE (TILESIZE+2*TILEBORDER) @@ -3279,7 +3280,7 @@ inline void RawImageSource::dcb_initTileLimits(int &colMin, int &rowMin, int &co } } -void RawImageSource::fill_raw( float (*cache )[4], int x0, int y0, float** rawData) +void RawImageSource::fill_raw( float (*cache )[3], int x0, int y0, float** rawData) { int rowMin, colMin, rowMax, colMax; dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 0); @@ -3290,7 +3291,7 @@ void RawImageSource::fill_raw( float (*cache )[4], int x0, int y0, float** rawDa } } -void RawImageSource::fill_border( float (*cache )[4], int border, int x0, int y0) +void RawImageSource::fill_border( float (*cache )[3], int border, int x0, int y0) { unsigned row, col, y, x, f, c; float sum[8]; @@ -3325,93 +3326,55 @@ void RawImageSource::fill_border( float (*cache )[4], int border, int x0, int y0 } } } + // saves red and blue -void RawImageSource::copy_to_buffer( float (*buffer)[3], float (*image)[4]) + +// change buffer[3] -> buffer[2], possibly to buffer[1] if split +// into two loops, one for R and another for B, could also be smaller because +// there is no need for green pixels pass +// this would decrease the amount of needed memory +// from megapixels*2 records to megapixels*0.5 +// also don't know if float is needed as data is 1-65536 integer (I believe!!) +// comment from Ingo: float is needed because rawdata in rt is float +void RawImageSource::copy_to_buffer( float (*buffer)[2], float (*image)[3]) { for (int indx = 0; indx < CACHESIZE * CACHESIZE; indx++) { buffer[indx][0] = image[indx][0]; //R - buffer[indx][2] = image[indx][2]; //B + buffer[indx][1] = image[indx][2]; //B } } // restores red and blue -void RawImageSource::restore_from_buffer(float (*image)[4], float (*buffer)[3]) + +// other comments like in copy_to_buffer +void RawImageSource::restore_from_buffer(float (*image)[3], float (*buffer)[2]) { for (int indx = 0; indx < CACHESIZE * CACHESIZE; indx++) { image[indx][0] = buffer[indx][0]; //R - image[indx][2] = buffer[indx][2]; //B + image[indx][2] = buffer[indx][1]; //B } } // First pass green interpolation -void RawImageSource::dcb_hid(float (*image)[4], float (*bufferH)[3], float (*bufferV)[3], int x0, int y0) + +// remove entirely: bufferH and bufferV +void RawImageSource::dcb_hid(float (*image)[3], int x0, int y0) { - const int u = CACHESIZE, v = 2 * CACHESIZE; - int rowMin, colMin, rowMax, colMax; + const int u = CACHESIZE; + int rowMin, colMin, rowMax, colMax, c; dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); - // green pixels - for (int row = rowMin; row < rowMax; row++) { - for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col; col < colMax; col += 2, indx += 2) { - assert(indx - u >= 0 && indx + u < u * u); - bufferH[indx][1] = (image[indx - 1][1] + image[indx + 1][1]) * 0.5f; - bufferV[indx][1] = (image[indx + u][1] + image[indx - u][1]) * 0.5f; - } - } - - // red in blue pixel, blue in red pixel +// simple green bilinear in R and B pixels for (int row = rowMin; row < rowMax; row++) - for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = 2 - FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { assert(indx - u - 1 >= 0 && indx + u + 1 < u * u && c >= 0 && c < 3); - bufferH[indx][c] = ( 4.f * bufferH[indx][1] - - bufferH[indx + u + 1][1] - bufferH[indx + u - 1][1] - bufferH[indx - u + 1][1] - bufferH[indx - u - 1][1] - + image[indx + u + 1][c] + image[indx + u - 1][c] + image[indx - u + 1][c] + image[indx - u - 1][c] ) * 0.25f; - bufferV[indx][c] = ( 4.f * bufferV[indx][1] - - bufferV[indx + u + 1][1] - bufferV[indx + u - 1][1] - bufferV[indx - u + 1][1] - bufferV[indx - u - 1][1] - + image[indx + u + 1][c] + image[indx + u - 1][c] + image[indx - u + 1][c] + image[indx - u - 1][c] ) * 0.25f; - } - - // red or blue in green pixels - for (int row = rowMin; row < rowMax; row++) - for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin + 1) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col + 1), d = 2 - c; col < colMax; col += 2, indx += 2) { - assert(indx - u >= 0 && indx + u < u * u && c >= 0 && c < 3 && d >= 0 && d < 3); - bufferH[indx][c] = (image[indx + 1][c] + image[indx - 1][c]) * 0.5f; - bufferH[indx][d] = (2.f * bufferH[indx][1] - bufferH[indx + u][1] - bufferH[indx - u][1] + image[indx + u][d] + image[indx - u][d]) * 0.5f; - bufferV[indx][c] = (2.f * bufferV[indx][1] - bufferV[indx + 1][1] - bufferV[indx - 1][1] + image[indx + 1][c] + image[indx - 1][c]) * 0.5f; - bufferV[indx][d] = (image[indx + u][d] + image[indx - u][d]) * 0.5f; - } - - // Decide green pixels - for (int row = rowMin; row < rowMax; row++) - for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col), d = 2 - c; col < colMax; col += 2, indx += 2) { - float current = max(image[indx + v][c], image[indx - v][c], image[indx - 2][c], image[indx + 2][c]) - - min(image[indx + v][c], image[indx - v][c], image[indx - 2][c], image[indx + 2][c]) + - max(image[indx + 1 + u][d], image[indx + 1 - u][d], image[indx - 1 + u][d], image[indx - 1 - u][d]) - - min(image[indx + 1 + u][d], image[indx + 1 - u][d], image[indx - 1 + u][d], image[indx - 1 - u][d]); - - float currentH = max(bufferH[indx + v][d], bufferH[indx - v][d], bufferH[indx - 2][d], bufferH[indx + 2][d]) - - min(bufferH[indx + v][d], bufferH[indx - v][d], bufferH[indx - 2][d], bufferH[indx + 2][d]) + - max(bufferH[indx + 1 + u][c], bufferH[indx + 1 - u][c], bufferH[indx - 1 + u][c], bufferH[indx - 1 - u][c]) - - min(bufferH[indx + 1 + u][c], bufferH[indx + 1 - u][c], bufferH[indx - 1 + u][c], bufferH[indx - 1 - u][c]); - - float currentV = max(bufferV[indx + v][d], bufferV[indx - v][d], bufferV[indx - 2][d], bufferV[indx + 2][d]) - - min(bufferV[indx + v][d], bufferV[indx - v][d], bufferV[indx - 2][d], bufferV[indx + 2][d]) + - max(bufferV[indx + 1 + u][c], bufferV[indx + 1 - u][c], bufferV[indx - 1 + u][c], bufferV[indx - 1 - u][c]) - - min(bufferV[indx + 1 + u][c], bufferV[indx + 1 - u][c], bufferV[indx - 1 + u][c], bufferV[indx - 1 - u][c]); - - assert(indx >= 0 && indx < u * u); - - if (ABS(current - currentH) < ABS(current - currentV)) { - image[indx][1] = bufferH[indx][1]; - } else { - image[indx][1] = bufferV[indx][1]; - } + image[indx][1] = 0.25*(image[indx-1][1]+image[indx+1][1]+image[indx-u][1]+image[indx+u][1]); } } -// missing colors are interpolated -void RawImageSource::dcb_color(float (*image)[4], int x0, int y0) +// missing colours are interpolated +void RawImageSource::dcb_color(float (*image)[3], int x0, int y0) { const int u = CACHESIZE; int rowMin, colMin, rowMax, colMax; @@ -3421,22 +3384,39 @@ void RawImageSource::dcb_color(float (*image)[4], int x0, int y0) for (int row = rowMin; row < rowMax; row++) for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = 2 - FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { assert(indx >= 0 && indx < u * u && c >= 0 && c < 4); + + +//Jacek comment: one multiplication less + image[indx][c] = image[indx][1] + + ( image[indx + u + 1][c] + image[indx + u - 1][c] + image[indx - u + 1][c] + image[indx - u - 1][c] + - (image[indx + u + 1][1] + image[indx + u - 1][1] + image[indx - u + 1][1] + image[indx - u - 1][1]) ) * 0.25f; + +/* original image[indx][c] = ( 4.f * image[indx][1] - image[indx + u + 1][1] - image[indx + u - 1][1] - image[indx - u + 1][1] - image[indx - u - 1][1] + image[indx + u + 1][c] + image[indx + u - 1][c] + image[indx - u + 1][c] + image[indx - u - 1][c] ) * 0.25f; - } +*/ + } // red or blue in green pixels for (int row = rowMin; row < rowMax; row++) for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin + 1) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col + 1), d = 2 - c; col < colMax; col += 2, indx += 2) { assert(indx >= 0 && indx < u * u && c >= 0 && c < 4); + +//Jacek comment: two multiplications (in total) less + image[indx][c] = image[indx][1] + (image[indx + 1][c] + image[indx - 1][c] - (image[indx + 1][1] + image[indx - 1][1])) * 0.5f; + image[indx][d] = image[indx][1] + (image[indx + u][d] + image[indx - u][d] - (image[indx + u][1] + image[indx - u][1])) * 0.5f; + + +/* original image[indx][c] = (2.f * image[indx][1] - image[indx + 1][1] - image[indx - 1][1] + image[indx + 1][c] + image[indx - 1][c]) * 0.5f; image[indx][d] = (2.f * image[indx][1] - image[indx + u][1] - image[indx - u][1] + image[indx + u][d] + image[indx - u][d]) * 0.5f; +*/ } } // green correction -void RawImageSource::dcb_hid2(float (*image)[4], int x0, int y0) +void RawImageSource::dcb_hid2(float (*image)[3], int x0, int y0) { const int u = CACHESIZE, v = 2 * CACHESIZE; int rowMin, colMin, rowMax, colMax; @@ -3445,8 +3425,16 @@ void RawImageSource::dcb_hid2(float (*image)[4], int x0, int y0) for (int row = rowMin; row < rowMax; row++) { for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { assert(indx - v >= 0 && indx + v < u * u); + +//Jacek comment: one multiplication less + image[indx][1] = image[indx][c] + + (image[indx + v][1] + image[indx - v][1] + image[indx - 2][1] + image[indx + 2][1] + - (image[indx + v][c] + image[indx - v][c] + image[indx - 2][c] + image[indx + 2][c])) * 0.25f; + +/* original image[indx][1] = (image[indx + v][1] + image[indx - v][1] + image[indx - 2][1] + image[indx + 2][1]) * 0.25f + image[indx][c] - ( image[indx + v][c] + image[indx - v][c] + image[indx - 2][c] + image[indx + 2][c]) * 0.25f; +*/ } } } @@ -3456,9 +3444,12 @@ void RawImageSource::dcb_hid2(float (*image)[4], int x0, int y0) // 1 = vertical // 0 = horizontal // saved in image[][3] -void RawImageSource::dcb_map(float (*image)[4], int x0, int y0) + +// seems at least 2 persons implemented some code, as this one has different coding style, could be unified +// I don't know if *pix is faster than a loop working on image[] directly +void RawImageSource::dcb_map(float (*image)[3], uint8_t *map, int x0, int y0) { - const int u = 4 * CACHESIZE; + const int u = 3 * CACHESIZE; int rowMin, colMin, rowMax, colMax; dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); @@ -3468,36 +3459,41 @@ void RawImageSource::dcb_map(float (*image)[4], int x0, int y0) assert(indx >= 0 && indx < u * u); - if ( *pix > ( pix[-4] + pix[+4] + pix[-u] + pix[+u]) / 4 ) { - image[indx][3] = ((min(pix[-4], pix[+4]) + pix[-4] + pix[+4] ) < (min(pix[-u], pix[+u]) + pix[-u] + pix[+u])); + // comparing 4 * a to (b+c+d+e) instead of a to (b+c+d+e)/4 is faster because divisions are slow + if ( 4 * (*pix) > ( (pix[-3] + pix[+3]) + (pix[-u] + pix[+u])) ) { + map[indx] = ((min(pix[-3], pix[+3]) + (pix[-3] + pix[+3]) ) < (min(pix[-u], pix[+u]) + (pix[-u] + pix[+u]))); } else { - image[indx][3] = ((max(pix[-4], pix[+4]) + pix[-4] + pix[+4] ) > (max(pix[-u], pix[+u]) + pix[-u] + pix[+u])); + map[indx] = ((max(pix[-3], pix[+3]) + (pix[-3] + pix[+3]) ) > (max(pix[-u], pix[+u]) + (pix[-u] + pix[+u]))); } } } } // interpolated green pixels are corrected using the map -void RawImageSource::dcb_correction(float (*image)[4], int x0, int y0) +void RawImageSource::dcb_correction(float (*image)[3], uint8_t *map, int x0, int y0) { const int u = CACHESIZE, v = 2 * CACHESIZE; int rowMin, colMin, rowMax, colMax; dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); for (int row = rowMin; row < rowMax; row++) { - for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col; col < colMax; col += 2, indx += 2) { - float current = 4.f * image[indx][3] + - 2.f * (image[indx + u][3] + image[indx - u][3] + image[indx + 1][3] + image[indx - 1][3]) + - image[indx + v][3] + image[indx - v][3] + image[indx + 2][3] + image[indx - 2][3]; + for (int indx = row * CACHESIZE + colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1); indx < row * CACHESIZE + colMax; indx += 2) { +// for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col; col < colMax; col += 2, indx += 2) { + float current = 4 * map[indx] + + 2 * (map[indx + u] + map[indx - u] + map[indx + 1] + map[indx - 1]) + + map[indx + v] + map[indx - v] + map[indx + 2] + map[indx - 2]; assert(indx >= 0 && indx < u * u); - image[indx][1] = ((16.f - current) * (image[indx - 1][1] + image[indx + 1][1]) * 0.5f + current * (image[indx - u][1] + image[indx + u][1]) * 0.5f ) * 0.0625f; + image[indx][1] = ((16.f - current) * (image[indx - 1][1] + image[indx + 1][1]) + current * (image[indx - u][1] + image[indx + u][1]) ) * 0.03125f; +// image[indx][1] = ((16.f - current) * (image[indx - 1][1] + image[indx + 1][1]) * 0.5f + current * (image[indx - u][1] + image[indx + u][1]) * 0.5f ) * 0.0625f; } } } // R and B smoothing using green contrast, all pixels except 2 pixel wide border -void RawImageSource::dcb_pp(float (*image)[4], int x0, int y0) + +// again code with *pix, is this kind of calculating faster in C, than this what was commented? +void RawImageSource::dcb_pp(float (*image)[3], int x0, int y0) { const int u = CACHESIZE; int rowMin, colMin, rowMax, colMax; @@ -3505,10 +3501,10 @@ void RawImageSource::dcb_pp(float (*image)[4], int x0, int y0) for (int row = rowMin; row < rowMax; row++) for (int col = colMin, indx = row * CACHESIZE + col; col < colMax; col++, indx++) { - //int r1 = ( image[indx-1][0] + image[indx+1][0] + image[indx-u][0] + image[indx+u][0] + image[indx-u-1][0] + image[indx+u+1][0] + image[indx-u+1][0] + image[indx+u-1][0])/8; - //int g1 = ( image[indx-1][1] + image[indx+1][1] + image[indx-u][1] + image[indx+u][1] + image[indx-u-1][1] + image[indx+u+1][1] + image[indx-u+1][1] + image[indx+u-1][1])/8; - //int b1 = ( image[indx-1][2] + image[indx+1][2] + image[indx-u][2] + image[indx+u][2] + image[indx-u-1][2] + image[indx+u+1][2] + image[indx-u+1][2] + image[indx+u-1][2])/8; - float (*pix)[4] = image + (indx - u - 1); +// float r1 = image[indx-1][0] + image[indx+1][0] + image[indx-u][0] + image[indx+u][0] + image[indx-u-1][0] + image[indx+u+1][0] + image[indx-u+1][0] + image[indx+u-1][0]; +// float g1 = image[indx-1][1] + image[indx+1][1] + image[indx-u][1] + image[indx+u][1] + image[indx-u-1][1] + image[indx+u+1][1] + image[indx-u+1][1] + image[indx+u-1][1]; +// float b1 = image[indx-1][2] + image[indx+1][2] + image[indx-u][2] + image[indx+u][2] + image[indx-u-1][2] + image[indx+u+1][2] + image[indx-u+1][2] + image[indx+u-1][2]; + float (*pix)[3] = image + (indx - u - 1); float r1 = (*pix)[0]; float g1 = (*pix)[1]; float b1 = (*pix)[2]; @@ -3543,8 +3539,8 @@ void RawImageSource::dcb_pp(float (*image)[4], int x0, int y0) r1 *= 0.125f; g1 *= 0.125f; b1 *= 0.125f; - r1 = r1 + ( image[indx][1] - g1 ); - b1 = b1 + ( image[indx][1] - g1 ); + r1 += ( image[indx][1] - g1 ); + b1 += ( image[indx][1] - g1 ); assert(indx >= 0 && indx < u * u); image[indx][0] = r1; @@ -3554,70 +3550,90 @@ void RawImageSource::dcb_pp(float (*image)[4], int x0, int y0) // interpolated green pixels are corrected using the map // with correction -void RawImageSource::dcb_correction2(float (*image)[4], int x0, int y0) +void RawImageSource::dcb_correction2(float (*image)[3], uint8_t *map, int x0, int y0) { const int u = CACHESIZE, v = 2 * CACHESIZE; int rowMin, colMin, rowMax, colMax; dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 4); for (int row = rowMin; row < rowMax; row++) { - for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { - float current = 4.f * image[indx][3] + - 2.f * (image[indx + u][3] + image[indx - u][3] + image[indx + 1][3] + image[indx - 1][3]) + - image[indx + v][3] + image[indx - v][3] + image[indx + 2][3] + image[indx - 2][3]; + for (int indx = row * CACHESIZE + colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1)); indx < row * CACHESIZE + colMax; indx += 2) { + // map values are uint8_t either 0 or 1. Adding them using integer instructions is perfectly valid and fast. Final result is converted to float then + float current = 4 * map[indx] + + 2 * (map[indx + u] + map[indx - u] + map[indx + 1] + map[indx - 1]) + + map[indx + v] + map[indx - v] + map[indx + 2] + map[indx - 2]; assert(indx >= 0 && indx < u * u); + +// Jacek comment: works now, and has 3 float mults and 9 float adds + image[indx][1] = image[indx][c] + + ((16.f - current) * (image[indx - 1][1] + image[indx + 1][1] - (image[indx + 2][c] + image[indx - 2][c])) + + current * (image[indx - u][1] + image[indx + u][1] - (image[indx + v][c] + image[indx - v][c]))) * 0.03125f; + + + // 4 float mults and 9 float adds + // Jacek comment: not mathematically identical to original +/* image[indx][1] = 16.f * image[indx][c] + + ((16.f - current) * ((image[indx - 1][1] + image[indx + 1][1]) + - (image[indx + 2][c] + image[indx - 2][c])) + + current * ((image[indx - u][1] + image[indx + u][1]) - (image[indx + v][c] + image[indx - v][c]))) * 0.03125f; +*/ + // 7 float mults and 10 float adds + // original code +/* image[indx][1] = ((16.f - current) * ((image[indx - 1][1] + image[indx + 1][1]) * 0.5f + image[indx][c] - (image[indx + 2][c] + image[indx - 2][c]) * 0.5f) + current * ((image[indx - u][1] + image[indx + u][1]) * 0.5f + image[indx][c] - (image[indx + v][c] + image[indx - v][c]) * 0.5f)) * 0.0625f; +*/ } } } // image refinement -void RawImageSource::dcb_refinement(float (*image)[4], int x0, int y0) +void RawImageSource::dcb_refinement(float (*image)[3], uint8_t *map, int x0, int y0) { const int u = CACHESIZE, v = 2 * CACHESIZE, w = 3 * CACHESIZE; int rowMin, colMin, rowMax, colMax; dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 4); - float f[5], g1, g2; + float f0, f1, f2, g1, h0, h1, h2, g2, current; for (int row = rowMin; row < rowMax; row++) for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { - float current = 4.f * image[indx][3] + - 2.f * (image[indx + u][3] + image[indx - u][3] + image[indx + 1][3] + image[indx - 1][3]) - + image[indx + v][3] + image[indx - v][3] + image[indx - 2][3] + image[indx + 2][3]; - f[0] = (float)(image[indx - u][1] + image[indx + u][1]) / (2.f + 2.f * image[indx][c]); - f[1] = 2.f * image[indx - u][1] / (2 + image[indx - v][c] + image[indx][c]); - f[2] = (float)(image[indx - u][1] + image[indx - w][1]) / (2.f + 2.f * image[indx - v][c]); - f[3] = 2.f * image[indx + u][1] / (2 + image[indx + v][c] + image[indx][c]); - f[4] = (float)(image[indx + u][1] + image[indx + w][1]) / (2.f + 2.f * image[indx + v][c]); + float current = 4 * map[indx] + + 2 * (map[indx + u] + map[indx - u] + map[indx + 1] + map[indx - 1]) + + map[indx + v] + map[indx - v] + map[indx - 2] + map[indx + 2]; - g1 = (f[0] + f[1] + f[2] + f[3] + f[4] - max(f[1], f[2], f[3], f[4]) - min(f[1], f[2], f[3], f[4])) / 3.f; + float currPix = image[indx][c]; - f[0] = (float)(image[indx - 1][1] + image[indx + 1][1]) / (2.f + 2.f * image[indx][c]); - f[1] = 2.f * image[indx - 1][1] / (2 + image[indx - 2][c] + image[indx][c]); - f[2] = (float)(image[indx - 1][1] + image[indx - 3][1]) / (2.f + 2.f * image[indx - 2][c]); - f[3] = 2.f * image[indx + 1][1] / (2 + image[indx + 2][c] + image[indx][c]); - f[4] = (float)(image[indx + 1][1] + image[indx + 3][1]) / (2.f + 2.f * image[indx + 2][c]); + f0 = (float)(image[indx - u][1] + image[indx + u][1]) / (1.f + 2.f * currPix); + f1 = 2.f * image[indx - u][1] / (1.f + image[indx - v][c] + currPix); + f2 = 2.f * image[indx + u][1] / (1.f + image[indx + v][c] + currPix); - g2 = (f[0] + f[1] + f[2] + f[3] + f[4] - max(f[1], f[2], f[3], f[4]) - min(f[1], f[2], f[3], f[4])) / 3.f; + g1 = f0 + f1 + f2; + h0 = (float)(image[indx - 1][1] + image[indx + 1][1]) / (1.f + 2.f * currPix); + h1 = 2.f * image[indx - 1][1] / (1.f + image[indx - 2][c] + currPix); + h2 = 2.f * image[indx + 1][1] / (1.f + image[indx + 2][c] + currPix); + + g2 = h0 + h1 + h2; + + // new green value assert(indx >= 0 && indx < u * u); - image[indx][1] = (2.f + image[indx][c]) * (current * g1 + (16.f - current) * g2) * 0.0625f; + currPix *= (current * g1 + (16.f - current) * g2) / 48.f; - // get rid of the overshooted pixels - float min_f = min(image[indx + 1 + u][1], min(image[indx + 1 - u][1], min(image[indx - 1 + u][1], min(image[indx - 1 - u][1], min(image[indx - 1][1], min(image[indx + 1][1], min(image[indx - u][1], image[indx + u][1]))))))); - float max_f = max(image[indx + 1 + u][1], max(image[indx + 1 - u][1], max(image[indx - 1 + u][1], max(image[indx - 1 - u][1], max(image[indx - 1][1], max(image[indx + 1][1], max(image[indx - u][1], image[indx + u][1]))))))); + // get rid of the overshot pixels + float minVal = min(image[indx - 1][1], min(image[indx + 1][1], min(image[indx - u][1], image[indx + u][1]))); + float maxVal = max(image[indx - 1][1], max(image[indx + 1][1], max(image[indx - u][1], image[indx + u][1]))); + + image[indx][1] = LIM(currPix, minVal, maxVal); - image[indx][1] = LIM(image[indx][1], min_f, max_f); } } -// missing colors are interpolated using high quality algorithm by Luis Sanz Rodriguez -void RawImageSource::dcb_color_full(float (*image)[4], int x0, int y0, float (*chroma)[2]) +// missing colours are interpolated using high quality algorithm by Luis Sanz Rodriguez +void RawImageSource::dcb_color_full(float (*image)[3], int x0, int y0, float (*chroma)[2]) { const int u = CACHESIZE, w = 3 * CACHESIZE; int rowMin, colMin, rowMax, colMax; @@ -3637,10 +3653,15 @@ void RawImageSource::dcb_color_full(float (*image)[4], int x0, int y0, float (*c f[1] = 1.f / (float)(1.f + fabs(chroma[indx - u + 1][c] - chroma[indx + u - 1][c]) + fabs(chroma[indx - u + 1][c] - chroma[indx - w + 3][c]) + fabs(chroma[indx + u - 1][c] - chroma[indx - w + 3][c])); f[2] = 1.f / (float)(1.f + fabs(chroma[indx + u - 1][c] - chroma[indx - u + 1][c]) + fabs(chroma[indx + u - 1][c] - chroma[indx + w + 3][c]) + fabs(chroma[indx - u + 1][c] - chroma[indx + w - 3][c])); f[3] = 1.f / (float)(1.f + fabs(chroma[indx + u + 1][c] - chroma[indx - u - 1][c]) + fabs(chroma[indx + u + 1][c] - chroma[indx + w - 3][c]) + fabs(chroma[indx - u - 1][c] - chroma[indx + w + 3][c])); - g[0] = 1.325f * chroma[indx - u - 1][c] - 0.175f * chroma[indx - w - 3][c] - 0.075f * chroma[indx - w - 1][c] - 0.075f * chroma[indx - u - 3][c]; - g[1] = 1.325f * chroma[indx - u + 1][c] - 0.175f * chroma[indx - w + 3][c] - 0.075f * chroma[indx - w + 1][c] - 0.075f * chroma[indx - u + 3][c]; - g[2] = 1.325f * chroma[indx + u - 1][c] - 0.175f * chroma[indx + w - 3][c] - 0.075f * chroma[indx + w - 1][c] - 0.075f * chroma[indx + u - 3][c]; - g[3] = 1.325f * chroma[indx + u + 1][c] - 0.175f * chroma[indx + w + 3][c] - 0.075f * chroma[indx + w + 1][c] - 0.075f * chroma[indx + u + 3][c]; + g[0] = 1.325f * chroma[indx - u - 1][c] - 0.175f * chroma[indx - w - 3][c] - 0.075f * (chroma[indx - w - 1][c] + chroma[indx - u - 3][c]); + g[1] = 1.325f * chroma[indx - u + 1][c] - 0.175f * chroma[indx - w + 3][c] - 0.075f * (chroma[indx - w + 1][c] + chroma[indx - u + 3][c]); + g[2] = 1.325f * chroma[indx + u - 1][c] - 0.175f * chroma[indx + w - 3][c] - 0.075f * (chroma[indx + w - 1][c] + chroma[indx + u - 3][c]); + g[3] = 1.325f * chroma[indx + u + 1][c] - 0.175f * chroma[indx + w + 3][c] - 0.075f * (chroma[indx + w + 1][c] + chroma[indx + u + 3][c]); + +// g[0] = 1.325f * chroma[indx - u - 1][c] - 0.175f * chroma[indx - w - 3][c] - 0.075f * chroma[indx - w - 1][c] - 0.075f * chroma[indx - u - 3][c]; +// g[1] = 1.325f * chroma[indx - u + 1][c] - 0.175f * chroma[indx - w + 3][c] - 0.075f * chroma[indx - w + 1][c] - 0.075f * chroma[indx - u + 3][c]; +// g[2] = 1.325f * chroma[indx + u - 1][c] - 0.175f * chroma[indx + w - 3][c] - 0.075f * chroma[indx + w - 1][c] - 0.075f * chroma[indx + u - 3][c]; +// g[3] = 1.325f * chroma[indx + u + 1][c] - 0.175f * chroma[indx + w + 3][c] - 0.075f * chroma[indx + w + 1][c] - 0.075f * chroma[indx + u + 3][c]; assert(indx >= 0 && indx < u * u && c >= 0 && c < 2); chroma[indx][c] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); @@ -3649,15 +3670,20 @@ void RawImageSource::dcb_color_full(float (*image)[4], int x0, int y0, float (*c for (int row = rowMin; row < rowMax; row++) for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin + 1) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col + 1) / 2; col < colMax; col += 2, indx += 2) for(int d = 0; d <= 1; c = 1 - c, d++) { - f[0] = 1.f / (float)(1.f + fabs(chroma[indx - u][c] - chroma[indx + u][c]) + fabs(chroma[indx - u][c] - chroma[indx - w][c]) + fabs(chroma[indx + u][c] - chroma[indx - w][c])); - f[1] = 1.f / (float)(1.f + fabs(chroma[indx + 1][c] - chroma[indx - 1][c]) + fabs(chroma[indx + 1][c] - chroma[indx + 3][c]) + fabs(chroma[indx - 1][c] - chroma[indx + 3][c])); - f[2] = 1.f / (float)(1.f + fabs(chroma[indx - 1][c] - chroma[indx + 1][c]) + fabs(chroma[indx - 1][c] - chroma[indx - 3][c]) + fabs(chroma[indx + 1][c] - chroma[indx - 3][c])); - f[3] = 1.f / (float)(1.f + fabs(chroma[indx + u][c] - chroma[indx - u][c]) + fabs(chroma[indx + u][c] - chroma[indx + w][c]) + fabs(chroma[indx - u][c] - chroma[indx + w][c])); + f[0] = 1.f / (1.f + fabs(chroma[indx - u][c] - chroma[indx + u][c]) + fabs(chroma[indx - u][c] - chroma[indx - w][c]) + fabs(chroma[indx + u][c] - chroma[indx - w][c])); + f[1] = 1.f / (1.f + fabs(chroma[indx + 1][c] - chroma[indx - 1][c]) + fabs(chroma[indx + 1][c] - chroma[indx + 3][c]) + fabs(chroma[indx - 1][c] - chroma[indx + 3][c])); + f[2] = 1.f / (1.f + fabs(chroma[indx - 1][c] - chroma[indx + 1][c]) + fabs(chroma[indx - 1][c] - chroma[indx - 3][c]) + fabs(chroma[indx + 1][c] - chroma[indx - 3][c])); + f[3] = 1.f / (1.f + fabs(chroma[indx + u][c] - chroma[indx - u][c]) + fabs(chroma[indx + u][c] - chroma[indx + w][c]) + fabs(chroma[indx - u][c] - chroma[indx + w][c])); - g[0] = 0.875f * chroma[indx - u][c] + 0.125f * chroma[indx - w][c]; - g[1] = 0.875f * chroma[indx + 1][c] + 0.125f * chroma[indx + 3][c]; - g[2] = 0.875f * chroma[indx - 1][c] + 0.125f * chroma[indx - 3][c]; - g[3] = 0.875f * chroma[indx + u][c] + 0.125f * chroma[indx + w][c]; + g[0] = intp(0.875f, chroma[indx - u][c], chroma[indx - w][c]); + g[1] = intp(0.875f, chroma[indx + 1][c], chroma[indx + 3][c]); + g[2] = intp(0.875f, chroma[indx - 1][c], chroma[indx - 3][c]); + g[3] = intp(0.875f, chroma[indx + u][c], chroma[indx + w][c]); + +// g[0] = 0.875f * chroma[indx - u][c] + 0.125f * chroma[indx - w][c]; +// g[1] = 0.875f * chroma[indx + 1][c] + 0.125f * chroma[indx + 3][c]; +// g[2] = 0.875f * chroma[indx - 1][c] + 0.125f * chroma[indx - 3][c]; +// g[3] = 0.875f * chroma[indx + u][c] + 0.125f * chroma[indx + w][c]; assert(indx >= 0 && indx < u * u && c >= 0 && c < 2); chroma[indx][c] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); @@ -3672,9 +3698,10 @@ void RawImageSource::dcb_color_full(float (*image)[4], int x0, int y0, float (*c } } -// DCB demosaicing main routine (sharp version) +// DCB demosaicing main routine void RawImageSource::dcb_demosaic(int iterations, bool dcb_enhance) { +BENCHFUN double currentProgress = 0.0; if(plistener) { @@ -3686,29 +3713,24 @@ void RawImageSource::dcb_demosaic(int iterations, bool dcb_enhance) int hTiles = H / TILESIZE + (H % TILESIZE ? 1 : 0); int numTiles = wTiles * hTiles; int tilesDone = 0; + constexpr int cldf = 2; // factor to multiply cache line distance. 1 = 64 bytes, 2 = 128 bytes ... + #ifdef _OPENMP - int nthreads = omp_get_max_threads(); - float (**image)[4] = (float(**)[4]) calloc( nthreads, sizeof( void*) ); - float (**image2)[3] = (float(**)[3]) calloc( nthreads, sizeof( void*) ); - float (**image3)[3] = (float(**)[3]) calloc( nthreads, sizeof( void*) ); - float (**chroma)[2] = (float (**)[2]) calloc( nthreads, sizeof( void*) ); - - for(int i = 0; i < nthreads; i++) { - image[i] = (float(*)[4]) calloc( CACHESIZE * CACHESIZE, sizeof **image); - image2[i] = (float(*)[3]) calloc( CACHESIZE * CACHESIZE, sizeof **image2); - image3[i] = (float(*)[3]) calloc( CACHESIZE * CACHESIZE, sizeof **image3); - chroma[i] = (float (*)[2]) calloc( CACHESIZE * CACHESIZE, sizeof **chroma); - } - -#else - float (*image)[4] = (float(*)[4]) calloc( CACHESIZE * CACHESIZE, sizeof * image); - float (*image2)[3] = (float(*)[3]) calloc( CACHESIZE * CACHESIZE, sizeof * image2); - float (*image3)[3] = (float(*)[3]) calloc( CACHESIZE * CACHESIZE, sizeof * image3); - float (*chroma)[2] = (float (*)[2]) calloc( CACHESIZE * CACHESIZE, sizeof * chroma); + #pragma omp parallel #endif +{ + // assign working space + char *buffer0 = (char *) malloc(5 * sizeof(float) * CACHESIZE * CACHESIZE + sizeof(uint8_t) * CACHESIZE * CACHESIZE + 3 * cldf * 64 + 63); + // aligned to 64 byte boundary + char *data = (char*)( ( uintptr_t(buffer0) + uintptr_t(63)) / 64 * 64); + + float (*tile)[3] = (float(*)[3]) data; + float (*buffer)[2] = (float(*)[2]) ((char*)tile + sizeof(float) * CACHESIZE * CACHESIZE * 3 + cldf * 64); + float (*chrm)[2] = (float(*)[2]) (buffer); // No overlap in usage of buffer and chrm means we can reuse buffer + uint8_t *map = (uint8_t*) ((char*)buffer + sizeof(float) * CACHESIZE * CACHESIZE * 2 + cldf * 64); #ifdef _OPENMP - #pragma omp parallel for + #pragma omp for schedule(dynamic) nowait #endif for( int iTile = 0; iTile < numTiles; iTile++) { @@ -3717,19 +3739,8 @@ void RawImageSource::dcb_demosaic(int iterations, bool dcb_enhance) int x0 = xTile * TILESIZE; int y0 = yTile * TILESIZE; -#ifdef _OPENMP - int tid = omp_get_thread_num(); - assert(tid < nthreads); - float (*tile)[4] = image[tid]; - float (*buffer)[3] = image2[tid]; - float (*buffer2)[3] = image3[tid]; - float (*chrm)[2] = chroma[tid]; -#else - float (*tile)[4] = image; - float (*buffer)[3] = image2; - float (*buffer2)[3] = image3; - float (*chrm)[2] = chroma; -#endif + memset(tile, 0, CACHESIZE * CACHESIZE * sizeof * tile); + memset(map, 0, CACHESIZE * CACHESIZE * sizeof * map); fill_raw( tile, x0, y0, rawData ); @@ -3737,7 +3748,44 @@ void RawImageSource::dcb_demosaic(int iterations, bool dcb_enhance) fill_border(tile, 6, x0, y0); } + copy_to_buffer(buffer, tile); + dcb_hid(tile, x0, y0); + + for (int i = iterations; i > 0; i--) { + dcb_hid2(tile, x0, y0); + dcb_hid2(tile, x0, y0); + dcb_hid2(tile, x0, y0); + dcb_map(tile, map, x0, y0); + dcb_correction(tile, map, x0, y0); + } + + dcb_color(tile, x0, y0); + dcb_pp(tile, x0, y0); + dcb_map(tile, map, x0, y0); + dcb_correction2(tile, map, x0, y0); + dcb_map(tile, map, x0, y0); + dcb_correction(tile, map, x0, y0); + dcb_color(tile, x0, y0); + dcb_map(tile, map, x0, y0); + dcb_correction(tile, map, x0, y0); + dcb_map(tile, map, x0, y0); + dcb_correction(tile, map, x0, y0); + dcb_map(tile, map, x0, y0); + restore_from_buffer(tile, buffer); + + if (!dcb_enhance) + dcb_color(tile, x0, y0); + else + { + memset(chrm, 0, CACHESIZE * CACHESIZE * sizeof * chrm); + dcb_refinement(tile, map, x0, y0); + dcb_color_full(tile, x0, y0, chrm); + } + + /* dcb_hid(tile, buffer, buffer2, x0, y0); + dcb_color(tile, x0, y0); + copy_to_buffer(buffer, tile); for (int i = iterations; i > 0; i--) { @@ -3761,13 +3809,13 @@ void RawImageSource::dcb_demosaic(int iterations, bool dcb_enhance) dcb_correction(tile, x0, y0); dcb_map(tile, x0, y0); restore_from_buffer(tile, buffer); - dcb_color(tile, x0, y0); + dcb_color_full(tile, x0, y0, chrm); if (dcb_enhance) { dcb_refinement(tile, x0, y0); dcb_color_full(tile, x0, y0, chrm); - } - + } +*/ for(int y = 0; y < TILESIZE && y0 + y < H; y++) { for (int j = 0; j < TILESIZE && x0 + j < W; j++) { red[y0 + y][x0 + j] = tile[(y + TILEBORDER) * CACHESIZE + TILEBORDER + j][0]; @@ -3792,21 +3840,8 @@ void RawImageSource::dcb_demosaic(int iterations, bool dcb_enhance) #endif tilesDone++; } - -#ifdef _OPENMP - - for(int i = 0; i < nthreads; i++) { - free(image[i]); - free(image2[i]); - free(image3[i]); - free(chroma[i]); - } - -#endif - free(image); - free(image2); - free(image3); - free(chroma); + free(buffer0); +} if(plistener) { plistener->setProgress (1.0); diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc index 728d40d53..c71d7f98b 100644 --- a/rtengine/dfmanager.cc +++ b/rtengine/dfmanager.cc @@ -144,7 +144,7 @@ void dfInfo::updateRawImage() } else { int H = ri->get_height(); int W = ri->get_width(); - ri->compress_image(); + 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]; @@ -164,7 +164,7 @@ void dfInfo::updateRawImage() RawImage* temp = new RawImage(*iName); if( !temp->loadRaw(true)) { - temp->compress_image(); //\ TODO would be better working on original, because is temporary + 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 ) { @@ -204,7 +204,7 @@ void dfInfo::updateRawImage() delete ri; ri = nullptr; } else { - ri->compress_image(); + ri->compress_image(0); } } } diff --git a/rtengine/expo_before_b.cc b/rtengine/expo_before_b.cc index 0854647c5..98fed04f7 100644 --- a/rtengine/expo_before_b.cc +++ b/rtengine/expo_before_b.cc @@ -44,7 +44,7 @@ namespace rtengine extern const Settings* settings; -void RawImageSource::processRawWhitepoint(float expos, float preser) +void RawImageSource::processRawWhitepoint(float expos, float preser, array2D &rawData) { MyTime t1e, t2e; diff --git a/rtengine/ffmanager.cc b/rtengine/ffmanager.cc index 069bbf563..87ae98905 100644 --- a/rtengine/ffmanager.cc +++ b/rtengine/ffmanager.cc @@ -130,14 +130,13 @@ void ffInfo::updateRawImage() if( !pathNames.empty() ) { std::list::iterator iName = pathNames.begin(); ri = new RawImage(*iName); // First file used also for extra pixels informations (width,height, shutter, filters etc.. ) - if( ri->loadRaw(true)) { delete ri; ri = nullptr; } else { int H = ri->get_height(); int W = ri->get_width(); - ri->compress_image(); + 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]; @@ -157,7 +156,7 @@ void ffInfo::updateRawImage() RawImage* temp = new RawImage(*iName); if( !temp->loadRaw(true)) { - temp->compress_image(); //\ TODO would be better working on original, because is temporary + 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 ) { @@ -192,12 +191,11 @@ void ffInfo::updateRawImage() } } else { ri = new RawImage(pathname); - if( ri->loadRaw(true)) { delete ri; ri = nullptr; } else { - ri->compress_image(); + ri->compress_image(0); } } diff --git a/rtengine/xtranscompressed.cc b/rtengine/fujicompressed.cc similarity index 63% rename from rtengine/xtranscompressed.cc rename to rtengine/fujicompressed.cc index 854ffec2f..2e0b83485 100644 --- a/rtengine/xtranscompressed.cc +++ b/rtengine/fujicompressed.cc @@ -1,5 +1,5 @@ /* -*- C++ -*- - * File: xtranscompressed.cpp + * File: fujicompressed.cpp * Copyright (C) 2016 Alexey Danilchenko * * Adopted to LibRaw by Alex Tutubalin, lexa@lexa.ru @@ -18,19 +18,23 @@ it under the terms of the one of three licenses as you choose: */ -void CLASS init_xtrans (struct xtrans_params* info) +void CLASS init_fuji_compr (struct fuji_compressed_params* info) { int cur_val, i; char *qt; - if (fuji_block_width % 3) { + if ((fuji_block_width % 3 && fuji_raw_type == 16) || (fuji_block_width & 1 && fuji_raw_type == 0)) { derror(); } info->q_table = (char *) malloc (32768); - merror (info->q_table, "init_xtrans()"); + merror (info->q_table, "init_fuji_compr()"); - info->line_width = (fuji_block_width * 2) / 3; + if (fuji_raw_type == 16) { + info->line_width = (fuji_block_width * 2) / 3; + } else { + info->line_width = fuji_block_width >> 1; + } info->q_point[0] = 0; info->q_point[1] = 0x12; @@ -79,9 +83,9 @@ void CLASS init_xtrans (struct xtrans_params* info) } } -#define XTRANS_BUF_SIZE 0x10000u +#define FUJI_BUF_SIZE 0x10000u -void CLASS fuji_fill_buffer (struct xtrans_block *info) +void CLASS fuji_fill_buffer (struct fuji_compressed_block *info) { if (info->cur_pos >= info->cur_buf_size) { info->cur_pos = 0; @@ -91,23 +95,31 @@ void CLASS fuji_fill_buffer (struct xtrans_block *info) #endif { fseek (info->input, info->cur_buf_offset, SEEK_SET); - info->cur_buf_size = fread (info->cur_buf, 1, std::min (info->max_read_size, XTRANS_BUF_SIZE), info->input); + info->cur_buf_size = fread (info->cur_buf, 1, std::min (info->max_read_size, FUJI_BUF_SIZE), info->input); + } + + if (info->cur_buf_size < 1) { // nothing read + if (info->fillbytes > 0) { + int ls = std::max (1, std::min (info->fillbytes, (int)FUJI_BUF_SIZE)); + memset (info->cur_buf, 0, ls); + info->fillbytes -= ls; + } else + ; } - if (info->cur_buf_size < 1) // nothing read - ;//throw LIBRAW_EXCEPTION_IO_EOF; info->max_read_size -= info->cur_buf_size; } } -void CLASS init_xtrans_block (struct xtrans_block* info, const struct xtrans_params *params, INT64 raw_offset, unsigned dsize) +void CLASS init_fuji_block (struct fuji_compressed_block* info, const struct fuji_compressed_params *params, INT64 raw_offset, unsigned dsize) { info->linealloc = (ushort*)calloc (sizeof (ushort), _ltotal * (params->line_width + 2)); - merror (info->linealloc, "init_xtrans_block()"); + merror (info->linealloc, "init_fuji_block()"); info->input = ifp; INT64 fsize = info->input->size; info->max_read_size = std::min (unsigned (fsize - raw_offset), dsize + 16); // Data size may be incorrect? + info->fillbytes = 1; info->linebuf[_R0] = info->linealloc; @@ -116,8 +128,8 @@ void CLASS init_xtrans_block (struct xtrans_block* info, const struct xtrans_par } // init buffer - info->cur_buf = (uchar*)malloc (XTRANS_BUF_SIZE); - merror (info->cur_buf, "init_xtrans_block()"); + info->cur_buf = (uchar*)malloc (FUJI_BUF_SIZE); + merror (info->cur_buf, "init_fuji_block()"); info->cur_bit = 0; info->cur_pos = 0; info->cur_buf_offset = raw_offset; @@ -134,7 +146,7 @@ void CLASS init_xtrans_block (struct xtrans_block* info, const struct xtrans_par fuji_fill_buffer (info); } -void CLASS copy_line_to_xtrans (struct xtrans_block* info, int cur_line, int cur_block, int cur_block_width) +void CLASS copy_line_to_xtrans (struct fuji_compressed_block* info, int cur_line, int cur_block, int cur_block_width) { ushort *lineBufB[3]; ushort *lineBufG[6]; @@ -185,9 +197,67 @@ void CLASS copy_line_to_xtrans (struct xtrans_block* info, int cur_line, int cur } } +void CLASS copy_line_to_bayer (struct fuji_compressed_block *info, int cur_line, int cur_block, int cur_block_width) +{ + ushort *lineBufB[3]; + ushort *lineBufG[6]; + ushort *lineBufR[3]; + unsigned pixel_count; + ushort *line_buf; + + int fuji_bayer[2][2]; + + for (int r = 0; r < 2; r++) + for (int c = 0; c < 2; c++) { + fuji_bayer[r][c] = FC (r, c); // We'll downgrade G2 to G below + } + + int offset = fuji_block_width * cur_block + 6 * raw_width * cur_line; + ushort *raw_block_data = raw_image + offset; + int row_count = 0; + + for (int i = 0; i < 3; i++) { + lineBufR[i] = info->linebuf[_R2 + i] + 1; + lineBufB[i] = info->linebuf[_B2 + i] + 1; + } + + for (int i = 0; i < 6; i++) { + lineBufG[i] = info->linebuf[_G2 + i] + 1; + } + + while (row_count < 6) { + pixel_count = 0; + + while (pixel_count < cur_block_width) { + switch (fuji_bayer[row_count & 1][pixel_count & 1]) { + case 0: // red + line_buf = lineBufR[row_count >> 1]; + break; + + case 1: // green + case 3: // second green + default: // to make static analyzer happy + line_buf = lineBufG[row_count]; + break; + + case 2: // blue + line_buf = lineBufB[row_count >> 1]; + break; + } + + raw_block_data[pixel_count] = line_buf[pixel_count >> 1]; + ++pixel_count; + } + + ++row_count; + raw_block_data += raw_width; + } +} + + #define fuji_quant_gradient(i,v1,v2) (9*i->q_table[i->q_point[4]+(v1)] + i->q_table[i->q_point[4]+(v2)]) -void CLASS fuji_zerobits (struct xtrans_block* info, int *count) +void CLASS fuji_zerobits (struct fuji_compressed_block* info, int *count) { uchar zero = 0; *count = 0; @@ -210,7 +280,7 @@ void CLASS fuji_zerobits (struct xtrans_block* info, int *count) } } -void CLASS fuji_read_code (struct xtrans_block* info, int *data, int bits_to_read) +void CLASS fuji_read_code (struct fuji_compressed_block* info, int *data, int bits_to_read) { uchar bits_left = bits_to_read; uchar bits_left_in_byte = 8 - (info->cur_bit & 7); @@ -253,7 +323,7 @@ int CLASS bitDiff (int value1, int value2) return decBits; } -int CLASS fuji_decode_sample_even (struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads) +int CLASS fuji_decode_sample_even (struct fuji_compressed_block* info, const struct fuji_compressed_params * params, ushort* line_buf, int pos, struct int_pair* grads) { int interp_val = 0; int errcnt = 0; @@ -333,7 +403,7 @@ int CLASS fuji_decode_sample_even (struct xtrans_block* info, const struct xtran return errcnt; } -int CLASS fuji_decode_sample_odd (struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads) +int CLASS fuji_decode_sample_odd (struct fuji_compressed_block* info, const struct fuji_compressed_params * params, ushort* line_buf, int pos, struct int_pair* grads) { int interp_val = 0; int errcnt = 0; @@ -400,7 +470,7 @@ int CLASS fuji_decode_sample_odd (struct xtrans_block* info, const struct xtrans } if ( interp_val >= 0 ) { - line_buf_cur[0] = std::min(interp_val, params->q_point[4]); + line_buf_cur[0] = std::min (interp_val, params->q_point[4]); } else { line_buf_cur[0] = 0; } @@ -428,7 +498,7 @@ void CLASS fuji_decode_interpolation_even (int line_width, ushort* line_buf, int } } -void CLASS xtrans_extend_generic (ushort *linebuf[_ltotal], int line_width, int start, int end) +void CLASS fuji_extend_generic (ushort *linebuf[_ltotal], int line_width, int start, int end) { for (int i = start; i <= end; i++) { linebuf[i][0] = linebuf[i - 1][1]; @@ -436,22 +506,22 @@ void CLASS xtrans_extend_generic (ushort *linebuf[_ltotal], int line_width, int } } -void CLASS xtrans_extend_red (ushort *linebuf[_ltotal], int line_width) +void CLASS fuji_extend_red (ushort *linebuf[_ltotal], int line_width) { - xtrans_extend_generic (linebuf, line_width, _R2, _R4); + fuji_extend_generic (linebuf, line_width, _R2, _R4); } -void CLASS xtrans_extend_green (ushort *linebuf[_ltotal], int line_width) +void CLASS fuji_extend_green (ushort *linebuf[_ltotal], int line_width) { - xtrans_extend_generic (linebuf, line_width, _G2, _G7); + fuji_extend_generic (linebuf, line_width, _G2, _G7); } -void CLASS xtrans_extend_blue (ushort *linebuf[_ltotal], int line_width) +void CLASS fuji_extend_blue (ushort *linebuf[_ltotal], int line_width) { - xtrans_extend_generic (linebuf, line_width, _B2, _B4); + fuji_extend_generic (linebuf, line_width, _B2, _B4); } -void CLASS xtrans_decode_block (struct xtrans_block* info, const struct xtrans_params *params, int cur_line) +void CLASS xtrans_decode_block (struct fuji_compressed_block* info, const struct fuji_compressed_params *params, int cur_line) { int r_even_pos = 0, r_odd_pos = 1; int g_even_pos = 0, g_odd_pos = 1; @@ -477,8 +547,8 @@ void CLASS xtrans_decode_block (struct xtrans_block* info, const struct xtrans_p } } - xtrans_extend_red (info->linebuf, line_width); - xtrans_extend_green (info->linebuf, line_width); + fuji_extend_red (info->linebuf, line_width); + fuji_extend_green (info->linebuf, line_width); g_even_pos = 0, g_odd_pos = 1; @@ -498,8 +568,8 @@ void CLASS xtrans_decode_block (struct xtrans_block* info, const struct xtrans_p } } - xtrans_extend_green (info->linebuf, line_width); - xtrans_extend_blue (info->linebuf, line_width); + fuji_extend_green (info->linebuf, line_width); + fuji_extend_blue (info->linebuf, line_width); r_even_pos = 0, r_odd_pos = 1; g_even_pos = 0, g_odd_pos = 1; @@ -525,8 +595,8 @@ void CLASS xtrans_decode_block (struct xtrans_block* info, const struct xtrans_p } } - xtrans_extend_red (info->linebuf, line_width); - xtrans_extend_green (info->linebuf, line_width); + fuji_extend_red (info->linebuf, line_width); + fuji_extend_green (info->linebuf, line_width); g_even_pos = 0, g_odd_pos = 1; b_even_pos = 0, b_odd_pos = 1; @@ -553,8 +623,8 @@ void CLASS xtrans_decode_block (struct xtrans_block* info, const struct xtrans_p } } - xtrans_extend_green (info->linebuf, line_width); - xtrans_extend_blue (info->linebuf, line_width); + fuji_extend_green (info->linebuf, line_width); + fuji_extend_blue (info->linebuf, line_width); r_even_pos = 0, r_odd_pos = 1; g_even_pos = 0, g_odd_pos = 1; @@ -580,8 +650,8 @@ void CLASS xtrans_decode_block (struct xtrans_block* info, const struct xtrans_p } } - xtrans_extend_red (info->linebuf, line_width); - xtrans_extend_green (info->linebuf, line_width); + fuji_extend_red (info->linebuf, line_width); + fuji_extend_green (info->linebuf, line_width); g_even_pos = 0, g_odd_pos = 1; b_even_pos = 0, b_odd_pos = 1; @@ -608,21 +678,165 @@ void CLASS xtrans_decode_block (struct xtrans_block* info, const struct xtrans_p } } - xtrans_extend_green (info->linebuf, line_width); - xtrans_extend_blue (info->linebuf, line_width); + fuji_extend_green (info->linebuf, line_width); + fuji_extend_blue (info->linebuf, line_width); if (errcnt) { derror(); } } -void CLASS xtrans_decode_strip (const struct xtrans_params* info_common, int cur_block, INT64 raw_offset, unsigned dsize) +void CLASS fuji_bayer_decode_block (struct fuji_compressed_block *info, const struct fuji_compressed_params *params, + int cur_line) +{ + int r_even_pos = 0, r_odd_pos = 1; + int g_even_pos = 0, g_odd_pos = 1; + int b_even_pos = 0, b_odd_pos = 1; + + int errcnt = 0; + + const int line_width = params->line_width; + + while (g_even_pos < line_width || g_odd_pos < line_width) { + if (g_even_pos < line_width) { + errcnt += fuji_decode_sample_even (info, params, info->linebuf[_R2] + 1, r_even_pos, info->grad_even[0]); + r_even_pos += 2; + errcnt += fuji_decode_sample_even (info, params, info->linebuf[_G2] + 1, g_even_pos, info->grad_even[0]); + g_even_pos += 2; + } + + if (g_even_pos > 8) { + errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_R2] + 1, r_odd_pos, info->grad_odd[0]); + r_odd_pos += 2; + errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_G2] + 1, g_odd_pos, info->grad_odd[0]); + g_odd_pos += 2; + } + } + + fuji_extend_red (info->linebuf, line_width); + fuji_extend_green (info->linebuf, line_width); + + g_even_pos = 0, g_odd_pos = 1; + + while (g_even_pos < line_width || g_odd_pos < line_width) { + if (g_even_pos < line_width) { + errcnt += fuji_decode_sample_even (info, params, info->linebuf[_G3] + 1, g_even_pos, info->grad_even[1]); + g_even_pos += 2; + errcnt += fuji_decode_sample_even (info, params, info->linebuf[_B2] + 1, b_even_pos, info->grad_even[1]); + b_even_pos += 2; + } + + if (g_even_pos > 8) { + errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_G3] + 1, g_odd_pos, info->grad_odd[1]); + g_odd_pos += 2; + errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_B2] + 1, b_odd_pos, info->grad_odd[1]); + b_odd_pos += 2; + } + } + + fuji_extend_green (info->linebuf, line_width); + fuji_extend_blue (info->linebuf, line_width); + + r_even_pos = 0, r_odd_pos = 1; + g_even_pos = 0, g_odd_pos = 1; + + while (g_even_pos < line_width || g_odd_pos < line_width) { + if (g_even_pos < line_width) { + errcnt += fuji_decode_sample_even (info, params, info->linebuf[_R3] + 1, r_even_pos, info->grad_even[2]); + r_even_pos += 2; + errcnt += fuji_decode_sample_even (info, params, info->linebuf[_G4] + 1, g_even_pos, info->grad_even[2]); + g_even_pos += 2; + } + + if (g_even_pos > 8) { + errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_R3] + 1, r_odd_pos, info->grad_odd[2]); + r_odd_pos += 2; + errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_G4] + 1, g_odd_pos, info->grad_odd[2]); + g_odd_pos += 2; + } + } + + fuji_extend_red (info->linebuf, line_width); + fuji_extend_green (info->linebuf, line_width); + + g_even_pos = 0, g_odd_pos = 1; + b_even_pos = 0, b_odd_pos = 1; + + while (g_even_pos < line_width || g_odd_pos < line_width) { + if (g_even_pos < line_width) { + errcnt += fuji_decode_sample_even (info, params, info->linebuf[_G5] + 1, g_even_pos, info->grad_even[0]); + g_even_pos += 2; + errcnt += fuji_decode_sample_even (info, params, info->linebuf[_B3] + 1, b_even_pos, info->grad_even[0]); + b_even_pos += 2; + } + + if (g_even_pos > 8) { + errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_G5] + 1, g_odd_pos, info->grad_odd[0]); + g_odd_pos += 2; + errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_B3] + 1, b_odd_pos, info->grad_odd[0]); + b_odd_pos += 2; + } + } + + fuji_extend_green (info->linebuf, line_width); + fuji_extend_blue (info->linebuf, line_width); + + r_even_pos = 0, r_odd_pos = 1; + g_even_pos = 0, g_odd_pos = 1; + + while (g_even_pos < line_width || g_odd_pos < line_width) { + if (g_even_pos < line_width) { + errcnt += fuji_decode_sample_even (info, params, info->linebuf[_R4] + 1, r_even_pos, info->grad_even[1]); + r_even_pos += 2; + errcnt += fuji_decode_sample_even (info, params, info->linebuf[_G6] + 1, g_even_pos, info->grad_even[1]); + g_even_pos += 2; + } + + if (g_even_pos > 8) { + errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_R4] + 1, r_odd_pos, info->grad_odd[1]); + r_odd_pos += 2; + errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_G6] + 1, g_odd_pos, info->grad_odd[1]); + g_odd_pos += 2; + } + } + + fuji_extend_red (info->linebuf, line_width); + fuji_extend_green (info->linebuf, line_width); + + g_even_pos = 0, g_odd_pos = 1; + b_even_pos = 0, b_odd_pos = 1; + + while (g_even_pos < line_width || g_odd_pos < line_width) { + if (g_even_pos < line_width) { + errcnt += fuji_decode_sample_even (info, params, info->linebuf[_G7] + 1, g_even_pos, info->grad_even[2]); + g_even_pos += 2; + errcnt += fuji_decode_sample_even (info, params, info->linebuf[_B4] + 1, b_even_pos, info->grad_even[2]); + b_even_pos += 2; + } + + if (g_even_pos > 8) { + errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_G7] + 1, g_odd_pos, info->grad_odd[2]); + g_odd_pos += 2; + errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_B4] + 1, b_odd_pos, info->grad_odd[2]); + b_odd_pos += 2; + } + } + + fuji_extend_green (info->linebuf, line_width); + fuji_extend_blue (info->linebuf, line_width); + + if (errcnt) { + derror(); + } +} + +void CLASS fuji_decode_strip (const struct fuji_compressed_params* info_common, int cur_block, INT64 raw_offset, unsigned dsize) { int cur_block_width, cur_line; unsigned line_size; - struct xtrans_block info; + struct fuji_compressed_block info; - init_xtrans_block (&info, info_common, raw_offset, dsize); + init_fuji_block (&info, info_common, raw_offset, dsize); line_size = sizeof (ushort) * (info_common->line_width + 2); cur_block_width = fuji_block_width; @@ -639,14 +853,22 @@ void CLASS xtrans_decode_strip (const struct xtrans_params* info_common, int cur ztable[3] = {{_R2, 3}, {_G2, 6}, {_B2, 3}}; for (cur_line = 0; cur_line < fuji_total_lines; cur_line++) { - xtrans_decode_block (&info, info_common, cur_line); + if (fuji_raw_type == 16) { + xtrans_decode_block (&info, info_common, cur_line); + } else { + fuji_bayer_decode_block (&info, info_common, cur_line); + } // copy data from line buffers and advance for (int i = 0; i < 6; i++) { memcpy (info.linebuf[mtable[i].a], info.linebuf[mtable[i].b], line_size); } - copy_line_to_xtrans (&info, cur_line, cur_block, cur_block_width); + if (fuji_raw_type == 16) { + copy_line_to_xtrans (&info, cur_line, cur_block, cur_block_width); + } else { + copy_line_to_bayer (&info, cur_line, cur_block, cur_block_width); + } for (int i = 0; i < 3; i++) { memset (info.linebuf[ztable[i].a], 0, ztable[i].b * line_size); @@ -671,22 +893,22 @@ static unsigned sgetn (int n, uchar *s) return result; } -void CLASS xtrans_compressed_load_raw() +void CLASS fuji_compressed_load_raw() { - struct xtrans_params common_info; + struct fuji_compressed_params common_info; int cur_block; unsigned line_size, *block_sizes; INT64 raw_offset, *raw_block_offsets; - //struct xtrans_block info; + //struct fuji_compressed_block info; - init_xtrans (&common_info); + init_fuji_compr (&common_info); line_size = sizeof (ushort) * (common_info.line_width + 2); // read block sizes block_sizes = (unsigned*) malloc (sizeof (unsigned) * fuji_total_blocks); - merror (block_sizes, "xtrans_load_raw()"); + merror (block_sizes, "fuji_compressed_load_raw()"); raw_block_offsets = (INT64*) malloc (sizeof (INT64) * fuji_total_blocks); - merror (raw_block_offsets, "xtrans_load_raw()"); + merror (raw_block_offsets, "fuji_compressed_load_raw()"); raw_offset = sizeof (unsigned) * fuji_total_blocks; @@ -711,27 +933,27 @@ void CLASS xtrans_compressed_load_raw() raw_block_offsets[cur_block] = raw_block_offsets[cur_block - 1] + block_sizes[cur_block - 1] ; } - xtrans_decode_loop (&common_info, fuji_total_blocks, raw_block_offsets, block_sizes); + fuji_decode_loop (&common_info, fuji_total_blocks, raw_block_offsets, block_sizes); free (block_sizes); free (raw_block_offsets); free (common_info.q_table); } -void CLASS xtrans_decode_loop (const struct xtrans_params* common_info, int count, INT64* raw_block_offsets, unsigned *block_sizes) +void CLASS fuji_decode_loop (const struct fuji_compressed_params* common_info, int count, INT64* raw_block_offsets, unsigned *block_sizes) { #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel for schedule(dynamic,1) // dynamic scheduling is faster if count > number of cores (e.g. count for GFX 50S is 12) #endif for (int cur_block = 0; cur_block < count ; cur_block++) { - xtrans_decode_strip (common_info, cur_block, raw_block_offsets[cur_block], block_sizes[cur_block]); + fuji_decode_strip (common_info, cur_block, raw_block_offsets[cur_block], block_sizes[cur_block]); } } -void CLASS parse_xtrans_header() +void CLASS parse_fuji_compressed_header() { uchar header[16]; @@ -783,7 +1005,7 @@ void CLASS parse_xtrans_header() || h_total_lines == 0 || h_total_lines != h_raw_height / 6 || (h_raw_bits != 12 && h_raw_bits != 14) - || h_raw_type != 16) { + || (h_raw_type != 16 && h_raw_type != 0)) { xtransCompressed = false; return; } @@ -793,8 +1015,9 @@ void CLASS parse_xtrans_header() fuji_total_blocks = h_blocks_in_row; fuji_block_width = h_block_size; fuji_bits = h_raw_bits; + fuji_raw_type = h_raw_type; raw_width = h_raw_width; raw_height = h_raw_height; data_offset += 16; - load_raw = &CLASS xtrans_compressed_load_raw; + load_raw = &CLASS fuji_compressed_load_raw; } diff --git a/rtengine/green_equil_RT.cc b/rtengine/green_equil_RT.cc index a9183509d..8b1136359 100644 --- a/rtengine/green_equil_RT.cc +++ b/rtengine/green_equil_RT.cc @@ -30,12 +30,11 @@ #include "rt_math.h" #include "rawimagesource.h" - namespace rtengine { //void green_equilibrate()//for dcraw implementation -void RawImageSource::green_equilibrate(float thresh) +void RawImageSource::green_equilibrate(float thresh, array2D &rawData) { // thresh = threshold for performing green equilibration; max percentage difference of G1 vs G2 // G1-G2 differences larger than this will be assumed to be Nyquist texture, and left untouched @@ -79,7 +78,7 @@ void RawImageSource::green_equilibrate(float thresh) */ //now smooth the cfa data #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel for schedule(dynamic,16) #endif for (int rr = 4; rr < height - 4; rr++) @@ -99,8 +98,8 @@ void RawImageSource::green_equilibrate(float thresh) float d1 = (o1_1 + o1_2 + o1_3 + o1_4) * 0.25f; float d2 = (o2_1 + o2_2 + o2_3 + o2_4) * 0.25f; - float c1 = (fabs(o1_1 - o1_2) + fabs(o1_1 - o1_3) + fabs(o1_1 - o1_4) + fabs(o1_2 - o1_3) + fabs(o1_3 - o1_4) + fabs(o1_2 - o1_4)) / 6.0; - float c2 = (fabs(o2_1 - o2_2) + fabs(o2_1 - o2_3) + fabs(o2_1 - o2_4) + fabs(o2_2 - o2_3) + fabs(o2_3 - o2_4) + fabs(o2_2 - o2_4)) / 6.0; + float c1 = (fabs(o1_1 - o1_2) + fabs(o1_1 - o1_3) + fabs(o1_1 - o1_4) + fabs(o1_2 - o1_3) + fabs(o1_3 - o1_4) + fabs(o1_2 - o1_4)) / 6.f; + float c2 = (fabs(o2_1 - o2_2) + fabs(o2_1 - o2_3) + fabs(o2_1 - o2_4) + fabs(o2_2 - o2_3) + fabs(o2_3 - o2_4) + fabs(o2_2 - o2_4)) / 6.f; //%%%%%%%%%%%%%%%%%%%%%% //vote1=(checker[rr-2][cc]+checker[rr][cc-2]+checker[rr][cc+2]+checker[rr+2][cc]); @@ -111,10 +110,10 @@ void RawImageSource::green_equilibrate(float thresh) //pixel interpolation float gin = cfa[rr][cc]; - float gse = (cfa[rr + 1][cc + 1]) + 0.5 * (cfa[rr][cc] - cfa[rr + 2][cc + 2]); - float gnw = (cfa[rr - 1][cc - 1]) + 0.5 * (cfa[rr][cc] - cfa[rr - 2][cc - 2]); - float gne = (cfa[rr - 1][cc + 1]) + 0.5 * (cfa[rr][cc] - cfa[rr - 2][cc + 2]); - float gsw = (cfa[rr + 1][cc - 1]) + 0.5 * (cfa[rr][cc] - cfa[rr + 2][cc - 2]); + float gse = (cfa[rr + 1][cc + 1]) + 0.5f * (cfa[rr][cc] - cfa[rr + 2][cc + 2]); + float gnw = (cfa[rr - 1][cc - 1]) + 0.5f * (cfa[rr][cc] - cfa[rr - 2][cc - 2]); + float gne = (cfa[rr - 1][cc + 1]) + 0.5f * (cfa[rr][cc] - cfa[rr - 2][cc + 2]); + float gsw = (cfa[rr + 1][cc - 1]) + 0.5f * (cfa[rr][cc] - cfa[rr + 2][cc - 2]); diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index bfb08e472..527dae568 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -510,7 +510,7 @@ public: for (const auto profile : fileProfiles) { if ( -( + ( type==ICCStore::ProfileType::MONITOR && cmsGetDeviceClass(profile.second) == cmsSigDisplayClass && cmsGetColorSpace(profile.second) == cmsSigRgbData @@ -521,7 +521,7 @@ public: ) ||( type==ICCStore::ProfileType::OUTPUT - && cmsGetDeviceClass(profile.second) == cmsSigDisplayClass + && (cmsGetDeviceClass(profile.second) == cmsSigDisplayClass || cmsGetDeviceClass(profile.second) == cmsSigOutputClass) && cmsGetColorSpace(profile.second) == cmsSigRgbData ) ) { diff --git a/rtengine/image16.cc b/rtengine/image16.cc index df2c5a21f..e0f7470a6 100644 --- a/rtengine/image16.cc +++ b/rtengine/image16.cc @@ -153,8 +153,8 @@ void Image16::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, Preview transform (pp, tran, sx1, sy1, sx2, sy2); - int imwidth = image->width; // Destination image - int imheight = image->height; // Destination image + int imwidth = image->getWidth(); // Destination image + int imheight = image->getHeight(); // Destination image if (((tran & TR_ROT) == TR_R90) || ((tran & TR_ROT) == TR_R270)) { int swap = imwidth; @@ -165,7 +165,7 @@ void Image16::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, Preview int maxx = width; // Source image int maxy = height; // Source image int mtran = tran & TR_ROT; - int skip = pp.skip; + int skip = pp.getSkip(); //if ((sx1 + skip*imwidth)>maxx) imwidth -- ; // we have a boundary condition that can cause errors diff --git a/rtengine/image8.cc b/rtengine/image8.cc index 9eaf3afc5..56c2a63ee 100644 --- a/rtengine/image8.cc +++ b/rtengine/image8.cc @@ -113,8 +113,8 @@ void Image8::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewP transform (pp, tran, sx1, sy1, sx2, sy2); - int imwidth = image->width; // Destination image - int imheight = image->height; // Destination image + int imwidth = image->getWidth(); // Destination image + int imheight = image->getHeight(); // Destination image if (((tran & TR_ROT) == TR_R90) || ((tran & TR_ROT) == TR_R270)) { int swap = imwidth; @@ -125,7 +125,7 @@ void Image8::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewP int maxx = width; // Source image int maxy = height; // Source image int mtran = tran & TR_ROT; - int skip = pp.skip; + int skip = pp.getSkip(); //if ((sx1 + skip*imwidth)>maxx) imwidth -- ; // we have a boundary condition that can cause errors diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 8dfd90ab3..fa3651571 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -16,9 +16,11 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ +#include +#include + #include "imagedata.h" #include "iptcpairs.h" -#include using namespace rtengine; diff --git a/rtengine/imagedimensions.cc b/rtengine/imagedimensions.cc index f7d291483..7dec1358a 100644 --- a/rtengine/imagedimensions.cc +++ b/rtengine/imagedimensions.cc @@ -20,49 +20,88 @@ #include "imagedimensions.h" #include "rtengine.h" -void ImageDimensions::transform (PreviewProps pp, int tran, int &sx1, int &sy1, int &sx2, int &sy2) +PreviewProps::PreviewProps(int _x, int _y, int _width, int _height, int _skip) : + x(_x), + y(_y), + width(_width), + height(_height), + skip(_skip) { +} - int sw = width, sh = height; +int PreviewProps::getX() const +{ + return x; +} + +int PreviewProps::getY() const +{ + return y; +} + +int PreviewProps::getWidth() const +{ + return width; +} + +int PreviewProps::getHeight() const +{ + return height; +} + +int PreviewProps::getSkip() const +{ + return skip; +} + +ImageDimensions::ImageDimensions() : + width(-1), + height(-1) +{ +} + +void ImageDimensions::transform(const PreviewProps& pp, int tran, int& sx1, int& sy1, int& sx2, int& sy2) const +{ + int sw = width; + int sh = height; if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { - sw = height; - sh = width; + std::swap(sw, sh); } - int ppx = pp.x, ppy = pp.y; + int ppx = pp.getX(); + int ppy = pp.getY(); if (tran & TR_HFLIP) { - ppx = sw - pp.x - pp.w; + ppx = sw - pp.getX() - pp.getWidth(); } if (tran & TR_VFLIP) { - ppy = sh - pp.y - pp.h; + ppy = sh - pp.getY() - pp.getHeight(); } sx1 = ppx; sy1 = ppy; - sx2 = ppx + pp.w; - sy2 = ppy + pp.h; + sx2 = ppx + pp.getWidth(); + sy2 = ppy + pp.getHeight(); if ((tran & TR_ROT) == TR_R180) { - sx1 = width - ppx - pp.w; - sy1 = height - ppy - pp.h; - sx2 = sx1 + pp.w; - sy2 = sy1 + pp.h; + sx1 = width - ppx - pp.getWidth(); + sy1 = height - ppy - pp.getHeight(); + sx2 = sx1 + pp.getWidth(); + sy2 = sy1 + pp.getHeight(); } else if ((tran & TR_ROT) == TR_R90) { sx1 = ppy; - sy1 = height - ppx - pp.w; - sx2 = sx1 + pp.h; - sy2 = sy1 + pp.w; + sy1 = height - ppx - pp.getWidth(); + sx2 = sx1 + pp.getHeight(); + sy2 = sy1 + pp.getWidth(); } else if ((tran & TR_ROT) == TR_R270) { - sx1 = width - ppy - pp.h; + sx1 = width - ppy - pp.getHeight(); sy1 = ppx; - sx2 = sx1 + pp.h; - sy2 = sy1 + pp.w; + sx2 = sx1 + pp.getHeight(); + sy2 = sy1 + pp.getWidth(); } - //printf ("ppx %d ppy %d ppw %d pph %d s: %d %d %d %d\n",pp.x, pp.y,pp.w,pp.h,sx1,sy1,sx2,sy2); if (sx1 < 0) { sx1 = 0; } diff --git a/rtengine/imagedimensions.h b/rtengine/imagedimensions.h index e3b98f7c5..63b1a1062 100644 --- a/rtengine/imagedimensions.h +++ b/rtengine/imagedimensions.h @@ -17,47 +17,47 @@ * along with RawTherapee. If not, see . */ -#ifndef _IMAGEDIMENSIONS_ -#define _IMAGEDIMENSIONS_ +#pragma once class PreviewProps { public: - int x, y, w, h, skip; - PreviewProps (int _x, int _y, int _w, int _h, int _skip) - : x(_x), y(_y), w(_w), h(_h), skip(_skip) {} + PreviewProps(int _x, int _y, int _width, int _height, int _skip); + + int getX() const; + int getY() const; + int getWidth() const; + int getHeight() const; + int getSkip() const; + +private: + int x; + int y; + int width; + int height; + int skip; }; /* - * Description of an image dimension, with getter and setter + * Description of an image dimension, with getter */ class ImageDimensions { - public: + ImageDimensions(); + + int getWidth() const + { + return width; + } + int getHeight() const + { + return height; + } + + void transform(const PreviewProps& pp, int tran, int& sx1, int& sy1, int& sx2, int& sy2) const; + +protected: int width; int height; - -public: - ImageDimensions() : width(-1), height(-1) {} - int getW () - { - return width; - } - int getH () - { - return height; - } - int getWidth () const - { - return width; - } - int getHeight () const - { - return height; - } - void transform (PreviewProps pp, int tran, int &sx1, int &sy1, int &sx2, int &sy2); }; - - -#endif diff --git a/rtengine/imagefloat.cc b/rtengine/imagefloat.cc index 665ba3ac6..a0a7e293c 100644 --- a/rtengine/imagefloat.cc +++ b/rtengine/imagefloat.cc @@ -203,7 +203,7 @@ void Imagefloat::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, Prev int maxx = width; // Source image int maxy = height; // Source image int mtran = tran & TR_ROT; - int skip = pp.skip; + int skip = pp.getSkip(); // improve speed by integrating the area division into the multipliers // switched to using ints for the red/green/blue channel buffer. diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index b8f2fb580..f24842b65 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -895,7 +895,7 @@ int ImageIO::loadPPMFromMemory(const char* buffer, int width, int height, bool s char swapped[line_length]; for ( int row = 0; row < height; ++row ) { - ::swab(((char*)buffer) + (row * line_length), swapped, line_length); + ::rtengine::swab(((char*)buffer) + (row * line_length), swapped, line_length); setScanline(row, (unsigned char*)&swapped[0], bps); } } else { @@ -909,7 +909,7 @@ int ImageIO::loadPPMFromMemory(const char* buffer, int width, int height, bool s int ImageIO::savePNG (Glib::ustring fname, int compression, volatile int bps) { - if (getW() < 1 || getH() < 1) { + if (getWidth() < 1 || getHeight() < 1) { return IMIO_HEADERERROR; } @@ -949,8 +949,8 @@ int ImageIO::savePNG (Glib::ustring fname, int compression, volatile int bps) png_set_compression_level(png, compression); - int width = getW (); - int height = getH (); + int width = getWidth (); + int height = getHeight (); if (bps < 0) { bps = getBPS (); @@ -1006,7 +1006,7 @@ int ImageIO::savePNG (Glib::ustring fname, int compression, volatile int bps) // Quality 0..100, subsampling: 1=low quality, 2=medium, 3=high int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) { - if (getW() < 1 || getH() < 1) { + if (getWidth() < 1 || getHeight() < 1) { return IMIO_HEADERERROR; } @@ -1054,8 +1054,8 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) jpeg_stdio_dest (&cinfo, file); - int width = getW (); - int height = getH (); + int width = getWidth (); + int height = getHeight (); cinfo.image_width = width; cinfo.image_height = height; @@ -1196,14 +1196,14 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) { - if (getW() < 1 || getH() < 1) { + if (getWidth() < 1 || getHeight() < 1) { return IMIO_HEADERERROR; } //TODO: Handling 32 bits floating point output images! bool writeOk = true; - int width = getW (); - int height = getH (); + int width = getWidth (); + int height = getHeight (); if (bps < 0) { bps = getBPS (); diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 59d46035b..8998fa848 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -66,7 +66,7 @@ public: embProfile(nullptr), idata(nullptr), dirpyrdenoiseExpComp(INFINITY) {} virtual ~ImageSource () {} - virtual int load (const Glib::ustring &fname, bool batch = false) = 0; + virtual int load (const Glib::ustring &fname, int imageNum = 0, bool batch = false) = 0; virtual void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse, bool prepareDenoise = true) {}; virtual void demosaic (const RAWParams &raw) {}; virtual void retinex (ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) {}; @@ -80,6 +80,9 @@ public: virtual bool IsrgbSourceModified() const = 0; // tracks whether cached rgb output of demosaic has been modified + virtual void setCurrentFrame(unsigned int frameNum) = 0; + + // use right after demosaicing image, add coarse transformation and put the result in the provided Imagefloat* virtual void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hlp, const ColorManagementParams &cmp, const RAWParams &raw) = 0; virtual eSensorType getSensorType () @@ -157,6 +160,7 @@ public: { return this; } + virtual void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) = 0; }; } #endif diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index e5422f6b3..31a09ef22 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -34,7 +34,7 @@ extern const Settings* settings; ImProcCoordinator::ImProcCoordinator () : orig_prev(nullptr), oprevi(nullptr), oprevl(nullptr), nprevl(nullptr), previmg(nullptr), workimg(nullptr), - ncie(nullptr), imgsrc(nullptr), shmap(nullptr), lastAwbEqual(0.), ipf(¶ms, true), monitorIntent(RI_RELATIVE), + ncie(nullptr), imgsrc(nullptr), shmap(nullptr), lastAwbEqual(0.), lastAwbTempBias(0.0), ipf(¶ms, true), monitorIntent(RI_RELATIVE), softProof(false), gamutCheck(false), scale(10), highDetailPreprocessComputed(false), highDetailRawComputed(false), allocated(false), bwAutoR(-9000.f), bwAutoG(-9000.f), bwAutoB(-9000.f), CAMMean(NAN), @@ -87,7 +87,7 @@ ImProcCoordinator::ImProcCoordinator () fw(0), fh(0), tr(0), fullw(1), fullh(1), pW(-1), pH(-1), - plistener(nullptr), imageListener(nullptr), aeListener(nullptr), acListener(nullptr), abwListener(nullptr), actListener(nullptr), adnListener(nullptr), awavListener(nullptr), dehaListener(nullptr), hListener(nullptr), + plistener(nullptr), imageListener(nullptr), aeListener(nullptr), acListener(nullptr), abwListener(nullptr), awbListener(nullptr), actListener(nullptr), adnListener(nullptr), awavListener(nullptr), dehaListener(nullptr), hListener(nullptr), resultValid(false), lastOutputProfile("BADFOOD"), lastOutputIntent(RI__COUNT), lastOutputBPC(false), thread(nullptr), changeSinceLast(0), updaterRunning(false), destroying(false), utili(false), autili(false), wavcontlutili(false), butili(false), ccutili(false), cclutili(false), clcutili(false), opautili(false), conversionBuffer(1, 1), colourToningSatLimit(0.f), colourToningSatLimitOpacity(0.f) {} @@ -185,6 +185,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) // raw auto CA is bypassed if no high detail is needed, so we have to compute it when high detail is needed if ( (todo & M_PREPROC) || (!highDetailPreprocessComputed && highDetailNeeded)) { + imgsrc->setCurrentFrame(params.raw.bayersensor.imageNum); imgsrc->preprocess( rp, params.lensProf, params.coarse ); imgsrc->getRAWHistogram( histRedRaw, histGreenRaw, histBlueRaw ); @@ -214,7 +215,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) if (settings->verbose) { if (imgsrc->getSensorType() == ST_BAYER) { - printf("Demosaic Bayer image using method: %s\n", rp.bayersensor.method.c_str()); + printf("Demosaic Bayer image n.%d using method: %s\n", rp.bayersensor.imageNum + 1, rp.bayersensor.method.c_str()); } else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) { printf("Demosaic X-Trans image with using method: %s\n", rp.xtranssensor.method.c_str()); } @@ -284,15 +285,17 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) if (params.wb.method == "Camera") { currWB = imgsrc->getWB (); } else if (params.wb.method == "Auto") { - if (lastAwbEqual != params.wb.equal) { + if (lastAwbEqual != params.wb.equal || lastAwbTempBias != params.wb.tempBias) { double rm, gm, bm; imgsrc->getAutoWBMultipliers(rm, gm, bm); if (rm != -1.) { - autoWB.update(rm, gm, bm, params.wb.equal); + autoWB.update(rm, gm, bm, params.wb.equal, params.wb.tempBias); lastAwbEqual = params.wb.equal; + lastAwbTempBias = params.wb.tempBias; } else { lastAwbEqual = -1.; + lastAwbTempBias = 0.0; autoWB.useDefaults(params.wb.equal); } @@ -305,6 +308,9 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) params.wb.temperature = currWB.getTemp (); params.wb.green = currWB.getGreen (); + if(params.wb.method == "Auto" && awbListener) { + awbListener->WBChanged(params.wb.temperature, params.wb.green); + } int tr = getCoarseBitMask(params.coarse); @@ -796,7 +802,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) MyMutex::MyLock prevImgLock(previmg->getMutex()); try { - // Computing the preview image, i.e. converting from WCS->Monitor color space (soft-proofing disabled) or WCS->Output profile->Monitor color space (soft-proofing enabled) + // Computing the preview image, i.e. converting from WCS->Monitor color space (soft-proofing disabled) or WCS->Printer profile->Monitor color space (soft-proofing enabled) ipf.lab2monitorRgb (nprevl, previmg); // Computing the internal image for analysis, i.e. conversion from WCS->Output profile @@ -1011,21 +1017,23 @@ void ImProcCoordinator::progress (Glib::ustring str, int pr) }*/ } -bool ImProcCoordinator::getAutoWB (double& temp, double& green, double equal) +bool ImProcCoordinator::getAutoWB (double& temp, double& green, double equal, double tempBias) { if (imgsrc) { - if (lastAwbEqual != equal) { + if (lastAwbEqual != equal || lastAwbTempBias != tempBias) { // Issue 2500 MyMutex::MyLock lock(minit); // Also used in crop window double rm, gm, bm; imgsrc->getAutoWBMultipliers(rm, gm, bm); if (rm != -1) { - autoWB.update(rm, gm, bm, equal); + autoWB.update(rm, gm, bm, equal, tempBias); lastAwbEqual = equal; + lastAwbTempBias = tempBias; } else { lastAwbEqual = -1.; autoWB.useDefaults(equal); + lastAwbTempBias = 0.0; } } @@ -1162,15 +1170,17 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool if (params.wb.method == "Camera") { currWB = imgsrc->getWB (); } else if (params.wb.method == "Auto") { - if (lastAwbEqual != params.wb.equal) { + if (lastAwbEqual != params.wb.equal || lastAwbTempBias != params.wb.tempBias) { double rm, gm, bm; imgsrc->getAutoWBMultipliers(rm, gm, bm); if (rm != -1.) { - autoWB.update(rm, gm, bm, params.wb.equal); + autoWB.update(rm, gm, bm, params.wb.equal, params.wb.tempBias); lastAwbEqual = params.wb.equal; + lastAwbTempBias = params.wb.tempBias; } else { lastAwbEqual = -1.; + lastAwbTempBias = 0.0; autoWB.useDefaults(params.wb.equal); } } @@ -1216,8 +1226,8 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool // image may contain out of range samples, clip them to avoid wrap-arounds #pragma omp parallel for - for(int i = 0; i < im->height; i++) { - for(int j = 0; j < im->width; j++) { + for(int i = 0; i < im->getHeight(); i++) { + for(int j = 0; j < im->getWidth(); j++) { im->r(i, j) = CLIP(im->r(i, j)); im->g(i, j) = CLIP(im->g(i, j)); im->b(i, j) = CLIP(im->b(i, j)); diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 2cc767b39..bf1e28aaa 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -69,6 +69,7 @@ protected: ColorTemp autoWB; double lastAwbEqual; + double lastAwbTempBias; ImProcFunctions ipf; @@ -156,6 +157,8 @@ protected: AutoExpListener* aeListener; AutoCamListener* acListener; AutoBWListener* abwListener; + AutoWBListener* awbListener; + AutoColorTonListener* actListener; AutoChromaListener* adnListener; WaveletListener* awavListener; @@ -256,7 +259,7 @@ public: DetailedCrop* createCrop (::EditDataProvider *editDataProvider, bool isDetailWindow); - bool getAutoWB (double& temp, double& green, double equal); + bool getAutoWB (double& temp, double& green, double equal, double tempBias); void getCamWB (double& temp, double& green); void getSpotWB (int x, int y, int rectSize, double& temp, double& green); void getAutoCrop (double ratio, int &x, int &y, int &w, int &h); @@ -311,6 +314,10 @@ public: { abwListener = abw; } + void setAutoWBListener (AutoWBListener* awb) + { + awbListener = awb; + } void setAutoColorTonListener (AutoColorTonListener* bwct) { actListener = bwct; diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 757b6e0b2..2d9deb10e 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -142,8 +142,8 @@ void ImProcFunctions::firstAnalysis (const Imagefloat* const original, const Pro lumimul[0] = wprof[1][0]; lumimul[1] = wprof[1][1]; lumimul[2] = wprof[1][2]; - int W = original->width; - int H = original->height; + int W = original->getWidth(); + int H = original->getHeight(); float lumimulf[3] = {static_cast(lumimul[0]), static_cast(lumimul[1]), static_cast(lumimul[2])}; @@ -2875,8 +2875,8 @@ void ImProcFunctions::moyeqt (Imagefloat* working, float &moyS, float &eqty) { BENCHFUN - int tHh = working->height; - int tWw = working->width; + int tHh = working->getHeight(); + int tWw = working->getWidth(); double moy = 0.0; double sqrs = 0.0; @@ -3271,11 +3271,11 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer bool hasgammabw = gammabwr != 1.f || gammabwg != 1.f || gammabwb != 1.f; if (hasColorToning || blackwhite || (params->dirpyrequalizer.cbdlMethod == "bef" && params->dirpyrequalizer.enabled)) { - tmpImage = new Imagefloat(working->width, working->height); + tmpImage = new Imagefloat(working->getWidth(), working->getHeight()); } - int W = working->width; - int H = working->height; + int W = working->getWidth(); + int H = working->getHeight(); // For tonecurve histogram int toneCurveHistSize = histToneCurve ? histToneCurve.getSize() : 0; @@ -3340,12 +3340,12 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer #pragma omp for schedule(dynamic) collapse(2) #endif - for(int ii = 0; ii < working->height; ii += TS) - for(int jj = 0; jj < working->width; jj += TS) { + for(int ii = 0; ii < working->getHeight(); ii += TS) + for(int jj = 0; jj < working->getWidth(); jj += TS) { istart = ii; jstart = jj; - tH = min(ii + TS, working->height); - tW = min(jj + TS, working->width); + tH = min(ii + TS, working->getHeight()); + tW = min(jj + TS, working->getWidth()); for (int i = istart, ti = 0; i < tH; i++, ti++) { @@ -4425,8 +4425,8 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer // starting a new tile processing with a 'reduction' clause for the auto mixer computing if (blackwhite) {//channel-mixer - int tW = working->width; - int tH = working->height; + int tW = working->getWidth(); + int tH = working->getHeight(); if (algm == 2) { //channel-mixer //end auto chmix @@ -6924,7 +6924,7 @@ double ImProcFunctions::getAutoDistor (const Glib::ustring &fname, int thumb_si return 0.0; } - Thumbnail* raw = rtengine::Thumbnail::loadFromRaw (fname, ri, w_raw, h_raw, 1, 1.0, FALSE); + Thumbnail* raw = rtengine::Thumbnail::loadFromRaw (fname, ri, w_raw, h_raw, 1, 1.0, FALSE, 0); if (!raw) { delete thumb; diff --git a/rtengine/ipresize.cc b/rtengine/ipresize.cc index 8bdc0a6cb..d3845ed8b 100644 --- a/rtengine/ipresize.cc +++ b/rtengine/ipresize.cc @@ -37,7 +37,7 @@ static inline float Lanc(float x, float a) } else if (x * x > a * a) { return 0.0f; } else { - x = static_cast(M_PI) * x; + x = static_cast(rtengine::RT_PI) * x; return a * xsinf(x) * xsinf(x / a) / (x * x); } } @@ -53,18 +53,18 @@ void ImProcFunctions::Lanczos(const Image16* src, Image16* dst, float scale) #pragma omp parallel { // storage for precomputed parameters for horisontal interpolation - float * wwh = new float[support * dst->width]; - int * jj0 = new int[dst->width]; - int * jj1 = new int[dst->width]; + float * wwh = new float[support * dst->getWidth()]; + int * jj0 = new int[dst->getWidth()]; + int * jj1 = new int[dst->getWidth()]; // temporal storage for vertically-interpolated row of pixels - float * lr = new float[src->width]; - float * lg = new float[src->width]; - float * lb = new float[src->width]; + float * lr = new float[src->getWidth()]; + float * lg = new float[src->getWidth()]; + float * lb = new float[src->getWidth()]; // Phase 1: precompute coefficients for horisontal interpolation - for (int j = 0; j < dst->width; j++) { + for (int j = 0; j < dst->getWidth(); j++) { // x coord of the center of pixel on src image float x0 = (static_cast(j) + 0.5f) * delta - 0.5f; @@ -76,7 +76,7 @@ void ImProcFunctions::Lanczos(const Image16* src, Image16* dst, float scale) float ws = 0.0f; jj0[j] = max(0, static_cast(floorf(x0 - a / sc)) + 1); - jj1[j] = min(src->width, static_cast(floorf(x0 + a / sc)) + 1); + jj1[j] = min(src->getWidth(), static_cast(floorf(x0 + a / sc)) + 1); // calculate weights for (int jj = jj0[j]; jj < jj1[j]; jj++) { @@ -95,7 +95,7 @@ void ImProcFunctions::Lanczos(const Image16* src, Image16* dst, float scale) // Phase 2: do actual interpolation #pragma omp for - for (int i = 0; i < dst->height; i++) { + for (int i = 0; i < dst->getHeight(); i++) { // y coord of the center of pixel on src image float y0 = (static_cast(i) + 0.5f) * delta - 0.5f; @@ -107,7 +107,7 @@ void ImProcFunctions::Lanczos(const Image16* src, Image16* dst, float scale) float ws = 0.0f; int ii0 = max(0, static_cast(floorf(y0 - a / sc)) + 1); - int ii1 = min(src->height, static_cast(floorf(y0 + a / sc)) + 1); + int ii1 = min(src->getHeight(), static_cast(floorf(y0 + a / sc)) + 1); // calculate weights for vertical interpolation for (int ii = ii0; ii < ii1; ii++) { @@ -123,7 +123,7 @@ void ImProcFunctions::Lanczos(const Image16* src, Image16* dst, float scale) } // Do vertical interpolation. Store results. - for (int j = 0; j < src->width; j++) { + for (int j = 0; j < src->getWidth(); j++) { float r = 0.0f, g = 0.0f, b = 0.0f; @@ -141,7 +141,7 @@ void ImProcFunctions::Lanczos(const Image16* src, Image16* dst, float scale) } // Do horizontal interpolation - for(int j = 0; j < dst->width; j++) { + for(int j = 0; j < dst->getWidth(); j++) { float * wh = wwh + support * j; @@ -407,13 +407,13 @@ void ImProcFunctions::resize (Image16* src, Image16* dst, float dScale) #pragma omp parallel for if (multiThread) #endif - for (int i = 0; i < dst->height; i++) { + for (int i = 0; i < dst->getHeight(); i++) { int sy = i / dScale; - sy = LIM(sy, 0, src->height - 1); + sy = LIM(sy, 0, src->getHeight() - 1); - for (int j = 0; j < dst->width; j++) { + for (int j = 0; j < dst->getWidth(); j++) { int sx = j / dScale; - sx = LIM(sx, 0, src->width - 1); + sx = LIM(sx, 0, src->getWidth() - 1); dst->r(i, j) = src->r(sy, sx); dst->g(i, j) = src->g(sy, sx); dst->b(i, j) = src->b(sy, sx); diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 1c0a09929..34aab1c7b 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -90,7 +90,6 @@ namespace rtengine #undef CLIPTOC #define CLIPTOC(a,b,c,d) ((a)>=(b)?((a)<=(c)?(a):(d=true,(c))):(d=true,(b))) -#define RT_PI 3.141592653589 bool ImProcFunctions::transCoord (int W, int H, const std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef, const LCPMapper *pLCPMap) @@ -122,19 +121,19 @@ bool ImProcFunctions::transCoord (int W, int H, const std::vector &src, double distAmount = params->distortion.amount; // auxiliary variables for rotation - double cost = cos(params->rotate.degree * RT_PI / 180.0); - double sint = sin(params->rotate.degree * RT_PI / 180.0); + double cost = cos(params->rotate.degree * rtengine::RT_PI / 180.0); + double sint = sin(params->rotate.degree * rtengine::RT_PI / 180.0); // auxiliary variables for vertical perspective correction double vpdeg = params->perspective.vertical / 100.0 * 45.0; - double vpalpha = (90.0 - vpdeg) / 180.0 * RT_PI; - double vpteta = fabs(vpalpha - RT_PI / 2) < 3e-4 ? 0.0 : acos ((vpdeg > 0 ? 1.0 : -1.0) * sqrt((-oW * oW * tan(vpalpha) * tan(vpalpha) + (vpdeg > 0 ? 1.0 : -1.0) * oW * tan(vpalpha) * sqrt(16 * maxRadius * maxRadius + oW * oW * tan(vpalpha) * tan(vpalpha))) / (maxRadius * maxRadius * 8))); + double vpalpha = (90.0 - vpdeg) / 180.0 * rtengine::RT_PI; + double vpteta = fabs(vpalpha - rtengine::RT_PI / 2) < 3e-4 ? 0.0 : acos ((vpdeg > 0 ? 1.0 : -1.0) * sqrt((-oW * oW * tan(vpalpha) * tan(vpalpha) + (vpdeg > 0 ? 1.0 : -1.0) * oW * tan(vpalpha) * sqrt(16 * maxRadius * maxRadius + oW * oW * tan(vpalpha) * tan(vpalpha))) / (maxRadius * maxRadius * 8))); double vpcospt = (vpdeg >= 0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); // auxiliary variables for horizontal perspective correction double hpdeg = params->perspective.horizontal / 100.0 * 45.0; - double hpalpha = (90.0 - hpdeg) / 180.0 * RT_PI; - double hpteta = fabs(hpalpha - RT_PI / 2) < 3e-4 ? 0.0 : acos ((hpdeg > 0 ? 1.0 : -1.0) * sqrt((-oH * oH * tan(hpalpha) * tan(hpalpha) + (hpdeg > 0 ? 1.0 : -1.0) * oH * tan(hpalpha) * sqrt(16 * maxRadius * maxRadius + oH * oH * tan(hpalpha) * tan(hpalpha))) / (maxRadius * maxRadius * 8))); + double hpalpha = (90.0 - hpdeg) / 180.0 * rtengine::RT_PI; + double hpteta = fabs(hpalpha - rtengine::RT_PI / 2) < 3e-4 ? 0.0 : acos ((hpdeg > 0 ? 1.0 : -1.0) * sqrt((-oH * oH * tan(hpalpha) * tan(hpalpha) + (hpdeg > 0 ? 1.0 : -1.0) * oH * tan(hpalpha) * sqrt(16 * maxRadius * maxRadius + oH * oH * tan(hpalpha) * tan(hpalpha))) / (maxRadius * maxRadius * 8))); double hpcospt = (hpdeg >= 0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); double ascale = ascaleDef > 0 ? ascaleDef : (params->commonTrans.autofill ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0); @@ -299,7 +298,7 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, LCPProfile *pLCPProf = lcpStore->getProfile(params->lensProf.lcpFile); if (pLCPProf) pLCPMap = new LCPMapper(pLCPProf, focalLen, focalLen35mm, focusDist, 0, false, params->lensProf.useDist, - original->width, original->height, params->coarse, rawRotationDeg); + original->getWidth(), original->getHeight(), params->coarse, rawRotationDeg); } if (!(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP()) && (needsVignetting() || needsPCVignetting() || needsGradient())) { @@ -351,14 +350,14 @@ static void calcGradientParams(int oW, int oH, const GradientParams& gradient, s double gradient_span = gradient.feather / 100.0; double gradient_center_x = gradient.centerX / 200.0 + 0.5; double gradient_center_y = gradient.centerY / 200.0 + 0.5; - double gradient_angle = gradient.degree / 180.0 * M_PI; + double gradient_angle = gradient.degree / 180.0 * rtengine::RT_PI; //fprintf(stderr, "%f %f %f %f %f %d %d\n", gradient_stops, gradient_span, gradient_center_x, gradient_center_y, gradient_angle, w, h); - // make 0.0 <= gradient_angle < 2 * M_PI - gradient_angle = fmod(gradient_angle, 2 * M_PI); + // make 0.0 <= gradient_angle < 2 * rtengine::RT_PI + gradient_angle = fmod(gradient_angle, 2 * rtengine::RT_PI); if (gradient_angle < 0.0) { - gradient_angle += 2.0 * M_PI; + gradient_angle += 2.0 * rtengine::RT_PI; } gp.bright_top = false; @@ -372,24 +371,24 @@ static void calcGradientParams(int oW, int oH, const GradientParams& gradient, s // (actually we could transpose only for 90 degrees, but this way we avoid // division with extremely small numbers gp.transpose = true; - gradient_angle += 0.5 * M_PI; + gradient_angle += 0.5 * rtengine::RT_PI; cosgrad = cos(gradient_angle); double gxc = gradient_center_x; gradient_center_x = 1.0 - gradient_center_y; gradient_center_y = gxc; } - gradient_angle = fmod(gradient_angle, 2 * M_PI); + gradient_angle = fmod(gradient_angle, 2 * rtengine::RT_PI); - if (gradient_angle > 0.5 * M_PI && gradient_angle < M_PI) { - gradient_angle += M_PI; + if (gradient_angle > 0.5 * rtengine::RT_PI && gradient_angle < rtengine::RT_PI) { + gradient_angle += rtengine::RT_PI; gp.bright_top = true; - } else if (gradient_angle >= M_PI && gradient_angle < 1.5 * M_PI) { - gradient_angle -= M_PI; + } else if (gradient_angle >= rtengine::RT_PI && gradient_angle < 1.5 * rtengine::RT_PI) { + gradient_angle -= rtengine::RT_PI; gp.bright_top = true; } - if (fabs(gradient_angle) < 0.001 || fabs(gradient_angle - 2 * M_PI) < 0.001) { + if (fabs(gradient_angle) < 0.001 || fabs(gradient_angle - 2 * rtengine::RT_PI) < 0.001) { gradient_angle = 0; gp.angle_is_zero = true; } @@ -444,7 +443,7 @@ static float calcGradientFactor(const struct grad_params& gp, int x, int y) val = 1.f - val; } - val *= M_PIf_2; + val *= rtengine::RT_PI_F_2; if (gp.scale < 1.f) { val = pow3(xsinf(val)); @@ -468,7 +467,7 @@ static float calcGradientFactor(const struct grad_params& gp, int x, int y) val = gp.bright_top ? 1.f - val : val; - val *= M_PIf_2; + val *= rtengine::RT_PI_F_2; if (gp.scale < 1.f) { val = pow3(xsinf(val)); @@ -623,7 +622,7 @@ static float calcPCVignetteFactor(const struct pcv_params& pcv, int x, int y) if (dist >= dist_oe) { val = pcv.scale; } else { - val = M_PIf_2 * (dist - dist_ie) / (dist_oe - dist_ie); + val = rtengine::RT_PI_F_2 * (dist - dist_ie) / (dist_oe - dist_ie); if (pcv.scale < 1.f) { val = pow4(xcosf(val)); @@ -663,17 +662,17 @@ void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat* struct pcv_params pcv; if (applyPCVignetting) { - //fprintf(stderr, "%d %d | %d %d | %d %d | %d %d [%d %d]\n", fW, fH, oW, oH, transformed->width, transformed->height, cx, cy, params->crop.w, params->crop.h); + //fprintf(stderr, "%d %d | %d %d | %d %d | %d %d [%d %d]\n", fW, fH, oW, oH, transformed->getWidth(), transformed->getHeight(), cx, cy, params->crop.w, params->crop.h); calcPCVignetteParams(fW, fH, oW, oH, params->pcvignette, params->crop, pcv); } bool darkening = (params->vignetting.amount <= 0.0); #pragma omp parallel for schedule(dynamic,16) if (multiThread) - for (int y = 0; y < transformed->height; y++) { + for (int y = 0; y < transformed->getHeight(); y++) { double vig_y_d = (double) (y + cy) - vig_h2 ; - for (int x = 0; x < transformed->width; x++) { + for (int x = 0; x < transformed->getWidth(); x++) { double factor = 1.0; if (applyVignetting) { @@ -746,20 +745,20 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr double distAmount = params->distortion.amount; // auxiliary variables for rotation - double cost = cos(params->rotate.degree * RT_PI / 180.0); - double sint = sin(params->rotate.degree * RT_PI / 180.0); + double cost = cos(params->rotate.degree * rtengine::RT_PI / 180.0); + double sint = sin(params->rotate.degree * rtengine::RT_PI / 180.0); // auxiliary variables for vertical perspective correction double vpdeg = params->perspective.vertical / 100.0 * 45.0; - double vpalpha = (90.0 - vpdeg) / 180.0 * RT_PI; - double vpteta = fabs(vpalpha - RT_PI / 2) < 3e-4 ? 0.0 : acos ((vpdeg > 0 ? 1.0 : -1.0) * sqrt((-SQR(oW * tan(vpalpha)) + (vpdeg > 0 ? 1.0 : -1.0) * + double vpalpha = (90.0 - vpdeg) / 180.0 * rtengine::RT_PI; + double vpteta = fabs(vpalpha - rtengine::RT_PI / 2) < 3e-4 ? 0.0 : acos ((vpdeg > 0 ? 1.0 : -1.0) * sqrt((-SQR(oW * tan(vpalpha)) + (vpdeg > 0 ? 1.0 : -1.0) * oW * tan(vpalpha) * sqrt(SQR(4 * maxRadius) + SQR(oW * tan(vpalpha)))) / (SQR(maxRadius) * 8))); double vpcospt = (vpdeg >= 0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); // auxiliary variables for horizontal perspective correction double hpdeg = params->perspective.horizontal / 100.0 * 45.0; - double hpalpha = (90.0 - hpdeg) / 180.0 * RT_PI; - double hpteta = fabs(hpalpha - RT_PI / 2) < 3e-4 ? 0.0 : acos ((hpdeg > 0 ? 1.0 : -1.0) * sqrt((-SQR(oH * tan(hpalpha)) + (hpdeg > 0 ? 1.0 : -1.0) * + double hpalpha = (90.0 - hpdeg) / 180.0 * rtengine::RT_PI; + double hpteta = fabs(hpalpha - rtengine::RT_PI / 2) < 3e-4 ? 0.0 : acos ((hpdeg > 0 ? 1.0 : -1.0) * sqrt((-SQR(oH * tan(hpalpha)) + (hpdeg > 0 ? 1.0 : -1.0) * oH * tan(hpalpha) * sqrt(SQR(4 * maxRadius) + SQR(oH * tan(hpalpha)))) / (SQR(maxRadius) * 8))); double hpcospt = (hpdeg >= 0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); @@ -779,8 +778,8 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr bool darkening = (params->vignetting.amount <= 0.0); #pragma omp parallel for if (multiThread) - for (int y = 0; y < transformed->height; y++) { - for (int x = 0; x < transformed->width; x++) { + for (int y = 0; y < transformed->getHeight(); y++) { + for (int x = 0; x < transformed->getWidth(); x++) { double x_d = x, y_d = y; if (enableLCPDist) { @@ -849,7 +848,7 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr yc -= sy; // Convert only valid pixels - if (yc >= 0 && yc < original->height && xc >= 0 && xc < original->width) { + if (yc >= 0 && yc < original->getHeight() && xc >= 0 && xc < original->getWidth()) { // multiplier for vignetting correction double vignmul = 1.0; @@ -870,7 +869,7 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr vignmul *= calcPCVignetteFactor(pcv, cx + x, cy + y); } - if (yc > 0 && yc < original->height - 2 && xc > 0 && xc < original->width - 2) { + if (yc > 0 && yc < original->getHeight() - 2 && xc > 0 && xc < original->getWidth() - 2) { // all interpolation pixels inside image if (enableCA) { interpolateTransformChannelsCubic (chOrig[c], xc - 1, yc - 1, Dx, Dy, &(chTrans[c][y][x]), vignmul); @@ -879,10 +878,10 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr } } else { // edge pixels - int y1 = LIM(yc, 0, original->height - 1); - int y2 = LIM(yc + 1, 0, original->height - 1); - int x1 = LIM(xc, 0, original->width - 1); - int x2 = LIM(xc + 1, 0, original->width - 1); + int y1 = LIM(yc, 0, original->getHeight() - 1); + int y2 = LIM(yc + 1, 0, original->getHeight() - 1); + int x1 = LIM(xc, 0, original->getWidth() - 1); + int x2 = LIM(xc + 1, 0, original->getWidth() - 1); if (enableCA) { chTrans[c][y][x] = vignmul * (chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); @@ -934,19 +933,19 @@ void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transf double distAmount = params->distortion.amount; // auxiliary variables for rotation - double cost = cos(params->rotate.degree * RT_PI / 180.0); - double sint = sin(params->rotate.degree * RT_PI / 180.0); + double cost = cos(params->rotate.degree * rtengine::RT_PI / 180.0); + double sint = sin(params->rotate.degree * rtengine::RT_PI / 180.0); // auxiliary variables for vertical perspective correction double vpdeg = params->perspective.vertical / 100.0 * 45.0; - double vpalpha = (90 - vpdeg) / 180.0 * RT_PI; - double vpteta = fabs(vpalpha - RT_PI / 2) < 3e-4 ? 0.0 : acos ((vpdeg > 0 ? 1.0 : -1.0) * sqrt((-oW * oW * tan(vpalpha) * tan(vpalpha) + (vpdeg > 0 ? 1.0 : -1.0) * oW * tan(vpalpha) * sqrt(16 * maxRadius * maxRadius + oW * oW * tan(vpalpha) * tan(vpalpha))) / (maxRadius * maxRadius * 8))); + double vpalpha = (90 - vpdeg) / 180.0 * rtengine::RT_PI; + double vpteta = fabs(vpalpha - rtengine::RT_PI / 2) < 3e-4 ? 0.0 : acos ((vpdeg > 0 ? 1.0 : -1.0) * sqrt((-oW * oW * tan(vpalpha) * tan(vpalpha) + (vpdeg > 0 ? 1.0 : -1.0) * oW * tan(vpalpha) * sqrt(16 * maxRadius * maxRadius + oW * oW * tan(vpalpha) * tan(vpalpha))) / (maxRadius * maxRadius * 8))); double vpcospt = (vpdeg >= 0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); // auxiliary variables for horizontal perspective correction double hpdeg = params->perspective.horizontal / 100.0 * 45.0; - double hpalpha = (90 - hpdeg) / 180.0 * RT_PI; - double hpteta = fabs(hpalpha - RT_PI / 2) < 3e-4 ? 0.0 : acos ((hpdeg > 0 ? 1.0 : -1.0) * sqrt((-oH * oH * tan(hpalpha) * tan(hpalpha) + (hpdeg > 0 ? 1.0 : -1.0) * oH * tan(hpalpha) * sqrt(16 * maxRadius * maxRadius + oH * oH * tan(hpalpha) * tan(hpalpha))) / (maxRadius * maxRadius * 8))); + double hpalpha = (90 - hpdeg) / 180.0 * rtengine::RT_PI; + double hpteta = fabs(hpalpha - rtengine::RT_PI / 2) < 3e-4 ? 0.0 : acos ((hpdeg > 0 ? 1.0 : -1.0) * sqrt((-oH * oH * tan(hpalpha) * tan(hpalpha) + (hpdeg > 0 ? 1.0 : -1.0) * oH * tan(hpalpha) * sqrt(16 * maxRadius * maxRadius + oH * oH * tan(hpalpha) * tan(hpalpha))) / (maxRadius * maxRadius * 8))); double hpcospt = (hpdeg >= 0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0; @@ -956,8 +955,8 @@ void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transf // main cycle #pragma omp parallel for if (multiThread) - for (int y = 0; y < transformed->height; y++) { - for (int x = 0; x < transformed->width; x++) { + for (int y = 0; y < transformed->getHeight(); y++) { + for (int x = 0; x < transformed->getWidth(); x++) { double x_d = x, y_d = y; if (pLCPMap && params->lensProf.useDist) { @@ -1019,7 +1018,7 @@ void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transf yc -= sy; // Convert only valid pixels - if (yc >= 0 && yc < original->height && xc >= 0 && xc < original->width) { + if (yc >= 0 && yc < original->getHeight() && xc >= 0 && xc < original->getWidth()) { // multiplier for vignetting correction double vignmul = 1.0; @@ -1040,17 +1039,17 @@ void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transf vignmul *= calcPCVignetteFactor(pcv, cx + x, cy + y); } - if (yc < original->height - 1 && xc < original->width - 1) { + if (yc < original->getHeight() - 1 && xc < original->getWidth() - 1) { // all interpolation pixels inside image transformed->r(y, x) = vignmul * (original->r(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->r(yc, xc + 1) * Dx * (1.0 - Dy) + original->r(yc + 1, xc) * (1.0 - Dx) * Dy + original->r(yc + 1, xc + 1) * Dx * Dy); transformed->g(y, x) = vignmul * (original->g(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g(yc, xc + 1) * Dx * (1.0 - Dy) + original->g(yc + 1, xc) * (1.0 - Dx) * Dy + original->g(yc + 1, xc + 1) * Dx * Dy); transformed->b(y, x) = vignmul * (original->b(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b(yc, xc + 1) * Dx * (1.0 - Dy) + original->b(yc + 1, xc) * (1.0 - Dx) * Dy + original->b(yc + 1, xc + 1) * Dx * Dy); } else { // edge pixels - int y1 = LIM(yc, 0, original->height - 1); - int y2 = LIM(yc + 1, 0, original->height - 1); - int x1 = LIM(xc, 0, original->width - 1); - int x2 = LIM(xc + 1, 0, original->width - 1); + int y1 = LIM(yc, 0, original->getHeight() - 1); + int y2 = LIM(yc + 1, 0, original->getHeight() - 1); + int x1 = LIM(xc, 0, original->getWidth() - 1); + int x2 = LIM(xc + 1, 0, original->getWidth() - 1); transformed->r(y, x) = vignmul * (original->r(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->r(y1, x2) * Dx * (1.0 - Dy) + original->r(y2, x1) * (1.0 - Dx) * Dy + original->r(y2, x2) * Dx * Dy); transformed->g(y, x) = vignmul * (original->g(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->g(y1, x2) * Dx * (1.0 - Dy) + original->g(y2, x1) * (1.0 - Dx) * Dy + original->g(y2, x2) * Dx * Dy); transformed->b(y, x) = vignmul * (original->b(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->b(y1, x2) * Dx * (1.0 - Dy) + original->b(y2, x1) * (1.0 - Dx) * Dy + original->b(y2, x2) * Dx * Dy); diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index 67402cac4..882dd8cdc 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -1058,7 +1058,7 @@ SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int } for (int i = 0; i < overlap; i++) { - float mask = SQR(sin((M_PI * i) / (2 * overlap))); + float mask = SQR(sin((rtengine::RT_PI * i) / (2 * overlap))); if (tiletop > 0) { Vmask[i] = mask; diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index ce1a6c67e..310361a72 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -16,103 +16,107 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ + +#include #include #include "lcp.h" -#include "iccmatrices.h" -#include "iccstore.h" -#include "rawimagesource.h" -#include "improcfun.h" -#include "rt_math.h" +#include #ifdef WIN32 #include -// for GCC32 -#ifndef _WIN32_IE -#define _WIN32_IE 0x0600 -#endif #include #endif using namespace std; using namespace rtengine; -using namespace rtexif; -LCPModelCommon::LCPModelCommon() +LCPModelCommon::LCPModelCommon() : + foc_len_x(-1.0f), + foc_len_y(-1.0f), + img_center_x(0.5f), + img_center_y(0.5f), + param{{}}, + scale_factor(1.0f), + mean_error(0.0), + bad_error(false), + x0(0.0f), + y0(0.0f), + fx(0.0f), + fy(0.0f), + rfx(0.0f), + rfy(0.0f), + vign_param{{}} { - focLenX = focLenY = -1; - imgXCenter = imgYCenter = 0.5; - x0 = y0 = fx = fy = meanErr = 0; - badErr = false; - - for (int i = 0; i < 5; i++) { - param[i] = 0; - } - - scaleFac = 1; } bool LCPModelCommon::empty() const { - return param[0] == 0 && param[1] == 0 && param[2] == 0; + return param[0] == 0.0f && param[1] == 0.0f && param[2] == 0.0f; } void LCPModelCommon::print() const { - printf("focLen %g/%g; imgCenter %g/%g; scale %g; err %g\n", focLenX, focLenY, imgXCenter, imgYCenter, scaleFac, meanErr); + printf("focLen %g/%g; imgCenter %g/%g; scale %g; err %g\n", foc_len_x, foc_len_y, img_center_x, img_center_y, scale_factor, mean_error); printf("xy0 %g/%g fxy %g/%g\n", x0, y0, fx, fy); printf("param: %g/%g/%g/%g/%g\n", param[0], param[1], param[2], param[3], param[4]); } -// weightened merge two parameters +// weighted merge two parameters void LCPModelCommon::merge(const LCPModelCommon& a, const LCPModelCommon& b, float facA) { - float facB = 1 - facA; + const float facB = 1.0f - facA; - focLenX = facA * a.focLenX + facB * b.focLenX; - focLenY = facA * a.focLenY + facB * b.focLenY; - imgXCenter = facA * a.imgXCenter + facB * b.imgXCenter; - imgYCenter = facA * a.imgYCenter + facB * b.imgYCenter; - scaleFac = facA * a.scaleFac + facB * b.scaleFac; - meanErr = facA * a.meanErr + facB * b.meanErr; + foc_len_x = facA * a.foc_len_x + facB * b.foc_len_x; + foc_len_y = facA * a.foc_len_y + facB * b.foc_len_y; + img_center_x = facA * a.img_center_x + facB * b.img_center_x; + img_center_y = facA * a.img_center_y + facB * b.img_center_y; + scale_factor = facA * a.scale_factor + facB * b.scale_factor; + mean_error = facA * a.mean_error + facB * b.mean_error; for (int i = 0; i < 5; i++) { param[i] = facA * a.param[i] + facB * b.param[i]; } + + const float param0Sqr = param[0] * param[0]; + + vign_param[0] = -param[0]; + vign_param[1] = param0Sqr - param[1]; + vign_param[2] = param0Sqr * param[0] - 2.0f * param[0] * param[1] + param[2]; + vign_param[3] = param0Sqr * param0Sqr + param[1] * param[1] + 2.0f * param[0] * param[2] - 3.0f * param0Sqr * param[1]; + } void LCPModelCommon::prepareParams(int fullWidth, int fullHeight, float focalLength, float focalLength35mm, float sensorFormatFactor, bool swapXY, bool mirrorX, bool mirrorY) { // Mention that the Adobe technical paper has a bug here, the DMAX is handled differently for focLen and imgCenter - int Dmax = fullWidth; - - if (fullHeight > fullWidth) { - Dmax = fullHeight; - } + const int Dmax = std::max(fullWidth, fullHeight); // correct focLens - if (focLenX < 0) { // they may not be given + if (foc_len_x < 0.0f) { // they may not be given // and 35mm may not be given either - if (focalLength35mm < 1) { + if (focalLength35mm < 1.0f) { focalLength35mm = focalLength * sensorFormatFactor; } - focLenX = focLenY = focalLength / ( 35 * focalLength / focalLength35mm); // focLen must be calculated in pixels + foc_len_x = foc_len_y = focalLength / (35.0f * focalLength / focalLength35mm); // focLen must be calculated in pixels } if (swapXY) { - x0 = (mirrorX ? 1. - imgYCenter : imgYCenter) * fullWidth; - y0 = (mirrorY ? 1. - imgXCenter : imgXCenter) * fullHeight; - fx = focLenY * Dmax; - fy = focLenX * Dmax; + x0 = (mirrorX ? 1.0f - img_center_y : img_center_y) * fullWidth; + y0 = (mirrorY ? 1.0f - img_center_x : img_center_x) * fullHeight; + fx = foc_len_y * Dmax; + fy = foc_len_x * Dmax; } else { - x0 = (mirrorX ? 1. - imgXCenter : imgXCenter) * fullWidth; - y0 = (mirrorY ? 1. - imgYCenter : imgYCenter) * fullHeight; - fx = focLenX * Dmax; - fy = focLenY * Dmax; + x0 = (mirrorX ? 1.0f - img_center_x : img_center_x) * fullWidth; + y0 = (mirrorY ? 1.0f - img_center_y : img_center_y) * fullHeight; + fx = foc_len_x * Dmax; + fy = foc_len_y * Dmax; } + rfx = 1.0f / fx; + rfy = 1.0f / fy; //printf("FW %i /X0 %g FH %i /Y0 %g %g\n",fullWidth,x0,fullHeight,y0, imgYCenter); } @@ -125,9 +129,9 @@ LCPPersModel::LCPPersModel() // mode: 0=distortion, 1=vignette, 2=CA bool LCPPersModel::hasModeData(int mode) const { - return (mode == 0 && !vignette.empty() && !vignette.badErr) || (mode == 1 && !base.empty() && !base.badErr) + return (mode == 0 && !vignette.empty() && !vignette.bad_error) || (mode == 1 && !base.empty() && !base.bad_error) || (mode == 2 && !chromRG.empty() && !chromG.empty() && !chromBG.empty() && - !chromRG.badErr && !chromG.badErr && !chromBG.badErr); + !chromRG.bad_error && !chromG.bad_error && !chromBG.bad_error); } void LCPPersModel::print() const @@ -200,7 +204,7 @@ void LCPMapper::correctDistortion(double& x, double& y) const { double xd = (x - mc.x0) / mc.fx, yd = (y - mc.y0) / mc.fy; - const float* aDist = mc.param; + const LCPModelCommon::Param aDist = mc.param; double rsqr = xd * xd + yd * yd; double xfac = aDist[swapXY ? 3 : 4], yfac = aDist[swapXY ? 4 : 3]; @@ -228,7 +232,7 @@ void LCPMapper::correctCA(double& x, double& y, int channel) const // Green contains main distortion, just like base if (useCADist) { - const float* aDist = chrom[1].param; + const LCPModelCommon::Param aDist = chrom[1].param; double rsqr = xd * xd + yd * yd; double xfac = aDist[swapXY ? 3 : 4], yfac = aDist[swapXY ? 4 : 3]; @@ -252,30 +256,72 @@ void LCPMapper::correctCA(double& x, double& y, int channel) const yd = ygreen; rsqr = xd * xd + yd * yd; - const float* aCA = chrom[channel].param; + const LCPModelCommon::Param aCA = chrom[channel].param; double xfac = aCA[swapXY ? 3 : 4], yfac = aCA[swapXY ? 4 : 3]; double commonSum = 1. + rsqr * (aCA[0] + rsqr * (aCA[1] + aCA[2] * rsqr)) + 2. * (yfac * yd + xfac * xd); - x = (chrom[channel].scaleFac * ( xd * commonSum + xfac * rsqr )) * chrom[channel].fx + chrom[channel].x0; - y = (chrom[channel].scaleFac * ( yd * commonSum + yfac * rsqr )) * chrom[channel].fy + chrom[channel].y0; + x = (chrom[channel].scale_factor * ( xd * commonSum + xfac * rsqr )) * chrom[channel].fx + chrom[channel].x0; + y = (chrom[channel].scale_factor * ( yd * commonSum + yfac * rsqr )) * chrom[channel].fy + chrom[channel].y0; } } -float LCPMapper::calcVignetteFac(int x, int y) const +SSEFUNCTION void LCPMapper::processVignetteLine(int width, int y, float *line) const { // No need for swapXY, since vignette is in RAW and always before rotation - double xd = ((double)x - mc.x0) / mc.fx, yd = ((double)y - mc.y0) / mc.fy; + float yd = ((float)y - mc.y0) * mc.rfy; + yd *= yd; + int x = 0; +#ifdef __SSE2__ + const vfloat fourv = F2V(4.f); + const vfloat zerov = F2V(0.f); + const vfloat ydv = F2V(yd); + const vfloat p0 = F2V(mc.vign_param[0]); + const vfloat p1 = F2V(mc.vign_param[1]); + const vfloat p2 = F2V(mc.vign_param[2]); + const vfloat p3 = F2V(mc.vign_param[3]); + const vfloat x0v = F2V(mc.x0); + const vfloat rfxv = F2V(mc.rfx); - const float* aVig = mc.param; - double rsqr = xd * xd + yd * yd; - double param0Sqr = aVig[0] * aVig[0]; - - return 1. + rsqr * (-aVig[0] + rsqr * ((param0Sqr - aVig[1]) - - (param0Sqr * aVig[0] - 2.*aVig[0] * aVig[1] + aVig[2]) * rsqr - + (param0Sqr * param0Sqr + aVig[1] * aVig[1] - + 2.*aVig[0] * aVig[2] - 3.*param0Sqr * aVig[1]) * rsqr * rsqr)); + vfloat xv = _mm_setr_ps(0.f, 1.f, 2.f, 3.f); + for (; x < width-3; x+=4) { + vfloat xdv = (xv - x0v) * rfxv; + vfloat rsqr = xdv * xdv + ydv; + vfloat vignFactorv = rsqr * (p0 + rsqr * (p1 - p2 * rsqr + p3 * rsqr * rsqr)); + vfloat valv = LVFU(line[x]); + valv += valv * vselfzero(vmaskf_gt(valv, zerov), vignFactorv); + STVFU(line[x], valv); + xv += fourv; + } +#endif // __SSE2__ + for (; x < width; x++) { + if (line[x] > 0) { + float xd = ((float)x - mc.x0) * mc.rfx; + const LCPModelCommon::VignParam vignParam = mc.vign_param; + float rsqr = xd * xd + yd; + line[x] += line[x] * rsqr * (vignParam[0] + rsqr * ((vignParam[1]) - (vignParam[2]) * rsqr + (vignParam[3]) * rsqr * rsqr)); + } + } } +SSEFUNCTION void LCPMapper::processVignetteLine3Channels(int width, int y, float *line) const +{ + // No need for swapXY, since vignette is in RAW and always before rotation + float yd = ((float)y - mc.y0) * mc.rfy; + yd *= yd; + const LCPModelCommon::VignParam vignParam = mc.vign_param; + for (int x = 0; x < width; x++) { + float xd = ((float)x - mc.x0) * mc.rfx; + float rsqr = xd * xd + yd; + float vignetteFactor = rsqr * (vignParam[0] + rsqr * ((vignParam[1]) - (vignParam[2]) * rsqr + (vignParam[3]) * rsqr * rsqr)); + for(int c = 0;c < 3; ++c) { + if (line[3*x+c] > 0) { + line[3*x+c] += line[3*x+c] * vignetteFactor; + } + } + } +} + + LCPProfile::LCPProfile(const Glib::ustring &fname) { const int BufferSize = 8192; @@ -336,17 +382,17 @@ int LCPProfile::filterBadFrames(double maxAvgDevFac, int minFramesLeft) for (int pm = 0; pm < MaxPersModelCount && aPersModel[pm]; pm++) { if (aPersModel[pm]->hasModeData(0)) { - errVignette += aPersModel[pm]->vignette.meanErr; + errVignette += aPersModel[pm]->vignette.mean_error; vignetteCount++; } if (aPersModel[pm]->hasModeData(1)) { - errBase += aPersModel[pm]->base.meanErr; + errBase += aPersModel[pm]->base.mean_error; baseCount++; } if (aPersModel[pm]->hasModeData(2)) { - errChrom += std::max(std::max(aPersModel[pm]->chromRG.meanErr, aPersModel[pm]->chromG.meanErr), aPersModel[pm]->chromBG.meanErr); + errChrom += std::max(std::max(aPersModel[pm]->chromRG.mean_error, aPersModel[pm]->chromG.mean_error), aPersModel[pm]->chromBG.mean_error); chromCount++; } } @@ -369,20 +415,20 @@ int LCPProfile::filterBadFrames(double maxAvgDevFac, int minFramesLeft) // Now mark all the bad ones as bad, and hasModeData will return false; for (int pm = 0; pm < MaxPersModelCount && aPersModel[pm]; pm++) { - if (aPersModel[pm]->hasModeData(0) && aPersModel[pm]->vignette.meanErr > maxAvgDevFac * errVignette) { - aPersModel[pm]->vignette.badErr = true; + if (aPersModel[pm]->hasModeData(0) && aPersModel[pm]->vignette.mean_error > maxAvgDevFac * errVignette) { + aPersModel[pm]->vignette.bad_error = true; filtered++; } - if (aPersModel[pm]->hasModeData(1) && aPersModel[pm]->base.meanErr > maxAvgDevFac * errBase) { - aPersModel[pm]->base.badErr = true; + if (aPersModel[pm]->hasModeData(1) && aPersModel[pm]->base.mean_error > maxAvgDevFac * errBase) { + aPersModel[pm]->base.bad_error = true; filtered++; } if (aPersModel[pm]->hasModeData(2) && - (aPersModel[pm]->chromRG.meanErr > maxAvgDevFac * errChrom || aPersModel[pm]->chromG.meanErr > maxAvgDevFac * errChrom - || aPersModel[pm]->chromBG.meanErr > maxAvgDevFac * errChrom)) { - aPersModel[pm]->chromRG.badErr = aPersModel[pm]->chromG.badErr = aPersModel[pm]->chromBG.badErr = true; + (aPersModel[pm]->chromRG.mean_error > maxAvgDevFac * errChrom || aPersModel[pm]->chromG.mean_error > maxAvgDevFac * errChrom + || aPersModel[pm]->chromBG.mean_error > maxAvgDevFac * errChrom)) { + aPersModel[pm]->chromRG.bad_error = aPersModel[pm]->chromG.bad_error = aPersModel[pm]->chromBG.bad_error = true; filtered++; } } @@ -438,48 +484,48 @@ void LCPProfile::calcParams(int mode, float focalLength, float focusDist, float if (aPersModel[pm]->hasModeData(mode)) { if (mode == 0) { - meanErr = aPersModel[pm]->vignette.meanErr; + meanErr = aPersModel[pm]->vignette.mean_error; // by aperture (vignette), and max out focus distance // tests showed doing this by log(aperture) is not as advisable if (aPersModel[pm]->focLen == bestFocLenLow && ( - (aper == aperture && pLow->vignette.meanErr > meanErr) + (aper == aperture && pLow->vignette.mean_error > meanErr) || (aper >= aperture && aper < pLow->aperture && pLow->aperture > aperture) || (aper <= aperture && (pLow->aperture > aperture || fabs(aperture - aper) < fabs(aperture - pLow->aperture))))) { pLow = aPersModel[pm]; } if (aPersModel[pm]->focLen == bestFocLenHigh && ( - (aper == aperture && pHigh->vignette.meanErr > meanErr) + (aper == aperture && pHigh->vignette.mean_error > meanErr) || (aper <= aperture && aper > pHigh->aperture && pHigh->aperture < aperture) || (aper >= aperture && (pHigh->aperture < aperture || fabs(aperture - aper) < fabs(aperture - pHigh->aperture))))) { pHigh = aPersModel[pm]; } } else { - meanErr = (mode == 1 ? aPersModel[pm]->base.meanErr : aPersModel[pm]->chromG.meanErr); + meanErr = (mode == 1 ? aPersModel[pm]->base.mean_error : aPersModel[pm]->chromG.mean_error); if (focusDist > 0) { // by focus distance if (aPersModel[pm]->focLen == bestFocLenLow && ( - (focDist == focusDist && (mode == 1 ? pLow->base.meanErr : pLow->chromG.meanErr) > meanErr) + (focDist == focusDist && (mode == 1 ? pLow->base.mean_error : pLow->chromG.mean_error) > meanErr) || (focDist >= focusDist && focDist < pLow->focDist && pLow->focDist > focusDist) || (focDist <= focusDist && (pLow->focDist > focusDist || fabs(focusDistLog - focDistLog) < fabs(focusDistLog - (log(pLow->focDist) + euler)))))) { pLow = aPersModel[pm]; } if (aPersModel[pm]->focLen == bestFocLenHigh && ( - (focDist == focusDist && (mode == 1 ? pHigh->base.meanErr : pHigh->chromG.meanErr) > meanErr) + (focDist == focusDist && (mode == 1 ? pHigh->base.mean_error : pHigh->chromG.mean_error) > meanErr) || (focDist <= focusDist && focDist > pHigh->focDist && pHigh->focDist < focusDist) || (focDist >= focusDist && (pHigh->focDist < focusDist || fabs(focusDistLog - focDistLog) < fabs(focusDistLog - (log(pHigh->focDist) + euler)))))) { pHigh = aPersModel[pm]; } } else { // no focus distance available, just error - if (aPersModel[pm]->focLen == bestFocLenLow && (mode == 1 ? pLow->base.meanErr : pLow->chromG.meanErr) > meanErr) { + if (aPersModel[pm]->focLen == bestFocLenLow && (mode == 1 ? pLow->base.mean_error : pLow->chromG.mean_error) > meanErr) { pLow = aPersModel[pm]; } - if (aPersModel[pm]->focLen == bestFocLenHigh && (mode == 1 ? pHigh->base.meanErr : pHigh->chromG.meanErr) > meanErr) { + if (aPersModel[pm]->focLen == bestFocLenHigh && (mode == 1 ? pHigh->base.mean_error : pHigh->chromG.mean_error) > meanErr) { pHigh = aPersModel[pm]; } } @@ -715,17 +761,17 @@ void XMLCALL LCPProfile::XmlTextHandler(void *pLCPProfile, const XML_Char *s, in // Section depended if (!strcmp("FocalLengthX", tag)) { - pProf->pCurCommon->focLenX = atof(raw); + pProf->pCurCommon->foc_len_x = atof(raw); } else if (!strcmp("FocalLengthY", tag)) { - pProf->pCurCommon->focLenY = atof(raw); + pProf->pCurCommon->foc_len_y = atof(raw); } else if (!strcmp("ImageXCenter", tag)) { - pProf->pCurCommon->imgXCenter = atof(raw); + pProf->pCurCommon->img_center_x = atof(raw); } else if (!strcmp("ImageYCenter", tag)) { - pProf->pCurCommon->imgYCenter = atof(raw); + pProf->pCurCommon->img_center_y = atof(raw); } else if (!strcmp("ScaleFactor", tag)) { - pProf->pCurCommon->scaleFac = atof(raw); + pProf->pCurCommon->scale_factor = atof(raw); } else if (!strcmp("ResidualMeanError", tag)) { - pProf->pCurCommon->meanErr = atof(raw); + pProf->pCurCommon->mean_error = atof(raw); } else if (!strcmp("RadialDistortParam1", tag) || !strcmp("VignetteModelParam1", tag)) { pProf->pCurCommon->param[0] = atof(raw); } else if (!strcmp("RadialDistortParam2", tag) || !strcmp("VignetteModelParam2", tag)) { diff --git a/rtengine/lcp.h b/rtengine/lcp.h index 908bacf56..fa8cf226d 100644 --- a/rtengine/lcp.h +++ b/rtengine/lcp.h @@ -17,36 +17,52 @@ * along with RawTherapee. If not, see . */ -#ifndef _LCP_ -#define _LCP_ +#pragma once + +#include +#include +#include + +#include +#include #include "imagefloat.h" -#include "../rtgui/threadutils.h" -#include -#include -#include -#include -#include +#include "opthelper.h" namespace rtengine { + // Perspective model common data, also used for Vignette and Fisheye -class LCPModelCommon +class LCPModelCommon final { public: - float focLenX, focLenY, imgXCenter, imgYCenter; - float param[5]; // k1..k5, resp. alpha1..5 - float scaleFac; // alpha0 - double meanErr; - bool badErr; - - double x0, y0, fx, fy; // prepared params - LCPModelCommon(); bool empty() const; // is it empty void print() const; // printf all values void merge(const LCPModelCommon& a, const LCPModelCommon& b, float facA); void prepareParams(int fullWidth, int fullHeight, float focalLength, float focalLength35mm, float sensorFormatFactor, bool swapXY, bool mirrorX, bool mirrorY); + +//private: + using Param = std::array; + using VignParam = std::array; + + float foc_len_x; + float foc_len_y; + float img_center_x; + float img_center_y; + Param param; // k1..k5, resp. alpha1..5 + float scale_factor; // alpha0 + double mean_error; + bool bad_error; + + // prepared params + float x0; + float y0; + float fx; + float fy; + float rfx; + float rfy; + VignParam vign_param; }; class LCPPersModel @@ -130,9 +146,10 @@ public: LCPMapper(LCPProfile* pProf, float focalLength, float focalLength35mm, float focusDist, float aperture, bool vignette, bool useCADistP, int fullWidth, int fullHeight, const CoarseTransformParams& coarse, int rawRotationDeg); - void correctDistortion(double& x, double& y) const; // MUST be the first stage - void correctCA(double& x, double& y, int channel) const; - float calcVignetteFac (int x, int y) const; // MUST be in RAW + void correctDistortion(double& x, double& y) const; // MUST be the first stage + void correctCA(double& x, double& y, int channel) const; + void processVignetteLine(int width, int y, float *line) const; + void processVignetteLine3Channels(int width, int y, float *line) const; }; + } -#endif diff --git a/rtengine/median.h b/rtengine/median.h index 971452bc3..30adbacb3 100644 --- a/rtengine/median.h +++ b/rtengine/median.h @@ -64,6 +64,15 @@ inline vfloat median(std::array array) } #endif + +template +inline T median(std::array array) +{ + float val1 = std::max(std::min(array[0], array[1]), std::min(array[2], array[3])); + float val2 = std::min(std::max(array[0], array[1]), std::max(array[2], array[3])); + return (val1 + val2) / 2.f; +} + template inline T median(std::array array) { diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc new file mode 100644 index 000000000..0ef4f6b6b --- /dev/null +++ b/rtengine/pixelshift.cc @@ -0,0 +1,1430 @@ +//////////////////////////////////////////////////////////////// +// +// pentax pixelshift algorithm with motion detection +// +// +// If motion correction is enabled only the pixels which are not detected as motion are set +// That means for a complete image you have to demosaic one of the frames with a bayer demosaicer to fill red, green and blue +// before calling pixelshift in case motion correction is enabled. +// +// copyright (c) Ingo Weyrich 2016 +// +// +// pixelshift.cc 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. +// +// This program 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 . +// +//////////////////////////////////////////////////////////////// + +#include +#include "rawimagesource.h" +#include "../rtgui/multilangmgr.h" +#include "procparams.h" +#include "gauss.h" +#include "median.h" +#define BENCHMARK +#include "StopWatch.h" + +namespace +{ + +float greenDiff(float a, float b, bool adaptive, float stddevFactor, float eperIso, float nreadIso, float prnu, bool showMotion) +{ + // calculate the difference between two green samples +#ifdef PIXELSHIFTDEV + if(adaptive) { +#endif + float gDiff = a - b; + gDiff *= eperIso; + gDiff *= gDiff; + float avg = (a + b) * 0.5f; + avg *= eperIso; + prnu *= avg; + float stddev = stddevFactor * (avg + nreadIso + prnu * prnu); + float result = gDiff - stddev; + + if(!showMotion) { + return result; + } else if(result > 0.f) { // for the motion mask + return std::fabs(a - b) / (std::max(a, b) + 0.01f); + } else { + return 0.f; + } +#ifdef PIXELSHIFTDEV + + } else { + float gDiff = std::fabs(a - b); + // add a small epsilon to avoid division by zero + float maxVal = std::max(a, b) + 0.01f; + return gDiff / maxVal; + } +#endif +} + +#ifdef PIXELSHIFTDEV +float nonGreenDiff(float a, float b, float stddevFactor, float eperIso, float nreadIso, float prnu, bool showMotion) +{ + // calculate the difference between two nongreen samples + float gDiff = a - b; + gDiff *= eperIso; + gDiff *= gDiff; + float avg = (a + b) / 2.f; + avg *= eperIso; + prnu *= avg; + float stddev = stddevFactor * (avg + nreadIso + prnu * prnu); + float result = gDiff - stddev; + + if(!showMotion) { + return result; + } else if(result > 0.f) { // for the motion mask + return std::fabs(a - b) / (std::max(a, b) + 0.01f); + } else { + return 0.f; + } +} +#endif + +float nonGreenDiffCross(float right, float left, float top, float bottom, float centre, float clippedVal, float stddevFactor, float eperIso, float nreadIso, float prnu, bool showMotion) +{ + if(rtengine::max(right, left, top, bottom, centre) > clippedVal) { + return 0.f; + } + // check non green cross + float hDiff = (right + left) * 0.5f - centre; + hDiff *= eperIso; + hDiff *= hDiff; + float vDiff = (top + bottom) * 0.5f - centre; + vDiff *= eperIso; + vDiff *= vDiff; + float avg = ((right + left) + (top + bottom)) * 0.25f; + avg *= eperIso; + prnu *= avg; + float stddev = stddevFactor * (avg + nreadIso + prnu * prnu); + float result = std::min(hDiff, vDiff) - stddev; + + if(!showMotion) { + return result; + } else if(result > 0.f) { // for the motion mask + return std::sqrt((result / (stddev + result + 0.01f))); + } else { + return 0.f; + } +} + +void paintMotionMask(int index, bool showMotion, float gridMax, bool showOnlyMask, float *maskDest, float *nonMaskDest0, float *nonMaskDest1) +{ + if(showMotion) { + if(!showOnlyMask) { + // if showMotion is enabled colourize the pixel + maskDest[index] = 1000.f + 25000.f * gridMax; + nonMaskDest1[index] = nonMaskDest0[index] = 0.f; + } else { + maskDest[index] = nonMaskDest0[index] = nonMaskDest1[index] = 1000.f + 25000.f * gridMax; + } + } +} + +void invertMask(int xStart, int xEnd, int yStart, int yEnd, array2D &maskIn, array2D &maskOut) +{ + #pragma omp parallel for schedule(dynamic,16) + + for(int i = yStart; i < yEnd; ++i) { + #pragma omp simd + + for(int j = xStart; j < xEnd; ++j) { + maskOut[i][j] = ~maskIn[i][j]; + } + } +} + +void xorMasks(int xStart, int xEnd, int yStart, int yEnd, array2D &maskIn, array2D &maskOut) +{ + #pragma omp parallel for schedule(dynamic,16) + + for(int i = yStart; i < yEnd; ++i) { + #pragma omp simd + + for(int j = xStart; j < xEnd; ++j) { + maskOut[i][j] ^= maskIn[i][j]; + } + } +} + +void floodFill4Impl(int y, int x, int xStart, int xEnd, int yStart, int yEnd, array2D &mask, std::stack, std::vector>> &coordStack) +{ + coordStack.emplace(x, y); + + while(!coordStack.empty()) { + auto coord = coordStack.top(); + coordStack.pop(); + auto x = coord.first, y = coord.second; + + if (mask[y][x] == 255) { + auto yUp = y - 1, yDown = y + 1; + bool lastXUp = false, lastXDown = false, firstXUp = false, firstXDown = false; + mask[y][x] = 0; + + if(yUp >= yStart && mask[yUp][x] == 255) { + coordStack.emplace(x, yUp); + firstXUp = lastXUp = true; + } + + if(yDown < yEnd && mask[yDown][x] == 255) { + coordStack.emplace(x, yDown); + firstXDown = lastXDown = true; + } + + auto xr = x + 1; + + while(xr < xEnd && mask[y][xr] == 255) { + mask[y][xr] = 0; + + if(yUp >= yStart && mask[yUp][xr] == 255) { + if(!lastXUp) { + coordStack.emplace(xr, yUp); + lastXUp = true; + } + } else { + lastXUp = false; + } + + if(yDown < yEnd && mask[yDown][xr] == 255) { + if(!lastXDown) { + coordStack.emplace(xr, yDown); + lastXDown = true; + } + } else { + lastXDown = false; + } + + xr++; + } + + auto xl = x - 1; + lastXUp = firstXUp; + lastXDown = firstXDown; + + while(xl >= xStart && mask[y][xl] == 255) { + mask[y][xl] = 0; + + if(yUp >= yStart && mask[yUp][xl] == 255) { + if(!lastXUp) { + coordStack.emplace(xl, yUp); + lastXUp = true; + } + } else { + lastXUp = false; + } + + if(yDown < yEnd && mask[yDown][xl] == 255) { + if(!lastXDown) { + coordStack.emplace(xl, yDown); + lastXDown = true; + } + } else { + lastXDown = false; + } + + xl--; + } + + mask[y][x] = 0; + } + } +} + +void floodFill4(int xStart, int xEnd, int yStart, int yEnd, array2D &mask) +{ + #pragma omp parallel + { + std::stack, std::vector>> coordStack; + + #pragma omp for schedule(dynamic,128) nowait + + for(uint16_t i = yStart; i < yEnd; i++) + { + floodFill4Impl(i, xStart, xStart, xEnd, yStart, yEnd, mask, coordStack); + } + + #pragma omp for schedule(dynamic,128) nowait + + for(int16_t i = yEnd - 1; i >= 0 ; i--) + { + floodFill4Impl(i, xEnd - 1, xStart, xEnd, yStart, yEnd, mask, coordStack); + } + + #pragma omp sections nowait + { + #pragma omp section + { + uint16_t i = yStart; + + for(uint16_t j = xStart; j < xEnd; j++) + { + floodFill4Impl(i, j, xStart, xEnd, yStart, yEnd, mask, coordStack); + } + } + #pragma omp section + { + uint16_t i = yStart; + + for(uint16_t j = xEnd - 1; j >= xStart; j--) + { + floodFill4Impl(i, j, xStart, xEnd, yStart, yEnd, mask, coordStack); + } + } + #pragma omp section + { + uint16_t i = yEnd; + + for(uint16_t j = xStart; j < xEnd; j++) + { + floodFill4Impl(i, j, xStart, xEnd, yStart, yEnd, mask, coordStack); + } + } + #pragma omp section + { + uint16_t i = yEnd; + + for(uint16_t j = xEnd - 1; j >= xStart; j--) + { + floodFill4Impl(i, j, xStart, xEnd, yStart, yEnd, mask, coordStack); + } + } + } + } +} + +} + +using namespace std; +using namespace rtengine; +void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RAWParams::BayerSensor &bayerParamsIn, unsigned int frame, const std::string &model, float rawWpCorrection) +{ +#ifdef PIXELSHIFTDEV + BENCHFUN +#endif + + if(numFrames != 4) { // fallback for non pixelshift files + amaze_demosaic_RT (0, 0, winw, winh, rawData, red, green, blue); + return; + } + + RAWParams::BayerSensor bayerParams = bayerParamsIn; + +#ifndef PIXELSHIFTDEV + bayerParams.pixelShiftAutomatic = true; +#endif + + if(bayerParams.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::Automatic) { + bool pixelShiftEqualBright = bayerParams.pixelShiftEqualBright; + bayerParams.setPixelShiftDefaults(); + bayerParams.pixelShiftEqualBright = pixelShiftEqualBright; + } else if(bayerParams.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::Off) { + bayerParams.pixelShiftMotion = 0; + bayerParams.pixelShiftAutomatic = false; + bayerParams.pixelshiftShowMotion = false; + } + + if((bayerParams.pixelShiftMotion > 0 || bayerParams.pixelShiftAutomatic)) { + if(bayerParams.pixelShiftMedian) { // We need the amaze demosaiced frames for motion correction +#ifdef PIXELSHIFTDEV + if(!bayerParams.pixelShiftMedian3) { +#endif + if(bayerParams.pixelShiftLmmse) { + lmmse_interpolate_omp(winw, winh, *(rawDataFrames[0]), red, green, blue, bayerParams.lmmse_iterations); + } else { + amaze_demosaic_RT (0, 0, winw, winh, *(rawDataFrames[0]), red, green, blue); + } + multi_array2D redTmp(W,H); + multi_array2D greenTmp(W,H); + multi_array2D blueTmp(W,H); + for(int i=0;i<3;i++) { + if(bayerParams.pixelShiftLmmse) { + lmmse_interpolate_omp(winw, winh, *(rawDataFrames[i+1]), redTmp[i], greenTmp[i], blueTmp[i], bayerParams.lmmse_iterations); + } else { + amaze_demosaic_RT (0, 0, winw, winh, *(rawDataFrames[i+1]), redTmp[i], greenTmp[i], blueTmp[i]); + } + } + #pragma omp parallel for schedule(dynamic,16) + for(int i=border;i redTmp(W,H); + multi_array2D greenTmp(W,H); + multi_array2D blueTmp(W,H); + for(int i=0, frameIndex = 0;i<4;++i) { + if(i != currFrame) { + if(bayerParams.pixelShiftLmmse) { + lmmse_interpolate_omp(winw, winh, *(rawDataFrames[i]), redTmp[frameIndex], greenTmp[frameIndex], blueTmp[frameIndex], raw.bayersensor.lmmse_iterations); + } else { + amaze_demosaic_RT (0, 0, winw, winh, *(rawDataFrames[i]), redTmp[frameIndex], greenTmp[frameIndex], blueTmp[frameIndex]); + } + ++frameIndex; + } + } + unsigned int offsX0 = 0, offsY0 = 0; + unsigned int offsX1 = 0, offsY1 = 0; + unsigned int offsX2 = 0, offsY2 = 0; + + // We have to adjust the offsets for the selected subframe we exclude from median + switch (currFrame) { + case 0: + offsY0 = 1; + offsX0 = 0; + offsY1 = 1; + offsX1 = 1; + offsY2 = 0; + offsX2 = 1; + break; + + case 1: + offsY0 = 0; + offsX0 = 0; + offsY1 = 1; + offsX1 = 1; + offsY2 = 0; + offsX2 = 1; + break; + + case 2: + offsY0 = 0; + offsX0 = 0; + offsY1 = 1; + offsX1 = 0; + offsY2 = 0; + offsX2 = 1; + break; + + case 3: + offsY0 = 0; + offsX0 = 0; + offsY1 = 1; + offsX1 = 0; + offsY2 = 1; + offsX2 = 1; + } + + #pragma omp parallel for schedule(dynamic,16) + for(int i=border;i 0; + float stddevFactorGreen = bayerParams.pixelShiftStddevFactorGreen; + float stddevFactorRed = bayerParams.pixelShiftStddevFactorRed; + float stddevFactorBlue = bayerParams.pixelShiftStddevFactorBlue; + float nreadIso = bayerParams.pixelShiftNreadIso; + float prnu = bayerParams.pixelShiftPrnu; + const float redBlueWeight = bayerParams.pixelShiftRedBlueWeight + 1.f; +#else + float stddevFactorGreen = 5.f; + float stddevFactorRed = 5.f; + float stddevFactorBlue = 5.f; + float nreadIso = 0.f; + float prnu = 1.f; + const float redBlueWeight = 0.7f + 1.f; +#endif + float eperIso = bayerParams.pixelShiftEperIso; + const bool checkNonGreenHorizontal = bayerParams.pixelShiftNonGreenHorizontal; + const bool checkNonGreenVertical = bayerParams.pixelShiftNonGreenVertical; + const bool checkNonGreenCross = bayerParams.pixelShiftNonGreenCross; + const bool checkNonGreenAmaze = bayerParams.pixelShiftNonGreenAmaze; + const bool checkNonGreenCross2 = bayerParams.pixelShiftNonGreenCross2; + const bool checkGreen = bayerParams.pixelShiftGreen; + const float greenWeight = 2.f; + const bool blurMap = bayerParams.pixelShiftBlur; + const float sigma = bayerParams.pixelShiftSigma; +#ifdef PIXELSHIFTDEV + const float threshold = bayerParams.pixelShiftSum + 9.f; +#else + constexpr float threshold = 3.f + 9.f; +#endif + const bool experimental0 = bayerParams.pixelShiftExp0; + const bool holeFill = bayerParams.pixelShiftHoleFill; + const bool equalBrightness = bayerParams.pixelShiftEqualBright; + const bool smoothTransitions = blurMap && bayerParams.pixelShiftSmoothFactor > 0. && !showOnlyMask; + const bool automatic = bayerParams.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::Automatic; + const float smoothFactor = 1.0 - bayerParams.pixelShiftSmoothFactor; + + static const float nReadK3II[] = { 3.4f, // ISO 100 + 3.1f, // ISO 125 + 2.5f, // ISO 160 + 2.5f, // ISO 200 + 2.5f, // ISO 250 + 2.5f, // ISO 320 + 2.3f, // ISO 400 + 2.5f, // ISO 500 + 2.3f, // ISO 640 + 2.3f, // ISO 800 + 2.4f, // ISO 1000 + 2.3f, // ISO 1250 + 1.75f, // ISO 1600 + 1.75f, // ISO 2000 + 1.75f, // ISO 2500 + 1.75f, // ISO 3200 + 1.75f, // ISO 4000 + 1.75f, // ISO 5000 + 1.75f, // ISO 6400 + 1.75f, // ISO 8000 + 1.75f, // ISO 10000 + 1.5f, // ISO 12800 + 1.5f, // ISO 16000 + 1.5f, // ISO 20000 + 1.5f, // ISO 25600 + 1.5f, // ISO 32000 + 1.5f, // ISO 40000 + 1.5f, // ISO 51200 + 1.5f // ISO > 51200 (we get a max ISO value of 65535 from dcraw) + }; + + static const float ePerIsoK3II = 0.35f; + + static const float nReadK1[] = { 3.45f, // ISO 100 + 3.15f, // ISO 125 + 3.45f, // ISO 160 + 3.0f, // ISO 200 + 3.0f, // ISO 250 + 3.0f, // ISO 320 + 2.7f, // ISO 400 + 2.7f, // ISO 500 + 2.7f, // ISO 640 + 2.5f, // ISO 800 + 2.5f, // ISO 1000 + 2.5f, // ISO 1250 + 2.4f, // ISO 1600 + 2.4f, // ISO 2000 + 2.4f, // ISO 2500 + 2.4f, // ISO 3200 + 2.4f, // ISO 4000 + 2.4f, // ISO 5000 + 2.4f, // ISO 6400 + 2.4f, // ISO 8000 + 2.4f, // ISO 10000 + 2.4f, // ISO 12800 + 2.4f, // ISO 16000 + 2.4f, // ISO 20000 + 2.4f, // ISO 25600 + 2.4f, // ISO 32000 + 2.4f, // ISO 40000 + 2.4f, // ISO 51200 + 2.4f, // ISO 64000 + 2.4f, // ISO 80000 + 2.4f, // ISO 102400 + 2.4f, // ISO 128000 + 2.4f, // ISO 160000 + 2.4f // ISO 204800 + }; + + static const float ePerIsoK1 = 0.75f; + + static const float nReadK70[] = { 4.0f, // ISO 100 + 4.0f, // ISO 125 + 4.0f, // ISO 160 + 4.0f, // ISO 200 + 4.0f, // ISO 250 + 4.0f, // ISO 320 + 4.0f, // ISO 400 + 4.0f, // ISO 500 + 4.0f, // ISO 640 + 3.0f, // ISO 800 + 3.0f, // ISO 1000 + 3.0f, // ISO 1250 + 3.0f, // ISO 1600 + 3.0f, // ISO 2000 + 3.0f, // ISO 2500 + 3.0f, // ISO 3200 + 3.0f, // ISO 4000 + 3.0f, // ISO 5000 + 3.0f, // ISO 6400 + 3.0f, // ISO 8000 + 3.0f, // ISO 10000 + 3.0f, // ISO 12800 + 3.0f, // ISO 16000 + 3.0f, // ISO 20000 + 3.0f, // ISO 25600 + 3.0f, // ISO 32000 + 3.0f, // ISO 40000 + 3.0f, // ISO 51200 + 3.0f // ISO > 51200 (we get a max ISO value of 65535 from dcraw) + }; + + static const float ePerIsoK70 = 0.5f; + + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::pixelshift])); + plistener->setProgress(0.0); + } + + + const bool skip = (gridSize_ == RAWParams::BayerSensor::ePSMotionCorrection::Grid1x2); + int gridSize = 1; + bool nOf3x3 = false; + + switch (gridSize_) { + case RAWParams::BayerSensor::ePSMotionCorrection::Grid1x1: + case RAWParams::BayerSensor::ePSMotionCorrection::Grid1x2: + gridSize = 1; + break; + + case RAWParams::BayerSensor::ePSMotionCorrection::Grid3x3: + gridSize = 3; + break; + + case RAWParams::BayerSensor::ePSMotionCorrection::Grid5x5: + gridSize = 5; + break; + + case RAWParams::BayerSensor::ePSMotionCorrection::Grid7x7: + gridSize = 7; + break; + + case RAWParams::BayerSensor::ePSMotionCorrection::Grid3x3New: + gridSize = 1; + nOf3x3 = true; + } + + if(adaptive && blurMap && nOf3x3 && smoothFactor == 0.f && !showMotion) { + if(plistener) { + plistener->setProgress(1.0); + } + + return; + } + +#ifdef PIXELSHIFTDEV + // Lookup table for non adaptive (slider) mode + LUTf log2Lut(32768, LUT_CLIP_BELOW | LUT_CLIP_ABOVE); + + if(detectMotion && !adaptive) { + const float lutStrength = 2.f; + log2Lut[0] = 0; + + for(int i = 2; i < 65536; i += 2) { + log2Lut[i >> 1] = lutStrength * log2(i) / 100.f; + } + } +#endif + + const float scaleGreen = 1.f / scale_mul[1]; + + float nRead; + float eperIsoModel; + + int nReadIndex = static_cast(round(log2(idata->getISOSpeed() / 100.f) * 3.f)); + + if(model.find("K-3") != string::npos) { + nRead = nReadK3II[nReadIndex]; + eperIsoModel = ePerIsoK3II; + } else if(model.find("K-1") != string::npos) { + nRead = nReadK1[nReadIndex]; + eperIsoModel = ePerIsoK1; + } else { + nRead = nReadK70[nReadIndex]; + eperIsoModel = ePerIsoK70; + } + + nRead *= pow(2.f, nreadIso); + eperIsoModel *= pow(2.f, eperIso); + +#ifdef PIXELSHIFTDEV + if(adaptive && experimental0) { + eperIso = eperIsoModel * sqrtf(100.f / (rawWpCorrection * idata->getISOSpeed())); + } else { + eperIso = eperIsoModel * (100.f / (rawWpCorrection * idata->getISOSpeed())); + } +#else + eperIso = eperIsoModel * (100.f / (rawWpCorrection * idata->getISOSpeed())); +#endif + +#ifdef PIXELSHIFTDEV + std::cout << "WL: " << c_white[0] << " BL: " << c_black[0] << " ePerIso multiplicator: " << (65535.f / (c_white[0] - c_black[0])) << std::endl; +#endif + float eperIsoRed = (eperIso / scale_mul[0]) * (65535.f / (c_white[0] - c_black[0])); + float eperIsoGreen = (eperIso * scaleGreen) * (65535.f / (c_white[1] - c_black[1])); + float eperIsoBlue = (eperIso / scale_mul[2]) * (65535.f / (c_white[2] - c_black[2])); + + const float clippedRed = 65535.f / scale_mul[0]; + const float clippedBlue = 65535.f / scale_mul[2]; + + prnu /= 100.f; + stddevFactorGreen *= stddevFactorGreen; + stddevFactorRed *= stddevFactorRed; + stddevFactorBlue *= stddevFactorBlue; + + + nRead *= nRead; + + // If the values of two corresponding green pixels differ my more then motionThreshold %, the pixel will be treated as a badGreen pixel + float motionThreshold = 1.f - (motion / 100.f); + // For shades of green motion indicators + const float blendFactor = ((adaptive || motion == 0.f) ? 1.f : 1.f / (1.f - motionThreshold)); + + unsigned int offsX = 0, offsY = 0; + + if(!bayerParams.pixelShiftMedian || !adaptive) { + // We have to adjust the offsets for the selected subframe we use for areas with motion + switch (frame) { + case 0: + offsX = offsY = 0; + break; + + case 1: + offsX = 0; + offsY = 1; + break; + + case 2: + offsX = offsY = 1; + break; + + case 3: + offsX = 1; + offsY = 0; + } + } + + const float thresh = adaptive ? 0.f : motionThreshold; + array2D psRed(winw + 32, winh); // increase width to avoid cache conflicts + array2D psG1(winw + 32, winh); + array2D psG2(winw + 32, winh); + array2D psBlue(winw + 32, winh); + + // calculate average green brightness for each frame + float greenBrightness[4] = {1.f, 1.f, 1.f, 1.f}; + + if(equalBrightness) { + LUT *histo[4]; + + for(int i = 0; i < 4; ++i) { + histo[i] = new LUT(65536); + histo[i]->clear(); + } + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + LUT *histoThr[4]; + + for(int i = 0; i < 4; ++i) { + histoThr[i] = new LUT(65536); + histoThr[i]->clear(); + } + +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) nowait +#endif + + for(int i = winy + 1; i < winh - 1; ++i) { + int j = winx + 1; + int c = FC(i, j); + + // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop + unsigned int offset = c & 1; + + for(; j < winw - 1; ++j) { + float green1 = (*rawDataFrames[1 - offset])[i - offset + 1][j]; + float green2 = (*rawDataFrames[3 - offset])[i + offset][j + 1]; + (*histoThr[1 - offset])[green1]++; + (*histoThr[3 - offset])[green2]++; + offset ^= 1; // 0 => 1 or 1 => 0 + } + } + + #pragma omp critical + { + for(int i = 0; i < 4; ++i) { + (*histo[i]) += (*histoThr[i]); + delete histoThr[i]; + } + } + } + + float medians[4]; + + for(int i = 0; i < 4; ++i) { + //find median of histogram + uint32_t median = 0, count = 0; + uint32_t datalen = (winh - 2) * (winw - 2) / 2; + + while (count < datalen / 2) { + count += (*histo[i])[median]; + ++median; + } + + const float weight = (count - datalen / 2.f) / (*histo[i])[median - 1]; + medians[i] = intp(weight, (float)(median - 2), (float)(median - 1)); + delete histo[i]; + } + + for(int i = 0; i < 4; ++i) { + greenBrightness[i] = medians[frame] / medians[i]; + } + +#ifdef PIXELSHIFTDEV + std::cout << "brightness factors by median : " << greenBrightness[0] << " " << greenBrightness[1] << " " << greenBrightness[2] << " " << greenBrightness[3] << std::endl; +#endif + + } + +// fill channels psRed, psG1, psG2 and psBlue +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for(int i = winy + 1; i < winh - 1; ++i) { + float *greenDest1 = psG1[i]; + float *greenDest2 = psG2[i]; + float *nonGreenDest0 = psRed[i]; + float *nonGreenDest1 = psBlue[i]; + int j = winx + 1; + int c = FC(i, j); + + if ((c + FC(i, j + 1)) == 3) { + // row with blue pixels => swap destination pointers for non green pixels + std::swap(nonGreenDest0, nonGreenDest1); + std::swap(greenDest1, greenDest2); + } + + // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop + unsigned int offset = c & 1; + + for(; j < winw - 1; ++j) { + // store the values from the 4 frames into 4 different temporary planes + greenDest1[j] = (*rawDataFrames[1 - offset])[i - offset + 1][j] * greenBrightness[1 - offset]; + greenDest2[j] = (*rawDataFrames[3 - offset])[i + offset][j + 1] * greenBrightness[3 - offset]; + nonGreenDest0[j] = (*rawDataFrames[(offset << 1) + offset])[i][j + offset] * greenBrightness[(offset << 1) + offset]; + nonGreenDest1[j] = (*rawDataFrames[2 - offset])[i + 1][j - offset + 1] * greenBrightness[2 - offset]; + offset ^= 1; // 0 => 1 or 1 => 0 + } + } + +// now that the temporary planes are filled for easy access we do the motion detection +#ifdef PIXELSHIFTDEV + int sum[2] = {0}; + float pixelcount = ((winh - (border + offsY) - (winy + border - offsY)) * (winw - (border + offsX) - (winx + border - offsX))) / 2.f; +#endif + + array2D psMask(winw, winh); + +#ifdef _OPENMP + #pragma omp parallel +#endif + { +#ifdef PIXELSHIFTDEV + int sumThr[2] = {0}; +#endif +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) nowait +#endif + + for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) { + float *greenDest = green[i + offsY]; + float *redDest = red[i + offsY]; + float *blueDest = blue[i + offsY]; + int j = winx + border - offsX; + +#ifdef PIXELSHIFTDEV + float greenDifMax[gridSize]; // Here we store the maximum differences per Column + + // green channel motion detection checks the grid around the pixel for differences in green channels + + if(detectMotion || (adaptive && checkGreen)) { + if(gridSize == 3) { + // compute maximum of differences for first two columns of 3x3 grid + greenDifMax[0] = std::max({greenDiff(psG1[i - 1][j - 1], psG2[i - 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][j - 1], psG2[ i ][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][j - 1], psG2[i + 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + greenDifMax[1] = std::max({greenDiff(psG1[i - 1][ j ], psG2[i - 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][ j ], psG2[ i ][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][ j ], psG2[i + 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + } else if(gridSize == 5) { + // compute maximum of differences for first four columns of 5x5 grid + greenDifMax[0] = std::max({greenDiff(psG1[i - 2][j - 2], psG2[i - 2][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 1][j - 2], psG2[i - 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][j - 2], psG2[ i ][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][j - 2], psG2[i + 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 2][j - 2], psG2[i + 2][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + greenDifMax[1] = std::max({greenDiff(psG1[i - 2][j - 1], psG2[i - 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 1][j - 1], psG2[i - 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][j - 1], psG2[ i ][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][j - 1], psG2[i + 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 2][j - 1], psG2[i + 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + greenDifMax[2] = std::max({greenDiff(psG1[i - 2][ j ], psG2[i - 2][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 1][ j ], psG2[i - 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][ j ], psG2[ i ][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][ j ], psG2[i + 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 2][ j ], psG2[i + 2][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + greenDifMax[3] = std::max({greenDiff(psG1[i - 2][j + 1], psG2[i - 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 1][j + 1], psG2[i - 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][j + 1], psG2[ i ][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][j + 1], psG2[i + 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 2][j + 1], psG2[i + 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + } else if(gridSize == 7) { + // compute maximum of differences for first six columns of 7x7 grid + greenDifMax[0] = std::max({greenDiff(psG1[i - 3][j - 3], psG2[i - 3][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 2][j - 3], psG2[i - 2][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 1][j - 3], psG2[i - 1][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][j - 3], psG2[ i ][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][j - 3], psG2[i + 1][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 2][j - 3], psG2[i + 2][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 3][j - 3], psG2[i + 3][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + greenDifMax[1] = std::max({greenDiff(psG1[i - 3][j - 2], psG2[i - 3][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 2][j - 2], psG2[i - 2][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 1][j - 2], psG2[i - 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][j - 2], psG2[ i ][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][j - 2], psG2[i + 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 2][j - 2], psG2[i + 2][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 3][j - 2], psG2[i + 3][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + greenDifMax[2] = std::max({greenDiff(psG1[i - 3][j - 1], psG2[i - 3][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 2][j - 1], psG2[i - 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 1][j - 1], psG2[i - 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][j - 1], psG2[ i ][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][j - 1], psG2[i + 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 2][j - 1], psG2[i + 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 3][j - 1], psG2[i + 3][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + greenDifMax[3] = std::max({greenDiff(psG1[i - 3][ j ], psG2[i - 3][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 2][ j ], psG2[i - 2][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 1][ j ], psG2[i - 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][ j ], psG2[ i ][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][ j ], psG2[i + 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 2][ j ], psG2[i + 2][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 3][ j ], psG2[i + 3][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + greenDifMax[4] = std::max({greenDiff(psG1[i - 3][j + 1], psG2[i - 3][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 2][j + 1], psG2[i - 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 1][j + 1], psG2[i - 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][j + 1], psG2[ i ][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][j + 1], psG2[i + 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 2][j + 1], psG2[i + 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 3][j + 1], psG2[i + 3][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + greenDifMax[5] = std::max({greenDiff(psG1[i - 3][j + 2], psG2[i - 3][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 2][j + 2], psG2[i - 2][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 1][j + 2], psG2[i - 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][j + 2], psG2[ i ][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][j + 2], psG2[i + 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 2][j + 2], psG2[i + 2][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 3][j + 2], psG2[i + 3][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + } + + } + + // this is the index for the last column of the grid. Obviously we have to start with gridSize - 1 + int lastIndex = gridSize - 1; + float korr = 0.f; + bool blueRow = false; +#endif + + int c = FC(i, j); + +#ifdef PIXELSHIFTDEV + if (c == 2 || ((c & 1) && FC(i, j + 1) == 2)) { + // row with blue pixels => swap destination pointers for non green pixels + blueRow = true; + } +#endif + // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop + unsigned int offset = c & 1; + + for(; j < winw - (border + offsX); ++j) { + psMask[i][j] = 1.f; + + offset ^= 1; // 0 => 1 or 1 => 0 + +#ifdef PIXELSHIFTDEV + if(detectMotion || (adaptive && checkGreen)) { + bool skipNext = false; +#else + if(adaptive && checkGreen) { +#endif + float gridMax; + +#ifdef PIXELSHIFTDEV + + if(gridSize < 2) { + // compute difference for current pixel and skip next pixel, that's roughly the method from dcrawps +#endif + gridMax = greenDiff(psG1[i][j], psG2[i][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion); +#ifdef PIXELSHIFTDEV + + skipNext = skip; + } else if(gridSize == 3) { + // compute maximum of differences for third column of 3x3 grid and save at position lastIndex + greenDifMax[lastIndex] = std::max({greenDiff(psG1[i - 1][j + 1], psG2[i - 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][j + 1], psG2[ i ][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][j + 1], psG2[i + 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + // calculate maximum of whole grid by calculating maximum of grid column max values + gridMax = std::max({greenDifMax[0], greenDifMax[1], greenDifMax[2]}); + // adjust index for next column + lastIndex ++; + lastIndex = lastIndex == gridSize ? 0 : lastIndex; + } else if(gridSize == 5) { + // compute maximum of differences for fifth column of 5x5 grid and save at position lastIndex + greenDifMax[lastIndex] = std::max({greenDiff(psG1[i - 2][j + 2], psG2[i - 2][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 1][j + 2], psG2[i - 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][j + 2], psG2[ i ][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][j + 2], psG2[i + 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 2][j + 2], psG2[i + 2][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) + }); + // calculate maximum of whole grid by calculating maximum of grid column max values + gridMax = std::max({greenDifMax[0], greenDifMax[1], greenDifMax[2], greenDifMax[3], greenDifMax[4]}); + // adjust index for next column + lastIndex ++; + lastIndex = lastIndex == gridSize ? 0 : lastIndex; + } else if(gridSize == 7) { + // compute maximum of differences for 7th column of 7x7 grid and save at position lastIndex + greenDifMax[lastIndex] = std::max({greenDiff(psG1[i - 3][j + 3], psG2[i - 3][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 2][j + 3], psG2[i - 2][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i - 1][j + 3], psG2[i - 1][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[ i ][j + 3], psG2[ i ][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 1][j + 3], psG2[i + 1][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 2][j + 3], psG2[i + 2][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + greenDiff(psG1[i + 3][j + 3], psG2[i + 3][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), + }); + // calculate maximum of whole grid by calculating maximum of grid column max values + gridMax = std::max({greenDifMax[0], greenDifMax[1], greenDifMax[2], greenDifMax[3], greenDifMax[4], greenDifMax[5], greenDifMax[6]}); + // adjust index for next column + lastIndex ++; + lastIndex = lastIndex == gridSize ? 0 : lastIndex; + } + + if(!adaptive) { + // increase motion detection dependent on brightness + korr = log2Lut[((int)(psG1[i][j] * scaleGreen)) >> 1]; + } + + if (gridMax > thresh - korr) { +#else + if (gridMax > thresh) { + +#endif + +#ifdef PIXELSHIFTDEV + sumThr[offset] ++; + + if(nOf3x3) { +#endif + psMask[i][j] = greenWeight; +#ifdef PIXELSHIFTDEV + } + + else if((offset == (frame & 1)) && checkNonGreenVertical) { + if(frame > 1) { + green[i + offsY][j + offsX] = blueRow ? psG1[i][j] : psG2[i][j]; + } else { + green[i + offsY][j + offsX] = blueRow ? psG2[i][j] : psG1[i][j];; + } + + } else { + // at least one of the tested green pixels of the grid is detected as motion + paintMotionMask(j + offsX, showMotion, (gridMax - thresh + korr) * blendFactor, showOnlyMask, greenDest, redDest, blueDest); + + if(skipNext) { + // treat the horizontally next pixel also as motion + j++; + paintMotionMask(j + offsX, showMotion, (gridMax - thresh + korr) * blendFactor, showOnlyMask, greenDest, redDest, blueDest); + } + } + +#endif + // do not set the motion pixel values. They have already been set by demosaicer or showMotion + continue; + } + } + + if(adaptive) { + if(checkNonGreenCross) { + // check red cross + float redTop = psRed[i - 1][ j ]; + float redLeft = psRed[ i ][j - 1]; + float redCentre = psRed[ i ][ j ]; + float redRight = psRed[ i ][j + 1]; + float redBottom = psRed[i + 1][ j ]; + float redDiff = nonGreenDiffCross(redRight, redLeft, redTop, redBottom, redCentre, clippedRed, stddevFactorRed, eperIsoRed, nRead, prnu, showMotion); + + if(redDiff > 0.f) { +#ifdef PIXELSHIFTDEV + + if(nOf3x3) { +#endif + psMask[i][j] = redBlueWeight; +#ifdef PIXELSHIFTDEV + } else { + paintMotionMask(j + offsX, showMotion, redDiff, showOnlyMask, redDest, blueDest, greenDest); + } + +#endif + continue; + } + + // check blue cross + float blueTop = psBlue[i - 1][ j ]; + float blueLeft = psBlue[ i ][j - 1]; + float blueCentre = psBlue[ i ][ j ]; + float blueRight = psBlue[ i ][j + 1]; + float blueBottom = psBlue[i + 1][ j ]; + float blueDiff = nonGreenDiffCross(blueRight, blueLeft, blueTop, blueBottom, blueCentre, clippedBlue, stddevFactorBlue, eperIsoBlue, nRead, prnu, showMotion); + + if(blueDiff > 0.f) { +#ifdef PIXELSHIFTDEV + + if(nOf3x3) { +#endif + psMask[i][j] = redBlueWeight; +#ifdef PIXELSHIFTDEV + } else { + paintMotionMask(j + offsX, showMotion, blueDiff, showOnlyMask, blueDest, redDest, greenDest); + } + +#endif + continue; + + } + } + +#ifdef PIXELSHIFTDEV + + if(checkNonGreenHorizontal) { + float redLeft = psRed[ i ][j - 1]; + float redCentre = psRed[ i ][ j ]; + float redRight = psRed[ i ][j + 1]; + + float redDiffLeft = redLeft - redCentre; + float redDiffRight = redRight - redCentre; + + if(redDiffLeft * redDiffRight >= 0.f) { + float redAvg = (redRight + redLeft) / 2.f; + float redDiffHor = nonGreenDiff(redCentre, redAvg, stddevFactorRed, eperIsoRed, nRead, prnu, showMotion); + + if(redDiffHor > 0.f) { + if(nOf3x3) { + psMask[i][j] = redBlueWeight; + } else { + paintMotionMask(j + offsX, showMotion, redDiffHor, showOnlyMask, redDest, blueDest, greenDest); + } + + continue; + } + } + + float blueLeft = psBlue[ i ][j - 1]; + float blueCentre = psBlue[ i ][ j ]; + float blueRight = psBlue[ i ][j + 1]; + + float blueDiffLeft = blueLeft - blueCentre; + float blueDiffRight = blueRight - blueCentre; + + if(blueDiffLeft * blueDiffRight >= 0.f) { + float blueAvg = (blueRight + blueLeft) / 2.f; + float blueDiffHor = nonGreenDiff(blueCentre, blueAvg, stddevFactorBlue, eperIsoBlue, nRead, prnu, showMotion); + + if(blueDiffHor > 0.f) { + if(nOf3x3) { + psMask[i][j] = redBlueWeight; + } else { + paintMotionMask(j + offsX, showMotion, blueDiffHor, showOnlyMask, blueDest, redDest, greenDest); + } + + continue; + } + } + } + + if(checkNonGreenVertical) { + // check red vertically + float redTop = psRed[i - 1][ j ]; + float redCentre = psRed[ i ][ j ]; + float redBottom = psRed[i + 1][ j ]; + + float redDiffTop = redTop - redCentre; + float redDiffBottom = redBottom - redCentre; + + if(redDiffTop * redDiffBottom >= 0.f) { + float redAvg = (redTop + redBottom) / 2.f; + float redDiff = nonGreenDiff(redCentre, redAvg, stddevFactorRed, eperIsoRed, nRead, prnu, showMotion); + + if(redDiff > 0.f) { + if(nOf3x3) { + psMask[i][j] = redBlueWeight; + } else { + paintMotionMask(j + offsX, showMotion, redDiff, showOnlyMask, redDest, blueDest, greenDest); + } + + continue; + } + } + + // check blue vertically + float blueTop = psBlue[i - 1][ j ]; + float blueCentre = psBlue[ i ][ j ]; + float blueBottom = psBlue[i + 1][ j ]; + + float blueDiffTop = blueTop - blueCentre; + float blueDiffBottom = blueBottom - blueCentre; + + if(blueDiffTop * blueDiffBottom >= 0.f) { + float blueAvg = (blueTop + blueBottom) / 2.f; + float blueDiff = nonGreenDiff(blueCentre, blueAvg, stddevFactorBlue, eperIsoBlue, nRead, prnu, showMotion); + + if(blueDiff > 0.f) { + if(nOf3x3) { + psMask[i][j] = redBlueWeight; + } else { + paintMotionMask(j + offsX, showMotion, blueDiff, showOnlyMask, blueDest, redDest, greenDest); + } + + continue; + } + } + } + + if(checkNonGreenAmaze) { + // check current pixel against amaze + float redCentre = psRed[ i ][ j ]; + float redAmaze = red[i + offsY][j + offsX]; + + float redDiffAmaze = nonGreenDiff(redCentre, redAmaze, stddevFactorRed, eperIsoRed, nRead, prnu, showMotion); + + if(redDiffAmaze > 0.f) { + if(nOf3x3) { + psMask[i][j] = redBlueWeight; + } else { + paintMotionMask(j + offsX, showMotion, redDiffAmaze, showOnlyMask, redDest, blueDest, greenDest); + } + + continue; + } + + float blueCentre = psBlue[ i ][ j ]; + float blueAmaze = blue[i + offsY][j + offsX]; + + float blueDiffAmaze = nonGreenDiff(blueCentre, blueAmaze, stddevFactorBlue, eperIsoBlue, nRead, prnu, showMotion); + + if(blueDiffAmaze > 0.f) { + if(nOf3x3) { + psMask[i][j] = redBlueWeight; + } else { + paintMotionMask(j + offsX, showMotion, blueDiffAmaze, showOnlyMask, blueDest, redDest, greenDest); + } + + continue; + } + } + + if(checkNonGreenCross2) { // for green amaze + float greenCentre = (psG1[ i ][ j ] + psG2[ i ][ j ]) / 2.f; + float greenAmaze = green[i + offsY][j + offsX]; + float greenDiffAmaze = nonGreenDiff(greenCentre, greenAmaze, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion); + + if(greenDiffAmaze > 0.f) { + if(nOf3x3) { + psMask[i][j] = greenWeight; + } else { + paintMotionMask(j + offsX, showMotion, greenDiffAmaze, showOnlyMask, greenDest, redDest, blueDest); + } + + continue; + } + } + + if(experimental0) { // for experiments + + } + +#endif + } + + if(showOnlyMask) { // we want only motion mask => paint areas without motion in pure black + red[i + offsY][j + offsX] = green[i + offsY][j + offsX] = blue[i + offsY][j + offsX] = 0.f; + } else if(!(adaptive && nOf3x3)) { + // no motion detected, replace the a priori demosaiced values by the pixelshift combined values + red[i + offsY][j + offsX] = psRed[i][j]; + green[i + offsY][j + offsX] = (psG1[i][j] + psG2[i][j]) / 2.f; + blue[i + offsY][j + offsX] = psBlue[i][j]; + } + } + } + +#ifdef PIXELSHIFTDEV + +#ifdef _OPENMP + #pragma omp critical +#endif + { + sum[0] += sumThr[0]; + sum[1] += sumThr[1]; + } +#endif + } + + +#ifdef PIXELSHIFTDEV + float percent0 = 100.f * sum[0] / pixelcount; + float percent1 = 100.f * sum[1] / pixelcount; + + std::cout << fileName << " : Green detections at stddev " << std::setprecision( 2 ) << bayerParams.pixelShiftStddevFactorGreen << " : Frame 1/3 : " << std::setprecision( 6 ) << sum[0] << " (" << percent0 << "%)" << " Frame 2/4 : " << sum[1] << " (" << percent1 << "%)" << std::endl; +#endif + + if(adaptive && nOf3x3) { + if(blurMap) { + #pragma omp parallel + { + gaussianBlur(psMask, psMask, winw, winh, sigma); + } + } + + array2D mask(W, H, ARRAY2D_CLEAR_DATA); + array2D maskInv(W, H, ARRAY2D_CLEAR_DATA); + + #pragma omp parallel for schedule(dynamic,16) + + for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) { + int j = winx + border - offsX; + float v3sum[3] = {0.f}; + + for(int v = -1; v <= 1; v++) { + for(int h = -1; h < 1; h++) { + v3sum[1 + h] += (psMask[i + v][j + h]); + } + } + + float blocksum = v3sum[0] + v3sum[1]; + + for(int voffset = 2; j < winw - (border + offsX); ++j, ++voffset) { + float colSum = psMask[i - 1][j + 1] + psMask[i][j + 1] + psMask[i + 1][j + 1]; + voffset = voffset == 3 ? 0 : voffset; // faster than voffset %= 3; + blocksum -= v3sum[voffset]; + blocksum += colSum; + v3sum[voffset] = colSum; + + if(blocksum >= threshold) { + mask[i][j] = 255; + } + } + } + + if(holeFill) { + invertMask(winx + border - offsX, winw - (border + offsX), winy + border - offsY, winh - (border + offsY), mask, maskInv); + floodFill4(winx + border - offsX, winw - (border + offsX), winy + border - offsY, winh - (border + offsY), maskInv); + xorMasks(winx + border - offsX, winw - (border + offsX), winy + border - offsY, winh - (border + offsY), maskInv, mask); + } + + + #pragma omp parallel for schedule(dynamic,16) + + for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) { +#ifdef __SSE2__ + + if(smoothTransitions) { // + vfloat onev = F2V(1.f); + vfloat smoothv = F2V(smoothFactor); + int j = winx + border - offsX; + + for(; j < winw - (border + offsX) - 3; j += 4) { + vfloat blendv = vmaxf(LVFU(psMask[i][j]), onev) - onev; + blendv = pow_F(blendv, smoothv); + blendv = vself(vmaskf_eq(smoothv, ZEROV), onev, blendv); + STVFU(psMask[i][j], blendv); + } + + for(; j < winw - (border + offsX); ++j) { + psMask[i][j] = smoothFactor == 0.f ? 1.f : pow_F(std::max(psMask[i][j] - 1.f, 0.f), smoothFactor); + } + } + +#endif + float *greenDest = green[i + offsY]; + float *redDest = red[i + offsY]; + float *blueDest = blue[i + offsY]; + + for(int j = winx + border - offsX; j < winw - (border + offsX); ++j) { + if(mask[i][j] == 255) { + paintMotionMask(j + offsX, showMotion, 0.5f, showOnlyMask, greenDest, redDest, blueDest); + } else if(showOnlyMask) { // we want only motion mask => paint areas without motion in pure black + red[i + offsY][j + offsX] = green[i + offsY][j + offsX] = blue[i + offsY][j + offsX] = 0.f; + } else { + if(smoothTransitions) { +#ifdef __SSE2__ + float blend = psMask[i][j]; +#else + float blend = smoothFactor == 0.f ? 1.f : pow_F(std::max(psMask[i][j] - 1.f, 0.f), smoothFactor); +#endif + red[i + offsY][j + offsX] = intp(blend, red[i + offsY][j + offsX], psRed[i][j] ); + green[i + offsY][j + offsX] = intp(blend, green[i + offsY][j + offsX], (psG1[i][j] + psG2[i][j]) * 0.5f); + blue[i + offsY][j + offsX] = intp(blend, blue[i + offsY][j + offsX], psBlue[i][j]); + } else { + red[i + offsY][j + offsX] = psRed[i][j]; + green[i + offsY][j + offsX] = (psG1[i][j] + psG2[i][j]) * 0.5f; + blue[i + offsY][j + offsX] = psBlue[i][j]; + } + } + } + } + } + + if(plistener) { + plistener->setProgress(1.0); + } +} diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 52517e527..a1c6f58f9 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -470,6 +470,37 @@ enum ProcEvent { EvRetinexgaintransmission = 440, EvLskal = 441, EvOBPCompens = 442, + EvWBtempBias = 443, + EvRawImageNum = 444, + EvPixelShiftMotion = 445, + EvPixelShiftMotionCorrection = 446, + EvPixelShiftStddevFactorGreen = 447, + EvPixelShiftEperIso = 448, + EvPixelShiftNreadIso = 449, + EvPixelShiftPrnu = 450, + EvPixelshiftShowMotion = 451, + EvPixelshiftShowMotionMaskOnly = 452, + EvPixelShiftAutomatic = 453, + EvPixelShiftNonGreenHorizontal = 454, + EvPixelShiftNonGreenVertical = 455, + EvPixelShiftNonGreenCross = 456, + EvPixelShiftStddevFactorRed = 457, + EvPixelShiftStddevFactorBlue = 458, + EvPixelShiftGreenAmaze = 459, + EvPixelShiftNonGreenAmaze = 460, + EvPixelShiftGreen = 461, + EvPixelShiftRedBlueWeight = 462, + EvPixelShiftBlur = 463, + EvPixelShiftSigma = 464, + EvPixelShiftSum = 465, + EvPixelShiftExp0 = 466, + EvPixelShiftHoleFill = 467, + EvPixelShiftMedian = 468, + EvPixelShiftMedian3 = 469, + EvPixelShiftMotionMethod = 470, + EvPixelShiftSmooth = 471, + EvPixelShiftLmmse = 472, + EvPixelShiftEqualBright = 473, NUMOFEVENTS }; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 788c422d6..9da09998d 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -40,7 +40,7 @@ const int br = (int) options.rtSettings.bot_right; const int tl = (int) options.rtSettings.top_left; const int bl = (int) options.rtSettings.bot_left; -const char *RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::numMethods] = {"amaze", "igv", "lmmse", "eahd", "hphd", "vng4", "dcb", "ahd", "fast", "mono", "none" }; +const char *RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::numMethods] = {"amaze", "igv", "lmmse", "eahd", "hphd", "vng4", "dcb", "ahd", "fast", "mono", "none", "pixelshift" }; const char *RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::numMethods] = {"3-pass (best)", "1-pass (medium)", "fast", "mono", "none" }; const char *RAWParams::ff_BlurTypestring[RAWParams::numFlatFileBlurTypes] = {/*"Parametric",*/ "Area Flatfield", "Vertical Flatfield", "Horizontal Flatfield", "V+H Flatfield"}; @@ -58,40 +58,40 @@ bool ToneCurveParams::HLReconstructionNecessary(LUTu &histRedRaw, LUTu &histGree void WBParams::init() { // Creation of the different methods and its associated temperature value - wbEntries.push_back(new WBEntry("Camera" , WBT_CAMERA, M("TP_WBALANCE_CAMERA"), 0, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Auto" , WBT_AUTO, M("TP_WBALANCE_AUTO"), 0, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Daylight" , WBT_DAYLIGHT, M("TP_WBALANCE_DAYLIGHT"), 5300, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Cloudy" , WBT_CLOUDY, M("TP_WBALANCE_CLOUDY"), 6200, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Shade" , WBT_SHADE, M("TP_WBALANCE_SHADE"), 7600, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Water 1" , WBT_WATER, M("TP_WBALANCE_WATER1"), 35000, 0.3f, 1.1f)); - wbEntries.push_back(new WBEntry("Water 2" , WBT_WATER, M("TP_WBALANCE_WATER2"), 48000, 0.63f, 1.38f)); - wbEntries.push_back(new WBEntry("Tungsten" , WBT_TUNGSTEN, M("TP_WBALANCE_TUNGSTEN"), 2856, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F1" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO1"), 6430, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F2" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO2"), 4230, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F3" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO3"), 3450, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F4" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO4"), 2940, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F5" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO5"), 6350, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F6" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO6"), 4150, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F7" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO7"), 6500, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F8" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO8"), 5020, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F9" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO9"), 4330, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F10" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO10"), 5300, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F11" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO11"), 4000, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F12" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO12"), 3000, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("HMI Lamp" , WBT_LAMP, M("TP_WBALANCE_HMI"), 4800, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("GTI Lamp" , WBT_LAMP, M("TP_WBALANCE_GTI"), 5000, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("JudgeIII Lamp" , WBT_LAMP, M("TP_WBALANCE_JUDGEIII"), 5100, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Solux Lamp 3500K" , WBT_LAMP, M("TP_WBALANCE_SOLUX35"), 3480, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Solux Lamp 4100K" , WBT_LAMP, M("TP_WBALANCE_SOLUX41"), 3930, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Solux Lamp 4700K" , WBT_LAMP, M("TP_WBALANCE_SOLUX47"), 4700, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("NG Solux Lamp 4700K" , WBT_LAMP, M("TP_WBALANCE_SOLUX47_NG"), 4480, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("LED LSI Lumelex 2040", WBT_LED, M("TP_WBALANCE_LED_LSI"), 2970, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("LED CRS SP12 WWMR16" , WBT_LED, M("TP_WBALANCE_LED_CRS"), 3050, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Flash 5500K" , WBT_FLASH, M("TP_WBALANCE_FLASH55"), 5500, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Flash 6000K" , WBT_FLASH, M("TP_WBALANCE_FLASH60"), 6000, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Flash 6500K" , WBT_FLASH, M("TP_WBALANCE_FLASH65"), 6500, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Camera" , WBT_CAMERA, M("TP_WBALANCE_CAMERA"), 0, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Auto" , WBT_AUTO, M("TP_WBALANCE_AUTO"), 0, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Daylight" , WBT_DAYLIGHT, M("TP_WBALANCE_DAYLIGHT"), 5300, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Cloudy" , WBT_CLOUDY, M("TP_WBALANCE_CLOUDY"), 6200, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Shade" , WBT_SHADE, M("TP_WBALANCE_SHADE"), 7600, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Water 1" , WBT_WATER, M("TP_WBALANCE_WATER1"), 35000, 0.3f, 1.1f, 0.f)); + wbEntries.push_back(new WBEntry("Water 2" , WBT_WATER, M("TP_WBALANCE_WATER2"), 48000, 0.63f, 1.38f, 0.f)); + wbEntries.push_back(new WBEntry("Tungsten" , WBT_TUNGSTEN, M("TP_WBALANCE_TUNGSTEN"), 2856, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Fluo F1" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO1"), 6430, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Fluo F2" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO2"), 4230, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Fluo F3" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO3"), 3450, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Fluo F4" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO4"), 2940, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Fluo F5" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO5"), 6350, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Fluo F6" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO6"), 4150, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Fluo F7" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO7"), 6500, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Fluo F8" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO8"), 5020, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Fluo F9" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO9"), 4330, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Fluo F10" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO10"), 5300, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Fluo F11" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO11"), 4000, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Fluo F12" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO12"), 3000, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("HMI Lamp" , WBT_LAMP, M("TP_WBALANCE_HMI"), 4800, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("GTI Lamp" , WBT_LAMP, M("TP_WBALANCE_GTI"), 5000, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("JudgeIII Lamp" , WBT_LAMP, M("TP_WBALANCE_JUDGEIII"), 5100, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Solux Lamp 3500K" , WBT_LAMP, M("TP_WBALANCE_SOLUX35"), 3480, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Solux Lamp 4100K" , WBT_LAMP, M("TP_WBALANCE_SOLUX41"), 3930, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Solux Lamp 4700K" , WBT_LAMP, M("TP_WBALANCE_SOLUX47"), 4700, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("NG Solux Lamp 4700K" , WBT_LAMP, M("TP_WBALANCE_SOLUX47_NG"), 4480, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("LED LSI Lumelex 2040", WBT_LED, M("TP_WBALANCE_LED_LSI"), 2970, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("LED CRS SP12 WWMR16" , WBT_LED, M("TP_WBALANCE_LED_CRS"), 3050, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Flash 5500K" , WBT_FLASH, M("TP_WBALANCE_FLASH55"), 5500, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Flash 6000K" , WBT_FLASH, M("TP_WBALANCE_FLASH60"), 6000, 1.f, 1.f, 0.f)); + wbEntries.push_back(new WBEntry("Flash 6500K" , WBT_FLASH, M("TP_WBALANCE_FLASH65"), 6500, 1.f, 1.f, 0.f)); // Should remain the last one - wbEntries.push_back(new WBEntry("Custom" , WBT_CUSTOM, M("TP_WBALANCE_CUSTOM"), 0, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Custom" , WBT_CUSTOM, M("TP_WBALANCE_CUSTOM"), 0, 1.f, 1.f, 0.f)); } void WBParams::cleanup() @@ -875,10 +875,41 @@ void CoarseTransformParams::setDefaults() hflip = false; vflip = false; } +void RAWParams::BayerSensor::setPixelShiftDefaults() +{ + pixelShiftMotion = 0; + pixelShiftMotionCorrection = RAWParams::BayerSensor::Grid3x3New; + pixelShiftMotionCorrectionMethod = RAWParams::BayerSensor::Automatic; + pixelShiftStddevFactorGreen = 5.0; + pixelShiftStddevFactorRed = 5.0; + pixelShiftStddevFactorBlue = 5.0; + pixelShiftEperIso = 0.0; + pixelShiftNreadIso = 0.0; + pixelShiftPrnu = 1.0; + pixelShiftSigma = 1.0; + pixelShiftSum = 3.0; + pixelShiftRedBlueWeight = 0.7; + pixelShiftAutomatic = true; + pixelShiftNonGreenHorizontal = false; + pixelShiftNonGreenVertical = false; + pixelShiftHoleFill = true; + pixelShiftMedian = false; + pixelShiftMedian3 = false; + pixelShiftGreen = true; + pixelShiftBlur = true; + pixelShiftSmoothFactor = 0.7; + pixelShiftExp0 = false; + pixelShiftLmmse = false; + pixelShiftEqualBright = false; + pixelShiftNonGreenCross = true; + pixelShiftNonGreenCross2 = false; + pixelShiftNonGreenAmaze = false; +} void RAWParams::setDefaults() { bayersensor.method = RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::amaze]; + bayersensor.imageNum = 0; bayersensor.ccSteps = 0; bayersensor.dcb_iterations = 2; bayersensor.dcb_enhance = true; @@ -913,6 +944,10 @@ void RAWParams::setDefaults() hotPixelFilter = false; deadPixelFilter = false; hotdeadpix_thresh = 100; + bayersensor.setPixelShiftDefaults(); + bayersensor.pixelshiftShowMotion = false; + bayersensor.pixelshiftShowMotionMaskOnly = false; + } void ColorManagementParams::setDefaults() @@ -1059,6 +1094,7 @@ void ProcParams::setDefaults () wb.temperature = 6504; wb.green = 1.0; wb.equal = 1.0; + wb.tempBias = 0.0; colorappearance.enabled = false; colorappearance.degree = 90; colorappearance.autodegree = true; @@ -1985,6 +2021,10 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b keyFile.set_double ("White Balance", "Equal", wb.equal); } + if (!pedited || pedited->wb.tempBias) { + keyFile.set_double ("White Balance", "TemperatureBias", wb.tempBias); + } + /* // save colorShift if (!pedited || pedited->colorShift.a) keyFile.set_double ("Color Shift", "ChannelA", colorShift.a); @@ -3315,6 +3355,10 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b keyFile.set_string ("RAW Bayer", "Method", raw.bayersensor.method ); } + if (!pedited || pedited->raw.bayersensor.imageNum) { + keyFile.set_integer ("RAW Bayer", "ImageNum", raw.bayersensor.imageNum + 1 ); + } + if (!pedited || pedited->raw.bayersensor.ccSteps) { keyFile.set_integer ("RAW Bayer", "CcSteps", raw.bayersensor.ccSteps); } @@ -3359,7 +3403,121 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b keyFile.set_integer ("RAW Bayer", "LMMSEIterations", raw.bayersensor.lmmse_iterations ); } - //if (!pedited || pedited->raw.bayersensor.allEnhance) keyFile.set_boolean ("RAW Bayer", "ALLEnhance", raw.bayersensor.all_enhance ); + if (!pedited || pedited->raw.bayersensor.pixelShiftMotion) { + keyFile.set_integer ("RAW Bayer", "PixelShiftMotion", raw.bayersensor.pixelShiftMotion ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftMotionCorrection) { + keyFile.set_integer ("RAW Bayer", "PixelShiftMotionCorrection", raw.bayersensor.pixelShiftMotionCorrection ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod) { + keyFile.set_integer ("RAW Bayer", "PixelShiftMotionCorrectionMethod", raw.bayersensor.pixelShiftMotionCorrectionMethod ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftStddevFactorGreen) { + keyFile.set_double ("RAW Bayer", "pixelShiftStddevFactorGreen", raw.bayersensor.pixelShiftStddevFactorGreen ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftStddevFactorRed) { + keyFile.set_double ("RAW Bayer", "pixelShiftStddevFactorRed", raw.bayersensor.pixelShiftStddevFactorRed ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftStddevFactorBlue) { + keyFile.set_double ("RAW Bayer", "pixelShiftStddevFactorBlue", raw.bayersensor.pixelShiftStddevFactorBlue ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftEperIso) { + keyFile.set_double ("RAW Bayer", "PixelShiftEperIso", raw.bayersensor.pixelShiftEperIso ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftNreadIso) { + keyFile.set_double ("RAW Bayer", "PixelShiftNreadIso", raw.bayersensor.pixelShiftNreadIso ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftPrnu) { + keyFile.set_double ("RAW Bayer", "PixelShiftPrnu", raw.bayersensor.pixelShiftPrnu ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftSigma) { + keyFile.set_double ("RAW Bayer", "PixelShiftSigma", raw.bayersensor.pixelShiftSigma ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftSum) { + keyFile.set_double ("RAW Bayer", "PixelShiftSum", raw.bayersensor.pixelShiftSum ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftRedBlueWeight) { + keyFile.set_double ("RAW Bayer", "PixelShiftRedBlueWeight", raw.bayersensor.pixelShiftRedBlueWeight ); + } + + if (!pedited || pedited->raw.bayersensor.pixelshiftShowMotion) { + keyFile.set_boolean ("RAW Bayer", "PixelShiftShowMotion", raw.bayersensor.pixelshiftShowMotion ); + } + + if (!pedited || pedited->raw.bayersensor.pixelshiftShowMotionMaskOnly) { + keyFile.set_boolean ("RAW Bayer", "PixelShiftShowMotionMaskOnly", raw.bayersensor.pixelshiftShowMotionMaskOnly ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftAutomatic) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftAutomatic", raw.bayersensor.pixelShiftAutomatic ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftNonGreenHorizontal) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftNonGreenHorizontal", raw.bayersensor.pixelShiftNonGreenHorizontal ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftNonGreenVertical) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftNonGreenVertical", raw.bayersensor.pixelShiftNonGreenVertical ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftHoleFill) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftHoleFill", raw.bayersensor.pixelShiftHoleFill ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftMedian) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftMedian", raw.bayersensor.pixelShiftMedian ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftMedian3) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftMedian3", raw.bayersensor.pixelShiftMedian3 ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftGreen) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftGreen", raw.bayersensor.pixelShiftGreen ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftBlur) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftBlur", raw.bayersensor.pixelShiftBlur ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftSmooth) { + keyFile.set_double ("RAW Bayer", "pixelShiftSmoothFactor", raw.bayersensor.pixelShiftSmoothFactor ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftExp0) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftExp0", raw.bayersensor.pixelShiftExp0 ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftLmmse) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftLmmse", raw.bayersensor.pixelShiftLmmse ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftEqualBright) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftEqualBright", raw.bayersensor.pixelShiftEqualBright ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftNonGreenCross) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftNonGreenCross", raw.bayersensor.pixelShiftNonGreenCross ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftNonGreenCross2) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftNonGreenCross2", raw.bayersensor.pixelShiftNonGreenCross2 ); + } + + if (!pedited || pedited->raw.bayersensor.pixelShiftNonGreenAmaze) { + keyFile.set_boolean ("RAW Bayer", "pixelShiftNonGreenAmaze", raw.bayersensor.pixelShiftNonGreenAmaze ); + } if (!pedited || pedited->raw.xtranssensor.method) { keyFile.set_string ("RAW X-Trans", "Method", raw.xtranssensor.method ); @@ -4664,6 +4822,14 @@ int ProcParams::load (const Glib::ustring &fname, ParamsEdited* pedited) pedited->wb.equal = true; } } + + if (keyFile.has_key ("White Balance", "TemperatureBias")) { + wb.tempBias = keyFile.get_double ("White Balance", "TemperatureBias"); + + if (pedited) { + pedited->wb.tempBias = true; + } + } } // load colorShift @@ -7321,6 +7487,14 @@ int ProcParams::load (const Glib::ustring &fname, ParamsEdited* pedited) } } + if (keyFile.has_key ("RAW Bayer", "ImageNum")) { + raw.bayersensor.imageNum = keyFile.get_integer ("RAW Bayer", "ImageNum") - 1; + + if (pedited) { + pedited->raw.bayersensor.imageNum = true; + } + } + if (keyFile.has_key ("RAW Bayer", "CcSteps")) { raw.bayersensor.ccSteps = keyFile.get_integer ("RAW Bayer", "CcSteps"); @@ -7409,7 +7583,237 @@ int ProcParams::load (const Glib::ustring &fname, ParamsEdited* pedited) } } - //if (keyFile.has_key ("RAW Bayer", "ALLEnhance")) { raw.bayersensor.all_enhance = keyFile.get_boolean("RAW Bayer", "ALLEnhance"); if (pedited) pedited->raw.bayersensor.allEnhance = true; } + if (keyFile.has_key ("RAW Bayer", "PixelShiftMotion")) { + raw.bayersensor.pixelShiftMotion = keyFile.get_integer("RAW Bayer", "PixelShiftMotion"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftMotion = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PixelShiftMotionCorrection")) { + raw.bayersensor.pixelShiftMotionCorrection = (RAWParams::BayerSensor::ePSMotionCorrection)keyFile.get_integer("RAW Bayer", "PixelShiftMotionCorrection"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftMotionCorrection = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PixelShiftMotionCorrectionMethod")) { + raw.bayersensor.pixelShiftMotionCorrectionMethod = (RAWParams::BayerSensor::ePSMotionCorrectionMethod)keyFile.get_integer("RAW Bayer", "PixelShiftMotionCorrectionMethod"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftStddevFactorGreen")) { + raw.bayersensor.pixelShiftStddevFactorGreen = keyFile.get_double("RAW Bayer", "pixelShiftStddevFactorGreen"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftStddevFactorGreen = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftStddevFactorRed")) { + raw.bayersensor.pixelShiftStddevFactorRed = keyFile.get_double("RAW Bayer", "pixelShiftStddevFactorRed"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftStddevFactorRed = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftStddevFactorBlue")) { + raw.bayersensor.pixelShiftStddevFactorBlue = keyFile.get_double("RAW Bayer", "pixelShiftStddevFactorBlue"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftStddevFactorBlue = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PixelShiftEperIso")) { + raw.bayersensor.pixelShiftEperIso = keyFile.get_double("RAW Bayer", "PixelShiftEperIso"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftEperIso = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PixelShiftNreadIso")) { + raw.bayersensor.pixelShiftNreadIso = keyFile.get_double("RAW Bayer", "PixelShiftNreadIso"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftNreadIso = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PixelShiftPrnu")) { + raw.bayersensor.pixelShiftPrnu = keyFile.get_double("RAW Bayer", "PixelShiftPrnu"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftPrnu = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PixelShiftSigma")) { + raw.bayersensor.pixelShiftSigma = keyFile.get_double("RAW Bayer", "PixelShiftSigma"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftSigma = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PixelShiftSum")) { + raw.bayersensor.pixelShiftSum = keyFile.get_double("RAW Bayer", "PixelShiftSum"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftSum = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PixelShiftRedBlueWeight")) { + raw.bayersensor.pixelShiftRedBlueWeight = keyFile.get_double("RAW Bayer", "PixelShiftRedBlueWeight"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftRedBlueWeight = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PixelShiftShowMotion")) { + raw.bayersensor.pixelshiftShowMotion = keyFile.get_boolean("RAW Bayer", "PixelShiftShowMotion"); + + if (pedited) { + pedited->raw.bayersensor.pixelshiftShowMotion = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PixelShiftShowMotionMaskOnly")) { + raw.bayersensor.pixelshiftShowMotionMaskOnly = keyFile.get_boolean("RAW Bayer", "PixelShiftShowMotionMaskOnly"); + + if (pedited) { + pedited->raw.bayersensor.pixelshiftShowMotionMaskOnly = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftAutomatic")) { + raw.bayersensor.pixelShiftAutomatic = keyFile.get_boolean("RAW Bayer", "pixelShiftAutomatic"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftAutomatic = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftNonGreenHorizontal")) { + raw.bayersensor.pixelShiftNonGreenHorizontal = keyFile.get_boolean("RAW Bayer", "pixelShiftNonGreenHorizontal"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftNonGreenHorizontal = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftNonGreenVertical")) { + raw.bayersensor.pixelShiftNonGreenVertical = keyFile.get_boolean("RAW Bayer", "pixelShiftNonGreenVertical"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftNonGreenVertical = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftHoleFill")) { + raw.bayersensor.pixelShiftHoleFill = keyFile.get_boolean("RAW Bayer", "pixelShiftHoleFill"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftHoleFill = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftMedian")) { + raw.bayersensor.pixelShiftMedian = keyFile.get_boolean("RAW Bayer", "pixelShiftMedian"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftMedian = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftMedian3")) { + raw.bayersensor.pixelShiftMedian3 = keyFile.get_boolean("RAW Bayer", "pixelShiftMedian3"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftMedian3 = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftGreen")) { + raw.bayersensor.pixelShiftGreen = keyFile.get_boolean("RAW Bayer", "pixelShiftGreen"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftGreen = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftBlur")) { + raw.bayersensor.pixelShiftBlur = keyFile.get_boolean("RAW Bayer", "pixelShiftBlur"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftBlur = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftSmoothFactor")) { + raw.bayersensor.pixelShiftSmoothFactor = keyFile.get_double("RAW Bayer", "pixelShiftSmoothFactor"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftSmooth = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftExp0")) { + raw.bayersensor.pixelShiftExp0 = keyFile.get_boolean("RAW Bayer", "pixelShiftExp0"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftExp0 = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftLmmse")) { + raw.bayersensor.pixelShiftLmmse = keyFile.get_boolean("RAW Bayer", "pixelShiftLmmse"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftLmmse = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftEqualBright")) { + raw.bayersensor.pixelShiftEqualBright = keyFile.get_boolean("RAW Bayer", "pixelShiftEqualBright"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftEqualBright = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftNonGreenCross")) { + raw.bayersensor.pixelShiftNonGreenCross = keyFile.get_boolean("RAW Bayer", "pixelShiftNonGreenCross"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftNonGreenCross = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftNonGreenCross2")) { + raw.bayersensor.pixelShiftNonGreenCross2 = keyFile.get_boolean("RAW Bayer", "pixelShiftNonGreenCross2"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftNonGreenCross2 = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "pixelShiftNonGreenAmaze")) { + raw.bayersensor.pixelShiftNonGreenAmaze = keyFile.get_boolean("RAW Bayer", "pixelShiftNonGreenAmaze"); + + if (pedited) { + pedited->raw.bayersensor.pixelShiftNonGreenAmaze = true; + } + } } // load X-Trans sensors' raw settings @@ -7837,6 +8241,7 @@ bool ProcParams::operator== (const ProcParams& other) && resize.width == other.resize.width && resize.height == other.resize.height && raw.bayersensor.method == other.raw.bayersensor.method + && raw.bayersensor.imageNum == other.raw.bayersensor.imageNum && raw.bayersensor.ccSteps == other.raw.bayersensor.ccSteps && raw.bayersensor.black0 == other.raw.bayersensor.black0 && raw.bayersensor.black1 == other.raw.bayersensor.black1 @@ -7845,8 +8250,38 @@ bool ProcParams::operator== (const ProcParams& other) && raw.bayersensor.twogreen == other.raw.bayersensor.twogreen && raw.bayersensor.greenthresh == other.raw.bayersensor.greenthresh && raw.bayersensor.linenoise == other.raw.bayersensor.linenoise - && raw.bayersensor.dcb_enhance == other.raw.bayersensor.dcb_enhance && raw.bayersensor.dcb_iterations == other.raw.bayersensor.dcb_iterations + && raw.bayersensor.lmmse_iterations == other.raw.bayersensor.lmmse_iterations + && raw.bayersensor.pixelShiftMotion == other.raw.bayersensor.pixelShiftMotion + && raw.bayersensor.pixelShiftMotionCorrection == other.raw.bayersensor.pixelShiftMotionCorrection + && raw.bayersensor.pixelShiftMotionCorrectionMethod == other.raw.bayersensor.pixelShiftMotionCorrectionMethod + && raw.bayersensor.pixelShiftStddevFactorGreen == other.raw.bayersensor.pixelShiftStddevFactorGreen + && raw.bayersensor.pixelShiftStddevFactorRed == other.raw.bayersensor.pixelShiftStddevFactorRed + && raw.bayersensor.pixelShiftStddevFactorBlue == other.raw.bayersensor.pixelShiftStddevFactorBlue + && raw.bayersensor.pixelShiftEperIso == other.raw.bayersensor.pixelShiftEperIso + && raw.bayersensor.pixelShiftNreadIso == other.raw.bayersensor.pixelShiftNreadIso + && raw.bayersensor.pixelShiftPrnu == other.raw.bayersensor.pixelShiftPrnu + && raw.bayersensor.pixelShiftSigma == other.raw.bayersensor.pixelShiftSigma + && raw.bayersensor.pixelShiftSum == other.raw.bayersensor.pixelShiftSum + && raw.bayersensor.pixelShiftRedBlueWeight == other.raw.bayersensor.pixelShiftRedBlueWeight + && raw.bayersensor.pixelshiftShowMotion == other.raw.bayersensor.pixelshiftShowMotion + && raw.bayersensor.pixelshiftShowMotionMaskOnly == other.raw.bayersensor.pixelshiftShowMotionMaskOnly + && raw.bayersensor.pixelShiftAutomatic == other.raw.bayersensor.pixelShiftAutomatic + && raw.bayersensor.pixelShiftNonGreenHorizontal == other.raw.bayersensor.pixelShiftNonGreenHorizontal + && raw.bayersensor.pixelShiftNonGreenVertical == other.raw.bayersensor.pixelShiftNonGreenVertical + && raw.bayersensor.pixelShiftHoleFill == other.raw.bayersensor.pixelShiftHoleFill + && raw.bayersensor.pixelShiftMedian == other.raw.bayersensor.pixelShiftMedian + && raw.bayersensor.pixelShiftMedian3 == other.raw.bayersensor.pixelShiftMedian3 + && raw.bayersensor.pixelShiftGreen == other.raw.bayersensor.pixelShiftGreen + && raw.bayersensor.pixelShiftBlur == other.raw.bayersensor.pixelShiftBlur + && raw.bayersensor.pixelShiftSmoothFactor == other.raw.bayersensor.pixelShiftSmoothFactor + && raw.bayersensor.pixelShiftExp0 == other.raw.bayersensor.pixelShiftExp0 + && raw.bayersensor.pixelShiftLmmse == other.raw.bayersensor.pixelShiftLmmse + && raw.bayersensor.pixelShiftEqualBright == other.raw.bayersensor.pixelShiftEqualBright + && raw.bayersensor.pixelShiftNonGreenCross == other.raw.bayersensor.pixelShiftNonGreenCross + && raw.bayersensor.pixelShiftNonGreenCross2 == other.raw.bayersensor.pixelShiftNonGreenCross2 + && raw.bayersensor.pixelShiftNonGreenAmaze == other.raw.bayersensor.pixelShiftNonGreenAmaze + && raw.bayersensor.dcb_enhance == other.raw.bayersensor.dcb_enhance && raw.xtranssensor.method == other.raw.xtranssensor.method && raw.xtranssensor.ccSteps == other.raw.xtranssensor.ccSteps && raw.xtranssensor.blackred == other.raw.xtranssensor.blackred @@ -8066,6 +8501,8 @@ int PartialProfile::load (const Glib::ustring &fName) if (fName == DEFPROFILE_INTERNAL) { return 0; + } else if (fName == DEFPROFILE_DYNAMIC) { + return -1; // should not happen here } else { return pparams->load(fName, pedited); } diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 7c2d71aaa..c83856870 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -546,8 +546,9 @@ public: int temperature; double green; double equal; + double tempBias; - WBEntry(const Glib::ustring &p, enum WBTypes t, const Glib::ustring &l, int temp, double green, double equal) : ppLabel(p), type(t), GUILabel(l), temperature(temp), green(green), equal(equal) {}; + WBEntry(const Glib::ustring &p, enum WBTypes t, const Glib::ustring &l, int temp, double green, double equal, double bias) : ppLabel(p), type(t), GUILabel(l), temperature(temp), green(green), equal(equal), tempBias(bias) {}; }; class WBParams @@ -559,6 +560,7 @@ public: int temperature; double green; double equal; + double tempBias; static void init(); static void cleanup(); @@ -1184,12 +1186,19 @@ public: public: //enum eMethod{ eahd,hphd,vng4,dcb,amaze,ahd,IGV_noise,fast, //numMethods }; // This MUST be the last enum - enum eMethod { amaze, igv, lmmse, eahd, hphd, vng4, dcb, ahd, fast, mono, none, + enum eMethod { amaze, igv, lmmse, eahd, hphd, vng4, dcb, ahd, fast, mono, none, pixelshift, numMethods }; // This MUST be the last enum + enum ePSMotionCorrection { + Grid1x1, Grid1x2, Grid3x3, Grid5x5, Grid7x7, Grid3x3New + }; + enum ePSMotionCorrectionMethod { + Off, Automatic, Custom + }; static const char *methodstring[numMethods]; Glib::ustring method; + int imageNum; int ccSteps; double black0; double black1; @@ -1200,8 +1209,40 @@ public: int greenthresh; int dcb_iterations; int lmmse_iterations; + int pixelShiftMotion; + ePSMotionCorrection pixelShiftMotionCorrection; + ePSMotionCorrectionMethod pixelShiftMotionCorrectionMethod; + double pixelShiftStddevFactorGreen; + double pixelShiftStddevFactorRed; + double pixelShiftStddevFactorBlue; + double pixelShiftEperIso; + double pixelShiftNreadIso; + double pixelShiftPrnu; + double pixelShiftSigma; + double pixelShiftSum; + double pixelShiftRedBlueWeight; + bool pixelshiftShowMotion; + bool pixelshiftShowMotionMaskOnly; + bool pixelShiftAutomatic; + bool pixelShiftNonGreenHorizontal; + bool pixelShiftNonGreenVertical; + bool pixelShiftHoleFill; + bool pixelShiftMedian; + bool pixelShiftMedian3; + bool pixelShiftGreen; + bool pixelShiftBlur; + double pixelShiftSmoothFactor; + bool pixelShiftExp0; + bool pixelShiftLmmse; + bool pixelShiftEqualBright; + bool pixelShiftNonGreenCross; + bool pixelShiftNonGreenCross2; + bool pixelShiftNonGreenAmaze; bool dcb_enhance; //bool all_enhance; + + void setPixelShiftDefaults(); + }; /** diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index bfe7092f2..2cd1abf5f 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -4,16 +4,18 @@ * Created on: 20/nov/2010 */ -#include "rawimage.h" -#include "settings.h" -#include "camconst.h" -#include "utils.h" +#include #ifdef WIN32 #include #else #include #endif +#include "rawimage.h" +#include "settings.h" +#include "camconst.h" +#include "utils.h" + namespace rtengine { @@ -398,7 +400,7 @@ skip_block: } } -int RawImage::loadRaw (bool loadData, bool closeFile, ProgressListener *plistener, double progressRange) +int RawImage::loadRaw (bool loadData, unsigned int imageNum, bool closeFile, ProgressListener *plistener, double progressRange) { ifname = filename.c_str(); image = nullptr; @@ -422,7 +424,12 @@ int RawImage::loadRaw (bool loadData, bool closeFile, ProgressListener *plistene raw_image = nullptr; //***************** Read ALL raw file info - identify (); + // set the number of the frame to extract. If the number is larger then number of existing frames - 1, dcraw will handle that correctly + + shot_select = imageNum; + identify(); + // in case dcraw didn't handle the above mentioned case... + shot_select = std::min(shot_select, std::max(is_raw, 1u) - 1); if (!is_raw) { fclose(ifp); @@ -435,9 +442,9 @@ int RawImage::loadRaw (bool loadData, bool closeFile, ProgressListener *plistene return 2; } - if(xtransCompressed) { - parse_xtrans_header(); - } + if(!strcmp(make,"Fujifilm") && raw_height * raw_width * 2 != raw_size) { + parse_fuji_compressed_header(); + } if (flip == 5) { this->rotate_deg = 270; @@ -658,7 +665,7 @@ int RawImage::loadRaw (bool loadData, bool closeFile, ProgressListener *plistene return 0; } -float** RawImage::compress_image() +float** RawImage::compress_image(int frameNum) { if( !image ) { return nullptr; @@ -666,11 +673,12 @@ float** RawImage::compress_image() if (isBayer() || isXtrans()) { if (!allocation) { - allocation = new float[height * width]; + // shift the beginning of all frames but the first by 32 floats to avoid cache miss conflicts on CPUs which have <= 4-way associative L1-Cache + allocation = new float[height * width + frameNum * 32]; data = new float*[height]; for (int i = 0; i < height; i++) { - data[i] = allocation + i * width; + data[i] = allocation + i * width + frameNum * 32; } } } else if (colors == 1) { diff --git a/rtengine/rawimage.h b/rtengine/rawimage.h index 804a2a346..3f4307054 100644 --- a/rtengine/rawimage.h +++ b/rtengine/rawimage.h @@ -106,7 +106,7 @@ public: explicit RawImage( const Glib::ustring &name ); ~RawImage(); - int loadRaw (bool loadData = true, bool closeFile = true, ProgressListener *plistener = nullptr, double progressRange = 1.0); + int loadRaw (bool loadData, unsigned int imageNum = 0, bool closeFile = true, ProgressListener *plistener = nullptr, double progressRange = 1.0); void get_colorsCoeff( float* pre_mul_, float* scale_mul_, float* cblack_, bool forceAutoWB ); void set_prefilters() { @@ -119,9 +119,10 @@ public: { return image; } - float** compress_image(); // revert to compressed pixels format and release image data + float** compress_image(int frameNum); // revert to compressed pixels format and release image data float** data; // holds pixel values, data[i][j] corresponds to the ith row and jth column unsigned prefilters; // original filters saved ( used for 4 color processing ) + unsigned int getFrameCount() const { return is_raw; } protected: Glib::ustring filename; // complete filename int rotate_deg; // 0,90,180,270 degree of rotation: info taken by dcraw from exif diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 80e1f65ba..4370befbb 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -37,7 +37,7 @@ #include #endif #include "opthelper.h" -//#define BENCHMARK +#define BENCHMARK #include "StopWatch.h" #define clipretinex( val, minv, maxv ) (( val = (val < minv ? minv : val ) ) > maxv ? maxv : val ) #undef CLIPD @@ -101,10 +101,10 @@ void transLineFuji (const float* const red, const float* const green, const floa int y = i + j - fw; int x = fw - i + j; - if (x >= 0 && y < image->height && y >= 0 && x < image->width) { - image->r(image->height - 1 - y, image->width - 1 - x) = red[j]; - image->g(image->height - 1 - y, image->width - 1 - x) = green[j]; - image->b(image->height - 1 - y, image->width - 1 - x) = blue[j]; + if (x >= 0 && y < image->getHeight() && y >= 0 && x < image->getWidth()) { + image->r(image->getHeight() - 1 - y, image->getWidth() - 1 - x) = red[j]; + image->g(image->getHeight() - 1 - y, image->getWidth() - 1 - x) = green[j]; + image->b(image->getHeight() - 1 - y, image->getWidth() - 1 - x) = blue[j]; } } @@ -115,10 +115,10 @@ void transLineFuji (const float* const red, const float* const green, const floa int y = i + j - fw; int x = fw - i + j; - if (x >= 0 && x < image->height && y >= 0 && y < image->width) { - image->r(image->height - 1 - x, y) = red[j]; - image->g(image->height - 1 - x, y) = green[j]; - image->b(image->height - 1 - x, y) = blue[j]; + if (x >= 0 && x < image->getHeight() && y >= 0 && y < image->getWidth()) { + image->r(image->getHeight() - 1 - x, y) = red[j]; + image->g(image->getHeight() - 1 - x, y) = green[j]; + image->b(image->getHeight() - 1 - x, y) = blue[j]; } } @@ -129,10 +129,10 @@ void transLineFuji (const float* const red, const float* const green, const floa int y = i + j - fw; int x = fw - i + j; - if (x >= 0 && y < image->width && y >= 0 && x < image->height) { - image->r(x, image->width - 1 - y) = red[j]; - image->g(x, image->width - 1 - y) = green[j]; - image->b(x, image->width - 1 - y) = blue[j]; + if (x >= 0 && y < image->getWidth() && y >= 0 && x < image->getHeight()) { + image->r(x, image->getWidth() - 1 - y) = red[j]; + image->g(x, image->getWidth() - 1 - y) = green[j]; + image->b(x, image->getWidth() - 1 - y) = blue[j]; } } @@ -144,7 +144,7 @@ void transLineFuji (const float* const red, const float* const green, const floa int y = i + j - fw; int x = fw - i + j; - if (x >= 0 && y < image->height && y >= 0 && x < image->width) { + if (x >= 0 && y < image->getHeight() && y >= 0 && x < image->getWidth()) { image->r(y, x) = red[j]; image->g(y, x) = green[j]; image->b(y, x) = blue[j]; @@ -475,8 +475,12 @@ RawImageSource::~RawImageSource () delete idata; - if (ri) { - delete ri; + for(size_t i = 0; i < numFrames; ++i) { + delete riFrames[i]; + } + + for(size_t i = 0; i < numFrames - 1; ++i) { + delete rawDataBuffer[i]; } flushRGB(); @@ -499,17 +503,18 @@ RawImageSource::~RawImageSource () void RawImageSource::transformRect (PreviewProps pp, int tran, int &ssx1, int &ssy1, int &width, int &height, int &fw) { - - pp.x += border; - pp.y += border; + int pp_x = pp.getX() + border; + int pp_y = pp.getY() + border; + int pp_width = pp.getWidth(); + int pp_height = pp.getHeight(); if (d1x) { if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { - pp.x /= 2; - pp.w = pp.w / 2 + 1; + pp_x /= 2; + pp_width = pp_width / 2 + 1; } else { - pp.y /= 2; - pp.h = pp.h / 2 + 1; + pp_y /= 2; + pp_height = pp_height / 2 + 1; } } @@ -527,44 +532,44 @@ void RawImageSource::transformRect (PreviewProps pp, int tran, int &ssx1, int &s sh = w; } - if( pp.w > sw - 2 * border) { - pp.w = sw - 2 * border; + if( pp_width > sw - 2 * border) { + pp_width = sw - 2 * border; } - if( pp.h > sh - 2 * border) { - pp.h = sh - 2 * border; + if( pp_height > sh - 2 * border) { + pp_height = sh - 2 * border; } - int ppx = pp.x, ppy = pp.y; + int ppx = pp_x, ppy = pp_y; if (tran & TR_HFLIP) { - ppx = sw - pp.x - pp.w; + ppx = sw - pp_x - pp_width; } if (tran & TR_VFLIP) { - ppy = sh - pp.y - pp.h; + ppy = sh - pp_y - pp_height; } int sx1 = ppx; // assuming it's >=0 int sy1 = ppy; // assuming it's >=0 - int sx2 = max(ppx + pp.w, w - 1); - int sy2 = max(ppy + pp.h, h - 1); + int sx2 = max(ppx + pp_width, w - 1); + int sy2 = max(ppy + pp_height, h - 1); if ((tran & TR_ROT) == TR_R180) { - sx1 = max(w - ppx - pp.w, 0); - sy1 = max(h - ppy - pp.h, 0); - sx2 = min(sx1 + pp.w, w - 1); - sy2 = min(sy1 + pp.h, h - 1); + sx1 = max(w - ppx - pp_width, 0); + sy1 = max(h - ppy - pp_height, 0); + sx2 = min(sx1 + pp_width, w - 1); + sy2 = min(sy1 + pp_height, h - 1); } else if ((tran & TR_ROT) == TR_R90) { sx1 = ppy; - sy1 = max(h - ppx - pp.w, 0); - sx2 = min(sx1 + pp.h, w - 1); - sy2 = min(sy1 + pp.w, h - 1); + sy1 = max(h - ppx - pp_width, 0); + sx2 = min(sx1 + pp_height, w - 1); + sy2 = min(sy1 + pp_width, h - 1); } else if ((tran & TR_ROT) == TR_R270) { - sx1 = max(w - ppy - pp.h, 0); + sx1 = max(w - ppy - pp_height, 0); sy1 = ppx; - sx2 = min(sx1 + pp.h, w - 1); - sy2 = min(sy1 + pp.w, h - 1); + sx2 = min(sx1 + pp_height, w - 1); + sy2 = min(sy1 + pp_width, h - 1); } if (fuji) { @@ -574,14 +579,14 @@ void RawImageSource::transformRect (PreviewProps pp, int tran, int &ssx1, int &s ssy1 = (sy1 - sx2 ) / 2 + ri->get_FujiWidth(); int ssx2 = (sx2 + sy2) / 2 + 1; int ssy2 = (sy2 - sx1) / 2 + ri->get_FujiWidth(); - fw = (sx2 - sx1) / 2 / pp.skip; - width = (ssx2 - ssx1) / pp.skip + ((ssx2 - ssx1) % pp.skip > 0); - height = (ssy2 - ssy1) / pp.skip + ((ssy2 - ssy1) % pp.skip > 0); + fw = (sx2 - sx1) / 2 / pp.getSkip(); + width = (ssx2 - ssx1) / pp.getSkip() + ((ssx2 - ssx1) % pp.getSkip() > 0); + height = (ssy2 - ssy1) / pp.getSkip() + ((ssy2 - ssy1) % pp.getSkip() > 0); } else { ssx1 = sx1; ssy1 = sy1; - width = (sx2 - sx1) / pp.skip + ((sx2 - sx1) % pp.skip > 0); - height = (sy2 - sy1) / pp.skip + ((sy2 - sy1) % pp.skip > 0); + width = (sx2 - sx1) / pp.getSkip() + ((sx2 - sx1) % pp.getSkip() > 0); + height = (sy2 - sy1) / pp.getSkip() + ((sy2 - sy1) % pp.getSkip() > 0); } } @@ -674,11 +679,11 @@ void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* ima int maximwidth, maximheight; if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { - maximwidth = image->height; - maximheight = image->width; + maximwidth = image->getHeight(); + maximheight = image->getWidth(); } else { - maximwidth = image->width; - maximheight = image->height; + maximwidth = image->getWidth(); + maximheight = image->getHeight(); } if (d1x) { @@ -699,7 +704,7 @@ void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* ima imheight = maximheight; } - int maxx = this->W, maxy = this->H, skip = pp.skip; + int maxx = this->W, maxy = this->H, skip = pp.getSkip(); // raw clip levels after white balance hlmax[0] = clmax[0] * rm; @@ -818,18 +823,18 @@ void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* ima #endif if (fuji) { - int a = ((tran & TR_ROT) == TR_R90 && image->width % 2 == 0) || ((tran & TR_ROT) == TR_R180 && image->height % 2 + image->width % 2 == 1) || ((tran & TR_ROT) == TR_R270 && image->height % 2 == 0); + int a = ((tran & TR_ROT) == TR_R90 && image->getWidth() % 2 == 0) || ((tran & TR_ROT) == TR_R180 && image->getHeight() % 2 + image->getWidth() % 2 == 1) || ((tran & TR_ROT) == TR_R270 && image->getHeight() % 2 == 0); // first row - for (int j = 1 + a; j < image->width - 1; j += 2) { + for (int j = 1 + a; j < image->getWidth() - 1; j += 2) { image->r(0, j) = (image->r(1, j) + image->r(0, j + 1) + image->r(0, j - 1)) / 3; image->g(0, j) = (image->g(1, j) + image->g(0, j + 1) + image->g(0, j - 1)) / 3; image->b(0, j) = (image->b(1, j) + image->b(0, j + 1) + image->b(0, j - 1)) / 3; } // other rows - for (int i = 1; i < image->height - 1; i++) { - for (int j = 2 - (a + i + 1) % 2; j < image->width - 1; j += 2) { + for (int i = 1; i < image->getHeight() - 1; i++) { + for (int j = 2 - (a + i + 1) % 2; j < image->getWidth() - 1; j += 2) { // edge-adaptive interpolation double dh = (ABS(image->r(i, j + 1) - image->r(i, j - 1)) + ABS(image->g(i, j + 1) - image->g(i, j - 1)) + ABS(image->b(i, j + 1) - image->b(i, j - 1))) / 1.0; double dv = (ABS(image->r(i + 1, j) - image->r(i - 1, j)) + ABS(image->g(i + 1, j) - image->g(i - 1, j)) + ABS(image->b(i + 1, j) - image->b(i - 1, j))) / 1.0; @@ -848,20 +853,20 @@ void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* ima } // last pixel - if (2 - (a + i + image->width) % 2 == 2) { - image->r(i, image->width - 1) = (image->r(i + 1, image->width - 1) + image->r(i - 1, image->width - 1) + image->r(i, image->width - 2)) / 3; - image->g(i, image->width - 1) = (image->g(i + 1, image->width - 1) + image->g(i - 1, image->width - 1) + image->g(i, image->width - 2)) / 3; - image->b(i, image->width - 1) = (image->b(i + 1, image->width - 1) + image->b(i - 1, image->width - 1) + image->b(i, image->width - 2)) / 3; + if (2 - (a + i + image->getWidth()) % 2 == 2) { + image->r(i, image->getWidth() - 1) = (image->r(i + 1, image->getWidth() - 1) + image->r(i - 1, image->getWidth() - 1) + image->r(i, image->getWidth() - 2)) / 3; + image->g(i, image->getWidth() - 1) = (image->g(i + 1, image->getWidth() - 1) + image->g(i - 1, image->getWidth() - 1) + image->g(i, image->getWidth() - 2)) / 3; + image->b(i, image->getWidth() - 1) = (image->b(i + 1, image->getWidth() - 1) + image->b(i - 1, image->getWidth() - 1) + image->b(i, image->getWidth() - 2)) / 3; } } // last row - int b = (a == 1 && image->height % 2) || (a == 0 && image->height % 2 == 0); + int b = (a == 1 && image->getHeight() % 2) || (a == 0 && image->getHeight() % 2 == 0); - for (int j = 1 + b; j < image->width - 1; j += 2) { - image->r(image->height - 1, j) = (image->r(image->height - 2, j) + image->r(image->height - 1, j + 1) + image->r(image->height - 1, j - 1)) / 3; - image->g(image->height - 1, j) = (image->g(image->height - 2, j) + image->g(image->height - 1, j + 1) + image->g(image->height - 1, j - 1)) / 3; - image->b(image->height - 1, j) = (image->b(image->height - 2, j) + image->b(image->height - 1, j + 1) + image->b(image->height - 1, j - 1)) / 3; + for (int j = 1 + b; j < image->getWidth() - 1; j += 2) { + image->r(image->getHeight() - 1, j) = (image->r(image->getHeight() - 2, j) + image->r(image->getHeight() - 1, j + 1) + image->r(image->getHeight() - 1, j - 1)) / 3; + image->g(image->getHeight() - 1, j) = (image->g(image->getHeight() - 2, j) + image->g(image->getHeight() - 1, j + 1) + image->g(image->getHeight() - 1, j - 1)) / 3; + image->b(image->getHeight() - 1, j) = (image->b(image->getHeight() - 2, j) + image->b(image->getHeight() - 1, j + 1) + image->b(image->getHeight() - 1, j - 1)) / 3; } } @@ -875,7 +880,7 @@ void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* ima } // Colour correction (only when running on full resolution) - if(pp.skip == 1) { + if(pp.getSkip() == 1) { switch(ri->getSensorType()) { case ST_BAYER: processFalseColorCorrection (image, raw.bayersensor.ccSteps); @@ -915,7 +920,7 @@ void RawImageSource::convertColorSpace(Imagefloat* image, const ColorManagementP /* interpolateBadPixelsBayer: correct raw pixels looking at the bitmap * takes into consideration if there are multiple bad pixels in the neighbourhood */ -int RawImageSource::interpolateBadPixelsBayer( PixelsMap &bitmapBads ) +int RawImageSource::interpolateBadPixelsBayer( PixelsMap &bitmapBads, array2D &rawData ) { static const float eps = 1.f; int counter = 0; @@ -1475,9 +1480,8 @@ void RawImageSource::getFullSize (int& w, int& h, int tr) void RawImageSource::getSize (PreviewProps pp, int& w, int& h) { - - w = pp.w / pp.skip + (pp.w % pp.skip > 0); - h = pp.h / pp.skip + (pp.h % pp.skip > 0); + w = pp.getWidth() / pp.getSkip() + (pp.getWidth() % pp.getSkip() > 0); + h = pp.getHeight() / pp.getSkip() + (pp.getHeight() % pp.getSkip() > 0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1497,7 +1501,7 @@ void RawImageSource::vflip (Imagefloat* image) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -int RawImageSource::load (const Glib::ustring &fname, bool batch) +int RawImageSource::load (const Glib::ustring &fname, int imageNum, bool batch) { MyTime t1, t2; @@ -1508,15 +1512,59 @@ int RawImageSource::load (const Glib::ustring &fname, bool batch) plistener->setProgressStr ("Decoding..."); plistener->setProgress (0.0); } - ri = new RawImage(fname); - int errCode = ri->loadRaw (true, true, plistener, 0.8); + int errCode = ri->loadRaw (false, 0, false); if (errCode) { return errCode; } + numFrames = ri->getFrameCount(); - ri->compress_image(); + errCode = 0; + + if(numFrames > 1) { +#ifdef _OPENMP + #pragma omp parallel +#endif + { + int errCodeThr = 0; +#ifdef _OPENMP + #pragma omp for nowait +#endif + for(unsigned int i = 0; i < numFrames; ++i) { + if(i == 0) { + riFrames[i] = ri; + errCodeThr = riFrames[i]->loadRaw (true, i, true, plistener, 0.8); + } else { + riFrames[i] = new RawImage(fname); + errCodeThr = riFrames[i]->loadRaw (true, i); + } + } +#ifdef _OPENMP + #pragma omp critical +#endif + { + errCode = errCodeThr ? errCodeThr : errCode; + } + } + } else { + riFrames[0] = ri; + errCode = riFrames[0]->loadRaw (true, 0, true, plistener, 0.8); + } + + if(!errCode) { + for(unsigned int i = 0; i < numFrames; ++i) { + riFrames[i]->compress_image(i); + } + } else { + return errCode; + } + + if(numFrames > 1 ) { // this disables multi frame support for Fuji S5 until I found a solution to handle different dimensions + if(riFrames[0]->get_width() != riFrames[1]->get_width() || riFrames[0]->get_height() != riFrames[1]->get_height()) { + numFrames = 1; + } + } if (plistener) { plistener->setProgress (0.9); @@ -1629,8 +1677,10 @@ int RawImageSource::load (const Glib::ustring &fname, bool batch) initialGain = 1.0 / min(pre_mul[0], pre_mul[1], pre_mul[2]); }*/ + for(unsigned int i = 0;i < numFrames; ++i) { + riFrames[i]->set_prefilters(); + } - ri->set_prefilters(); //Load complete Exif informations RawMetaDataLocation rml; @@ -1722,7 +1772,24 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le printf( "Flat Field Correction:%s\n", rif->get_filename().c_str()); } - copyOriginalPixels(raw, ri, rid, rif); + if(numFrames == 4) { + int bufferNumber = 0; + for(int i=0; i<4; ++i) { + if(i==currFrame) { + copyOriginalPixels(raw, ri, rid, rif, rawData); + rawDataFrames[i] = &rawData; + } else { + if(!rawDataBuffer[bufferNumber]) { + rawDataBuffer[bufferNumber] = new array2D; + } + rawDataFrames[i] = rawDataBuffer[bufferNumber]; + ++bufferNumber; + copyOriginalPixels(raw, riFrames[i], rid, rif, *rawDataFrames[i]); + } + } + } else { + copyOriginalPixels(raw, ri, rid, rif, rawData); + } //FLATFIELD end @@ -1762,8 +1829,13 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le } } - - scaleColors( 0, 0, W, H, raw); //+ + raw parameters for black level(raw.blackxx) + if(numFrames == 4) { + for(int i=0; i<4; ++i) { + scaleColors( 0, 0, W, H, raw, *rawDataFrames[i]); + } + } else { + scaleColors( 0, 0, W, H, raw, rawData); //+ + raw parameters for black level(raw.blackxx) + } // Correct vignetting of lens profile if (!hasFlatField && lensProf.useVign) { @@ -1772,15 +1844,34 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le if (pLCPProf) { // don't check focal length to allow distortion correction for lenses without chip, also pass dummy focal length 1 in case of 0 LCPMapper map(pLCPProf, max(idata->getFocalLen(), 1.0), idata->getFocalLen35mm(), idata->getFocusDist(), idata->getFNumber(), true, false, W, H, coarse, -1); + if (ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS || ri->get_colors() == 1) { + if(numFrames == 4) { + for(int i = 0; i < 4; ++i) { #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel for schedule(dynamic,16) #endif - for (int y = 0; y < H; y++) { - for (int x = 0; x < W; x++) { - if (rawData[y][x] > 0) { - rawData[y][x] *= map.calcVignetteFac(x, y); + for (int y = 0; y < H; y++) { + map.processVignetteLine(W, y, (*rawDataFrames[i])[y]); + } } + } else { + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < H; y++) { + map.processVignetteLine(W, y, rawData[y]); + } + } + } else if(ri->get_colors() == 3) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < H; y++) { + map.processVignetteLine3Channels(W, y, rawData[y]); } } } @@ -1850,13 +1941,25 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le plistener->setProgress (0.0); } - green_equilibrate(0.01 * (raw.bayersensor.greenthresh)); + if(numFrames == 4) { + for(int i = 0; i < 4; ++i) { + green_equilibrate(0.01 * (raw.bayersensor.greenthresh), *rawDataFrames[i]); + } + } else { + green_equilibrate(0.01 * (raw.bayersensor.greenthresh), rawData); + } } if( totBP ) { if ( ri->getSensorType() == ST_BAYER ) { - interpolateBadPixelsBayer( *bitmapBads ); + if(numFrames == 4) { + for(int i = 0; i < 4; ++i) { + interpolateBadPixelsBayer( *bitmapBads, *rawDataFrames[i] ); + } + } else { + interpolateBadPixelsBayer( *bitmapBads, rawData ); + } } else if ( ri->getSensorType() == ST_FUJI_XTRANS ) { interpolateBadPixelsXtrans( *bitmapBads ); } else { @@ -1878,12 +1981,23 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le plistener->setProgressStr ("CA Auto Correction..."); plistener->setProgress (0.0); } - - CA_correct_RT(raw.cared, raw.cablue, 10.0 - raw.caautostrength); + if(numFrames == 4) { + for(int i=0; i<4; ++i) { + CA_correct_RT(raw.ca_autocorrect, raw.cared, raw.cablue, 10.0 - raw.caautostrength, *rawDataFrames[i]); + } + } else { + CA_correct_RT(raw.ca_autocorrect, raw.cared, raw.cablue, 10.0 - raw.caautostrength, rawData); + } } if ( raw.expos != 1 ) { - processRawWhitepoint(raw.expos, raw.preser); + if(numFrames == 4) { + for(int i = 0; i < 4; ++i) { + processRawWhitepoint(raw.expos, raw.preser, *rawDataFrames[i]); + } + } else { + processRawWhitepoint(raw.expos, raw.preser, rawData); + } } if(prepareDenoise && dirpyrdenoiseExpComp == INFINITY) { @@ -1922,7 +2036,9 @@ void RawImageSource::demosaic(const RAWParams &raw) } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::ahd] ) { ahd_demosaic (0, 0, W, H); } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::amaze] ) { - amaze_demosaic_RT (0, 0, W, H); + amaze_demosaic_RT (0, 0, W, H, rawData, red, green, blue); + } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::pixelshift] ) { + pixelshift(0, 0, W, H, raw.bayersensor, currFrame, ri->get_model(), raw.expos); } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::dcb] ) { dcb_demosaic(raw.bayersensor.dcb_iterations, raw.bayersensor.dcb_enhance); } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::eahd]) { @@ -1930,7 +2046,7 @@ void RawImageSource::demosaic(const RAWParams &raw) } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::igv]) { igv_interpolate(W, H); } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::lmmse]) { - lmmse_interpolate_omp(W, H, raw.bayersensor.lmmse_iterations); + lmmse_interpolate_omp(W, H, rawData, red, green, blue, raw.bayersensor.lmmse_iterations); } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::fast] ) { fast_demosaic (0, 0, W, H); } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::mono] ) { @@ -2969,7 +3085,7 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile /* Copy original pixel data and * subtract dark frame (if present) from current image and apply flat field correction (if present) */ -void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, RawImage *riDark, RawImage *riFlatFile ) +void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, RawImage *riDark, RawImage *riFlatFile, array2D &rawData ) { // TODO: Change type of black[] to float to avoid conversions unsigned short black[4] = { @@ -3300,7 +3416,7 @@ SSEFUNCTION void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur // Scale original pixels into the range 0 65535 using black offsets and multipliers -void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const RAWParams &raw) +void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const RAWParams &raw, array2D &rawData) { chmax[0] = chmax[1] = chmax[2] = chmax[3] = 0; //channel maxima float black_lev[4] = {0.f};//black level @@ -3517,7 +3633,7 @@ int RawImageSource::defTransform (int tran) void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, array2D &rbconv_Y, array2D &rbconv_I, array2D &rbconv_Q, array2D &rbout_I, array2D &rbout_Q, const int row_from, const int row_to) { - const int W = im->width; + const int W = im->getWidth(); constexpr float onebynine = 1.f / 9.f; #ifdef __SSE2__ @@ -3664,7 +3780,7 @@ void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, array2D void RawImageSource::processFalseColorCorrection (Imagefloat* im, const int steps) { - if (im->height < 4 || steps < 1) { + if (im->getHeight() < 4 || steps < 1) { return; } @@ -3674,14 +3790,14 @@ void RawImageSource::processFalseColorCorrection (Imagefloat* im, const int ste multi_array2D buffer (W, 3); int tid = omp_get_thread_num(); int nthreads = omp_get_num_threads(); - int blk = (im->height - 2) / nthreads; + int blk = (im->getHeight() - 2) / nthreads; for (int t = 0; t < steps; t++) { if (tid < nthreads - 1) { processFalseColorCorrectionThread (im, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], 1 + tid * blk, 1 + (tid + 1)*blk); } else { - processFalseColorCorrectionThread (im, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], 1 + tid * blk, im->height - 1); + processFalseColorCorrectionThread (im, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], 1 + tid * blk, im->getHeight() - 1); } #pragma omp barrier @@ -3691,7 +3807,7 @@ void RawImageSource::processFalseColorCorrection (Imagefloat* im, const int ste multi_array2D buffer (W, 3); for (int t = 0; t < steps; t++) { - processFalseColorCorrectionThread (im, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], 1 , im->height - 1); + processFalseColorCorrectionThread (im, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], 1 , im->getHeight() - 1); } #endif @@ -3815,8 +3931,8 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam #pragma omp parallel for #endif - for (int i = 0; i < im->height; i++) - for (int j = 0; j < im->width; j++) { + for (int i = 0; i < im->getHeight(); i++) + for (int j = 0; j < im->getWidth(); j++) { float newr = mat[0][0] * im->r(i, j) + mat[0][1] * im->g(i, j) + mat[0][2] * im->b(i, j); float newg = mat[1][0] * im->r(i, j) + mat[1][1] * im->g(i, j) + mat[1][2] * im->b(i, j); @@ -3948,18 +4064,18 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam #pragma omp parallel #endif { - AlignedBuffer buffer(im->width * 3); - AlignedBuffer hl_buffer(im->width * 3); - AlignedBuffer hl_scale(im->width); + AlignedBuffer buffer(im->getWidth() * 3); + AlignedBuffer hl_buffer(im->getWidth() * 3); + AlignedBuffer hl_scale(im->getWidth()); #ifdef _OPENMP #pragma omp for schedule(static) #endif - for ( int h = 0; h < im->height; ++h ) { + for ( int h = 0; h < im->getHeight(); ++h ) { float *p = buffer.data, *pR = im->r(h), *pG = im->g(h), *pB = im->b(h); // Apply pre-processing - for ( int w = 0; w < im->width; ++w ) { + for ( int w = 0; w < im->getWidth(); ++w ) { float r = *(pR++); float g = *(pG++); float b = *(pB++); @@ -4030,10 +4146,10 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam } // Run icc transform - cmsDoTransform (hTransform, buffer.data, buffer.data, im->width); + cmsDoTransform (hTransform, buffer.data, buffer.data, im->getWidth()); if (separate_pcs_lab_highlights) { - cmsDoTransform (hTransform, hl_buffer.data, hl_buffer.data, im->width); + cmsDoTransform (hTransform, hl_buffer.data, hl_buffer.data, im->getWidth()); } // Apply post-processing @@ -4042,7 +4158,7 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam pG = im->g(h); pB = im->b(h); - for ( int w = 0; w < im->width; ++w ) { + for ( int w = 0; w < im->getWidth(); ++w ) { float r, g, b, hr, hg, hb; @@ -5231,6 +5347,36 @@ void RawImageSource::init () } } +void RawImageSource::getRawValues(int x, int y, int rotate, int &R, int &G, int &B) +{ + int xnew = x + border; + int ynew = y + border; + rotate += ri->get_rotateDegree(); + rotate %= 360; + if (rotate == 90) { + std::swap(xnew,ynew); + ynew = H - 1 - ynew; + } else if (rotate == 180) { + xnew = W - 1 - xnew; + ynew = H - 1 - ynew; + } else if (rotate == 270) { + std::swap(xnew,ynew); + ynew = H - 1 - ynew; + xnew = W - 1 - xnew; + ynew = H - 1 - ynew; + } + + int c = ri->getSensorType() == ST_FUJI_XTRANS ? ri->XTRANSFC(ynew,xnew) : ri->FC(ynew,xnew); + int val = round(rawData[ynew][xnew] / scale_mul[c]); + if(c == 0) { + R = val; G = 0; B = 0; + } else if(c == 2) { + R = 0; G = 0; B = val; + } else { + R = 0; G = val; B = 0; + } +} + void RawImageSource::cleanup () { delete phaseOneIccCurve; diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 151edf959..0efa2b828 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -25,7 +25,7 @@ #include "curves.h" #include "color.h" #include "iimage.h" - +#include #define HR_SCALE 2 namespace rtengine @@ -71,6 +71,9 @@ protected: bool rgbSourceModified; RawImage* ri; // Copy of raw pixels, NOT corrected for initial gain, blackpoint etc. + RawImage* riFrames[4] = {nullptr}; + unsigned int currFrame = 0; + unsigned int numFrames = 0; // to accelerate CIELAB conversion: double lc00, lc01, lc02, lc10, lc11, lc12, lc20, lc21, lc22; @@ -78,6 +81,8 @@ protected: int threshold; array2D rawData; // holds preprocessed pixel values, rowData[i][j] corresponds to the ith row and jth column + array2D *rawDataFrames[4] = {nullptr}; + array2D *rawDataBuffer[3] = {nullptr}; // the interpolated green plane: array2D green; @@ -107,7 +112,7 @@ public: RawImageSource (); ~RawImageSource (); - int load (const Glib::ustring &fname, bool batch = false); + int load (const Glib::ustring &fname, int imageNum = 0, bool batch = false); void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse, bool prepareDenoise = true); void demosaic (const RAWParams &raw); void retinex (ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI); @@ -125,9 +130,9 @@ public: } void processFlatField(const RAWParams &raw, RawImage *riFlatFile, unsigned short black[4]); - void copyOriginalPixels(const RAWParams &raw, RawImage *ri, RawImage *riDark, RawImage *riFlatFile ); + void copyOriginalPixels(const RAWParams &raw, RawImage *ri, RawImage *riDark, RawImage *riFlatFile, array2D &rawData ); void cfaboxblur (RawImage *riFlatFile, float* cfablur, int boxH, int boxW); - void scaleColors (int winx, int winy, int winw, int winh, const RAWParams &raw); // raw for cblack + void scaleColors (int winx, int winy, int winw, int winh, const RAWParams &raw, array2D &rawData); // raw for cblack void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const ColorManagementParams &cmp, const RAWParams &raw); eSensorType getSensorType () const @@ -195,7 +200,10 @@ public: static void HLRecovery_blend (float* rin, float* gin, float* bin, int width, float maxval, float* hlmax); static void init (); static void cleanup (); - + void setCurrentFrame(unsigned int frameNum) { + currFrame = std::min(numFrames - 1, frameNum); + ri = riFrames[currFrame]; + } protected: typedef unsigned short ushort; void processFalseColorCorrection (Imagefloat* i, const int steps); @@ -208,18 +216,18 @@ protected: inline void interpolate_row_rb (float* ar, float* ab, float* pg, float* cg, float* ng, int i); inline void interpolate_row_rb_mul_pp (float* ar, float* ab, float* pg, float* cg, float* ng, int i, float r_mul, float g_mul, float b_mul, int x1, int width, int skip); - void CA_correct_RT (const double cared, const double cablue, const double caautostrength); + void CA_correct_RT (const bool autoCA, const double cared, const double cablue, const double caautostrength, array2D &rawData); void ddct8x8s(int isgn, float a[8][8]); - void processRawWhitepoint (float expos, float preser); // exposure before interpolation + void processRawWhitepoint (float expos, float preser, array2D &rawData); // exposure before interpolation - int interpolateBadPixelsBayer( PixelsMap &bitmapBads ); + int interpolateBadPixelsBayer( PixelsMap &bitmapBads, array2D &rawData ); int interpolateBadPixelsNColours( PixelsMap &bitmapBads, const int colours ); int interpolateBadPixelsXtrans( PixelsMap &bitmapBads ); int findHotDeadPixels( PixelsMap &bpMap, float thresh, bool findHotPixels, bool findDeadPixels ); void cfa_linedn (float linenoiselevel);//Emil's line denoise - void green_equilibrate (float greenthresh);//Emil's green equilibration + void green_equilibrate (float greenthresh, array2D &rawData);//Emil's green equilibration void nodemosaic(bool bw); void eahd_demosaic(); @@ -228,33 +236,35 @@ protected: void ppg_demosaic(); void jdl_interpolate_omp(); void igv_interpolate(int winw, int winh); - void lmmse_interpolate_omp(int winw, int winh, int iterations); - void amaze_demosaic_RT(int winx, int winy, int winw, int winh);//Emil's code for AMaZE + void lmmse_interpolate_omp(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations); + void amaze_demosaic_RT(int winx, int winy, int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue);//Emil's code for AMaZE void fast_demosaic(int winx, int winy, int winw, int winh );//Emil's code for fast demosaicing void dcb_demosaic(int iterations, bool dcb_enhance); void ahd_demosaic(int winx, int winy, int winw, int winh); void border_interpolate(unsigned int border, float (*image)[4], unsigned int start = 0, unsigned int end = 0); void border_interpolate2(int winw, int winh, int lborders); void dcb_initTileLimits(int &colMin, int &rowMin, int &colMax, int &rowMax, int x0, int y0, int border); - void fill_raw( float (*cache )[4], int x0, int y0, float** rawData); - void fill_border( float (*cache )[4], int border, int x0, int y0); - void copy_to_buffer(float (*image2)[3], float (*image)[4]); - void dcb_hid(float (*image)[4], float (*bufferH)[3], float (*bufferV)[3], int x0, int y0); - void dcb_color(float (*image)[4], int x0, int y0); - void dcb_hid2(float (*image)[4], int x0, int y0); - void dcb_map(float (*image)[4], int x0, int y0); - void dcb_correction(float (*image)[4], int x0, int y0); - void dcb_pp(float (*image)[4], int x0, int y0); - void dcb_correction2(float (*image)[4], int x0, int y0); - void restore_from_buffer(float (*image)[4], float (*image2)[3]); - void dcb_refinement(float (*image)[4], int x0, int y0); - void dcb_color_full(float (*image)[4], int x0, int y0, float (*chroma)[2]); + void fill_raw( float (*cache )[3], int x0, int y0, float** rawData); + void fill_border( float (*cache )[3], int border, int x0, int y0); + void copy_to_buffer(float (*image2)[2], float (*image)[3]); + void dcb_hid(float (*image)[3], int x0, int y0); + void dcb_color(float (*image)[3], int x0, int y0); + void dcb_hid2(float (*image)[3], int x0, int y0); + void dcb_map(float (*image)[3], uint8_t *map, int x0, int y0); + void dcb_correction(float (*image)[3], uint8_t *map, int x0, int y0); + void dcb_pp(float (*image)[3], int x0, int y0); + void dcb_correction2(float (*image)[3], uint8_t *map, int x0, int y0); + void restore_from_buffer(float (*image)[3], float (*image2)[2]); + void dcb_refinement(float (*image)[3], uint8_t *map, int x0, int y0); + void dcb_color_full(float (*image)[3], int x0, int y0, float (*chroma)[2]); void cielab (const float (*rgb)[3], float* l, float* a, float *b, const int width, const int height, const int labWidth, const float xyz_cam[3][3]); void xtransborder_interpolate (int border); void xtrans_interpolate (const int passes, const bool useCieLab); void fast_xtrans_interpolate (); + void pixelshift(int winx, int winy, int winw, int winh, const RAWParams::BayerSensor &bayerParams, unsigned int frame, const std::string &model, float rawWpCorrection); void hflip (Imagefloat* im); void vflip (Imagefloat* im); + void getRawValues(int x, int y, int rotate, int &R, int &G, int &B); }; } diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 025265e0a..0bb188b5d 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -469,7 +469,38 @@ int refreshmap[rtengine::NUMOFEVENTS] = { ALLNORAW, // EvcbdlMethod RETINEX, // EvRetinexgaintransmission RETINEX, // EvLskal - OUTPUTPROFILE // EvOBPCompens + OUTPUTPROFILE, // EvOBPCompens + ALLNORAW, // EvWBtempBias + DARKFRAME, // EvRawImageNum + DEMOSAIC, // EvPixelShiftMotion + DEMOSAIC, // EvPixelShiftMotionCorrection + DEMOSAIC, // EvPixelShiftStddevFactorGreen + DEMOSAIC, // EvPixelShiftEperIso + DEMOSAIC, // EvPixelShiftNreadIso + DEMOSAIC, // EvPixelShiftPrnu + DEMOSAIC, // EvPixelshiftShowMotion + DEMOSAIC, // EvPixelshiftShowMotionMaskOnly + DEMOSAIC, // EvPixelShiftAutomatic + DEMOSAIC, // EvPixelShiftNonGreenHorizontal + DEMOSAIC, // EvPixelShiftNonGreenVertical + DEMOSAIC, // EvPixelShiftNonGreenCross + DEMOSAIC, // EvPixelShiftStddevFactorRed + DEMOSAIC, // EvPixelShiftStddevFactorBlue + DEMOSAIC, // EvPixelShiftNonGreenCross2 + DEMOSAIC, // EvPixelShiftNonGreenAmaze + DEMOSAIC, // EvPixelShiftGreen + DEMOSAIC, // EvPixelShiftRedBlueWeight + DEMOSAIC, // EvPixelShiftBlur + DEMOSAIC, // EvPixelShiftSigma + DEMOSAIC, // EvPixelShiftSum + DEMOSAIC, // EvPixelShiftExp0 + DEMOSAIC, // EvPixelShiftHoleFill + DEMOSAIC, // EvPixelShiftMedian + DEMOSAIC, // EvPixelShiftMedian3 + DEMOSAIC, // EvPixelShiftMotionMethod + DEMOSAIC, // EvPixelShiftSmooth + DEMOSAIC, // EvPixelShiftLmmse + DEMOSAIC // EvPixelShiftEqualBright }; diff --git a/rtengine/rt_math.h b/rtengine/rt_math.h index 67d883080..6e1138476 100644 --- a/rtengine/rt_math.h +++ b/rtengine/rt_math.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -11,71 +12,83 @@ constexpr int MAXVAL = 0xffff; constexpr float MAXVALF = static_cast(MAXVAL); // float version of MAXVAL constexpr double MAXVALD = static_cast(MAXVAL); // double version of MAXVAL -template -inline _Tp SQR (_Tp x) +constexpr double RT_PI = 3.14159265358979323846; // pi +constexpr double RT_PI_2 = 1.57079632679489661923; // pi/2 +constexpr double RT_1_PI = 0.31830988618379067154; // 1/pi +constexpr double RT_2_PI = 0.63661977236758134308; // 2/pi +constexpr double RT_SQRT1_2 = 0.70710678118654752440; // 1/sqrt(2) + +constexpr double RT_INFINITY = std::numeric_limits::infinity(); +constexpr double RT_NAN = std::numeric_limits::quiet_NaN(); + +constexpr float RT_PI_F = RT_PI; +constexpr float RT_PI_F_2 = RT_PI_2; + +constexpr float RT_INFINITY_F = std::numeric_limits::infinity(); +constexpr float RT_NAN_F = std::numeric_limits::quiet_NaN(); + +template +constexpr T SQR(T x) { -// return std::pow(x,2); Slower than: return x * x; } -template -inline const _Tp& min(const _Tp& a, const _Tp& b) +template +constexpr const T& min(const T& a) { - return std::min(a, b); + return a; } -template -inline const _Tp& max(const _Tp& a, const _Tp& b) +template +constexpr const T& min(const T& a, const T& b) { - return std::max(a, b); + return b < a ? b : a; } - -template -inline const _Tp& LIM(const _Tp& a, const _Tp& b, const _Tp& c) +template +constexpr const T& min(const T& a, const T& b, const ARGS&... args) { - return std::max(b, std::min(a, c)); + return min(min(a, b), min(args...)); } -template -inline _Tp LIM01(const _Tp& a) +template +constexpr const T& max(const T& a) { - return std::max(_Tp(0), std::min(a, _Tp(1))); + return a; } -template -inline _Tp CLIP(const _Tp& a) +template +constexpr const T& max(const T& a, const T& b) { - return LIM(a, static_cast<_Tp>(0), static_cast<_Tp>(MAXVAL)); + return a < b ? b : a; } - -template -inline const _Tp& min(const _Tp& a, const _Tp& b, const _Tp& c) +template +constexpr const T& max(const T& a, const T& b, const ARGS&... args) { - return std::min(c, std::min(a, b)); + return max(max(a, b), max(args...)); } -template -inline const _Tp& max(const _Tp& a, const _Tp& b, const _Tp& c) +template +constexpr const T& LIM(const T& a, const T& b, const T& c) { - return std::max(c, std::max(a, b)); + return max(b, min(a, c)); } -template -inline const _Tp& min(const _Tp& a, const _Tp& b, const _Tp& c, const _Tp& d) +template +constexpr T LIM01(const T& a) { - return std::min(d, std::min(c, std::min(a, b))); + return max(T(0), min(a, T(1))); } -template -inline const _Tp& max(const _Tp& a, const _Tp& b, const _Tp& c, const _Tp& d) +template +constexpr T CLIP(const T& a) { - return std::max(d, std::max(c, std::max(a, b))); + return LIM(a, static_cast(0), static_cast(MAXVAL)); } -template -inline _Tp intp(_Tp a, _Tp b, _Tp c) +template +constexpr T intp(T a, T b, T c) { // calculate a * b + (1 - a) * c // following is valid: @@ -99,13 +112,13 @@ inline T norm2(const T& x, const T& y) template< typename T > inline T norminf(const T& x, const T& y) { - return std::max(std::abs(x), std::abs(y)); + return max(std::abs(x), std::abs(y)); } -inline int float2uint16range(float d) // clips input to [0;65535] and rounds +constexpr int float2uint16range(float d) { - d = CLIP(d); // clip to [0;65535] - return d + 0.5f; + // clips input to [0;65535] and rounds + return CLIP(d) + 0.5f; } constexpr std::uint8_t uint16ToUint8Rounded(std::uint16_t i) diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index f99df3fe3..edcbae351 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -310,6 +310,13 @@ public : }; +class AutoWBListener +{ +public : + virtual ~AutoWBListener() = default; + virtual void WBChanged(double temp, double green) = 0; +}; + class WaveletListener { public : @@ -396,7 +403,7 @@ public: * @return a pointer to the Crop object that handles the image data trough its own pipeline */ virtual DetailedCrop* createCrop (::EditDataProvider *editDataProvider, bool isDetailWindow) = 0; - virtual bool getAutoWB (double& temp, double& green, double equal) = 0; + virtual bool getAutoWB (double& temp, double& green, double equal, double tempBias) = 0; virtual void getCamWB (double& temp, double& green) = 0; virtual void getSpotWB (int x, int y, int rectSize, double& temp, double& green) = 0; virtual void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) = 0; @@ -411,6 +418,7 @@ public: virtual void setPreviewImageListener (PreviewImageListener* l) = 0; virtual void setAutoCamListener (AutoCamListener* l) = 0; virtual void setAutoBWListener (AutoBWListener* l) = 0; + virtual void setAutoWBListener (AutoWBListener* l) = 0; virtual void setAutoColorTonListener (AutoColorTonListener* l) = 0; virtual void setAutoChromaListener (AutoChromaListener* l) = 0; virtual void setRetinexListener (RetinexListener* l) = 0; diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 86729fce2..cabcb34ab 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -98,16 +98,16 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, if (inspectorMode) { // Special case, meaning that we want a full sized thumbnail image (e.g. for the Inspector feature) - w = img->width; - h = img->height; + w = img->getWidth(); + h = img->getHeight(); tpp->scale = 1.; } else { if (fixwh == 1) { - w = h * img->width / img->height; - tpp->scale = (double)img->height / h; + w = h * img->getWidth() / img->getHeight(); + tpp->scale = (double)img->getHeight() / h; } else { - h = w * img->height / img->width; - tpp->scale = (double)img->width / w; + h = w * img->getHeight() / img->getWidth(); + tpp->scale = (double)img->getWidth() / w; } } @@ -162,6 +162,7 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, tpp->greenAWBMul = avg_g / double(n); tpp->blueAWBMul = avg_b / double(n); tpp->wbEqual = wbEq; + tpp->wbTempBias = 0.0; cTemp.mul2temp (tpp->redAWBMul, tpp->greenAWBMul, tpp->blueAWBMul, tpp->wbEqual, tpp->autoWBTemp, tpp->autoWBGreen); } @@ -175,7 +176,8 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate, bool inspectorMode) { RawImage *ri = new RawImage(fname); - int r = ri->loadRaw(false, false); + unsigned int imageNum = 0; + int r = ri->loadRaw(false, imageNum, false); if( r ) { delete ri; @@ -223,16 +225,16 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL if (inspectorMode) { // Special case, meaning that we want a full sized thumbnail image (e.g. for the Inspector feature) - w = img->width; - h = img->height; + w = img->getWidth(); + h = img->getHeight(); tpp->scale = 1.; } else { if (fixwh == 1) { - w = h * img->width / img->height; - tpp->scale = (double)img->height / h; + w = h * img->getWidth() / img->getHeight(); + tpp->scale = (double)img->getHeight() / h; } else { - h = w * img->height / img->width; - tpp->scale = (double)img->width / w; + h = w * img->getHeight() / img->getWidth(); + tpp->scale = (double)img->getWidth() / w; } } @@ -260,8 +262,8 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL if (suffix != "mos" && suffix != "mef" && suffix != "iiq") { tpp->thumbImg->rotate(ri->get_rotateDegree()); // width/height may have changed after rotating - w = tpp->thumbImg->width; - h = tpp->thumbImg->height; + w = tpp->thumbImg->getWidth(); + h = tpp->thumbImg->getHeight(); } } @@ -289,7 +291,9 @@ RawMetaDataLocation Thumbnail::loadMetaDataFromRaw (const Glib::ustring& fname) rml.ciffLength = -1; RawImage ri(fname); - int r = ri.loadRaw(false); + unsigned int imageNum = 0; + + int r = ri.loadRaw(false, imageNum); if( !r ) { rml.exifBase = ri.get_exifBase(); @@ -300,10 +304,12 @@ RawMetaDataLocation Thumbnail::loadMetaDataFromRaw (const Glib::ustring& fname) return rml; } -Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate) +Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate, int imageNum) { RawImage *ri = new RawImage (fname); - int r = ri->loadRaw(1, 0); + unsigned int tempImageNum = 0; + + int r = ri->loadRaw(1, tempImageNum, 0); if( r ) { delete ri; @@ -735,6 +741,7 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati tpp->greenAWBMul = ri->get_rgb_cam(1, 0) * reds + ri->get_rgb_cam(1, 1) * greens + ri->get_rgb_cam(1, 2) * blues; tpp->blueAWBMul = ri->get_rgb_cam(2, 0) * reds + ri->get_rgb_cam(2, 1) * greens + ri->get_rgb_cam(2, 2) * blues; tpp->wbEqual = wbEq; + tpp->wbTempBias = 0.0; ColorTemp cTemp; cTemp.mul2temp(tpp->redAWBMul, tpp->greenAWBMul, tpp->blueAWBMul, tpp->wbEqual, tpp->autoWBTemp, tpp->autoWBGreen); @@ -776,7 +783,7 @@ Thumbnail::Thumbnail () : camProfile(nullptr), thumbImg(nullptr), camwbRed(1.0), camwbGreen(1.0), camwbBlue(1.0), redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), - autoWBTemp(2700), autoWBGreen(1.0), wbEqual(-1.0), + autoWBTemp(2700), autoWBGreen(1.0), wbEqual(-1.0), wbTempBias(0.0), embProfileLength(0), embProfileData(nullptr), embProfile(nullptr), redMultiplier(1.0), greenMultiplier(1.0), blueMultiplier(1.0), defGain(1.0), @@ -810,9 +817,9 @@ IImage8* Thumbnail::quickProcessImage (const procparams::ProcParams& params, int if (params.coarse.rotate == 90 || params.coarse.rotate == 270) { rwidth = rheight; - rheight = thumbImg->height * rwidth / thumbImg->width; + rheight = thumbImg->getHeight() * rwidth / thumbImg->getWidth(); } else { - rwidth = thumbImg->width * rheight / thumbImg->height; + rwidth = thumbImg->getWidth() * rheight / thumbImg->getHeight(); } Image8* baseImg = resizeTo(rwidth, rheight, interp, thumbImg); @@ -839,11 +846,13 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei BENCHFUN // check if the WB's equalizer value has changed - if (wbEqual < (params.wb.equal - 5e-4) || wbEqual > (params.wb.equal + 5e-4)) { + if (wbEqual < (params.wb.equal - 5e-4) || wbEqual > (params.wb.equal + 5e-4) || wbTempBias < (params.wb.tempBias - 5e-4) || wbTempBias > (params.wb.tempBias + 5e-4)) { wbEqual = params.wb.equal; + wbTempBias = params.wb.tempBias; // recompute the autoWB ColorTemp cTemp; cTemp.mul2temp (redAWBMul, greenAWBMul, blueAWBMul, wbEqual, autoWBTemp, autoWBGreen); + autoWBTemp += autoWBTemp * wbTempBias; } // compute WB multipliers @@ -889,9 +898,9 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei if (params.coarse.rotate == 90 || params.coarse.rotate == 270) { rwidth = rheight; - rheight = int(size_t(thumbImg->height) * size_t(rwidth) / size_t(thumbImg->width)); + rheight = int(size_t(thumbImg->getHeight()) * size_t(rwidth) / size_t(thumbImg->getWidth())); } else { - rwidth = int(size_t(thumbImg->width) * size_t(rheight) / size_t(thumbImg->height)); + rwidth = int(size_t(thumbImg->getWidth()) * size_t(rheight) / size_t(thumbImg->getHeight())); } @@ -899,8 +908,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei if (params.coarse.rotate) { baseImg->rotate (params.coarse.rotate); - rwidth = baseImg->width; - rheight = baseImg->height; + rwidth = baseImg->getWidth(); + rheight = baseImg->getHeight(); } if (params.coarse.hflip) { @@ -940,12 +949,12 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei StdImageSource::colorSpaceConversion (baseImg, params.icm, embProfile, thumbImg->getSampleFormat()); } - int fw = baseImg->width; - int fh = baseImg->height; + int fw = baseImg->getWidth(); + int fh = baseImg->getHeight(); //ColorTemp::CAT02 (baseImg, ¶ms) ;//perhaps not good! ImProcFunctions ipf (¶ms, false); - ipf.setScale (sqrt(double(fw * fw + fh * fh)) / sqrt(double(thumbImg->width * thumbImg->width + thumbImg->height * thumbImg->height))*scale); + ipf.setScale (sqrt(double(fw * fw + fh * fh)) / sqrt(double(thumbImg->getWidth() * thumbImg->getWidth() + thumbImg->getHeight() * thumbImg->getHeight()))*scale); ipf.updateColorProfiles (options.rtSettings.monitorProfile, options.rtSettings.monitorIntent, false, false); LUTu hist16 (65536); @@ -1206,9 +1215,9 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei // calculate scale if (params.coarse.rotate == 90 || params.coarse.rotate == 270) { - myscale = scale * thumbImg->width / fh; + myscale = scale * thumbImg->getWidth() / fh; } else { - myscale = scale * thumbImg->height / fh; + myscale = scale * thumbImg->getHeight() / fh; } myscale = 1.0 / myscale; @@ -1238,9 +1247,9 @@ int Thumbnail::getImageWidth (const procparams::ProcParams& params, int rheight, int rwidth; if (params.coarse.rotate == 90 || params.coarse.rotate == 270) { - ratio = (float)(thumbImg->height) / (float)(thumbImg->width); + ratio = (float)(thumbImg->getHeight()) / (float)(thumbImg->getWidth()); } else { - ratio = (float)(thumbImg->width) / (float)(thumbImg->height); + ratio = (float)(thumbImg->getWidth()) / (float)(thumbImg->getHeight()); } rwidth = (int)(ratio * (float)rheight); @@ -1251,8 +1260,8 @@ int Thumbnail::getImageWidth (const procparams::ProcParams& params, int rheight, void Thumbnail::getDimensions (int& w, int& h, double& scaleFac) { if (thumbImg) { - w = thumbImg->width; - h = thumbImg->height; + w = thumbImg->getWidth(); + h = thumbImg->getHeight(); scaleFac = scale; } else { w = 0; @@ -1272,15 +1281,17 @@ void Thumbnail::getCamWB (double& temp, double& green) green = currWB.getGreen (); } -void Thumbnail::getAutoWB (double& temp, double& green, double equal) +void Thumbnail::getAutoWB (double& temp, double& green, double equal, double tempBias) { - if (equal != wbEqual) { + if (equal != wbEqual || tempBias != wbTempBias) { // compute the values depending on equal ColorTemp cTemp; wbEqual = equal; + wbTempBias = tempBias; // compute autoWBTemp and autoWBGreen cTemp.mul2temp(redAWBMul, greenAWBMul, blueAWBMul, wbEqual, autoWBTemp, autoWBGreen); + autoWBTemp += autoWBTemp * tempBias; } temp = autoWBTemp; @@ -1314,11 +1325,11 @@ void Thumbnail::getSpotWB (const procparams::ProcParams& params, int xp, int yp, points.push_back (Coord2D (j, i)); } - int fw = thumbImg->width, fh = thumbImg->height; + int fw = thumbImg->getWidth(), fh = thumbImg->getHeight(); if (params.coarse.rotate == 90 || params.coarse.rotate == 270) { - fw = thumbImg->height; - fh = thumbImg->width; + fw = thumbImg->getHeight(); + fh = thumbImg->getWidth(); } ImProcFunctions ipf (¶ms, false); @@ -1343,8 +1354,8 @@ void Thumbnail::getSpotWB (const procparams::ProcParams& params, int xp, int yp, void Thumbnail::transformPixel (int x, int y, int tran, int& tx, int& ty) { - int W = thumbImg->width; - int H = thumbImg->height; + int W = thumbImg->getWidth(); + int H = thumbImg->getHeight(); int sw = W, sh = H; if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { @@ -1386,12 +1397,12 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) return nullptr; } - if (thumbImg->width < trim_width) { + if (thumbImg->getWidth() < trim_width) { return nullptr; } // to utilize the 8 bit color range of the thumbnail we brighten it and apply gamma correction - unsigned char* tmpdata = new unsigned char[thumbImg->height * trim_width]; + unsigned char* tmpdata = new unsigned char[thumbImg->getHeight() * trim_width]; int ix = 0, max; if (gammaCorrected) { @@ -1417,7 +1428,7 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) } // Go down till we cut off that many pixels - unsigned long cutoff = thumbImg->height * thumbImg->height * 4 * BurnOffPct; + unsigned long cutoff = thumbImg->getHeight() * thumbImg->getHeight() * 4 * BurnOffPct; int max_; unsigned long sum = 0; @@ -1434,8 +1445,8 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) if (thumbImg->getType() == sImage8) { Image8 *image = static_cast(thumbImg); - for (int i = 0; i < thumbImg->height; i++) - for (int j = (thumbImg->width - trim_width) / 2; j < trim_width + (thumbImg->width - trim_width) / 2; j++) { + for (int i = 0; i < thumbImg->getHeight(); i++) + for (int j = (thumbImg->getWidth() - trim_width) / 2; j < trim_width + (thumbImg->getWidth() - trim_width) / 2; j++) { unsigned short r_, g_, b_; image->convertTo(image->r(i, j), r_); image->convertTo(image->g(i, j), g_); @@ -1448,8 +1459,8 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) } else if (thumbImg->getType() == sImage16) { Image16 *image = static_cast(thumbImg); - for (int i = 0; i < thumbImg->height; i++) - for (int j = (thumbImg->width - trim_width) / 2; j < trim_width + (thumbImg->width - trim_width) / 2; j++) { + for (int i = 0; i < thumbImg->getHeight(); i++) + for (int j = (thumbImg->getWidth() - trim_width) / 2; j < trim_width + (thumbImg->getWidth() - trim_width) / 2; j++) { unsigned short r_, g_, b_; image->convertTo(image->r(i, j), r_); image->convertTo(image->g(i, j), g_); @@ -1462,8 +1473,8 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) } else if (thumbImg->getType() == sImagefloat) { Imagefloat *image = static_cast(thumbImg); - for (int i = 0; i < thumbImg->height; i++) - for (int j = (thumbImg->width - trim_width) / 2; j < trim_width + (thumbImg->width - trim_width) / 2; j++) { + for (int i = 0; i < thumbImg->getHeight(); i++) + for (int j = (thumbImg->getWidth() - trim_width) / 2; j < trim_width + (thumbImg->getWidth() - trim_width) / 2; j++) { unsigned short r_, g_, b_; image->convertTo(image->r(i, j), r_); image->convertTo(image->g(i, j), g_); @@ -1482,8 +1493,8 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) Image8 *image = static_cast(thumbImg); unsigned char max_ = 0; - for (int row = 0; row < image->height; row++) - for (int col = 0; col < image->width; col++) { + for (int row = 0; row < image->getHeight(); row++) + for (int col = 0; col < image->getWidth(); col++) { if (image->r(row, col) > max_) { max_ = image->r(row, col); } @@ -1506,8 +1517,8 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) scaleForSave = 65535 * 8192 / max; // Correction and gamma to 8 Bit - for (int i = 0; i < image->height; i++) - for (int j = (image->width - trim_width) / 2; j < trim_width + (image->width - trim_width) / 2; j++) { + for (int i = 0; i < image->getHeight(); i++) + for (int j = (image->getWidth() - trim_width) / 2; j < trim_width + (image->getWidth() - trim_width) / 2; j++) { unsigned short rtmp, gtmp, btmp; image->convertTo(image->r(i, j), rtmp); image->convertTo(image->g(i, j), gtmp); @@ -1521,8 +1532,8 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) Image16 *image = static_cast(thumbImg); unsigned short max_ = 0; - for (int row = 0; row < image->height; row++) - for (int col = 0; col < image->width; col++) { + for (int row = 0; row < image->getHeight(); row++) + for (int col = 0; col < image->getWidth(); col++) { if (image->r(row, col) > max_) { max_ = image->r(row, col); } @@ -1545,8 +1556,8 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) scaleForSave = 65535 * 8192 / max; // Correction and gamma to 8 Bit - for (int i = 0; i < image->height; i++) - for (int j = (image->width - trim_width) / 2; j < trim_width + (image->width - trim_width) / 2; j++) { + for (int i = 0; i < image->getHeight(); i++) + for (int j = (image->getWidth() - trim_width) / 2; j < trim_width + (image->getWidth() - trim_width) / 2; j++) { unsigned short rtmp, gtmp, btmp; image->convertTo(image->r(i, j), rtmp); image->convertTo(image->g(i, j), gtmp); @@ -1560,8 +1571,8 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) Imagefloat *image = static_cast(thumbImg); float max_ = 0.f; - for (int row = 0; row < image->height; row++) - for (int col = 0; col < image->width; col++) { + for (int row = 0; row < image->getHeight(); row++) + for (int col = 0; col < image->getWidth(); col++) { if (image->r(row, col) > max_) { max_ = image->r(row, col); } @@ -1584,8 +1595,8 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) scaleForSave = 65535 * 8192 / max; // Correction and gamma to 8 Bit - for (int i = 0; i < image->height; i++) - for (int j = (image->width - trim_width) / 2; j < trim_width + (image->width - trim_width) / 2; j++) { + for (int i = 0; i < image->getHeight(); i++) + for (int j = (image->getWidth() - trim_width) / 2; j < trim_width + (image->getWidth() - trim_width) / 2; j++) { unsigned short rtmp, gtmp, btmp; image->convertTo(image->r(i, j), rtmp); image->convertTo(image->g(i, j), gtmp); @@ -1617,7 +1628,7 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) } if (cdf_min != -1) { - hist[i] = (cdf - cdf_min) * 255 / ((thumbImg->height * trim_width) - cdf_min); + hist[i] = (cdf - cdf_min) * 255 / ((thumbImg->getHeight() * trim_width) - cdf_min); } } @@ -1645,8 +1656,8 @@ bool Thumbnail::writeImage (const Glib::ustring& fname, int format) fwrite (thumbImg->getType(), sizeof (char), strlen(thumbImg->getType()), f); fputc ('\n', f); - guint32 w = guint32(thumbImg->width); - guint32 h = guint32(thumbImg->height); + guint32 w = guint32(thumbImg->getWidth()); + guint32 h = guint32(thumbImg->getHeight()); fwrite (&w, sizeof (guint32), 1, f); fwrite (&h, sizeof (guint32), 1, f); diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h index 18e72fc19..c40a226c4 100644 --- a/rtengine/rtthumbnail.h +++ b/rtengine/rtthumbnail.h @@ -47,7 +47,7 @@ class Thumbnail double camwbGreen; double camwbBlue; double redAWBMul, greenAWBMul, blueAWBMul; // multipliers for auto WB - double autoWBTemp, autoWBGreen, wbEqual; // autoWBTemp and autoWBGreen are updated each time autoWB is requested and if wbEqual has been modified + double autoWBTemp, autoWBGreen, wbEqual, wbTempBias; // autoWBTemp and autoWBGreen are updated each time autoWB is requested and if wbEqual has been modified LUTu aeHistogram; int aeHistCompression; int embProfileLength; @@ -78,12 +78,12 @@ public: void getDimensions (int& w, int& h, double& scaleFac); static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate, bool inspectorMode = false); - static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate); + static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate, int imageNum); static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode = false); static RawMetaDataLocation loadMetaDataFromRaw (const Glib::ustring& fname); void getCamWB (double& temp, double& green); - void getAutoWB (double& temp, double& green, double equal); + void getAutoWB (double& temp, double& green, double equal, double tempBias); void getAutoWBMultipliers (double& rm, double& gm, double& bm); void getSpotWB (const procparams::ProcParams& params, int x, int y, int rect, double& temp, double& green); void applyAutoExp (procparams::ProcParams& pparams); diff --git a/rtengine/shmap.cc b/rtengine/shmap.cc index 65c1070a2..a92264117 100644 --- a/rtengine/shmap.cc +++ b/rtengine/shmap.cc @@ -85,12 +85,21 @@ void SHMap::update (Imagefloat* img, double radius, double lumi[3], bool hq, int if (!hq) { fillLuminance( img, map, lumi); + float *buffer = nullptr; + + if(radius > 40.) { + // When we pass another buffer to gaussianBlur, it will use iterated boxblur which is less prone to artifacts + buffer = new float[W * H]; + } + #ifdef _OPENMP #pragma omp parallel #endif { - gaussianBlur (map, map, W, H, radius); + gaussianBlur (map, map, W, H, radius, buffer); } + + delete [] buffer; } else { diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 0f3aea0d0..c7a05ab1a 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -102,6 +102,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p ImProcFunctions ipf (¶ms, true); PreviewProps pp (0, 0, fw, fh, 1); + imgsrc->setCurrentFrame(params.raw.bayersensor.imageNum); imgsrc->preprocess( params.raw, params.lensProf, params.coarse, params.dirpyrDenoise.enabled); if (params.toneCurve.autoexp) {// this enabled HLRecovery @@ -160,7 +161,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p } else if (params.wb.method == "Auto") { double rm, gm, bm; imgsrc->getAutoWBMultipliers(rm, gm, bm); - currWB.update(rm, gm, bm, params.wb.equal); + currWB.update(rm, gm, bm, params.wb.equal, params.wb.tempBias); } NoiseCurve noiseLCurve; diff --git a/rtengine/sleef.c b/rtengine/sleef.c index bc38a3cfb..17dfccc0f 100644 --- a/rtengine/sleef.c +++ b/rtengine/sleef.c @@ -12,7 +12,8 @@ #include #include -#include +//#include +#include "rt_math.h" //#include //#include @@ -56,9 +57,9 @@ __inline double mla(double x, double y, double z) { return x * y + z; } __inline double xrint(double x) { return x < 0 ? (int)(x - 0.5) : (int)(x + 0.5); } __inline int xisnan(double x) { return x != x; } -__inline int xisinf(double x) { return x == INFINITY || x == -INFINITY; } -__inline int xisminf(double x) { return x == -INFINITY; } -__inline int xispinf(double x) { return x == INFINITY; } +__inline int xisinf(double x) { return x == rtengine::RT_INFINITY || x == -rtengine::RT_INFINITY; } +__inline int xisminf(double x) { return x == -rtengine::RT_INFINITY; } +__inline int xispinf(double x) { return x == rtengine::RT_INFINITY; } __inline double ldexpk(double x, int q) { double u; @@ -87,7 +88,7 @@ __inline int ilogbp1(double d) { __inline int xilogb(double d) { int e = ilogbp1(xfabs(d)) - 1; e = d == 0 ? (-2147483647 - 1) : e; - e = d == INFINITY || d == -INFINITY ? 2147483647 : e; + e = d == rtengine::RT_INFINITY || d == -rtengine::RT_INFINITY ? 2147483647 : e; return e; } @@ -309,7 +310,7 @@ __inline double atan2k(double y, double x) { u = u * t + (-0.333333333333311110369124); t = u * t * s + s; - t = q * (M_PI/2) + t; + t = q * (rtengine::RT_PI_2) + t; return t; } @@ -318,11 +319,11 @@ __inline double xatan2(double y, double x) { double r = atan2k(xfabs(y), x); r = mulsign(r, x); - if (xisinf(x) || x == 0) r = M_PI/2 - (xisinf(x) ? (sign(x) * (M_PI /2)) : 0); - if (xisinf(y) ) r = M_PI/2 - (xisinf(x) ? (sign(x) * (M_PI*1/4)) : 0); - if ( y == 0) r = (sign(x) == -1 ? M_PI : 0); + if (xisinf(x) || x == 0) r = rtengine::RT_PI_2 - (xisinf(x) ? (sign(x) * (rtengine::RT_PI_2)) : 0); + if (xisinf(y) ) r = rtengine::RT_PI_2 - (xisinf(x) ? (sign(x) * (rtengine::RT_PI*1/4)) : 0); + if ( y == 0) r = (sign(x) == -1 ? rtengine::RT_PI : 0); - return xisnan(x) || xisnan(y) ? NAN : mulsign(r, y); + return xisnan(x) || xisnan(y) ? rtengine::RT_NAN : mulsign(r, y); } __inline double xasin(double d) { @@ -330,7 +331,7 @@ __inline double xasin(double d) { } __inline double xacos(double d) { - return mulsign(atan2k(sqrt((1+d)*(1-d)), xfabs(d)), d) + (d < 0 ? M_PI : 0); + return mulsign(atan2k(sqrt((1+d)*(1-d)), xfabs(d)), d) + (d < 0 ? rtengine::RT_PI : 0); } __inline double xatan(double s) { @@ -374,7 +375,7 @@ __inline double xsin(double d) { int q; double u, s; - q = (int)xrint(d * M_1_PI); + q = (int)xrint(d * rtengine::RT_1_PI); d = mla(q, -PI4_A*4, d); d = mla(q, -PI4_B*4, d); @@ -403,7 +404,7 @@ __inline double xcos(double d) { int q; double u, s; - q = 1 + 2*(int)xrint(d * M_1_PI - 0.5); + q = 1 + 2*(int)xrint(d * rtengine::RT_1_PI - 0.5); d = mla(q, -PI4_A*2, d); d = mla(q, -PI4_B*2, d); @@ -433,7 +434,7 @@ __inline double2 xsincos(double d) { double u, s, t; double2 r; - q = (int)xrint(d * (2 * M_1_PI)); + q = (int)xrint(d * (2 * rtengine::RT_1_PI)); s = d; @@ -469,7 +470,7 @@ __inline double2 xsincos(double d) { if ((q & 2) != 0) { r.x = -r.x; } if (((q+1) & 2) != 0) { r.y = -r.y; } - if (xisinf(d)) { r.x = r.y = NAN; } + if (xisinf(d)) { r.x = r.y = rtengine::RT_NAN; } return r; } @@ -478,7 +479,7 @@ __inline double xtan(double d) { int q; double u, s, x; - q = (int)xrint(d * (2 * M_1_PI)); + q = (int)xrint(d * (2 * rtengine::RT_1_PI)); x = mla(q, -PI4_A*2, d); x = mla(q, -PI4_B*2, x); @@ -508,7 +509,7 @@ __inline double xtan(double d) { if ((q & 1) != 0) u = 1.0 / u; - if (xisinf(d)) u = NAN; + if (xisinf(d)) u = rtengine::RT_NAN; return u; } @@ -534,9 +535,9 @@ __inline double xlog(double d) { x = x * t + 0.693147180559945286226764 * e; - if (xisinf(d)) x = INFINITY; - if (d < 0) x = NAN; - if (d == 0) x = -INFINITY; + if (xisinf(d)) x = rtengine::RT_INFINITY; + if (d < 0) x = rtengine::RT_NAN; + if (d == 0) x = -rtengine::RT_INFINITY; return x; } @@ -625,13 +626,13 @@ __inline double xpow(double x, double y) { double result = expk(mul_ds(logk(xfabs(x)), y)); - result = xisnan(result) ? INFINITY : result; - result *= (x >= 0 ? 1 : (!yisint ? NAN : (yisodd ? -1 : 1))); + result = xisnan(result) ? rtengine::RT_INFINITY : result; + result *= (x >= 0 ? 1 : (!yisint ? rtengine::RT_NAN : (yisodd ? -1 : 1))); double efx = mulsign(xfabs(x) - 1, y); - if (xisinf(y)) result = efx < 0 ? 0.0 : (efx == 0 ? 1.0 : INFINITY); - if (xisinf(x) || x == 0) result = (yisodd ? sign(x) : 1) * ((x == 0 ? -y : y) < 0 ? 0 : INFINITY); - if (xisnan(x) || xisnan(y)) result = NAN; + if (xisinf(y)) result = efx < 0 ? 0.0 : (efx == 0 ? 1.0 : rtengine::RT_INFINITY); + if (xisinf(x) || x == 0) result = (yisodd ? sign(x) : 1) * ((x == 0 ? -y : y) < 0 ? 0 : rtengine::RT_INFINITY); + if (xisnan(x) || xisnan(y)) result = rtengine::RT_NAN; if (y == 0 || x == 1) result = 1; return result; @@ -670,9 +671,9 @@ __inline double xsinh(double x) { d = add2_dd(d, div_dd(dd(-1, 0), d)); y = (d.x + d.y) * 0.5; - y = xisinf(x) || xisnan(y) ? INFINITY : y; + y = xisinf(x) || xisnan(y) ? rtengine::RT_INFINITY : y; y = mulsign(y, x); - y = xisnan(x) ? NAN : y; + y = xisnan(x) ? rtengine::RT_NAN : y; return y; } @@ -682,8 +683,8 @@ __inline double xcosh(double x) { d = add2_dd(d, div_dd(dd(1, 0), d)); double y = (d.x + d.y) * 0.5; - y = xisinf(x) || xisnan(y) ? INFINITY : y; - y = xisnan(x) ? NAN : y; + y = xisinf(x) || xisnan(y) ? rtengine::RT_INFINITY : y; + y = xisnan(x) ? rtengine::RT_NAN : y; return y; } @@ -697,7 +698,7 @@ __inline double xtanh(double x) { y = xisinf(x) || xisnan(y) ? 1.0 : y; y = mulsign(y, x); - y = xisnan(x) ? NAN : y; + y = xisnan(x) ? rtengine::RT_NAN : y; return y; } @@ -732,9 +733,9 @@ __inline double xasinh(double x) { double2 d = logk2(add2_ds(sqrt_d(add2_ds(mul_ss(y, y), 1)), y)); y = d.x + d.y; - y = xisinf(x) || xisnan(y) ? INFINITY : y; + y = xisinf(x) || xisnan(y) ? rtengine::RT_INFINITY : y; y = mulsign(y, x); - y = xisnan(x) ? NAN : y; + y = xisnan(x) ? rtengine::RT_NAN : y; return y; } @@ -743,10 +744,10 @@ __inline double xacosh(double x) { double2 d = logk2(add2_ds(sqrt_d(add2_ds(mul_ss(x, x), -1)), x)); double y = d.x + d.y; - y = xisinf(x) || xisnan(y) ? INFINITY : y; + y = xisinf(x) || xisnan(y) ? rtengine::RT_INFINITY : y; y = x == 1.0 ? 0.0 : y; - y = x < 1.0 ? NAN : y; - y = xisnan(x) ? NAN : y; + y = x < 1.0 ? rtengine::RT_NAN : y; + y = xisnan(x) ? rtengine::RT_NAN : y; return y; } @@ -754,11 +755,11 @@ __inline double xacosh(double x) { __inline double xatanh(double x) { double y = xfabs(x); double2 d = logk2(div_dd(add2_ss(1, y), add2_ss(1, -y))); - y = y > 1.0 ? NAN : (y == 1.0 ? INFINITY : (d.x + d.y) * 0.5); + y = y > 1.0 ? rtengine::RT_NAN : (y == 1.0 ? rtengine::RT_INFINITY : (d.x + d.y) * 0.5); - y = xisinf(x) || xisnan(y) ? NAN : y; + y = xisinf(x) || xisnan(y) ? rtengine::RT_NAN : y; y = mulsign(y, x); - y = xisnan(x) ? NAN : y; + y = xisnan(x) ? rtengine::RT_NAN : y; return y; } @@ -809,7 +810,7 @@ __inline double xsqrt(double d) { // max error : 0.5 ulp // You can change xfma to fma if fma is correctly implemented x = xfma(d * x, d * x, -d) * (x * -0.5) + d * x; - return d == INFINITY ? INFINITY : x * q; + return d == rtengine::RT_INFINITY ? rtengine::RT_INFINITY : x * q; } __inline double xcbrt(double d) { // max error : 2 ulps @@ -842,14 +843,14 @@ __inline double xcbrt(double d) { // max error : 2 ulps __inline double xexp2(double a) { double u = expk(mul_ds(dd(0.69314718055994528623, 2.3190468138462995584e-17), a)); - if (xispinf(a)) u = INFINITY; + if (xispinf(a)) u = rtengine::RT_INFINITY; if (xisminf(a)) u = 0; return u; } __inline double xexp10(double a) { double u = expk(mul_ds(dd(2.3025850929940459011, -2.1707562233822493508e-16), a)); - if (xispinf(a)) u = INFINITY; + if (xispinf(a)) u = rtengine::RT_INFINITY; if (xisminf(a)) u = 0; return u; } @@ -857,7 +858,7 @@ __inline double xexp10(double a) { __inline double xexpm1(double a) { double2 d = add2_ds(expk2(dd(a, 0)), -1.0); double x = d.x + d.y; - if (xispinf(a)) x = INFINITY; + if (xispinf(a)) x = rtengine::RT_INFINITY; if (xisminf(a)) x = -1; return x; } @@ -866,9 +867,9 @@ __inline double xlog10(double a) { double2 d = mul_dd(logk(a), dd(0.43429448190325176116, 6.6494347733425473126e-17)); double x = d.x + d.y; - if (xisinf(a)) x = INFINITY; - if (a < 0) x = NAN; - if (a == 0) x = -INFINITY; + if (xisinf(a)) x = rtengine::RT_INFINITY; + if (a < 0) x = rtengine::RT_NAN; + if (a == 0) x = -rtengine::RT_INFINITY; return x; } @@ -877,9 +878,9 @@ __inline double xlog1p(double a) { double2 d = logk2(add2_ss(a, 1)); double x = d.x + d.y; - if (xisinf(a)) x = INFINITY; - if (a < -1) x = NAN; - if (a == -1) x = -INFINITY; + if (xisinf(a)) x = rtengine::RT_INFINITY; + if (a < -1) x = rtengine::RT_NAN; + if (a == -1) x = -rtengine::RT_INFINITY; return x; } @@ -895,11 +896,6 @@ __inline double xlog1p(double a) { #define L2Lf 1.428606765330187045e-06f #define R_LN2f 1.442695040888963407359924681001892137426645954152985934135449406931f -#define M_PIf ((float)M_PI) -#define M_PIf_2 ((float)M_PI_2) - -#define INFINITYf ((float)INFINITY) -#define NANf ((float)NAN) __inline int32_t floatToRawIntBits(float d) { union { @@ -932,9 +928,9 @@ __inline float mlaf(float x, float y, float z) { return x * y + z; } __inline float xrintf(float x) { return x < 0 ? (int)(x - 0.5f) : (int)(x + 0.5f); } __inline int xisnanf(float x) { return x != x; } -__inline int xisinff(float x) { return x == INFINITYf || x == -INFINITYf; } -__inline int xisminff(float x) { return x == -INFINITYf; } -__inline int xispinff(float x) { return x == INFINITYf; } +__inline int xisinff(float x) { return x == rtengine::RT_INFINITY_F || x == -rtengine::RT_INFINITY_F; } +__inline int xisminff(float x) { return x == -rtengine::RT_INFINITY_F; } +__inline int xispinff(float x) { return x == rtengine::RT_INFINITY_F; } __inline int ilogbp1f(float d) { int m = d < 5.421010862427522E-20f; @@ -988,7 +984,7 @@ __inline float xsinf(float d) { int q; float u, s; - q = (int)xrintf(d * (float)M_1_PI); + q = (int)xrintf(d * (float)rtengine::RT_1_PI); d = mlaf(q, -PI4_Af*4, d); d = mlaf(q, -PI4_Bf*4, d); @@ -1013,7 +1009,7 @@ __inline float xcosf(float d) { int q; float u, s; - q = 1 + 2*(int)xrintf(d * (float)M_1_PI - 0.5f); + q = 1 + 2*(int)xrintf(d * (float)rtengine::RT_1_PI - 0.5f); d = mlaf(q, -PI4_Af*2, d); d = mlaf(q, -PI4_Bf*2, d); @@ -1039,7 +1035,7 @@ __inline float2 xsincosf(float d) { float u, s, t; float2 r; - q = (int)rint(d * ((float)(2 * M_1_PI))); + q = (int)rint(d * ((float)(2 * rtengine::RT_1_PI))); s = d; @@ -1071,7 +1067,7 @@ __inline float2 xsincosf(float d) { if ((q & 2) != 0) { r.x = -r.x; } if (((q+1) & 2) != 0) { r.y = -r.y; } - if (xisinff(d)) { r.x = r.y = NANf; } + if (xisinff(d)) { r.x = r.y = rtengine::RT_NAN_F; } return r; } @@ -1080,7 +1076,7 @@ __inline float xtanf(float d) { int q; float u, s, x; - q = (int)xrintf(d * (float)(2 * M_1_PI)); + q = (int)xrintf(d * (float)(2 * rtengine::RT_1_PI)); x = d; @@ -1104,7 +1100,7 @@ __inline float xtanf(float d) { if ((q & 1) != 0) u = 1.0f / u; - if (xisinff(d)) u = NANf; + if (xisinff(d)) u = rtengine::RT_NAN_F; return u; } @@ -1156,18 +1152,18 @@ __inline float atan2kf(float y, float x) { t = u * t; t = mlaf(t,s,s); - return mlaf(q,(float)(M_PIf_2),t); + return mlaf(q,(float)(rtengine::RT_PI_F_2),t); } __inline float xatan2f(float y, float x) { float r = atan2kf(xfabsf(y), x); r = mulsignf(r, x); - if (xisinff(x) || x == 0) r = M_PIf/2 - (xisinff(x) ? (signf(x) * (float)(M_PIf*.5f)) : 0); - if (xisinff(y) ) r = M_PIf/2 - (xisinff(x) ? (signf(x) * (float)(M_PIf*.25f)) : 0); - if ( y == 0) r = (signf(x) == -1 ? M_PIf : 0); + if (xisinff(x) || x == 0) r = rtengine::RT_PI_F/2 - (xisinff(x) ? (signf(x) * (float)(rtengine::RT_PI_F*.5f)) : 0); + if (xisinff(y) ) r = rtengine::RT_PI_F/2 - (xisinff(x) ? (signf(x) * (float)(rtengine::RT_PI_F*.25f)) : 0); + if ( y == 0) r = (signf(x) == -1 ? rtengine::RT_PI_F : 0); - return xisnanf(x) || xisnanf(y) ? NANf : mulsignf(r, y); + return xisnanf(x) || xisnanf(y) ? rtengine::RT_NAN_F : mulsignf(r, y); } __inline float xasinf(float d) { @@ -1175,7 +1171,7 @@ __inline float xasinf(float d) { } __inline float xacosf(float d) { - return mulsignf(atan2kf(sqrtf((1.0f+d)*(1.0f-d)), fabsf(d)), d) + (d < 0 ? (float)M_PI : 0.0f); + return mulsignf(atan2kf(sqrtf((1.0f+d)*(1.0f-d)), fabsf(d)), d) + (d < 0 ? (float)rtengine::RT_PI : 0.0f); } __inline float xlogf(float d) { @@ -1196,9 +1192,9 @@ __inline float xlogf(float d) { x = x * t + 0.693147180559945286226764f * e; - if (xisinff(d)) x = INFINITYf; - if (d < 0) x = NANf; - if (d == 0) x = -INFINITYf; + if (xisinff(d)) x = rtengine::RT_INFINITY_F; + if (d < 0) x = rtengine::RT_NAN_F; + if (d == 0) x = -rtengine::RT_INFINITY_F; return x; } diff --git a/rtengine/sleefsseavx.c b/rtengine/sleefsseavx.c index a55fcf897..e4f587464 100644 --- a/rtengine/sleefsseavx.c +++ b/rtengine/sleefsseavx.c @@ -12,10 +12,11 @@ #define SLEEFSSEAVX #include -#include +//#include //#include //#include //#include "sleefsseavx.h" +#include "rt_math.h" #ifdef __SSE2__ #include "helpersse2.h" @@ -51,8 +52,8 @@ #define L2Lf 1.428606765330187045e-06f #define R_LN2f 1.442695040888963407359924681001892137426645954152985934135449406931f -#define INFINITYf ((float)INFINITY) -#define NANf ((float)NAN) +#define INFINITYf ((float)rtengine::RT_INFINITY) +#define NANf ((float)rtengine::RT_NAN) // @@ -259,7 +260,7 @@ static INLINE vdouble xldexp(vdouble x, vint q) { return vldexp(x, q); } static INLINE vint xilogb(vdouble d) { vdouble e = vcast_vd_vi(vsubi(vilogbp1(vabs(d)), vcast_vi_i(1))); e = vsel(vmask_eq(d, vcast_vd_d(0)), vcast_vd_d(-2147483648.0), e); - e = vsel(vmask_eq(vabs(d), vcast_vd_d(INFINITY)), vcast_vd_d(2147483647), e); + e = vsel(vmask_eq(vabs(d), vcast_vd_d(rtengine::RT_INFINITY)), vcast_vd_d(2147483647), e); return vrint_vi_vd(e); } @@ -267,7 +268,7 @@ static INLINE vdouble xsin(vdouble d) { vint q; vdouble u, s; - q = vrint_vi_vd(vmul(d, vcast_vd_d(M_1_PI))); + q = vrint_vi_vd(vmul(d, vcast_vd_d(rtengine::RT_1_PI))); u = vcast_vd_vi(q); d = vadd(d, vmul(u, vcast_vd_d(-PI4_A*4))); @@ -297,7 +298,7 @@ static INLINE vdouble xcos(vdouble d) { vint q; vdouble u, s; - q = vrint_vi_vd(vsub(vmul(d, vcast_vd_d(M_1_PI)), vcast_vd_d(0.5))); + q = vrint_vi_vd(vsub(vmul(d, vcast_vd_d(rtengine::RT_1_PI)), vcast_vd_d(0.5))); q = vaddi(vaddi(q, q), vcast_vi_i(1)); u = vcast_vd_vi(q); @@ -330,7 +331,7 @@ static INLINE vdouble2 xsincos(vdouble d) { vdouble u, s, t, rx, ry; vdouble2 r; - q = vrint_vi_vd(vmul(d, vcast_vd_d(M_2_PI))); + q = vrint_vi_vd(vmul(d, vcast_vd_d(rtengine::RT_2_PI))); s = d; @@ -374,8 +375,8 @@ static INLINE vdouble2 xsincos(vdouble d) { r.y = vreinterpret_vd_vm(vxorm(vandm(m, vreinterpret_vm_vd(vcast_vd_d(-0.0))), vreinterpret_vm_vd(r.y))); m = vmask_isinf(d); - r.x = vsel(m, vcast_vd_d(NAN), r.x); - r.y = vsel(m, vcast_vd_d(NAN), r.y); + r.x = vsel(m, vcast_vd_d(rtengine::RT_NAN), r.x); + r.y = vsel(m, vcast_vd_d(rtengine::RT_NAN), r.y); return r; } @@ -385,7 +386,7 @@ static INLINE vdouble xtan(vdouble d) { vdouble u, s, x; vmask m; - q = vrint_vi_vd(vmul(d, vcast_vd_d(M_2_PI))); + q = vrint_vi_vd(vmul(d, vcast_vd_d(rtengine::RT_2_PI))); u = vcast_vd_vi(q); x = vadd(d, vmul(u, vcast_vd_d(-PI4_A*2))); @@ -417,7 +418,7 @@ static INLINE vdouble xtan(vdouble d) { u = vsel(m, vrec(u), u); - u = vsel(vmask_isinf(d), vcast_vd_d(NAN), u); + u = vsel(vmask_isinf(d), vcast_vd_d(rtengine::RT_NAN), u); return u; } @@ -459,7 +460,7 @@ static INLINE vdouble atan2k(vdouble y, vdouble x) { u = vmla(u, t, vcast_vd_d(-0.333333333333311110369124)); t = vadd(s, vmul(s, vmul(t, u))); - t = vadd(t, vmul(vcast_vd_vi(q), vcast_vd_d(M_PI/2))); + t = vadd(t, vmul(vcast_vd_vi(q), vcast_vd_d(rtengine::RT_PI/2))); return t; } @@ -468,11 +469,11 @@ static INLINE vdouble xatan2(vdouble y, vdouble x) { vdouble r = atan2k(vabs(y), x); r = vmulsign(r, x); - r = vsel(vorm(vmask_isinf(x), vmask_eq(x, vcast_vd_d(0))), vsub(vcast_vd_d(M_PI/2), visinf2(x, vmulsign(vcast_vd_d(M_PI/2), x))), r); - r = vsel(vmask_isinf(y), vsub(vcast_vd_d(M_PI/2), visinf2(x, vmulsign(vcast_vd_d(M_PI/4), x))), r); - r = vsel(vmask_eq(y, vcast_vd_d(0)), vsel(vmask_eq(vsign(x), vcast_vd_d(-1.0)), vcast_vd_d(M_PI), vcast_vd_d(0)), r); + r = vsel(vorm(vmask_isinf(x), vmask_eq(x, vcast_vd_d(0))), vsub(vcast_vd_d(rtengine::RT_PI/2), visinf2(x, vmulsign(vcast_vd_d(rtengine::RT_PI/2), x))), r); + r = vsel(vmask_isinf(y), vsub(vcast_vd_d(rtengine::RT_PI/2), visinf2(x, vmulsign(vcast_vd_d(rtengine::RT_PI/4), x))), r); + r = vsel(vmask_eq(y, vcast_vd_d(0)), vsel(vmask_eq(vsign(x), vcast_vd_d(-1.0)), vcast_vd_d(rtengine::RT_PI), vcast_vd_d(0)), r); - return vsel(vorm(vmask_isnan(x), vmask_isnan(y)), vcast_vd_d(NAN), vmulsign(r, y)); + return vsel(vorm(vmask_isnan(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_NAN), vmulsign(r, y)); } static INLINE vdouble xasin(vdouble d) { @@ -481,7 +482,7 @@ static INLINE vdouble xasin(vdouble d) { y = vsub(vcast_vd_d(1), d); x = vmul(x, y); x = vsqrt(x); - x = vsel(vmask_isnan(x), vcast_vd_d(NAN), atan2k(vabs(d), x)); + x = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), atan2k(vabs(d), x)); return vmulsign(x, d); } @@ -492,7 +493,7 @@ static INLINE vdouble xacos(vdouble d) { x = vmul(x, y); x = vsqrt(x); x = vmulsign(atan2k(x, vabs(d)), d); - y = (vdouble)vandm(vmask_lt(d, vcast_vd_d(0)), (vmask)vcast_vd_d(M_PI)); + y = (vdouble)vandm(vmask_lt(d, vcast_vd_d(0)), (vmask)vcast_vd_d(rtengine::RT_PI)); x = vadd(x, y); return x; } @@ -531,7 +532,7 @@ static INLINE vdouble xatan(vdouble s) { t = vadd(s, vmul(s, vmul(t, u))); - t = vsel(vmaski_eq(vandi(q, vcast_vi_i(1)), vcast_vi_i(1)), vsub(vcast_vd_d(M_PI/2), t), t); + t = vsel(vmaski_eq(vandi(q, vcast_vi_i(1)), vcast_vi_i(1)), vsub(vcast_vd_d(rtengine::RT_PI/2), t), t); t = vsel(vmaski_eq(vandi(q, vcast_vi_i(2)), vcast_vi_i(2)), vneg(t), t); return t; @@ -559,9 +560,9 @@ static INLINE vdouble xlog(vdouble d) { x = vadd(vmul(x, t), vmul(vcast_vd_d(0.693147180559945286226764), vcast_vd_vi(e))); - x = vsel(vmask_ispinf(d), vcast_vd_d(INFINITY), x); - x = vsel(vmask_gt(vcast_vd_d(0), d), vcast_vd_d(NAN), x); - x = vsel(vmask_eq(d, vcast_vd_d(0)), vcast_vd_d(-INFINITY), x); + x = vsel(vmask_ispinf(d), vcast_vd_d(rtengine::RT_INFINITY), x); + x = vsel(vmask_gt(vcast_vd_d(0), d), vcast_vd_d(rtengine::RT_NAN), x); + x = vsel(vmask_eq(d, vcast_vd_d(0)), vcast_vd_d(-rtengine::RT_INFINITY), x); return x; } @@ -659,7 +660,7 @@ static INLINE vdouble xpow(vdouble x, vdouble y) { vdouble result = expk(mul_ds(logk(vabs(x)), y)); - //result = vsel(vmask_isnan(result), vcast_vd_d(INFINITY), result); + //result = vsel(vmask_isnan(result), vcast_vd_d(rtengine::RT_INFINITY), result); result = vmul(result, vsel(vmask_gt(x, vcast_vd_d(0)), @@ -668,7 +669,7 @@ static INLINE vdouble xpow(vdouble x, vdouble y) { vsel(yisodd, vcast_vd_d(-1), vcast_vd_d(1)), - vcast_vd_d(NAN)))); + vcast_vd_d(rtengine::RT_NAN)))); vdouble efx = vreinterpret_vd_vm(vxorm(vreinterpret_vm_vd(vsub(vabs(x), vcast_vd_d(1))), vsignbit(y))); @@ -677,17 +678,17 @@ static INLINE vdouble xpow(vdouble x, vdouble y) { vcast_vd_d(0), vsel(vmask_eq(efx, vcast_vd_d(0)), vcast_vd_d(1.0), - vcast_vd_d(INFINITY))), + vcast_vd_d(rtengine::RT_INFINITY))), result); result = vsel(vorm(vmask_isinf(x), vmask_eq(x, vcast_vd_d(0))), vmul(vsel(yisodd, vsign(x), vcast_vd_d(1)), vsel(vmask_lt(vsel(vmask_eq(x, vcast_vd_d(0)), vneg(y), y), vcast_vd_d(0)), vcast_vd_d(0), - vcast_vd_d(INFINITY))), + vcast_vd_d(rtengine::RT_INFINITY))), result); - result = vsel(vorm(vmask_isnan(x), vmask_isnan(y)), vcast_vd_d(NAN), result); + result = vsel(vorm(vmask_isnan(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_NAN), result); result = vsel(vorm(vmask_eq(y, vcast_vd_d(0)), vmask_eq(x, vcast_vd_d(1))), vcast_vd_d(1), result); @@ -733,9 +734,9 @@ static INLINE vdouble xsinh(vdouble x) { d = add2_dd(d, div_dd(dd(vcast_vd_d(-1), vcast_vd_d(0)), d)); y = vmul(vadd(d.x, d.y), vcast_vd_d(0.5)); - y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(INFINITY), y); + y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_INFINITY), y); y = vmulsign(y, x); - y = vsel(vmask_isnan(x), vcast_vd_d(NAN), y); + y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); return y; } @@ -745,8 +746,8 @@ static INLINE vdouble xcosh(vdouble x) { d = add2_dd(d, div_dd(dd(vcast_vd_d(1), vcast_vd_d(0)), d)); vdouble y = vmul(vadd(d.x, d.y), vcast_vd_d(0.5)); - y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(INFINITY), y); - y = vsel(vmask_isnan(x), vcast_vd_d(NAN), y); + y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_INFINITY), y); + y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); return y; } @@ -760,7 +761,7 @@ static INLINE vdouble xtanh(vdouble x) { y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(1.0), y); y = vmulsign(y, x); - y = vsel(vmask_isnan(x), vcast_vd_d(NAN), y); + y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); return y; } @@ -797,9 +798,9 @@ static INLINE vdouble xasinh(vdouble x) { vdouble2 d = logk2(add2_ds(sqrt_d(add2_ds(mul_ss(y, y), vcast_vd_d(1))), y)); y = vadd(d.x, d.y); - y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(INFINITY), y); + y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_INFINITY), y); y = vmulsign(y, x); - y = vsel(vmask_isnan(x), vcast_vd_d(NAN), y); + y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); return y; } @@ -808,10 +809,10 @@ static INLINE vdouble xacosh(vdouble x) { vdouble2 d = logk2(add2_ds(sqrt_d(add2_ds(mul_ss(x, x), vcast_vd_d(-1))), x)); vdouble y = vadd(d.x, d.y); - y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(INFINITY), y); + y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_INFINITY), y); y = vsel(vmask_eq(x, vcast_vd_d(1.0)), vcast_vd_d(0.0), y); - y = vsel(vmask_lt(x, vcast_vd_d(1.0)), vcast_vd_d(NAN), y); - y = vsel(vmask_isnan(x), vcast_vd_d(NAN), y); + y = vsel(vmask_lt(x, vcast_vd_d(1.0)), vcast_vd_d(rtengine::RT_NAN), y); + y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); return y; } @@ -819,11 +820,11 @@ static INLINE vdouble xacosh(vdouble x) { static INLINE vdouble xatanh(vdouble x) { vdouble y = vabs(x); vdouble2 d = logk2(div_dd(add2_ss(vcast_vd_d(1), y), add2_ss(vcast_vd_d(1), -y))); - y = vsel(vmask_gt(y, vcast_vd_d(1.0)), vcast_vd_d(NAN), vsel(vmask_eq(y, vcast_vd_d(1.0)), vcast_vd_d(INFINITY), vmul(vadd(d.x, d.y), vcast_vd_d(0.5)))); + y = vsel(vmask_gt(y, vcast_vd_d(1.0)), vcast_vd_d(rtengine::RT_NAN), vsel(vmask_eq(y, vcast_vd_d(1.0)), vcast_vd_d(rtengine::RT_INFINITY), vmul(vadd(d.x, d.y), vcast_vd_d(0.5)))); - y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(NAN), y); + y = vsel(vorm(vmask_isinf(x), vmask_isnan(y)), vcast_vd_d(rtengine::RT_NAN), y); y = vmulsign(y, x); - y = vsel(vmask_isnan(x), vcast_vd_d(NAN), y); + y = vsel(vmask_isnan(x), vcast_vd_d(rtengine::RT_NAN), y); return y; } @@ -864,14 +865,14 @@ static INLINE vdouble xcbrt(vdouble d) { static INLINE vdouble xexp2(vdouble a) { vdouble u = expk(mul_ds(dd(vcast_vd_d(0.69314718055994528623), vcast_vd_d(2.3190468138462995584e-17)), a)); - u = vsel(vmask_ispinf(a), vcast_vd_d(INFINITY), u); + u = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), u); u = vsel(vmask_isminf(a), vcast_vd_d(0), u); return u; } static INLINE vdouble xexp10(vdouble a) { vdouble u = expk(mul_ds(dd(vcast_vd_d(2.3025850929940459011), vcast_vd_d(-2.1707562233822493508e-16)), a)); - u = vsel(vmask_ispinf(a), vcast_vd_d(INFINITY), u); + u = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), u); u = vsel(vmask_isminf(a), vcast_vd_d(0), u); return u; } @@ -879,7 +880,7 @@ static INLINE vdouble xexp10(vdouble a) { static INLINE vdouble xexpm1(vdouble a) { vdouble2 d = add2_ds(expk2(dd(a, vcast_vd_d(0))), vcast_vd_d(-1.0)); vdouble x = d.x + d.y; - x = vsel(vmask_ispinf(a), vcast_vd_d(INFINITY), x); + x = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), x); x = vsel(vmask_isminf(a), vcast_vd_d(-1), x); return x; } @@ -888,9 +889,9 @@ static INLINE vdouble xlog10(vdouble a) { vdouble2 d = mul_dd(logk(a), dd(vcast_vd_d(0.43429448190325176116), vcast_vd_d(6.6494347733425473126e-17))); vdouble x = d.x + d.y; - x = vsel(vmask_ispinf(a), vcast_vd_d(INFINITY), x); - x = vsel(vmask_gt(vcast_vd_d(0), a), vcast_vd_d(NAN), x); - x = vsel(vmask_eq(a, vcast_vd_d(0)), vcast_vd_d(-INFINITY), x); + x = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), x); + x = vsel(vmask_gt(vcast_vd_d(0), a), vcast_vd_d(rtengine::RT_NAN), x); + x = vsel(vmask_eq(a, vcast_vd_d(0)), vcast_vd_d(-rtengine::RT_INFINITY), x); return x; } @@ -899,9 +900,9 @@ static INLINE vdouble xlog1p(vdouble a) { vdouble2 d = logk2(add2_ss(a, vcast_vd_d(1))); vdouble x = d.x + d.y; - x = vsel(vmask_ispinf(a), vcast_vd_d(INFINITY), x); - x = vsel(vmask_gt(vcast_vd_d(-1), a), vcast_vd_d(NAN), x); - x = vsel(vmask_eq(a, vcast_vd_d(-1)), vcast_vd_d(-INFINITY), x); + x = vsel(vmask_ispinf(a), vcast_vd_d(rtengine::RT_INFINITY), x); + x = vsel(vmask_gt(vcast_vd_d(-1), a), vcast_vd_d(rtengine::RT_NAN), x); + x = vsel(vmask_eq(a, vcast_vd_d(-1)), vcast_vd_d(-rtengine::RT_INFINITY), x); return x; } @@ -1005,7 +1006,7 @@ static INLINE vfloat xsinf(vfloat d) { vint2 q; vfloat u, s; - q = vrint_vi2_vf(vmulf(d, vcast_vf_f((float)M_1_PI))); + q = vrint_vi2_vf(vmulf(d, vcast_vf_f((float)rtengine::RT_1_PI))); u = vcast_vf_vi2(q); d = vmlaf(u, vcast_vf_f(-PI4_Af*4), d); @@ -1031,7 +1032,7 @@ static INLINE vfloat xcosf(vfloat d) { vint2 q; vfloat u, s; - q = vrint_vi2_vf(vsubf(vmulf(d, vcast_vf_f((float)M_1_PI)), vcast_vf_f(0.5f))); + q = vrint_vi2_vf(vsubf(vmulf(d, vcast_vf_f((float)rtengine::RT_1_PI)), vcast_vf_f(0.5f))); q = vaddi2(vaddi2(q, q), vcast_vi2_i(1)); u = vcast_vf_vi2(q); @@ -1060,7 +1061,7 @@ static INLINE vfloat2 xsincosf(vfloat d) { vfloat u, s, t, rx, ry; vfloat2 r; - q = vrint_vi2_vf(vmulf(d, vcast_vf_f((float)M_2_PI))); + q = vrint_vi2_vf(vmulf(d, vcast_vf_f((float)rtengine::RT_2_PI))); s = d; @@ -1100,8 +1101,8 @@ static INLINE vfloat2 xsincosf(vfloat d) { r.y = vreinterpret_vf_vm(vxorm(vandm(m, vreinterpret_vm_vf(vcast_vf_f(-0.0))), vreinterpret_vm_vf(r.y))); m = vmaskf_isinf(d); - r.x = vself(m, vcast_vf_f(NAN), r.x); - r.y = vself(m, vcast_vf_f(NAN), r.y); + r.x = vself(m, vcast_vf_f(rtengine::RT_NAN), r.x); + r.y = vself(m, vcast_vf_f(rtengine::RT_NAN), r.y); return r; } @@ -1111,7 +1112,7 @@ static INLINE vfloat xtanf(vfloat d) { vmask m; vfloat u, s, x; - q = vrint_vi2_vf(vmulf(d, vcast_vf_f((float)(2 * M_1_PI)))); + q = vrint_vi2_vf(vmulf(d, vcast_vf_f((float)(2 * rtengine::RT_1_PI)))); x = d; @@ -1165,7 +1166,7 @@ static INLINE vfloat xatanf(vfloat s) { t = vaddf(s, vmulf(s, vmulf(t, u))); - t = vself(vmaski2_eq(vandi2(q, vcast_vi2_i(1)), vcast_vi2_i(1)), vsubf(vcast_vf_f((float)(M_PI/2)), t), t); + t = vself(vmaski2_eq(vandi2(q, vcast_vi2_i(1)), vcast_vi2_i(1)), vsubf(vcast_vf_f((float)(rtengine::RT_PI/2)), t), t); t = vself(vmaski2_eq(vandi2(q, vcast_vi2_i(2)), vcast_vi2_i(2)), vnegf(t), t); return t; @@ -1197,7 +1198,7 @@ static INLINE vfloat atan2kf(vfloat y, vfloat x) { u = vmlaf(u, t, vcast_vf_f(-0.333331018686294555664062f)); t = vaddf(s, vmulf(s, vmulf(t, u))); - t = vaddf(t, vmulf(vcast_vf_vi2(q), vcast_vf_f((float)(M_PI/2)))); + t = vaddf(t, vmulf(vcast_vf_vi2(q), vcast_vf_f((float)(rtengine::RT_PI/2)))); return t; } @@ -1206,9 +1207,9 @@ static INLINE vfloat xatan2f(vfloat y, vfloat x) { vfloat r = atan2kf(vabsf(y), x); r = vmulsignf(r, x); - r = vself(vorm(vmaskf_isinf(x), vmaskf_eq(x, vcast_vf_f(0.0f))), vsubf(vcast_vf_f((float)(M_PI/2)), visinf2f(x, vmulsignf(vcast_vf_f((float)(M_PI/2)), x))), r); - r = vself(vmaskf_isinf(y), vsubf(vcast_vf_f((float)(M_PI/2)), visinf2f(x, vmulsignf(vcast_vf_f((float)(M_PI/4)), x))), r); - r = vself(vmaskf_eq(y, vcast_vf_f(0.0f)), vselfzero(vmaskf_eq(vsignf(x), vcast_vf_f(-1.0f)), vcast_vf_f((float)M_PI)), r); + r = vself(vorm(vmaskf_isinf(x), vmaskf_eq(x, vcast_vf_f(0.0f))), vsubf(vcast_vf_f((float)(rtengine::RT_PI/2)), visinf2f(x, vmulsignf(vcast_vf_f((float)(rtengine::RT_PI/2)), x))), r); + r = vself(vmaskf_isinf(y), vsubf(vcast_vf_f((float)(rtengine::RT_PI/2)), visinf2f(x, vmulsignf(vcast_vf_f((float)(rtengine::RT_PI/4)), x))), r); + r = vself(vmaskf_eq(y, vcast_vf_f(0.0f)), vselfzero(vmaskf_eq(vsignf(x), vcast_vf_f(-1.0f)), vcast_vf_f((float)rtengine::RT_PI)), r); return vself(vorm(vmaskf_isnan(x), vmaskf_isnan(y)), vcast_vf_f(NANf), vmulsignf(r, y)); } @@ -1230,7 +1231,7 @@ static INLINE vfloat xacosf(vfloat d) { x = vmulf(x, y); x = vsqrtf(x); x = vmulsignf(atan2kf(x, vabsf(d)), d); - y = (vfloat)vandm(vmaskf_lt(d, vcast_vf_f(0.0f)), (vmask)vcast_vf_f((float)M_PI)); + y = (vfloat)vandm(vmaskf_lt(d, vcast_vf_f(0.0f)), (vmask)vcast_vf_f((float)rtengine::RT_PI)); x = vaddf(x, y); return x; } diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc index ed960508e..5e7001028 100644 --- a/rtengine/stdimagesource.cc +++ b/rtengine/stdimagesource.cc @@ -102,7 +102,7 @@ void StdImageSource::getSampleFormat (const Glib::ustring &fname, IIOSampleForma * and RT's image data type (Image8, Image16 and Imagefloat), then it will * load the image into it */ -int StdImageSource::load (const Glib::ustring &fname, bool batch) +int StdImageSource::load (const Glib::ustring &fname, int imageNum, bool batch) { fileName = fname; @@ -276,20 +276,19 @@ void StdImageSource::colorSpaceConversion (Imagefloat* im, const ColorManagement void StdImageSource::getFullSize (int& w, int& h, int tr) { - w = img->width; - h = img->height; + w = img->getWidth(); + h = img->getHeight(); if ((tr & TR_ROT) == TR_R90 || (tr & TR_ROT) == TR_R270) { - w = img->height; - h = img->width; + w = img->getHeight(); + h = img->getWidth(); } } void StdImageSource::getSize (PreviewProps pp, int& w, int& h) { - - w = pp.w / pp.skip + (pp.w % pp.skip > 0); - h = pp.h / pp.skip + (pp.h % pp.skip > 0); + w = pp.getWidth() / pp.getSkip() + (pp.getWidth() % pp.getSkip() > 0); + h = pp.getHeight() / pp.getSkip() + (pp.getHeight() % pp.getSkip() > 0); } void StdImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index 0ef487a75..1dbddf325 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -42,7 +42,7 @@ public: StdImageSource (); ~StdImageSource (); - int load (const Glib::ustring &fname, bool batch = false); + int load (const Glib::ustring &fname, int imageNum = 0, bool batch = false); void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const ColorManagementParams &cmp, const RAWParams &raw); ColorTemp getWB () const { @@ -95,6 +95,11 @@ public: { return rgbSourceModified; } + void setCurrentFrame(unsigned int frameNum) {} + + void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) { R = G = B = 0;} + + }; } #endif diff --git a/rtengine/utils.cc b/rtengine/utils.cc index f5b3e496b..c9bce803d 100644 --- a/rtengine/utils.cc +++ b/rtengine/utils.cc @@ -245,4 +245,19 @@ bool hasPngExtension(const Glib::ustring& filename) return getFileExtension(filename) == "png"; } +void swab(const void* from, void* to, ssize_t n) +{ + // Adapted from glibc + const char* char_from = static_cast(from); + char* char_to = static_cast(to); + + n &= ~static_cast(1); + + while (n > 1) { + const char b0 = char_from[--n], b1 = char_from[--n]; + char_to[n] = b0; + char_to[n + 1] = b1; + } +} + } diff --git a/rtengine/utils.h b/rtengine/utils.h index b2c1d16a8..9c56ad0a0 100644 --- a/rtengine/utils.h +++ b/rtengine/utils.h @@ -52,4 +52,6 @@ bool hasTiffExtension(const Glib::ustring& filename); // Return true if file has .png extension (ignoring case) bool hasPngExtension(const Glib::ustring& filename); +void swab(const void* from, void* to, ssize_t n); + } diff --git a/rtexif/pentaxattribs.cc b/rtexif/pentaxattribs.cc index 9fc6b6fb6..13dca86b1 100644 --- a/rtexif/pentaxattribs.cc +++ b/rtexif/pentaxattribs.cc @@ -42,6 +42,7 @@ public: choices[3] = "TIFF"; choices[4] = "RAW"; choices[5] = "Premium"; + choices[6] = "RAW (HDR enabled)"; choices[7] = "RAW (pixel shift enabled)"; choices[65535] = "n/a"; } diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index f6fc98371..bc12ea6aa 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -5,7 +5,7 @@ set (CLISOURCEFILES set (NONCLISOURCEFILES editwindow.cc batchtoolpanelcoord.cc paramsedited.cc cropwindow.cc previewhandler.cc previewwindow.cc navigator.cc indclippedpanel.cc previewmodepanel.cc filterpanel.cc - exportpanel.cc cursormanager.cc rtwindow.cc renamedlg.cc recentbrowser.cc placesbrowser.cc filepanel.cc editorpanel.cc batchqueuepanel.cc + exportpanel.cc cursormanager.cc rtwindow.cc renamedlg.cc recentbrowser.cc placesbrowser.cc filepanel.cc editorpanel.cc batchqueuepanel.cc checkbox.cc ilabel.cc thumbbrowserbase.cc adjuster.cc filebrowserentry.cc filebrowser.cc filethumbnailbuttonset.cc cachemanager.cc cacheimagedata.cc shcselector.cc perspective.cc thresholdselector.cc thresholdadjuster.cc clipboard.cc thumbimageupdater.cc bqentryupdater.cc lensgeom.cc coloredbar.cc edit.cc coordinateadjuster.cc @@ -34,7 +34,8 @@ set (NONCLISOURCEFILES darkframe.cc flatfield.cc rawcacorrection.cc rawexposure.cc wavelet.cc dirpyrequalizer.cc hsvequalizer.cc defringe.cc popupcommon.cc popupbutton.cc popuptogglebutton.cc sharpenedge.cc sharpenmicro.cc colorappearance.cc - filmsimulation.cc prsharpening.cc) + filmsimulation.cc prsharpening.cc + dynamicprofile.cc dynamicprofilepanel.cc) include_directories (BEFORE "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h index 580874e5a..898ef9528 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -115,6 +115,7 @@ enum { ADDSET_RETI_VART, ADDSET_RETI_GAM, ADDSET_RETI_SLO, + ADDSET_WB_TEMPBIAS, ADDSET_PARAM_NUM // THIS IS USED AS A DELIMITER!! }; diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index 66f5341fa..1810501b5 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -115,6 +115,8 @@ BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) if (Glib::file_test (options.savePathFolder, Glib::FILE_TEST_IS_DIR)) { outdirFolder->set_current_folder (options.savePathFolder); + } else { + outdirFolder->set_current_folder (Glib::get_home_dir()); } outdirFolderButton = 0; diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index 2caa61187..63ece79b2 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -152,7 +152,7 @@ void BatchToolPanelCoordinator::initSession () toneCurve->setAdjusterBehavior (false, false, false, false, false, false, false, false); lcurve->setAdjusterBehavior (false, false, false); - whitebalance->setAdjusterBehavior (false, false, false); + whitebalance->setAdjusterBehavior (false, false, false, false); vibrance->setAdjusterBehavior (false, false); vignetting->setAdjusterBehavior (false, false, false, false); colorappearance->setAdjusterBehavior (false, false, false, false, false, false, false, false, false, false, false, false, false); @@ -191,7 +191,7 @@ void BatchToolPanelCoordinator::initSession () toneCurve->setAdjusterBehavior (options.baBehav[ADDSET_TC_EXPCOMP], options.baBehav[ADDSET_TC_HLCOMPAMOUNT], options.baBehav[ADDSET_TC_HLCOMPTHRESH], options.baBehav[ADDSET_TC_BRIGHTNESS], options.baBehav[ADDSET_TC_BLACKLEVEL], options.baBehav[ADDSET_TC_SHCOMP], options.baBehav[ADDSET_TC_CONTRAST], options.baBehav[ADDSET_TC_SATURATION]); lcurve->setAdjusterBehavior (options.baBehav[ADDSET_LC_BRIGHTNESS], options.baBehav[ADDSET_LC_CONTRAST], options.baBehav[ADDSET_LC_CHROMATICITY]); - whitebalance->setAdjusterBehavior (options.baBehav[ADDSET_WB_TEMPERATURE], options.baBehav[ADDSET_WB_GREEN], options.baBehav[ADDSET_WB_EQUAL]); + whitebalance->setAdjusterBehavior (options.baBehav[ADDSET_WB_TEMPERATURE], options.baBehav[ADDSET_WB_GREEN], options.baBehav[ADDSET_WB_EQUAL], options.baBehav[ADDSET_WB_TEMPBIAS]); vibrance->setAdjusterBehavior (options.baBehav[ADDSET_VIBRANCE_PASTELS], options.baBehav[ADDSET_VIBRANCE_SATURATED]); vignetting->setAdjusterBehavior (options.baBehav[ADDSET_VIGN_AMOUNT], options.baBehav[ADDSET_VIGN_RADIUS], options.baBehav[ADDSET_VIGN_STRENGTH], options.baBehav[ADDSET_VIGN_CENTER]); colorappearance->setAdjusterBehavior (options.baBehav[ADDSET_CAT_DEGREE], options.baBehav[ADDSET_CAT_ADAPTSCENE], options.baBehav[ADDSET_CAT_ADAPTVIEWING], options.baBehav[ADDSET_CAT_BADPIX], options.baBehav[ADDSET_CAT_LIGHT], options.baBehav[ADDSET_CAT_CHROMA], options.baBehav[ADDSET_CAT_CONTRAST], options.baBehav[ADDSET_CAT_RSTPRO], options.baBehav[ADDSET_CAT_BRIGHT], options.baBehav[ADDSET_CAT_CONTRAST_Q], options.baBehav[ADDSET_CAT_CHROMA_S], options.baBehav[ADDSET_CAT_CHROMA_M], options.baBehav[ADDSET_CAT_HUE]); @@ -325,6 +325,10 @@ void BatchToolPanelCoordinator::initSession () pparams.wb.equal = 0; } + if (options.baBehav[ADDSET_WB_TEMPBIAS]) { + pparams.wb.tempBias = 0; + } + if (options.baBehav[ADDSET_VIBRANCE_PASTELS]) { pparams.vibrance.pastels = 0; } @@ -856,11 +860,11 @@ void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const G } } -void BatchToolPanelCoordinator::getAutoWB (double& temp, double& green, double equal) +void BatchToolPanelCoordinator::getAutoWB (double& temp, double& green, double equal, double tempBias) { if (!selected.empty()) { - selected[0]->getAutoWB (temp, green, equal); + selected[0]->getAutoWB (temp, green, equal, tempBias); } } diff --git a/rtgui/batchtoolpanelcoord.h b/rtgui/batchtoolpanelcoord.h index c96a1a329..4efcea6fa 100644 --- a/rtgui/batchtoolpanelcoord.h +++ b/rtgui/batchtoolpanelcoord.h @@ -60,7 +60,7 @@ public: void profileChange (const rtengine::procparams::PartialProfile* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited = nullptr); // wbprovider interface - void getAutoWB (double& temp, double& green, double equal); + void getAutoWB (double& temp, double& green, double equal, double tempBias); void getCamWB (double& temp, double& green); // thumbnaillistener interface diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index e1bf790a6..75b27b360 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -22,6 +22,7 @@ using namespace rtengine; using namespace rtengine::procparams; + BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RAW_LABEL"), true) { Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); @@ -38,6 +39,30 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA hb1->pack_end (*method, Gtk::PACK_EXPAND_WIDGET, 4); pack_start( *hb1, Gtk::PACK_SHRINK, 4); + imageNumberBox = Gtk::manage (new Gtk::HBox ()); + imageNumberBox->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_IMAGENUM") + ": ")), Gtk::PACK_SHRINK, 4); + imageNumber = Gtk::manage (new MyComboBoxText ()); + imageNumber->append("1"); + imageNumber->append("2"); + imageNumber->append("3"); + imageNumber->append("4"); + imageNumber->set_active(0); + imageNumberBox->set_tooltip_text(M("TP_RAW_IMAGENUM_TOOLTIP")); + imageNumberBox->pack_end (*imageNumber, Gtk::PACK_EXPAND_WIDGET, 4); + pack_start( *imageNumberBox, Gtk::PACK_SHRINK, 4); + + pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); + ccSteps = Gtk::manage (new Adjuster (M("TP_RAW_FALSECOLOR"), 0, 5, 1, 0 )); + ccSteps->setAdjusterListener (this); + + if (ccSteps->delay < options.adjusterMaxDelay) { + ccSteps->delay = options.adjusterMaxDelay; + } + + ccSteps->show(); + pack_start( *ccSteps, Gtk::PACK_SHRINK, 4); + + dcbOptions = Gtk::manage (new Gtk::VBox ()); dcbIterations = Gtk::manage (new Adjuster (M("TP_RAW_DCBITERATIONS"), 0, 5, 1, 2)); @@ -48,7 +73,8 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA } dcbIterations->show(); - dcbEnhance = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_DCBENHANCE"))); + dcbEnhance = Gtk::manage (new CheckBox(M("TP_RAW_DCBENHANCE"), multiImage)); + dcbEnhance->setCheckBoxListener (this); dcbOptions->pack_start(*dcbIterations); dcbOptions->pack_start(*dcbEnhance); pack_start( *dcbOptions, Gtk::PACK_SHRINK, 4); @@ -67,92 +93,413 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA lmmseOptions->pack_start(*lmmseIterations); pack_start( *lmmseOptions, Gtk::PACK_SHRINK, 4); - pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); - ccSteps = Gtk::manage (new Adjuster (M("TP_RAW_FALSECOLOR"), 0, 5, 1, 0 )); - ccSteps->setAdjusterListener (this); + pixelShiftFrame = Gtk::manage (new Gtk::VBox ()); + pixelShiftFrame->set_border_width(0); - if (ccSteps->delay < options.adjusterMaxDelay) { - ccSteps->delay = options.adjusterMaxDelay; + pixelShiftEqualBright = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTEQUALBRIGHT"), multiImage)); + pixelShiftEqualBright->setCheckBoxListener (this); + pixelShiftEqualBright->set_tooltip_text (M("TP_RAW_PIXELSHIFTEQUALBRIGHT_TOOLTIP")); + pixelShiftFrame->pack_start(*pixelShiftEqualBright); + + Gtk::HBox* hb3 = Gtk::manage (new Gtk::HBox ()); + hb3->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_PIXELSHIFTMOTIONMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); + pixelShiftMotionMethod = Gtk::manage (new MyComboBoxText ()); + pixelShiftMotionMethod->append(M("TP_RAW_PIXELSHIFTMM_OFF")); + pixelShiftMotionMethod->append(M("TP_RAW_PIXELSHIFTMM_AUTO")); + pixelShiftMotionMethod->append(M("TP_RAW_PIXELSHIFTMM_CUSTOM")); + pixelShiftMotionMethod->set_active(RAWParams::BayerSensor::ePSMotionCorrectionMethod::Automatic); + pixelShiftMotionMethod->show(); + hb3->pack_start(*pixelShiftMotionMethod); + pixelShiftFrame->pack_start(*hb3); + + pixelShiftOptions = Gtk::manage (new Gtk::VBox ()); + pixelShiftOptions->set_border_width(0); + + pixelShiftShowMotion = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTSHOWMOTION"), multiImage)); + pixelShiftShowMotion->setCheckBoxListener (this); + pixelShiftShowMotion->set_tooltip_text (M("TP_RAW_PIXELSHIFTSHOWMOTION_TOOLTIP")); + pixelShiftFrame->pack_start(*pixelShiftShowMotion); + + pixelShiftShowMotionMaskOnly = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY"), multiImage)); + pixelShiftShowMotionMaskOnly->setCheckBoxListener (this); + pixelShiftShowMotionMaskOnly->set_tooltip_text (M("TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY_TOOLTIP")); + pixelShiftFrame->pack_start(*pixelShiftShowMotionMaskOnly); + +#ifdef PIXELSHIFTDEV + pixelShiftAutomatic = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTADAPTIVE"), multiImage)); + pixelShiftAutomatic->setCheckBoxListener (this); + pixelShiftOptions->pack_start(*pixelShiftAutomatic); +#endif + pixelShiftGreen = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTGREEN"), multiImage)); + pixelShiftGreen->setCheckBoxListener (this); + pixelShiftOptions->pack_start(*pixelShiftGreen); + + pixelShiftNonGreenCross = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTNONGREENCROSS"), multiImage)); + pixelShiftNonGreenCross->setCheckBoxListener (this); + pixelShiftOptions->pack_start(*pixelShiftNonGreenCross); + + pixelShiftHoleFill = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTHOLEFILL"), multiImage)); + pixelShiftHoleFill->setCheckBoxListener (this); + pixelShiftHoleFill->set_tooltip_text (M("TP_RAW_PIXELSHIFTHOLEFILL_TOOLTIP")); + pixelShiftOptions->pack_start(*pixelShiftHoleFill); + + pixelShiftBlur = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTBLUR"), multiImage)); + pixelShiftBlur->setCheckBoxListener (this); + pixelShiftBlur->set_tooltip_text (M("TP_RAW_PIXELSHIFTSIGMA_TOOLTIP")); + pixelShiftOptions->pack_start(*pixelShiftBlur); + + pixelShiftSigma = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTSIGMA"), 0.5, 25, 0.1, 1.0)); + pixelShiftSigma->set_tooltip_text (M("TP_RAW_PIXELSHIFTSIGMA_TOOLTIP")); + pixelShiftSigma->setAdjusterListener (this); + + if (pixelShiftSigma->delay < options.adjusterMaxDelay) { + pixelShiftSigma->delay = options.adjusterMaxDelay; } - ccSteps->show(); - pack_start( *ccSteps, Gtk::PACK_SHRINK, 4); + pixelShiftSigma->show(); + pixelShiftOptions->pack_start(*pixelShiftSigma); - //pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); - //allOptions = Gtk::manage (new Gtk::VBox ()); - //allEnhance = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_ALLENHANCE"))); - //allOptions->pack_start(*allEnhance); - //pack_start( *allOptions, Gtk::PACK_SHRINK, 4); - methodconn = method->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::methodChanged) ); - dcbEnhconn = dcbEnhance->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::dcbEnhanceChanged), true); - //allEnhconn = allEnhance->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::allEnhanceChanged), true); + pixelShiftSmooth = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTSMOOTH"), 0, 1, 0.05, 0.7)); + pixelShiftSmooth->set_tooltip_text (M("TP_RAW_PIXELSHIFTSMOOTH_TOOLTIP")); + pixelShiftSmooth->setAdjusterListener (this); + + if (pixelShiftSmooth->delay < options.adjusterMaxDelay) { + pixelShiftSmooth->delay = options.adjusterMaxDelay; + } + + pixelShiftSmooth->show(); + pixelShiftOptions->pack_start(*pixelShiftSmooth); + + pixelShiftEperIso = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTEPERISO"), -5.0, 5.0, 0.05, 0.0)); + pixelShiftEperIso->set_tooltip_text(M("TP_RAW_PIXELSHIFTEPERISO_TOOLTIP")); + pixelShiftEperIso->setAdjusterListener (this); + + if (pixelShiftEperIso->delay < options.adjusterMaxDelay) { + pixelShiftEperIso->delay = options.adjusterMaxDelay; + } + + pixelShiftEperIso->show(); + pixelShiftOptions->pack_start(*pixelShiftEperIso); + + + pixelShiftMedian = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTMEDIAN"), multiImage)); + pixelShiftMedian->setCheckBoxListener (this); + pixelShiftMedian->set_tooltip_text (M("TP_RAW_PIXELSHIFTMEDIAN_TOOLTIP")); + pixelShiftOptions->pack_start(*pixelShiftMedian); + + +#ifdef PIXELSHIFTDEV + pixelShiftMedian3 = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTMEDIAN3"), multiImage)); + pixelShiftMedian3->setCheckBoxListener (this); + pixelShiftMedian3->set_tooltip_text (M("TP_RAW_PIXELSHIFTMEDIAN3_TOOLTIP")); + pixelShiftOptions->pack_start(*pixelShiftMedian3); + + pixelShiftNonGreenCross2 = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTNONGREENCROSS2"), multiImage)); + pixelShiftNonGreenCross2->setCheckBoxListener (this); + pixelShiftOptions->pack_start(*pixelShiftNonGreenCross2); + + pixelShiftNonGreenAmaze = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTNONGREENAMAZE"), multiImage)); + pixelShiftNonGreenAmaze->setCheckBoxListener (this); + pixelShiftOptions->pack_start(*pixelShiftNonGreenAmaze); + + pixelShiftNonGreenHorizontal = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTNONGREENHORIZONTAL"), multiImage)); + pixelShiftNonGreenHorizontal->setCheckBoxListener (this); + pixelShiftOptions->pack_start(*pixelShiftNonGreenHorizontal); + + pixelShiftNonGreenVertical = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTNONGREENVERTICAL"), multiImage)); + pixelShiftNonGreenVertical->setCheckBoxListener (this); + pixelShiftOptions->pack_start(*pixelShiftNonGreenVertical); + + pixelShiftExp0 = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTEXP0"), multiImage)); + pixelShiftExp0->setCheckBoxListener (this); + pixelShiftOptions->pack_start(*pixelShiftExp0); +#endif + pixelShiftLmmse = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTLMMSE"), multiImage)); + pixelShiftLmmse->setCheckBoxListener (this); + pixelShiftLmmse->set_tooltip_text (M("TP_RAW_PIXELSHIFTLMMSE_TOOLTIP")); + pixelShiftOptions->pack_start(*pixelShiftLmmse); + +#ifdef PIXELSHIFTDEV + pixelShiftMotion = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTMOTION"), 0, 100, 1, 70)); + pixelShiftMotion->setAdjusterListener (this); + pixelShiftMotion->set_tooltip_text (M("TP_RAW_PIXELSHIFTMOTION_TOOLTIP")); + + if (pixelShiftMotion->delay < options.adjusterMaxDelay) { + pixelShiftMotion->delay = options.adjusterMaxDelay; + } + pixelShiftMotion->show(); + pixelShiftOptions->pack_start(*pixelShiftMotion); + + Gtk::HBox* hb2 = Gtk::manage (new Gtk::HBox ()); + hb2->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_PIXELSHIFTMOTIONCORRECTION") + ": ")), Gtk::PACK_SHRINK, 0); + pixelShiftMotionCorrection = Gtk::manage (new MyComboBoxText ()); + pixelShiftMotionCorrection->append("1x1"); + pixelShiftMotionCorrection->append("1x2"); + pixelShiftMotionCorrection->append("3x3"); + pixelShiftMotionCorrection->append("5x5"); + pixelShiftMotionCorrection->append("7x7"); + pixelShiftMotionCorrection->append("3x3 new"); + pixelShiftMotionCorrection->set_active(0); + pixelShiftMotionCorrection->show(); + hb2->pack_start(*pixelShiftMotionCorrection); + pixelShiftOptions->pack_start(*hb2); + pixelShiftStddevFactorGreen = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTSTDDEVFACTORGREEN"), 2, 8, 0.1, 5)); + pixelShiftStddevFactorGreen->setAdjusterListener (this); + + if (pixelShiftStddevFactorGreen->delay < options.adjusterMaxDelay) { + pixelShiftStddevFactorGreen->delay = options.adjusterMaxDelay; + } + + pixelShiftStddevFactorGreen->show(); + pixelShiftOptions->pack_start(*pixelShiftStddevFactorGreen); + + pixelShiftStddevFactorRed = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTSTDDEVFACTORRED"), 1, 8, 0.1, 5)); + pixelShiftStddevFactorRed->setAdjusterListener (this); + + if (pixelShiftStddevFactorRed->delay < options.adjusterMaxDelay) { + pixelShiftStddevFactorRed->delay = options.adjusterMaxDelay; + } + + pixelShiftStddevFactorRed->show(); + pixelShiftOptions->pack_start(*pixelShiftStddevFactorRed); + + pixelShiftStddevFactorBlue = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTSTDDEVFACTORBLUE"), 1, 8, 0.1, 5)); + pixelShiftStddevFactorBlue->setAdjusterListener (this); + + if (pixelShiftStddevFactorBlue->delay < options.adjusterMaxDelay) { + pixelShiftStddevFactorBlue->delay = options.adjusterMaxDelay; + } + + pixelShiftStddevFactorBlue->show(); + pixelShiftOptions->pack_start(*pixelShiftStddevFactorBlue); +#endif + +#ifdef PIXELSHIFTDEV + pixelShiftNreadIso = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTNREADISO"), -2.0, 2.0, 0.05, 0.0)); + pixelShiftNreadIso->setAdjusterListener (this); + + if (pixelShiftNreadIso->delay < options.adjusterMaxDelay) { + pixelShiftNreadIso->delay = options.adjusterMaxDelay; + } + + pixelShiftNreadIso->show(); + pixelShiftOptions->pack_start(*pixelShiftNreadIso); + + + pixelShiftPrnu = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTPRNU"), 0.3, 2.0, 0.1, 1.0)); + pixelShiftPrnu->setAdjusterListener (this); + + if (pixelShiftPrnu->delay < options.adjusterMaxDelay) { + pixelShiftPrnu->delay = options.adjusterMaxDelay; + } + + pixelShiftPrnu->show(); + pixelShiftOptions->pack_start(*pixelShiftPrnu); + + pixelShiftSum = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTMASKTHRESHOLD"), 1.0, 8.0, 0.1, 3.0)); + pixelShiftSum->setAdjusterListener (this); + + if (pixelShiftSum->delay < options.adjusterMaxDelay) { + pixelShiftSum->delay = options.adjusterMaxDelay; + } + + pixelShiftSum->show(); + pixelShiftOptions->pack_start(*pixelShiftSum); + + pixelShiftRedBlueWeight = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTREDBLUEWEIGHT"), 0.1, 1.0, 0.1, 0.7)); + pixelShiftRedBlueWeight->setAdjusterListener (this); + + if (pixelShiftRedBlueWeight->delay < options.adjusterMaxDelay) { + pixelShiftRedBlueWeight->delay = options.adjusterMaxDelay; + } + + pixelShiftRedBlueWeight->show(); + pixelShiftOptions->pack_start(*pixelShiftRedBlueWeight); +#endif + + pixelShiftFrame->pack_start(*pixelShiftOptions); + pixelShiftOptions->hide(); + + pack_start( *pixelShiftFrame, Gtk::PACK_SHRINK, 4); + + method->connect(method->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::methodChanged) )); + imageNumber->connect(imageNumber->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::imageNumberChanged) )); + pixelShiftMotionMethod->connect(pixelShiftMotionMethod->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::pixelShiftMotionMethodChanged) )); +#ifdef PIXELSHIFTDEV + pixelShiftMotionCorrection->connect(pixelShiftMotionCorrection->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::psMotionCorrectionChanged) )); +#endif } void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { disableListener (); - methodconn.block (true); - dcbEnhconn.block (true); + method->block (true); + imageNumber->block (true); //allEnhconn.block (true); +#ifdef PIXELSHIFTDEV + pixelShiftMotionCorrection->block (true); +#endif method->set_active(procparams::RAWParams::BayerSensor::numMethods); + imageNumber->set_active(pp->raw.bayersensor.imageNum); - for( size_t i = 0; i < procparams::RAWParams::BayerSensor::numMethods; i++) + for( size_t i = 0; i < procparams::RAWParams::BayerSensor::numMethods; i++) { if( pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[i]) { method->set_active(i); - oldSelection = i; + oldMethod = i; break; } - - if(pedited ) { - ccSteps->setEditedState (pedited->raw.bayersensor.ccSteps ? Edited : UnEdited); - dcbIterations->setEditedState ( pedited->raw.bayersensor.dcbIterations ? Edited : UnEdited); - dcbEnhance->set_inconsistent(!pedited->raw.bayersensor.dcbEnhance); - //allEnhance->set_inconsistent(!pedited->raw.bayersensor.allEnhance); - lmmseIterations->setEditedState ( pedited->raw.bayersensor.lmmseIterations ? Edited : UnEdited); - - if( !pedited->raw.bayersensor.method ) { - method->set_active(procparams::RAWParams::BayerSensor::numMethods); // No name - } } //allEnhance->set_active(pp->raw.bayersensor.all_enhance); dcbIterations->setValue (pp->raw.bayersensor.dcb_iterations); - dcbEnhance->set_active(pp->raw.bayersensor.dcb_enhance); + dcbEnhance->setValue (pp->raw.bayersensor.dcb_enhance); + pixelShiftShowMotion->setValue (pp->raw.bayersensor.pixelshiftShowMotion); + if (!batchMode) { + pixelShiftShowMotionMaskOnly->set_sensitive (pp->raw.bayersensor.pixelshiftShowMotion); + } + pixelShiftShowMotionMaskOnly->setValue (pp->raw.bayersensor.pixelshiftShowMotionMaskOnly); + pixelShiftHoleFill->setValue (pp->raw.bayersensor.pixelShiftHoleFill); + pixelShiftMedian->setValue (pp->raw.bayersensor.pixelShiftMedian); + pixelShiftGreen->setValue (pp->raw.bayersensor.pixelShiftGreen); + pixelShiftBlur->setValue (pp->raw.bayersensor.pixelShiftBlur); + if (!batchMode) { + pixelShiftSmooth->set_sensitive (pp->raw.bayersensor.pixelShiftBlur); + } + pixelShiftSmooth->setValue (pp->raw.bayersensor.pixelShiftSmoothFactor); + pixelShiftLmmse->setValue (pp->raw.bayersensor.pixelShiftLmmse); + pixelShiftEqualBright->setValue (pp->raw.bayersensor.pixelShiftEqualBright); + pixelShiftNonGreenCross->setValue (pp->raw.bayersensor.pixelShiftNonGreenCross); ccSteps->setValue (pp->raw.bayersensor.ccSteps); - - if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::dcb] || - method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) { - dcbOptions->show(); - } else { - dcbOptions->hide(); - } - lmmseIterations->setValue (pp->raw.bayersensor.lmmse_iterations); + pixelShiftMotionMethod->set_active ((int)pp->raw.bayersensor.pixelShiftMotionCorrectionMethod); + pixelShiftEperIso->setValue (pp->raw.bayersensor.pixelShiftEperIso); + pixelShiftSigma->setValue (pp->raw.bayersensor.pixelShiftSigma); + if (!batchMode) { + pixelShiftSigma->set_sensitive (pp->raw.bayersensor.pixelShiftBlur); + } +#ifdef PIXELSHIFTDEV + pixelShiftStddevFactorGreen->setValue (pp->raw.bayersensor.pixelShiftStddevFactorGreen); + pixelShiftStddevFactorRed->setValue (pp->raw.bayersensor.pixelShiftStddevFactorRed); + pixelShiftStddevFactorBlue->setValue (pp->raw.bayersensor.pixelShiftStddevFactorBlue); + pixelShiftSum->setValue (pp->raw.bayersensor.pixelShiftSum); + pixelShiftMedian3->setValue (pp->raw.bayersensor.pixelShiftMedian3); + if (!batchMode) { + pixelShiftMedian3->set_sensitive (pixelShiftMedian->getValue() != CheckValue::off); + } + pixelShiftAutomatic->setValue (pp->raw.bayersensor.pixelShiftAutomatic); + pixelShiftNonGreenHorizontal->setValue (pp->raw.bayersensor.pixelShiftNonGreenHorizontal); + pixelShiftNonGreenVertical->setValue (pp->raw.bayersensor.pixelShiftNonGreenVertical); + pixelShiftExp0->setValue (pp->raw.bayersensor.pixelShiftExp0); + pixelShiftNonGreenCross2->setValue (pp->raw.bayersensor.pixelShiftNonGreenCross2); + pixelShiftNonGreenAmaze->setValue (pp->raw.bayersensor.pixelShiftNonGreenAmaze); + pixelShiftMotion->setValue (pp->raw.bayersensor.pixelShiftMotion); + pixelShiftMotionCorrection->setValue ((int)pp->raw.bayersensor.pixelShiftMotionCorrection); + if (!batchMode) { + pixelShiftHoleFill->set_sensitive (pixelShiftAutomatic->getValue () != CheckValue::off && pixelShiftMotionCorrection->get_active_row_number() == 5); + pixelShiftBlur->set_sensitive(pixelShiftAutomatic->getValue () != CheckValue::off && pixelShiftMotionCorrection->get_active_row_number() == 5); + pixelShiftSmooth->set_sensitive(pixelShiftAutomatic->getValue () != CheckValue::off && pixelShiftMotionCorrection->get_active_row_number() == 5 && pixelShiftBlur->getValue() != CheckValue::off); + } + pixelShiftNreadIso->setValue (pp->raw.bayersensor.pixelShiftNreadIso); + pixelShiftPrnu->setValue (pp->raw.bayersensor.pixelShiftPrnu); + pixelShiftRedBlueWeight->setValue (pp->raw.bayersensor.pixelShiftRedBlueWeight); +#endif - if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::lmmse] || - method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) { - lmmseOptions->show(); - } else { - lmmseOptions->hide(); + if(pedited) { + ccSteps->setEditedState (pedited->raw.bayersensor.ccSteps ? Edited : UnEdited); + dcbIterations->setEditedState ( pedited->raw.bayersensor.dcbIterations ? Edited : UnEdited); + dcbEnhance->setEdited (pedited->raw.bayersensor.dcbEnhance); + pixelShiftShowMotion->setEdited (pedited->raw.bayersensor.pixelshiftShowMotion); + pixelShiftShowMotionMaskOnly->setEdited (pedited->raw.bayersensor.pixelshiftShowMotionMaskOnly); + pixelShiftHoleFill->setEdited (pedited->raw.bayersensor.pixelShiftHoleFill); + pixelShiftMedian->setEdited(pedited->raw.bayersensor.pixelShiftMedian); + pixelShiftGreen->setEdited (pedited->raw.bayersensor.pixelShiftGreen); + pixelShiftBlur->setEdited (pedited->raw.bayersensor.pixelShiftBlur); + pixelShiftSmooth->setEditedState ( pedited->raw.bayersensor.pixelShiftSmooth ? Edited : UnEdited); + pixelShiftLmmse->setEdited (pedited->raw.bayersensor.pixelShiftLmmse); + pixelShiftEqualBright->setEdited (pedited->raw.bayersensor.pixelShiftEqualBright); + pixelShiftNonGreenCross->setEdited (pedited->raw.bayersensor.pixelShiftNonGreenCross); + lmmseIterations->setEditedState ( pedited->raw.bayersensor.lmmseIterations ? Edited : UnEdited); + pixelShiftEperIso->setEditedState ( pedited->raw.bayersensor.pixelShiftEperIso ? Edited : UnEdited); + pixelShiftSigma->setEditedState ( pedited->raw.bayersensor.pixelShiftSigma ? Edited : UnEdited); +#ifdef PIXELSHIFTDEV + pixelShiftNreadIso->setEditedState ( pedited->raw.bayersensor.pixelShiftNreadIso ? Edited : UnEdited); + pixelShiftPrnu->setEditedState ( pedited->raw.bayersensor.pixelShiftPrnu ? Edited : UnEdited); + pixelShiftStddevFactorGreen->setEditedState ( pedited->raw.bayersensor.pixelShiftStddevFactorGreen ? Edited : UnEdited); + pixelShiftStddevFactorRed->setEditedState ( pedited->raw.bayersensor.pixelShiftStddevFactorRed ? Edited : UnEdited); + pixelShiftStddevFactorBlue->setEditedState ( pedited->raw.bayersensor.pixelShiftStddevFactorBlue ? Edited : UnEdited); + pixelShiftSum->setEditedState ( pedited->raw.bayersensor.pixelShiftSum ? Edited : UnEdited); + pixelShiftAutomatic->setEdited (pedited->raw.bayersensor.pixelShiftAutomatic); + pixelShiftNonGreenHorizontal->setEdited (pedited->raw.bayersensor.pixelShiftNonGreenHorizontal); + pixelShiftNonGreenVertical->setEdited (pedited->raw.bayersensor.pixelShiftNonGreenVertical); + pixelShiftMedian3->setEdited (pedited->raw.bayersensor.pixelShiftMedian3); + pixelShiftExp0->setEdited (pedited->raw.bayersensor.pixelShiftExp0); + pixelShiftNonGreenCross2->setEdited (pedited->raw.bayersensor.pixelShiftNonGreenCross2); + pixelShiftNonGreenAmaze->setEdited (pedited->raw.bayersensor.pixelShiftNonGreenAmaze); + pixelShiftMotion->setEditedState ( pedited->raw.bayersensor.pixelShiftMotion ? Edited : UnEdited); + pixelShiftRedBlueWeight->setEditedState ( pedited->raw.bayersensor.pixelShiftRedBlueWeight ? Edited : UnEdited); +#endif + + if(!pedited->raw.bayersensor.method) { + method->set_active(procparams::RAWParams::BayerSensor::numMethods); // No name + } + if(!pedited->raw.bayersensor.imageNum) { + imageNumber->set_active_text(M("GENERAL_UNCHANGED")); + } +#ifdef PIXELSHIFTDEV + if(!pedited->raw.bayersensor.pixelShiftMotionCorrection) { + pixelShiftMotionCorrection->set_active_text(M("GENERAL_UNCHANGED")); + } +#endif + if(!pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod) { + pixelShiftMotionMethod->set_active_text(M("GENERAL_UNCHANGED")); + } } - // Flase color suppression is applied to all demozaicing method, so don't hide anything - /*if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::eahd] || - pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::hphd] || - pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::vng4]) - ccSteps->show(); - else - ccSteps->hide();*/ + if (!batchMode) { + if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::dcb] || + method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) { + dcbOptions->show(); + } else { + dcbOptions->hide(); + } + if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::lmmse] || + method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) { + lmmseOptions->show(); + } else { + lmmseOptions->hide(); + } + if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::pixelshift] || + method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) { + if(pp->raw.bayersensor.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::Custom) { + pixelShiftOptions->show(); + } else { + pixelShiftOptions->hide(); + } + pixelShiftFrame->show(); + } else { + pixelShiftFrame->hide(); + } + + // Flase color suppression is applied to all demozaicing method, so don't hide anything + /*if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::eahd] || + pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::hphd] || + pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::vng4]) + ccSteps->show(); + else + ccSteps->hide();*/ + } - lastDCBen = pp->raw.bayersensor.dcb_enhance; //lastALLen = pp->raw.bayersensor.all_enhance; - methodconn.block (false); - dcbEnhconn.block (false); + method->block (false); +#ifdef PIXELSHIFTDEV + pixelShiftMotionCorrection->block (false); +#endif + imageNumber->block (false); //allEnhconn.block (false); enableListener (); @@ -162,24 +509,91 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe { pp->raw.bayersensor.ccSteps = ccSteps->getIntValue(); pp->raw.bayersensor.dcb_iterations = dcbIterations->getIntValue(); - pp->raw.bayersensor.dcb_enhance = dcbEnhance->get_active(); - //pp->raw.bayersensor.all_enhance = allEnhance->get_active(); + pp->raw.bayersensor.dcb_enhance = dcbEnhance->getLastActive (); + //pp->raw.bayersensor.all_enhance = allEnhance->getLastActive (); pp->raw.bayersensor.lmmse_iterations = lmmseIterations->getIntValue(); + pp->raw.bayersensor.pixelShiftMotionCorrectionMethod = (RAWParams::BayerSensor::ePSMotionCorrectionMethod)pixelShiftMotionMethod->get_active_row_number(); + pp->raw.bayersensor.pixelShiftEperIso = pixelShiftEperIso->getValue(); + pp->raw.bayersensor.pixelShiftSigma = pixelShiftSigma->getValue(); + pp->raw.bayersensor.pixelshiftShowMotion = pixelShiftShowMotion->getLastActive (); + pp->raw.bayersensor.pixelshiftShowMotionMaskOnly = pixelShiftShowMotionMaskOnly->getLastActive (); + pp->raw.bayersensor.pixelShiftHoleFill = pixelShiftHoleFill->getLastActive (); + pp->raw.bayersensor.pixelShiftMedian = pixelShiftMedian->getLastActive (); + pp->raw.bayersensor.pixelShiftGreen = pixelShiftGreen->getLastActive (); + pp->raw.bayersensor.pixelShiftBlur = pixelShiftBlur->getLastActive (); + pp->raw.bayersensor.pixelShiftSmoothFactor = pixelShiftSmooth->getValue(); + pp->raw.bayersensor.pixelShiftLmmse = pixelShiftLmmse->getLastActive (); + pp->raw.bayersensor.pixelShiftEqualBright = pixelShiftEqualBright->getLastActive (); + pp->raw.bayersensor.pixelShiftNonGreenCross = pixelShiftNonGreenCross->getLastActive (); +#ifdef PIXELSHIFTDEV + pp->raw.bayersensor.pixelShiftStddevFactorGreen = pixelShiftStddevFactorGreen->getValue(); + pp->raw.bayersensor.pixelShiftStddevFactorRed = pixelShiftStddevFactorRed->getValue(); + pp->raw.bayersensor.pixelShiftStddevFactorBlue = pixelShiftStddevFactorBlue->getValue(); + pp->raw.bayersensor.pixelShiftSum = pixelShiftSum->getValue(); + pp->raw.bayersensor.pixelShiftMedian3 = pixelShiftMedian3->getLastActive (); + pp->raw.bayersensor.pixelShiftMotion = pixelShiftMotion->getIntValue(); + pp->raw.bayersensor.pixelShiftMotionCorrection = (RAWParams::BayerSensor::ePSMotionCorrection)pixelShiftMotionCorrection->get_active_row_number(); + pp->raw.bayersensor.pixelShiftAutomatic = pixelShiftAutomatic->getLastActive (); + pp->raw.bayersensor.pixelShiftNonGreenHorizontal = pixelShiftNonGreenHorizontal->getLastActive (); + pp->raw.bayersensor.pixelShiftNonGreenVertical = pixelShiftNonGreenVertical->getLastActive (); + pp->raw.bayersensor.pixelShiftExp0 = pixelShiftExp0->getLastActive (); + pp->raw.bayersensor.pixelShiftNonGreenCross2 = pixelShiftNonGreenCross2->getLastActive (); + pp->raw.bayersensor.pixelShiftNonGreenAmaze = pixelShiftNonGreenAmaze->getLastActive (); + pp->raw.bayersensor.pixelShiftNreadIso = pixelShiftNreadIso->getValue(); + pp->raw.bayersensor.pixelShiftPrnu = pixelShiftPrnu->getValue(); + pp->raw.bayersensor.pixelShiftRedBlueWeight = pixelShiftRedBlueWeight->getValue(); +#endif int currentRow = method->get_active_row_number(); - if( currentRow >= 0 && currentRow < procparams::RAWParams::BayerSensor::numMethods) { pp->raw.bayersensor.method = procparams::RAWParams::BayerSensor::methodstring[currentRow]; } + currentRow = imageNumber->get_active_row_number(); + if (currentRow < 4) { + pp->raw.bayersensor.imageNum = currentRow; + } + + if (pedited) { pedited->raw.bayersensor.ccSteps = ccSteps->getEditedState (); pedited->raw.bayersensor.method = method->get_active_row_number() != procparams::RAWParams::BayerSensor::numMethods; + pedited->raw.bayersensor.imageNum = imageNumber->get_active_text() != M("GENERAL_UNCHANGED"); pedited->raw.bayersensor.dcbIterations = dcbIterations->getEditedState (); pedited->raw.bayersensor.dcbEnhance = !dcbEnhance->get_inconsistent(); //pedited->raw.bayersensor.allEnhance = !allEnhance->get_inconsistent(); pedited->raw.bayersensor.lmmseIterations = lmmseIterations->getEditedState (); - + pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod = pixelShiftMotionMethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->raw.bayersensor.pixelShiftEperIso = pixelShiftEperIso->getEditedState (); + pedited->raw.bayersensor.pixelShiftSigma = pixelShiftSigma->getEditedState (); + pedited->raw.bayersensor.pixelshiftShowMotion = !pixelShiftShowMotion->get_inconsistent(); + pedited->raw.bayersensor.pixelshiftShowMotionMaskOnly = !pixelShiftShowMotionMaskOnly->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftHoleFill = !pixelShiftHoleFill->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftMedian = !pixelShiftMedian->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftGreen = !pixelShiftGreen->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftBlur = !pixelShiftBlur->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftSmooth = pixelShiftSmooth->getEditedState(); + pedited->raw.bayersensor.pixelShiftLmmse = !pixelShiftLmmse->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftEqualBright = !pixelShiftEqualBright->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftNonGreenCross = !pixelShiftNonGreenCross->get_inconsistent(); +#ifdef PIXELSHIFTDEV + pedited->raw.bayersensor.pixelShiftStddevFactorGreen = pixelShiftStddevFactorGreen->getEditedState (); + pedited->raw.bayersensor.pixelShiftStddevFactorRed = pixelShiftStddevFactorRed->getEditedState (); + pedited->raw.bayersensor.pixelShiftStddevFactorBlue = pixelShiftStddevFactorBlue->getEditedState (); + pedited->raw.bayersensor.pixelShiftSum = pixelShiftSum->getEditedState (); + pedited->raw.bayersensor.pixelShiftMedian3 = !pixelShiftMedian3->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftMotion = pixelShiftMotion->getEditedState (); + pedited->raw.bayersensor.pixelShiftMotionCorrection = pixelShiftMotionCorrection->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->raw.bayersensor.pixelShiftAutomatic = !pixelShiftAutomatic->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftNonGreenHorizontal = !pixelShiftNonGreenHorizontal->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftNonGreenVertical = !pixelShiftNonGreenVertical->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftExp0 = !pixelShiftExp0->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftNonGreenCross2 = !pixelShiftNonGreenCross2->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftNonGreenAmaze = !pixelShiftNonGreenAmaze->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftNreadIso = pixelShiftNreadIso->getEditedState (); + pedited->raw.bayersensor.pixelShiftPrnu = pixelShiftPrnu->getEditedState (); + pedited->raw.bayersensor.pixelShiftRedBlueWeight = pixelShiftRedBlueWeight->getEditedState (); +#endif } } @@ -187,27 +601,81 @@ void BayerProcess::setBatchMode(bool batchMode) { method->append (M("GENERAL_UNCHANGED")); method->set_active(procparams::RAWParams::BayerSensor::numMethods); // No name - dcbOptions->hide(); - lmmseOptions->hide(); +#ifdef PIXELSHIFTDEV + pixelShiftMotionCorrection->append (M("GENERAL_UNCHANGED")); + pixelShiftMotionCorrection->set_active_text (M("GENERAL_UNCHANGED")); +#endif + pixelShiftMotionMethod->append (M("GENERAL_UNCHANGED")); + pixelShiftMotionMethod->set_active_text (M("GENERAL_UNCHANGED")); + imageNumber->append (M("GENERAL_UNCHANGED")); + imageNumber->set_active_text (M("GENERAL_UNCHANGED")); ToolPanel::setBatchMode (batchMode); ccSteps->showEditedCB (); dcbIterations->showEditedCB (); lmmseIterations->showEditedCB (); +#ifdef PIXELSHIFTDEV + pixelShiftMotion->showEditedCB (); + pixelShiftSum->showEditedCB (); + pixelShiftStddevFactorGreen->showEditedCB (); + pixelShiftStddevFactorRed->showEditedCB (); + pixelShiftStddevFactorBlue->showEditedCB (); + pixelShiftNreadIso->showEditedCB (); + pixelShiftPrnu->showEditedCB (); + pixelShiftRedBlueWeight->showEditedCB (); +#endif + pixelShiftEperIso->showEditedCB (); + pixelShiftSigma->showEditedCB (); } void BayerProcess::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { dcbIterations->setDefault( defParams->raw.bayersensor.dcb_iterations); lmmseIterations->setDefault( defParams->raw.bayersensor.lmmse_iterations); +#ifdef PIXELSHIFTDEV + pixelShiftMotion->setDefault( defParams->raw.bayersensor.pixelShiftMotion); + pixelShiftSum->setDefault( defParams->raw.bayersensor.pixelShiftSum); + pixelShiftStddevFactorGreen->setDefault( defParams->raw.bayersensor.pixelShiftStddevFactorGreen); + pixelShiftStddevFactorRed->setDefault( defParams->raw.bayersensor.pixelShiftStddevFactorRed); + pixelShiftStddevFactorBlue->setDefault( defParams->raw.bayersensor.pixelShiftStddevFactorBlue); + pixelShiftNreadIso->setDefault( defParams->raw.bayersensor.pixelShiftNreadIso); + pixelShiftPrnu->setDefault( defParams->raw.bayersensor.pixelShiftPrnu); + pixelShiftRedBlueWeight->setDefault( defParams->raw.bayersensor.pixelShiftRedBlueWeight); +#endif + pixelShiftEperIso->setDefault( defParams->raw.bayersensor.pixelShiftEperIso); + pixelShiftSigma->setDefault( defParams->raw.bayersensor.pixelShiftSigma); ccSteps->setDefault (defParams->raw.bayersensor.ccSteps); if (pedited) { dcbIterations->setDefaultEditedState( pedited->raw.bayersensor.dcbIterations ? Edited : UnEdited); lmmseIterations->setDefaultEditedState( pedited->raw.bayersensor.lmmseIterations ? Edited : UnEdited); +#ifdef PIXELSHIFTDEV + pixelShiftMotion->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftMotion ? Edited : UnEdited); + pixelShiftSum->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftSum ? Edited : UnEdited); + pixelShiftStddevFactorGreen->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftStddevFactorGreen ? Edited : UnEdited); + pixelShiftStddevFactorRed->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftStddevFactorRed ? Edited : UnEdited); + pixelShiftStddevFactorBlue->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftStddevFactorBlue ? Edited : UnEdited); + pixelShiftNreadIso->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftNreadIso ? Edited : UnEdited); + pixelShiftPrnu->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftPrnu ? Edited : UnEdited); + pixelShiftRedBlueWeight->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftRedBlueWeight ? Edited : UnEdited); +#endif + pixelShiftEperIso->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftEperIso ? Edited : UnEdited); + pixelShiftSigma->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftSigma ? Edited : UnEdited); ccSteps->setDefaultEditedState(pedited->raw.bayersensor.ccSteps ? Edited : UnEdited); } else { dcbIterations->setDefaultEditedState( Irrelevant ); lmmseIterations->setDefaultEditedState( Irrelevant ); +#ifdef PIXELSHIFTDEV + pixelShiftMotion->setDefaultEditedState( Irrelevant ); + pixelShiftSum->setDefaultEditedState( Irrelevant ); + pixelShiftStddevFactorGreen->setDefaultEditedState( Irrelevant ); + pixelShiftStddevFactorRed->setDefaultEditedState( Irrelevant ); + pixelShiftStddevFactorBlue->setDefaultEditedState( Irrelevant ); + pixelShiftNreadIso->setDefaultEditedState( Irrelevant ); + pixelShiftPrnu->setDefaultEditedState( Irrelevant ); + pixelShiftRedBlueWeight->setDefaultEditedState( Irrelevant ); +#endif + pixelShiftEperIso->setDefaultEditedState( Irrelevant ); + pixelShiftSigma->setDefaultEditedState( Irrelevant ); ccSteps->setDefaultEditedState(Irrelevant ); } } @@ -221,24 +689,82 @@ void BayerProcess::adjusterChanged (Adjuster* a, double newval) listener->panelChanged (EvDemosaicFalseColorIter, a->getTextValue() ); } else if (a == lmmseIterations) { listener->panelChanged (EvDemosaicLMMSEIter, a->getTextValue() ); +#ifdef PIXELSHIFTDEV + } else if (a == pixelShiftMotion) { + listener->panelChanged (EvPixelShiftMotion, a->getTextValue() ); + } else if (a == pixelShiftSum) { + listener->panelChanged (EvPixelShiftSum, a->getTextValue() ); + } else if (a == pixelShiftStddevFactorGreen) { + listener->panelChanged (EvPixelShiftStddevFactorGreen, a->getTextValue() ); + } else if (a == pixelShiftStddevFactorRed) { + listener->panelChanged (EvPixelShiftStddevFactorRed, a->getTextValue() ); + } else if (a == pixelShiftStddevFactorBlue) { + listener->panelChanged (EvPixelShiftStddevFactorBlue, a->getTextValue() ); + } else if (a == pixelShiftNreadIso) { + listener->panelChanged (EvPixelShiftNreadIso, a->getTextValue() ); + } else if (a == pixelShiftPrnu) { + listener->panelChanged (EvPixelShiftPrnu, a->getTextValue() ); + } else if (a == pixelShiftRedBlueWeight) { + listener->panelChanged (EvPixelShiftRedBlueWeight, a->getTextValue() ); +#endif + } else if (a == pixelShiftEperIso) { + listener->panelChanged (EvPixelShiftEperIso, a->getTextValue() ); + } else if (a == pixelShiftSigma) { + listener->panelChanged (EvPixelShiftSigma, a->getTextValue() ); + } else if (a == pixelShiftSmooth) { + listener->panelChanged (EvPixelShiftSmooth, a->getTextValue() ); } } } +#ifdef PIXELSHIFTDEV +void BayerProcess::psMotionCorrectionChanged () +{ + if (!batchMode) { + if(pixelShiftMotionCorrection->get_active_row_number() == 5) { + pixelShiftBlur->set_sensitive(true); + pixelShiftHoleFill->set_sensitive(true); + pixelShiftSmooth->set_sensitive(pixelShiftBlur->getValue() != CheckValue::off); + } else { + pixelShiftBlur->set_sensitive(false); + pixelShiftHoleFill->set_sensitive(false); + pixelShiftSmooth->set_sensitive(false); + } + } + + if (listener) { + listener->panelChanged (EvPixelShiftMotionCorrection, pixelShiftMotionCorrection->get_active_text()); + } +} +#endif + void BayerProcess::methodChanged () { int curSelection = method->get_active_row_number(); - if ( curSelection == procparams::RAWParams::BayerSensor::dcb) { - dcbOptions->show(); - } else { - dcbOptions->hide(); - } + if (!batchMode) { + if ( curSelection == procparams::RAWParams::BayerSensor::dcb) { + dcbOptions->show(); + } else { + dcbOptions->hide(); + } - if ( curSelection == procparams::RAWParams::BayerSensor::lmmse) { - lmmseOptions->show(); - } else { - lmmseOptions->hide(); + if ( curSelection == procparams::RAWParams::BayerSensor::lmmse) { + lmmseOptions->show(); + } else { + lmmseOptions->hide(); + } + + if ( curSelection == procparams::RAWParams::BayerSensor::pixelshift) { + if(pixelShiftMotionMethod->get_active_row_number() == 2) { + pixelShiftOptions->show(); + } else { + pixelShiftOptions->hide(); + } + pixelShiftFrame->show(); + } else { + pixelShiftFrame->hide(); + } } Glib::ustring methodName = ""; @@ -247,52 +773,155 @@ void BayerProcess::methodChanged () if( curSelection >= 0 && curSelection < procparams::RAWParams::BayerSensor::numMethods) { methodName = procparams::RAWParams::BayerSensor::methodstring[curSelection]; - if (curSelection == procparams::RAWParams::BayerSensor::mono || oldSelection == procparams::RAWParams::BayerSensor::mono) { + if (curSelection == procparams::RAWParams::BayerSensor::mono || oldMethod == procparams::RAWParams::BayerSensor::mono) { ppreq = true; } } - oldSelection = curSelection; + oldMethod = curSelection; if (listener) { listener->panelChanged (ppreq ? EvDemosaicMethodPreProc : EvDemosaicMethod, methodName); } } -void BayerProcess::dcbEnhanceChanged () +void BayerProcess::imageNumberChanged () { - if (batchMode) { - if (dcbEnhance->get_inconsistent()) { - dcbEnhance->set_inconsistent (false); - dcbEnhconn.block (true); - dcbEnhance->set_active (false); - dcbEnhconn.block (false); - } else if (lastDCBen) { - dcbEnhance->set_inconsistent (true); - } - - lastDCBen = dcbEnhance->get_active (); - } - if (listener) { - listener->panelChanged (EvDemosaicDCBEnhanced, dcbEnhance->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + listener->panelChanged (EvRawImageNum, imageNumber->get_active_text()); } } -/*void BayerProcess::allEnhanceChanged () +void BayerProcess::checkBoxToggled (CheckBox* c, CheckValue newval) { - if (batchMode) { - if (allEnhance->get_inconsistent()) { - allEnhance->set_inconsistent (false); - allEnhconn.block (true); - allEnhance->set_active (false); - allEnhconn.block (false); + if (c == dcbEnhance) { + if (listener) { + listener->panelChanged (EvDemosaicDCBEnhanced, dcbEnhance->getValueAsStr ()); + } + } else if (c == pixelShiftShowMotion) { + if (!batchMode) { + pixelShiftShowMotionMaskOnly->set_sensitive(newval != CheckValue::off); + } + if (listener) { + listener->panelChanged (EvPixelshiftShowMotion, pixelShiftShowMotion->getValueAsStr ()); + } + } else if (c == pixelShiftShowMotionMaskOnly) { + if (listener) { + listener->panelChanged (EvPixelshiftShowMotionMaskOnly, pixelShiftShowMotionMaskOnly->getValueAsStr ()); + } + } else if (c == pixelShiftHoleFill) { + if (listener) { + listener->panelChanged (EvPixelShiftHoleFill, pixelShiftHoleFill->getValueAsStr ()); + } + } else if (c == pixelShiftMedian) { +#ifdef PIXELSHIFTDEV + if (!batchMode) { + pixelShiftMedian3->set_sensitive(newval != CheckValue::off); + } +#endif + if (listener) { + listener->panelChanged (EvPixelShiftMedian, pixelShiftMedian->getValueAsStr ()); + } + } else if (c == pixelShiftGreen) { + if (listener) { + listener->panelChanged (EvPixelShiftGreen, pixelShiftGreen->getValueAsStr ()); + } + } else if (c == pixelShiftBlur) { + if (!batchMode) { + pixelShiftSmooth->set_sensitive(newval != CheckValue::off); + pixelShiftSigma->set_sensitive(newval != CheckValue::off); + } + if (listener) { + listener->panelChanged (EvPixelShiftBlur, pixelShiftBlur->getValueAsStr ()); + } + } else if (c == pixelShiftLmmse) { + if (listener) { + listener->panelChanged (EvPixelShiftLmmse, pixelShiftLmmse->getValueAsStr ()); + } + } else if (c == pixelShiftEqualBright) { + if (listener) { + listener->panelChanged (EvPixelShiftEqualBright, pixelShiftEqualBright->getValueAsStr ()); + } + } else if (c == pixelShiftNonGreenCross) { + if (listener) { + listener->panelChanged (EvPixelShiftNonGreenCross, pixelShiftNonGreenCross->getValueAsStr ()); } - else if (lastALLen) - allEnhance->set_inconsistent (true); - - lastALLen = allEnhance->get_active (); } - if (listener) - listener->panelChanged (EvDemosaicALLEnhanced, allEnhance->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED")); -}*/ +#ifdef PIXELSHIFTDEV + else if (c == pixelShiftAutomatic) { + if (!batchMode) { + pixelShiftMotion->set_sensitive(!newval != CheckValue::off); + pixelShiftEperIso->set_sensitive(newval != CheckValue::off); + pixelShiftNreadIso->set_sensitive(newval != CheckValue::off); + pixelShiftPrnu->set_sensitive(newval != CheckValue::off); + pixelShiftSigma->set_sensitive(newval != CheckValue::off); + pixelShiftSum->set_sensitive(newval != CheckValue::off); + pixelShiftRedBlueWeight->set_sensitive(newval != CheckValue::off); + pixelShiftStddevFactorGreen->set_sensitive(newval != CheckValue::off); + pixelShiftStddevFactorRed->set_sensitive(newval != CheckValue::off); + pixelShiftStddevFactorBlue->set_sensitive(newval != CheckValue::off); + pixelShiftNonGreenHorizontal->set_sensitive(newval != CheckValue::off); + pixelShiftNonGreenVertical->set_sensitive(newval != CheckValue::off); + pixelShiftHoleFill->set_sensitive(newval != CheckValue::off && pixelShiftMotionCorrection->get_active_row_number() == 5); + pixelShiftMedian3->set_sensitive(newval != CheckValue::off && pixelShiftMedian->getValue () != CheckValue::off); + pixelShiftGreen->set_sensitive(newval != CheckValue::off); + pixelShiftBlur->set_sensitive(newval != CheckValue::off && pixelShiftMotionCorrection->get_active_row_number() == 5); + pixelShiftSmooth->set_sensitive(newval != CheckValue::off && pixelShiftMotionCorrection->get_active_row_number() == 5 && pixelShiftBlur->getValue () != CheckValue::off); + pixelShiftExp0->set_sensitive(newval != CheckValue::off); + pixelShiftNonGreenCross->set_sensitive(newval != CheckValue::off); + pixelShiftNonGreenCross2->set_sensitive(newval != CheckValue::off); + pixelShiftNonGreenAmaze->set_sensitive(newval != CheckValue::off); + } + + if (listener) { + listener->panelChanged (EvPixelShiftAutomatic, pixelShiftAutomatic->getValueAsStr ()); + } + } else if (c == pixelShiftNonGreenHorizontal) { + if (listener) { + listener->panelChanged (EvPixelShiftNonGreenHorizontal, pixelShiftNonGreenHorizontal->getValueAsStr ()); + } + } else if (c == pixelShiftNonGreenVertical) { + if (listener) { + listener->panelChanged (EvPixelShiftNonGreenVertical, pixelShiftNonGreenVertical->getValueAsStr ()); + } + } else if (c == pixelShiftMedian3) { + if (listener) { + listener->panelChanged (EvPixelShiftMedian3, pixelShiftMedian3->getValueAsStr ()); + } + } else if (c == pixelShiftExp0) { + if (listener) { + listener->panelChanged (EvPixelShiftExp0, pixelShiftExp0->getValueAsStr ()); + } + } else if (c == pixelShiftNonGreenCross2) { + if (listener) { + listener->panelChanged (EvPixelShiftGreenAmaze, pixelShiftNonGreenCross2->getValueAsStr ()); + } + } else if (c == pixelShiftNonGreenAmaze) { + if (listener) { + listener->panelChanged (EvPixelShiftNonGreenAmaze, pixelShiftNonGreenAmaze->getValueAsStr ()); + } + } +#endif +} + +void BayerProcess::pixelShiftMotionMethodChanged () +{ + if (!batchMode) { + if(pixelShiftMotionMethod->get_active_row_number() == 0) { + pixelShiftOptions->hide(); + pixelShiftShowMotion->hide(); + pixelShiftShowMotionMaskOnly->hide(); + } else if(pixelShiftMotionMethod->get_active_row_number() == 2) { + pixelShiftOptions->show(); + pixelShiftShowMotion->show(); + pixelShiftShowMotionMaskOnly->show(); + } else { + pixelShiftOptions->hide(); + pixelShiftShowMotion->show(); + pixelShiftShowMotionMaskOnly->show(); + } + } + if (listener) { + listener->panelChanged (EvPixelShiftMotionMethod, pixelShiftMotionMethod->get_active_text()); + } +} diff --git a/rtgui/bayerprocess.h b/rtgui/bayerprocess.h index b78002ea3..9c2285951 100644 --- a/rtgui/bayerprocess.h +++ b/rtgui/bayerprocess.h @@ -21,29 +21,59 @@ #include #include "adjuster.h" +#include "checkbox.h" #include "guiutils.h" #include "toolpanel.h" -class BayerProcess : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class BayerProcess : public ToolParamBlock, public AdjusterListener, public CheckBoxListener, public FoldableToolPanel { protected: MyComboBoxText* method; + Gtk::HBox *imageNumberBox; + MyComboBoxText* imageNumber; Adjuster* ccSteps; Gtk::VBox *dcbOptions; Adjuster* dcbIterations; - Gtk::CheckButton* dcbEnhance; - //Gtk::VBox *allOptions; - //Gtk::CheckButton* allEnhance; + CheckBox* dcbEnhance; Gtk::VBox *lmmseOptions; Adjuster* lmmseIterations; - - bool lastDCBen; - int oldSelection; - //bool lastALLen; - sigc::connection methodconn, dcbEnhconn; //,allEnhconn; + Gtk::VBox *pixelShiftFrame; + Gtk::VBox *pixelShiftOptions; + MyComboBoxText* pixelShiftMotionMethod; + CheckBox* pixelShiftShowMotion; + CheckBox* pixelShiftShowMotionMaskOnly; + CheckBox* pixelShiftNonGreenCross; + CheckBox* pixelShiftGreen; + CheckBox* pixelShiftBlur; + CheckBox* pixelShiftHoleFill; + CheckBox* pixelShiftMedian; + CheckBox* pixelShiftLmmse; + CheckBox* pixelShiftEqualBright; + Adjuster* pixelShiftSmooth; + Adjuster* pixelShiftEperIso; + Adjuster* pixelShiftSigma; +#ifdef PIXELSHIFTDEV + Adjuster* pixelShiftSum; + Adjuster* pixelShiftMotion; + MyComboBoxText* pixelShiftMotionCorrection; + CheckBox* pixelShiftAutomatic; + CheckBox* pixelShiftNonGreenHorizontal; + CheckBox* pixelShiftNonGreenVertical; + CheckBox* pixelShiftNonGreenCross2; + CheckBox* pixelShiftNonGreenAmaze; + CheckBox* pixelShiftExp0; + CheckBox* pixelShiftMedian3; + Adjuster* pixelShiftStddevFactorGreen; + Adjuster* pixelShiftStddevFactorRed; + Adjuster* pixelShiftStddevFactorBlue; + Adjuster* pixelShiftNreadIso; + Adjuster* pixelShiftPrnu; + Adjuster* pixelShiftRedBlueWeight; +#endif + int oldMethod; public: BayerProcess (); @@ -54,9 +84,13 @@ public: void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); void methodChanged (); - void adjusterChanged (Adjuster* a, double newval); - void dcbEnhanceChanged(); - //void allEnhanceChanged(); + void imageNumberChanged (); + void adjusterChanged (Adjuster* a, double newval); + void checkBoxToggled (CheckBox* c, CheckValue newval); + void pixelShiftMotionMethodChanged(); +#ifdef PIXELSHIFTDEV + void psMotionCorrectionChanged (); +#endif }; #endif diff --git a/rtgui/bayerrawexposure.cc b/rtgui/bayerrawexposure.cc index ee9b4fc4d..2194d1639 100644 --- a/rtgui/bayerrawexposure.cc +++ b/rtgui/bayerrawexposure.cc @@ -18,7 +18,6 @@ */ #include "bayerrawexposure.h" #include "guiutils.h" -#include using namespace rtengine; using namespace rtengine::procparams; @@ -57,9 +56,9 @@ BayerRAWExposure::BayerRAWExposure () : FoldableToolPanel(this, "bayerrawexposur } PexBlack0->show(); - PextwoGreen = Gtk::manage(new Gtk::CheckButton((M("TP_RAWEXPOS_TWOGREEN"))));// two green + PextwoGreen = Gtk::manage(new CheckBox(M("TP_RAWEXPOS_TWOGREEN"), multiImage));// two green PextwoGreen->set_active (true); - greenconn = PextwoGreen->signal_toggled().connect ( sigc::mem_fun(*this, &BayerRAWExposure::GreenChanged)); + PextwoGreen->setCheckBoxListener (this); pack_start( *PexBlack1, Gtk::PACK_SHRINK, 0);//black R pack_start( *PexBlack0, Gtk::PACK_SHRINK, 0);//black G1 @@ -79,16 +78,13 @@ void BayerRAWExposure::read(const rtengine::procparams::ProcParams* pp, const Pa PexBlack3->setEditedState( pedited->raw.bayersensor.exBlack3 ? Edited : UnEdited ); } - greenconn.block (true); - PextwoGreen->set_active (pp->raw.bayersensor.twogreen); - greenconn.block (false); - lastPextwoGreen = pp->raw.bayersensor.twogreen; + PextwoGreen->setValue (pp->raw.bayersensor.twogreen); PexBlack0->setValue (pp->raw.bayersensor.black0);//black PexBlack1->setValue (pp->raw.bayersensor.black1);//black PexBlack2->setValue (pp->raw.bayersensor.black2);//black - if(!PextwoGreen->get_active()) { + if(!PextwoGreen->getLastActive()) { PexBlack3->setValue (pp->raw.bayersensor.black3); } else { PexBlack3->setValue (PexBlack0->getValue()); @@ -102,9 +98,9 @@ void BayerRAWExposure::write( rtengine::procparams::ProcParams* pp, ParamsEdited pp->raw.bayersensor.black0 = PexBlack0->getValue();// black pp->raw.bayersensor.black1 = PexBlack1->getValue();// black pp->raw.bayersensor.black2 = PexBlack2->getValue();// black - pp->raw.bayersensor.twogreen = PextwoGreen->get_active(); + pp->raw.bayersensor.twogreen = PextwoGreen->getLastActive(); - if(PextwoGreen->get_active()) { + if(PextwoGreen->getLastActive()) { pp->raw.bayersensor.black3 = pp->raw.bayersensor.black0; // active or desactive 2 green together } else { pp->raw.bayersensor.black3 = PexBlack3->getValue(); @@ -126,7 +122,7 @@ void BayerRAWExposure::adjusterChanged (Adjuster* a, double newval) Glib::ustring value = a->getTextValue(); if (a == PexBlack0) { - if(!PextwoGreen->get_active()) { + if(!PextwoGreen->getLastActive()) { listener->panelChanged (EvPreProcessExpBlackzero, value ); } else { listener->panelChanged (EvPreProcessExpBlackzero, value ); @@ -137,7 +133,7 @@ void BayerRAWExposure::adjusterChanged (Adjuster* a, double newval) } else if (a == PexBlack2) { listener->panelChanged (EvPreProcessExpBlacktwo, value ); } else if (a == PexBlack3) { - if(!PextwoGreen->get_active()) { + if(!PextwoGreen->getLastActive()) { listener->panelChanged (EvPreProcessExpBlackthree, value ); } else { listener->panelChanged (EvPreProcessExpBlackthree, value ); @@ -146,33 +142,17 @@ void BayerRAWExposure::adjusterChanged (Adjuster* a, double newval) } } } -void BayerRAWExposure::GreenChanged() + +void BayerRAWExposure::checkBoxToggled (CheckBox* c, CheckValue newval) { - if (batchMode) { - if (PextwoGreen->get_inconsistent()) { - PextwoGreen->set_inconsistent (false); - greenconn.block (true); - PextwoGreen->set_active (false); - greenconn.block (false); - } else if (lastPextwoGreen) { - PextwoGreen->set_inconsistent (true); + if (c == PextwoGreen) { + if (listener) { + listener->panelChanged (EvPreProcessExptwoGreen, PextwoGreen->getLastActive() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + if (PextwoGreen->getLastActive()) { + PexBlack3->setValue (PexBlack0->getValue());//two green together + } } - - lastPextwoGreen = PextwoGreen->get_active (); } - - if (listener) { - if (PextwoGreen->get_active()) { - listener->panelChanged (EvPreProcessExptwoGreen, M("GENERAL_ENABLED")); - PexBlack3->setValue (PexBlack0->getValue());//two green together - } - - else { - listener->panelChanged (EvPreProcessExptwoGreen, M("GENERAL_DISABLED")); - } - - } - } void BayerRAWExposure::setBatchMode(bool batchMode) diff --git a/rtgui/bayerrawexposure.h b/rtgui/bayerrawexposure.h index 733aafc25..5d51babbb 100644 --- a/rtgui/bayerrawexposure.h +++ b/rtgui/bayerrawexposure.h @@ -21,10 +21,10 @@ #include #include "adjuster.h" +#include "checkbox.h" #include "toolpanel.h" -#include "../rtengine/rawimage.h" -class BayerRAWExposure : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class BayerRAWExposure : public ToolParamBlock, public AdjusterListener, public CheckBoxListener, public FoldableToolPanel { protected: @@ -32,12 +32,8 @@ protected: Adjuster* PexBlack1; Adjuster* PexBlack2; Adjuster* PexBlack3; - bool lastPextwoGreen; - sigc::connection greenconn; - Gtk::CheckButton* PextwoGreen; + CheckBox* PextwoGreen; -private: -// Gtk::CheckButton* PextwoGreen; public: BayerRAWExposure (); @@ -46,8 +42,8 @@ public: void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); void setBatchMode (bool batchMode); void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void GreenChanged() ; void adjusterChanged (Adjuster* a, double newval); + void checkBoxToggled (CheckBox* c, CheckValue newval); void setAdjusterBehavior (bool pexblackadd); void trimValues (rtengine::procparams::ProcParams* pp); }; diff --git a/rtgui/bqentryupdater.cc b/rtgui/bqentryupdater.cc index 37ce4c0ef..1bb7e4257 100644 --- a/rtgui/bqentryupdater.cc +++ b/rtgui/bqentryupdater.cc @@ -120,11 +120,11 @@ void BatchQueueEntryUpdater::processThread () int prevh = img->getHeight(); #ifndef NDEBUG - if (current.ow != img->getW() || current.oh != img->getH()) { - printf("WARNING! Expected image size: %dx%d ; image size is: %dx%d\n", current.ow, current.oh, img->getW(), img->getH()); + if (current.ow != img->getWidth() || current.oh != img->getHeight()) { + printf("WARNING! Expected image size: %dx%d ; image size is: %dx%d\n", current.ow, current.oh, img->getWidth(), img->getHeight()); } - assert ((current.ow + 1)*current.oh >= img->getW()*img->getH()); + assert ((current.ow + 1)*current.oh >= img->getWidth()*img->getHeight()); #endif current.ow = prevw; current.oh = prevh; diff --git a/rtgui/checkbox.cc b/rtgui/checkbox.cc new file mode 100644 index 000000000..716802f0f --- /dev/null +++ b/rtgui/checkbox.cc @@ -0,0 +1,156 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Jean-Christophe FRISCH + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +#include + +#include "multilangmgr.h" +#include "checkbox.h" +#include "guiutils.h" + +CheckBox::CheckBox (Glib::ustring label, bool const& multiImageVal) + : Gtk::CheckButton (label) + , listener (nullptr) + , lastActive (false) + , inBatchMode (false) + , multiImage (multiImageVal) +{ + conn = signal_toggled().connect( sigc::mem_fun(*this, &CheckBox::buttonToggled) ); +} + +void CheckBox::buttonToggled () +{ + + CheckValue newValue; + + if (multiImage) { + if (get_inconsistent()) { + set_inconsistent (false); + ConnectionBlocker bloker (conn); + set_active (false); + newValue = CheckValue::off; + } else if (getLastActive()) { + set_inconsistent (true); + newValue = CheckValue::unchanged; + } + } else { + newValue = get_active () ? CheckValue::on : CheckValue::off; + } + setLastActive(); + + if (listener) { + listener->checkBoxToggled(this, newValue); + } +} + +void CheckBox::setLastActive() +{ + lastActive = get_active(); +} + +// return the actual bool value, ignoring the inconsistent state +bool CheckBox::getLastActive () +{ + return lastActive; +} + +void CheckBox::setValue (CheckValue newValue) +{ + + ConnectionBlocker blocker (conn); + switch (newValue) { + case CheckValue::on: + set_inconsistent (false); + set_active(true); + lastActive = true; + break; + case CheckValue::off: + set_inconsistent (false); + set_active(true); + lastActive = false; + break; + case CheckValue::unchanged: + set_inconsistent (true); + break; + default: + break; + } +} + +void CheckBox::setValue (bool active) +{ + + ConnectionBlocker blocker (conn); + set_inconsistent (false); + set_active(active); + lastActive = active; +} + +CheckValue CheckBox::getValue () +{ + return (get_inconsistent() ? CheckValue::unchanged : get_active() ? CheckValue::on : CheckValue::off); +} + +Glib::ustring CheckBox::getValueAsStr () +{ + if (get_inconsistent()) { + return M("GENERAL_UNCHANGED"); + } else if (get_active ()) { + return M("GENERAL_ENABLED"); + } else { + return M("GENERAL_DISABLED"); + } +} + +/* +void CheckBox::set_sensitive (bool isSensitive) +{ + Gtk::CheckButton::set_sensitive(isSensitive); +} + +void CheckBox::set_tooltip_text (const Glib::ustring& tooltip) +{ + Gtk::CheckButton::set_tooltip_text (tooltip); +} + +void CheckBox::set_tooltip_markup (const Glib::ustring& tooltip) +{ + Gtk::CheckButton::set_tooltip_markup (tooltip); +} +*/ + +void CheckBox::setEdited (bool edited) +{ + + ConnectionBlocker blocker (conn); + set_inconsistent (!edited); + if (edited) { + set_active (lastActive); + } +} + +bool CheckBox::getEdited () +{ + + return !get_inconsistent (); +} + +void CheckBox::setCheckBoxListener (CheckBoxListener* cblistener) +{ + listener = cblistener; +} diff --git a/rtgui/checkbox.h b/rtgui/checkbox.h new file mode 100644 index 000000000..8745de6d3 --- /dev/null +++ b/rtgui/checkbox.h @@ -0,0 +1,78 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Jean-Christophe FRISCH + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#ifndef _CHECKBOX_H_ +#define _CHECKBOX_H_ + +#include +#include "editedstate.h" +#include "guiutils.h" + +class CheckBox; + +enum class CheckValue { + on, + off, + unchanged +}; + +class CheckBoxListener +{ + +public: + virtual ~CheckBoxListener() {}; + virtual void checkBoxToggled (CheckBox* c, CheckValue newval) {} +}; + + +/** + * @brief subclass of Gtk::CheckButton for convenience + */ +class CheckBox : public Gtk::CheckButton // Should ideally be private, but in this case build fail on the instantiation +{ + + CheckBoxListener *listener; + bool lastActive; + bool inBatchMode; + bool const& multiImage; + sigc::connection conn; + void buttonToggled (); + void setLastActive(); + +public: + //using CheckButton::CheckButton; + explicit CheckBox (Glib::ustring label, bool const& multiImageVal); + bool getLastActive(); + void setValue (CheckValue newValue); + void setValue (bool active); + CheckValue getValue (); + void setEdited (bool edited); + bool getEdited (); + Glib::ustring getValueAsStr (); + + void setCheckBoxListener (CheckBoxListener* cblistener); + + /* Used if the Gtk::CheckButton parent class can be private + * + void set_sensitive (bool isSensitive = true); + void set_tooltip_text (const Glib::ustring& tooltip); + void set_tooltip_markup (const Glib::ustring& tooltip); + */ +}; + +#endif diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index 7ff139e81..d261da64c 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -61,9 +61,10 @@ ZoomStep zoomSteps[] = { {"500%", 5.0, 5000}, {"600%", 6.0, 6000}, {"700%", 7.0, 7000}, - {"800%", 8.0, 8000} + {"800%", 8.0, 8000}, + {"1600%", 16.0, 16000} }; -#define MAXZOOMSTEPS 20 +#define MAXZOOMSTEPS 21 #define ZOOM11INDEX 13 CropWindow::CropWindow (ImageArea* parent, bool isLowUpdatePriority_, bool isDetailWindow) @@ -1034,9 +1035,21 @@ void CropWindow::pointerMoved (int bstate, int x, int y) int imheight = cropHandler.cropPixbuf->get_height(); guint8* pix = cropHandler.cropPixbuftrue->get_pixels() + vy * cropHandler.cropPixbuf->get_rowstride() + vx * 3; + int rval = pix[0]; + int gval = pix[1]; + int bval = pix[2]; if (vx < imwidth && vy < imheight) { + rtengine::StagedImageProcessor* ipc = iarea->getImProcCoordinator(); + if(ipc) { + procparams::ProcParams params; + ipc->getParams(¶ms); + if(params.raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::none] || params.raw.xtranssensor.method == RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::none]) { + ImageSource *isrc = static_cast(ipc->getInitialImage()); + isrc->getRawValues(mx, my, params.coarse.rotate, rval, gval, bval); + } + } // pmlistener->pointerMoved (true, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]); - pmlistener->pointerMoved (true, cropHandler.colorParams.output, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]); + pmlistener->pointerMoved (true, cropHandler.colorParams.output, cropHandler.colorParams.working, mx, my, rval, gval, bval); if (pmhlistener) // pmhlistener->pointerMoved (true, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]); @@ -2320,7 +2333,7 @@ void CropWindow::drawStraightenGuide (Cairo::RefPtr cr) if (action_x != press_x || action_y != press_y) { double arg = (press_x - action_x) / sqrt(double((press_x - action_x) * (press_x - action_x) + (press_y - action_y) * (press_y - action_y))); double sol1, sol2; - double pi = M_PI; + double pi = rtengine::RT_PI; if (press_y > action_y) { sol1 = acos(arg) * 180 / pi; diff --git a/rtgui/dynamicprofile.cc b/rtgui/dynamicprofile.cc new file mode 100644 index 000000000..4439a1562 --- /dev/null +++ b/rtgui/dynamicprofile.cc @@ -0,0 +1,255 @@ +/* -*- C++ -*- + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Alberto Griggio + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +#include "dynamicprofile.h" +#include "profilestore.h" +#include +#include + +using namespace rtengine; +using namespace rtengine::procparams; + +namespace { + +const int ISO_MAX = 512000; +const double FNUMBER_MAX = 100.0; +const double FOCALLEN_MAX = 10000.0; +const double SHUTTERSPEED_MAX = 1000.0; +const double EXPCOMP_MIN = -20.0; +const double EXPCOMP_MAX = 20.0; + +} // namespace + + +bool DynamicProfileRule::Optional::operator()(const Glib::ustring &val) const +{ + if (!enabled) { + return true; + } + if (value.find("re:") == 0) { + // this is a regexp + return Glib::Regex::match_simple(value.substr(3), val, + Glib::REGEX_CASELESS); + } else { + // normal string comparison + return value.casefold() == val.casefold(); + } +} + + +DynamicProfileRule::DynamicProfileRule(): + serial_number(0), + iso(0, ISO_MAX), + fnumber(0, FNUMBER_MAX), + focallen(0, FOCALLEN_MAX), + shutterspeed(0, SHUTTERSPEED_MAX), + expcomp(EXPCOMP_MIN, EXPCOMP_MAX) +{ +} + + +bool DynamicProfileRule::operator<(const DynamicProfileRule &other) const +{ + return serial_number < other.serial_number; +} + + +bool DynamicProfileRule::matches(const rtengine::ImageMetaData *im) const +{ + return (iso(im->getISOSpeed()) + && fnumber(im->getFNumber()) + && focallen(im->getFocalLen()) + && shutterspeed(im->getShutterSpeed()) + && expcomp(im->getExpComp()) + && camera(im->getCamera()) + && lens(im->getLens())); +} + +namespace { + +void get_int_range(DynamicProfileRule::Range &dest, + const Glib::KeyFile &kf, const Glib::ustring &group, + const Glib::ustring &key) +{ + try { + int min = kf.get_integer(group, key + "_min"); + int max = kf.get_integer(group, key + "_max"); + if (min <= max) { + dest.min = min; + dest.max = max; + } + } catch (Glib::KeyFileError &e) { + } +} + + +void get_double_range(DynamicProfileRule::Range &dest, + const Glib::KeyFile &kf, const Glib::ustring &group, + const Glib::ustring &key) +{ + try { + double min = kf.get_double(group, key + "_min"); + double max = kf.get_double(group, key + "_max"); + if (min <= max) { + dest.min = min; + dest.max = max; + } + } catch (Glib::KeyFileError &e) { + } +} + + +void get_optional(DynamicProfileRule::Optional &dest, + const Glib::KeyFile &kf, const Glib::ustring &group, + const Glib::ustring &key) +{ + try { + bool e = kf.get_boolean(group, key + "_enabled"); + if (e) { + Glib::ustring s = kf.get_string(group, key + "_value"); + dest.enabled = e; + dest.value = s; + } + } catch (Glib::KeyFileError &) { + } +} + +void set_int_range(Glib::KeyFile &kf, const Glib::ustring &group, + const Glib::ustring &key, + const DynamicProfileRule::Range &val) +{ + kf.set_integer(group, key + "_min", val.min); + kf.set_integer(group, key + "_max", val.max); +} + +void set_double_range(Glib::KeyFile &kf, const Glib::ustring &group, + const Glib::ustring &key, + const DynamicProfileRule::Range &val) +{ + kf.set_double(group, key + "_min", val.min); + kf.set_double(group, key + "_max", val.max); +} + +void set_optional(Glib::KeyFile &kf, const Glib::ustring &group, + const Glib::ustring &key, + const DynamicProfileRule::Optional &val) +{ + kf.set_boolean(group, key + "_enabled", val.enabled); + kf.set_string(group, key + "_value", val.value); +} + +} // namespace + + +bool loadDynamicProfileRules(std::vector &out) +{ + out.clear(); + Glib::KeyFile kf; + try { + if (!kf.load_from_file( + Glib::build_filename(Options::rtdir, "dynamicprofile.cfg"))) { + return false; + } + } catch (Glib::Error &e) { + return false; + } + if (options.rtSettings.verbose) { + printf("loading dynamic profiles...\n"); + } + auto groups = kf.get_groups(); + for (auto group : groups) { + // groups are of the form "rule N", where N is a positive integer + if (group.find("rule ") != 0) { + return false; + } + std::istringstream buf(group.c_str() + 5); + int serial = 0; + if (!(buf >> serial) || !buf.eof()) { + return false; + } + if (options.rtSettings.verbose) { + printf(" loading rule %d\n", serial); + } + + out.emplace_back(DynamicProfileRule()); + DynamicProfileRule &rule = out.back(); + rule.serial_number = serial; + get_int_range(rule.iso, kf, group, "iso"); + get_double_range(rule.fnumber, kf, group, "fnumber"); + get_double_range(rule.focallen, kf, group, "focallen"); + get_double_range(rule.shutterspeed, kf, group, "shutterspeed"); + get_double_range(rule.expcomp, kf, group, "expcomp"); + get_optional(rule.camera, kf, group, "camera"); + get_optional(rule.lens, kf, group, "lens"); + try { + rule.profilepath = kf.get_string(group, "profilepath"); + } catch (Glib::KeyFileError &) { + out.pop_back(); + } + } + std::sort(out.begin(), out.end()); + return true; +} + + +bool storeDynamicProfileRules(const std::vector &rules) +{ + if (options.rtSettings.verbose) { + printf("saving dynamic profiles...\n"); + } + Glib::KeyFile kf; + for (auto &rule : rules) { + std::ostringstream buf; + buf << "rule " << rule.serial_number; + Glib::ustring group = buf.str(); + set_int_range(kf, group, "iso", rule.iso); + set_double_range(kf, group, "fnumber", rule.fnumber); + set_double_range(kf, group, "focallen", rule.focallen); + set_double_range(kf, group, "shutterspeed", rule.shutterspeed); + set_double_range(kf, group, "expcomp", rule.expcomp); + set_optional(kf, group, "camera", rule.camera); + set_optional(kf, group, "lens", rule.lens); + kf.set_string(group, "profilepath", rule.profilepath); + } + return kf.save_to_file( + Glib::build_filename(Options::rtdir, "dynamicprofile.cfg")); +} + + +PartialProfile *loadDynamicProfile(const ImageMetaData *im) +{ + PartialProfile *ret = new PartialProfile(true, true); + for (auto &rule : profileStore.getDynamicProfileRules()) { + if (rule.matches(im)) { + if (options.rtSettings.verbose) { + printf("found matching profile %s\n", + rule.profilepath.c_str()); + } + const PartialProfile *p = + profileStore.getProfile(rule.profilepath); + if (p != nullptr) { + p->applyTo(ret->pparams); + } else { + printf("ERROR loading matching profile from: %s\n", + rule.profilepath.c_str()); + } + } + } + return ret; +} diff --git a/rtgui/dynamicprofile.h b/rtgui/dynamicprofile.h new file mode 100644 index 000000000..4c5e552e4 --- /dev/null +++ b/rtgui/dynamicprofile.h @@ -0,0 +1,74 @@ +/* -*- C++ -*- + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Alberto Griggio + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#ifndef _DYNAMICPROFILE_H_ +#define _DYNAMICPROFILE_H_ + +#include +#include +#include "options.h" + + +class DynamicProfileRule { +public: + template + struct Range { + T min; + T max; + explicit Range(T l=T(), T u=T()): min(l), max(u) {} + + bool operator()(T val) const + { + return val >= min && val <= max; + } + }; + + struct Optional { + Glib::ustring value; + bool enabled; + explicit Optional(const Glib::ustring v="", bool e=false): + value(v), enabled(e) {} + + bool operator()(const Glib::ustring &val) const; + }; + + DynamicProfileRule(); + bool matches(const rtengine::ImageMetaData *im) const; + bool operator<(const DynamicProfileRule &other) const; + + int serial_number; + Range iso; + Range fnumber; + Range focallen; + Range shutterspeed; + Range expcomp; + Optional camera; + Optional lens; + Glib::ustring profilepath; +}; + + +bool loadDynamicProfileRules(std::vector &out); +bool storeDynamicProfileRules( + const std::vector &rules); + +rtengine::procparams::PartialProfile *loadDynamicProfile( + const rtengine::ImageMetaData *im); + + +#endif // _DYNAMICPROFILE_H_ diff --git a/rtgui/dynamicprofilepanel.cc b/rtgui/dynamicprofilepanel.cc new file mode 100644 index 000000000..e5f9ae1cc --- /dev/null +++ b/rtgui/dynamicprofilepanel.cc @@ -0,0 +1,533 @@ +/* -*- C++ -*- + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Alberto Griggio + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +#include "dynamicprofilepanel.h" +#include "multilangmgr.h" +#include "profilestore.h" +#include "../rtengine/rtengine.h" +#include +#include + + +//----------------------------------------------------------------------------- +// DynamicProfilePanel::EditDialog +//----------------------------------------------------------------------------- + +DynamicProfilePanel::EditDialog::EditDialog(const Glib::ustring &title, + Gtk::Window &parent): + Gtk::Dialog(title, parent) +{ + profilepath_ = Gtk::manage(new ProfileStoreComboBox()); + Gtk::HBox *hb = Gtk::manage(new Gtk::HBox()); + hb->pack_start(*Gtk::manage(new Gtk::Label(M("DYNPROFILEEDITOR_PROFILE"))), + false, false, 4); + hb->pack_start(*profilepath_, true, true, 2); + get_content_area()->pack_start(*hb, Gtk::PACK_SHRINK, 4); + + add_optional(M("EXIFFILTER_CAMERA"), has_camera_, camera_); + add_optional(M("EXIFFILTER_LENS"), has_lens_, lens_); + + add_range(M("EXIFFILTER_ISO"), iso_min_, iso_max_); + add_range(M("EXIFFILTER_APERTURE"), fnumber_min_, fnumber_max_); + add_range(M("EXIFFILTER_FOCALLEN"), focallen_min_, focallen_max_); + add_range(M("EXIFFILTER_SHUTTER"), shutterspeed_min_, shutterspeed_max_); + add_range(M("EXIFFILTER_EXPOSURECOMPENSATION"), expcomp_min_, expcomp_max_); + + add_button(M("GENERAL_OK"), 1); + add_button(M("GENERAL_CANCEL"), 2); + + set_ranges(); + + show_all_children(); +} + + +void DynamicProfilePanel::EditDialog::set_rule( + const DynamicProfileRule &rule) +{ + iso_min_->set_value(rule.iso.min); + iso_max_->set_value(rule.iso.max); + + fnumber_min_->set_value(rule.fnumber.min); + fnumber_max_->set_value(rule.fnumber.max); + + focallen_min_->set_value(rule.focallen.min); + focallen_max_->set_value(rule.focallen.max); + + shutterspeed_min_->set_value(rule.shutterspeed.min); + shutterspeed_max_->set_value(rule.shutterspeed.max); + + expcomp_min_->set_value(rule.expcomp.min); + expcomp_max_->set_value(rule.expcomp.max); + + has_camera_->set_active(rule.camera.enabled); + camera_->set_text(rule.camera.value); + + has_lens_->set_active(rule.lens.enabled); + lens_->set_text(rule.lens.value); + + profilepath_->updateProfileList(); + if (!profilepath_->setActiveRowFromFullPath(rule.profilepath)) { + profilepath_->setInternalEntry(); + } +} + + +DynamicProfileRule DynamicProfilePanel::EditDialog::get_rule() +{ + DynamicProfileRule ret; + ret.iso.min = iso_min_->get_value_as_int(); + ret.iso.max = iso_max_->get_value_as_int(); + + ret.fnumber.min = fnumber_min_->get_value(); + ret.fnumber.max = fnumber_max_->get_value(); + + ret.focallen.min = focallen_min_->get_value(); + ret.focallen.max = focallen_max_->get_value(); + + ret.shutterspeed.min = shutterspeed_min_->get_value(); + ret.shutterspeed.max = shutterspeed_max_->get_value(); + + ret.expcomp.min = expcomp_min_->get_value(); + ret.expcomp.max = expcomp_max_->get_value(); + + ret.camera.enabled = has_camera_->get_active(); + ret.camera.value = camera_->get_text(); + + ret.lens.enabled = has_lens_->get_active(); + ret.lens.value = lens_->get_text(); + + ret.profilepath = profilepath_->getFullPathFromActiveRow(); + + return ret; +} + +void DynamicProfilePanel::EditDialog::set_ranges() +{ + DynamicProfileRule default_rule; + iso_min_->set_digits(0); + iso_max_->set_digits(0); + iso_min_->set_increments(1, 10); + iso_max_->set_increments(1, 10); + iso_min_->set_range(default_rule.iso.min, default_rule.iso.max); + iso_max_->set_range(default_rule.iso.min, default_rule.iso.max); + iso_min_->set_value(default_rule.iso.min); + iso_max_->set_value(default_rule.iso.max); + +#define DOIT_(name) \ + name ## _min_->set_digits(1); \ + name ## _max_->set_digits(1); \ + name ## _min_->set_increments(0.1, 1); \ + name ## _max_->set_increments(0.1, 1); \ + name ## _min_->set_range(default_rule. name .min, \ + default_rule. name .max); \ + name ## _max_->set_range(default_rule. name .min, \ + default_rule. name .max); \ + name ## _min_->set_value(default_rule. name .min); \ + name ## _max_->set_value(default_rule. name .max) + + DOIT_(fnumber); + DOIT_(focallen); + DOIT_(shutterspeed); + DOIT_(expcomp); +#undef DOIT_ + shutterspeed_min_->set_digits(4); + shutterspeed_max_->set_digits(4); + + profilepath_->setInternalEntry(); +} + + +void DynamicProfilePanel::EditDialog::add_range(const Glib::ustring &name, + Gtk::SpinButton *&from, Gtk::SpinButton *&to) +{ + Gtk::HBox *hb = Gtk::manage(new Gtk::HBox()); + hb->pack_start(*Gtk::manage(new Gtk::Label(name)), false, false, 4); + from = Gtk::manage(new Gtk::SpinButton()); + to = Gtk::manage(new Gtk::SpinButton()); + from->set_numeric(true); + to->set_numeric(true); + hb->pack_start(*from, true, true, 2); + hb->pack_start(*Gtk::manage(new Gtk::Label(" - ")), + false, false, 4); + hb->pack_start(*to, true, true, 2); + get_content_area()->pack_start(*hb, Gtk::PACK_SHRINK, 4); +} + + +void DynamicProfilePanel::EditDialog::add_optional(const Glib::ustring &name, + Gtk::CheckButton *&check, Gtk::Entry *&field) +{ + check = Gtk::manage (new Gtk::CheckButton(name)); + Gtk::HBox *hb = Gtk::manage(new Gtk::HBox()); + hb->pack_start(*check, Gtk::PACK_SHRINK, 4); + field = Gtk::manage(new Gtk::Entry()); + hb->pack_start(*field, true, true, 2); + get_content_area()->pack_start(*hb, Gtk::PACK_SHRINK, 4); + field->set_tooltip_text(M("DYNPROFILEEDITOR_ENTRY_TOOLTIP")); +} + + +//----------------------------------------------------------------------------- +// DynamicProfilePanel +//----------------------------------------------------------------------------- + +DynamicProfilePanel::DynamicProfilePanel(): + vbox_(Gtk::ORIENTATION_VERTICAL), + button_up_(M("DYNPROFILEEDITOR_MOVE_UP")), + button_down_(M("DYNPROFILEEDITOR_MOVE_DOWN")), + button_new_(M("DYNPROFILEEDITOR_NEW")), + button_edit_(M("DYNPROFILEEDITOR_EDIT")), + button_delete_(M("DYNPROFILEEDITOR_DELETE")) +{ + add(vbox_); + + treeview_.set_grid_lines(Gtk::TREE_VIEW_GRID_LINES_VERTICAL); + scrolledwindow_.add(treeview_); + + scrolledwindow_.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + + vbox_.pack_start(scrolledwindow_); + vbox_.pack_start(buttonbox_, Gtk::PACK_SHRINK); + + buttonbox_.pack_start(button_new_, Gtk::PACK_SHRINK); + buttonbox_.pack_start(button_edit_, Gtk::PACK_SHRINK); + buttonbox_.pack_start(button_delete_, Gtk::PACK_SHRINK); + buttonbox_.pack_start(button_up_, Gtk::PACK_SHRINK); + buttonbox_.pack_start(button_down_, Gtk::PACK_SHRINK); + buttonbox_.set_border_width(5); + buttonbox_.set_layout(Gtk::BUTTONBOX_END); + button_up_.signal_clicked().connect( + sigc::mem_fun(*this, &DynamicProfilePanel::on_button_up)); + button_down_.signal_clicked().connect( + sigc::mem_fun(*this, &DynamicProfilePanel::on_button_down)); + button_new_.signal_clicked().connect( + sigc::mem_fun(*this, &DynamicProfilePanel::on_button_new)); + button_edit_.signal_clicked().connect( + sigc::mem_fun(*this, &DynamicProfilePanel::on_button_edit)); + button_delete_.signal_clicked().connect( + sigc::mem_fun(*this, &DynamicProfilePanel::on_button_delete)); + + treemodel_ = Gtk::ListStore::create(columns_); + treeview_.set_model(treemodel_); + + auto cell = Gtk::manage(new Gtk::CellRendererText()); + int cols_count = treeview_.append_column( + M("DYNPROFILEEDITOR_PROFILE"), *cell); + auto col = treeview_.get_column(cols_count - 1); + if (col) { + col->set_cell_data_func( + *cell, sigc::mem_fun( + *this, &DynamicProfilePanel::render_profilepath)); + } + cell = Gtk::manage(new Gtk::CellRendererText()); + cols_count = treeview_.append_column( + M("EXIFFILTER_CAMERA"), *cell); + col = treeview_.get_column(cols_count - 1); + if (col) { + col->set_cell_data_func( + *cell, sigc::mem_fun( + *this, &DynamicProfilePanel::render_camera)); + } + cell = Gtk::manage(new Gtk::CellRendererText()); + cols_count = treeview_.append_column(M("EXIFFILTER_LENS"), *cell); + col = treeview_.get_column(cols_count - 1); + if (col) { + col->set_cell_data_func( + *cell, sigc::mem_fun( + *this, &DynamicProfilePanel::render_lens)); + } + cell = Gtk::manage(new Gtk::CellRendererText()); + cols_count = treeview_.append_column(M("EXIFFILTER_ISO"), *cell); + col = treeview_.get_column(cols_count - 1); + if (col) { + col->set_cell_data_func( + *cell, sigc::mem_fun( + *this, &DynamicProfilePanel::render_iso)); + } + cell = Gtk::manage(new Gtk::CellRendererText()); + cols_count = treeview_.append_column(M("EXIFFILTER_APERTURE"), *cell); + col = treeview_.get_column(cols_count - 1); + if (col) { + col->set_cell_data_func( + *cell, sigc::mem_fun( + *this, &DynamicProfilePanel::render_fnumber)); + } + cell = Gtk::manage(new Gtk::CellRendererText()); + cols_count = treeview_.append_column(M("EXIFFILTER_FOCALLEN"), *cell); + col = treeview_.get_column(cols_count - 1); + if (col) { + col->set_cell_data_func( + *cell, sigc::mem_fun( + *this, &DynamicProfilePanel::render_focallen)); + } + cell = Gtk::manage(new Gtk::CellRendererText()); + cols_count = treeview_.append_column(M("EXIFFILTER_SHUTTER"), *cell); + col = treeview_.get_column(cols_count - 1); + if (col) { + col->set_cell_data_func( + *cell, sigc::mem_fun( + *this, &DynamicProfilePanel::render_shutterspeed)); + } + cell = Gtk::manage(new Gtk::CellRendererText()); + cols_count = treeview_.append_column( + M("EXIFFILTER_EXPOSURECOMPENSATION"), *cell); + col = treeview_.get_column(cols_count - 1); + if (col) { + col->set_cell_data_func( + *cell, sigc::mem_fun( + *this, &DynamicProfilePanel::render_expcomp)); + } + + show_all_children(); + + for (auto &r : profileStore.getDynamicProfileRules()) { + add_rule(r); + } +} + + +void DynamicProfilePanel::update_rule(Gtk::TreeModel::Row row, + const DynamicProfileRule &rule) +{ + row[columns_.iso] = rule.iso; + row[columns_.fnumber] = rule.fnumber; + row[columns_.focallen] = rule.focallen; + row[columns_.shutterspeed] = rule.shutterspeed; + row[columns_.expcomp] = rule.expcomp; + row[columns_.camera] = rule.camera; + row[columns_.lens] = rule.lens; + row[columns_.profilepath] = rule.profilepath; +} + +void DynamicProfilePanel::add_rule(const DynamicProfileRule &rule) +{ + auto row = *(treemodel_->append()); + update_rule(row, rule); +} + + +DynamicProfileRule DynamicProfilePanel::to_rule(Gtk::TreeModel::Row row, + int serial) +{ + DynamicProfileRule ret; + ret.serial_number = serial; + ret.iso = row[columns_.iso]; + ret.fnumber = row[columns_.fnumber]; + ret.focallen = row[columns_.focallen]; + ret.shutterspeed = row[columns_.shutterspeed]; + ret.expcomp = row[columns_.expcomp]; + ret.camera = row[columns_.camera]; + ret.lens = row[columns_.lens]; + ret.profilepath = row[columns_.profilepath]; + return ret; +} + + +void DynamicProfilePanel::render_profilepath( + Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) +{ + auto row = *iter; + Gtk::CellRendererText *ct = static_cast(cell); + auto value = row[columns_.profilepath]; + auto pse = profileStore.findEntryFromFullPath(value); + if (pse != nullptr) { + ct->property_text() = pse->label; + } else { + ct->property_text() = value; + } +} + + +#define RENDER_RANGE_(tp, name, tostr) \ + auto row = *iter; \ + Gtk::CellRendererText *ct = static_cast(cell); \ + DynamicProfileRule::Range r = row[columns_. name]; \ + DynamicProfileRule dflt; \ + if (r.min > dflt.name.min || r.max < dflt.name.max) { \ + auto value = tostr(r.min) + " - " + tostr(r.max); \ + ct->property_text() = value; \ + } else { \ + ct->property_text() = ""; \ + } + + +namespace { + +template +Glib::ustring to_str(V n, int precision=1) +{ + std::ostringstream buf; + buf << std::setprecision(precision) << std::fixed << n; + return buf.str(); +} + +} // namespace + +void DynamicProfilePanel::render_iso( + Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) +{ + RENDER_RANGE_(int, iso, to_str); +} + + +void DynamicProfilePanel::render_fnumber( + Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) +{ + RENDER_RANGE_(double, fnumber, + [](double f) + { return std::string("f/") + + rtengine::ImageMetaData::apertureToString(f); }); +} + + +void DynamicProfilePanel::render_focallen( + Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) +{ + RENDER_RANGE_(double, focallen, to_str); +} + + +void DynamicProfilePanel::render_shutterspeed( + Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) +{ + RENDER_RANGE_(double, shutterspeed, + rtengine::ImageMetaData::shutterToString); +} + + +void DynamicProfilePanel::render_expcomp( + Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) +{ + RENDER_RANGE_(double, expcomp, to_str); +} + +#undef RENDER_RANGE_ + +#define RENDER_OPTIONAL_(name) \ + auto row = *iter; \ + Gtk::CellRendererText *ct = static_cast(cell); \ + DynamicProfileRule::Optional o = row[columns_. name]; \ + if (o.enabled) { \ + ct->property_text() = o.value; \ + } else { \ + ct->property_text() = ""; \ + } + +void DynamicProfilePanel::render_camera( + Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) +{ + RENDER_OPTIONAL_(camera); +} + + +void DynamicProfilePanel::render_lens( + Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) +{ + RENDER_OPTIONAL_(lens); +} + +#undef RENDER_OPTIONAL_ + +void DynamicProfilePanel::on_button_up() +{ + auto s = treeview_.get_selection(); + if (!s->count_selected_rows()) { + return; + } + auto it = s->get_selected(); + if (it != treemodel_->children().begin()) { + auto it2 = it; + --it2; + treemodel_->iter_swap(it, it2); + } +} + +void DynamicProfilePanel::on_button_down() +{ + auto s = treeview_.get_selection(); + if (!s->count_selected_rows()) { + return; + } + auto it = s->get_selected(); + auto it2 = it; + ++it2; + if (it2 != treemodel_->children().end()) { + treemodel_->iter_swap(it, it2); + } +} + + +void DynamicProfilePanel::on_button_delete() +{ + auto s = treeview_.get_selection(); + if (!s->count_selected_rows()) { + return; + } + auto it = s->get_selected(); + treemodel_->erase(it); +} + + +void DynamicProfilePanel::on_button_new() +{ + EditDialog d(M("DYNPROFILEEDITOR_NEW_RULE"), + static_cast(*get_toplevel())); + int status = d.run(); + if (status == 1) { + DynamicProfileRule rule = d.get_rule(); + add_rule(rule); + } +} + + +void DynamicProfilePanel::on_button_edit() +{ + auto s = treeview_.get_selection(); + if (!s->count_selected_rows()) { + return; + } + EditDialog d(M("DYNPROFILEEDITOR_EDIT_RULE"), + static_cast(*get_toplevel())); + auto it = s->get_selected(); + Gtk::TreeModel::Row row = *(s->get_selected()); + d.set_rule(to_rule(row)); + int status = d.run(); + if (status == 1) { + update_rule(row, d.get_rule()); + } +} + + +void DynamicProfilePanel::save() +{ + std::vector rules; + int serial = 1; + for (auto row : treemodel_->children()) { + rules.emplace_back(to_rule(row, serial++)); + } + if (!storeDynamicProfileRules(rules)) { + printf("Error in saving dynamic profile rules\n"); + } else { + profileStore.setDynamicProfileRules(rules); + if (options.rtSettings.verbose) { + printf("Saved %d dynamic profile rules\n", int(rules.size())); + } + } +} diff --git a/rtgui/dynamicprofilepanel.h b/rtgui/dynamicprofilepanel.h new file mode 100644 index 000000000..72ff95b9a --- /dev/null +++ b/rtgui/dynamicprofilepanel.h @@ -0,0 +1,140 @@ +/* -*- C++ -*- + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Alberto Griggio + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#ifndef _DYNAMICPROFILEPANEL_H_ +#define _DYNAMICPROFILEPANEL_H_ + +#include +#include "dynamicprofile.h" +#include "profilestore.h" + +class DynamicProfilePanel: public Gtk::VBox { +public: + DynamicProfilePanel(); + void save(); + +private: + void update_rule(Gtk::TreeModel::Row row, + const DynamicProfileRule &rule); + void add_rule(const DynamicProfileRule &rule); + DynamicProfileRule to_rule(Gtk::TreeModel::Row row, int serial=0); + + void on_button_quit(); + void on_button_up(); + void on_button_down(); + void on_button_new(); + void on_button_edit(); + void on_button_delete(); + + class DynamicProfileColumns: public Gtk::TreeModel::ColumnRecord { + public: + DynamicProfileColumns() + { + add(iso); + add(fnumber); + add(focallen); + add(shutterspeed); + add(expcomp); + add(camera); + add(lens); + add(profilepath); + } + + Gtk::TreeModelColumn> iso; + Gtk::TreeModelColumn> fnumber; + Gtk::TreeModelColumn> focallen; + Gtk::TreeModelColumn> shutterspeed; + Gtk::TreeModelColumn> expcomp; + Gtk::TreeModelColumn camera; + Gtk::TreeModelColumn lens; + Gtk::TreeModelColumn profilepath; + }; + + // cell renderers + void render_iso(Gtk::CellRenderer* cell, + const Gtk::TreeModel::iterator& iter); + void render_fnumber(Gtk::CellRenderer* cell, + const Gtk::TreeModel::iterator& iter); + void render_focallen(Gtk::CellRenderer* cell, + const Gtk::TreeModel::iterator& iter); + void render_shutterspeed(Gtk::CellRenderer* cell, + const Gtk::TreeModel::iterator& iter); + void render_expcomp(Gtk::CellRenderer* cell, + const Gtk::TreeModel::iterator& iter); + void render_camera(Gtk::CellRenderer* cell, + const Gtk::TreeModel::iterator& iter); + void render_lens(Gtk::CellRenderer* cell, + const Gtk::TreeModel::iterator& iter); + void render_profilepath(Gtk::CellRenderer* cell, + const Gtk::TreeModel::iterator& iter); + + class EditDialog: public Gtk::Dialog { + public: + EditDialog(const Glib::ustring &title, Gtk::Window &parent); + void set_rule(const DynamicProfileRule &rule); + DynamicProfileRule get_rule(); + + private: + void set_ranges(); + void add_range(const Glib::ustring &name, + Gtk::SpinButton *&from, Gtk::SpinButton *&to); + void add_optional(const Glib::ustring &name, + Gtk::CheckButton *&check, Gtk::Entry *&field); + + Gtk::SpinButton *iso_min_; + Gtk::SpinButton *iso_max_; + + Gtk::SpinButton *fnumber_min_; + Gtk::SpinButton *fnumber_max_; + + Gtk::SpinButton *focallen_min_; + Gtk::SpinButton *focallen_max_; + + Gtk::SpinButton *shutterspeed_min_; + Gtk::SpinButton *shutterspeed_max_; + + Gtk::SpinButton *expcomp_min_; + Gtk::SpinButton *expcomp_max_; + + Gtk::CheckButton *has_camera_; + Gtk::Entry *camera_; + + Gtk::CheckButton *has_lens_; + Gtk::Entry *lens_; + + ProfileStoreComboBox *profilepath_; + }; + + DynamicProfileColumns columns_; + + //Child widgets: + Gtk::Box vbox_; + + Gtk::ScrolledWindow scrolledwindow_; + Gtk::TreeView treeview_; + Glib::RefPtr treemodel_; + + Gtk::ButtonBox buttonbox_; + Gtk::Button button_up_; + Gtk::Button button_down_; + Gtk::Button button_new_; + Gtk::Button button_edit_; + Gtk::Button button_delete_; +}; + +#endif // _DYNAMICPROFILEPANEL_H_ diff --git a/rtgui/edit.cc b/rtgui/edit.cc index 2f9b5eeef..476cd3602 100644 --- a/rtgui/edit.cc +++ b/rtgui/edit.cc @@ -191,7 +191,7 @@ void Circle::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer center_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } - cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*M_PI); + cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*rtengine::RT_PI); cr->stroke(); } } @@ -225,7 +225,7 @@ void Circle::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer } if (filled && state != INSENSITIVE) { - cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*M_PI); + cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*rtengine::RT_PI); if (innerLineWidth > 0.) { cr->fill_preserve(); @@ -234,7 +234,7 @@ void Circle::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer cr->fill(); } } else if (innerLineWidth > 0.) { - cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*M_PI); + cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*rtengine::RT_PI); if (state == INSENSITIVE) { std::valarray ds(1); @@ -274,7 +274,7 @@ void Circle::drawToMOChannel (Cairo::RefPtr &cr, unsigned short } else { cr->set_source_rgba (0., 0., 0., (id + 1) / 65535.); } - cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0, 2.*M_PI); + cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0, 2.*rtengine::RT_PI); if (filled) { if (innerLineWidth > 0.) { diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc index 6e32ea742..c016717a3 100644 --- a/rtgui/filebrowserentry.cc +++ b/rtgui/filebrowserentry.cc @@ -719,7 +719,7 @@ void FileBrowserEntry::drawStraightenGuide (Cairo::RefPtr cr) if (action_x != press_x || action_y != press_y) { double arg = (press_x - action_x) / sqrt(double((press_x - action_x) * (press_x - action_x) + (press_y - action_y) * (press_y - action_y))); double sol1, sol2; - double pi = M_PI; + double pi = rtengine::RT_PI; if (press_y > action_y) { sol1 = acos(arg) * 180 / pi; diff --git a/rtgui/gradient.cc b/rtgui/gradient.cc index 50625251e..cbaa39066 100644 --- a/rtgui/gradient.cc +++ b/rtgui/gradient.cc @@ -424,7 +424,7 @@ bool Gradient::button1Pressed(const int modifierKey) draggedPoint = currPos - centerPos; // compute the projected value of the dragged point - draggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle - degree->getValue()) / 180.*M_PI); + draggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle - degree->getValue()) / 180.*rtengine::RT_PI); if (lastObject == 3) { draggedFeatherOffset = -draggedFeatherOffset; @@ -526,7 +526,7 @@ bool Gradient::drag1(const int modifierKey) currPos.y = p; draggedPoint = currPos - centerPos; - double currDraggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle - degree->getValue()) / 180.*M_PI); + double currDraggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle - degree->getValue()) / 180.*rtengine::RT_PI); if (lastObject == 2) // Dragging the upper feather bar diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index 7bc0861f0..3f88adf0c 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -315,6 +315,7 @@ public: class MyComboBoxText : public Gtk::ComboBoxText { int naturalWidth, minimumWidth; + sigc::connection myConnection; bool on_scroll_event (GdkEventScroll* event); void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const; @@ -324,6 +325,8 @@ public: MyComboBoxText (bool has_entry = false); void setPreferredWidth (int minimum_width, int natural_width); + void connect(const sigc::connection &connection) { myConnection = connection; } + void block(bool blocked) { myConnection.block(blocked); } }; /** diff --git a/rtgui/lockablecolorpicker.cc b/rtgui/lockablecolorpicker.cc index 70a06ddb2..d10dfb438 100644 --- a/rtgui/lockablecolorpicker.cc +++ b/rtgui/lockablecolorpicker.cc @@ -127,13 +127,13 @@ void LockableColorPicker::updateBackBuffer () // black background of the whole color picker bbcr->set_line_width (0.); bbcr->set_source_rgba (0., 0., 0., opacity); - bbcr->arc_negative (center, center, center, 0., (double)M_PI); + bbcr->arc_negative (center, center, center, 0., (double)rtengine::RT_PI); bbcr->line_to (0, 2. * center + textHeight); - bbcr->arc_negative (2. * textPadding, 2. * center + textHeight, 2. * textPadding, (double)M_PI, (double)M_PI / 2.); + bbcr->arc_negative (2. * textPadding, 2. * center + textHeight, 2. * textPadding, (double)rtengine::RT_PI, (double)rtengine::RT_PI / 2.); bbcr->line_to (textWidth, 2. * center + textHeight + 2. * textPadding); - bbcr->arc_negative (textWidth, 2. * center + textHeight, 2. * textPadding, (double)M_PI / 2., 0.); + bbcr->arc_negative (textWidth, 2. * center + textHeight, 2. * textPadding, (double)rtengine::RT_PI / 2., 0.); bbcr->line_to (textWidth + 2. * textPadding, 2. * center + 2. * textPadding); - bbcr->arc_negative (textWidth, 2. * center + 2. * textPadding, 2. * textPadding, 0., (double)M_PI * 1.5); + bbcr->arc_negative (textWidth, 2. * center + 2. * textPadding, 2. * textPadding, 0., (double)rtengine::RT_PI * 1.5); bbcr->line_to (2. * center, 2. * center); bbcr->close_path(); bbcr->set_line_join (Cairo::LINE_JOIN_BEVEL); @@ -141,13 +141,13 @@ void LockableColorPicker::updateBackBuffer () bbcr->fill (); // light grey circle around the color mark - bbcr->arc (center, center, center - circlePadding / 2., 0., 2. * (double)M_PI); + bbcr->arc (center, center, center - circlePadding / 2., 0., 2. * (double)rtengine::RT_PI); bbcr->set_source_rgb (0.75, 0.75, 0.75); bbcr->set_line_width (circlePadding - 2.); bbcr->stroke (); // spot disc with picked color - bbcr->arc (center, center, center - circlePadding, 0., 2. * (double)M_PI); + bbcr->arc (center, center, center - circlePadding, 0., 2. * (double)rtengine::RT_PI); bbcr->set_source_rgb (rpreview, gpreview, bpreview); // <- set the picker color here bbcr->set_line_width (0.); bbcr->fill(); @@ -226,7 +226,7 @@ void LockableColorPicker::updateBackBuffer () float center = (float)size / 2.f + circlePadding; // light grey circle around the color mark - bbcr->arc (center, center, center - circlePadding / 2., 0., 2. * (double)M_PI); + bbcr->arc (center, center, center - circlePadding / 2., 0., 2. * (double)rtengine::RT_PI); bbcr->set_source_rgba (0., 0., 0., opacity); bbcr->set_line_width(circlePadding); bbcr->stroke_preserve(); diff --git a/rtgui/main-cli.cc b/rtgui/main-cli.cc index d92643489..d9a481e7e 100644 --- a/rtgui/main-cli.cc +++ b/rtgui/main-cli.cc @@ -169,6 +169,9 @@ int main(int argc, char **argv) #ifdef WIN32 bool consoleOpened = false; + // suppression of annoying error boxes + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); + if (argc > 1 || options.rtSettings.verbose) { if (options.rtSettings.verbose || ( !Glib::file_test (fname_to_utf8 (argv[1]), Glib::FILE_TEST_EXISTS ) && !Glib::file_test (fname_to_utf8 (argv[1]), Glib::FILE_TEST_IS_DIR))) { bool stdoutRedirectedtoFile = (GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == 0x0001); @@ -577,7 +580,7 @@ int processLineParams( int argc, char **argv ) rawParams = new rtengine::procparams::PartialProfile(true, true); Glib::ustring profPath = options.findProfilePath(options.defProfRaw); - if (options.is_defProfRawMissing() || profPath.empty() || rawParams->load(profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, options.defProfRaw.substr(5) + paramFileExtension))) { + if (options.is_defProfRawMissing() || profPath.empty() || (profPath != DEFPROFILE_DYNAMIC && rawParams->load(profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, options.defProfRaw.substr(5) + paramFileExtension)))) { std::cerr << "Error: default raw processing profile not found" << std::endl; rawParams->deleteInstance(); delete rawParams; @@ -588,7 +591,7 @@ int processLineParams( int argc, char **argv ) imgParams = new rtengine::procparams::PartialProfile(true); profPath = options.findProfilePath(options.defProfImg); - if (options.is_defProfImgMissing() || profPath.empty() || imgParams->load(profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, options.defProfImg.substr(5) + paramFileExtension))) { + if (options.is_defProfImgMissing() || profPath.empty() || (profPath != DEFPROFILE_DYNAMIC && imgParams->load(profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, options.defProfImg.substr(5) + paramFileExtension)))) { std::cerr << "Error: default non-raw processing profile not found" << std::endl; imgParams->deleteInstance(); delete imgParams; @@ -660,9 +663,19 @@ int processLineParams( int argc, char **argv ) if (useDefault) { if (isRaw) { + if (options.defProfRaw == DEFPROFILE_DYNAMIC) { + rawParams->deleteInstance(); + delete rawParams; + rawParams = loadDynamicProfile(ii->getMetaData()); + } std::cout << " Merging default raw processing profile" << std::endl; rawParams->applyTo(¤tParams); - } else { + } else { + if (options.defProfImg == DEFPROFILE_DYNAMIC) { + imgParams->deleteInstance(); + delete imgParams; + imgParams = loadDynamicProfile(ii->getMetaData()); + } std::cout << " Merging default non-raw processing profile" << std::endl; imgParams->applyTo(¤tParams); } diff --git a/rtgui/main.cc b/rtgui/main.cc index a328260db..00cdc3b94 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -38,6 +38,7 @@ #include "rtimage.h" #include "version.h" #include "extprog.h" +#include "dynamicprofile.h" #ifndef WIN32 #include diff --git a/rtgui/mydiagonalcurve.cc b/rtgui/mydiagonalcurve.cc index aac021748..8bdb7fa0d 100644 --- a/rtgui/mydiagonalcurve.cc +++ b/rtgui/mydiagonalcurve.cc @@ -481,12 +481,12 @@ void MyDiagonalCurve::draw (int handle) double x = double(graphX + 1) + double((graphW - 2) * curve.x.at(i)); // project (curve.x.at(i), 0, 1, graphW); double y = double(graphY - 1) - double((graphH - 2) * curve.y.at(i)); // project (curve.y.at(i), 0, 1, graphH); - cr->arc (x, y, RADIUS + 0.5, 0, 2 * M_PI); + cr->arc (x, y, RADIUS + 0.5, 0, 2 * rtengine::RT_PI); cr->fill (); if (i == edited_point) { cr->set_line_width(2.); - cr->arc (x, y, RADIUS + 3.5, 0, 2 * M_PI); + cr->arc (x, y, RADIUS + 3.5, 0, 2 * rtengine::RT_PI); cr->stroke(); cr->set_line_width(1.); } diff --git a/rtgui/myflatcurve.cc b/rtgui/myflatcurve.cc index a5f08b8ed..532557a3b 100644 --- a/rtgui/myflatcurve.cc +++ b/rtgui/myflatcurve.cc @@ -456,13 +456,13 @@ void MyFlatCurve::draw () double x = double(graphX + 1) + innerW * curve.x.at(i); // project (curve.x.at(i), 0, 1, graphW); double y = double(graphY - 1) - innerH * curve.y.at(i); // project (curve.y.at(i), 0, 1, graphH); - cr->arc (x, y, (double)RADIUS, 0, 2 * M_PI); + cr->arc (x, y, (double)RADIUS, 0, 2 * rtengine::RT_PI); cr->fill (); if (i == edited_point) { cr->set_source_rgb (1.0, 0.0, 0.0); cr->set_line_width(2.); - cr->arc (x, y, RADIUS + 3.5, 0, 2 * M_PI); + cr->arc (x, y, RADIUS + 3.5, 0, 2 * rtengine::RT_PI); cr->stroke(); cr->set_line_width(1.); } diff --git a/rtgui/options.cc b/rtgui/options.cc index 95bb59061..3daa764ec 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -241,6 +241,10 @@ Glib::ustring Options::findProfilePath (Glib::ustring &profName) return profName; } + if (profName == DEFPROFILE_DYNAMIC) { + return profName; + } + Glib::ustring p = profName.substr (0, 4); if (p == "${U}") { @@ -604,6 +608,7 @@ void Options::setDefaults () 0, // ADDSET_RETI_VART 0, // ADDSET_RETI_GAM 0, // ADDSET_RETI_SLO + 0, // ADDSET_WB_TEMPBIAS }; rtSettings.darkFramesPath = ""; diff --git a/rtgui/options.h b/rtgui/options.h index 84b9b2473..7c0a3534d 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -39,11 +39,23 @@ #define DEFPROFILE_IMG "Neutral" // Profile name to use for internal values' profile #define DEFPROFILE_INTERNAL "Neutral" +// Special name for the Dynamic profile +#define DEFPROFILE_DYNAMIC "Dynamic" -class SaveFormat +struct SaveFormat { + SaveFormat() : + format("jpg"), + pngBits(8), + pngCompression(6), + jpegQuality(90), + jpegSubSamp(2), + tiffBits(8), + tiffUncompressed(true), + saveParams(true) + { + } -public: Glib::ustring format; int pngBits; int pngCompression; @@ -52,7 +64,6 @@ public: int tiffBits; bool tiffUncompressed; bool saveParams; - SaveFormat () : format("jpg"), pngBits(8), pngCompression(6), jpegQuality(90), jpegSubSamp(2), tiffBits(8), tiffUncompressed(true), saveParams(true) {}; }; enum ThFileType {FT_Invalid = -1, FT_None = 0, FT_Raw = 1, FT_Jpeg = 2, FT_Tiff = 3, FT_Png = 4, FT_Custom = 5, FT_Tiff16 = 6, FT_Png16 = 7, FT_Custom16 = 8}; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index ff3e4c0b1..4d05158c0 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -215,6 +215,7 @@ void ParamsEdited::set (bool v) wb.green = v; wb.temperature = v; wb.equal = v; + wb.tempBias = v; //colorShift.a = v; //colorShift.b = v; //lumaDenoise.enabled = v; @@ -359,6 +360,7 @@ void ParamsEdited::set (bool v) icm.gampos = v; icm.slpos = v; raw.bayersensor.method = v; + raw.bayersensor.imageNum = v; raw.bayersensor.ccSteps = v; raw.bayersensor.exBlack0 = v; raw.bayersensor.exBlack1 = v; @@ -369,6 +371,35 @@ void ParamsEdited::set (bool v) raw.bayersensor.dcbEnhance = v; //raw.bayersensor.allEnhance = v; raw.bayersensor.lmmseIterations = v; + raw.bayersensor.pixelShiftMotion = v; + raw.bayersensor.pixelShiftMotionCorrection = v; + raw.bayersensor.pixelShiftMotionCorrectionMethod = v; + raw.bayersensor.pixelShiftStddevFactorGreen = v; + raw.bayersensor.pixelShiftStddevFactorRed = v; + raw.bayersensor.pixelShiftStddevFactorBlue = v; + raw.bayersensor.pixelShiftEperIso = v; + raw.bayersensor.pixelShiftNreadIso = v; + raw.bayersensor.pixelShiftPrnu = v; + raw.bayersensor.pixelShiftSigma = v; + raw.bayersensor.pixelShiftSum = v; + raw.bayersensor.pixelShiftRedBlueWeight = v; + raw.bayersensor.pixelshiftShowMotion = v; + raw.bayersensor.pixelshiftShowMotionMaskOnly = v; + raw.bayersensor.pixelShiftAutomatic = v; + raw.bayersensor.pixelShiftNonGreenHorizontal = v; + raw.bayersensor.pixelShiftNonGreenVertical = v; + raw.bayersensor.pixelShiftHoleFill = v; + raw.bayersensor.pixelShiftMedian = v; + raw.bayersensor.pixelShiftMedian3 = v; + raw.bayersensor.pixelShiftGreen = v; + raw.bayersensor.pixelShiftBlur = v; + raw.bayersensor.pixelShiftSmooth = v; + raw.bayersensor.pixelShiftExp0 = v; + raw.bayersensor.pixelShiftLmmse = v; + raw.bayersensor.pixelShiftEqualBright = v; + raw.bayersensor.pixelShiftNonGreenCross = v; + raw.bayersensor.pixelShiftNonGreenCross2 = v; + raw.bayersensor.pixelShiftNonGreenAmaze = v; raw.bayersensor.greenEq = v; raw.bayersensor.linenoise = v; raw.xtranssensor.method = v; @@ -708,6 +739,7 @@ void ParamsEdited::initFrom (const std::vector wb.green = wb.green && p.wb.green == other.wb.green; wb.equal = wb.equal && p.wb.equal == other.wb.equal; wb.temperature = wb.temperature && p.wb.temperature == other.wb.temperature; + wb.tempBias = wb.tempBias && p.wb.tempBias == other.wb.tempBias; //colorShift.a = colorShift.a && p.colorShift.a == other.colorShift.a; //colorShift.b = colorShift.b && p.colorShift.b == other.colorShift.b; //lumaDenoise.enabled = lumaDenoise.enabled && p.lumaDenoise.enabled == other.lumaDenoise.enabled; @@ -854,6 +886,7 @@ void ParamsEdited::initFrom (const std::vector icm.gampos = icm.gampos && p.icm.gampos == other.icm.gampos; icm.slpos = icm.slpos && p.icm.slpos == other.icm.slpos; raw.bayersensor.method = raw.bayersensor.method && p.raw.bayersensor.method == other.raw.bayersensor.method; + raw.bayersensor.imageNum = raw.bayersensor.imageNum && p.raw.bayersensor.imageNum == other.raw.bayersensor.imageNum; raw.bayersensor.ccSteps = raw.bayersensor.ccSteps && p.raw.bayersensor.ccSteps == other.raw.bayersensor.ccSteps; raw.bayersensor.exBlack0 = raw.bayersensor.exBlack0 && p.raw.bayersensor.black0 == other.raw.bayersensor.black0; raw.bayersensor.exBlack1 = raw.bayersensor.exBlack1 && p.raw.bayersensor.black1 == other.raw.bayersensor.black1; @@ -864,6 +897,35 @@ void ParamsEdited::initFrom (const std::vector raw.bayersensor.dcbEnhance = raw.bayersensor.dcbEnhance && p.raw.bayersensor.dcb_enhance == other.raw.bayersensor.dcb_enhance; //raw.bayersensor.allEnhance = raw.bayersensor.allEnhance && p.raw.bayersensor.all_enhance == other.raw.bayersensor.all_enhance; raw.bayersensor.lmmseIterations = raw.bayersensor.lmmseIterations && p.raw.bayersensor.lmmse_iterations == other.raw.bayersensor.lmmse_iterations; + raw.bayersensor.pixelShiftMotion = raw.bayersensor.pixelShiftMotion && p.raw.bayersensor.pixelShiftMotion == other.raw.bayersensor.pixelShiftMotion; + raw.bayersensor.pixelShiftMotionCorrection = raw.bayersensor.pixelShiftMotionCorrection && p.raw.bayersensor.pixelShiftMotionCorrection == other.raw.bayersensor.pixelShiftMotionCorrection; + raw.bayersensor.pixelShiftMotionCorrectionMethod = raw.bayersensor.pixelShiftMotionCorrectionMethod && p.raw.bayersensor.pixelShiftMotionCorrectionMethod == other.raw.bayersensor.pixelShiftMotionCorrectionMethod; + raw.bayersensor.pixelShiftStddevFactorGreen = raw.bayersensor.pixelShiftStddevFactorGreen && p.raw.bayersensor.pixelShiftStddevFactorGreen == other.raw.bayersensor.pixelShiftStddevFactorGreen; + raw.bayersensor.pixelShiftStddevFactorRed = raw.bayersensor.pixelShiftStddevFactorRed && p.raw.bayersensor.pixelShiftStddevFactorRed == other.raw.bayersensor.pixelShiftStddevFactorRed; + raw.bayersensor.pixelShiftStddevFactorBlue = raw.bayersensor.pixelShiftStddevFactorBlue && p.raw.bayersensor.pixelShiftStddevFactorBlue == other.raw.bayersensor.pixelShiftStddevFactorBlue; + raw.bayersensor.pixelShiftEperIso = raw.bayersensor.pixelShiftEperIso && p.raw.bayersensor.pixelShiftEperIso == other.raw.bayersensor.pixelShiftEperIso; + raw.bayersensor.pixelShiftNreadIso = raw.bayersensor.pixelShiftNreadIso && p.raw.bayersensor.pixelShiftNreadIso == other.raw.bayersensor.pixelShiftNreadIso; + raw.bayersensor.pixelShiftPrnu = raw.bayersensor.pixelShiftPrnu && p.raw.bayersensor.pixelShiftPrnu == other.raw.bayersensor.pixelShiftPrnu; + raw.bayersensor.pixelShiftSigma = raw.bayersensor.pixelShiftSigma && p.raw.bayersensor.pixelShiftSigma == other.raw.bayersensor.pixelShiftSigma; + raw.bayersensor.pixelShiftSum = raw.bayersensor.pixelShiftSum && p.raw.bayersensor.pixelShiftSum == other.raw.bayersensor.pixelShiftSum; + raw.bayersensor.pixelShiftRedBlueWeight = raw.bayersensor.pixelShiftRedBlueWeight && p.raw.bayersensor.pixelShiftRedBlueWeight == other.raw.bayersensor.pixelShiftRedBlueWeight; + raw.bayersensor.pixelshiftShowMotion = raw.bayersensor.pixelshiftShowMotion && p.raw.bayersensor.pixelshiftShowMotion == other.raw.bayersensor.pixelshiftShowMotion; + raw.bayersensor.pixelshiftShowMotionMaskOnly = raw.bayersensor.pixelshiftShowMotionMaskOnly && p.raw.bayersensor.pixelshiftShowMotionMaskOnly == other.raw.bayersensor.pixelshiftShowMotionMaskOnly; + raw.bayersensor.pixelShiftAutomatic = raw.bayersensor.pixelShiftAutomatic && p.raw.bayersensor.pixelShiftAutomatic == other.raw.bayersensor.pixelShiftAutomatic; + raw.bayersensor.pixelShiftNonGreenHorizontal = raw.bayersensor.pixelShiftNonGreenHorizontal && p.raw.bayersensor.pixelShiftNonGreenHorizontal == other.raw.bayersensor.pixelShiftNonGreenHorizontal; + raw.bayersensor.pixelShiftNonGreenVertical = raw.bayersensor.pixelShiftNonGreenVertical && p.raw.bayersensor.pixelShiftNonGreenVertical == other.raw.bayersensor.pixelShiftNonGreenVertical; + raw.bayersensor.pixelShiftHoleFill = raw.bayersensor.pixelShiftHoleFill && p.raw.bayersensor.pixelShiftHoleFill == other.raw.bayersensor.pixelShiftHoleFill; + raw.bayersensor.pixelShiftMedian = raw.bayersensor.pixelShiftMedian && p.raw.bayersensor.pixelShiftMedian == other.raw.bayersensor.pixelShiftMedian; + raw.bayersensor.pixelShiftMedian3 = raw.bayersensor.pixelShiftMedian3 && p.raw.bayersensor.pixelShiftMedian3 == other.raw.bayersensor.pixelShiftMedian3; + raw.bayersensor.pixelShiftGreen = raw.bayersensor.pixelShiftGreen && p.raw.bayersensor.pixelShiftGreen == other.raw.bayersensor.pixelShiftGreen; + raw.bayersensor.pixelShiftBlur = raw.bayersensor.pixelShiftBlur && p.raw.bayersensor.pixelShiftBlur == other.raw.bayersensor.pixelShiftBlur; + raw.bayersensor.pixelShiftSmooth = raw.bayersensor.pixelShiftSmooth && p.raw.bayersensor.pixelShiftSmoothFactor == other.raw.bayersensor.pixelShiftSmoothFactor; + raw.bayersensor.pixelShiftExp0 = raw.bayersensor.pixelShiftExp0 && p.raw.bayersensor.pixelShiftExp0 == other.raw.bayersensor.pixelShiftExp0; + raw.bayersensor.pixelShiftLmmse = raw.bayersensor.pixelShiftLmmse && p.raw.bayersensor.pixelShiftLmmse == other.raw.bayersensor.pixelShiftLmmse; + raw.bayersensor.pixelShiftEqualBright = raw.bayersensor.pixelShiftEqualBright && p.raw.bayersensor.pixelShiftEqualBright == other.raw.bayersensor.pixelShiftEqualBright; + raw.bayersensor.pixelShiftNonGreenCross = raw.bayersensor.pixelShiftNonGreenCross && p.raw.bayersensor.pixelShiftNonGreenCross == other.raw.bayersensor.pixelShiftNonGreenCross; + raw.bayersensor.pixelShiftNonGreenCross2 = raw.bayersensor.pixelShiftNonGreenCross2 && p.raw.bayersensor.pixelShiftNonGreenCross2 == other.raw.bayersensor.pixelShiftNonGreenCross2; + raw.bayersensor.pixelShiftNonGreenAmaze = raw.bayersensor.pixelShiftNonGreenAmaze && p.raw.bayersensor.pixelShiftNonGreenAmaze == other.raw.bayersensor.pixelShiftNonGreenAmaze; raw.bayersensor.greenEq = raw.bayersensor.greenEq && p.raw.bayersensor.greenthresh == other.raw.bayersensor.greenthresh; raw.bayersensor.linenoise = raw.bayersensor.linenoise && p.raw.bayersensor.linenoise == other.raw.bayersensor.linenoise; raw.xtranssensor.method = raw.xtranssensor.method && p.raw.xtranssensor.method == other.raw.xtranssensor.method; @@ -1587,6 +1649,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.wb.equal = dontforceSet && options.baBehav[ADDSET_WB_EQUAL] ? toEdit.wb.equal + mods.wb.equal : mods.wb.equal; } + if (wb.tempBias) { + toEdit.wb.tempBias = dontforceSet && options.baBehav[ADDSET_WB_TEMPBIAS] ? toEdit.wb.tempBias + mods.wb.tempBias : mods.wb.tempBias; + } + if (wb.green) { toEdit.wb.green = dontforceSet && options.baBehav[ADDSET_WB_GREEN] ? toEdit.wb.green + mods.wb.green : mods.wb.green; } @@ -2236,6 +2302,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.raw.bayersensor.method = mods.raw.bayersensor.method; } + if (raw.bayersensor.imageNum) { + toEdit.raw.bayersensor.imageNum = mods.raw.bayersensor.imageNum; + } + if (raw.bayersensor.ccSteps) { toEdit.raw.bayersensor.ccSteps = mods.raw.bayersensor.ccSteps; } @@ -2272,7 +2342,122 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.raw.bayersensor.lmmse_iterations = mods.raw.bayersensor.lmmse_iterations; } - //if (raw.bayersensor.allEnhance) toEdit.raw.bayersensor.all_enhance = mods.raw.bayersensor.all_enhance; + if (raw.bayersensor.pixelShiftMotion) { + toEdit.raw.bayersensor.pixelShiftMotion = mods.raw.bayersensor.pixelShiftMotion; + } + + if (raw.bayersensor.pixelShiftMotionCorrection) { + toEdit.raw.bayersensor.pixelShiftMotionCorrection = mods.raw.bayersensor.pixelShiftMotionCorrection; + } + + if (raw.bayersensor.pixelShiftMotionCorrectionMethod) { + toEdit.raw.bayersensor.pixelShiftMotionCorrectionMethod = mods.raw.bayersensor.pixelShiftMotionCorrectionMethod; + } + + if (raw.bayersensor.pixelShiftStddevFactorGreen) { + toEdit.raw.bayersensor.pixelShiftStddevFactorGreen = mods.raw.bayersensor.pixelShiftStddevFactorGreen; + } + + if (raw.bayersensor.pixelShiftStddevFactorRed) { + toEdit.raw.bayersensor.pixelShiftStddevFactorRed = mods.raw.bayersensor.pixelShiftStddevFactorRed; + } + + if (raw.bayersensor.pixelShiftStddevFactorBlue) { + toEdit.raw.bayersensor.pixelShiftStddevFactorBlue = mods.raw.bayersensor.pixelShiftStddevFactorBlue; + } + + if (raw.bayersensor.pixelShiftEperIso) { + toEdit.raw.bayersensor.pixelShiftEperIso = mods.raw.bayersensor.pixelShiftEperIso; + } + + if (raw.bayersensor.pixelShiftNreadIso) { + toEdit.raw.bayersensor.pixelShiftNreadIso = mods.raw.bayersensor.pixelShiftNreadIso; + } + + if (raw.bayersensor.pixelShiftPrnu) { + toEdit.raw.bayersensor.pixelShiftPrnu = mods.raw.bayersensor.pixelShiftPrnu; + } + + if (raw.bayersensor.pixelShiftSigma) { + toEdit.raw.bayersensor.pixelShiftSigma = mods.raw.bayersensor.pixelShiftSigma; + } + + if (raw.bayersensor.pixelShiftSum) { + toEdit.raw.bayersensor.pixelShiftSum = mods.raw.bayersensor.pixelShiftSum; + } + + if (raw.bayersensor.pixelShiftRedBlueWeight) { + toEdit.raw.bayersensor.pixelShiftRedBlueWeight = mods.raw.bayersensor.pixelShiftRedBlueWeight; + } + + if (raw.bayersensor.pixelshiftShowMotion) { + toEdit.raw.bayersensor.pixelshiftShowMotion = mods.raw.bayersensor.pixelshiftShowMotion; + } + + if (raw.bayersensor.pixelshiftShowMotionMaskOnly) { + toEdit.raw.bayersensor.pixelshiftShowMotionMaskOnly = mods.raw.bayersensor.pixelshiftShowMotionMaskOnly; + } + + if (raw.bayersensor.pixelShiftAutomatic) { + toEdit.raw.bayersensor.pixelShiftAutomatic = mods.raw.bayersensor.pixelShiftAutomatic; + } + + if (raw.bayersensor.pixelShiftNonGreenHorizontal) { + toEdit.raw.bayersensor.pixelShiftNonGreenHorizontal = mods.raw.bayersensor.pixelShiftNonGreenHorizontal; + } + + if (raw.bayersensor.pixelShiftNonGreenVertical) { + toEdit.raw.bayersensor.pixelShiftNonGreenVertical = mods.raw.bayersensor.pixelShiftNonGreenVertical; + } + + if (raw.bayersensor.pixelShiftHoleFill) { + toEdit.raw.bayersensor.pixelShiftHoleFill = mods.raw.bayersensor.pixelShiftHoleFill; + } + + if (raw.bayersensor.pixelShiftMedian) { + toEdit.raw.bayersensor.pixelShiftMedian = mods.raw.bayersensor.pixelShiftMedian; + } + + if (raw.bayersensor.pixelShiftMedian3) { + toEdit.raw.bayersensor.pixelShiftMedian3 = mods.raw.bayersensor.pixelShiftMedian3; + } + + if (raw.bayersensor.pixelShiftGreen) { + toEdit.raw.bayersensor.pixelShiftGreen = mods.raw.bayersensor.pixelShiftGreen; + } + + if (raw.bayersensor.pixelShiftBlur) { + toEdit.raw.bayersensor.pixelShiftBlur = mods.raw.bayersensor.pixelShiftBlur; + } + + if (raw.bayersensor.pixelShiftSmooth) { + toEdit.raw.bayersensor.pixelShiftSmoothFactor = mods.raw.bayersensor.pixelShiftSmoothFactor; + } + + if (raw.bayersensor.pixelShiftExp0) { + toEdit.raw.bayersensor.pixelShiftExp0 = mods.raw.bayersensor.pixelShiftExp0; + } + + if (raw.bayersensor.pixelShiftLmmse) { + toEdit.raw.bayersensor.pixelShiftLmmse = mods.raw.bayersensor.pixelShiftLmmse; + } + + if (raw.bayersensor.pixelShiftEqualBright) { + toEdit.raw.bayersensor.pixelShiftEqualBright = mods.raw.bayersensor.pixelShiftEqualBright; + } + + if (raw.bayersensor.pixelShiftNonGreenCross) { + toEdit.raw.bayersensor.pixelShiftNonGreenCross = mods.raw.bayersensor.pixelShiftNonGreenCross; + } + + if (raw.bayersensor.pixelShiftNonGreenCross2) { + toEdit.raw.bayersensor.pixelShiftNonGreenCross2 = mods.raw.bayersensor.pixelShiftNonGreenCross2; + } + + if (raw.bayersensor.pixelShiftNonGreenAmaze) { + toEdit.raw.bayersensor.pixelShiftNonGreenAmaze = mods.raw.bayersensor.pixelShiftNonGreenAmaze; + } + if (raw.bayersensor.greenEq) { toEdit.raw.bayersensor.greenthresh = dontforceSet && options.baBehav[ADDSET_PREPROCESS_GREENEQUIL] ? toEdit.raw.bayersensor.greenthresh + mods.raw.bayersensor.greenthresh : mods.raw.bayersensor.greenthresh; } @@ -2782,7 +2967,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten bool RAWParamsEdited::BayerSensor::isUnchanged() const { - return method && dcbIterations && dcbEnhance && lmmseIterations/*&& allEnhance*/ && greenEq + return method && imageNum && dcbIterations && dcbEnhance && lmmseIterations/*&& allEnhance*/ && greenEq + && pixelShiftMotion && pixelShiftMotionCorrection && pixelShiftMotionCorrectionMethod && pixelShiftStddevFactorGreen && pixelShiftStddevFactorRed && pixelShiftStddevFactorBlue && pixelShiftEperIso + && pixelShiftNreadIso && pixelShiftPrnu && pixelShiftSigma && pixelShiftSum && pixelShiftRedBlueWeight && pixelshiftShowMotion && pixelshiftShowMotionMaskOnly + && pixelShiftAutomatic && pixelShiftNonGreenHorizontal && pixelShiftNonGreenVertical && pixelShiftHoleFill && pixelShiftMedian && pixelShiftMedian3 && pixelShiftNonGreenCross && pixelShiftNonGreenCross2 && pixelShiftNonGreenAmaze && pixelShiftGreen && pixelShiftBlur && pixelShiftSmooth && pixelShiftExp0 && pixelShiftLmmse && pixelShiftEqualBright && linenoise && exBlack0 && exBlack1 && exBlack2 && exBlack3 && exTwoGreen; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 38f26658a..fc69a1e48 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -234,6 +234,7 @@ public: bool temperature; bool green; bool equal; + bool tempBias; }; /*class ColorShiftParamsEdited { @@ -681,6 +682,7 @@ public: public: bool method; + bool imageNum; bool ccSteps; bool exBlack0; bool exBlack1; @@ -690,6 +692,36 @@ public: bool dcbIterations; bool dcbEnhance; bool lmmseIterations; + bool pixelShiftMotion; + bool pixelShiftMotionCorrection; + bool pixelShiftMotionCorrectionMethod; + bool pixelShiftStddevFactorGreen; + bool pixelShiftStddevFactorRed; + bool pixelShiftStddevFactorBlue; + bool pixelShiftEperIso; + bool pixelShiftNreadIso; + bool pixelShiftPrnu; + bool pixelShiftSigma; + bool pixelShiftSum; + bool pixelShiftRedBlueWeight; + bool pixelshiftShowMotion; + bool pixelshiftShowMotionMaskOnly; + bool pixelShiftAutomatic; + bool pixelShiftNonGreenHorizontal; + bool pixelShiftNonGreenVertical; + bool pixelShiftHoleFill; + bool pixelShiftMedian; + bool pixelShiftMedian3; + bool pixelShiftGreen; + bool pixelShiftBlur; + bool pixelShiftSmooth; + bool pixelShiftExp0; + bool pixelShiftLmmse; + bool pixelShiftEqualBright; + bool pixelShiftNonGreenCross; + bool pixelShiftNonGreenCross2; + bool pixelShiftNonGreenAmaze; + //bool allEnhance; bool greenEq; bool linenoise; diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index c0cc2c87c..7cf7de15e 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -111,6 +111,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren raw_linenoise = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PREPROCESS_LINEDENOISE"))); raw_greenthresh = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PREPROCESS_GREENEQUIL"))); raw_method = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_DMETHOD"))); + raw_imagenum = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_IMAGENUM"))); raw_ccSteps = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_FALSECOLOR"))); raw_dcb_iterations = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_DCBITERATIONS"))); raw_dcb_enhance = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_DCBENHANCE"))); @@ -200,6 +201,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren vboxes[6]->pack_start (*raw, Gtk::PACK_SHRINK, 2); vboxes[6]->pack_start (*hseps[6], Gtk::PACK_SHRINK, 2); vboxes[6]->pack_start (*raw_method, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_imagenum, Gtk::PACK_SHRINK, 2); vboxes[6]->pack_start (*raw_ccSteps, Gtk::PACK_SHRINK, 2); vboxes[6]->pack_start (*raw_dcb_iterations, Gtk::PACK_SHRINK, 2); vboxes[6]->pack_start (*raw_dcb_enhance, Gtk::PACK_SHRINK, 2); @@ -338,7 +340,8 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren exifchConn = exifch->signal_toggled().connect (sigc::bind (sigc::mem_fun(*meta, &Gtk::CheckButton::set_inconsistent), true)); iptcConn = iptc->signal_toggled().connect (sigc::bind (sigc::mem_fun(*meta, &Gtk::CheckButton::set_inconsistent), true)); - raw_methodConn = raw_method->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); + raw_methodConn = raw_method->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); + raw_imagenumConn = raw_imagenum->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); raw_ccStepsConn = raw_ccSteps->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); raw_dcb_iterationsConn = raw_dcb_iterations->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); raw_dcb_enhanceConn = raw_dcb_enhance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); @@ -418,6 +421,7 @@ void PartialPasteDlg::rawToggled () { raw_methodConn.block (true); + raw_imagenumConn.block (true); raw_ccStepsConn.block (true); raw_dcb_iterationsConn.block (true); raw_dcb_enhanceConn.block (true); @@ -444,6 +448,7 @@ void PartialPasteDlg::rawToggled () raw->set_inconsistent (false); raw_method->set_active (raw->get_active ()); + raw_imagenum->set_active (raw->get_active ()); raw_ccSteps->set_active (raw->get_active ()); raw_dcb_iterations->set_active (raw->get_active ()); raw_dcb_enhance->set_active (raw->get_active ()); @@ -468,6 +473,7 @@ void PartialPasteDlg::rawToggled () ff_ClipControl->set_active (raw->get_active ()); raw_methodConn.block (false); + raw_imagenumConn.block (false); raw_ccStepsConn.block (false); raw_dcb_iterationsConn.block (false); raw_dcb_enhanceConn.block (false); @@ -847,6 +853,10 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param filterPE.raw.xtranssensor.method = falsePE.raw.xtranssensor.method; } + if (!raw_imagenum->get_active ()) { + filterPE.raw.bayersensor.imageNum = falsePE.raw.bayersensor.imageNum; + } + if (!raw_ccSteps->get_active ()) { filterPE.raw.bayersensor.ccSteps = falsePE.raw.bayersensor.ccSteps; filterPE.raw.xtranssensor.ccSteps = falsePE.raw.xtranssensor.ccSteps; diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h index 99249eefd..177b0b720 100644 --- a/rtgui/partialpastedlg.h +++ b/rtgui/partialpastedlg.h @@ -107,6 +107,7 @@ public: Gtk::CheckButton* raw_linenoise; Gtk::CheckButton* raw_greenthresh; Gtk::CheckButton* raw_method; + Gtk::CheckButton* raw_imagenum; Gtk::CheckButton* raw_ccSteps; Gtk::CheckButton* raw_dcb_iterations; Gtk::CheckButton* raw_dcb_enhance; @@ -129,7 +130,7 @@ public: sigc::connection coarserotConn, finerotConn, cropConn, resizeConn, prsharpeningConn, perspectiveConn, commonTransConn; sigc::connection exifchConn, iptcConn, icmConn; sigc::connection df_fileConn, df_AutoSelectConn, ff_fileConn, ff_AutoSelectConn, ff_BlurRadiusConn, ff_BlurTypeConn, ff_ClipControlConn; - sigc::connection raw_caredConn, raw_cablueConn, raw_ca_autocorrectConn, raw_hotpix_filtConn, raw_deadpix_filtConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_methodConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_dcb_enhanceConn, raw_exposConn, raw_preserConn, raw_blackConn; + sigc::connection raw_caredConn, raw_cablueConn, raw_ca_autocorrectConn, raw_hotpix_filtConn, raw_deadpix_filtConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_methodConn, raw_imagenumConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_dcb_enhanceConn, raw_exposConn, raw_preserConn, raw_blackConn; public: PartialPasteDlg (const Glib::ustring &title, Gtk::Window* parent); diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index bcd8540fc..8130e2dfc 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -42,6 +42,8 @@ Preferences::Preferences (RTWindow *rtwindow) , rprofiles (nullptr) , iprofiles (nullptr) , parent (rtwindow) + , newFont (false) + , newCPFont (false) { regex = Glib::Regex::create(THEMEREGEXSTR, Glib::RegexCompileFlags::REGEX_CASELESS); @@ -57,6 +59,10 @@ Preferences::Preferences (RTWindow *rtwindow) set_size_request (650, -1); set_default_size (options.preferencesWidth, options.preferencesHeight); + Pango::FontDescription defaultFont = get_style_context ()->get_font(); + initialFontFamily = defaultFont.get_family (); + initialFontSize = defaultFont.get_size () / Pango::SCALE; + Gtk::Box* mainBox = get_content_area (); //GTK318 #if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 20 @@ -83,6 +89,7 @@ Preferences::Preferences (RTWindow *rtwindow) nb->append_page (*getGeneralPanel(), M("PREFERENCES_TAB_GENERAL")); nb->append_page (*getProcParamsPanel(), M("PREFERENCES_TAB_IMPROC")); + nb->append_page (*getDynProfilePanel(), M("PREFERENCES_TAB_DYNAMICPROFILE")); nb->append_page (*getFileBrowserPanel(), M("PREFERENCES_TAB_BROWSER")); nb->append_page (*getColorManagementPanel(), M("PREFERENCES_TAB_COLORMGR")); nb->append_page (*getBatchProcPanel(), M("PREFERENCES_BATCH_PROCESSING")); @@ -232,6 +239,7 @@ Gtk::Widget* Preferences::getBatchProcPanel () appendBehavList (mi, M("TP_WBALANCE_TEMPERATURE"), ADDSET_WB_TEMPERATURE, true); appendBehavList (mi, M("TP_WBALANCE_GREEN"), ADDSET_WB_GREEN, true); appendBehavList (mi, M("TP_WBALANCE_EQBLUERED"), ADDSET_WB_EQUAL, true); + appendBehavList (mi, M("TP_WBALANCE_TEMPBIAS"), ADDSET_WB_TEMPBIAS, true); mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_COLORAPP_LABEL")); @@ -420,6 +428,14 @@ void Preferences::behSetRadioToggled (const Glib::ustring& path) iter->set_value (behavColumns.badd, false); } + +Gtk::Widget *Preferences::getDynProfilePanel() +{ + dynProfilePanel = Gtk::manage(new DynamicProfilePanel()); + return dynProfilePanel; +} + + Gtk::Widget* Preferences::getProcParamsPanel () { @@ -429,11 +445,13 @@ Gtk::Widget* Preferences::getProcParamsPanel () Gtk::VBox* vbpp = Gtk::manage (new Gtk::VBox ()); Gtk::Label* drlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_FORRAW") + ":", Gtk::ALIGN_START)); rprofiles = Gtk::manage (new ProfileStoreComboBox ()); + rprofiles->addRow(profileStore.getInternalDynamicPSE()); setExpandAlignProperties(rprofiles, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); rprofiles->set_size_request(50, -1); rpconn = rprofiles->signal_changed().connect( sigc::mem_fun(*this, &Preferences::forRAWComboChanged) ); Gtk::Label* drimg = Gtk::manage (new Gtk::Label (M("PREFERENCES_FORIMAGE") + ":", Gtk::ALIGN_START)); iprofiles = Gtk::manage (new ProfileStoreComboBox ()); + iprofiles->addRow(profileStore.getInternalDynamicPSE()); iprofiles->set_size_request(50, -1); setExpandAlignProperties(iprofiles, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); ipconn = iprofiles->signal_changed().connect( sigc::mem_fun(*this, &Preferences::forImageComboChanged) ); @@ -1021,7 +1039,11 @@ Gtk::Widget* Preferences::getGeneralPanel () fontButton = Gtk::manage( new Gtk::FontButton ()); setExpandAlignProperties(fontButton, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); fontButton->set_use_size(true); - fontButton->set_font_name(Glib::ustring::compose("%1 %2", options.fontFamily == "default" ? "sans" : options.fontFamily, options.fontSize)); + if (options.fontFamily == "default") { + fontButton->set_font_name (Glib::ustring::compose("%1 %2", initialFontFamily, initialFontSize)); + } else { + fontButton->set_font_name (Glib::ustring::compose("%1 %2", options.fontFamily, options.fontSize)); + } themeGrid->attach_next_to(*fontlab, *theme, Gtk::POS_RIGHT, 1, 1); themeGrid->attach_next_to(*fontButton, *fontlab, Gtk::POS_RIGHT, 1, 1); @@ -1031,7 +1053,11 @@ Gtk::Widget* Preferences::getGeneralPanel () colorPickerFontButton = Gtk::manage( new Gtk::FontButton ()); setExpandAlignProperties(fontButton, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); colorPickerFontButton->set_use_size(true); - colorPickerFontButton->set_font_name(Glib::ustring::compose("%1 %2", options.CPFontFamily == "default" ? "sans" : options.CPFontFamily, options.CPFontSize)); + if (options.fontFamily == "default") { + colorPickerFontButton->set_font_name (Glib::ustring::compose("%1 %2", initialFontFamily, initialFontSize)); + } else { + colorPickerFontButton->set_font_name (Glib::ustring::compose("%1 %2", options.CPFontFamily, options.CPFontSize)); + } themeGrid->attach_next_to(*cpfontlab, *fontButton, Gtk::POS_RIGHT, 1, 1); themeGrid->attach_next_to(*colorPickerFontButton, *cpfontlab, Gtk::POS_RIGHT, 1, 1); @@ -1182,6 +1208,7 @@ Gtk::Widget* Preferences::getGeneralPanel () langAutoDetectConn = ckbLangAutoDetect->signal_toggled().connect (sigc::mem_fun(*this, &Preferences::langAutoDetectToggled)); tconn = theme->signal_changed().connect( sigc::mem_fun(*this, &Preferences::themeChanged) ); fconn = fontButton->signal_font_set().connect( sigc::mem_fun(*this, &Preferences::fontChanged) ); + cpfconn = colorPickerFontButton->signal_font_set().connect( sigc::mem_fun(*this, &Preferences::cpFontChanged) ); return mvbsd; } @@ -1571,12 +1598,16 @@ void Preferences::storePreferences () moptions.navGuideBrush[3] = butNavGuideCol->get_alpha() / 65535.0; Pango::FontDescription fd(fontButton->get_font_name()); - moptions.fontFamily = fd.get_family(); - moptions.fontSize = fd.get_size() / Pango::SCALE; + if (newFont) { + moptions.fontFamily = fd.get_family(); + moptions.fontSize = fd.get_size() / Pango::SCALE; + } Pango::FontDescription cpfd(colorPickerFontButton->get_font_name()); - moptions.CPFontFamily = cpfd.get_family(); - moptions.CPFontSize = cpfd.get_size() / Pango::SCALE; + if (newCPFont) { + moptions.CPFontFamily = cpfd.get_family(); + moptions.CPFontSize = cpfd.get_size() / Pango::SCALE; + } #ifdef WIN32 moptions.gimpDir = gimpDir->get_filename (); @@ -1747,6 +1778,7 @@ void Preferences::fillPreferences () tconn.block (true); fconn.block (true); + cpfconn.block (true); sconn.block (true); dfconn.block (true); ffconn.block (true); @@ -1832,8 +1864,17 @@ void Preferences::fillPreferences () butNavGuideCol->set_rgba(NavGuideCol); butNavGuideCol->set_alpha ( (unsigned short)(moptions.navGuideBrush[3] * 65535.0)); - fontButton->set_font_name(Glib::ustring::compose("%1 %2", options.fontFamily == "default" ? "sans" : options.fontFamily, options.fontSize)); - colorPickerFontButton->set_font_name(Glib::ustring::compose("%1 %2", options.CPFontFamily == "default" ? "sans" : options.CPFontFamily, options.CPFontSize)); + if (options.fontFamily == "default") { + fontButton->set_font_name (Glib::ustring::compose("%1 %2", initialFontFamily, initialFontSize)); + } else { + fontButton->set_font_name (Glib::ustring::compose("%1 %2", options.fontFamily, options.fontSize)); + } + + if (options.CPFontFamily == "default") { + colorPickerFontButton->set_font_name (Glib::ustring::compose("%1 %2", initialFontFamily, initialFontSize)); + } else { + colorPickerFontButton->set_font_name (Glib::ustring::compose("%1 %2", options.CPFontFamily, options.CPFontSize)); + } showDateTime->set_active (moptions.fbShowDateTime); showBasicExif->set_active (moptions.fbShowBasicExif); @@ -1855,13 +1896,13 @@ void Preferences::fillPreferences () if (Glib::file_test (moptions.gimpDir, Glib::FILE_TEST_IS_DIR)) { gimpDir->set_current_folder (moptions.gimpDir); } else { - gimpDir->set_current_folder (""); + gimpDir->set_current_folder (Glib::get_home_dir()); } if (Glib::file_test (moptions.psDir, Glib::FILE_TEST_IS_DIR)) { psDir->set_current_folder (moptions.psDir); } else { - psDir->set_current_folder (""); + psDir->set_current_folder (Glib::get_home_dir()); } #elif defined __APPLE__ @@ -1869,6 +1910,8 @@ void Preferences::fillPreferences () if (Glib::file_test (moptions.psDir, Glib::FILE_TEST_IS_DIR)) { psDir->set_current_folder (moptions.psDir); + } else { + psDir->set_current_folder (Glib::get_home_dir()); } #endif @@ -1954,6 +1997,7 @@ void Preferences::fillPreferences () addc.block (false); setc.block (false); + cpfconn.block (false); fconn.block (false); tconn.block (false); sconn.block (false); @@ -2020,6 +2064,7 @@ void Preferences::okPressed () options.copyFrom (&moptions); options.filterOutParsedExtensions(); Options::save (); + dynProfilePanel->save(); hide (); } @@ -2035,7 +2080,11 @@ void Preferences::cancelPressed () // set the initial font back Pango::FontDescription fd(fontButton->get_font_name()); if (fd.get_family() != options.fontFamily && (fd.get_size() / Pango::SCALE) != options.fontSize) { - switchFontTo(options.fontFamily == "default" ? "sans" : options.fontFamily, options.fontSize); + if (options.fontFamily == "default") { + switchFontTo(initialFontFamily, initialFontSize); + } else { + switchFontTo(options.fontFamily, options.fontSize); + } } // update the profileStore @@ -2181,6 +2230,8 @@ void Preferences::updateProfileList() { rprofiles->updateProfileList(); iprofiles->updateProfileList(); + rprofiles->addRow(profileStore.getInternalDynamicPSE()); + iprofiles->addRow(profileStore.getInternalDynamicPSE()); } void Preferences::restoreValue() @@ -2230,10 +2281,17 @@ void Preferences::switchThemeTo(Glib::ustring newTheme) void Preferences::fontChanged () { + newFont = true; Pango::FontDescription fd(fontButton->get_font_name()); switchFontTo(fd.get_family(), fd.get_size() / Pango::SCALE); } +void Preferences::cpFontChanged () +{ + + newCPFont = true; +} + void Preferences::switchFontTo(const Glib::ustring &newFontFamily, const int newFontSize) { @@ -2258,6 +2316,13 @@ void Preferences::switchFontTo(const Glib::ustring &newFontFamily, const int new printf("Error: Can't find the font named \"%s\"\n", newFontFamily.c_str()); } } + else { + if (fontcss) { + fontcss = Gtk::CssProvider::create(); + Glib::RefPtr screen = Gdk::Screen::get_default(); + Gtk::StyleContext::remove_provider_for_screen(screen, fontcss); + } + } } void Preferences::workflowUpdate () diff --git a/rtgui/preferences.h b/rtgui/preferences.h index 91951a2df..18c8a466b 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -24,6 +24,7 @@ #include "options.h" #include #include "rtwindow.h" +#include "dynamicprofilepanel.h" class Preferences : public Gtk::Dialog, public ProfileStoreListener { @@ -201,14 +202,19 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener Gtk::CheckButton* ckbHideTPVScrollbar; Gtk::CheckButton* ckbUseIconNoText; + DynamicProfilePanel *dynProfilePanel; + Glib::ustring storedValueRaw; Glib::ustring storedValueImg; Options moptions; - sigc::connection tconn, sconn, fconn, addc, setc, dfconn, ffconn, bpconn, rpconn, ipconn; + sigc::connection tconn, sconn, fconn, cpfconn, addc, setc, dfconn, ffconn, bpconn, rpconn, ipconn; sigc::connection autoMonProfileConn, sndEnableConn, langAutoDetectConn, autocielabConn; Glib::ustring initialTheme; - Glib::ustring initialFont; + Glib::ustring initialFontFamily; + int initialFontSize; + bool newFont; + bool newCPFont; void fillPreferences (); void storePreferences (); @@ -219,6 +225,7 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener void workflowUpdate(); void themeChanged (); void fontChanged (); + void cpFontChanged (); void forRAWComboChanged (); void forImageComboChanged (); void layoutComboChanged (); @@ -239,6 +246,7 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener Gtk::Widget* getBatchProcPanel (); Gtk::Widget* getPerformancePanel (); Gtk::Widget* getSoundPanel (); + Gtk::Widget* getDynProfilePanel (); public: explicit Preferences (RTWindow *rtwindow); diff --git a/rtgui/profilestore.cc b/rtgui/profilestore.cc index 6b1171d23..d7bf18ab5 100644 --- a/rtgui/profilestore.cc +++ b/rtgui/profilestore.cc @@ -20,13 +20,14 @@ #include "options.h" #include "toolpanel.h" #include "guiutils.h" +#include "dynamicprofile.h" ProfileStore profileStore; using namespace rtengine; using namespace rtengine::procparams; -ProfileStore::ProfileStore () : parseMutex(nullptr), storeState(STORESTATE_NOTINITIALIZED), internalDefaultProfile(nullptr), internalDefaultEntry(nullptr) +ProfileStore::ProfileStore () : parseMutex(nullptr), storeState(STORESTATE_NOTINITIALIZED), internalDefaultProfile(nullptr), internalDefaultEntry(nullptr), internalDynamicEntry(nullptr), dynamicRules(new std::vector()) { internalDefaultProfile = new AutoPartialProfile(); internalDefaultProfile->set(true); @@ -42,6 +43,7 @@ bool ProfileStore::init () storeState = STORESTATE_BEINGINITIALIZED; parseMutex = new MyMutex(); _parseProfiles (); + loadDynamicProfileRules(*dynamicRules); storeState = STORESTATE_INITIALIZED; } @@ -63,6 +65,8 @@ ProfileStore::~ProfileStore () partProfiles.clear (); clearFileList(); delete internalDefaultProfile; + delete internalDefaultEntry; + delete internalDynamicEntry; lock.release(); delete parseMutex; parseMutex = nullptr; @@ -140,6 +144,10 @@ void ProfileStore::_parseProfiles () entries.push_back(internalDefaultEntry); partProfiles[internalDefaultEntry] = internalDefaultProfile; + if (!internalDynamicEntry) { + internalDynamicEntry = new ProfileStoreEntry(Glib::ustring("(") + M("PROFILEPANEL_PDYNAMIC") + Glib::ustring(")"), PSET_FILE, 0, 0); + // do not add it to the entries. This is here only for the preferences dialog + } // Check if the default profiles has been found. if (findEntryFromFullPathU(options.defProfRaw) == nullptr) { @@ -273,7 +281,7 @@ const ProfileStoreEntry* ProfileStore::findEntryFromFullPathU(Glib::ustring path return nullptr; } - if (path == DEFPROFILE_INTERNAL) { + if (path == DEFPROFILE_INTERNAL || path == DEFPROFILE_DYNAMIC) { return internalDefaultEntry; } @@ -499,6 +507,20 @@ void ProfileStore::dumpFolderList() printf("\n"); } + +const std::vector &ProfileStore::getDynamicProfileRules() const +{ + return *dynamicRules; +} + + +void ProfileStore::setDynamicProfileRules(const std::vector &r) +{ + *dynamicRules = r; +} + + + ProfileStoreEntry::ProfileStoreEntry() : label(""), type(PSET_FOLDER), parentFolderId(0), folderId(0) {} ProfileStoreEntry::ProfileStoreEntry(Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder) : label(label), type(type), parentFolderId(parentFolder), folderId(folder) {} @@ -570,12 +592,12 @@ void ProfileStoreComboBox::refreshProfileList_ (Gtk::TreeModel::Row *parentRow, // creating and assigning the custom Label object newSubMenu[methodColumns.label] = entry->label; newSubMenu[methodColumns.profileStoreEntry] = entry; - +#if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION == 18 // HACK: Workaround for bug in Gtk+ 3.18... Gtk::TreeModel::Row menuHeader = *(refTreeModel->append(newSubMenu->children())); - menuHeader[methodColumns.label] = entry->label; + menuHeader[methodColumns.label] = "-"; menuHeader[methodColumns.profileStoreEntry] = entry; - +#endif refreshProfileList_ (&newSubMenu, entry->folderId, false, entryList); } else { refreshProfileList_ (parentRow, entry->folderId, true, entryList); @@ -603,7 +625,6 @@ void ProfileStoreComboBox::refreshProfileList_ (Gtk::TreeModel::Row *parentRow, */ void ProfileStoreComboBox::updateProfileList () { - // clear items clear(); refTreeModel.clear(); @@ -710,6 +731,11 @@ Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath (Glib::ustring path) return row; } + if (path == DEFPROFILE_DYNAMIC) { + row = findRowFromEntry(profileStore.getInternalDynamicPSE()); + return row; + } + // removing the filename Glib::ustring fName = Glib::path_get_basename(path); @@ -758,6 +784,10 @@ Glib::ustring ProfileStoreComboBox::getFullPathFromActiveRow() return Glib::ustring(DEFPROFILE_INTERNAL); } + if (currEntry == profileStore.getInternalDynamicPSE()) { + return Glib::ustring(DEFPROFILE_DYNAMIC); + } + path = Glib::build_filename(profileStore.getPathFromId(currEntry->parentFolderId), currEntry->label); } diff --git a/rtgui/profilestore.h b/rtgui/profilestore.h index ab45a0867..ad569c180 100644 --- a/rtgui/profilestore.h +++ b/rtgui/profilestore.h @@ -31,6 +31,9 @@ #include "guiutils.h" +// forward decl +class DynamicProfileRule; + /** @brief This will implement callback functions for the ProfileStore * */ @@ -144,6 +147,7 @@ private: StoreState storeState; rtengine::procparams::AutoPartialProfile *internalDefaultProfile; ProfileStoreEntry *internalDefaultEntry; + ProfileStoreEntry *internalDynamicEntry; /** Alphabetically ordered list of folder and files through Gtk::Label sub-class; * ready to be used in Menu and Combobox @@ -160,6 +164,9 @@ private: /** List of the client of this store */ std::list listeners; + /** cache for dynamic profile rules */ + std::unique_ptr> dynamicRules; + /** @brief Method to recursively parse a profile folder with a level depth arbitrarily limited to 3 * * @param realPath current full path of the scanned directory ; e.g.: ~/MyProfiles/ @@ -198,6 +205,14 @@ public: return internalDefaultEntry; } + const ProfileStoreEntry* getInternalDynamicPSE() + { + return internalDynamicEntry; + } + + const std::vector &getDynamicProfileRules() const; + void setDynamicProfileRules(const std::vector &r); + void addListener(ProfileStoreListener *listener); void removeListener(ProfileStoreListener *listener); diff --git a/rtgui/rawcacorrection.cc b/rtgui/rawcacorrection.cc index d619ab112..683dcc97f 100644 --- a/rtgui/rawcacorrection.cc +++ b/rtgui/rawcacorrection.cc @@ -18,7 +18,6 @@ */ #include "rawcacorrection.h" #include "guiutils.h" -#include #include "rtimage.h" using namespace rtengine; @@ -31,7 +30,8 @@ RAWCACorr::RAWCACorr () : FoldableToolPanel(this, "rawcacorrection", M("TP_CHROM Gtk::Image* icablueL = Gtk::manage (new RTImage ("ajd-ca-blue1.png")); Gtk::Image* icablueR = Gtk::manage (new RTImage ("ajd-ca-blue2.png")); - caAutocorrect = Gtk::manage(new Gtk::CheckButton((M("TP_RAWCACORR_AUTO")))); + caAutocorrect = Gtk::manage (new CheckBox(M("TP_RAWCACORR_AUTO"), multiImage)); + caAutocorrect->setCheckBoxListener (this); caStrength = Gtk::manage(new Adjuster (M("TP_RAWCACORR_CASTR"), 2.0, 8.0, 0.5, 6.0)); caStrength->setAdjusterListener (this); @@ -62,40 +62,35 @@ RAWCACorr::RAWCACorr () : FoldableToolPanel(this, "rawcacorrection", M("TP_CHROM pack_start( *caRed, Gtk::PACK_SHRINK, 4); pack_start( *caBlue, Gtk::PACK_SHRINK, 4); - caacsconn = caAutocorrect->signal_toggled().connect ( sigc::mem_fun(*this, &RAWCACorr::caCorrectionChanged), true); } void RAWCACorr::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { disableListener (); - caacsconn.block (true); if(pedited ) { - caAutocorrect->set_inconsistent(!pedited->raw.caCorrection); + caAutocorrect->setEdited(pedited->raw.caCorrection); caStrength->setEditedState( pedited->raw.caAutoStrength ? Edited : UnEdited ); caRed->setEditedState( pedited->raw.caRed ? Edited : UnEdited ); caBlue->setEditedState( pedited->raw.caBlue ? Edited : UnEdited ); } - lastCA = pp->raw.ca_autocorrect; - caStrength->set_sensitive(pp->raw.ca_autocorrect); // disable Red and Blue sliders when caAutocorrect is enabled caRed->set_sensitive(!pp->raw.ca_autocorrect); caBlue->set_sensitive(!pp->raw.ca_autocorrect); - caAutocorrect->set_active(pp->raw.ca_autocorrect); + caAutocorrect->setValue(pp->raw.ca_autocorrect); caStrength->setValue (pp->raw.caautostrength); caRed->setValue (pp->raw.cared); caBlue->setValue (pp->raw.cablue); - caacsconn.block (false); enableListener (); } void RAWCACorr::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->raw.ca_autocorrect = caAutocorrect->get_active(); + pp->raw.ca_autocorrect = caAutocorrect->getLastActive(); pp->raw.caautostrength = caStrength->getValue(); pp->raw.cared = caRed->getValue(); pp->raw.cablue = caBlue->getValue(); @@ -125,6 +120,21 @@ void RAWCACorr::adjusterChanged (Adjuster* a, double newval) } } +void RAWCACorr::checkBoxToggled (CheckBox* c, CheckValue newval) +{ + if (c == caAutocorrect) { + if (!batchMode) { + caStrength->set_sensitive(caAutocorrect->getLastActive ()); + // disable Red and Blue sliders when caAutocorrect is enabled + caRed->set_sensitive(!caAutocorrect->getLastActive ()); + caBlue->set_sensitive(!caAutocorrect->getLastActive ()); + } + if (listener) { + listener->panelChanged (EvPreProcessAutoCA, caAutocorrect->getLastActive() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } + } +} + void RAWCACorr::setBatchMode(bool batchMode) { ToolPanel::setBatchMode (batchMode); @@ -150,52 +160,6 @@ void RAWCACorr::setDefaults(const rtengine::procparams::ProcParams* defParams, c } } -void RAWCACorr::caCorrectionChanged() -{ - if (batchMode) { - if (caAutocorrect->get_inconsistent()) { - caAutocorrect->set_inconsistent (false); - caacsconn.block (true); - caAutocorrect->set_active (false); - caacsconn.block (false); - } else if (lastCA) { - caAutocorrect->set_inconsistent (true); - } - - lastCA = caAutocorrect->get_active (); - - } - - /*else { - // For non batch mode, we disable the red and blue slider if caAutocorrect is true - if (caAutocorrect->get_active ()) { - caRed->set_sensitive(false); - caBlue->set_sensitive(false); - } - else { - caRed->set_sensitive(true); - caBlue->set_sensitive(true); - } - }*/ - - caStrength->set_sensitive(caAutocorrect->get_active ()); - // disable Red and Blue sliders when caAutocorrect is enabled - caRed->set_sensitive(!caAutocorrect->get_active ()); - caBlue->set_sensitive(!caAutocorrect->get_active ()); - - if (caAutocorrect->get_active ()) { - // set caRed and caBlue to 0 as RawImageSource::CA_correct_RT uses this as - // a condition for auto-CA correction. Alternative would be to change - // RawImageSource::CA_correct_RT and pass it ca_autocorrect value - caRed->setValue(0); - caBlue->setValue(0); - } - - if (listener) { - listener->panelChanged (EvPreProcessAutoCA, caAutocorrect->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); - } -} - void RAWCACorr::setAdjusterBehavior (bool caadd) { diff --git a/rtgui/rawcacorrection.h b/rtgui/rawcacorrection.h index 4edf9f9f2..a1873b2ad 100644 --- a/rtgui/rawcacorrection.h +++ b/rtgui/rawcacorrection.h @@ -21,19 +21,17 @@ #include #include "adjuster.h" +#include "checkbox.h" #include "toolpanel.h" -#include "../rtengine/rawimage.h" -class RAWCACorr : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class RAWCACorr : public ToolParamBlock, public AdjusterListener, public CheckBoxListener, public FoldableToolPanel { protected: - Gtk::CheckButton* caAutocorrect; + CheckBox* caAutocorrect; Adjuster* caStrength; Adjuster* caRed; Adjuster* caBlue; - bool lastCA; - sigc::connection caacsconn; public: @@ -47,7 +45,7 @@ public: void trimValues (rtengine::procparams::ProcParams* pp); void adjusterChanged (Adjuster* a, double newval); - void caCorrectionChanged (); + void checkBoxToggled (CheckBox* c, CheckValue newval); }; #endif diff --git a/rtgui/saveasdlg.cc b/rtgui/saveasdlg.cc index 9ca26d217..865373b60 100644 --- a/rtgui/saveasdlg.cc +++ b/rtgui/saveasdlg.cc @@ -21,6 +21,8 @@ #include "guiutils.h" #include "rtimage.h" +#include "../rtengine/utils.h" + extern Options options; SaveAsDialog::SaveAsDialog (const Glib::ustring &initialDir, Gtk::Window* parent) @@ -217,41 +219,57 @@ SaveFormat SaveAsDialog::getFormat () void SaveAsDialog::okPressed () { - fname = fchooser->get_filename(); - // checking if the filename field is empty. The user have to click Cancel if he don't want to specify a filename // NB: There seem to be a bug in Gtkmm2.22 / FileChooserWidget : if you suppress the filename entry and // click on a folder in the list, the filename field is empty but get_filename will return the folder's path :/ - if (!fname.length() || Glib::file_test (fname, Glib::FILE_TEST_IS_DIR)) { - Glib::ustring msg_ = Glib::ustring("") + M("MAIN_MSG_EMPTYFILENAME") + ""; - Gtk::MessageDialog msgd (*this, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true); - msgd.run (); + if (Glib::file_test(fname, Glib::FILE_TEST_IS_DIR)) { + fname = fchooser->get_current_name(); + } + + // Checking if the filename field is empty. The user have to click Cancel if he don't want to specify a filename + if (fname.empty()) { + Gtk::MessageDialog( + *this, + Glib::ustring("") + + M("MAIN_MSG_EMPTYFILENAME") + + "", + true, + Gtk::MESSAGE_WARNING, + Gtk::BUTTONS_OK, + true + ).run(); return; } - // resolve extension ambiguities - SaveFormat sf = formatOpts->getFormat (); - Glib::ustring extLower = getExtension (fname).lowercase (); - bool extIsEmpty = (extLower == ""); - bool extIsJpeg = (extLower == "jpg" || extLower == "jpeg" || extLower == "jpe"); - bool extIsTiff = (extLower == "tif" || extLower == "tiff"); - bool extIsPng = (extLower == "png"); + if (getExtension(fname).empty()) { + // Extension is either empty or unfamiliar + fname += '.' + formatOpts->getFormat().format; + } else if ( + !rtengine::hasJpegExtension(fname) + && !rtengine::hasTiffExtension(fname) + && !rtengine::hasPngExtension(fname) + ) { + // Create dialog to warn user that the filename may have two extensions on the end + Gtk::MessageDialog msgd( + *this, + Glib::ustring("") + + M("GENERAL_WARNING") + + ": " + + M("SAVEDLG_WARNFILENAME") + + " \"" + + Glib::path_get_basename (fname) + + '.' + + formatOpts->getFormat().format + + "\"", + true, + Gtk::MESSAGE_WARNING, + Gtk::BUTTONS_OK_CANCEL, + true + ); - if (extIsEmpty || !(extIsJpeg || extIsTiff || extIsPng)) { - // extension is either empty or unfamiliar. - fname += Glib::ustring (".") + sf.format; - } else if ( !(sf.format == "jpg" && extIsJpeg) - && !(sf.format == "tif" && extIsTiff) - && !(sf.format == "png" && extIsPng ) ) { - // create dialog to warn user that the filename may have two extensions on the end. - Glib::ustring msg_ = Glib::ustring ("") + M("GENERAL_WARNING") + ": " - + M("SAVEDLG_WARNFILENAME") + " \"" + Glib::path_get_basename (fname) - + "." + sf.format + "\""; - Gtk::MessageDialog msgd (*this, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK_CANCEL, true); - - if (msgd.run () == Gtk::RESPONSE_OK) { - fname += Glib::ustring (".") + sf.format; + if (msgd.run() == Gtk::RESPONSE_OK) { + fname += "." + formatOpts->getFormat().format; } else { return; } diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index 8ba713c53..6fa8eac52 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -434,10 +434,10 @@ void ThumbBrowserEntryBase::drawFrame (Cairo::RefPtr cc, const G if (selected || framed) { cc->move_to (radius, 0); - cc->arc (exp_width - 1 - radius, radius, radius, -M_PI / 2, 0); - cc->arc (exp_width - 1 - radius, exp_height - 1 - radius, radius, 0, M_PI / 2); - cc->arc (radius, exp_height - 1 - radius, radius, M_PI / 2, M_PI); - cc->arc (radius, radius, radius, M_PI, -M_PI / 2); + cc->arc (exp_width - 1 - radius, radius, radius, -rtengine::RT_PI / 2, 0); + cc->arc (exp_width - 1 - radius, exp_height - 1 - radius, radius, 0, rtengine::RT_PI / 2); + cc->arc (radius, exp_height - 1 - radius, radius, rtengine::RT_PI / 2, rtengine::RT_PI); + cc->arc (radius, radius, radius, rtengine::RT_PI, -rtengine::RT_PI / 2); cc->close_path (); if (selected) { @@ -452,10 +452,10 @@ void ThumbBrowserEntryBase::drawFrame (Cairo::RefPtr cc, const G if (framed) { cc->move_to (+2 + 0.5 + radius, +2 + 0.5); - cc->arc (-2 + 0.5 + exp_width - 1 - radius, +2 + 0.5 + radius, radius, -M_PI / 2, 0); - cc->arc (-2 + 0.5 + exp_width - 1 - radius, -2 + 0.5 + exp_height - 1 - radius, radius, 0, M_PI / 2); - cc->arc (+2 + 0.5 + radius, -2 + exp_height - 1 - radius, radius, M_PI / 2, M_PI); - cc->arc (+2 + 0.5 + radius, +2 + radius, radius, M_PI, -M_PI / 2); + cc->arc (-2 + 0.5 + exp_width - 1 - radius, +2 + 0.5 + radius, radius, -rtengine::RT_PI / 2, 0); + cc->arc (-2 + 0.5 + exp_width - 1 - radius, -2 + 0.5 + exp_height - 1 - radius, radius, 0, rtengine::RT_PI / 2); + cc->arc (+2 + 0.5 + radius, -2 + exp_height - 1 - radius, radius, rtengine::RT_PI / 2, rtengine::RT_PI); + cc->arc (+2 + 0.5 + radius, +2 + radius, radius, rtengine::RT_PI, -rtengine::RT_PI / 2); cc->close_path (); cc->set_source_rgb (fg.get_red(), fg.get_green(), fg.get_blue()); cc->set_line_width (2.0); diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 71aeab0ab..1be475d59 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -30,6 +30,7 @@ #include "profilestore.h" #include "batchqueue.h" #include "extprog.h" +#include "dynamicprofile.h" using namespace rtengine::procparams; @@ -137,7 +138,7 @@ void Thumbnail::_generateThumbnailImage () if ( tpp == nullptr ) { quick = false; - tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, tw, th, 1, pparams.wb.equal, TRUE); + tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, tw, th, 1, pparams.wb.equal, TRUE, pparams.raw.bayersensor.imageNum); } if (tpp) { @@ -184,7 +185,7 @@ const ProcParams& Thumbnail::getProcParamsU () pparams.wb.temperature = ct; } else if (pparams.wb.method == "Auto") { double ct; - getAutoWB (ct, pparams.wb.green, pparams.wb.equal); + getAutoWB (ct, pparams.wb.green, pparams.wb.equal, pparams.wb.tempBias); pparams.wb.temperature = ct; } } @@ -216,8 +217,31 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu const CacheImageData* cfs = getCacheImageData(); Glib::ustring defaultPparamsPath = options.findProfilePath(defProf); + const bool create = (!hasProcParams() || forceCPB); - if (!options.CPBPath.empty() && !defaultPparamsPath.empty() && (!hasProcParams() || forceCPB) && cfs && cfs->exifValid) { + const Glib::ustring outFName = + (options.paramsLoadLocation == PLL_Input) ? + fname + paramFileExtension : + getCacheFileName("profiles", paramFileExtension); + + if (defProf == DEFPROFILE_DYNAMIC && create && cfs && cfs->exifValid) { + rtengine::ImageMetaData* imageMetaData; + if (getType() == FT_Raw) { + rtengine::RawMetaDataLocation metaData = rtengine::Thumbnail::loadMetaDataFromRaw(fname); + imageMetaData = rtengine::ImageMetaData::fromFile (fname, &metaData); + } else { + imageMetaData = rtengine::ImageMetaData::fromFile (fname, nullptr); + } + PartialProfile *pp = loadDynamicProfile(imageMetaData); + int err = pp->pparams->save(outFName); + pp->deleteInstance(); + delete pp; + if (!err) { + loadProcParams(); + } + } + + if (!options.CPBPath.empty() && !defaultPparamsPath.empty() && create && cfs && cfs->exifValid) { // First generate the communication file, with general values and EXIF metadata rtengine::ImageMetaData* imageMetaData; @@ -233,14 +257,6 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu const rtexif::TagDirectory* exifDir = nullptr; if (imageMetaData && (exifDir = imageMetaData->getExifData())) { - Glib::ustring outFName; - - if (options.paramsLoadLocation == PLL_Input) { - outFName = fname + paramFileExtension; - } else { - outFName = getCacheFileName("profiles", paramFileExtension); - } - exifDir->CPBDump(tmpFileName, fname, outFName, defaultPparamsPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(defaultPparamsPath, Glib::path_get_basename(defProf) + paramFileExtension), cfs, @@ -669,7 +685,7 @@ const Glib::ustring& Thumbnail::getDateTimeString () return dateTimeString; } -void Thumbnail::getAutoWB (double& temp, double& green, double equal) +void Thumbnail::getAutoWB (double& temp, double& green, double equal, double tempBias) { if (cfs.redAWBMul != -1.0) { rtengine::ColorTemp ct(cfs.redAWBMul, cfs.greenAWBMul, cfs.blueAWBMul, equal); diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index a7b889d5f..8c7691ed2 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -125,7 +125,7 @@ public: temp = green = -1.0; } } - void getAutoWB (double& temp, double& green, double equal); + void getAutoWB (double& temp, double& green, double equal, double tempBias); void getSpotWB (int x, int y, int rect, double& temp, double& green) { if (tpp) { diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 98dc311f8..71281abd3 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -488,6 +488,7 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool ipc->setAutoExpListener (toneCurve); ipc->setAutoCamListener (colorappearance); ipc->setAutoBWListener (blackwhite); + ipc->setAutoWBListener (whitebalance); ipc->setAutoColorTonListener (colortoning); ipc->setAutoChromaListener (dirpyrdenoise); ipc->setWaveletListener (wavelet); diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index c4d4d3ac2..68a458916 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -252,10 +252,10 @@ public: void writeOptions (); // wbprovider interface - void getAutoWB (double& temp, double& green, double equal) + void getAutoWB (double& temp, double& green, double equal, double tempBias) { if (ipc) { - ipc->getAutoWB (temp, green, equal); + ipc->getAutoWB (temp, green, equal, tempBias); } } void getCamWB (double& temp, double& green) diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 71f3235c6..e1d0fc425 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -172,8 +172,7 @@ Wavelet::Wavelet() : enableFinalConn = expfinal->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), expfinal) ); // Wavelet Settings - Gtk::VBox* const settingsVBox = Gtk::manage(new Gtk::VBox()); - settingsVBox->set_spacing(2); + ToolParamBlock* const settingsBox = Gtk::manage (new ToolParamBlock()); strength->setAdjusterListener (this); @@ -247,16 +246,16 @@ Wavelet::Wavelet() : levdirSubHBox->pack_start(*Lmethod); levdirSubHBox->pack_start(*Dirmethod, Gtk::PACK_EXPAND_WIDGET, 2); // same, but 2 not 4? - settingsVBox->pack_start(*strength); - settingsVBox->pack_start(*thres); - settingsVBox->pack_start(*tilesizeHBox); - settingsVBox->pack_start(*daubcoeffHBox); - settingsVBox->pack_start(*backgroundHBox); - settingsVBox->pack_start(*levdirMainHBox); - settingsVBox->pack_start(*levdirSubHBox); + settingsBox->pack_start(*strength); + settingsBox->pack_start(*thres); + settingsBox->pack_start(*tilesizeHBox); + settingsBox->pack_start(*daubcoeffHBox); + settingsBox->pack_start(*backgroundHBox); + settingsBox->pack_start(*levdirMainHBox); + settingsBox->pack_start(*levdirSubHBox); // Contrast - Gtk::VBox* const levBox = Gtk::manage (new ToolParamBlock()); + ToolParamBlock* const levBox = Gtk::manage (new ToolParamBlock()); Gtk::HBox* const buttonBox = Gtk::manage (new Gtk::HBox(true, 10)); levBox->pack_start(*buttonBox, Gtk::PACK_SHRINK, 2); @@ -335,7 +334,7 @@ Wavelet::Wavelet() : levBox->pack_start(*contrastSHFrame); // Chromaticity - Gtk::VBox* const chBox = Gtk::manage (new ToolParamBlock()); + ToolParamBlock* const chBox = Gtk::manage (new ToolParamBlock()); Gtk::Label* const labmch = Gtk::manage(new Gtk::Label(M("TP_WAVELET_CHTYPE") + ":")); Gtk::HBox* const ctboxch = Gtk::manage(new Gtk::HBox()); @@ -405,7 +404,7 @@ Wavelet::Wavelet() : } // Toning - Gtk::VBox* const tonBox = Gtk::manage (new ToolParamBlock()); + ToolParamBlock* const tonBox = Gtk::manage (new ToolParamBlock()); opaCurveEditorG->setCurveListener (this); @@ -434,7 +433,7 @@ Wavelet::Wavelet() : tonBox->pack_start( *opacityCurveEditorG, Gtk::PACK_SHRINK, 2); // Denoise and Refine - Gtk::VBox* const noiseBox = Gtk::manage (new ToolParamBlock()); + ToolParamBlock* const noiseBox = Gtk::manage (new ToolParamBlock()); linkedg->set_active (true); linkedgConn = linkedg->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::linkedgToggled) ); @@ -458,7 +457,7 @@ Wavelet::Wavelet() : noiseBox->pack_start( *level3noise, Gtk::PACK_SHRINK, 0); // Edge Sharpness - Gtk::VBox* const edgBox = Gtk::manage (new ToolParamBlock()); + ToolParamBlock* const edgBox = Gtk::manage (new ToolParamBlock()); edgval->setAdjusterListener(this); edgBox->pack_start(*edgval); @@ -571,7 +570,7 @@ Wavelet::Wavelet() : edgBox->pack_start(*ctboxES); // Gamut - Gtk::VBox* const conBox = Gtk::manage (new ToolParamBlock()); + ToolParamBlock* const conBox = Gtk::manage (new ToolParamBlock()); median->set_active (true); medianConn = median->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::medianToggled) ); @@ -621,7 +620,7 @@ Wavelet::Wavelet() : conBox->pack_start(*avoid); // Residual Image - Gtk::VBox* const resBox = Gtk::manage (new ToolParamBlock()); + ToolParamBlock* const resBox = Gtk::manage (new ToolParamBlock()); rescon->setAdjusterListener (this); resBox->pack_start(*rescon, Gtk::PACK_SHRINK); @@ -822,7 +821,7 @@ Wavelet::Wavelet() : tmr->set_tooltip_text (M("TP_WAVELET_BALCHRO_TOOLTIP")); tmrConn = tmr->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::tmrToggled) ); - Gtk::VBox* const finalBox = Gtk::manage (new ToolParamBlock()); + ToolParamBlock* const finalBox = Gtk::manage (new ToolParamBlock()); finalBox->pack_start (*ctboxBA); finalBox->pack_start(*balance); @@ -839,7 +838,7 @@ Wavelet::Wavelet() : //----------------------------- - expsettings->add(*settingsVBox); + expsettings->add(*settingsBox); expsettings->setLevel(2); pack_start (*expsettings); diff --git a/rtgui/wbprovider.h b/rtgui/wbprovider.h index 2e46467f9..df1329c84 100644 --- a/rtgui/wbprovider.h +++ b/rtgui/wbprovider.h @@ -25,7 +25,7 @@ class WBProvider public: virtual ~WBProvider() {} - virtual void getAutoWB (double& temp, double& green, double equal) {} + virtual void getAutoWB (double& temp, double& green, double equal, double tempBias) {} virtual void getCamWB (double& temp, double& green) {} virtual void spotWBRequested (int size) {} }; diff --git a/rtgui/whitebalance.cc b/rtgui/whitebalance.cc index d0413412b..362d03a8d 100644 --- a/rtgui/whitebalance.cc +++ b/rtgui/whitebalance.cc @@ -309,17 +309,22 @@ WhiteBalance::WhiteBalance () : FoldableToolPanel(this, "whitebalance", M("TP_WB Gtk::Image* igreenR = Gtk::manage (new RTImage ("ajd-wb-green2.png")); Gtk::Image* iblueredL = Gtk::manage (new RTImage ("ajd-wb-bluered1.png")); Gtk::Image* iblueredR = Gtk::manage (new RTImage ("ajd-wb-bluered2.png")); + Gtk::Image* itempbiasL = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); + Gtk::Image* itempbiasR = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); temp = Gtk::manage (new Adjuster (M("TP_WBALANCE_TEMPERATURE"), MINTEMP, MAXTEMP, 5, CENTERTEMP, itempL, itempR, &wbSlider2Temp, &wbTemp2Slider)); green = Gtk::manage (new Adjuster (M("TP_WBALANCE_GREEN"), MINGREEN, MAXGREEN, 0.001, 1.0, igreenL, igreenR)); equal = Gtk::manage (new Adjuster (M("TP_WBALANCE_EQBLUERED"), MINEQUAL, MAXEQUAL, 0.001, 1.0, iblueredL, iblueredR)); + tempBias = Gtk::manage (new Adjuster(M("TP_WBALANCE_TEMPBIAS"), -0.5, 0.5, 0.01, 0.0, itempbiasL, itempbiasR)); cache_customTemp (0); cache_customGreen (0); cache_customEqual (0); equal->set_tooltip_markup (M("TP_WBALANCE_EQBLUERED_TOOLTIP")); + tempBias->set_tooltip_markup (M("TP_WBALANCE_TEMPBIAS_TOOLTIP")); temp->show (); green->show (); equal->show (); + tempBias->show (); /* Gtk::HBox* boxgreen = Gtk::manage (new Gtk::HBox ()); boxgreen->show (); @@ -332,10 +337,12 @@ WhiteBalance::WhiteBalance () : FoldableToolPanel(this, "whitebalance", M("TP_WB //pack_start (*boxgreen); pack_start (*green); pack_start (*equal); + pack_start (*tempBias); temp->setAdjusterListener (this); green->setAdjusterListener (this); equal->setAdjusterListener (this); + tempBias->setAdjusterListener (this); spotbutton->signal_pressed().connect( sigc::mem_fun(*this, &WhiteBalance::spotPressed) ); methconn = method->signal_changed().connect( sigc::mem_fun(*this, &WhiteBalance::optChanged) ); @@ -348,6 +355,7 @@ void WhiteBalance::adjusterChanged (Adjuster* a, double newval) int tVal = (int)temp->getValue(); double gVal = green->getValue(); double eVal = equal->getValue(); + double tempBiasVal = tempBias->getValue(); Gtk::TreeModel::Row row = getActiveMethod(); if (row == refTreeModel->children().end()) { @@ -358,11 +366,15 @@ void WhiteBalance::adjusterChanged (Adjuster* a, double newval) WBEntry* ppMethod = findWBEntry (row[methodColumns.colLabel], WBLT_GUI); WBEntry* wbCustom = findWBEntry ("Custom", WBLT_PP); - if (!ppMethod || (ppMethod->ppLabel != wbCustom->ppLabel && !(a == equal && ppMethod->type == WBT_AUTO)) ) { + if (!ppMethod || (ppMethod->ppLabel != wbCustom->ppLabel && !((a == equal || a == tempBias) && ppMethod->type == WBT_AUTO)) ) { methconn.block(true); opt = setActiveMethod(wbCustom->GUILabel); + tempBias->set_sensitive(false); + cache_customWB (tVal, gVal); - cache_customEqual(eVal); + if (a != equal) { + cache_customEqual(eVal); + } methconn.block(false); } @@ -373,27 +385,10 @@ void WhiteBalance::adjusterChanged (Adjuster* a, double newval) cache_customGreen (gVal); } else if (a == equal) { cache_customEqual (eVal); - - // Recomputing AutoWB if it's the current method - if (wbp && ppMethod->type == WBT_AUTO) { - double ctemp = -1.0; - double cgreen = -1.0; - wbp->getAutoWB (ctemp, cgreen, eVal); - - if (ctemp != -1.0) { - // Set the automatics temperature value only if in SET mode - if (temp->getEditedState() && !temp->getAddMode() ) { - temp->setValue (ctemp); - } - - // Set the automatics green value only if in SET mode - if (green->getEditedState() && !green->getAddMode()) { - green->setValue (cgreen); - } - } - } } + // Recomputing AutoWB if it's the current method will happen in improccoordinator.cc + if (listener) { if (a == temp) { listener->panelChanged (EvWBTemp, Glib::ustring::format ((int)a->getValue())); @@ -401,6 +396,8 @@ void WhiteBalance::adjusterChanged (Adjuster* a, double newval) listener->panelChanged (EvWBGreen, Glib::ustring::format (std::setw(4), std::fixed, std::setprecision(3), a->getValue())); } else if (a == equal) { listener->panelChanged (EvWBequal, Glib::ustring::format (std::setw(4), std::fixed, std::setprecision(3), a->getValue())); + } else if (a == tempBias) { + listener->panelChanged (EvWBtempBias, Glib::ustring::format (std::setw(4), std::fixed, std::setprecision(2), a->getValue())); } } } @@ -430,10 +427,13 @@ void WhiteBalance::optChanged () temp->setEditedState (UnEdited); green->setEditedState (UnEdited); equal->setEditedState (UnEdited); + tempBias->setEditedState (UnEdited); } else { int methodId = findWBEntryId (row[methodColumns.colLabel], WBLT_GUI); WBEntry* currMethod = WBParams::wbEntries[methodId]; + tempBias->set_sensitive(currMethod->type == WBT_AUTO); + switch (currMethod->type) { case WBT_CAMERA: if (wbp) { @@ -460,15 +460,7 @@ void WhiteBalance::optChanged () // equal remain as is } - if (!batchMode || equal->getEditedState()) { - double ctemp, cgreen; - wbp->getAutoWB (ctemp, cgreen, equal->getValue()); - - if (ctemp != -1.0) { - temp->setValue (temp->getAddMode() ? 0.0 : (int)ctemp); - green->setValue (green->getAddMode() ? 0.0 : cgreen); - } - } + // Recomputing AutoWB will happen in improccoordinator.cc } break; @@ -546,12 +538,15 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) methconn.block (true); equal->setValue (pp->wb.equal); + tempBias->setValue (pp->wb.tempBias); + tempBias->set_sensitive(true); if (pedited) { // By default, temperature and green are said "UnEdited", but it may change later temp->setEditedState (UnEdited); green->setEditedState (UnEdited); equal->setEditedState (pedited->wb.equal ? Edited : UnEdited); + tempBias->setEditedState (pedited->wb.tempBias ? Edited : UnEdited); } if (pedited && !pedited->wb.method) { @@ -571,6 +566,7 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) temp->setValue (temp->getAddMode() ? 0.0 : pp->wb.temperature); green->setValue (green->getAddMode() ? 0.0 : pp->wb.green); equal->setValue (equal->getAddMode() ? 0.0 : pp->wb.equal); + tempBias->setValue (tempBias->getAddMode() ? 0.0 : pp->wb.tempBias); cache_customTemp (pp->wb.temperature); cache_customGreen (pp->wb.green); cache_customEqual (pp->wb.equal); @@ -600,6 +596,7 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) green->setValue (green->getAddMode() ? 0.0 : pp->wb.green); equal->setValue (equal->getAddMode() ? 0.0 : pp->wb.equal); } + tempBias->setValue (equal->getAddMode() ? 0.0 : pp->wb.tempBias); } break; @@ -607,7 +604,8 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) case WBT_AUTO: // the equalizer's value is restored for the AutoWB equal->setValue (equal->getAddMode() ? 0.0 : pp->wb.equal); - + tempBias->setValue (tempBias->getAddMode() ? 0.0 : pp->wb.tempBias); + // set default values first if in ADD mode, otherwise keep the current ones if (temp->getAddMode() ) { temp->setValue (0.0); @@ -617,32 +615,7 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) green->setValue (0.0); } - // then check for the correct ones, if possible - if (wbp) { - double ctemp = -1.0; - double cgreen = -1.0; - wbp->getAutoWB (ctemp, cgreen, pp->wb.equal); - - if (ctemp != -1.0) { - // Set the automatics temperature if in SET mode - if (!pedited || (pedited->wb.temperature && !temp->getAddMode()) ) { - temp->setValue (ctemp); - - if (pedited) { - temp->setEditedState (Edited); - } - } - - // Set the automatics green value if in SET mode - if (!pedited || (pedited->wb.green && !green->getAddMode())) { - green->setValue (cgreen); - - if (pedited) { - green->setEditedState (Edited); - } - } - } - } + // Recomputing AutoWB will happen in improccoordinator.cc break; @@ -663,16 +636,20 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) // Set the stored temperature, or 0.0 if in ADD mode green->setValue(green->getAddMode() ? 0.0 : pp->wb.green); equal->setValue(equal->getAddMode() ? 0.0 : pp->wb.equal); + tempBias->setValue(equal->getAddMode() ? 0.0 : pp->wb.tempBias); // The user may have changed the green value even for predefined WB values if (pedited) { green->setEditedState (pedited->wb.green ? Edited : UnEdited); equal->setEditedState (pedited->wb.equal ? Edited : UnEdited); + tempBias->setEditedState (pedited->wb.tempBias ? Edited : UnEdited); } //cache_customGreen (pp->wb.green); break; } + + tempBias->set_sensitive(wbValues->type == WBT_AUTO); } methconn.block (false); @@ -688,6 +665,7 @@ void WhiteBalance::write (ProcParams* pp, ParamsEdited* pedited) pedited->wb.temperature = temp->getEditedState (); pedited->wb.green = green->getEditedState (); pedited->wb.equal = equal->getEditedState (); + pedited->wb.tempBias = tempBias->getEditedState (); pedited->wb.method = row[methodColumns.colLabel] != M("GENERAL_UNCHANGED"); } @@ -700,11 +678,14 @@ void WhiteBalance::write (ProcParams* pp, ParamsEdited* pedited) pp->wb.temperature = temp->getIntValue (); pp->wb.green = green->getValue (); pp->wb.equal = equal->getValue (); + pp->wb.tempBias = tempBias->getValue (); } void WhiteBalance::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { + equal->setDefault (defParams->wb.equal); + tempBias->setDefault (defParams->wb.tempBias); if (wbp && defParams->wb.method == "Camera") { double ctemp; @@ -716,34 +697,22 @@ void WhiteBalance::setDefaults (const ProcParams* defParams, const ParamsEdited* temp->setDefault (temp->getAddMode() ? 0 : (int)ctemp); green->setDefault (green->getAddMode() ? 0 : cgreen); } - } else if (wbp && defParams->wb.method == "Auto") { - // this setDefaults method is called too early ; the wbp has been set, - // but wbp is not ready to provide! - double ctemp; - double cgreen; - wbp->getAutoWB (ctemp, cgreen, defParams->wb.equal); - - if (ctemp != -1.0) { - temp->setDefault (temp->getAddMode() ? 0 : (int)ctemp); - green->setDefault (green->getAddMode() ? 0 : cgreen); - } else { - // 6504 & 1.0 = same values as in ProcParams::setDefaults - temp->setDefault (temp->getAddMode() ? 0 : 6504); - green->setDefault (green->getAddMode() ? 0 : 1.0); - } } else { temp->setDefault (defParams->wb.temperature); green->setDefault (defParams->wb.green); } + // Recomputing AutoWB if it's the current method will happen in improccoordinator.cc if (pedited) { temp->setDefaultEditedState (pedited->wb.temperature ? Edited : UnEdited); green->setDefaultEditedState (pedited->wb.green ? Edited : UnEdited); equal->setDefaultEditedState (pedited->wb.equal ? Edited : UnEdited); + tempBias->setDefaultEditedState (pedited->wb.tempBias ? Edited : UnEdited); } else { temp->setDefaultEditedState (Irrelevant); green->setDefaultEditedState (Irrelevant); equal->setDefaultEditedState (Irrelevant); + tempBias->setDefaultEditedState (Irrelevant); } } @@ -754,6 +723,7 @@ void WhiteBalance::setBatchMode (bool batchMode) temp->showEditedCB (); green->showEditedCB (); equal->showEditedCB (); + tempBias->showEditedCB (); Gtk::TreeModel::Row row = *(refTreeModel->append()); row[methodColumns.colId] = WBParams::wbEntries.size(); row[methodColumns.colLabel] = M("GENERAL_UNCHANGED"); @@ -785,12 +755,13 @@ void WhiteBalance::setWB (int vtemp, double vgreen) } } -void WhiteBalance::setAdjusterBehavior (bool tempadd, bool greenadd, bool equaladd) +void WhiteBalance::setAdjusterBehavior (bool tempadd, bool greenadd, bool equaladd, bool tempbiasadd) { temp->setAddMode(tempadd); green->setAddMode(greenadd); equal->setAddMode(equaladd); + tempBias->setAddMode(tempbiasadd); } void WhiteBalance::trimValues (rtengine::procparams::ProcParams* pp) @@ -799,6 +770,7 @@ void WhiteBalance::trimValues (rtengine::procparams::ProcParams* pp) temp->trimValue(pp->wb.temperature); green->trimValue(pp->wb.green); equal->trimValue(pp->wb.equal); + tempBias->trimValue(pp->wb.tempBias); } inline void WhiteBalance::cache_customTemp(int temp) @@ -884,3 +856,14 @@ inline Gtk::TreeRow WhiteBalance::getActiveMethod () { return *(method->get_active()); } + +void WhiteBalance::WBChanged(double temperature, double greenVal) +{ + GThreadLock lock; + disableListener(); + temp->setValue(temperature); + green->setValue(greenVal); + temp->setDefault(temperature); + green->setDefault(greenVal); + enableListener(); +} diff --git a/rtgui/whitebalance.h b/rtgui/whitebalance.h index c18b15853..1d493c035 100644 --- a/rtgui/whitebalance.h +++ b/rtgui/whitebalance.h @@ -34,7 +34,7 @@ public: virtual void spotWBRequested (int size) {} }; -class WhiteBalance : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +class WhiteBalance : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoWBListener { enum WB_LabelType { @@ -65,6 +65,7 @@ protected: Adjuster* temp; Adjuster* green; Adjuster* equal; + Adjuster* tempBias; Gtk::Button* spotbutton; int opt; @@ -114,8 +115,9 @@ public: wblistener = l; } void setWB (int temp, double green); + void WBChanged (double temp, double green); - void setAdjusterBehavior (bool tempadd, bool greenadd, bool equaladd); + void setAdjusterBehavior (bool tempadd, bool greenadd, bool equaladd, bool tempbiasadd); void trimValues (rtengine::procparams::ProcParams* pp); }; diff --git a/win.cmake b/win.cmake index 072061d8f..0a32ac956 100644 --- a/win.cmake +++ b/win.cmake @@ -1,48 +1,50 @@ -# Use the 'Debug' build type to have a non optimized, with debugging information, with a console executable. -# Use the 'Release' build type to have an optimized, without debugging information, console-free executable. -# Use the 'RelWithDebInfo' build type to have an optimized, without debugging information, with a console executable. -# Use the 'MinSizeRel' build type to have the smallest possible, without debugging information, console-free executable. -# +# Use the 'Debug' build type to have a non optimized, with debugging information, with a console executable +# Use the 'Release' build type to have an optimized, without debugging information, console free executable +# Use the 'RelWithDebInfo' build type to have an optimized, without debugging information, with a console executable +# Use the 'MinSizeRel' build type to have the smallest possible, without debugging information, console free executable #set(CMAKE_BUILD_TYPE Release CACHE STRING "Between: None Debug Release RelWithDebInfo MinSizeRel.") -set(CMAKE_INSTALL_PREFIX ./Builds/${CMAKE_BUILD_TYPE} CACHE PATH "Library installation path") -set(DATADIR . CACHE PATH "Data installation path") +set(CMAKE_INSTALL_PREFIX ./${CMAKE_BUILD_TYPE} CACHE PATH "Libraries installation path") +set(DATADIR . CACHE PATH "Datas installation path") set(BINDIR . CACHE PATH "Binaries installation path") -set(LIBDIR . CACHE PATH "Library installation path") +set(LIBDIR . CACHE PATH "Libraries installation path") set(DOCDIR ./doc CACHE PATH "Documentation installation path") set(CREDITSDIR . CACHE PATH "Credit file installation path") set(LICENCEDIR . CACHE PATH "Licence file installation path") -set(BUILD_SHARED OFF CACHE BOOL "Should shared libraries be generated") +set(BUILD_SHARED OFF CACHE BOOL "Should RT generate shared libraries") set(OPTION_OMP ON CACHE BOOL "Use OpenMP to speedup the preview and batch processing") -# set WITH_MYFILE_MMAP to OFF if you experience crashes caused by thumbnail creation (it will be slower but more reliable). -set(WITH_MYFILE_MMAP ON CACHE BOOL "Use the MMAP mechanism to speedup thumbnail creation") +# set WITH_MYFILE_MMAP to OFF if you experience crash with thumbnail creation (it should be slower, but more reliable) +set(WITH_MYFILE_MMAP ON CACHE BOOL "Use the MMAP mechanism to speedup thumbnail creations") -set(CACHE_NAME_SUFFIX "" CACHE STRING "RawTherapee's cache folder suffix (leave empty to use default from UpdateIndo.cmake)") +set(CACHE_NAME_SUFFIX "" CACHE STRING "RawTherapee's cache folder suffix (leave empty to use the default suffix, i.e. latesttag)") -# Choose the target processor's number from ProcessorTargets.cmake. -set(PROC_TARGET_NUMBER 0 CACHE STRING "Target processor") +# This line will let you chose the target number, and the associated processor +set(PROC_TARGET_NUMBER 0 CACHE STRING "Target Processor") # If you want to force the target processor name when PROC_TARGET_NUMBER = 0 or 2, -# uncomment the next line and replace labelWithoutQuotes with a string. -#set (PROC_LABEL labelWithoutQuotes CACHE STRING "Target processor label") +# uncomment the next line and replace labelWithoutQuotes by its value +#set (PROC_LABEL labelWithoutQuotes CACHE STRING "Target Processor label") -# Important: MinGW-w64 users may need to specify the -m32 or -m64 flag in CMAKE_CXX_FLAGS, -# CMAKE_C_FLAGS and CMAKE_EXE_LINKER_FLAGS to select between 32-/64-bit builds. -set(CMAKE_CXX_FLAGS "-mwin32 -mthreads" CACHE STRING "Compiler options for C++ source files") +# Important: MinGW-w64 user may need to specify the -m32 or -m64 flag in CMAKE_CXX_FLAGS, +# CMAKE_C_FLAGS and CMAKE_EXE_LINKER_FLAGS to select between 32/64bit build +set(CMAKE_CXX_FLAGS "-mwin32 -m64 -mthreads -msse2" CACHE STRING "Compiler options for C++ source files") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g2" CACHE STRING "Compiler options for C++ source files and Debug target") -set(CMAKE_CXX_FLAGS_RELEASE "-mwindows -DNDEBUG -O2" CACHE STRING "Compiler options for C++ source files and Release target") +set(CMAKE_CXX_FLAGS_RELEASE "-mwindows -Wno-aggressive-loop-optimizations -DNDEBUG -O3" CACHE STRING "Compiler options for C++ source files and Release target") set(CMAKE_CXX_FLAGS_MINSIZEREL "-mwindows -DNDEBUG -Os" CACHE STRING "Compiler options for C++ source files and MinSizeRel target") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g" CACHE STRING "Compiler options for C++ source files and RelWithDebInfo target") -set(CMAKE_C_FLAGS "-mwin32 -mthreads" CACHE STRING "Compiler options for C source files") +# Uncomment the next line and set the right value to override the default value (special compiling flags for RTEngine) +#set(RTENGINE_CXX_FLAGS "-funroll-loops" CACHE STRING "Special compilation flags for RTEngine") + +set(CMAKE_C_FLAGS "-mwin32 -m64 -mthreads -msse2" CACHE STRING "Compiler options for C source files") set(CMAKE_C_FLAGS_DEBUG "-O0 -g2" CACHE STRING "Compiler options for C source files and Debug target") set(CMAKE_C_FLAGS_RELEASE "-mwindows -DNDEBUG -O2" CACHE STRING "Compiler options for C source files and Release target") set(CMAKE_C_FLAGS_MINSIZEREL "-mwindows -DNDEBUG -Os" CACHE STRING "Compiler options for C source files and MinSizeRel target") set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g" CACHE STRING "Compiler options for C source files and RelWithDebInfo target") -set(CMAKE_EXE_LINKER_FLAGS "-mwin32 -mthreads -static-libgcc -Wl,--large-address-aware,--verbose" CACHE STRING "Linker options") +set(CMAKE_EXE_LINKER_FLAGS "-m64 -mthreads -static-libgcc" CACHE STRING "Linker options") set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-O0" CACHE STRING "Linkage options for the Debug target") -set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-mwindows -s -O2" CACHE STRING "Linkage options for the Release target") +set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-mwindows -s -O3" CACHE STRING "Linkage options for the Release target") set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-mwindows -s -Os" CACHE STRING "Linkage options for the MinSizeRel target") set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "-s -O2" CACHE STRING "Linkage options for the RelWithDebInfo target")