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/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 991d99479..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 @@ -1437,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 @@ -1451,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 diff --git a/rtdata/languages/Chinese (Simplified) b/rtdata/languages/Chinese (Simplified) index af56b7dd1..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) @@ -1399,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 @@ -1417,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 diff --git a/rtdata/languages/Chinese (Traditional) b/rtdata/languages/Chinese (Traditional) index 65abab6de..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. @@ -1209,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 @@ -1232,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... diff --git a/rtdata/languages/Czech b/rtdata/languages/Czech index 08efca6cb..4a6aa685f 100644 --- a/rtdata/languages/Czech +++ b/rtdata/languages/Czech @@ -2074,6 +2074,17 @@ 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 0726bf930..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. @@ -1207,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 @@ -1230,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... diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index deec1e3a1..1d1c8275e 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -35,6 +35,7 @@ #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 @@ -70,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. @@ -1108,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 @@ -1136,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 @@ -2071,3 +2083,4 @@ ZOOMPANEL_ZOOMFITCROPSCREEN;Ausschnitt an Bildschirm anpassen\nTaste: Alt ZOOMPANEL_ZOOMFITSCREEN;An Bildschirm anpassen\nTaste: f ZOOMPANEL_ZOOMIN;Hineinzoomen\nTaste: + ZOOMPANEL_ZOOMOUT;Herauszoomen\nTaste: - + diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index cb0bfa7ad..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. @@ -1137,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 @@ -1165,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 diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index f9aa862f4..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. @@ -1075,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 @@ -1103,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 diff --git a/rtdata/languages/Espanol b/rtdata/languages/Espanol index 3cd36a01f..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. @@ -1779,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 @@ -1787,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. diff --git a/rtdata/languages/Euskara b/rtdata/languages/Euskara index 7dce64cdf..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. @@ -1207,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 @@ -1230,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... diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index d1031f359..0a7ea0edd 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -2039,6 +2039,17 @@ 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 e71a2c1e0..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. @@ -1206,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 @@ -1229,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... diff --git a/rtdata/languages/Hebrew b/rtdata/languages/Hebrew index d0a5d9023..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. @@ -1207,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 @@ -1230,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... diff --git a/rtdata/languages/Italiano b/rtdata/languages/Italiano index ae60b9303..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. @@ -1650,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 @@ -1658,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. diff --git a/rtdata/languages/Japanese b/rtdata/languages/Japanese index c879c649c..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 @@ -1967,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. diff --git a/rtdata/languages/Latvian b/rtdata/languages/Latvian index 4594b8250..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. @@ -1207,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 @@ -1230,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... diff --git a/rtdata/languages/Magyar b/rtdata/languages/Magyar index 1188f5344..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 @@ -1374,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 @@ -1388,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 diff --git a/rtdata/languages/Nederlands b/rtdata/languages/Nederlands index 636efe1ad..04d5bd4d5 100644 --- a/rtdata/languages/Nederlands +++ b/rtdata/languages/Nederlands @@ -1998,6 +1998,15 @@ 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 @@ -2038,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 diff --git a/rtdata/languages/Norsk BM b/rtdata/languages/Norsk BM index 2525bb55e..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. @@ -1206,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 @@ -1229,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... diff --git a/rtdata/languages/Polish b/rtdata/languages/Polish index 6493ba694..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. @@ -1727,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 @@ -1735,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. diff --git a/rtdata/languages/Polish (Latin Characters) b/rtdata/languages/Polish (Latin Characters) index ce490653c..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. @@ -1727,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 @@ -1735,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. diff --git a/rtdata/languages/Portugues (Brasil) b/rtdata/languages/Portugues (Brasil) index a08f2453d..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. @@ -1207,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 @@ -1230,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... diff --git a/rtdata/languages/Russian b/rtdata/languages/Russian index 9ed2b940b..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 @@ -1607,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 @@ -1615,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. diff --git a/rtdata/languages/Serbian (Cyrilic Characters) b/rtdata/languages/Serbian (Cyrilic Characters) index 648a123e2..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 @@ -1773,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 @@ -1780,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 diff --git a/rtdata/languages/Serbian (Latin Characters) b/rtdata/languages/Serbian (Latin Characters) index 49f5eee27..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 @@ -1773,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 @@ -1780,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 diff --git a/rtdata/languages/Slovak b/rtdata/languages/Slovak index 4fbe51c42..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. @@ -1251,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 @@ -1272,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... diff --git a/rtdata/languages/Suomi b/rtdata/languages/Suomi index aeed6500f..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. @@ -1208,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 @@ -1231,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... diff --git a/rtdata/languages/Swedish b/rtdata/languages/Swedish index b25ebf2a5..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 @@ -1957,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 diff --git a/rtdata/languages/Turkish b/rtdata/languages/Turkish index e9da40531..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. @@ -1207,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 @@ -1230,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... diff --git a/rtdata/languages/default b/rtdata/languages/default index 10a1eeb48..1cb5a9105 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. @@ -1152,6 +1161,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 @@ -1180,6 +1190,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 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 19bd6ac9c..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; diff --git a/rtdata/themes/TooWaBlue-Dark-GTK3-20_.css b/rtdata/themes/TooWaBlue-Dark-GTK3-20_.css index 4c6bbc3ef..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.45 - 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 { @@ -789,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; } @@ -892,6 +901,11 @@ 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; @@ -1087,6 +1101,9 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { border-color: @bg-dark-grey; background-image: none; } +#ThresholdAdjuster { + margin: 0.08334em 0 0.16667em 0; +} #ToolPanelNotebook scrolledwindow viewport.frame { padding: 0 0.56em; @@ -1340,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, @@ -1374,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 { @@ -1392,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,6 +1471,7 @@ window .view button { min-height: 2em; min-width: 1.33334em; padding: 0 0.33334em; + margin: 0; } dialog .view button.text-button label, window .view button.text-button label { @@ -1476,10 +1495,10 @@ dialog .view button { 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, @@ -1488,6 +1507,7 @@ window .view header button, } #pathbarbox button:last-child { + min-height: 2em; min-width: 2em; margin: 0; padding: 0; @@ -1519,7 +1539,7 @@ popover button.text-button { 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; } @@ -1609,17 +1629,14 @@ headerbar button.titlebutton.close:active{ /*** 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); @@ -1662,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: 1.83334em; -} -#PrefNotebook radiobutton { - min-height: 2em; -} #MyExpander button + checkbutton:last-child { margin-left: 0.33334em; @@ -1682,7 +1689,7 @@ 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; @@ -1693,7 +1700,7 @@ entry { } spinbutton { - margin: 0; + margin: 0.08334em 0; padding: 0; min-height: 1.66667em; min-width: 0; diff --git a/rtdata/themes/TooWaBlue-GTK3-20_.css b/rtdata/themes/TooWaBlue-GTK3-20_.css index 795dc0441..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.45 - 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 { @@ -789,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; } @@ -892,6 +901,11 @@ 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; @@ -1087,6 +1101,9 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { border-color: @bg-dark-grey; background-image: none; } +#ThresholdAdjuster { + margin: 0.08334em 0 0.16667em 0; +} #ToolPanelNotebook scrolledwindow viewport.frame { padding: 0 0.56em; @@ -1340,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, @@ -1374,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 { @@ -1392,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,6 +1471,7 @@ window .view button { min-height: 2em; min-width: 1.33334em; padding: 0 0.33334em; + margin: 0; } dialog .view button.text-button label, window .view button.text-button label { @@ -1476,10 +1495,10 @@ dialog .view button { 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, @@ -1488,6 +1507,7 @@ window .view header button, } #pathbarbox button:last-child { + min-height: 2em; min-width: 2em; margin: 0; padding: 0; @@ -1519,7 +1539,7 @@ popover button.text-button { 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; } @@ -1609,17 +1629,14 @@ headerbar button.titlebutton.close:active{ /*** 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); @@ -1662,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: 1.83334em; -} -#PrefNotebook radiobutton { - min-height: 2em; -} #MyExpander button + checkbutton:last-child { margin-left: 0.33334em; @@ -1682,7 +1689,7 @@ 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; @@ -1693,7 +1700,7 @@ entry { } spinbutton { - margin: 0; + margin: 0.08334em 0; padding: 0; min-height: 1.66667em; min-width: 0; 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/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/curves.h b/rtengine/curves.h index 2abd4daee..4760b26d7 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -1090,8 +1090,10 @@ 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/dcraw.cc b/rtengine/dcraw.cc index f762fefcd..286574e0f 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -9022,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; @@ -9874,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/demosaic_algos.cc b/rtengine/demosaic_algos.cc index e641ed777..60abe8998 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -1,3 +1,4 @@ +/* /* * This file is part of RawTherapee. * @@ -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/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/iccstore.cc b/rtengine/iccstore.cc index 16ae455b6..52dd25573 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -173,9 +173,15 @@ std::vector ICCStore::getProfiles (const ProfileType type) const std::vector res; for (const auto profile : fileProfiles) { - if ( (type==ICCStore::ProfileType::MONITOR && cmsGetDeviceClass(profile.second) == cmsSigDisplayClass && cmsGetColorSpace (profile.second) == cmsSigRgbData) - || (type==ICCStore::ProfileType::PRINTER && cmsGetDeviceClass(profile.second) == cmsSigOutputClass) - || (type==ICCStore::ProfileType::OUTPUT && cmsGetDeviceClass(profile.second) == cmsSigDisplayClass && cmsGetColorSpace (profile.second) == cmsSigRgbData) ) + if ( (type==ICCStore::ProfileType::MONITOR + && cmsGetDeviceClass(profile.second) == cmsSigDisplayClass + && cmsGetColorSpace (profile.second) == cmsSigRgbData) + || (type==ICCStore::ProfileType::PRINTER + && cmsGetDeviceClass(profile.second) == cmsSigOutputClass) + || (type==ICCStore::ProfileType::OUTPUT + && (cmsGetDeviceClass(profile.second) == cmsSigDisplayClass || cmsGetDeviceClass(profile.second) == cmsSigOutputClass) + && cmsGetColorSpace (profile.second) == cmsSigRgbData) + ) { res.push_back (profile.first); } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 6cdc53b7a..379e1d810 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -2681,7 +2681,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 diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index bd3a97964..6f1c470d2 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -9236,6 +9236,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/rawimage.cc b/rtengine/rawimage.cc index 1c129d28a..88fed5473 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -437,9 +437,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; diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 151edf959..9fafef8bb 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -236,19 +236,19 @@ protected: 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); diff --git a/rtengine/rt_math.h b/rtengine/rt_math.h index a7cbbf301..6e1138476 100644 --- a/rtengine/rt_math.h +++ b/rtengine/rt_math.h @@ -27,71 +27,68 @@ 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 -inline _Tp SQR (_Tp x) +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: @@ -115,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/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/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index ab3c8b3b4..b553bc31e 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -30,7 +30,8 @@ set (BASESOURCEFILES 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 locallab.cc - filmsimulation.cc prsharpening.cc) + filmsimulation.cc prsharpening.cc + dynamicprofile.cc dynamicprofilepanel.cc) include_directories (BEFORE "${CMAKE_CURRENT_BINARY_DIR}") 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/main.cc b/rtgui/main.cc index 4eae480f7..05842b2cd 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -37,6 +37,7 @@ #include "rtimage.h" #include "version.h" #include "extprog.h" +#include "dynamicprofile.h" #ifndef WIN32 #include @@ -182,7 +183,7 @@ int main (int argc, char **argv) bool consoleOpened = false; // suppression of annoying error boxes - SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); + 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))) { @@ -208,8 +209,8 @@ int main (int argc, char **argv) SetConsoleCtrlHandler ( NULL, true ); // Set title of console char consoletitle[128]; - sprintf(consoletitle, "RawTherapee %s Console", RTVERSION); - SetConsoleTitle(consoletitle); + sprintf (consoletitle, "RawTherapee %s Console", RTVERSION); + SetConsoleTitle (consoletitle); // increase size of screen buffer COORD c; c.X = 200; @@ -717,7 +718,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; @@ -728,7 +729,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; @@ -800,9 +801,21 @@ 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 { + 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/options.cc b/rtgui/options.cc index f2c7fe533..bf200cfe1 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -245,6 +245,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}") { diff --git a/rtgui/options.h b/rtgui/options.h index 350221dd2..d6b8aec0f 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -39,11 +39,22 @@ #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 +63,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/preferences.cc b/rtgui/preferences.cc index 1e81c8ea6..147cdbced 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -82,6 +82,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")); @@ -247,11 +248,11 @@ Gtk::Widget* Preferences::getBatchProcPanel () appendBehavList (mi, M ("TP_DIRPYRDENOISE_PASSES"), ADDSET_DIRPYRDN_PASSES, true); mi = behModel->append (); - mi->set_value (behavColumns.label, M("TP_WBALANCE_LABEL")); - 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->set_value (behavColumns.label, M ("TP_WBALANCE_LABEL")); + 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")); @@ -440,6 +441,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 () { @@ -449,11 +458,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) ); @@ -2106,6 +2117,7 @@ void Preferences::okPressed () options.copyFrom (&moptions); options.filterOutParsedExtensions(); Options::save (); + dynProfilePanel->save(); hide (); } @@ -2269,6 +2281,8 @@ void Preferences::updateProfileList() { rprofiles->updateProfileList(); iprofiles->updateProfileList(); + rprofiles->addRow (profileStore.getInternalDynamicPSE()); + iprofiles->addRow (profileStore.getInternalDynamicPSE()); } void Preferences::restoreValue() diff --git a/rtgui/preferences.h b/rtgui/preferences.h index 2a6e3ea6d..fd438d1d2 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 { @@ -204,6 +205,8 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener Gtk::CheckButton* ckbHideTPVScrollbar; Gtk::CheckButton* ckbUseIconNoText; + DynamicProfilePanel *dynProfilePanel; + Glib::ustring storedValueRaw; Glib::ustring storedValueImg; @@ -242,6 +245,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/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/thumbnail.cc b/rtgui/thumbnail.cc index 03ef49a5e..62f543d4a 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; @@ -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,