diff --git a/rtdata/images/Dark/actions/HDR-thumbnail.png b/rtdata/images/Dark/actions/HDR-thumbnail.png new file mode 100644 index 000000000..182e603e8 Binary files /dev/null and b/rtdata/images/Dark/actions/HDR-thumbnail.png differ diff --git a/rtdata/images/Dark/actions/PixelShift-thumbnail.png b/rtdata/images/Dark/actions/PixelShift-thumbnail.png new file mode 100644 index 000000000..4bbea1aee Binary files /dev/null and b/rtdata/images/Dark/actions/PixelShift-thumbnail.png differ diff --git a/rtdata/images/Light/actions/HDR-thumbnail.png b/rtdata/images/Light/actions/HDR-thumbnail.png new file mode 100644 index 000000000..182e603e8 Binary files /dev/null and b/rtdata/images/Light/actions/HDR-thumbnail.png differ diff --git a/rtdata/images/Light/actions/PixelShift-thumbnail.png b/rtdata/images/Light/actions/PixelShift-thumbnail.png new file mode 100644 index 000000000..4bbea1aee Binary files /dev/null and b/rtdata/images/Light/actions/PixelShift-thumbnail.png differ diff --git a/rtdata/languages/Catala b/rtdata/languages/Catala index d006e1995..1e2127bd1 100644 --- a/rtdata/languages/Catala +++ b/rtdata/languages/Catala @@ -976,6 +976,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !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. +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_BYPASS_RAW_LMMSE_ITERATIONS;Bypass [raw] LMMSE Enhancement Steps @@ -1509,10 +1510,19 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !PROFILEPANEL_PINTERNAL;Neutral !PROGRESSBAR_NOIMAGES;No images found !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_FORCEFORMATOPTS;Force saving options !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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !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 !TP_BWMIX_ALGO;Algorithm OYCPM !TP_BWMIX_ALGO_LI;Linear diff --git a/rtdata/languages/Chinese (Simplified) b/rtdata/languages/Chinese (Simplified) index e58875107..6c1e54685 100644 --- a/rtdata/languages/Chinese (Simplified) +++ b/rtdata/languages/Chinese (Simplified) @@ -1042,6 +1042,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !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. !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. +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_RAW_DCB_ENHANCE;Bypass [raw] DCB Enhancement Steps !EXPORT_BYPASS_RAW_DCB_ITERATIONS;Bypass [raw] DCB Iterations @@ -1491,10 +1492,19 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !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. !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Chinese (Traditional) b/rtdata/languages/Chinese (Traditional) index 5a330fd13..10e5f974a 100644 --- a/rtdata/languages/Chinese (Traditional) +++ b/rtdata/languages/Chinese (Traditional) @@ -471,6 +471,7 @@ TP_WBALANCE_TEMPERATURE;色溫 !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1294,6 +1295,15 @@ TP_WBALANCE_TEMPERATURE;色溫 !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1304,8 +1314,8 @@ TP_WBALANCE_TEMPERATURE;色溫 !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Czech b/rtdata/languages/Czech index a7a743377..898ae93c2 100644 --- a/rtdata/languages/Czech +++ b/rtdata/languages/Czech @@ -2170,6 +2170,7 @@ ZOOMPANEL_ZOOMOUT;Oddálit\nZkratka: - !!!!!!!!!!!!!!!!!!!!!!!!! !DONT_SHOW_AGAIN;Don't show this message again. +!EXIFPANEL_SHOWALL;Show all !GIMP_PLUGIN_INFO;Welcome to the RawTherapee GIMP plugin!\nOnce you are done editing, simply close the main RawTherapee window and the image will be automatically imported in GIMP. !HISTORY_MSG_476;CAM02 - Temp out !HISTORY_MSG_477;CAM02 - Green out @@ -2194,6 +2195,15 @@ ZOOMPANEL_ZOOMOUT;Oddálit\nZkratka: - !PREFERENCES_LANG;Language !PREFERENCES_SAVE_TP_OPEN_NOW;Save tools collapsed/expanded state now !PREFERENCES_THEME;Theme +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !TP_COLORAPP_FREE;Free temp+green + CAT02 + [output] !TP_COLORAPP_NEUTRAL;Reset !TP_COLORAPP_NEUTRAL_TIP;Reset all sliders checkbox and curves to their default values diff --git a/rtdata/languages/Dansk b/rtdata/languages/Dansk index da080ee2b..3c6921967 100644 --- a/rtdata/languages/Dansk +++ b/rtdata/languages/Dansk @@ -463,6 +463,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1292,6 +1293,15 @@ TP_WBALANCE_TEMPERATURE;Temperatur !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1302,8 +1312,8 @@ TP_WBALANCE_TEMPERATURE;Temperatur !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 60a276a20..aa72b5757 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -2218,3 +2218,17 @@ ZOOMPANEL_ZOOMFITSCREEN;An Bildschirm anpassen\nTaste: f ZOOMPANEL_ZOOMIN;Hineinzoomen\nTaste: + ZOOMPANEL_ZOOMOUT;Herauszoomen\nTaste: - +!!!!!!!!!!!!!!!!!!!!!!!!! +! Untranslated keys follow; remove the ! prefix after an entry is translated. +!!!!!!!!!!!!!!!!!!!!!!!!! + +!EXIFPANEL_SHOWALL;Show all +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index 0ab6aae48..165b3de80 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -42,7 +42,8 @@ PREFERENCES_NAVGUIDEBRUSH;Navigator guide colour PREFERENCES_PRTPROFILE;Colour profile PREFERENCES_SELECTFONT_COLPICKER;Select Colour Picker's font PREFERENCES_TAB_COLORMGR;Colour Management -SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colours from the output profile. +SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colours from the Printer profile. +SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Colour Management. TOOLBAR_TOOLTIP_COLORPICKER;Lockable Colour Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a colour picker\nDrag it around while pressing the left mouse button\nDelete the colour picker with a right mouse button click\nDelete all colour pickers with Shift + Right mouse button click\nRight click away from any colour picker to go back to the Hand tool TOOLBAR_TOOLTIP_STRAIGHTEN;Straighten / fine rotation.\nShortcut: s\n\nIndicate the vertical or horizontal by drawing a guide line over the image preview. Angle of rotation will be shown next to the guide line. Centre of rotation is the geometrical centre of the image. TP_BWMIX_CC_ENABLED;Adjust complementary colour @@ -176,6 +177,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !EXIFPANEL_RESETALL;Reset All !EXIFPANEL_RESETALLHINT;Reset all tags to their original values. !EXIFPANEL_RESETHINT;Reset the selected tags to their original values. +!EXIFPANEL_SHOWALL;Show all !EXIFPANEL_SUBDIRECTORY;Subdirectory !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All @@ -1241,8 +1243,17 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !PROGRESSBAR_SAVETIFF;Saving TIFF file... !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) !QINFO_ISO;ISO !QINFO_NOEXIF;Exif data not available. +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FILEFORMAT;File format !SAVEDLG_FORCEFORMATOPTS;Force saving options @@ -1261,7 +1272,6 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index abad71651..25054bd30 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -72,6 +72,7 @@ !EXIFPANEL_RESETALL;Reset All !EXIFPANEL_RESETALLHINT;Reset all tags to their original values. !EXIFPANEL_RESETHINT;Reset the selected tags to their original values. +!EXIFPANEL_SHOWALL;Show all !EXIFPANEL_SUBDIRECTORY;Subdirectory !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All @@ -1181,8 +1182,17 @@ !PROGRESSBAR_SAVETIFF;Saving TIFF file... !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) !QINFO_ISO;ISO !QINFO_NOEXIF;Exif data not available. +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FILEFORMAT;File format !SAVEDLG_FORCEFORMATOPTS;Force saving options @@ -1201,8 +1211,8 @@ !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Espanol b/rtdata/languages/Espanol index 141a36c8b..8a83535b1 100644 --- a/rtdata/languages/Espanol +++ b/rtdata/languages/Espanol @@ -1515,6 +1515,7 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !DYNPROFILEEDITOR_NEW;New !DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule !DYNPROFILEEDITOR_PROFILE;Processing Profile +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1841,9 +1842,18 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !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 !TP_CBDL_AFT;After Black-and-White !TP_CBDL_BEF;Before Black-and-White diff --git a/rtdata/languages/Euskara b/rtdata/languages/Euskara index 2abf08f8b..dd3e410ed 100644 --- a/rtdata/languages/Euskara +++ b/rtdata/languages/Euskara @@ -463,6 +463,7 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1292,6 +1293,15 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1302,8 +1312,8 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 6c581d55b..001304c35 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -68,6 +68,7 @@ EXIFPANEL_RESET;Réinitialiser EXIFPANEL_RESETALL;Réinitialiser tout EXIFPANEL_RESETALLHINT;Réinitialise tous les tags à leur valeur initiale EXIFPANEL_RESETHINT;Réinitialise les données sélectionnées à la valeur initiale +EXIFPANEL_SHOWALL;Voir tout EXIFPANEL_SUBDIRECTORY;Sous-répertoire EXPORT_BYPASS;Étapes de traitement à ignorer EXPORT_BYPASS_ALL;Sélectionner / Désélectionner tout @@ -1153,8 +1154,17 @@ PROGRESSBAR_SAVEPNG;Enregistrement du fichier PNG... PROGRESSBAR_SAVETIFF;Enregistrement du fichier TIFF... PROGRESSBAR_SNAPSHOT_ADDED;Signet ajouté PROGRESSDLG_PROFILECHANGEDINBROWSER;Profil modifié dans le navigateur +QINFO_FRAMECOUNT;%2 images +QINFO_HDR;HDR / %2 image(s) QINFO_ISO;ISO QINFO_NOEXIF;Données EXIF non disponibles. +QINFO_PIXELSHIFT;PixelShift / %2 images +SAMPLEFORMAT_0;Format de donnée inconnu +SAMPLEFORMAT_1;8 bits non signé +SAMPLEFORMAT_2;16 bits non signé +SAMPLEFORMAT_4;LogLuv 24 bits +SAMPLEFORMAT_8;LogLuv 32 bits +SAMPLEFORMAT_16;32 bits à virgule flottante SAVEDLG_AUTOSUFFIX;Ajouter automatiquement un suffixe si le fichier existe déjà SAVEDLG_FILEFORMAT;Format de fichier SAVEDLG_FORCEFORMATOPTS;Forcer les options d'enregistrement diff --git a/rtdata/languages/Greek b/rtdata/languages/Greek index 631b789d9..f41040577 100644 --- a/rtdata/languages/Greek +++ b/rtdata/languages/Greek @@ -462,6 +462,7 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1291,6 +1292,15 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1301,8 +1311,8 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Hebrew b/rtdata/languages/Hebrew index 36eaa57b6..346a39cdc 100644 --- a/rtdata/languages/Hebrew +++ b/rtdata/languages/Hebrew @@ -463,6 +463,7 @@ TP_WBALANCE_TEMPERATURE;מידת חום !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1292,6 +1293,15 @@ TP_WBALANCE_TEMPERATURE;מידת חום !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1302,8 +1312,8 @@ TP_WBALANCE_TEMPERATURE;מידת חום !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Italiano b/rtdata/languages/Italiano index 2a2a4f761..4101355c0 100644 --- a/rtdata/languages/Italiano +++ b/rtdata/languages/Italiano @@ -1346,6 +1346,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !DYNPROFILEEDITOR_NEW;New !DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule !DYNPROFILEEDITOR_PROFILE;Processing Profile +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1712,9 +1713,18 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !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 !TP_CBDL_AFT;After Black-and-White !TP_CBDL_BEF;Before Black-and-White diff --git a/rtdata/languages/Japanese b/rtdata/languages/Japanese index 7665c03dd..787b5dfe6 100644 --- a/rtdata/languages/Japanese +++ b/rtdata/languages/Japanese @@ -1885,6 +1885,7 @@ ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - !DYNPROFILEEDITOR_NEW;New !DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule !DYNPROFILEEDITOR_PROFILE;Processing Profile +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_PIPELINE;Processing pipeline !EXPORT_USE_FAST_PIPELINE;Dedicated (full processing on resized image) @@ -2022,9 +2023,18 @@ ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - !PREFERENCES_THEME;Theme !PREFERENCES_TUNNELMETADATA;Copy Exif/IPTC/XMP unchanged to output file !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !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 !TP_CBDL_AFT;After Black-and-White !TP_CBDL_BEF;Before Black-and-White diff --git a/rtdata/languages/Latvian b/rtdata/languages/Latvian index a9565f70c..8dc2dc670 100644 --- a/rtdata/languages/Latvian +++ b/rtdata/languages/Latvian @@ -463,6 +463,7 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1292,6 +1293,15 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1302,8 +1312,8 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Magyar b/rtdata/languages/Magyar index 73ad45af0..d98d6e29c 100644 --- a/rtdata/languages/Magyar +++ b/rtdata/languages/Magyar @@ -891,6 +891,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !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. +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_BYPASS_RAW_LMMSE_ITERATIONS;Bypass [raw] LMMSE Enhancement Steps @@ -1447,6 +1448,15 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !PROGRESSBAR_NOIMAGES;No images found !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling !SAVEDLG_SUBSAMP_1;Best compression @@ -1455,8 +1465,8 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !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. !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Nederlands b/rtdata/languages/Nederlands index f75a8626e..754ba1573 100644 --- a/rtdata/languages/Nederlands +++ b/rtdata/languages/Nederlands @@ -2140,6 +2140,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !!!!!!!!!!!!!!!!!!!!!!!!! !DONT_SHOW_AGAIN;Don't show this message again. +!EXIFPANEL_SHOWALL;Show all !GIMP_PLUGIN_INFO;Welcome to the RawTherapee GIMP plugin!\nOnce you are done editing, simply close the main RawTherapee window and the image will be automatically imported in GIMP. !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_475;PS - Equalize channel @@ -2169,6 +2170,15 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !PREFERENCES_PROFILESAVELOCATION;Processing profile saving location !PREFERENCES_SAVE_TP_OPEN_NOW;Save tools collapsed/expanded state now !PREFERENCES_THEME;Theme +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !TP_COLORAPP_FREE;Free temp+green + CAT02 + [output] !TP_COLORAPP_NEUTRAL;Reset !TP_COLORAPP_NEUTRAL_TIP;Reset all sliders checkbox and curves to their default values diff --git a/rtdata/languages/Norsk BM b/rtdata/languages/Norsk BM index 7c12038a7..c270541d8 100644 --- a/rtdata/languages/Norsk BM +++ b/rtdata/languages/Norsk BM @@ -462,6 +462,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1291,6 +1292,15 @@ TP_WBALANCE_TEMPERATURE;Temperatur !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1301,8 +1311,8 @@ TP_WBALANCE_TEMPERATURE;Temperatur !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Polish b/rtdata/languages/Polish index 789a76eeb..7845247dc 100644 --- a/rtdata/languages/Polish +++ b/rtdata/languages/Polish @@ -1473,6 +1473,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !DYNPROFILEEDITOR_NEW;New !DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule !DYNPROFILEEDITOR_PROFILE;Processing Profile +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1789,9 +1790,18 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !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 !TP_CBDL_AFT;After Black-and-White !TP_CBDL_BEF;Before Black-and-White diff --git a/rtdata/languages/Polish (Latin Characters) b/rtdata/languages/Polish (Latin Characters) index a32059598..978fa96cf 100644 --- a/rtdata/languages/Polish (Latin Characters) +++ b/rtdata/languages/Polish (Latin Characters) @@ -1473,6 +1473,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !DYNPROFILEEDITOR_NEW;New !DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule !DYNPROFILEEDITOR_PROFILE;Processing Profile +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1789,9 +1790,18 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !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 !TP_CBDL_AFT;After Black-and-White !TP_CBDL_BEF;Before Black-and-White diff --git a/rtdata/languages/Portugues (Brasil) b/rtdata/languages/Portugues (Brasil) index b1d6b77d3..102f6ac89 100644 --- a/rtdata/languages/Portugues (Brasil) +++ b/rtdata/languages/Portugues (Brasil) @@ -463,6 +463,7 @@ TP_WBALANCE_TEMPERATURE;Temperatura !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1292,6 +1293,15 @@ TP_WBALANCE_TEMPERATURE;Temperatura !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1302,8 +1312,8 @@ TP_WBALANCE_TEMPERATURE;Temperatura !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Russian b/rtdata/languages/Russian index 2b09c7c65..908bc03df 100644 --- a/rtdata/languages/Russian +++ b/rtdata/languages/Russian @@ -1284,6 +1284,7 @@ ZOOMPANEL_ZOOMOUT;Удалить - !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. +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1669,9 +1670,18 @@ ZOOMPANEL_ZOOMOUT;Удалить - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !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 !TP_BWMIX_SET_RGBABS;Absolute RGB !TP_BWMIX_SET_RGBREL;Relative RGB diff --git a/rtdata/languages/Serbian (Cyrilic Characters) b/rtdata/languages/Serbian (Cyrilic Characters) index ec4c6597d..76c8d8693 100644 --- a/rtdata/languages/Serbian (Cyrilic Characters) +++ b/rtdata/languages/Serbian (Cyrilic Characters) @@ -1306,6 +1306,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !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. +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1700,8 +1701,17 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !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. +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_BL;Bottom-left !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 !TP_BWMIX_FILTER_TOOLTIP;The color filter simulates shots taken with a colored filter placed in front of the lens. Colored filters reduce the transmission of specific color ranges and therefore affect their lightness. E.g. a red filter darkens blue skies. diff --git a/rtdata/languages/Serbian (Latin Characters) b/rtdata/languages/Serbian (Latin Characters) index 5cc7873c5..603526a14 100644 --- a/rtdata/languages/Serbian (Latin Characters) +++ b/rtdata/languages/Serbian (Latin Characters) @@ -1306,6 +1306,7 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !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. +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1700,8 +1701,17 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !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. +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_BL;Bottom-left !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 !TP_BWMIX_FILTER_TOOLTIP;The color filter simulates shots taken with a colored filter placed in front of the lens. Colored filters reduce the transmission of specific color ranges and therefore affect their lightness. E.g. a red filter darkens blue skies. diff --git a/rtdata/languages/Slovak b/rtdata/languages/Slovak index ee719f656..6bacd9d7e 100644 --- a/rtdata/languages/Slovak +++ b/rtdata/languages/Slovak @@ -543,6 +543,7 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !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) !EXIFFILTER_FILETYPE;File type +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1333,6 +1334,15 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !PROGRESSBAR_NOIMAGES;No images found !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling !SAVEDLG_SUBSAMP_1;Best compression @@ -1341,8 +1351,8 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !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. !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Suomi b/rtdata/languages/Suomi index 571a3c084..413144a76 100644 --- a/rtdata/languages/Suomi +++ b/rtdata/languages/Suomi @@ -464,6 +464,7 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1293,6 +1294,15 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1302,8 +1312,8 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !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. !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Swedish b/rtdata/languages/Swedish index 87e0b81a6..cc459eaa1 100644 --- a/rtdata/languages/Swedish +++ b/rtdata/languages/Swedish @@ -1896,6 +1896,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !DYNPROFILEEDITOR_NEW;New !DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule !DYNPROFILEEDITOR_PROFILE;Processing Profile +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_PIPELINE;Processing pipeline !EXPORT_USE_FAST_PIPELINE;Dedicated (full processing on resized image) @@ -2011,6 +2012,15 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_THEME;Theme !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !TP_CBDL_METHOD;Process located !TP_COLORAPP_FREE;Free temp+green + CAT02 + [output] !TP_COLORAPP_NEUTRAL;Reset diff --git a/rtdata/languages/Turkish b/rtdata/languages/Turkish index 1e873db1f..5c98df27d 100644 --- a/rtdata/languages/Turkish +++ b/rtdata/languages/Turkish @@ -463,6 +463,7 @@ TP_WBALANCE_TEMPERATURE;Isı !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1292,6 +1293,15 @@ TP_WBALANCE_TEMPERATURE;Isı !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1301,8 +1311,8 @@ TP_WBALANCE_TEMPERATURE;Isı !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. !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!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. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/default b/rtdata/languages/default index 0f51938a0..7c7ad3b88 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -71,6 +71,7 @@ EXIFPANEL_RESET;Reset EXIFPANEL_RESETALL;Reset All EXIFPANEL_RESETALLHINT;Reset all tags to their original values. EXIFPANEL_RESETHINT;Reset the selected tags to their original values. +EXIFPANEL_SHOWALL;Show all EXIFPANEL_SUBDIRECTORY;Subdirectory EXPORT_BYPASS;Processing steps to bypass EXPORT_BYPASS_ALL;Select / Unselect All @@ -1304,8 +1305,17 @@ PROGRESSBAR_SAVEPNG;Saving PNG file... PROGRESSBAR_SAVETIFF;Saving TIFF file... PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +QINFO_FRAMECOUNT;%2 frames +QINFO_HDR;HDR / %2 frame(s) QINFO_ISO;ISO QINFO_NOEXIF;Exif data not available. +QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +SAMPLEFORMAT_0;Unknown data format +SAMPLEFORMAT_1;Unsigned 8 bits +SAMPLEFORMAT_2;Unsigned 16 bits +SAMPLEFORMAT_4;LogLuv 24 bits +SAMPLEFORMAT_8;LogLuv 32 bits +SAMPLEFORMAT_16;32 bits floating point SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists SAVEDLG_FILEFORMAT;File format SAVEDLG_FORCEFORMATOPTS;Force saving options diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc index 6b4a36c4b..469d18571 100644 --- a/rtengine/camconst.cc +++ b/rtengine/camconst.cc @@ -184,7 +184,7 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model) js = (cJSON *)cJSON_; CameraConst *cc = new CameraConst; - cc->make_model = Glib::ustring(make_model); + cc->make_model = make_model; ji = cJSON_GetObjectItem(js, "dcraw_matrix"); @@ -739,7 +739,7 @@ CameraConstantsStore::get(const char make[], const char model[]) key += " "; key += model; key = key.uppercase(); - std::map::iterator it; + std::map::iterator it; it = mCameraConstants.find(key); if (it == mCameraConstants.end()) { diff --git a/rtengine/camconst.h b/rtengine/camconst.h index 31b65f3e8..47c8d8bee 100644 --- a/rtengine/camconst.h +++ b/rtengine/camconst.h @@ -17,7 +17,7 @@ struct camera_const_levels { class CameraConst { private: - Glib::ustring make_model; + std::string make_model; short dcraw_matrix[12]; int raw_crop[4]; int raw_mask[8][4]; @@ -48,7 +48,7 @@ public: class CameraConstantsStore { private: - std::map mCameraConstants; + std::map mCameraConstants; CameraConstantsStore(); bool parse_camera_constants_file(Glib::ustring filename); diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index 43aa98480..f9cdd1c73 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -696,7 +696,9 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : return; } - std::unique_ptr tagDir(ExifManager::parseTIFF(file, false)); + ExifManager exifManager(file, nullptr, true); + exifManager.parseTIFF(false); + std::unique_ptr tagDir(exifManager.roots.at(0)); Tag* tag = tagDir->getTag(toUnderlying(TagKey::CALIBRATION_ILLUMINANT_1)); light_source_1 = diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc index b9841c86b..a8d31f0ac 100644 --- a/rtengine/dfmanager.cc +++ b/rtengine/dfmanager.cc @@ -377,11 +377,7 @@ dfInfo* DFManager::addFileInfo (const Glib::ustring& filename, bool pool) return &(iter->second); } - RawMetaDataLocation rml; - rml.exifBase = ri.get_exifBase(); - rml.ciffBase = ri.get_ciffBase(); - rml.ciffLength = ri.get_ciffLen(); - ImageData idata(filename, &rml); + FramesData idata(filename, std::unique_ptr(new RawMetaDataLocation(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen())), true); /* Files are added in the map, divided by same maker/model,ISO and shutter*/ std::string key(dfInfo::key(((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed())); iter = dfList.find(key); diff --git a/rtengine/dynamicprofile.cc b/rtengine/dynamicprofile.cc index 5ac408da5..1afc04446 100644 --- a/rtengine/dynamicprofile.cc +++ b/rtengine/dynamicprofile.cc @@ -72,7 +72,7 @@ bool DynamicProfileRule::operator< (const DynamicProfileRule &other) const } -bool DynamicProfileRule::matches (const rtengine::ImageMetaData *im) const +bool DynamicProfileRule::matches (const rtengine::FramesMetaData *im) const { return (iso (im->getISOSpeed()) && fnumber (im->getFNumber()) diff --git a/rtengine/dynamicprofile.h b/rtengine/dynamicprofile.h index cfe46d9ba..4e6bbbba9 100644 --- a/rtengine/dynamicprofile.h +++ b/rtengine/dynamicprofile.h @@ -48,7 +48,7 @@ public: }; DynamicProfileRule(); - bool matches (const rtengine::ImageMetaData *im) const; + bool matches (const rtengine::FramesMetaData *im) const; bool operator< (const DynamicProfileRule &other) const; int serial_number; diff --git a/rtengine/ffmanager.cc b/rtengine/ffmanager.cc index d0edffb17..028b8a79a 100644 --- a/rtengine/ffmanager.cc +++ b/rtengine/ffmanager.cc @@ -332,11 +332,7 @@ ffInfo* FFManager::addFileInfo (const Glib::ustring& filename, bool pool) return &(iter->second); } - RawMetaDataLocation rml; - rml.exifBase = ri.get_exifBase(); - rml.ciffBase = ri.get_ciffBase(); - rml.ciffLength = ri.get_ciffLen(); - ImageData idata(filename, &rml); + FramesData idata(filename, std::unique_ptr(new RawMetaDataLocation(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen())), true); /* Files are added in the map, divided by same maker/model,lens and aperture*/ std::string key(ffInfo::key(idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber())); iter = ffList.find(key); diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 5faa6175e..ed8e0b52b 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -18,9 +18,14 @@ */ #include #include +#include #include "imagedata.h" #include "iptcpairs.h" +#include "imagesource.h" +#include "rt_math.h" + +#define PRINT_HDR_PS_DETECTION 0 using namespace rtengine; @@ -40,87 +45,25 @@ Glib::ustring to_utf8 (const std::string& str) } -ImageMetaData* ImageMetaData::fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml) +FramesMetaData* FramesMetaData::fromFile (const Glib::ustring& fname, std::unique_ptr rml, bool firstFrameOnly) { - - return new ImageData (fname, rml); + return new FramesData (fname, std::move(rml), firstFrameOnly); } -ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) : iso_speed(0), aperture(0.), shutter(0.) +FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* rootDir, rtexif::TagDirectory* firstRootDir) + : frameRootDir(frameRootDir_), iptc(nullptr), time(), timeStamp(), iso_speed(0), aperture(0.), focal_len(0.), focal_len35mm(0.), focus_dist(0.f), + shutter(0.), expcomp(0.), make("Unknown"), model("Unknown"), orientation("Unknown"), lens("Unknown"), + sampleFormat(IIOSF_UNKNOWN), isPixelShift(false), isHDR(false) { memset (&time, 0, sizeof(time)); - root = nullptr; - iptc = nullptr; - if (ri && (ri->exifBase >= 0 || ri->ciffBase >= 0)) { - FILE* f = g_fopen (fname.c_str (), "rb"); - - if (f) { - if (ri->exifBase >= 0) { - root = rtexif::ExifManager::parse (f, ri->exifBase); - - if (root) { - rtexif::Tag* t = root->getTag (0x83BB); - - if (t) { - iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); - } - } - } else if (ri->ciffBase >= 0) { - root = rtexif::ExifManager::parseCIFF (f, ri->ciffBase, ri->ciffLength); - } - - fclose (f); - extractInfo (); - } - } else if (hasJpegExtension(fname)) { - FILE* f = g_fopen (fname.c_str (), "rb"); - - if (f) { - root = rtexif::ExifManager::parseJPEG (f); - extractInfo (); - fclose (f); - FILE* ff = g_fopen (fname.c_str (), "rb"); - iptc = iptc_data_new_from_jpeg_file (ff); - fclose (ff); - } - } else if (hasTiffExtension(fname)) { - FILE* f = g_fopen (fname.c_str (), "rb"); - - if (f) { - root = rtexif::ExifManager::parseTIFF (f); - fclose (f); - extractInfo (); - - if (root) { - rtexif::Tag* t = root->getTag (0x83BB); - - if (t) { - iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); - } - } - } - } else { - root = new rtexif::TagDirectory (); - shutter = 0; - aperture = 0; - iso_speed = 0; - lens = "Unknown"; - make = "Unknown"; - model = "Unknown"; - orientation = "Unknown"; - expcomp = 0; - focal_len = 0; - } -} - -void ImageData::extractInfo () -{ - - if (!root) { + if (!frameRootDir) { return; } + rtexif::Tag* tag; + rtexif::TagDirectory* newFrameRootDir = frameRootDir; + memset(&time, 0, sizeof(time)); timeStamp = 0; iso_speed = 0; @@ -136,8 +79,18 @@ void ImageData::extractInfo () orientation.clear(); lens.clear(); - if (root->getTag("Make")) { - make = root->getTag ("Make")->valueToString(); + tag = newFrameRootDir->findTag("Make"); + if (!tag) { + newFrameRootDir = rootDir; + tag = newFrameRootDir->findTag("Make"); + if (!tag) { + // For some raw files (like Canon's CR2 files), the metadata are contained in the first root directory + newFrameRootDir = firstRootDir; + tag = newFrameRootDir->findTag("Make"); + } + } + if (tag) { + make = tag->valueToString(); // Same dcraw treatment for (const auto& corp : { "Canon", @@ -169,8 +122,9 @@ void ImageData::extractInfo () make.erase(make.find_last_not_of(' ') + 1); } - if (root->getTag("Model")) { - model = root->getTag("Model")->valueToString(); + tag = newFrameRootDir->findTagUpward("Model"); + if (tag) { + model = tag->valueToString(); } if (!model.empty()) { @@ -202,61 +156,68 @@ void ImageData::extractInfo () model = "Unknown"; } - if (root->getTag ("Orientation")) { - orientation = root->getTag ("Orientation")->valueToString (); + tag = newFrameRootDir->findTagUpward("Orientation"); + if (tag) { + orientation = tag->valueToString (); + } + + tag = newFrameRootDir->findTagUpward("MakerNote"); + rtexif::TagDirectory* mnote = nullptr; + if (tag) { + mnote = tag->getDirectory(); } rtexif::TagDirectory* exif = nullptr; - - if (root->getTag ("Exif")) { - exif = root->getTag ("Exif")->getDirectory (); + tag = newFrameRootDir->findTagUpward("Exif"); + if (tag) { + exif = tag->getDirectory (); } if (exif) { // standard exif tags - if (exif->getTag ("ShutterSpeedValue")) { - shutter = exif->getTag ("ShutterSpeedValue")->toDouble (); + if ((tag = exif->getTag ("ShutterSpeedValue"))) { + shutter = tag->toDouble (); } - if (exif->getTag ("ExposureTime")) { - shutter = exif->getTag ("ExposureTime")->toDouble (); + if ((tag = exif->getTag ("ExposureTime"))) { + shutter = tag->toDouble (); } - if (exif->getTag ("ApertureValue")) { - aperture = exif->getTag ("ApertureValue")->toDouble (); + if ((tag = exif->getTag ("ApertureValue"))) { + aperture = tag->toDouble (); } - if (exif->getTag ("FNumber")) { - aperture = exif->getTag ("FNumber")->toDouble (); + if ((tag = exif->getTag ("FNumber"))) { + aperture = tag->toDouble (); } - if (exif->getTag ("ExposureBiasValue")) { - expcomp = exif->getTag ("ExposureBiasValue")->toDouble (); + if ((tag = exif->getTag ("ExposureBiasValue"))) { + expcomp = tag->toDouble (); } - if (exif->getTag ("FocalLength")) { - focal_len = exif->getTag ("FocalLength")->toDouble (); + if ((tag = exif->getTag ("FocalLength"))) { + focal_len = tag->toDouble (); } - if (exif->getTag ("FocalLengthIn35mmFilm")) { - focal_len35mm = exif->getTag ("FocalLengthIn35mmFilm")->toDouble (); + if ((tag = exif->getTag ("FocalLengthIn35mmFilm"))) { + focal_len35mm = tag->toDouble (); } // Focus distance from EXIF or XMP. MakerNote ones are scattered and partly encrypted int num = -3, denom = -3; // First try, offical EXIF. Set by Adobe on some DNGs - rtexif::Tag* pDst = exif->getTag("SubjectDistance"); + tag = exif->getTag("SubjectDistance"); - if (pDst) { + if (tag) { int num, denom; - pDst->toRational(num, denom); + tag->toRational(num, denom); } else { // Second try, XMP data char sXMPVal[64]; - if (root->getXMPTagValue("aux:ApproximateFocusDistance", sXMPVal)) { + if (newFrameRootDir->getXMPTagValue("aux:ApproximateFocusDistance", sXMPVal)) { sscanf(sXMPVal, "%d/%d", &num, &denom); } } @@ -269,12 +230,12 @@ void ImageData::extractInfo () } } - if (exif->getTag ("ISOSpeedRatings")) { - iso_speed = exif->getTag ("ISOSpeedRatings")->toDouble (); + if ((tag = exif->getTag ("ISOSpeedRatings"))) { + iso_speed = tag->toDouble (); } - if (exif->getTag ("DateTimeOriginal")) { - if (sscanf ((const char*)exif->getTag("DateTimeOriginal")->getValue(), "%d:%d:%d %d:%d:%d", &time.tm_year, &time.tm_mon, &time.tm_mday, &time.tm_hour, &time.tm_min, &time.tm_sec) == 6) { + if ((tag = exif->getTag ("DateTimeOriginal"))) { + if (sscanf ((const char*)tag->getValue(), "%d:%d:%d %d:%d:%d", &time.tm_year, &time.tm_mon, &time.tm_mday, &time.tm_hour, &time.tm_min, &time.tm_sec) == 6) { time.tm_year -= 1900; time.tm_mon -= 1; time.tm_isdst = -1; @@ -282,14 +243,14 @@ void ImageData::extractInfo () } } - rtexif::Tag *snTag = exif->findTag ("SerialNumber"); + tag = exif->findTag ("SerialNumber"); - if(!snTag) { - snTag = exif->findTag ("InternalSerialNumber"); + if(!tag) { + tag = exif->findTag ("InternalSerialNumber"); } - if ( snTag ) { - serial = snTag->valueToString(); + if (tag) { + serial = tag->valueToString(); } // guess lens... @@ -313,12 +274,10 @@ void ImageData::extractInfo () } if (lens == "Unknown") { - rtexif::Tag* mnoteTag = root->findTag("MakerNote"); - if (mnoteTag) { - rtexif::TagDirectory* mnote = mnoteTag->getDirectory(); + if (mnote) { - if (mnote && !make.compare (0, 5, "NIKON")) { + if (!make.compare (0, 5, "NIKON")) { // ISO at max value supported, check manufacturer specific if (iso_speed == 65535 || iso_speed == 0) { rtexif::Tag* isoTag = mnote->getTagP("ISOInfo/ISO"); @@ -406,7 +365,7 @@ void ImageData::extractInfo () } } } - } else if (mnote && !make.compare (0, 5, "Canon")) { + } else if (!make.compare (0, 5, "Canon")) { // ISO at max value supported, check manufacturer specific if (iso_speed == 65535 || iso_speed == 0) { rtexif::Tag* baseIsoTag = mnote->getTagP("CanonShotInfo/BaseISO"); @@ -440,7 +399,7 @@ void ImageData::extractInfo () } } } - } else if (mnote && (!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX")))) { + } else if (!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX"))) { // ISO at max value supported, check manufacturer specific if (iso_speed == 65535 || iso_speed == 0) { rtexif::Tag* baseIsoTag = mnote->getTag("ISO"); @@ -475,7 +434,7 @@ void ImageData::extractInfo () if (mnote->getTag ("LensID")) { lens = mnote->getTag ("LensID")->valueToString (); } - } else if (mnote && !make.compare (0, 7, "OLYMPUS")) { + } else if (!make.compare (0, 7, "OLYMPUS")) { if (mnote->getTag ("Equipment")) { rtexif::TagDirectory* eq = mnote->getTag ("Equipment")->getDirectory (); @@ -504,31 +463,168 @@ void ImageData::extractInfo () } } } + + rtexif::Tag* t = newFrameRootDir->getTag(0x83BB); + if (t) { + iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); + } + + + // ----------------------- Special file type detection (HDR, PixelShift) ------------------------ + + + uint16 bitspersample = 0, sampleformat = 0, photometric = 0, compression = 0; + rtexif::Tag* bps = frameRootDir->findTag("BitsPerSample"); + rtexif::Tag* spp = frameRootDir->findTag("SamplesPerPixel"); + rtexif::Tag* sf = frameRootDir->findTag("SampleFormat"); + rtexif::Tag* pi = frameRootDir->findTag("PhotometricInterpretation"); + rtexif::Tag* c = frameRootDir->findTag("Compression"); + + if (mnote && (!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX")))) { + rtexif::Tag* hdr = mnote->findTag("HDR"); + if (hdr) { + if (hdr->toInt() > 0 && hdr->toInt(2) > 0) { + isHDR = true; +#if PRINT_HDR_PS_DETECTION + printf("HDR detected ! -> \"HDR\" tag found\n"); +#endif + } + } else { + rtexif::Tag* dm = mnote->findTag("DriveMode"); + if (dm) { + char buffer[60]; + dm->toString(buffer, 3); + buffer[3] = 0; + if (!strcmp(buffer, "HDR")) { + isHDR = true; +#if PRINT_HDR_PS_DETECTION + printf("HDR detected ! -> DriveMode = \"HDR\"\n"); +#endif + } + } + } + + if (!isHDR) { + rtexif::Tag* q = mnote->findTag("Quality"); + if (q && q->toInt() == 7) { + isPixelShift = true; +#if PRINT_HDR_PS_DETECTION + printf("PixelShift detected ! -> \"Quality\" = 7\n"); +#endif + } + } + } + + sampleFormat = IIOSF_UNKNOWN; + + if (!sf) + /* + * WARNING: This is a dirty hack! + * We assume that files which doesn't contain the TIFFTAG_SAMPLEFORMAT tag + * (which is the case with uncompressed TIFFs produced by RT!) are RGB files, + * but that may be not true. --- Hombre + */ + { + sampleformat = SAMPLEFORMAT_UINT; + } else { + sampleformat = sf->toInt(); + } + + if ((!bps & !spp) || !pi) { + return; + } + + bitspersample = bps->toInt(); + + photometric = pi->toInt(); + if (photometric == PHOTOMETRIC_LOGLUV) { + if (!c) { + compression = COMPRESSION_NONE; + } else { + compression = c->toInt(); + } + } + + if (photometric == PHOTOMETRIC_RGB || photometric == PHOTOMETRIC_MINISBLACK) { + if (sampleformat == SAMPLEFORMAT_INT || sampleformat == SAMPLEFORMAT_UINT) { + if (bitspersample == 8) { + sampleFormat = IIOSF_UNSIGNED_CHAR; + } else if (bitspersample <= 16) { + sampleFormat = IIOSF_UNSIGNED_SHORT; + } + } else if (sampleformat == SAMPLEFORMAT_IEEEFP) { + /* + * Not yet supported + * + if (bitspersample==16) { + sampleFormat = IIOSF_HALF; + isHDR = true; + }*/ + if (bitspersample == 32) { + sampleFormat = IIOSF_FLOAT; + isHDR = true; +#if PRINT_HDR_PS_DETECTION + printf("HDR detected ! -> sampleFormat = %d\n", sampleFormat); +#endif + } + } + } else if (photometric == PHOTOMETRIC_CFA) { + if (sampleformat == SAMPLEFORMAT_IEEEFP) { + sampleFormat = IIOSF_FLOAT; + isHDR = true; +#if PRINT_HDR_PS_DETECTION + printf("HDR detected ! -> sampleFormat = %d\n", sampleFormat); +#endif + } else if (sampleformat == SAMPLEFORMAT_INT || sampleformat == SAMPLEFORMAT_UINT) { + if (bitspersample == 8) { // shouldn't occur... + sampleFormat = IIOSF_UNSIGNED_CHAR; + } else if (bitspersample <= 16) { + sampleFormat = IIOSF_UNSIGNED_SHORT; + } + } + } else if (photometric == PHOTOMETRIC_LOGLUV) { + if (compression == COMPRESSION_SGILOG24) { + sampleFormat = IIOSF_LOGLUV24; + isHDR = true; +#if PRINT_HDR_PS_DETECTION + printf("HDR detected ! -> sampleFormat = %d\n", sampleFormat); +#endif + } else if (compression == COMPRESSION_SGILOG) { + sampleFormat = IIOSF_LOGLUV32; + isHDR = true; +#if PRINT_HDR_PS_DETECTION + printf("HDR detected ! -> sampleFormat = %d\n", sampleFormat); +#endif + } + } } -ImageData::~ImageData () +FrameData::~FrameData () { - delete root; - if (iptc) { iptc_data_free (iptc); } } -const procparams::IPTCPairs ImageData::getIPTCData () const +procparams::IPTCPairs FrameData::getIPTCData () const +{ + return getIPTCData(iptc); +} + +procparams::IPTCPairs FrameData::getIPTCData (IptcData* iptc_) { procparams::IPTCPairs iptcc; - if (!iptc) { + if (!iptc_) { return iptcc; } unsigned char buffer[2100]; for (int i = 0; i < 16; i++) { - IptcDataSet* ds = iptc_data_get_next_dataset (iptc, nullptr, IPTC_RECORD_APP_2, strTags[i].tag); + IptcDataSet* ds = iptc_data_get_next_dataset (iptc_, nullptr, IPTC_RECORD_APP_2, strTags[i].tag); if (ds) { iptc_dataset_get_data (ds, buffer, 2100); @@ -543,7 +639,7 @@ const procparams::IPTCPairs ImageData::getIPTCData () const IptcDataSet* ds = nullptr; std::vector keywords; - while ((ds = iptc_data_get_next_dataset (iptc, ds, IPTC_RECORD_APP_2, IPTC_TAG_KEYWORDS))) { + while ((ds = iptc_data_get_next_dataset (iptc_, ds, IPTC_RECORD_APP_2, IPTC_TAG_KEYWORDS))) { iptc_dataset_get_data (ds, buffer, 2100); keywords.push_back (to_utf8((char*)buffer)); } @@ -552,7 +648,7 @@ const procparams::IPTCPairs ImageData::getIPTCData () const ds = nullptr; std::vector suppCategories; - while ((ds = iptc_data_get_next_dataset (iptc, ds, IPTC_RECORD_APP_2, IPTC_TAG_SUPPL_CATEGORY))) { + while ((ds = iptc_data_get_next_dataset (iptc_, ds, IPTC_RECORD_APP_2, IPTC_TAG_SUPPL_CATEGORY))) { iptc_dataset_get_data (ds, buffer, 2100); suppCategories.push_back (to_utf8((char*)buffer)); iptc_dataset_unref (ds); @@ -562,10 +658,269 @@ const procparams::IPTCPairs ImageData::getIPTCData () const return iptcc; } + +bool FrameData::getPixelShift () const +{ + return isPixelShift; +} +bool FrameData::getHDR () const +{ + return isHDR; +} +IIOSampleFormat FrameData::getSampleFormat () const +{ + return sampleFormat; +} +rtexif::TagDirectory* FrameData::getExifData () const +{ + return frameRootDir; +} +bool FrameData::hasExif () const +{ + return frameRootDir && frameRootDir->getCount(); +} +bool FrameData::hasIPTC () const +{ + return iptc; +} +tm FrameData::getDateTime () const +{ + return time; +} +time_t FrameData::getDateTimeAsTS () const +{ + return timeStamp; +} +int FrameData::getISOSpeed () const +{ + return iso_speed; +} +double FrameData::getFNumber () const +{ + return aperture; +} +double FrameData::getFocalLen () const +{ + return focal_len; +} +double FrameData::getFocalLen35mm () const +{ + return focal_len35mm; +} +float FrameData::getFocusDist () const +{ + return focus_dist; +} +double FrameData::getShutterSpeed () const +{ + return shutter; +} +double FrameData::getExpComp () const +{ + return expcomp; +} +std::string FrameData::getMake () const +{ + return make; +} +std::string FrameData::getModel () const +{ + return model; +} +std::string FrameData::getLens () const +{ + return lens; +} +std::string FrameData::getSerialNumber () const +{ + return serial; +} +std::string FrameData::getOrientation () const +{ + return orientation; +} + + + +void FramesData::setDCRawFrameCount (unsigned int frameCount) +{ + dcrawFrameCount = frameCount; +} + +unsigned int FramesData::getRootCount () const +{ + return roots.size(); +} + +unsigned int FramesData::getFrameCount () const +{ + return dcrawFrameCount ? dcrawFrameCount : frames.size(); +} + +FrameData *FramesData::getFrameData (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? nullptr : frames.at(frame); +} + +bool FramesData::getPixelShift (unsigned int frame) const +{ + // So far only Pentax provide multi-frame HDR file. + // Only the first frame contains the HDR tag + // If more brand have to be supported, this rule may need + // to evolve + + //return frames.at(frame)->getPixelShift (); + return frames.empty() || frame >= frames.size() ? false : frames.at(0)->getPixelShift (); +} +bool FramesData::getHDR (unsigned int frame) const +{ + // So far only Pentax provide multi-frame HDR file. + // Only the first frame contains the HDR tag + // If more brand have to be supported, this rule may need + // to evolve + + //return frames.at(frame)->getHDR (); + return frames.empty() || frame >= frames.size() ? false : frames.at(0)->getHDR (); +} + +IIOSampleFormat FramesData::getSampleFormat (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? IIOSF_UNKNOWN : frames.at(frame)->getSampleFormat (); +} + +rtexif::TagDirectory* FramesData::getFrameExifData (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? nullptr : frames.at(frame)->getExifData (); +} + +rtexif::TagDirectory* FramesData::getBestExifData (ImageSource *imgSource, procparams::RAWParams *rawParams) const +{ + rtexif::TagDirectory *td = nullptr; + if (frames.empty()) { + return nullptr; + } + if (imgSource && rawParams) { + eSensorType sensorType = imgSource->getSensorType(); + unsigned int imgNum = 0; + if (sensorType == ST_BAYER) { + imgNum = rtengine::LIM(rawParams->bayersensor.imageNum, 0, frames.size() - 1); + /* + // might exist someday ? + } else if (sensorType == ST_FUJI_XTRANS) { + imgNum = rtengine::LIM(rawParams->xtranssensor.imageNum, 0, frames.size() - 1); + } else if (sensorType == ST_NONE && !imgSource->isRAW()) { + // standard image multiframe support should come here (when implemented in GUI) + */ + } + + frames[imgNum]->getExifData (); + + td = getFrameExifData (imgNum); + rtexif::Tag* makeTag; + if (td && (makeTag = td->findTag("Make", true))) { + td = makeTag->getParent(); + } else { + td = getRootExifData(0); + } + } + return td; +} + +rtexif::TagDirectory* FramesData::getRootExifData (unsigned int root) const +{ + return roots.empty() || root >= roots.size() ? nullptr : roots.at(root); +} + +procparams::IPTCPairs FramesData::getIPTCData (unsigned int frame) const +{ + if (frame < frames.size() && frames.at(frame)->hasIPTC()) { + return frames.at(frame)->getIPTCData(); + } else { + if (iptc) { + return FrameData::getIPTCData(iptc); + } else { + procparams::IPTCPairs emptyPairs; + return emptyPairs; + } + } +} + +bool FramesData::hasExif (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? false : frames.at(frame)->hasExif (); +} +bool FramesData::hasIPTC (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? false : frames.at(frame)->hasIPTC (); +} + +tm FramesData::getDateTime (unsigned int frame) const +{ + if (frames.empty() || frame >= frames.size() ) { + tm emptytm = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + return emptytm; + } else { + return frames.at(frame)->getDateTime (); + } +} +time_t FramesData::getDateTimeAsTS(unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? 0 : frames.at(frame)->getDateTimeAsTS (); +} +int FramesData::getISOSpeed (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? 0 : frames.at(frame)->getISOSpeed (); +} +double FramesData::getFNumber (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? 0. : frames.at(frame)->getFNumber (); +} +double FramesData::getFocalLen (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? 0. : frames.at(frame)->getFocalLen (); +} +double FramesData::getFocalLen35mm (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? 0. : frames.at(frame)->getFocalLen35mm (); +} +float FramesData::getFocusDist (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? 0.f : frames.at(frame)->getFocusDist (); +} +double FramesData::getShutterSpeed (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? 0. : frames.at(frame)->getShutterSpeed (); +} +double FramesData::getExpComp (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? 0. : frames.at(frame)->getExpComp (); +} +std::string FramesData::getMake (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? std::string() : frames.at(frame)->getMake (); +} +std::string FramesData::getModel (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? std::string() : frames.at(frame)->getModel (); +} +std::string FramesData::getLens (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? std::string() : frames.at(frame)->getLens (); +} +std::string FramesData::getSerialNumber (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? std::string() : frames.at(frame)->getSerialNumber (); +} +std::string FramesData::getOrientation (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? std::string() : frames.at(frame)->getOrientation (); +} + + //------inherited functions--------------// -std::string ImageMetaData::apertureToString (double aperture) +std::string FramesMetaData::apertureToString (double aperture) { char buffer[256]; @@ -573,7 +928,7 @@ std::string ImageMetaData::apertureToString (double aperture) return buffer; } -std::string ImageMetaData::shutterToString (double shutter) +std::string FramesMetaData::shutterToString (double shutter) { char buffer[256]; @@ -587,7 +942,7 @@ std::string ImageMetaData::shutterToString (double shutter) return buffer; } -std::string ImageMetaData::expcompToString (double expcomp, bool maskZeroexpcomp) +std::string FramesMetaData::expcompToString (double expcomp, bool maskZeroexpcomp) { char buffer[256]; @@ -605,7 +960,7 @@ std::string ImageMetaData::expcompToString (double expcomp, bool maskZeroexpcomp } } -double ImageMetaData::shutterFromString (std::string s) +double FramesMetaData::shutterFromString (std::string s) { size_t i = s.find_first_of ('/'); @@ -617,7 +972,7 @@ double ImageMetaData::shutterFromString (std::string s) } } -double ImageMetaData::apertureFromString (std::string s) +double FramesMetaData::apertureFromString (std::string s) { return atof (s.c_str()); @@ -685,3 +1040,98 @@ failure: } } + +FramesData::FramesData (const Glib::ustring& fname, std::unique_ptr rml, bool firstFrameOnly, bool loadAll) : + iptc(nullptr), dcrawFrameCount (0) +{ + if (rml && (rml->exifBase >= 0 || rml->ciffBase >= 0)) { + FILE* f = g_fopen (fname.c_str (), "rb"); + + if (f) { + const bool has_rml_exif_base = rml->exifBase >= 0; + rtexif::ExifManager exifManager (f, std::move(rml), firstFrameOnly); + + if (has_rml_exif_base) { + if (exifManager.f && exifManager.rml) { + if (exifManager.rml->exifBase >= 0) { + exifManager.parseRaw (); + + } else if (exifManager.rml->ciffBase >= 0) { + exifManager.parseCIFF (); + } + } + + // copying roots + roots = exifManager.roots; + + // creating FrameData + for (auto currFrame : exifManager.frames) { + FrameData* fd = new FrameData(currFrame, currFrame->getRoot(), roots.at(0)); + + frames.push_back(fd); + } + for (auto currRoot : roots) { + rtexif::Tag* t = currRoot->getTag(0x83BB); + + if (t && !iptc) { + iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); + break; + } + } + } + fclose (f); + } + } else if (hasJpegExtension(fname)) { + FILE* f = g_fopen (fname.c_str (), "rb"); + + if (f) { + rtexif::ExifManager exifManager (f, std::move(rml), true); + if (exifManager.f) { + exifManager.parseJPEG (); + roots = exifManager.roots; + for (auto currFrame : exifManager.frames) { + FrameData* fd = new FrameData(currFrame, currFrame->getRoot(), roots.at(0)); + frames.push_back(fd); + } + rewind (exifManager.f); // Not sure this is necessary + iptc = iptc_data_new_from_jpeg_file (exifManager.f); + } + fclose (f); + } + } else if (hasTiffExtension(fname)) { + FILE* f = g_fopen (fname.c_str (), "rb"); + + if (f) { + rtexif::ExifManager exifManager (f, std::move(rml), firstFrameOnly); + + exifManager.parseTIFF(); + + // creating FrameData + for (auto currFrame : exifManager.frames) { + FrameData* fd = new FrameData(currFrame, currFrame->getRoot(), roots.at(0)); + + frames.push_back(fd); + } + for (auto currRoot : roots) { + rtexif::Tag* t = currRoot->getTag(0x83BB); + + if (t && !iptc) { + iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); + break; + } + } + fclose (f); + } + } +} + +FramesData::~FramesData () +{ + for (auto currRoot : roots) { + delete currRoot; + } + + if (iptc) { + iptc_data_free (iptc); + } +} diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index f28a49a2f..2da97a5d1 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -31,11 +31,11 @@ namespace rtengine { -class ImageData : public ImageMetaData +class FrameData { protected: - rtexif::TagDirectory* root; + rtexif::TagDirectory* frameRootDir; IptcData* iptc; struct tm time; @@ -49,84 +49,84 @@ protected: std::string make, model, serial; std::string orientation; std::string lens; + IIOSampleFormat sampleFormat; - void extractInfo (); + // each frame has the knowledge of "being an" + // or "being part of an" HDR or PS image + bool isPixelShift; + bool isHDR; public: - ImageData (Glib::ustring fname, RawMetaDataLocation* rml = nullptr); - virtual ~ImageData (); + FrameData (rtexif::TagDirectory* frameRootDir, rtexif::TagDirectory* rootDir, rtexif::TagDirectory* firstRootDir); + virtual ~FrameData (); - const rtexif::TagDirectory* getExifData () const - { - return root; - } - const procparams::IPTCPairs getIPTCData () const; - - bool hasExif () const - { - return root && root->getCount(); - } - bool hasIPTC () const - { - return iptc; - } - - struct tm getDateTime () const { - return time; - } - time_t getDateTimeAsTS() const - { - return timeStamp; - } - int getISOSpeed () const - { - return iso_speed; - } - double getFNumber () const - { - return aperture; - } - double getFocalLen () const - { - return focal_len; - } - double getFocalLen35mm () const - { - return focal_len35mm; - } - float getFocusDist () const - { - return focus_dist; - } - double getShutterSpeed () const - { - return shutter; - } - double getExpComp () const - { - return expcomp; - } - std::string getMake () const - { - return make; - } - std::string getModel () const - { - return model; - } - std::string getLens () const - { - return lens; - } - std::string getSerialNumber () const - { - return serial; - } - std::string getOrientation () const - { - return orientation; - } + bool getPixelShift () const; + bool getHDR () const; + IIOSampleFormat getSampleFormat () const; + rtexif::TagDirectory* getExifData () const; + procparams::IPTCPairs getIPTCData () const; + static procparams::IPTCPairs getIPTCData (IptcData* iptc_); + bool hasExif () const; + bool hasIPTC () const; + tm getDateTime () const; + time_t getDateTimeAsTS () const; + int getISOSpeed () const; + double getFNumber () const; + double getFocalLen () const; + double getFocalLen35mm () const; + float getFocusDist () const; + double getShutterSpeed () const; + double getExpComp () const; + std::string getMake () const; + std::string getModel () const; + std::string getLens () const; + std::string getSerialNumber () const; + std::string getOrientation () const; }; + +class FramesData : public FramesMetaData { +private: + // frame's root IFD, can be a file root IFD or a SUB-IFD + std::vector frames; + // root IFD in the file + std::vector roots; + IptcData* iptc; + unsigned int dcrawFrameCount; + +public: + FramesData (const Glib::ustring& fname, std::unique_ptr rml = nullptr, bool firstFrameOnly = false, bool loadAll = false); + ~FramesData (); + + void setDCRawFrameCount (unsigned int frameCount); + unsigned int getRootCount () const; + unsigned int getFrameCount () const; + FrameData *getFrameData (unsigned int frame) const; + bool getPixelShift (unsigned int frame = 0) const; + bool getHDR (unsigned int frame = 0) const; + IIOSampleFormat getSampleFormat (unsigned int frame = 0) const; + rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const; + rtexif::TagDirectory* getRootExifData (unsigned int root = 0) const; + rtexif::TagDirectory* getBestExifData (ImageSource *imgSource, procparams::RAWParams *rawParams) const; + procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const; + bool hasExif (unsigned int frame = 0) const; + bool hasIPTC (unsigned int frame = 0) const; + tm getDateTime (unsigned int frame = 0) const; + time_t getDateTimeAsTS (unsigned int frame = 0) const; + int getISOSpeed (unsigned int frame = 0) const; + double getFNumber (unsigned int frame = 0) const; + double getFocalLen (unsigned int frame = 0) const; + double getFocalLen35mm (unsigned int frame = 0) const; + float getFocusDist (unsigned int frame = 0) const; + double getShutterSpeed (unsigned int frame = 0) const; + double getExpComp (unsigned int frame = 0) const; + std::string getMake (unsigned int frame = 0) const; + std::string getModel (unsigned int frame = 0) const; + std::string getLens (unsigned int frame = 0) const; + std::string getSerialNumber (unsigned int frame = 0) const; + std::string getOrientation (unsigned int frame = 0) const; +}; + + } #endif diff --git a/rtengine/imageformat.h b/rtengine/imageformat.h new file mode 100644 index 000000000..2c9bb480d --- /dev/null +++ b/rtengine/imageformat.h @@ -0,0 +1,54 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Jean-Christophe Frisch + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#ifndef _IMAGEFORMAT_ +#define _IMAGEFORMAT_ + +namespace rtengine +{ + +//NB: Update the associated strings in languages files when updating the following enum +// Look for "SAMPLEFORMAT_" +typedef enum IIO_Sample_Format { + IIOSF_UNKNOWN = 0, // Unknown or Unsupported file type; Has to remain 0 + //IIOSF_SIGNED_INT , // Not yet supported + IIOSF_UNSIGNED_CHAR = 1 << 0, + IIOSF_UNSIGNED_SHORT = 1 << 1, + //IIOSF_HALF , // OpenEXR & NVidia's Half Float, not yet supported + IIOSF_LOGLUV24 = 1 << 2, + IIOSF_LOGLUV32 = 1 << 3, + IIOSF_FLOAT = 1 << 4 +} IIOSampleFormat; + +typedef enum IIO_Sample_Arrangement { + IIOSA_UNKNOWN, // Unknown or Unsupported file type + IIOSA_CHUNKY, + IIOSA_PLANAR +} IIOSampleArrangement; + +typedef enum SensorType { + ST_NONE, // use this value if the image is already demosaiced (i.e. not a raw file) + ST_BAYER, + ST_FUJI_XTRANS, + ST_FOVEON, + //ST_FUJI_EXR +} eSensorType; + +} + +#endif diff --git a/rtengine/imageio.h b/rtengine/imageio.h index 1fbeb6e2d..372f42380 100644 --- a/rtengine/imageio.h +++ b/rtengine/imageio.h @@ -29,6 +29,7 @@ #define IMIO_CANNOTWRITEFILE 7 #include "rtengine.h" +#include "imageformat.h" #include #include "procparams.h" #include @@ -43,31 +44,6 @@ namespace rtengine class ProgressListener; class Imagefloat; -typedef enum IIO_Sample_Format { - IIOSF_UNKNOWN = 0, // Unknown or Unsupported file type; Has to remain 0 - //IIOSF_SIGNED_INT , // Not yet supported - IIOSF_UNSIGNED_CHAR = 1 << 0, - IIOSF_UNSIGNED_SHORT = 1 << 1, - //IIOSF_HALF , // OpenEXR & NVidia's Half Float, not yet supported - IIOSF_LOGLUV24 = 1 << 2, - IIOSF_LOGLUV32 = 1 << 3, - IIOSF_FLOAT = 1 << 4 -} IIOSampleFormat; - -typedef enum IIO_Sample_Arrangement { - IIOSA_UNKNOWN, // Unknown or Unsupported file type - IIOSA_CHUNKY, - IIOSA_PLANAR -} IIOSampleArrangement; - -typedef enum SensorType { - ST_NONE, // use this value if the image is already demosaiced (i.e. not a raw file) - ST_BAYER, - ST_FUJI_XTRANS, - ST_FOVEON, - //ST_FUJI_EXR -} eSensorType; - class ImageIO : virtual public ImageDatas { diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 0eec1325a..757e6f5a7 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -57,7 +57,7 @@ protected: double redAWBMul, greenAWBMul, blueAWBMul; // local copy of the multipliers, to avoid recomputing the values cmsHPROFILE embProfile; Glib::ustring fileName; - ImageData* idata; + FramesData* idata; ImageMatrices imatrices; double dirpyrdenoiseExpComp; @@ -76,12 +76,12 @@ public: virtual void flushRGB () {}; virtual void HLRecovery_Global (ToneCurveParams hrp) {}; virtual void HLRecovery_inpaint (float** red, float** green, float** blue) {}; - virtual void MSR(LabImage* lab, LUTf & mapcurve, bool &mapcontlutili, int width, int height, int skip, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax) {}; + virtual void MSR (LabImage* lab, LUTf & mapcurve, bool &mapcontlutili, int width, int height, int skip, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax) {}; - virtual bool IsrgbSourceModified() const = 0; // tracks whether cached rgb output of demosaic has been modified + virtual bool isRGBSourceModified () const = 0; // tracks whether cached rgb output of demosaic has been modified - virtual void setCurrentFrame(unsigned int frameNum) = 0; - virtual int getFrameCount() = 0; + virtual void setCurrentFrame (unsigned int frameNum) = 0; + virtual int getFrameCount () = 0; // use right after demosaicing image, add coarse transformation and put the result in the provided Imagefloat* @@ -107,10 +107,10 @@ public: return 0; } - virtual ImageData* getImageData () = 0; + virtual FrameData* getImageData (unsigned int frameNum) = 0; virtual ImageMatrices* getImageMatrices () = 0; - virtual bool isRAW() const = 0; - virtual DCPProfile* getDCP(const ColorManagementParams &cmp, ColorTemp &wb, DCPProfile::ApplyState &as) + virtual bool isRAW () const = 0; + virtual DCPProfile* getDCP (const ColorManagementParams &cmp, ColorTemp &wb, DCPProfile::ApplyState &as) { return nullptr; }; @@ -150,7 +150,7 @@ public: { return embProfile; } - virtual const ImageMetaData* getMetaData () + virtual const FramesMetaData* getMetaData () { return idata; } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index d3b65ec26..237eadb41 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -338,8 +338,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) if ( (todo & M_RAW) || (!highDetailRawComputed && highDetailNeeded) - || ( params.toneCurve.hrenabled && params.toneCurve.method != "Color" && imgsrc->IsrgbSourceModified()) - || (!params.toneCurve.hrenabled && params.toneCurve.method == "Color" && imgsrc->IsrgbSourceModified())) { + || ( params.toneCurve.hrenabled && params.toneCurve.method != "Color" && imgsrc->isRGBSourceModified()) + || (!params.toneCurve.hrenabled && params.toneCurve.method == "Color" && imgsrc->isRGBSourceModified())) { if (settings->verbose) { if (imgsrc->getSensorType() == ST_BAYER) { @@ -3299,10 +3299,21 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) CurveFactory::curveLightBrightColor (params.colorappearance.curve, params.colorappearance.curve2, params.colorappearance.curve3, lhist16CAM, histLCAM, lhist16CCAM, histCCAM, customColCurve1, customColCurve2, customColCurve3, 1); - float fnum = imgsrc->getMetaData()->getFNumber (); // F number - float fiso = imgsrc->getMetaData()->getISOSpeed () ; // ISO - float fspeed = imgsrc->getMetaData()->getShutterSpeed () ; // Speed - double fcomp = imgsrc->getMetaData()->getExpComp (); // Compensation +/- + + const FramesMetaData* metaData = imgsrc->getMetaData(); + int imgNum = 0; + if (imgsrc->isRAW()) { + if (imgsrc->getSensorType() == ST_BAYER) { + imgNum = rtengine::LIM(params.raw.bayersensor.imageNum, 0, metaData->getFrameCount() - 1); + } else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) { + //imgNum = rtengine::LIM(params.raw.xtranssensor.imageNum, 0, metaData->getFrameCount() - 1); + } + } + + float fnum = metaData->getFNumber (imgNum); // F number + float fiso = metaData->getISOSpeed (imgNum) ; // ISO + float fspeed = metaData->getShutterSpeed (imgNum) ; // Speed + double fcomp = metaData->getExpComp (imgNum); // Compensation +/- double adap; if (fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 9545da398..96e6e352b 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -7183,13 +7183,14 @@ double ImProcFunctions::getAutoDistor (const Glib::ustring &fname, int thumb_si int w_raw = -1, h_raw = thumb_size; int w_thumb = -1, h_thumb = thumb_size; - Thumbnail* thumb = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, w_thumb, h_thumb, 1, FALSE); + eSensorType sensorType = rtengine::ST_NONE; + Thumbnail* thumb = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, sensorType, w_thumb, h_thumb, 1, FALSE); if (!thumb) { return 0.0; } - Thumbnail* raw = rtengine::Thumbnail::loadFromRaw (fname, ri, w_raw, h_raw, 1, 1.0, FALSE, 0); + Thumbnail* raw = rtengine::Thumbnail::loadFromRaw (fname, ri, sensorType, w_raw, h_raw, 1, 1.0, FALSE, 0); if (!raw) { delete thumb; diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 07e4a28ac..f4ea684a8 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -251,7 +251,7 @@ public: void colorCurve (LabImage* lold, LabImage* lnew); void sharpening (LabImage* lab, float** buffer, SharpeningParams &sharpenParam); void sharpeningcam (CieImage* ncie, float** buffer); - void transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const ImageMetaData *metadata, int rawRotationDeg, bool fullImage); + void transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, int rawRotationDeg, bool fullImage); float resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh); void lab2monitorRgb (LabImage* lab, Image8* image); void resize (Image16* src, Image16* dst, float dScale); diff --git a/rtengine/init.cc b/rtengine/init.cc index 41f599b01..6c1f4b98a 100644 --- a/rtengine/init.cc +++ b/rtengine/init.cc @@ -42,24 +42,65 @@ MyMutex* lcmsMutex = nullptr; int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir, bool loadAll) { settings = s; - ProfileStore::getInstance()->init (loadAll); - ICCStore::getInstance()->init (s->iccDirectory, Glib::build_filename (baseDir, "iccprofiles"), loadAll); - DCPStore::getInstance()->init (Glib::build_filename (baseDir, "dcpprofiles"), loadAll); + ProcParams::init(); + PerceptualToneCurve::init(); + RawImageSource::init(); - CameraConstantsStore::getInstance ()->init (baseDir, userSettingsDir); - ProcParams::init (); - Color::init (); - PerceptualToneCurve::init (); - RawImageSource::init (); +#ifdef _OPENMP +#pragma omp parallel sections +#endif +{ +#ifdef _OPENMP +#pragma omp section +#endif +{ if (s->lensfunDbDirectory.empty() || Glib::path_is_absolute(s->lensfunDbDirectory)) { LFDatabase::init(s->lensfunDbDirectory); } else { LFDatabase::init(Glib::build_filename(baseDir, s->lensfunDbDirectory)); } +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + ProfileStore::getInstance()->init(loadAll); +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + ICCStore::getInstance()->init(s->iccDirectory, Glib::build_filename (baseDir, "iccprofiles"), loadAll); +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + DCPStore::getInstance()->init(Glib::build_filename (baseDir, "dcpprofiles"), loadAll); +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + CameraConstantsStore::getInstance()->init(baseDir, userSettingsDir); +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + dfm.init(s->darkFramesPath); +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + ffm.init(s->flatFieldsPath); +} +} + + Color::init (); delete lcmsMutex; lcmsMutex = new MyMutex; - dfm.init( s->darkFramesPath ); - ffm.init( s->flatFieldsPath ); return 0; } diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index d3e6ca759..f227af2ed 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -296,7 +296,7 @@ bool ImProcFunctions::transCoord (int W, int H, int x, int y, int w, int h, int& } void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, - const ImageMetaData *metadata, + const FramesMetaData *metadata, int rawRotationDeg, bool fullImage) { double focalLen = metadata->getFocalLen(); diff --git a/rtengine/previewimage.cc b/rtengine/previewimage.cc index aba43ace5..e6703aed5 100644 --- a/rtengine/previewimage.cc +++ b/rtengine/previewimage.cc @@ -59,7 +59,8 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext } } else { rtengine::RawMetaDataLocation ri; - tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, width, height, 1, true, true); + eSensorType sensorType = rtengine::ST_NONE; + tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, sensorType, width, height, 1, true, true); if (tpp) { data = tpp->getImage8Data(); diff --git a/rtengine/profilestore.cc b/rtengine/profilestore.cc index c713d6b5c..4d06b6f6b 100644 --- a/rtengine/profilestore.cc +++ b/rtengine/profilestore.cc @@ -498,7 +498,7 @@ void ProfileStore::dumpFolderList() printf ("\n"); } -PartialProfile *ProfileStore::loadDynamicProfile (const ImageMetaData *im) +PartialProfile *ProfileStore::loadDynamicProfile (const FramesMetaData *im) { if (storeState == STORESTATE_NOTINITIALIZED) { parseProfilesOnce(); diff --git a/rtengine/profilestore.h b/rtengine/profilestore.h index 372dbfc3b..4949517da 100644 --- a/rtengine/profilestore.h +++ b/rtengine/profilestore.h @@ -195,7 +195,7 @@ public: void addListener (ProfileStoreListener *listener); void removeListener (ProfileStoreListener *listener); - rtengine::procparams::PartialProfile* loadDynamicProfile (const rtengine::ImageMetaData *im); + rtengine::procparams::PartialProfile* loadDynamicProfile (const rtengine::FramesMetaData *im); void dumpFolderList(); }; diff --git a/rtengine/rawimage.h b/rtengine/rawimage.h index b8a45d708..95e7aea8d 100644 --- a/rtengine/rawimage.h +++ b/rtengine/rawimage.h @@ -24,7 +24,7 @@ #include #include "dcraw.h" -#include "imageio.h" +#include "imageformat.h" #include "noncopyable.h" namespace rtengine diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 3ebcfe6fd..7a07cff36 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -914,7 +914,7 @@ DCPProfile *RawImageSource::getDCP (const ColorManagementParams &cmp, ColorTemp { DCPProfile *dcpProf = nullptr; cmsHPROFILE dummy; - findInputProfile (cmp.input, nullptr, (static_cast (getMetaData()))->getCamera(), &dcpProf, dummy); + findInputProfile(cmp.input, nullptr, (static_cast(getMetaData()))->getCamera(), &dcpProf, dummy); if (dcpProf == nullptr) { if (settings->verbose) { @@ -930,8 +930,8 @@ DCPProfile *RawImageSource::getDCP (const ColorManagementParams &cmp, ColorTemp void RawImageSource::convertColorSpace (Imagefloat* image, const ColorManagementParams &cmp, const ColorTemp &wb) { - double pre_mul[3] = { ri->get_pre_mul (0), ri->get_pre_mul (1), ri->get_pre_mul (2) }; - colorSpaceConversion (image, cmp, wb, pre_mul, embProfile, camProfile, imatrices.xyz_cam, (static_cast (getMetaData()))->getCamera()); + double pre_mul[3] = { ri->get_pre_mul(0), ri->get_pre_mul(1), ri->get_pre_mul(2) }; + colorSpaceConversion (image, cmp, wb, pre_mul, embProfile, camProfile, imatrices.xyz_cam, (static_cast(getMetaData()))->getCamera()); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1705,15 +1705,14 @@ int RawImageSource::load (const Glib::ustring &fname, int imageNum, bool batch) } - //Load complete Exif informations - RawMetaDataLocation rml; - rml.exifBase = ri->get_exifBase(); - rml.ciffBase = ri->get_ciffBase(); - rml.ciffLength = ri->get_ciffLen(); - idata = new ImageData (fname, &rml); - green (W, H); - red (W, H); - blue (W, H); + // Load complete Exif informations + std::unique_ptr rml(new RawMetaDataLocation (ri->get_exifBase(), ri->get_ciffBase(), ri->get_ciffLen())); + idata = new FramesData (fname, std::move(rml)); + idata->setDCRawFrameCount (numFrames); + + green(W, H); + red(W, H); + blue(W, H); //hpmap = allocArray(W, H); if (plistener) { diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 8ce27f289..99cc9af64 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -128,7 +128,7 @@ public: void refinement_lassus (int PassCount); void refinement(int PassCount); - bool IsrgbSourceModified() const + bool isRGBSourceModified() const { return rgbSourceModified; // tracks whether cached rgb output of demosaic has been modified } @@ -166,9 +166,9 @@ public: return ri->get_rotateDegree(); } - ImageData* getImageData () + FrameData* getImageData (unsigned int frameNum) { - return idata; + return idata->getFrameData (frameNum); } ImageMatrices* getImageMatrices () { diff --git a/rtengine/rawmetadatalocation.h b/rtengine/rawmetadatalocation.h index d029d2a13..40ac6cc3e 100644 --- a/rtengine/rawmetadatalocation.h +++ b/rtengine/rawmetadatalocation.h @@ -22,11 +22,19 @@ namespace rtengine { -struct RawMetaDataLocation { +class RawMetaDataLocation { + +public: int exifBase; int ciffBase; int ciffLength; + + RawMetaDataLocation () : exifBase(-1), ciffBase(-1), ciffLength(-1) {} + RawMetaDataLocation (int exifBase) : exifBase(exifBase), ciffBase(-1), ciffLength(-1) {} + RawMetaDataLocation (int ciffBase, int ciffLength) : exifBase(-1), ciffBase(ciffBase), ciffLength(ciffLength) {} + RawMetaDataLocation (int exifBase, int ciffBase, int ciffLength) : exifBase(exifBase), ciffBase(ciffBase), ciffLength(ciffLength) {} }; + } #endif diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index e338399da..8e6e62508 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -19,6 +19,7 @@ #ifndef _RTENGINE_ #define _RTENGINE_ +#include "imageformat.h" #include "rt_math.h" #include "procparams.h" #include "procevents.h" @@ -48,60 +49,84 @@ namespace rtengine class IImage8; class IImage16; class IImagefloat; - +class ImageSource; /** - * This class represents provides functions to obtain exif and IPTC metadata information - * from the image file + * This class provides functions to obtain exif and IPTC metadata information + * from any of the sub-frame of an image file */ -class ImageMetaData +class FramesMetaData { public: + /** @return Returns the number of root Metadata */ + virtual unsigned int getRootCount () const = 0; + /** @return Returns the number of frame contained in the file based on Metadata */ + virtual unsigned int getFrameCount () const = 0; + /** Checks the availability of exif metadata tags. * @return Returns true if image contains exif metadata tags */ - virtual bool hasExif () const = 0; + virtual bool hasExif (unsigned int frame = 0) const = 0; /** Returns the directory of exif metadata tags. + * @param root root number in the metadata tree * @return The directory of exif metadata tags */ - virtual const rtexif::TagDirectory* getExifData () const = 0; + virtual rtexif::TagDirectory* getRootExifData (unsigned int root = 0) const = 0; + /** Returns the directory of exif metadata tags. + * @param frame frame number in the metadata tree + * @return The directory of exif metadata tags */ + virtual rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const = 0; + /** Returns the directory of exif metadata tags containing at least the 'Make' tag for the requested frame. + * If no usable metadata exist in the frame, send back the best TagDirectory describing the frame content. + * @param imgSource rawimage that we want the metadata from + * @param rawParams RawParams to select the frame number + * @return The directory of exif metadata tags containing at least the 'Make' tag */ + virtual rtexif::TagDirectory* getBestExifData (ImageSource *imgSource, procparams::RAWParams *rawParams) const = 0; /** Checks the availability of IPTC tags. * @return Returns true if image contains IPTC tags */ - virtual bool hasIPTC () const = 0; + virtual bool hasIPTC (unsigned int frame = 0) const = 0; /** Returns the directory of IPTC tags. * @return The directory of IPTC tags */ - virtual const procparams::IPTCPairs getIPTCData () const = 0; + virtual procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const = 0; /** @return a struct containing the date and time of the image */ - virtual struct tm getDateTime () const = 0; + virtual tm getDateTime (unsigned int frame = 0) const = 0; /** @return a timestamp containing the date and time of the image */ - virtual time_t getDateTimeAsTS() const = 0; + virtual time_t getDateTimeAsTS(unsigned int frame = 0) const = 0; /** @return the ISO of the image */ - virtual int getISOSpeed () const = 0; + virtual int getISOSpeed (unsigned int frame = 0) const = 0; /** @return the F number of the image */ - virtual double getFNumber () const = 0; + virtual double getFNumber (unsigned int frame = 0) const = 0; /** @return the focal length used at the exposure */ - virtual double getFocalLen () const = 0; + virtual double getFocalLen (unsigned int frame = 0) const = 0; /** @return the focal length in 35mm used at the exposure */ - virtual double getFocalLen35mm () const = 0; + virtual double getFocalLen35mm (unsigned int frame = 0) const = 0; /** @return the focus distance in meters, 0=unknown, 10000=infinity */ - virtual float getFocusDist () const = 0; + virtual float getFocusDist (unsigned int frame = 0) const = 0; /** @return the shutter speed */ - virtual double getShutterSpeed () const = 0; + virtual double getShutterSpeed (unsigned int frame = 0) const = 0; /** @return the exposure compensation */ - virtual double getExpComp () const = 0; + virtual double getExpComp (unsigned int frame = 0) const = 0; /** @return the maker of the camera */ - virtual std::string getMake () const = 0; + virtual std::string getMake (unsigned int frame = 0) const = 0; /** @return the model of the camera */ - virtual std::string getModel () const = 0; + virtual std::string getModel (unsigned int frame = 0) const = 0; - std::string getCamera () const + std::string getCamera (unsigned int frame = 0) const { - return getMake() + " " + getModel(); + return getMake(frame) + " " + getModel(frame); } /** @return the lens on the camera */ - virtual std::string getLens () const = 0; + virtual std::string getLens (unsigned int frame = 0) const = 0; /** @return the orientation of the image */ - virtual std::string getOrientation () const = 0; + virtual std::string getOrientation (unsigned int frame = 0) const = 0; + + /** @return true if the file is a PixelShift shot (Pentax bodies) */ + virtual bool getPixelShift (unsigned int frame = 0) const = 0; + /** @return false: not an HDR file ; true: single or multi-frame HDR file (e.g. Pentax HDR raw file or 32 bit float DNG file or Log compressed) */ + virtual bool getHDR (unsigned int frame = 0) const = 0; + /** @return the sample format based on MetaData */ + virtual IIOSampleFormat getSampleFormat (unsigned int frame = 0) const = 0; + /** Functions to convert between floating point and string representation of shutter and aperture */ static std::string apertureToString (double aperture); /** Functions to convert between floating point and string representation of shutter and aperture */ @@ -113,14 +138,15 @@ public: /** Functions to convert between floating point and string representation of exposure compensation */ static std::string expcompToString (double expcomp, bool maskZeroexpcomp); - virtual ~ImageMetaData () {} + virtual ~FramesMetaData () = default; /** Reads metadata from file. * @param fname is the name of the file - * @param rml is a struct containing information about metadata location. Use it only for raw files. In case - * of jpgs and tiffs pass a NULL pointer. + * @param rml is a struct containing information about metadata location of the first frame. + * Use it only for raw files. In caseof jpgs and tiffs pass a NULL pointer. + * @param firstFrameOnly must be true to get the MetaData of the first frame only, e.g. for a PixelShift file. * @return The metadata */ - static ImageMetaData* fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml); + static FramesMetaData* fromFile (const Glib::ustring& fname, std::unique_ptr rml, bool firstFrameOnly = false); }; /** This listener interface is used to indicate the progress of time consuming operations */ @@ -159,9 +185,9 @@ public: /** Returns the embedded icc profile of the image. * @return The handle of the embedded profile */ virtual cmsHPROFILE getEmbeddedProfile () = 0; - /** Returns a class providing access to the exif and iptc metadata tags of the image. - * @return An instance of the ImageMetaData class */ - virtual const ImageMetaData* getMetaData () = 0; + /** Returns a class providing access to the exif and iptc metadata tags of all frames of the image. + * @return An instance of the FramesMetaData class */ + virtual const FramesMetaData* getMetaData () = 0; /** This is a function used for internal purposes only. */ virtual ImageSource* getImageSource () = 0; /** This class has manual reference counting. You have to call this function each time to make a new reference to an instance. */ diff --git a/rtengine/rtlensfun.cc b/rtengine/rtlensfun.cc index 2f47ec1a3..ddbeca9bf 100644 --- a/rtengine/rtlensfun.cc +++ b/rtengine/rtlensfun.cc @@ -432,7 +432,7 @@ std::unique_ptr LFDatabase::getModifier(const LFCamera &camera, cons } -std::unique_ptr LFDatabase::findModifier(const LensProfParams &lensProf, const ImageMetaData *idata, int width, int height, const CoarseTransformParams &coarse, int rawRotationDeg) +std::unique_ptr LFDatabase::findModifier(const LensProfParams &lensProf, const FramesMetaData *idata, int width, int height, const CoarseTransformParams &coarse, int rawRotationDeg) { const LFDatabase *db = getInstance(); Glib::ustring make, model, lens; diff --git a/rtengine/rtlensfun.h b/rtengine/rtlensfun.h index 303c9a45a..207e4e86e 100644 --- a/rtengine/rtlensfun.h +++ b/rtengine/rtlensfun.h @@ -110,7 +110,7 @@ public: LFCamera findCamera(const Glib::ustring &make, const Glib::ustring &model) const; LFLens findLens(const LFCamera &camera, const Glib::ustring &name) const; - static std::unique_ptr findModifier(const LensProfParams &lensProf, const ImageMetaData *idata, int width, int height, const CoarseTransformParams &coarse, int rawRotationDeg); + static std::unique_ptr findModifier(const LensProfParams &lensProf, const FramesMetaData *idata, int width, int height, const CoarseTransformParams &coarse, int rawRotationDeg); private: std::unique_ptr getModifier(const LFCamera &camera, const LFLens &lens, diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 271fcc05a..63164cb62 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -247,7 +247,7 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, return tpp; } -Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate, bool inspectorMode) +Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode) { RawImage *ri = new RawImage (fname); unsigned int imageNum = 0; @@ -255,9 +255,12 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL if ( r ) { delete ri; + sensorType = ST_NONE; return nullptr; } + sensorType = ri->getSensorType(); + rml.exifBase = ri->get_exifBase(); rml.ciffBase = ri->get_ciffBase(); rml.ciffLength = ri->get_ciffLen(); @@ -378,7 +381,7 @@ RawMetaDataLocation Thumbnail::loadMetaDataFromRaw (const Glib::ustring& fname) return rml; } -Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate, int imageNum) +Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, bool rotate, int imageNum) { RawImage *ri = new RawImage (fname); unsigned int tempImageNum = 0; @@ -387,9 +390,12 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati if ( r ) { delete ri; + sensorType = ST_NONE; return nullptr; } + sensorType = ri->getSensorType(); + int width = ri->get_width(); int height = ri->get_height(); rtengine::Thumbnail* tpp = new rtengine::Thumbnail; @@ -953,13 +959,21 @@ IImage8* Thumbnail::quickProcessImage (const procparams::ProcParams& params, int } // Full thumbnail processing, second stage if complete profile exists -IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rheight, TypeInterpolation interp, const ImageMetaData *metadata, double& myscale) +IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorType sensorType, int rheight, TypeInterpolation interp, const FramesMetaData *metadata, double& myscale) { - std::string camName = metadata->getCamera(); - float shutter = metadata->getShutterSpeed(); - float fnumber = metadata->getFNumber(); - float iso = metadata->getISOSpeed(); - float fcomp = metadata->getExpComp(); + unsigned int imgNum = 0; + if (isRaw) { + if (sensorType == ST_BAYER) { + imgNum = rtengine::LIM(params.raw.bayersensor.imageNum, 0, metadata->getFrameCount() - 1); + } else if (sensorType == ST_FUJI_XTRANS) { + //imgNum = rtengine::LIM(params.raw.xtranssensor.imageNum, 0, metadata->getFrameCount() - 1) + } + } + std::string camName = metadata->getCamera(imgNum); + float shutter = metadata->getShutterSpeed(imgNum); + float fnumber = metadata->getFNumber(imgNum); + float iso = metadata->getISOSpeed(imgNum); + float fcomp = metadata->getExpComp(imgNum); // check if the WB's equalizer value has changed if (wbEqual < (params.wb.equal - 5e-4) || wbEqual > (params.wb.equal + 5e-4) || wbTempBias < (params.wb.tempBias - 5e-4) || wbTempBias > (params.wb.tempBias + 5e-4)) { diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h index 3610a530f..4987cc88c 100644 --- a/rtengine/rtthumbnail.h +++ b/rtengine/rtthumbnail.h @@ -71,13 +71,13 @@ public: void init (); - IImage8* processImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, const ImageMetaData *metadata, double& scale); + IImage8* processImage (const procparams::ProcParams& pparams, eSensorType sensorType, int rheight, TypeInterpolation interp, const FramesMetaData *metadata, double& scale); IImage8* quickProcessImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, double& scale); int getImageWidth (const procparams::ProcParams& pparams, int rheight, float &ratio); void getDimensions (int& w, int& h, double& scaleFac); - static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate, bool inspectorMode = false); - static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate, int imageNum); + static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode = false); + static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, bool rotate, int imageNum); static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode = false); static RawMetaDataLocation loadMetaDataFromRaw (const Glib::ustring& fname); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 38820888c..f56f2f6dd 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -2072,10 +2072,16 @@ private: if (params.colorappearance.enabled) { double adap; - float fnum = imgsrc->getMetaData()->getFNumber ();// F number - float fiso = imgsrc->getMetaData()->getISOSpeed () ;// ISO - float fspeed = imgsrc->getMetaData()->getShutterSpeed () ;//speed - float fcomp = imgsrc->getMetaData()->getExpComp ();//compensation + - + int imgNum = 0; + if (imgsrc->getSensorType() == ST_BAYER) { + imgNum = params.raw.bayersensor.imageNum; + } else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) { + //imgNum = params.raw.xtranssensor.imageNum; + } + float fnum = imgsrc->getMetaData()->getFNumber (imgNum); // F number + float fiso = imgsrc->getMetaData()->getISOSpeed (imgNum) ; // ISO + float fspeed = imgsrc->getMetaData()->getShutterSpeed (imgNum) ; //speed + float fcomp = imgsrc->getMetaData()->getExpComp (imgNum); //compensation + - if (fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { adap = 2000.; @@ -2248,9 +2254,12 @@ private: } if (tunnelMetaData) { - readyImg->setMetadata (ii->getMetaData()->getExifData ()); + // Sending back the whole first root, which won't necessarily be the selected frame number + // and may contain subframe depending on initial raw's hierarchy + readyImg->setMetadata (ii->getMetaData()->getRootExifData ()); } else { - readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); + // ask for the correct frame number, but may contain subframe depending on initial raw's hierarchy + readyImg->setMetadata (ii->getMetaData()->getBestExifData(imgsrc, ¶ms.raw), params.exif, params.iptc); } diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc index 87f25a497..d4e6a62f1 100644 --- a/rtengine/stdimagesource.cc +++ b/rtengine/stdimagesource.cc @@ -158,7 +158,7 @@ int StdImageSource::load (const Glib::ustring &fname, int imageNum, bool batch) embProfile = img->getEmbeddedProfile (); - idata = new ImageData (fname); + idata = new FramesData (fname); if (idata->hasExif()) { int deg = 0; diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index 330c08244..1450d745e 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -68,9 +68,9 @@ public: void getFullSize (int& w, int& h, int tr = TR_NONE); void getSize (const PreviewProps &pp, int& w, int& h); - ImageData* getImageData () + FrameData* getImageData (unsigned int frameNum) { - return idata; + return idata->getFrameData (frameNum); } ImageIO* getImageIO () { @@ -93,7 +93,7 @@ public: void convertColorSpace(Imagefloat* image, const ColorManagementParams &cmp, const ColorTemp &wb);// RAWParams raw will not be used for non-raw files (see imagesource.h) static void colorSpaceConversion (Imagefloat* im, const ColorManagementParams &cmp, cmsHPROFILE embedded, IIOSampleFormat sampleFormat); - bool IsrgbSourceModified() const + bool isRGBSourceModified() const { return rgbSourceModified; } diff --git a/rtexif/canonattribs.cc b/rtexif/canonattribs.cc index cabafad32..eb2378696 100644 --- a/rtexif/canonattribs.cc +++ b/rtexif/canonattribs.cc @@ -1109,7 +1109,7 @@ public: sprintf (buffer, "%d", a); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = Interpreter::toInt (t, ofs); @@ -1120,7 +1120,7 @@ public: return 0.; } } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { int a = Interpreter::toInt (t, ofs, astype); diff --git a/rtexif/nikonattribs.cc b/rtexif/nikonattribs.cc index ac8e69ead..781224a5f 100644 --- a/rtexif/nikonattribs.cc +++ b/rtexif/nikonattribs.cc @@ -55,7 +55,7 @@ public: sprintf (buffer, "%d", a); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->getValue()[ofs]; @@ -66,7 +66,7 @@ public: return 0.; } } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { int a = t->getValue()[ofs]; diff --git a/rtexif/pentaxattribs.cc b/rtexif/pentaxattribs.cc index a1f752f5e..7444e7212 100644 --- a/rtexif/pentaxattribs.cc +++ b/rtexif/pentaxattribs.cc @@ -1230,6 +1230,7 @@ public: choices[2] = "HDR 1"; choices[3] = "HDR 2"; choices[4] = "HDR 3"; + choices[5] = "Advanced"; choices1[0] = "Auto-align Off"; choices1[1] = "Auto-align On"; @@ -1336,7 +1337,7 @@ public: sprintf (buffer, "%d", a ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a; @@ -1367,7 +1368,7 @@ public: return "n/a"; } } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { double a = double (t->toInt (0, LONG)); @@ -1397,7 +1398,7 @@ public: return "n/a"; } } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (ofs, BYTE); float b = float (10 * int (a >> 2)) * pow (4.f, float (int (a & 0x03) - 2)); @@ -1423,7 +1424,7 @@ public: sprintf (buffer, "%.1f", v ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, BYTE); return 100.*exp (double (a - 32) * log (2.) / 8.); @@ -1454,7 +1455,7 @@ public: return "n/a"; } } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, BYTE); a &= 0x7F; @@ -1480,7 +1481,7 @@ public: sprintf (buffer, "%.1f", v ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, BYTE); return double (a - 64) / 8.; @@ -1500,7 +1501,7 @@ public: sprintf (buffer, "%.1f", v ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, SBYTE); return double (a) / 8.; @@ -1520,7 +1521,7 @@ public: sprintf (buffer, "%.1f", v ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, BYTE); return exp ((double (a) - 68.) * log (2.) / 16.); @@ -1540,7 +1541,7 @@ public: sprintf (buffer, "%.6f", v ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, BYTE); return 24.*exp (- (double (a) - 32.) * log (2.) / 8.); @@ -1560,7 +1561,7 @@ public: sprintf (buffer, "%.1f", double (int (pow (2.0, double (mina + 10) / 4.0) + 0.2))); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, BYTE) & 0x0F; return double (int (pow (2.0, double (a + 10) / 4.0) + 0.2)); @@ -1580,7 +1581,7 @@ public: sprintf (buffer, "%.1f", double (int (pow (2.0, double (maxa) / 4.0) + 0.2)) ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = ( t->toInt (0, BYTE) & 0xF0) >> 4; return double (int (pow (2.0, double (a) / 4.0) + 0.2)); diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index c12f5f782..bc0e2002f 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -19,13 +19,16 @@ * along with RawTherapee. If not, see . */ #include +#include #include #include #include #include #include +#include #include +#include #include "rtexif.h" @@ -33,6 +36,9 @@ #include "../rtgui/version.h" #include "../rtgui/ppversion.h" +// see end of ExifManager::parse(bool, bool) +#define PRINT_METADATA_TREE 0 + using namespace std; namespace rtexif @@ -44,8 +50,6 @@ Interpreter stdInterpreter; // this class is a collection (an array) of tags //----------------------------------------------------------------------------- -#define TAG_SUBFILETYPE 0x00fe - TagDirectory::TagDirectory () : attribs (ifdAttribs), order (HOSTORDER), parent (nullptr) {} @@ -78,7 +82,7 @@ TagDirectory::TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* int id = newTag->getID(); // detect and possibly ignore tags of directories belonging to the embedded thumbnail image - if (attribs == ifdAttribs && id == TAG_SUBFILETYPE && newTag->toInt() != 0) { + if (attribs == ifdAttribs && id == TIFFTAG_SUBFILETYPE && newTag->toInt() != 0) { thumbdescr = true; } @@ -207,11 +211,14 @@ void TagDirectory::printAll (unsigned int level) const for (size_t i = 0; i < tags.size(); i++) { std::string name = tags[i]->nameToString (); + TagDirectory* currTagDir; if (tags[i]->isDirectory()) { - for (int j = 0; tags[i]->getDirectory (j); j++) { + for (int j = 0; (currTagDir = tags[i]->getDirectory (j)) != nullptr; j++) { printf ("%s+-- DIRECTORY %s[%d]:\n", prefixStr, name.c_str(), j); - tags[i]->getDirectory (j)->printAll (level + 1); + currTagDir->printAll (level + 1); } + } else { + printf ("%s- %s\n", prefixStr, name.c_str()); } } } @@ -285,6 +292,10 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring kf->set_string ("RT General", "DefaultProcParams", defaultPParams); kf->set_boolean ("RT General", "FlaggingMode", flagMode); + kf->set_integer ("Common Data", "FrameCount", cfs->frameCount); + kf->set_integer ("Common Data", "SampleFormat", cfs->sampleFormat); + kf->set_boolean ("Common Data", "IsHDR", cfs->isHDR); + kf->set_boolean ("Common Data", "IsPixelShift", cfs->isPixelShift); kf->set_double ("Common Data", "FNumber", cfs->fnumber); kf->set_double ("Common Data", "Shutter", cfs->shutter); kf->set_double ("Common Data", "FocalLength", cfs->focalLen); @@ -445,34 +456,126 @@ Tag* TagDirectory::getTagP (const char* name) const return nullptr; } -Tag* TagDirectory::findTag (const char* name) const +Tag* TagDirectory::findTag (const char* name, bool lookUpward) const { - if (attribs) { - for (int i = 0; attribs[i].ignore != -1; i++) - if (!strcmp (attribs[i].name, name)) { - Tag* t = getTag (attribs[i].ID); + Tag* t = getTag(name); + if (t) { + return t; + } + + for (auto tag : tags) { + if (tag->isDirectory()) { + TagDirectory *dir; + int i = 0; + while ((dir = tag->getDirectory(i)) != nullptr) { + TagDirectory *dir = tag->getDirectory(); + Tag* t = dir->findTag (name); if (t) { return t; - } else { - break; } - } - } - - for (size_t i = 0; i < tags.size(); i++) - if (tags[i]->isDirectory()) { - TagDirectory *dir = tags[i]->getDirectory(); - Tag* t = dir->findTag (name); - - if (t) { - return t; + ++i; } } + } + + if (lookUpward && parent) { + Tag* t = parent->findTagUpward(name); + + if (t) { + return t; + } + } return nullptr; } +std::vector TagDirectory::findTags (int ID) +{ + + std::vector tagList; + + //assuming that an entry can only exist once + Tag* t = getTag(ID); + if (t) { + tagList.push_back(t); + } + + for (auto tag : tags) { + if (tag->isDirectory()) { + TagDirectory *dir; + int i = 0; + while ((dir = tag->getDirectory(i)) != nullptr) { + std::vector subTagList = dir->findTags (ID); + + if (!subTagList.empty()) { + // concatenating the 2 vectors + // not really optimal in a memory efficiency pov + for (auto tag2 : subTagList) { + tagList.push_back(tag2); + } + } + ++i; + } + } + } + + return tagList; +} + +std::vector TagDirectory::findTags (const char* name) +{ + + std::vector tagList; + + //assuming that an entry can only exist once + Tag* t = getTag(name); + if (t) { + tagList.push_back(t); + } + + for (auto tag : tags) { + if (tag->isDirectory()) { + TagDirectory *dir; + int i = 0; + while ((dir = tag->getDirectory(i)) != nullptr) { + std::vector subTagList = dir->findTags (name); + + if (!subTagList.empty()) { + // concatenating the 2 vectors + // not really optimal in a memory efficiency pov, but adding 10 items should be a maximum + for (auto tag2 : subTagList) { + tagList.push_back(tag2); + } + } + ++i; + } + } + } + + return tagList; +} + + +Tag* TagDirectory::findTagUpward (const char* name) const +{ + Tag* t = findTag(name); + if (t) { + return t; + } + + if (parent) { + Tag* t = parent->findTagUpward(name); + + if (t) { + return t; + } + } + + return nullptr; +} + + // Searches a simple value, as either attribute or element // only for simple values, not for entries with special chars or free text bool TagDirectory::getXMPTagValue (const char* name, char* value) const @@ -605,7 +708,7 @@ int TagDirectory::write (int start, unsigned char* buffer) return maxPos; } -void TagDirectory::applyChange (std::string name, std::string value) +void TagDirectory::applyChange (std::string name, Glib::ustring value) { std::string::size_type dp = name.find_first_of ('.'); @@ -627,7 +730,12 @@ void TagDirectory::applyChange (std::string name, std::string value) } else if (value == "#delete" && t) { t->setKeep (false); } else if (t && !t->isDirectory()) { - t->valueFromString (value); + if (name == "UserComment") { + // UserComment can be Unicode + t->userCommentFromString (value); + } else { + t->valueFromString (value); + } } else { const TagAttrib* attrib = nullptr; @@ -639,7 +747,12 @@ void TagDirectory::applyChange (std::string name, std::string value) if (attrib) { Tag* nt = new Tag (this, attrib); - nt->initString (value.c_str()); + if (name == "UserComment") { + // UserComment can be Unicode + nt->initUserComment (value); + } else { + nt->initString (value.c_str()); + } addTag (nt); } } @@ -849,9 +962,11 @@ Tag::Tag (TagDirectory* p, FILE* f, int base) } if (tag == 0x002e) { // location of the embedded preview image in raw files of Panasonic cameras - TagDirectory* previewdir = ExifManager::parseJPEG (f, ftell (f)); // try to parse the exif data from the preview image + ExifManager eManager(f, nullptr, true); + eManager.parseJPEG(ftell(f)); // try to parse the exif data from the preview image - if (previewdir) { + if (eManager.roots.size()) { + const TagDirectory* const previewdir = eManager.roots.at(0); if (previewdir->getTag ("Exif")) { if (previewdir->getTag ("Make")) { if (previewdir->getTag ("Make")->valueToString() == "Panasonic") { // "make" is not yet available here, so get it from the preview tags to assure we're doing the right thing @@ -1351,7 +1466,7 @@ void Tag::fromString (const char* v, int size) } } -int Tag::toInt (int ofs, TagType astype) +int Tag::toInt (int ofs, TagType astype) const { if (attrib) { return attrib->interpreter->toInt (this, ofs, astype); @@ -1402,7 +1517,7 @@ int Tag::toInt (int ofs, TagType astype) return 0; } -double Tag::toDouble (int ofs) +double Tag::toDouble (int ofs) const { if (attrib) { return attrib->interpreter->toDouble (this, ofs); @@ -1642,6 +1757,19 @@ void Tag::valueFromString (const std::string& value) } } +void Tag::userCommentFromString (const Glib::ustring& text) +{ + + if (!allocOwnMemory) { + return; + } + if (value) { + delete [] value; + value = nullptr; + } + initUserComment(text); +} + int Tag::calculateSize () { int size = 0; @@ -1803,6 +1931,28 @@ void Tag::initInt (int data, TagType t, int cnt) setInt (data, 0, t); } +void Tag::initUserComment (const Glib::ustring &text) +{ + type = UNDEFINED; + if (text.is_ascii()) { + count = 8 + strlen (text.c_str()); + valuesize = count; + value = new unsigned char[valuesize]; + strcpy ((char*)value, "ASCII"); + value[5] = value[6] = value[7] = 0; + strcpy ((char*)value + 8, text.c_str()); + } else { + wchar_t *commentStr = (wchar_t*)g_utf8_to_utf16 (text.c_str(), -1, NULL, NULL, NULL); + count = 8 + wcslen(commentStr)*2; + valuesize = count; + value = (unsigned char*)new char[valuesize]; + strcpy ((char*)value, "UNICODE"); + value[7] = 0; + wcscpy(((wchar_t*)value) + 4, commentStr); + g_free(commentStr); + } +} + void Tag::initString (const char* text) { @@ -1893,8 +2043,12 @@ const TagAttrib* lookupAttrib (const TagAttrib* dir, const char* field) return nullptr; } +void ExifManager::setIFDOffset(unsigned int offset) +{ + IFDOffset = offset; +} -TagDirectory* ExifManager::parseCIFF (FILE* f, int base, int length) +void ExifManager::parseCIFF () { TagDirectory* root = new TagDirectory (nullptr, ifdAttribs, INTEL); @@ -1904,12 +2058,11 @@ TagDirectory* ExifManager::parseCIFF (FILE* f, int base, int length) mn->initMakerNote (IFD, canonAttribs); root->addTag (exif); exif->getDirectory()->addTag (mn); - parseCIFF (f, base, length, root); + parseCIFF (rml->ciffLength, root); root->sort (); - return root; } -Tag* ExifManager::saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const char* name) +Tag* ExifManager::saveCIFFMNTag (TagDirectory* root, int len, const char* name) { int s = ftell (f); if(s >= 0) { @@ -1927,15 +2080,22 @@ Tag* ExifManager::saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const cha } } -void ExifManager::parseCIFF (FILE* f, int base, int length, TagDirectory* root) +void ExifManager::parseCIFF (int length, TagDirectory* root) { + if (!f) { + #ifndef NDEBUG + std::cerr << "ERROR : no file opened !" << std::endl; + #endif + return; + } + char buffer[1024]; Tag* t; - fseek (f, base + length - 4, SEEK_SET); + fseek (f, rml->ciffBase + length - 4, SEEK_SET); - int dirStart = get4 (f, INTEL) + base; + int dirStart = get4 (f, INTEL) + rml->ciffBase; fseek (f, dirStart, SEEK_SET); int numOfTags = get2 (f, INTEL); @@ -1960,10 +2120,19 @@ void ExifManager::parseCIFF (FILE* f, int base, int length, TagDirectory* root) int nextPos = ftell (f) + 4; // seek to the location of the value - fseek (f, base + get4 (f, INTEL), SEEK_SET); + fseek (f, rml->ciffBase + get4 (f, INTEL), SEEK_SET); if ((((type >> 8) + 8) | 8) == 0x38) { - parseCIFF (f, ftell (f), len, root); // Parse a sub-table + ExifManager( + f, + std::unique_ptr( + new rtengine::RawMetaDataLocation( + ftell(f), + len + ) + ), + true + ).parseCIFF(len, root); // Parse a sub-table } if (type == 0x0810) { @@ -1994,8 +2163,9 @@ void ExifManager::parseCIFF (FILE* f, int base, int length, TagDirectory* root) } + ExifManager exifManager(f, nullptr, true); if (type == 0x102d) { - Tag* t = saveCIFFMNTag (f, root, len, "CanonCameraSettings"); + Tag* t = exifManager.saveCIFFMNTag (root, len, "CanonCameraSettings"); int mm = t->toInt (34, SHORT); Tag* nt = new Tag (exif, lookupAttrib (exifAttribs, "MeteringMode")); @@ -2074,31 +2244,31 @@ void ExifManager::parseCIFF (FILE* f, int base, int length, TagDirectory* root) } if (type == 0x1029) { - saveCIFFMNTag (f, root, len, "CanonFocalLength"); + exifManager.saveCIFFMNTag (root, len, "CanonFocalLength"); } if (type == 0x1031) { - saveCIFFMNTag (f, root, len, "SensorInfo"); + exifManager.saveCIFFMNTag (root, len, "SensorInfo"); } if (type == 0x1033) { - saveCIFFMNTag (f, root, len, "CustomFunctions"); + exifManager.saveCIFFMNTag (root, len, "CustomFunctions"); } if (type == 0x1038) { - saveCIFFMNTag (f, root, len, "CanonAFInfo"); + exifManager.saveCIFFMNTag (root, len, "CanonAFInfo"); } if (type == 0x1093) { - saveCIFFMNTag (f, root, len, "CanonFileInfo"); + exifManager.saveCIFFMNTag (root, len, "CanonFileInfo"); } if (type == 0x10a9) { - saveCIFFMNTag (f, root, len, "ColorBalance"); + exifManager.saveCIFFMNTag (root, len, "ColorBalance"); } if (type == 0x102a) { - saveCIFFMNTag (f, root, len, "CanonShotInfo"); + exifManager.saveCIFFMNTag (root, len, "CanonShotInfo"); iso = pow (2, (get4 (f, INTEL), get2 (f, INTEL)) / 32.0 - 4) * 50; aperture = (get2 (f, INTEL), (short)get2 (f, INTEL)) / 32.0f; @@ -2193,6 +2363,9 @@ void ExifManager::parseCIFF (FILE* f, int base, int length, TagDirectory* root) t->initString (buffer); root->addTag (t); } + + roots.push_back(root); + } static void @@ -2530,33 +2703,65 @@ parse_leafdata (TagDirectory* root, ByteOrder order) } } -TagDirectory* ExifManager::parse (FILE* f, int base, bool skipIgnored) +void ExifManager::parseRaw (bool skipIgnored) { + parse(true, skipIgnored); +} + +void ExifManager::parseStd (bool skipIgnored) { + parse(false, skipIgnored); +} + +void ExifManager::parse (bool isRaw, bool skipIgnored) { + int ifdOffset = IFDOffset; + + if (!f) { + #ifndef NDEBUG + std::cerr << "ERROR : no file opened !" << std::endl; + #endif + return; + } setlocale (LC_NUMERIC, "C"); // to set decimal point in sscanf - // read tiff header - fseek (f, base, SEEK_SET); - unsigned short bo; - fread (&bo, 1, 2, f); - ByteOrder order = (ByteOrder) ((int)bo); - get2 (f, order); - int firstifd = get4 (f, order); - // seek to IFD0 - fseek (f, base + firstifd, SEEK_SET); + if (order == ByteOrder::UNKNOWN) { + // read tiff header + fseek (f, rml->exifBase, SEEK_SET); + unsigned short bo; + fread (&bo, 1, 2, f); + order = (ByteOrder) ((int)bo); + get2 (f, order); + if (!ifdOffset) { + ifdOffset = get4 (f, order); + } + } - // first read the IFD directory - TagDirectory* root = new TagDirectory (nullptr, f, base, ifdAttribs, order, skipIgnored); + do { + // seek to IFD + fseek (f, rml->exifBase + ifdOffset, SEEK_SET); - // fix ISO issue with nikon and panasonic cameras - Tag* make = root->getTag ("Make"); - Tag* exif = root->getTag ("Exif"); + // first read the IFD directory + TagDirectory* root = new TagDirectory (nullptr, f, rml->exifBase, ifdAttribs, order, skipIgnored); - if (exif && !exif->getDirectory()->getTag ("ISOSpeedRatings")) { - if (make && !strncmp ((char*)make->getValue(), "NIKON", 5)) { - Tag* mn = exif->getDirectory()->getTag ("MakerNote"); + // fix ISO issue with nikon and panasonic cameras + Tag* make = root->getTag ("Make"); + Tag* exif = root->getTag ("Exif"); - if (mn) { - Tag* iso = mn->getDirectory()->getTag ("ISOSpeed"); + if (exif && !exif->getDirectory()->getTag ("ISOSpeedRatings")) { + if (make && !strncmp ((char*)make->getValue(), "NIKON", 5)) { + Tag* mn = exif->getDirectory()->getTag ("MakerNote"); + + if (mn) { + Tag* iso = mn->getDirectory()->getTag ("ISOSpeed"); + + if (iso) { + std::string isov = iso->valueToString (); + Tag* niso = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); + niso->initInt (atoi (isov.c_str()), SHORT); + exif->getDirectory()->addTagFront (niso); + } + } + } else if (make && (!strncmp ((char*)make->getValue(), "Panasonic", 9) || !strncmp ((char*)make->getValue(), "LEICA", 5))) { + Tag* iso = root->getTag ("PanaISO"); if (iso) { std::string isov = iso->valueToString (); @@ -2565,225 +2770,310 @@ TagDirectory* ExifManager::parse (FILE* f, int base, bool skipIgnored) exif->getDirectory()->addTagFront (niso); } } - } else if (make && (!strncmp ((char*)make->getValue(), "Panasonic", 9) || !strncmp ((char*)make->getValue(), "LEICA", 5))) { - Tag* iso = root->getTag ("PanaISO"); - - if (iso) { - std::string isov = iso->valueToString (); - Tag* niso = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); - niso->initInt (atoi (isov.c_str()), SHORT); - exif->getDirectory()->addTagFront (niso); - } } - } - if (make && !strncmp ((char*)make->getValue(), "Kodak", 5)) { - if (!exif) { - // old Kodak cameras may have exif tags in IFD0, reparse and create an exif subdir - fseek (f, base + firstifd, SEEK_SET); - TagDirectory* exifdir = new TagDirectory (nullptr, f, base, exifAttribs, order, true); + if (make && !strncmp ((char*)make->getValue(), "Kodak", 5)) { + if (!exif) { + // old Kodak cameras may have exif tags in IFD0, reparse and create an exif subdir + fseek (f, rml->exifBase + ifdOffset, SEEK_SET); + TagDirectory* exifdir = new TagDirectory (nullptr, f, rml->exifBase, exifAttribs, order, true); - exif = new Tag (root, root->getAttrib ("Exif")); - exif->initSubDir (exifdir); - root->addTagFront (exif); + exif = new Tag (root, root->getAttrib ("Exif")); + exif->initSubDir (exifdir); + root->addTagFront (exif); - if (!exif->getDirectory()->getTag ("ISOSpeedRatings") && exif->getDirectory()->getTag ("ExposureIndex")) { - Tag* niso = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); - niso->initInt (exif->getDirectory()->getTag ("ExposureIndex")->toInt(), SHORT); - exif->getDirectory()->addTagFront (niso); + if (!exif->getDirectory()->getTag ("ISOSpeedRatings") && exif->getDirectory()->getTag ("ExposureIndex")) { + Tag* niso = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); + niso->initInt (exif->getDirectory()->getTag ("ExposureIndex")->toInt(), SHORT); + exif->getDirectory()->addTagFront (niso); + } + } + + Tag *kodakIFD = root->getTag ("KodakIFD"); + + if (kodakIFD && kodakIFD->getDirectory()->getTag ("TextualInfo")) { + parseKodakIfdTextualInfo (kodakIFD->getDirectory()->getTag ("TextualInfo"), exif); } } - Tag *kodakIFD = root->getTag ("KodakIFD"); + parse_leafdata (root, order); - if (kodakIFD && kodakIFD->getDirectory()->getTag ("TextualInfo")) { - parseKodakIfdTextualInfo (kodakIFD->getDirectory()->getTag ("TextualInfo"), exif); - } - } + if (make && !strncmp ((char*)make->getValue(), "Hasselblad", 10)) { + /* + Figuring out the Hasselblad model is a mess. Hasselblad raw data comes in four slightly + different containers, 3FR (directly from CF card), FFF (same as 3FR but filtered through + Phocus, calibration data applied and a bit different tags), Adobe-generated DNGs and + Phocus-generated DNGs. - parse_leafdata (root, order); + FFF usually has a sane model name in Model (and is used as reference for what we shall + call the different Hasselblad models), but 3FR only says like "Hasselblad H3D" for + all H3D models, or "Flash Sync" if the back has been used on a mechanical camera body. + V-mount backs may have the model name of the V body instead of the back model. Etc... + as said it's a mess. - if (make && !strncmp ((char*)make->getValue(), "Hasselblad", 10)) { - /* - Figuring out the Hasselblad model is a mess. Hasselblad raw data comes in four slightly - different containers, 3FR (directly from CF card), FFF (same as 3FR but filtered through - Phocus, calibration data applied and a bit different tags), Adobe-generated DNGs and - Phocus-generated DNGs. + This code is supposed to handle all raw containers and end up with the same model + regardless of container. - FFF usually has a sane model name in Model (and is used as reference for what we shall - call the different Hasselblad models), but 3FR only says like "Hasselblad H3D" for - all H3D models, or "Flash Sync" if the back has been used on a mechanical camera body. - V-mount backs may have the model name of the V body instead of the back model. Etc... - as said it's a mess. + We don't differ between single shot and multi-shot models, and probably there's no use + of doing so. You need Hasselblad's own software to shoot multi-shot and can only do that + tethered. In single-shot mode they should be exactly the same as the single-shot models. + */ + Tag *subd = root->getTag (0x14a); + Tag *iw = (subd) ? subd->getDirectory()->getTag ("ImageWidth") : nullptr; + int sensorWidth = (iw) ? iw->toInt() : 0; + Tag* tmodel = root->getTag ("Model"); + const char *model = (tmodel) ? (const char *)tmodel->getValue() : ""; - This code is supposed to handle all raw containers and end up with the same model - regardless of container. + if (strstr (model, "Hasselblad ") == model) { + model += 11; + } else { + // if HxD is used in flash sync mode for example, we need to fetch model from this tag + Tag* tmodel3 = root->getTag ("UniqueCameraModel"); + const char *model3 = (tmodel3) ? (const char *)tmodel3->getValue() : ""; - We don't differ between single shot and multi-shot models, and probably there's no use - of doing so. You need Hasselblad's own software to shoot multi-shot and can only do that - tethered. In single-shot mode they should be exactly the same as the single-shot models. - */ - Tag *subd = root->getTag (0x14a); - Tag *iw = (subd) ? subd->getDirectory()->getTag ("ImageWidth") : nullptr; - int sensorWidth = (iw) ? iw->toInt() : 0; - Tag* tmodel = root->getTag ("Model"); - const char *model = (tmodel) ? (const char *)tmodel->getValue() : ""; + if (strstr (model3, "Hasselblad ") == model3) { + model = model3 + 11; + } + } - if (strstr (model, "Hasselblad ") == model) { - model += 11; - } else { - // if HxD is used in flash sync mode for example, we need to fetch model from this tag + // FIXME: due to lack of test files this Hasselblad model identification is not 100% complete + // This needs checking out: CFV-39/CFV-50 3FR, H3DII vs H3D, old CF/CFH models + + if (!strcmp (model, "H3D")) { + // We can't differ between H3D and H3DII for the 22, 31 and 39 models. There's was no H3D-50 so we know that is a + // H3DII-50. At the time of writing I have no test files for the H3D vs H3DII models, so there still may be a chance + // to differ between them. AFAIK Adobe's DNG converter don't differ between them, and actually call the H3DII-50 + // H3D-50 although Hasselblad never released such a model. + switch (sensorWidth) { + case 4096: + tmodel->initString ("H3D-22"); + break; + + case 6542: + tmodel->initString ("H3D-31"); + break; + + case 7262: + tmodel->initString ("H3D-39"); + break; + + case 8282: + tmodel->initString ("H3DII-50"); + break; + } + } else if (!strcmp (model, "H4D")) { + switch (sensorWidth) { + case 6542: + tmodel->initString ("H4D-31"); + break; + + case 7410: + tmodel->initString ("H4D-40"); + break; + + case 8282: + tmodel->initString ("H4D-50"); + break; + + case 9044: + tmodel->initString ("H4D-60"); + break; + } + } else if (!strcmp (model, "H5D")) { + switch (sensorWidth) { + case 7410: + tmodel->initString ("H5D-40"); + break; + + case 8282: + tmodel->initString ("H5D-50"); + break; + + case 8374: + tmodel->initString ("H5D-50c"); + break; + + case 9044: + tmodel->initString ("H5D-60"); + break; + } + } else if (!strcmp (model, "CFV")) { + switch (sensorWidth) { + case 7262: + tmodel->initString ("CFV-39"); + break; + + case 8282: + tmodel->initString ("CFV-50"); + break; + + case 8374: + tmodel->initString ("CFV-50c"); + break; + } + } + + // and a few special cases Tag* tmodel3 = root->getTag ("UniqueCameraModel"); const char *model3 = (tmodel3) ? (const char *)tmodel3->getValue() : ""; if (strstr (model3, "Hasselblad ") == model3) { - model = model3 + 11; - } - } - - // FIXME: due to lack of test files this Hasselblad model identification is not 100% complete - // This needs checking out: CFV-39/CFV-50 3FR, H3DII vs H3D, old CF/CFH models - - if (!strcmp (model, "H3D")) { - // We can't differ between H3D and H3DII for the 22, 31 and 39 models. There's was no H3D-50 so we know that is a - // H3DII-50. At the time of writing I have no test files for the H3D vs H3DII models, so there still may be a chance - // to differ between them. AFAIK Adobe's DNG converter don't differ between them, and actually call the H3DII-50 - // H3D-50 although Hasselblad never released such a model. - switch (sensorWidth) { - case 4096: - tmodel->initString ("H3D-22"); - break; - - case 6542: - tmodel->initString ("H3D-31"); - break; - - case 7262: - tmodel->initString ("H3D-39"); - break; - - case 8282: - tmodel->initString ("H3DII-50"); - break; - } - } else if (!strcmp (model, "H4D")) { - switch (sensorWidth) { - case 6542: - tmodel->initString ("H4D-31"); - break; - - case 7410: - tmodel->initString ("H4D-40"); - break; - - case 8282: - tmodel->initString ("H4D-50"); - break; - - case 9044: - tmodel->initString ("H4D-60"); - break; - } - } else if (!strcmp (model, "H5D")) { - switch (sensorWidth) { - case 7410: - tmodel->initString ("H5D-40"); - break; - - case 8282: - tmodel->initString ("H5D-50"); - break; - - case 8374: - tmodel->initString ("H5D-50c"); - break; - - case 9044: - tmodel->initString ("H5D-60"); - break; - } - } else if (!strcmp (model, "CFV")) { - switch (sensorWidth) { - case 7262: - tmodel->initString ("CFV-39"); - break; - - case 8282: - tmodel->initString ("CFV-50"); - break; - - case 8374: - tmodel->initString ("CFV-50c"); - break; - } - } - - // and a few special cases - Tag* tmodel3 = root->getTag ("UniqueCameraModel"); - const char *model3 = (tmodel3) ? (const char *)tmodel3->getValue() : ""; - - if (strstr (model3, "Hasselblad ") == model3) { - model3 = model3 + 11; - } - - if (!strcmp (model3, "ixpressCF132")) { - tmodel->initString ("CF-22"); - } else if (!strcmp (model3, "Hasselblad96")) { - tmodel->initString ("CFV"); // popularly called CFV-16, but the official name is CFV - } else if (!strcmp (model3, "Hasselblad234")) { - tmodel->initString ("CFV-39"); - } else if (sensorWidth == 4090) { - tmodel->initString ("V96C"); - } - - // and yet some, this is for Adobe-generated DNG files - Tag* tmodel4 = root->getTag ("LocalizedCameraModel"); - - if (tmodel4) { - const char *model4 = (const char *)tmodel4->getValue(); - - if (strstr (model4, "Hasselblad ") == model4) { - model4 = model4 + 11; + model3 = model3 + 11; } - if (!strcmp (model4, "ixpressCF132-22")) { + if (!strcmp (model3, "ixpressCF132")) { tmodel->initString ("CF-22"); - } else if (!strcmp (model4, "Hasselblad96-16")) { - tmodel->initString ("CFV"); - } else if (!strcmp (model4, "Hasselblad234-39")) { + } else if (!strcmp (model3, "Hasselblad96")) { + tmodel->initString ("CFV"); // popularly called CFV-16, but the official name is CFV + } else if (!strcmp (model3, "Hasselblad234")) { tmodel->initString ("CFV-39"); - } else if (!strcmp (model4, "H3D-50")) { - // Adobe names H3DII-50 incorrectly as H3D-50 - tmodel->initString ("H3DII-50"); - } else if (strstr (model4, "H3D-") == model4 || strstr (model4, "H4D-") == model4 || strstr (model4, "H5D-") == model4) { - tmodel->initString (model4); - } - } - } - - if (!root->getTag ("Orientation")) { - if (make && !strncmp ((char*)make->getValue(), "Phase One", 9)) { - int orientation = 0; - Tag *iw = root->getTag ("ImageWidth"); - - if (iw) { - // from dcraw, derive orientation from image width - orientation = "0653"[iw->toInt() & 3] - '0'; + } else if (sensorWidth == 4090) { + tmodel->initString ("V96C"); } - Tag *t = new Tag (root, root->getAttrib ("Orientation")); - t->initInt (orientation, SHORT); - root->addTagFront (t); + // and yet some, this is for Adobe-generated DNG files + Tag* tmodel4 = root->getTag ("LocalizedCameraModel"); + + if (tmodel4) { + const char *model4 = (const char *)tmodel4->getValue(); + + if (strstr (model4, "Hasselblad ") == model4) { + model4 = model4 + 11; + } + + if (!strcmp (model4, "ixpressCF132-22")) { + tmodel->initString ("CF-22"); + } else if (!strcmp (model4, "Hasselblad96-16")) { + tmodel->initString ("CFV"); + } else if (!strcmp (model4, "Hasselblad234-39")) { + tmodel->initString ("CFV-39"); + } else if (!strcmp (model4, "H3D-50")) { + // Adobe names H3DII-50 incorrectly as H3D-50 + tmodel->initString ("H3DII-50"); + } else if (strstr (model4, "H3D-") == model4 || strstr (model4, "H4D-") == model4 || strstr (model4, "H5D-") == model4) { + tmodel->initString (model4); + } + } } + + if (!root->getTag ("Orientation")) { + if (make && !strncmp ((char*)make->getValue(), "Phase One", 9)) { + int orientation = 0; + Tag *iw = root->getTag ("ImageWidth"); + + if (iw) { + // from dcraw, derive orientation from image width + orientation = "0653"[iw->toInt() & 3] - '0'; + } + + Tag *t = new Tag (root, root->getAttrib ("Orientation")); + t->initInt (orientation, SHORT); + root->addTagFront (t); + } + } + + // --- detecting image root IFD based on SubFileType, or if not provided, on PhotometricInterpretation + + bool frameRootDetected = false; + + if(!frameRootDetected) { + std::vector risTagList = root->findTags("RawImageSegmentation"); + if (!risTagList.empty()) { + for (auto ris : risTagList) { + frames.push_back(ris->getParent()); + frameRootDetected = true; + + #if PRINT_METADATA_TREE + printf("\n--------------- FRAME (RAWIMAGESEGMENTATION) ---------------\n\n"); + ris->getParent()->printAll (); + #endif + } + } + } + + if(!frameRootDetected) { + std::vector sftTagList = root->findTags(TIFFTAG_SUBFILETYPE); + if (!sftTagList.empty()) { + for (auto sft : sftTagList) { + int sftVal = sft->toInt(); + if (sftVal == (isRaw ? 0 : 2)) { + frames.push_back(sft->getParent()); + frameRootDetected = true; + +#if PRINT_METADATA_TREE + printf("\n--------------- FRAME (SUBFILETYPE) ---------------\n\n"); + sft->getParent()->printAll (); +#endif + } + } + } + } + + if(!frameRootDetected) { + std::vector sftTagList = root->findTags(TIFFTAG_OSUBFILETYPE); + if (!sftTagList.empty()) { + for (auto sft : sftTagList) { + int sftVal = sft->toInt(); + if (sftVal == OFILETYPE_IMAGE) { + frames.push_back(sft->getParent()); + frameRootDetected = true; + +#if PRINT_METADATA_TREE + printf("\n--------------- FRAME (OSUBFILETYPE) ---------------\n\n"); + sft->getParent()->printAll (); +#endif + } + } + } + } + + if(!frameRootDetected) { + std::vector piTagList = root->findTags("PhotometricInterpretation"); + if (!piTagList.empty()) { + for (auto pi : piTagList) { + int piVal = pi->toInt(); + if (piVal == (isRaw ? 32803 : 2)) { + frames.push_back(pi->getParent()); + //frameRootDetected = true; not used afterward + +#if PRINT_METADATA_TREE + printf("\n--------------- FRAME (PHOTOMETRIC) ---------------\n\n"); + pi->getParent()->printAll (); +#endif + } + } + } + } + + // --- getting next sibling root + + ifdOffset = get4 (f, order); + + roots.push_back(root); + +#if PRINT_METADATA_TREE + printf("\n~~~~~~~~~ ROOT ~~~~~~~~~~~~~~~~~~~~~~~~\n\n"); + root->printAll (); +#endif + + } while (ifdOffset && !onlyFirst); + + // Security check : if there's at least one root, there must be at least one image. + // If the following occurs, then image detection above has failed or it's an unsupported file type. + // Yet the result of this should be valid. + if (!roots.empty() && frames.empty()) { + frames.push_back(roots.at(0)); } - -// root->printAll (); - - return root; } -TagDirectory* ExifManager::parseJPEG (FILE* f, int offset) +void ExifManager::parseJPEG (int offset) { + if (!f) { + #ifndef NDEBUG + std::cerr << "ERROR : no file opened !" << std::endl; + #endif + return; + } if(!fseek (f, offset, SEEK_SET)) { unsigned char c; @@ -2800,25 +3090,39 @@ TagDirectory* ExifManager::parseJPEG (FILE* f, int offset) if (fread (&c, 1, 1, f) && c == 0xe1) { // APP1 marker found if (fread (idbuff, 1, 8, f) < 8) { - return nullptr; + return; } if (!memcmp (idbuff + 2, exifid, 6)) { // Exif info found tiffbase = ftell (f); - return parse (f, tiffbase); + + // We need a RawMetaDataLocation to put the 'tiffbase' value + const bool rmlCreated = !rml; + if (rmlCreated) { + rml.reset(new rtengine::RawMetaDataLocation(0)); + } + rml->exifBase = tiffbase; + parse (false); + if (rmlCreated) { + rml.reset(); + } + return; } } } } } - - return nullptr; } -TagDirectory* ExifManager::parseTIFF (FILE* f, bool skipIgnored) +void ExifManager::parseTIFF (bool skipIgnored) { - - return parse (f, 0, skipIgnored); + if (!rml) { + rml.reset(new rtengine::RawMetaDataLocation(0)); + parse(false, skipIgnored); + rml.reset(); + } else { + parse (false,skipIgnored); + } } std::vector ExifManager::getDefaultTIFFTags (TagDirectory* forthis) diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index 0167ef445..125d38c94 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -27,10 +27,13 @@ #include #include #include +#include + #include #include "../rtengine/procparams.h" #include "../rtengine/noncopyable.h" +#include "../rtengine/rawmetadatalocation.h" class CacheImageData; @@ -46,9 +49,9 @@ enum ActionCode { AC_INVALID = 100, // invalid state }; -enum ByteOrder {INTEL = 0x4949, MOTOROLA = 0x4D4D}; +enum ByteOrder {UNKNOWN = 0, INTEL = 0x4949, MOTOROLA = 0x4D4D}; #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ -const enum ByteOrder HOSTORDER = INTEL; +const ByteOrder HOSTORDER = INTEL; #else const enum ByteOrder HOSTORDER = MOTOROLA; #endif @@ -99,10 +102,10 @@ class TagDirectory { protected: - std::vector tags; // tags in the directory - const TagAttrib* attribs; // descriptor table to decode the tags - ByteOrder order; // byte order - TagDirectory* parent; // parent directory (NULL if root) + std::vector tags; // tags in the directory + const TagAttrib* attribs; // descriptor table to decode the tags + ByteOrder order; // byte order + TagDirectory* parent; // parent directory (NULL if root) static Glib::ustring getDumpKey (int tagID, const Glib::ustring &tagName); public: @@ -125,16 +128,31 @@ public: return tags.size (); } const TagAttrib* getAttrib (int id); - const TagAttrib* getAttrib (const char* name); // Find a Tag by scanning the whole tag tree and stopping at the first occurrence - const TagAttrib* getAttribP (const char* name); // Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength") + // Find a Tag by scanning the whole tag tree and stopping at the first occurrence + const TagAttrib* getAttrib (const char* name); + // Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength") + const TagAttrib* getAttribP (const char* name); const TagAttrib* getAttribTable() { return attribs; } - Tag* getTag (const char* name) const; // Find a Tag by scanning the whole tag tree and stopping at the first occurrence - Tag* getTagP (const char* name) const; // Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength") + // Find a Tag by scanning the whole tag tree and stopping at the first occurrence + Tag* getTag (const char* name) const; + // Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength") + Tag* getTagP (const char* name) const; Tag* getTag (int ID) const; - virtual Tag* findTag (const char* name) const; + + // Try to get the Tag in the current directory and in subdirectories + // if lookUpward = true, it will scan the parents TagDirectory up to the root one, + // but w/o looking into their subdirs + virtual Tag* findTag (const char* name, bool lookUpward = false) const; + // Find a all Tags with the given name by scanning the whole tag tree + std::vector findTags (const char* name); + // Find a all Tags with the given ID by scanning the whole tag tree + std::vector findTags (int ID); + // Try to get the Tag in the current directory and in parent directories + // (won't look into subdirs) + virtual Tag* findTagUpward (const char* name) const; bool getXMPTagValue (const char* name, char* value) const; void keepTag (int ID); @@ -153,7 +171,7 @@ public: virtual int calculateSize (); virtual int write (int start, unsigned char* buffer); virtual TagDirectory* clone (TagDirectory* parent); - virtual void applyChange (std::string field, std::string value); + virtual void applyChange (std::string field, Glib::ustring value); virtual void printAll (unsigned int level = 0) const; // reentrant debug function, keep level=0 on first call ! virtual bool CPBDump (const Glib::ustring &commFName, const Glib::ustring &imageFName, const Glib::ustring &profileFName, const Glib::ustring &defaultPParams, @@ -207,15 +225,16 @@ public: Tag (TagDirectory* parent, const TagAttrib* attr, const char* data); // create a new tag from array (used ~Tag (); - void initType (unsigned char *data, TagType type); - void initInt (int data, TagType t, int count = 1); - void initString (const char* text); - void initSubDir (); - void initSubDir (TagDirectory* dir); - void initMakerNote (MNKind mnk, const TagAttrib* ta); - void initUndefArray (const char* data, int len); - void initLongArray (const char* data, int len); - void initRational (int num, int den); + void initType (unsigned char *data, TagType type); + void initInt (int data, TagType t, int count = 1); + void initUserComment (const Glib::ustring &text); + void initString (const char* text); + void initSubDir (); + void initSubDir (TagDirectory* dir); + void initMakerNote (MNKind mnk, const TagAttrib* ta); + void initUndefArray (const char* data, int len); + void initLongArray (const char* data, int len); + void initRational (int num, int den); // get basic tag properties int getID () const @@ -260,9 +279,9 @@ public: } // read/write value - int toInt (int ofs = 0, TagType astype = INVALID); + int toInt (int ofs = 0, TagType astype = INVALID) const; void fromInt (int v); - double toDouble (int ofs = 0); + double toDouble (int ofs = 0) const; double *toDoubleArray (int ofs = 0); void toRational (int& num, int& denom, int ofs = 0); void toString (char* buffer, int ofs = 0); @@ -271,9 +290,10 @@ public: // additional getter/setter for more comfortable use - std::string valueToString (); - std::string nameToString (int i = 0); - void valueFromString (const std::string& value); + std::string valueToString (); + std::string nameToString (int i = 0); + void valueFromString (const std::string& value); + void userCommentFromString (const Glib::ustring& text); // functions for writing int calculateSize (); @@ -309,13 +329,31 @@ public: class ExifManager { - static Tag* saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const char* name); + Tag* saveCIFFMNTag (TagDirectory* root, int len, const char* name); + void parseCIFF (int length, TagDirectory* root); + void parse (bool isRaw, bool skipIgnored = true); + public: - static TagDirectory* parse (FILE*f, int base, bool skipIgnored = true); - static TagDirectory* parseJPEG (FILE*f, int offset = 0); // offset: to extract exif data from a embedded preview/thumbnail - static TagDirectory* parseTIFF (FILE*f, bool skipIgnored = true); - static TagDirectory* parseCIFF (FILE* f, int base, int length); - static void parseCIFF (FILE* f, int base, int length, TagDirectory* root); + FILE* f; + std::unique_ptr rml; + ByteOrder order; + bool onlyFirst; // Only first IFD + unsigned int IFDOffset; + std::vector roots; + std::vector frames; + + ExifManager (FILE* fHandle, std::unique_ptr _rml, bool onlyFirstIFD) + : f(fHandle), rml(std::move(_rml)), order(UNKNOWN), onlyFirst(onlyFirstIFD), + IFDOffset(0) {} + + void setIFDOffset(unsigned int offset); + + + void parseRaw (bool skipIgnored = true); + void parseStd (bool skipIgnored = true); + void parseJPEG (int offset = 0); // offset: to extract exif data from a embedded preview/thumbnail + void parseTIFF (bool skipIgnored = true); + void parseCIFF (); /// @brief Get default tag for TIFF /// @param forthis The byte order will be taken from the given directory. @@ -352,7 +390,7 @@ public: } } // Get the value as a double - virtual double toDouble (Tag* t, int ofs = 0) + virtual double toDouble (const Tag* t, int ofs = 0) { double ud, dd; @@ -393,7 +431,7 @@ public: } } // Get the value as an int - virtual int toInt (Tag* t, int ofs = 0, TagType astype = INVALID) + virtual int toInt (const Tag* t, int ofs = 0, TagType astype = INVALID) { int a; diff --git a/rtexif/sonyminoltaattribs.cc b/rtexif/sonyminoltaattribs.cc index 4e5fa4ba2..7680e53eb 100644 --- a/rtexif/sonyminoltaattribs.cc +++ b/rtexif/sonyminoltaattribs.cc @@ -2044,7 +2044,7 @@ public: return "n/a"; } } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT TagType astype = t->getType(); @@ -2063,7 +2063,7 @@ public: return 0.; } } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT int a = 0; @@ -2104,7 +2104,7 @@ public: return "n/a"; } } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT TagType astype = t->getType(); @@ -2123,7 +2123,7 @@ public: return 0.; } } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT int a = 0; @@ -2164,7 +2164,7 @@ public: return "Auto"; } } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT int a = 0; @@ -2200,7 +2200,7 @@ public: sprintf (buffer, "%.2f", a ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { // Get the value int a = t->getValue()[ofs]; @@ -2220,7 +2220,7 @@ public: sprintf (buffer, "%d", t->getValue()[0] - 20); return buffer; } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { return t->getValue()[0] - 20; } @@ -2241,7 +2241,7 @@ public: return "Off"; } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { return (t->getValue()[0] & 0x80) == 0x80 ? 1 : 0; } @@ -2259,7 +2259,7 @@ public: sprintf (buffer, "%d", t->getValue()[0] & 0x7f); return buffer; } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { return t->getValue()[0] & 0x7f; } @@ -2315,7 +2315,7 @@ public: sprintf (buffer, "%d", t->toInt()); return buffer; } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { int a = 0; diff --git a/rtexif/stdattribs.cc b/rtexif/stdattribs.cc index 514dd5215..a7e3fe00f 100644 --- a/rtexif/stdattribs.cc +++ b/rtexif/stdattribs.cc @@ -534,11 +534,28 @@ public: }; UTF8BinInterpreter utf8BinInterpreter; +class RawImageSegmentationInterpreter : public Interpreter +{ +public: + virtual std::string toString (Tag* t) + { + int segmentNumber = t->toInt(0, SHORT); + int segmentWidth = t->toInt(2, SHORT); + int lastSegmentWidth = t->toInt(4, SHORT); + + char buffer[32]; + sprintf (buffer, "%d %d %d", segmentNumber, segmentWidth, lastSegmentWidth); + return buffer; + } +}; +RawImageSegmentationInterpreter rawImageSegmentationInterpreter; + const TagAttrib exifAttribs[] = { {0, AC_SYSTEM, 0, nullptr, 0x0100, AUTO, "ImageWidth", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0101, AUTO, "ImageHeight", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0102, AUTO, "BitsPerSample", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0103, AUTO, "Compression", &compressionInterpreter}, + {0, AC_SYSTEM, 0, nullptr, 0x0153, AUTO, "SampleFormat", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0x828d, AUTO, "CFAPatternDim", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0x828e, AUTO, "CFAPattern", &cfaInterpreter}, {0, AC_WRITE, 0, nullptr, 0x829A, AUTO, "ExposureTime", &exposureTimeInterpreter}, @@ -643,9 +660,9 @@ const TagAttrib exifAttribs[] = { {0, AC_WRITE, 0, nullptr, 0xC68B, AUTO, "OriginalRawFileName", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC68D, AUTO, "ActiveArea", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC68E, AUTO, "MaskedAreas", &stdInterpreter}, -// {0, AC_WRITE, 0, 0, 0xC68F, AUTO, "AsShotICCProfile", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC68F, AUTO, "AsShotICCProfile", & ???}, {0, AC_WRITE, 0, nullptr, 0xC690, AUTO, "AsShotPreProfileMatrix", &stdInterpreter}, -// {0, AC_WRITE, 0, 0, 0xC691, AUTO, "CurrentICCProfile", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC691, AUTO, "CurrentICCProfile", & ???}, {0, AC_WRITE, 0, nullptr, 0xC692, AUTO, "CurrentPreProfileMatrix", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC6BF, AUTO, "ColorimetricReference", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC6F3, AUTO, "CameraCalibrationSig", &stdInterpreter}, @@ -670,13 +687,13 @@ const TagAttrib exifAttribs[] = { {0, AC_WRITE, 0, nullptr, 0xC71B, AUTO, "PreviewDateTime", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC71C, AUTO, "RawImageDigest", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC71D, AUTO, "OriginalRawFileDigest", &stdInterpreter}, -// {0, AC_WRITE, 0, 0, 0xC71E, AUTO, "SubTileBlockSize", & ???}, -// {0, AC_WRITE, 0, 0, 0xC71F, AUTO, "RowInterleaveFactor", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC71E, AUTO, "SubTileBlockSize", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC71F, AUTO, "RowInterleaveFactor", & ???}, {0, AC_WRITE, 0, nullptr, 0xC725, AUTO, "ProfileLookTableDims", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC726, AUTO, "ProfileLookTableData", &stdInterpreter}, -// {0, AC_WRITE, 0, 0, 0xC740, AUTO, "OpcodeList1", & ???}, -// {0, AC_WRITE, 0, 0, 0xC741, AUTO, "OpcodeList2", & ???}, -// {0, AC_WRITE, 0, 0, 0xC74E, AUTO, "OpcodeList3", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC740, AUTO, "OpcodeList1", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC741, AUTO, "OpcodeList2", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC74E, AUTO, "OpcodeList3", & ???}, {0, AC_WRITE, 0, nullptr, 0xC761, AUTO, "NoiseProfile", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC763, AUTO, "TimeCodes", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC764, AUTO, "FrameRate", &stdInterpreter}, @@ -753,6 +770,7 @@ const TagAttrib iopAttribs[] = { const TagAttrib ifdAttribs[] = { {0, AC_SYSTEM, 0, nullptr, 0x0017, AUTO, "PanaISO", &stdInterpreter}, + {0, AC_SYSTEM, 0, nullptr, 0x00fe, AUTO, "NewSubFileType", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0100, AUTO, "ImageWidth", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0101, AUTO, "ImageHeight", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0102, AUTO, "BitsPerSample", &stdInterpreter}, @@ -777,6 +795,7 @@ const TagAttrib ifdAttribs[] = { {0, AC_SYSTEM, 0, nullptr, 0x013E, AUTO, "WhitePoint", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x013F, AUTO, "PriomaryChromaticities", &stdInterpreter}, {0, AC_WRITE, 0, ifdAttribs, 0x014A, AUTO, "SubIFD", &stdInterpreter}, + {0, AC_SYSTEM, 0, nullptr, 0x0153, AUTO, "SampleFormat", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0201, AUTO, "JPEGInterchangeFormat", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0202, AUTO, "JPEGInterchangeFormatLength", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0211, AUTO, "YCbCrCoefficients", &stdInterpreter}, @@ -807,9 +826,9 @@ const TagAttrib ifdAttribs[] = { {0, AC_WRITE, 0, nullptr, 0xc62f, AUTO, "CameraSerialNumber", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0xc630, AUTO, "DNGLensInfo", &stdInterpreter}, {0, AC_DONTWRITE, 0, nullptr, 0xC634, AUTO, "MakerNote", &stdInterpreter}, //DNGPrivateData + {0, AC_SYSTEM, 0, nullptr, 0xC640, AUTO, "RawImageSegmentation", &rawImageSegmentationInterpreter}, {0, AC_WRITE, 0, nullptr, 0xc65d, AUTO, "RawDataUniqueID", &stdInterpreter}, {0, AC_DONTWRITE, 0, nullptr, 0xc761, AUTO, "NoiseProfile", &stdInterpreter}, - {0, AC_SYSTEM, 0, nullptr, 0x00fe, AUTO, "NewSubFileType", &stdInterpreter}, { -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr} }; } diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index 489f74123..990ff69b9 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -25,31 +25,14 @@ using namespace rtengine::procparams; -BatchToolPanelCoordinator::BatchToolPanelCoordinator (FilePanel* parent) : ToolPanelCoordinator(), somethingChanged (false), parent (parent) +BatchToolPanelCoordinator::BatchToolPanelCoordinator (FilePanel* parent) : ToolPanelCoordinator(true), somethingChanged(false), parent(parent) { blockedUpdate = false; - // remove exif panel and iptc panel - std::vector::iterator epi = std::find (toolPanels.begin(), toolPanels.end(), exifpanel); - - if (epi != toolPanels.end()) { - toolPanels.erase (epi); - } - - std::vector::iterator ipi = std::find (toolPanels.begin(), toolPanels.end(), iptcpanel); - - if (ipi != toolPanels.end()) { - toolPanels.erase (ipi); - } - if (toolBar) { toolBar->setBatchMode (); } - toolPanelNotebook->remove_page (*metadataPanel); - metadataPanel = nullptr; - toiM = nullptr; - for (size_t i = 0; i < toolPanels.size(); i++) { toolPanels[i]->setBatchMode (true); } diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 34983d46a..dbb3b2946 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -24,8 +24,9 @@ CacheImageData::CacheImageData () : md5(""), supported(false), format(FT_Invalid), rankOld(-1), inTrashOld(false), recentlySaved(false), - timeValid(false), year(0), month(0), day(0), hour(0), min(0), sec(0), exifValid(false), - fnumber(0.0), shutter(0.0), focalLen(0.0), focalLen35mm(0.0), focusDist(0.f), iso(0), + timeValid(false), year(0), month(0), day(0), hour(0), min(0), sec(0), exifValid(false), frameCount(1), + fnumber(0.0), shutter(0.0), focalLen(0.0), focalLen35mm(0.0), focusDist(0.f), iso(0), isHDR (false), + isPixelShift (false), sensortype(rtengine::ST_NONE), sampleFormat(rtengine::IIOSF_UNKNOWN), redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), rotate(0), thumbImgType(0) { } @@ -138,6 +139,14 @@ int CacheImageData::load (const Glib::ustring& fname) iso = keyFile.get_integer ("ExifInfo", "ISO"); } + if (keyFile.has_key ("ExifInfo", "IsHDR")) { + isHDR = keyFile.get_boolean ("ExifInfo", "IsHDR"); + } + + if (keyFile.has_key ("ExifInfo", "IsPixelShift")) { + isPixelShift = keyFile.get_boolean ("ExifInfo", "IsPixelShift"); + } + if (keyFile.has_key ("ExifInfo", "ExpComp")) { expcomp = keyFile.get_string ("ExifInfo", "ExpComp"); } @@ -160,12 +169,21 @@ int CacheImageData::load (const Glib::ustring& fname) if (keyFile.has_key ("FileInfo", "Filetype")) { filetype = keyFile.get_string ("FileInfo", "Filetype"); } + if (keyFile.has_key ("FileInfo", "FrameCount")) { + frameCount = static_cast(keyFile.get_integer ("FileInfo", "FrameCount")); + } + if (keyFile.has_key ("FileInfo", "SampleFormat")) { + sampleFormat = (rtengine::IIO_Sample_Format)keyFile.get_integer ("FileInfo", "SampleFormat"); + } } if (format == FT_Raw && keyFile.has_group ("ExtraRawInfo")) { if (keyFile.has_key ("ExtraRawInfo", "ThumbImageType")) { thumbImgType = keyFile.get_integer ("ExtraRawInfo", "ThumbImageType"); } + if (keyFile.has_key ("ExtraRawInfo", "SensorType")) { + sensortype = keyFile.get_integer ("ExtraRawInfo", "SensorType"); + } } else { rotate = 0; thumbImgType = 0; @@ -235,6 +253,8 @@ int CacheImageData::save (const Glib::ustring& fname) keyFile.set_double ("ExifInfo", "FocalLen35mm", focalLen35mm); keyFile.set_double ("ExifInfo", "FocusDist", focusDist); keyFile.set_integer ("ExifInfo", "ISO", iso); + keyFile.set_boolean ("ExifInfo", "IsHDR", isHDR); + keyFile.set_boolean ("ExifInfo", "IsPixelShift", isPixelShift); keyFile.set_string ("ExifInfo", "ExpComp", expcomp); } @@ -242,9 +262,12 @@ int CacheImageData::save (const Glib::ustring& fname) keyFile.set_string ("ExifInfo", "CameraMake", camMake); keyFile.set_string ("ExifInfo", "CameraModel", camModel); keyFile.set_string ("FileInfo", "Filetype", filetype); + keyFile.set_integer ("FileInfo", "FrameCount", frameCount); + keyFile.set_integer ("FileInfo", "SampleFormat", sampleFormat); if (format == FT_Raw) { keyFile.set_integer ("ExtraRawInfo", "ThumbImageType", thumbImgType); + keyFile.set_integer ("ExtraRawInfo", "SensorType", sensortype); } keyData = keyFile.to_data (); diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index 63eebf25c..52675d77b 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -22,8 +22,9 @@ #include #include "options.h" #include "../rtengine/rtengine.h" +#include "../rtengine/imageformat.h" -class CacheImageData: public rtengine::ImageMetaData +class CacheImageData: public rtengine::FramesMetaData { public: @@ -47,11 +48,16 @@ public: char sec; // exif info bool exifValid; + unsigned short frameCount; double fnumber; double shutter; double focalLen, focalLen35mm; float focusDist; unsigned iso; + bool isHDR; + bool isPixelShift; + int sensortype; + rtengine::IIO_Sample_Format sampleFormat; Glib::ustring lens; Glib::ustring camMake; Glib::ustring camModel; @@ -78,25 +84,32 @@ public: int save (const Glib::ustring& fname); //------------------------------------------------------------------------- - // ImageMetaData interface + // FramesMetaData interface //------------------------------------------------------------------------- - bool hasExif() const { return false; } - const rtexif::TagDirectory *getExifData() const { return NULL; } - bool hasIPTC() const { return false; } - const rtengine::procparams::IPTCPairs getIPTCData () const { return rtengine::procparams::IPTCPairs(); } - tm getDateTime () const { return tm{}; } - time_t getDateTimeAsTS() const { return time_t(-1); } - int getISOSpeed() const { return iso; } - double getFNumber() const { return fnumber; } - double getFocalLen() const { return focalLen; } - double getFocalLen35mm() const { return focalLen35mm; } - float getFocusDist() const { return focusDist; } - double getShutterSpeed() const { return shutter; } - double getExpComp() const { return atof(expcomp.c_str()); } - std::string getMake() const { return camMake; } - std::string getModel() const { return camModel; } - std::string getLens() const { return lens; } - std::string getOrientation() const { return ""; } // TODO + unsigned int getRootCount () const { return -1; } + unsigned int getFrameCount () const { return frameCount; } + bool hasExif (unsigned int frame = 0) const { return false; } + rtexif::TagDirectory* getRootExifData (unsigned int root = 0) const { return nullptr; } + rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const { return nullptr; } + rtexif::TagDirectory* getBestExifData (rtengine::ImageSource *imgSource, rtengine::procparams::RAWParams *rawParams) const { return nullptr; } + bool hasIPTC (unsigned int frame = 0) const { return false; } + rtengine::procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const { return rtengine::procparams::IPTCPairs(); } + tm getDateTime (unsigned int frame = 0) const { return tm{}; } + time_t getDateTimeAsTS(unsigned int frame = 0) const { return time_t(-1); } + int getISOSpeed (unsigned int frame = 0) const { return iso; } + double getFNumber (unsigned int frame = 0) const { return fnumber; } + double getFocalLen (unsigned int frame = 0) const { return focalLen; } + double getFocalLen35mm (unsigned int frame = 0) const { return focalLen35mm; } + float getFocusDist (unsigned int frame = 0) const { return focusDist; } + double getShutterSpeed (unsigned int frame = 0) const { return shutter; } + double getExpComp (unsigned int frame = 0) const { return atof(expcomp.c_str()); } + std::string getMake (unsigned int frame = 0) const { return camMake; } + std::string getModel (unsigned int frame = 0) const { return camModel; } + std::string getLens (unsigned int frame = 0) const { return lens; } + std::string getOrientation (unsigned int frame = 0) const { return ""; } // TODO + bool getPixelShift (unsigned int frame = 0) const { return isPixelShift; } + bool getHDR (unsigned int frame = 0) const { return isHDR; } + rtengine::IIOSampleFormat getSampleFormat (unsigned int frame = 0) const { return sampleFormat; } }; #endif diff --git a/rtgui/dynamicprofilepanel.cc b/rtgui/dynamicprofilepanel.cc index db3a19ed0..c8a8a1644 100644 --- a/rtgui/dynamicprofilepanel.cc +++ b/rtgui/dynamicprofilepanel.cc @@ -405,7 +405,7 @@ void DynamicProfilePanel::render_fnumber ( RENDER_RANGE_ (double, fnumber, [] (double f) { return std::string ("f/") + - rtengine::ImageMetaData::apertureToString (f); + rtengine::FramesMetaData::apertureToString (f); }); } @@ -421,7 +421,7 @@ void DynamicProfilePanel::render_shutterspeed ( Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) { RENDER_RANGE_ (double, shutterspeed, - rtengine::ImageMetaData::shutterToString); + rtengine::FramesMetaData::shutterToString); } diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index f3e6189ba..f5c6aa679 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -484,7 +484,12 @@ public: }; EditorPanel::EditorPanel (FilePanel* filePanel) - : catalogPane (nullptr), realized (false), tbBeforeLock (nullptr), iHistoryShow (nullptr), iHistoryHide (nullptr), iTopPanel_1_Show (nullptr), iTopPanel_1_Hide (nullptr), iRightPanel_1_Show (nullptr), iRightPanel_1_Hide (nullptr), iBeforeLockON (nullptr), iBeforeLockOFF (nullptr), previewHandler (nullptr), beforePreviewHandler (nullptr), beforeIarea (nullptr), beforeBox (nullptr), afterBox (nullptr), beforeLabel (nullptr), afterLabel (nullptr), beforeHeaderBox (nullptr), afterHeaderBox (nullptr), parent (nullptr), parentWindow (nullptr), openThm (nullptr), isrc (nullptr), ipc (nullptr), beforeIpc (nullptr), err (0), isProcessing (false) + : catalogPane (nullptr), realized (false), tbBeforeLock (nullptr), iHistoryShow (nullptr), iHistoryHide (nullptr), + iTopPanel_1_Show (nullptr), iTopPanel_1_Hide (nullptr), iRightPanel_1_Show (nullptr), iRightPanel_1_Hide (nullptr), + iBeforeLockON (nullptr), iBeforeLockOFF (nullptr), previewHandler (nullptr), beforePreviewHandler (nullptr), + beforeIarea (nullptr), beforeBox (nullptr), afterBox (nullptr), beforeLabel (nullptr), afterLabel (nullptr), + beforeHeaderBox (nullptr), afterHeaderBox (nullptr), parent (nullptr), parentWindow (nullptr), openThm (nullptr), + selectedFrame(0), isrc (nullptr), ipc (nullptr), beforeIpc (nullptr), err (0), isProcessing (false) { epih = new EditorPanelIdleHelper; @@ -1137,6 +1142,18 @@ void EditorPanel::procParamsChanged (rtengine::procparams::ProcParams* params, r // if (ev!=EvPhotoLoaded) // saveLabel->set_markup (Glib::ustring("") + M("MAIN_BUTTON_SAVE") + ""); + + rtengine::eSensorType sensorType = isrc->getImageSource()->getSensorType(); + + selectedFrame = 0; + if (sensorType == rtengine::ST_BAYER) { + selectedFrame = params->raw.bayersensor.imageNum; + //} else if (sensorType == rtengine::ST_FUJI_XTRANS) { + // selectedFrame = params->raw.xtranssensor.imageNum; + } + selectedFrame = rtengine::LIM(selectedFrame, 0, isrc->getImageSource()->getMetaData()->getFrameCount() - 1); + + info_toggled(); } void EditorPanel::setProgressState (bool inProcessing) @@ -1306,47 +1323,59 @@ void EditorPanel::info_toggled () { Glib::ustring infoString; - Glib::ustring infoString1; //1-st line - Glib::ustring infoString2; //2-nd line - Glib::ustring infoString3; //3-rd line - Glib::ustring infoString4; //4-th line Glib::ustring expcomp; if (!ipc || !openThm) { return; } - const rtengine::ImageMetaData* idata = ipc->getInitialImage()->getMetaData(); + const rtengine::FramesMetaData* idata = ipc->getInitialImage()->getMetaData(); - if (idata && idata->hasExif()) { - infoString1 = Glib::ustring::compose ("%1 + %2", + if (idata && idata->hasExif(selectedFrame)) { + infoString = Glib::ustring::compose ("%1 + %2\nf/%3 %4s %5%6 %7mm", Glib::ustring (idata->getMake() + " " + idata->getModel()), - Glib::ustring (idata->getLens())); + Glib::ustring (idata->getLens()), + Glib::ustring (idata->apertureToString (idata->getFNumber(selectedFrame))), + Glib::ustring (idata->shutterToString (idata->getShutterSpeed(selectedFrame))), + M ("QINFO_ISO"), idata->getISOSpeed(selectedFrame), + Glib::ustring::format (std::setw (3), std::fixed, std::setprecision (2), idata->getFocalLen(selectedFrame))); - infoString2 = Glib::ustring::compose ("f/%1 %2s %3%4 %5mm", - Glib::ustring (idata->apertureToString (idata->getFNumber())), - Glib::ustring (idata->shutterToString (idata->getShutterSpeed())), - M ("QINFO_ISO"), idata->getISOSpeed(), - Glib::ustring::format (std::setw (3), std::fixed, std::setprecision (2), idata->getFocalLen())); + expcomp = Glib::ustring (idata->expcompToString (idata->getExpComp(selectedFrame), true)); // maskZeroexpcomp - expcomp = Glib::ustring (idata->expcompToString (idata->getExpComp(), true)); // maskZeroexpcomp - - if (expcomp != "") { - infoString2 = Glib::ustring::compose ("%1 %2EV", - infoString2, + if (!expcomp.empty ()) { + infoString = Glib::ustring::compose ("%1 %2EV", + infoString, expcomp /*Glib::ustring(idata->expcompToString(idata->getExpComp()))*/); } - infoString3 = Glib::ustring::compose ("%1%2", + infoString = Glib::ustring::compose ("%1\n%2%3", + infoString, escapeHtmlChars (Glib::path_get_dirname (openThm->getFileName())) + G_DIR_SEPARATOR_S, escapeHtmlChars (Glib::path_get_basename (openThm->getFileName())) ); int ww = ipc->getFullWidth(); int hh = ipc->getFullHeight(); //megapixels - infoString4 = Glib::ustring::compose ("%1 MP (%2x%3)", Glib::ustring::format (std::setw (4), std::fixed, std::setprecision (1), (float)ww * hh / 1000000), ww, hh); + infoString = Glib::ustring::compose ("%1\n%2 MP (%3x%4)", + infoString, + Glib::ustring::format (std::setw (4), std::fixed, std::setprecision (1), (float)ww * hh / 1000000), + ww, hh); - infoString = Glib::ustring::compose ("%1\n%2\n%3\n%4", infoString1, infoString2, infoString3, infoString4); + //adding special characteristics + bool isHDR = idata->getHDR(); + bool isPixelShift = idata->getPixelShift(); + unsigned int numFrames = idata->getFrameCount(); + if (isHDR) { + infoString = Glib::ustring::compose ("%1\n" + M("QINFO_HDR"), infoString, numFrames); + if (numFrames == 1) { + int sampleFormat = idata->getSampleFormat(selectedFrame); + infoString = Glib::ustring::compose ("%1 / %2", infoString, M(Glib::ustring::compose("SAMPLEFORMAT_%1", sampleFormat))); + } + } else if (isPixelShift) { + infoString = Glib::ustring::compose ("%1\n" + M("QINFO_PIXELSHIFT"), infoString, numFrames); + } else if (numFrames > 1) { + infoString = Glib::ustring::compose ("%1\n" + M("QINFO_FRAMECOUNT"), infoString, numFrames); + } } else { infoString = M ("QINFO_NOEXIF"); } diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index 9c063661a..5beb9ee7d 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -212,6 +212,8 @@ private: Thumbnail* openThm; // may get invalid on external delete event Glib::ustring fname; // must be saved separately + int selectedFrame; + rtengine::InitialImage* isrc; rtengine::StagedImageProcessor* ipc; rtengine::StagedImageProcessor* beforeIpc; // for the before-after view diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 34cb2c064..2e47786e5 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -25,44 +25,50 @@ using namespace rtengine; using namespace rtengine::procparams; using namespace rtexif; -ExifPanel::ExifPanel () : idata(nullptr) +ExifPanel::ExifPanel () : idata (nullptr) { recursiveOp = true; - exifTree = Gtk::manage(new Gtk::TreeView()); - scrolledWindow = Gtk::manage(new Gtk::ScrolledWindow()); + exifTree = Gtk::manage (new Gtk::TreeView()); + scrolledWindow = Gtk::manage (new Gtk::ScrolledWindow()); - exifTree->set_headers_visible(false); - exifTree->set_rules_hint(false); - exifTree->set_reorderable(false); - exifTree->set_enable_search(true); + exifTree->set_headers_visible (false); + exifTree->set_rules_hint (false); + exifTree->set_reorderable (false); + exifTree->set_enable_search (true); exifTree->get_selection()->set_mode (Gtk::SELECTION_MULTIPLE); - scrolledWindow->set_shadow_type(Gtk::SHADOW_NONE); - scrolledWindow->set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS); - scrolledWindow->property_window_placement().set_value(Gtk::CORNER_TOP_LEFT); - scrolledWindow->add(*exifTree); + scrolledWindow->set_shadow_type (Gtk::SHADOW_NONE); + scrolledWindow->set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS); + scrolledWindow->property_window_placement().set_value (Gtk::CORNER_TOP_LEFT); + scrolledWindow->add (*exifTree); - exifTreeModel = Gtk::TreeStore::create(exifColumns); + exifTreeModel = Gtk::TreeStore::create (exifColumns); exifTree->set_model (exifTreeModel); + exifTree->set_grid_lines (Gtk::TREE_VIEW_GRID_LINES_NONE); + exifTree->set_row_separator_func ( + [&] (const Glib::RefPtr& model, const Gtk::TreeModel::iterator & row) { + return row->get_value (exifColumns.isSeparator); + } + ); delicon = RTImage::createFromFile ("gtk-close.png"); keepicon = RTImage::createFromFile ("gtk-apply.png"); editicon = RTImage::createFromFile ("gtk-add.png"); - Gtk::TreeView::Column *viewcol = Gtk::manage(new Gtk::TreeView::Column ("Field Name")); - Gtk::CellRendererPixbuf* render_pb = Gtk::manage(new Gtk::CellRendererPixbuf ()); - Gtk::CellRendererText *render_txt = Gtk::manage(new Gtk::CellRendererText()); + Gtk::TreeView::Column *viewcol = Gtk::manage (new Gtk::TreeView::Column ("Field Name")); + Gtk::CellRendererPixbuf* render_pb = Gtk::manage (new Gtk::CellRendererPixbuf ()); + Gtk::CellRendererText *render_txt = Gtk::manage (new Gtk::CellRendererText()); render_txt->property_ellipsize() = Pango::ELLIPSIZE_END; viewcol->pack_start (*render_pb, false); viewcol->pack_start (*render_txt, true); viewcol->add_attribute (*render_pb, "pixbuf", exifColumns.icon); viewcol->add_attribute (*render_txt, "markup", exifColumns.field); - viewcol->set_expand(true); + viewcol->set_expand (true); viewcol->set_resizable (true); - viewcol->set_fixed_width(35); - viewcol->set_min_width(35); - viewcol->set_sizing(Gtk::TREE_VIEW_COLUMN_AUTOSIZE); + viewcol->set_fixed_width (35); + viewcol->set_min_width (35); + viewcol->set_sizing (Gtk::TREE_VIEW_COLUMN_AUTOSIZE); render_pb->property_ypad() = 0; render_txt->property_ypad() = 0; @@ -71,16 +77,16 @@ ExifPanel::ExifPanel () : idata(nullptr) exifTree->append_column (*viewcol); - Gtk::TreeView::Column *viewcolv = Gtk::manage(new Gtk::TreeView::Column ("Value")); - Gtk::CellRendererText *render_txtv = Gtk::manage(new Gtk::CellRendererText()); + Gtk::TreeView::Column *viewcolv = Gtk::manage (new Gtk::TreeView::Column ("Value")); + Gtk::CellRendererText *render_txtv = Gtk::manage (new Gtk::CellRendererText()); render_txtv->property_ellipsize() = Pango::ELLIPSIZE_END; viewcolv->pack_start (*render_txtv, true); viewcolv->add_attribute (*render_txtv, "markup", exifColumns.value); - viewcolv->set_expand(true); + viewcolv->set_expand (true); viewcolv->set_resizable (true); - viewcol->set_fixed_width(35); - viewcolv->set_min_width(35); - viewcolv->set_sizing(Gtk::TREE_VIEW_COLUMN_AUTOSIZE); + viewcol->set_fixed_width (35); + viewcolv->set_min_width (35); + viewcolv->set_sizing (Gtk::TREE_VIEW_COLUMN_AUTOSIZE); render_txtv->property_ypad() = 0; @@ -88,61 +94,68 @@ ExifPanel::ExifPanel () : idata(nullptr) pack_start (*scrolledWindow); - Gtk::Grid* buttons1 = Gtk::manage(new Gtk::Grid()); - buttons1->set_row_homogeneous(true); - buttons1->set_column_homogeneous(true); - setExpandAlignProperties(buttons1, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); - Gtk::Grid* buttons2 = Gtk::manage(new Gtk::Grid()); - buttons2->set_row_homogeneous(true); - buttons2->set_column_homogeneous(true); - setExpandAlignProperties(buttons2, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + Gtk::Grid* buttons1 = Gtk::manage (new Gtk::Grid()); + buttons1->set_row_homogeneous (true); + buttons1->set_column_homogeneous (true); + setExpandAlignProperties (buttons1, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + Gtk::Grid* buttons2 = Gtk::manage (new Gtk::Grid()); + buttons2->set_row_homogeneous (true); + buttons2->set_column_homogeneous (true); + setExpandAlignProperties (buttons2, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); - remove = Gtk::manage(new Gtk::Button ()); // M("EXIFPANEL_REMOVE") - remove->set_image (*Gtk::manage(new Gtk::Image (delicon))); - remove->set_tooltip_text (M("EXIFPANEL_REMOVEHINT")); - remove->get_style_context()->add_class("Left"); - setExpandAlignProperties(remove, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - buttons1->attach_next_to(*remove, Gtk::POS_LEFT, 1, 1); + remove = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_REMOVE") + remove->set_image (*Gtk::manage (new Gtk::Image (delicon))); + remove->set_tooltip_text (M ("EXIFPANEL_REMOVEHINT")); + remove->get_style_context()->add_class ("Left"); + setExpandAlignProperties (remove, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + buttons1->attach_next_to (*remove, Gtk::POS_LEFT, 1, 1); - keep = Gtk::manage(new Gtk::Button ()); // M("EXIFPANEL_KEEP") - keep->set_image (*Gtk::manage(new Gtk::Image (keepicon))); - keep->set_tooltip_text (M("EXIFPANEL_KEEPHINT")); - keep->get_style_context()->add_class("MiddleH"); - setExpandAlignProperties(keep, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - buttons1->attach_next_to(*keep, Gtk::POS_RIGHT, 1, 1); + keep = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_KEEP") + keep->set_image (*Gtk::manage (new Gtk::Image (keepicon))); + keep->set_tooltip_text (M ("EXIFPANEL_KEEPHINT")); + keep->get_style_context()->add_class ("MiddleH"); + setExpandAlignProperties (keep, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + buttons1->attach_next_to (*keep, Gtk::POS_RIGHT, 1, 1); - add = Gtk::manage(new Gtk::Button ()); // M("EXIFPANEL_ADDEDIT") - add->set_image (*Gtk::manage(new Gtk::Image (editicon))); - add->set_tooltip_text (M("EXIFPANEL_ADDEDITHINT")); - add->get_style_context()->add_class("Right"); - setExpandAlignProperties(add, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - buttons1->attach_next_to(*add, Gtk::POS_RIGHT, 1, 1); + add = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_ADDEDIT") + add->set_image (*Gtk::manage (new Gtk::Image (editicon))); + add->set_tooltip_text (M ("EXIFPANEL_ADDEDITHINT")); + add->get_style_context()->add_class ("Right"); + setExpandAlignProperties (add, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + buttons1->attach_next_to (*add, Gtk::POS_RIGHT, 1, 1); - reset = Gtk::manage(new Gtk::Button ()); // M("EXIFPANEL_RESET") - reset->set_image (*Gtk::manage(new RTImage ("gtk-undo-ltr.png", "gtk-undo-rtl.png"))); - reset->set_tooltip_text (M("EXIFPANEL_RESETHINT")); - reset->get_style_context()->add_class("Left"); - setExpandAlignProperties(reset, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - buttons2->attach_next_to(*reset, Gtk::POS_LEFT, 1, 1); + showAll = Gtk::manage (new Gtk::ToggleButton (M ("EXIFPANEL_SHOWALL"))); + //add->set_tooltip_text (M("EXIFPANEL_SHOWALL")); + setExpandAlignProperties (showAll, false, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + showAll->set_active (options.lastShowAllExif); + buttons2->attach_next_to (*showAll, Gtk::POS_LEFT, 1, 1); - resetAll = Gtk::manage(new Gtk::Button ()); // M("EXIFPANEL_RESETALL") - resetAll->set_image (*Gtk::manage(new RTImage ("gtk-undoall-ltr.png", "gtk-undoall-rtl.png"))); - resetAll->set_tooltip_text (M("EXIFPANEL_RESETALLHINT")); - resetAll->get_style_context()->add_class("Right"); - setExpandAlignProperties(resetAll, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - buttons2->attach_next_to(*resetAll, Gtk::POS_RIGHT, 1, 1); + reset = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_RESET") + reset->set_image (*Gtk::manage (new RTImage ("gtk-undo-ltr.png", "gtk-undo-rtl.png"))); + reset->set_tooltip_text (M ("EXIFPANEL_RESETHINT")); + reset->get_style_context()->add_class ("Left"); + setExpandAlignProperties (reset, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + buttons2->attach_next_to (*reset, Gtk::POS_RIGHT, 1, 1); + + resetAll = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_RESETALL") + resetAll->set_image (*Gtk::manage (new RTImage ("gtk-undoall-ltr.png", "gtk-undoall-rtl.png"))); + resetAll->set_tooltip_text (M ("EXIFPANEL_RESETALLHINT")); + resetAll->get_style_context()->add_class ("Right"); + setExpandAlignProperties (resetAll, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + buttons2->attach_next_to (*resetAll, Gtk::POS_RIGHT, 1, 1); pack_end (*buttons2, Gtk::PACK_SHRINK); pack_end (*buttons1, Gtk::PACK_SHRINK); - exifTree->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &ExifPanel::exifSelectionChanged)); - exifTree->signal_row_activated().connect(sigc::mem_fun(*this, &ExifPanel::row_activated)); + exifTree->get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ExifPanel::exifSelectionChanged)); + exifTree->signal_row_activated().connect (sigc::mem_fun (*this, &ExifPanel::row_activated)); - remove->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::removePressed) ); - keep->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::keepPressed) ); - reset->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::resetPressed) ); - resetAll->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::resetAllPressed) ); - add->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::addPressed) ); + remove->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::removePressed) ); + keep->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::keepPressed) ); + reset->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::resetPressed) ); + resetAll->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::resetAllPressed) ); + add->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::addPressed) ); + showAll->signal_toggled().connect ( sigc::mem_fun (*this, &ExifPanel::showAlltoggled) ); show_all (); } @@ -177,22 +190,25 @@ void ExifPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pe defChangeList = defParams->exif; } -void ExifPanel::setImageData (const ImageMetaData* id) +void ExifPanel::setImageData (const FramesMetaData* id) { idata = id; exifTreeModel->clear (); - if (id && id->getExifData ()) { -// id->getExifData ()->printAll (); - addDirectory (id->getExifData (), exifTreeModel->children()); + if (idata) { + for (unsigned int rootNum = 0; rootNum < id->getRootCount (); ++rootNum) { + if ( id->getRootExifData (rootNum)) { + addDirectory (id->getRootExifData (rootNum), exifTreeModel->children(), rootNum > 0); + } + } } } Gtk::TreeModel::Children ExifPanel::addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable) { - Gtk::TreeModel::Row row = *(exifTreeModel->append(root)); + Gtk::TreeModel::Row row = * (exifTreeModel->append (root)); row[exifColumns.action] = action; row[exifColumns.editable] = editable; row[exifColumns.edited] = false; @@ -207,36 +223,74 @@ Gtk::TreeModel::Children ExifPanel::addTag (const Gtk::TreeModel::Children& root } if (editable) { - row[exifColumns.field] = Glib::ustring("") + escapeHtmlChars(field) + ""; - row[exifColumns.value] = Glib::ustring("") + escapeHtmlChars(value) + ""; + row[exifColumns.field] = Glib::ustring ("") + escapeHtmlChars (field) + ""; + row[exifColumns.value] = Glib::ustring ("") + escapeHtmlChars (value) + ""; } else if (action == AC_SYSTEM) { - row[exifColumns.field] = Glib::ustring("") + escapeHtmlChars(field) + ""; - row[exifColumns.value] = Glib::ustring("") + escapeHtmlChars(value) + ""; + row[exifColumns.field] = Glib::ustring ("") + escapeHtmlChars (field) + ""; + row[exifColumns.value] = Glib::ustring ("") + escapeHtmlChars (value) + ""; } else { - row[exifColumns.field] = escapeHtmlChars(field); - row[exifColumns.value] = escapeHtmlChars(value); + row[exifColumns.field] = escapeHtmlChars (field); + row[exifColumns.value] = escapeHtmlChars (value); } return row.children(); } -void ExifPanel::addDirectory (const TagDirectory* dir, Gtk::TreeModel::Children root) +Gtk::TreeModel::Children ExifPanel::addSeparator () { - for (int i = 0; i < dir->getCount(); i++) { - Tag* t = (const_cast(dir))->getTagByIndex (i); + Gtk::TreeModel::Row row = * (exifTreeModel->append (exifTreeModel->children())); + row[exifColumns.action] = rtexif::ActionCode::AC_INVALID; + row[exifColumns.editable] = false; + row[exifColumns.edited] = false; + row[exifColumns.field_nopango] = ""; + row[exifColumns.value_nopango] = ""; + row[exifColumns.orig_value] = ""; + row[exifColumns.isSeparator] = true; - if (t->getAttrib() && t->getAttrib()->action == AC_SYSTEM) { + return row.children(); +} + +void ExifPanel::addDirectory (const TagDirectory* dir, Gtk::TreeModel::Children root, bool checkForSeparator) +{ + + for (int i = 0; i < dir->getCount(); ++i) { + Tag* t = (const_cast (dir))->getTagByIndex (i); + + bool hasContent = false; + + if (checkForSeparator && i == 0) { + for (int j = 0; j < dir->getCount(); ++j) { + Tag* t2 = (const_cast (dir))->getTagByIndex (j); + const TagAttrib* currAttrib = t2->getAttrib(); + + if (currAttrib && ((options.lastShowAllExif) || (!options.lastShowAllExif && currAttrib->action != AC_SYSTEM))) { + addSeparator(); + hasContent = true; + break; + } + } + } else { + hasContent = true; + } + + if (!hasContent) { + return; + } + + const TagAttrib* currAttrib = t->getAttrib(); + + if (!options.lastShowAllExif && currAttrib && currAttrib->action == AC_SYSTEM) { continue; } - if (t->isDirectory()) - for (int j = 0; t->getDirectory(j); j++) { - Gtk::TreeModel::Children ch = addTag (root, t->nameToString (j), M("EXIFPANEL_SUBDIRECTORY"), t->getAttrib() ? t->getAttrib()->action : AC_DONTWRITE, t->getAttrib() && t->getAttrib()->editable); - addDirectory (t->getDirectory(j), ch); + if (t->isDirectory()) { + for (int j = 0; t->getDirectory (j); j++) { + Gtk::TreeModel::Children ch = addTag (root, t->nameToString (j), M ("EXIFPANEL_SUBDIRECTORY"), currAttrib ? currAttrib->action : AC_DONTWRITE, currAttrib && currAttrib->editable); + addDirectory (t->getDirectory (j), ch); } - else { - addTag (root, t->nameToString (), t->valueToString (), t->getAttrib() ? (t->getOwnMemory() ? t->getAttrib()->action : AC_SYSTEM) : AC_DONTWRITE, t->getAttrib() && t->getAttrib()->editable); + } else { + addTag (root, t->nameToString (), t->valueToString (), currAttrib ? (t->getOwnMemory() ? currAttrib->action : AC_SYSTEM) : AC_DONTWRITE, currAttrib && currAttrib->editable); } } } @@ -262,11 +316,11 @@ void ExifPanel::exifSelectionChanged () remove->set_sensitive (1); keep->set_sensitive (1); reset->set_sensitive (1); - } else if (iter->get_value(exifColumns.icon) == delicon) { + } else if (iter->get_value (exifColumns.icon) == delicon) { remove->set_sensitive (0); keep->set_sensitive (1); reset->set_sensitive (1); - } else if (iter->get_value(exifColumns.icon) == keepicon || iter->get_value(exifColumns.icon) == editicon) { + } else if (iter->get_value (exifColumns.icon) == keepicon || iter->get_value (exifColumns.icon) == editicon) { keep->set_sensitive (0); remove->set_sensitive (1); reset->set_sensitive (1); @@ -371,8 +425,8 @@ Gtk::TreeModel::iterator ExifPanel::resetIt (Gtk::TreeModel::iterator iter) } if (iter->get_value (exifColumns.edited)) { - iter->set_value (exifColumns.value, Glib::ustring("") + iter->get_value(exifColumns.orig_value) + ""); - iter->set_value (exifColumns.value_nopango, iter->get_value(exifColumns.orig_value)); + iter->set_value (exifColumns.value, Glib::ustring ("") + iter->get_value (exifColumns.orig_value) + ""); + iter->set_value (exifColumns.value_nopango, iter->get_value (exifColumns.orig_value)); iter->set_value (exifColumns.edited, false); } @@ -415,14 +469,14 @@ void ExifPanel::resetAllPressed () void ExifPanel::addPressed () { - Gtk::Dialog* dialog = new Gtk::Dialog (M("EXIFPANEL_ADDTAGDLG_TITLE"), *((Gtk::Window*)get_toplevel()), true); + Gtk::Dialog* dialog = new Gtk::Dialog (M ("EXIFPANEL_ADDTAGDLG_TITLE"), * ((Gtk::Window*)get_toplevel()), true); dialog->add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); dialog->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); Gtk::HBox* hb1 = new Gtk::HBox (); Gtk::HBox* hb2 = new Gtk::HBox (); - Gtk::Label* tlabel = new Gtk::Label (M("EXIFPANEL_ADDTAGDLG_SELECTTAG") + ":"); + Gtk::Label* tlabel = new Gtk::Label (M ("EXIFPANEL_ADDTAGDLG_SELECTTAG") + ":"); MyComboBoxText* tcombo = new MyComboBoxText (); tcombo->append ("Artist"); @@ -433,7 +487,7 @@ void ExifPanel::addPressed () hb1->pack_start (*tlabel, Gtk::PACK_SHRINK, 4); hb1->pack_start (*tcombo); - Gtk::Label* vlabel = new Gtk::Label (M("EXIFPANEL_ADDTAGDLG_ENTERVALUE") + ":"); + Gtk::Label* vlabel = new Gtk::Label (M ("EXIFPANEL_ADDTAGDLG_ENTERVALUE") + ":"); Gtk::Entry* ventry = new Gtk::Entry (); hb2->pack_start (*vlabel, Gtk::PACK_SHRINK, 4); hb2->pack_start (*ventry); @@ -479,6 +533,12 @@ void ExifPanel::addPressed () delete hb2; } +void ExifPanel::showAlltoggled () +{ + options.lastShowAllExif = showAll->get_active(); + setImageData (idata); +} + void ExifPanel::editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value) { @@ -493,29 +553,30 @@ void ExifPanel::editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib } if (iter == root.end() && value != "#keep" && value != "#delete") { - iter = exifTreeModel->append(root); + iter = exifTreeModel->append (root); iter->set_value (exifColumns.field_nopango, fseg); iter->set_value (exifColumns.action, AC_INVALID); if (dp == Glib::ustring::npos) { - iter->set_value (exifColumns.value, Glib::ustring("") + value + ""); + iter->set_value (exifColumns.value, Glib::ustring ("") + value + ""); iter->set_value (exifColumns.value_nopango, value); iter->set_value (exifColumns.orig_value, value); - iter->set_value (exifColumns.field, Glib::ustring("") + fseg + ""); + iter->set_value (exifColumns.field, Glib::ustring ("") + fseg + ""); iter->set_value (exifColumns.edited, true); iter->set_value (exifColumns.editable, true); iter->set_value (exifColumns.icon, editicon); } else { - iter->set_value (exifColumns.value, Glib::ustring(M("EXIFPANEL_SUBDIRECTORY"))); - iter->set_value (exifColumns.value_nopango, Glib::ustring(M("EXIFPANEL_SUBDIRECTORY"))); + iter->set_value (exifColumns.value, Glib::ustring (M ("EXIFPANEL_SUBDIRECTORY"))); + iter->set_value (exifColumns.value_nopango, Glib::ustring (M ("EXIFPANEL_SUBDIRECTORY"))); iter->set_value (exifColumns.field, fseg); iter->set_value (exifColumns.icon, keepicon); - iter->set_value (exifColumns.orig_value, Glib::ustring(M("EXIFPANEL_SUBDIRECTORY"))); + iter->set_value (exifColumns.orig_value, Glib::ustring (M ("EXIFPANEL_SUBDIRECTORY"))); } } - if (iter == root.end()) + if (iter == root.end()) { return; + } if (dp == Glib::ustring::npos) { if (value == "#keep" && iter->get_value (exifColumns.action) != AC_SYSTEM) { @@ -523,7 +584,7 @@ void ExifPanel::editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib } else if (value == "#delete" && iter->get_value (exifColumns.action) != AC_SYSTEM) { iter->set_value (exifColumns.icon, delicon); } else { - iter->set_value (exifColumns.value, Glib::ustring("") + value + ""); + iter->set_value (exifColumns.value, Glib::ustring ("") + value + ""); iter->set_value (exifColumns.value_nopango, value); iter->set_value (exifColumns.edited, true); iter->set_value (exifColumns.icon, editicon); @@ -571,11 +632,11 @@ Glib::ustring ExifPanel::getSelection (bool onlyeditable) while (iter) { if (first) { ret = iter->get_value (exifColumns.field_nopango); + editable = iter->get_value (exifColumns.editable); } else { ret = iter->get_value (exifColumns.field_nopango) + "." + ret; } - editable = iter->get_value (exifColumns.editable); iter = iter->parent (); first = false; } @@ -637,8 +698,7 @@ void ExifPanel::row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewCo exifTree->collapse_row (path); } else { exifTree->expand_row (path, false); - } - else if (iter->get_value (exifColumns.editable)) { + } else if (iter->get_value (exifColumns.editable)) { addPressed (); } } @@ -649,6 +709,6 @@ void ExifPanel::notifyListener () { if (listener) { - listener->panelChanged (EvExif, M("HISTORY_CHANGED")); + listener->panelChanged (EvExif, M ("HISTORY_CHANGED")); } } diff --git a/rtgui/exifpanel.h b/rtgui/exifpanel.h index 6244c1a4f..b9d76f25d 100644 --- a/rtgui/exifpanel.h +++ b/rtgui/exifpanel.h @@ -26,7 +26,7 @@ class ExifPanel : public Gtk::VBox, public ToolPanel { private: - const rtengine::ImageMetaData* idata; + const rtengine::FramesMetaData* idata; rtengine::procparams::ExifPairs changeList; rtengine::procparams::ExifPairs defChangeList; bool recursiveOp; @@ -43,18 +43,20 @@ private: Gtk::TreeModelColumn action; Gtk::TreeModelColumn editable; Gtk::TreeModelColumn edited; + Gtk::TreeModelColumn isSeparator; ExifColumns() { - add(field); - add(value); - add(icon); - add(action); - add(edited); - add(field_nopango); - add(value_nopango); - add(editable); - add(orig_value); + add (field); + add (value); + add (icon); + add (action); + add (edited); + add (field_nopango); + add (value_nopango); + add (editable); + add (orig_value); + add (isSeparator); } }; Glib::RefPtr delicon; @@ -71,37 +73,41 @@ private: Gtk::Button* add; Gtk::Button* reset; Gtk::Button* resetAll; + Gtk::ToggleButton* showAll; - Gtk::TreeModel::Children addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable); + Gtk::TreeModel::Children addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable); void editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value); void updateChangeList (Gtk::TreeModel::Children root, std::string prefix); - void addDirectory (const rtexif::TagDirectory* dir, Gtk::TreeModel::Children root); + void addDirectory (const rtexif::TagDirectory* dir, Gtk::TreeModel::Children root, bool checkForSeparator = false); + Gtk::TreeModel::Children addSeparator(); Glib::ustring getSelection (bool onlyifeditable = false); - Glib::ustring getSelectedValue (); - void updateChangeList (); - void applyChangeList (); - void keepIt (Gtk::TreeModel::iterator iter); - void delIt (Gtk::TreeModel::iterator iter); + Glib::ustring getSelectedValue(); + void updateChangeList(); + void applyChangeList(); + void keepIt (Gtk::TreeModel::iterator iter); + void delIt (Gtk::TreeModel::iterator iter); Gtk::TreeModel::iterator resetIt (Gtk::TreeModel::iterator iter); + void removePressed(); + void keepPressed(); + void resetPressed(); + void resetAllPressed(); + void addPressed(); + void showAlltoggled(); + public: ExifPanel (); - virtual ~ExifPanel (); + virtual ~ExifPanel(); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void setImageData (const rtengine::ImageMetaData* id); + void setImageData (const rtengine::FramesMetaData* id); - void exifSelectionChanged (); - void removePressed (); - void keepPressed (); - void resetPressed (); - void resetAllPressed (); - void addPressed (); + void exifSelectionChanged(); void row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column); - void notifyListener (); + void notifyListener(); }; diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index b9c5baafb..0a4bec4ab 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -1535,8 +1535,8 @@ bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry && (!filter.exifFilter.filterExpComp || filter.exifFilter.expcomp.count(cfs->expcomp) > 0); return - (!filter.exifFilter.filterShutter || (rtengine::ImageMetaData::shutterFromString(rtengine::ImageMetaData::shutterToString(cfs->shutter)) >= filter.exifFilter.shutterFrom - tol2 && rtengine::ImageMetaData::shutterFromString(rtengine::ImageMetaData::shutterToString(cfs->shutter)) <= filter.exifFilter.shutterTo + tol2)) - && (!filter.exifFilter.filterFNumber || (rtengine::ImageMetaData::apertureFromString(rtengine::ImageMetaData::apertureToString(cfs->fnumber)) >= filter.exifFilter.fnumberFrom - tol2 && rtengine::ImageMetaData::apertureFromString(rtengine::ImageMetaData::apertureToString(cfs->fnumber)) <= filter.exifFilter.fnumberTo + tol2)) + (!filter.exifFilter.filterShutter || (rtengine::FramesMetaData::shutterFromString(rtengine::FramesMetaData::shutterToString(cfs->shutter)) >= filter.exifFilter.shutterFrom - tol2 && rtengine::FramesMetaData::shutterFromString(rtengine::FramesMetaData::shutterToString(cfs->shutter)) <= filter.exifFilter.shutterTo + tol2)) + && (!filter.exifFilter.filterFNumber || (rtengine::FramesMetaData::apertureFromString(rtengine::FramesMetaData::apertureToString(cfs->fnumber)) >= filter.exifFilter.fnumberFrom - tol2 && rtengine::FramesMetaData::apertureFromString(rtengine::FramesMetaData::apertureToString(cfs->fnumber)) <= filter.exifFilter.fnumberTo + tol2)) && (!filter.exifFilter.filterFocalLen || (cfs->focalLen >= filter.exifFilter.focalFrom - tol && cfs->focalLen <= filter.exifFilter.focalTo + tol)) && (!filter.exifFilter.filterISO || (cfs->iso >= filter.exifFilter.isoFrom && cfs->iso <= filter.exifFilter.isoTo)) && (!filter.exifFilter.filterExpComp || filter.exifFilter.expcomp.count(cfs->expcomp) > 0) diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc index d76870788..c3adae3aa 100644 --- a/rtgui/filebrowserentry.cc +++ b/rtgui/filebrowserentry.cc @@ -36,6 +36,8 @@ bool FileBrowserEntry::iconsLoaded(false); Glib::RefPtr FileBrowserEntry::editedIcon; Glib::RefPtr FileBrowserEntry::recentlySavedIcon; Glib::RefPtr FileBrowserEntry::enqueuedIcon; +Glib::RefPtr FileBrowserEntry::hdr; +Glib::RefPtr FileBrowserEntry::ps; FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname) : ThumbBrowserEntryBase (fname), wasInside(false), iatlistener(nullptr), press_x(0), press_y(0), action_x(0), action_y(0), rot_deg(0.0), landscape(true), cropgl(nullptr), state(SNormal), crop_custom_ratio(0.f) @@ -57,6 +59,8 @@ FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname) editedIcon = RTImage::createFromFile ("edited.png"); recentlySavedIcon = RTImage::createFromFile ("recent-save.png"); enqueuedIcon = RTImage::createFromFile ("processing.png"); + hdr = RTImage::createFromFile ("HDR-thumbnail.png"); + ps = RTImage::createFromFile ("PixelShift-thumbnail.png"); iconsLoaded = true; } @@ -137,6 +141,26 @@ std::vector > FileBrowserEntry::getIconsOnImageArea () return ret; } +std::vector > FileBrowserEntry::getSpecificityIconsOnImageArea () +{ + + std::vector > ret; + + if (!thumbnail) { + return ret; + } + + if (thumbnail->isHDR() && hdr) { + ret.push_back (hdr); + } + + if (thumbnail->isPixelShift() && ps) { + ret.push_back (ps); + } + + return ret; +} + void FileBrowserEntry::customBackBufferUpdate (Cairo::RefPtr c) { if(scale != 1.0 && cropParams.enabled) { // somewhere in pipeline customBackBufferUpdate is called when scale == 1.0, which is nonsense for a thumb diff --git a/rtgui/filebrowserentry.h b/rtgui/filebrowserentry.h index 4c3d519ab..423128ddb 100644 --- a/rtgui/filebrowserentry.h +++ b/rtgui/filebrowserentry.h @@ -70,6 +70,8 @@ public: static Glib::RefPtr editedIcon; static Glib::RefPtr recentlySavedIcon; static Glib::RefPtr enqueuedIcon; + static Glib::RefPtr hdr; + static Glib::RefPtr ps; FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname); ~FileBrowserEntry (); @@ -87,6 +89,7 @@ public: void calcThumbnailSize (); virtual std::vector > getIconsOnImageArea (); + virtual std::vector > getSpecificityIconsOnImageArea (); virtual void getIconSize (int& w, int& h); // thumbnaillistener interface diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index eafe32fcd..a2088b9e2 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -770,6 +770,8 @@ void FileCatalog::previewReady (int dir_id, FileBrowserEntry* fdn) if (cfs->focalLen > dirEFS.focalTo) { dirEFS.focalTo = cfs->focalLen; } + + //TODO: ass filters for HDR and PixelShift files } dirEFS.filetypes.insert (cfs->filetype); diff --git a/rtgui/filmsimulation.cc b/rtgui/filmsimulation.cc index 716b686e9..89ab31748 100644 --- a/rtgui/filmsimulation.cc +++ b/rtgui/filmsimulation.cc @@ -62,8 +62,8 @@ bool notifySlowParseDir (const std::chrono::system_clock::time_point& startedAt) FilmSimulation::FilmSimulation() : FoldableToolPanel( this, "filmsimulation", M("TP_FILMSIMULATION_LABEL"), false, true ) { - m_clutComboBox = Gtk::manage( new ClutComboBox() ); - int foundClutsCount = m_clutComboBox->fillFromDir( options.clutsDir ); + m_clutComboBox = Gtk::manage( new ClutComboBox(options.clutsDir) ); + int foundClutsCount = m_clutComboBox->foundClutsCount(); if ( foundClutsCount == 0 ) { pack_start( *Gtk::manage( new Gtk::Label( M("TP_FILMSIMULATION_ZEROCLUTSFOUND") ) ) ); @@ -117,7 +117,7 @@ void FilmSimulation::adjusterChanged( Adjuster* a, double newval ) void FilmSimulation::setBatchMode( bool batchMode ) { ToolPanel::setBatchMode( batchMode ); - m_clutComboBox->addUnchangedEntry(); + m_clutComboBox->setBatchMode(batchMode); } void FilmSimulation::read( const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited ) @@ -197,27 +197,100 @@ void FilmSimulation::trimValues( rtengine::procparams::ProcParams* pp ) //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +std::unique_ptr ClutComboBox::cm; +std::unique_ptr ClutComboBox::cm2; + +ClutComboBox::ClutComboBox(const Glib::ustring &path): + MyComboBox(), + batchMode(false) +{ + if (!cm) { + cm.reset(new ClutModel(path)); + } + if (!cm2 && options.multiDisplayMode) { + cm2.reset(new ClutModel(path)); + } + + set_model(m_model()); + + if (cm->count > 0) { + pack_start(m_columns().label, false); + } + + if (!options.multiDisplayMode) { + signal_map().connect(sigc::mem_fun(*this, &ClutComboBox::updateUnchangedEntry)); + } +} + + +inline Glib::RefPtr &ClutComboBox::m_model() +{ + if (!batchMode || !options.multiDisplayMode) { + return cm->m_model; + } else { + return cm2->m_model; + } +} + + +inline ClutComboBox::ClutColumns &ClutComboBox::m_columns() +{ + if (!batchMode || !options.multiDisplayMode) { + return cm->m_columns; + } else { + return cm2->m_columns; + } +} + + +void ClutComboBox::setBatchMode(bool yes) +{ + if (batchMode != yes) { + batchMode = yes; + set_model(m_model()); + if (batchMode && options.multiDisplayMode) { + updateUnchangedEntry(); + } + } +} + + +void ClutComboBox::updateUnchangedEntry() +{ + auto c = m_model()->children(); + + if (batchMode) { + if (c.empty() || c[c.size()-1][m_columns().clutFilename] != "NULL") { + Gtk::TreeModel::Row row = *(m_model()->append()); + row[m_columns().label] = M("GENERAL_UNCHANGED"); + row[m_columns().clutFilename] = "NULL"; + } + } else { + if (c.size() > 0) { + Gtk::TreeModel::Row row = c[c.size()-1]; + if (row[m_columns().clutFilename] == "NULL") { + std::cout << " removing " << ((void *)this) << std::endl; + m_model()->erase(row); + } + } + } +} + ClutComboBox::ClutColumns::ClutColumns() { add( label ); add( clutFilename ); } -int ClutComboBox::fillFromDir (const Glib::ustring& path) +ClutComboBox::ClutModel::ClutModel(const Glib::ustring &path) { m_model = Gtk::TreeStore::create (m_columns); - set_model (m_model); - - const auto result = parseDir (path); - - if (result > 0) { - pack_start (m_columns.label, false); - } - - return result; + //set_model (m_model); + count = parseDir(path); } -int ClutComboBox::parseDir(const Glib::ustring& path) +int ClutComboBox::ClutModel::parseDir(const Glib::ustring& path) { if (path.empty() || !Glib::file_test(path, Glib::FILE_TEST_IS_DIR)) { return 0; @@ -327,6 +400,11 @@ int ClutComboBox::parseDir(const Glib::ustring& path) return fileCount; } +int ClutComboBox::foundClutsCount() const +{ + return cm->count; +} + Glib::ustring ClutComboBox::getSelectedClut() { Glib::ustring result; @@ -334,7 +412,7 @@ Glib::ustring ClutComboBox::getSelectedClut() Gtk::TreeModel::Row row = *current; if ( row ) { - result = row[ m_columns.clutFilename ]; + result = row[ m_columns().clutFilename ]; } return result; @@ -343,7 +421,7 @@ Glib::ustring ClutComboBox::getSelectedClut() void ClutComboBox::setSelectedClut( Glib::ustring filename ) { if ( !filename.empty() ) { - Gtk::TreeIter found = findRowByClutFilename( m_model->children(), filename ); + Gtk::TreeIter found = findRowByClutFilename( m_model()->children(), filename ); if ( found ) { set_active( found ); @@ -358,7 +436,7 @@ Gtk::TreeIter ClutComboBox::findRowByClutFilename( Gtk::TreeModel::Children chil for( Gtk::TreeModel::Children::iterator it = childs.begin(); !result && it != childs.end(); ++it ) { Gtk::TreeModel::Row row = *it; - if ( row[ m_columns.clutFilename ] == filename ) { + if ( row[ m_columns().clutFilename ] == filename ) { result = it; } else { result = findRowByClutFilename( it->children(), filename ); @@ -367,10 +445,3 @@ Gtk::TreeIter ClutComboBox::findRowByClutFilename( Gtk::TreeModel::Children chil return result; } - -void ClutComboBox::addUnchangedEntry() -{ - Gtk::TreeModel::Row row = *(m_model->append()); - row[m_columns.label] = M("GENERAL_UNCHANGED"); - row[m_columns.clutFilename] = "NULL"; -} diff --git a/rtgui/filmsimulation.h b/rtgui/filmsimulation.h index 9979f45b3..c813f9c85 100644 --- a/rtgui/filmsimulation.h +++ b/rtgui/filmsimulation.h @@ -11,12 +11,16 @@ class ClutComboBox : public MyComboBox { public: - int fillFromDir (const Glib::ustring& path); + ClutComboBox(const Glib::ustring &path); + //int fillFromDir (const Glib::ustring& path); + int foundClutsCount() const; Glib::ustring getSelectedClut(); void setSelectedClut( Glib::ustring filename ); - void addUnchangedEntry(); - + void setBatchMode(bool yes); + private: + void updateUnchangedEntry(); // in batchMode we need to add an extra entry "(Unchanged)". We do this whenever the widget is mapped (connecting to signal_map()), unless options.multiDisplayMode (see the comment below about cm2 in this case) + class ClutColumns : public Gtk::TreeModel::ColumnRecord { public: @@ -25,11 +29,24 @@ private: ClutColumns(); }; - int parseDir (const Glib::ustring& path); + class ClutModel { + public: + Glib::RefPtr m_model; + ClutColumns m_columns; + int count; + ClutModel(const Glib::ustring &path); + int parseDir (const Glib::ustring& path); + }; + + Glib::RefPtr &m_model(); + ClutColumns &m_columns(); + Gtk::TreeIter findRowByClutFilename( Gtk::TreeModel::Children childs, Glib::ustring filename ); - Glib::RefPtr m_model; - ClutColumns m_columns; + static std::unique_ptr cm; // we use a shared TreeModel for all the combo boxes, to save time (no need to reparse the clut dir multiple times)... + static std::unique_ptr cm2; // ... except when options.multiDisplayMode (i.e. editors in their own window), where we need two. This is because we might have two combo boxes displayed at the same time in this case + int count; // the number of clut entries + bool batchMode; }; class FilmSimulation : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel diff --git a/rtgui/filterpanel.cc b/rtgui/filterpanel.cc index a8691c1b3..5f8fa2781 100644 --- a/rtgui/filterpanel.cc +++ b/rtgui/filterpanel.cc @@ -171,15 +171,15 @@ void FilterPanel::setFilter (ExifFilterSettings& defefs, bool updateLists) } // enaFNumber->set_active (curefs.filterFNumber); - fnumberFrom->set_text (ImageMetaData::apertureToString (defefs.fnumberFrom)); + fnumberFrom->set_text (FramesMetaData::apertureToString (defefs.fnumberFrom)); curefs.fnumberFrom = defefs.fnumberFrom; - fnumberTo->set_text (ImageMetaData::apertureToString (defefs.fnumberTo)); + fnumberTo->set_text (FramesMetaData::apertureToString (defefs.fnumberTo)); curefs.fnumberTo = defefs.fnumberTo; // enaShutter->set_active (curefs.filterShutter); - shutterFrom->set_text (ImageMetaData::shutterToString (defefs.shutterFrom)); + shutterFrom->set_text (FramesMetaData::shutterToString (defefs.shutterFrom)); curefs.shutterFrom = defefs.shutterFrom; - shutterTo->set_text (ImageMetaData::shutterToString (defefs.shutterTo)); + shutterTo->set_text (FramesMetaData::shutterToString (defefs.shutterTo)); curefs.shutterTo = defefs.shutterTo; // enaISO->set_active (curefs.filterISO); @@ -315,8 +315,8 @@ ExifFilterSettings FilterPanel::getFilter () efs.focalTo = atof (focalTo->get_text().c_str()); efs.isoFrom = atoi (isoFrom->get_text().c_str()); efs.isoTo = atoi (isoTo->get_text().c_str()); - efs.shutterFrom = ImageMetaData::shutterFromString (shutterFrom->get_text()); - efs.shutterTo = ImageMetaData::shutterFromString (shutterTo->get_text()); + efs.shutterFrom = FramesMetaData::shutterFromString (shutterFrom->get_text()); + efs.shutterTo = FramesMetaData::shutterFromString (shutterTo->get_text()); efs.filterFNumber = enaFNumber->get_active (); efs.filterShutter = enaShutter->get_active (); diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index 1bb1c23a3..e026243be 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -958,7 +958,7 @@ void ICMPanel::oBPCChanged () } } -void ICMPanel::setRawMeta (bool raw, const rtengine::ImageData* pMeta) +void ICMPanel::setRawMeta (bool raw, const rtengine::FramesData* pMeta) { disableListener (); diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index 35017bed4..f8c762b0e 100644 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -122,7 +122,7 @@ public: void applyBaselineExposureOffsetChanged(); void applyHueSatMapChanged(); - void setRawMeta (bool raw, const rtengine::ImageData* pMeta); + void setRawMeta (bool raw, const rtengine::FramesData* pMeta); void saveReferencePressed (); void setICMPanelListener (ICMPanelListener* ipl) diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc index 8af99b2ab..4084e300f 100644 --- a/rtgui/inspector.cc +++ b/rtgui/inspector.cc @@ -59,7 +59,7 @@ InspectorBuffer::~InspectorBuffer() { //int InspectorBuffer::infoFromImage (const Glib::ustring& fname) //{ // -// rtengine::ImageMetaData* idata = rtengine::ImageMetaData::fromFile (fname, nullptr); +// rtengine::FramesMetaData* idata = rtengine::FramesMetaData::fromFile (fname, nullptr, true); // // if (!idata) { // return 0; diff --git a/rtgui/iptcpanel.cc b/rtgui/iptcpanel.cc index 5ee533e2c..cd0fe4050 100644 --- a/rtgui/iptcpanel.cc +++ b/rtgui/iptcpanel.cc @@ -434,7 +434,7 @@ void IPTCPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pe defChangeList = defParams->iptc; } -void IPTCPanel::setImageData (const ImageMetaData* id) +void IPTCPanel::setImageData (const FramesMetaData* id) { if (id) { diff --git a/rtgui/iptcpanel.h b/rtgui/iptcpanel.h index 63309cc27..b216cf638 100644 --- a/rtgui/iptcpanel.h +++ b/rtgui/iptcpanel.h @@ -75,7 +75,7 @@ public: void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void setImageData (const rtengine::ImageMetaData* id); + void setImageData (const rtengine::FramesMetaData* id); void notifyListener (); diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index 0c3b227aa..3efe54347 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -177,7 +177,7 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa if (pp->lensProf.lcpFile.empty()) { Glib::ustring lastFolder = fcbLCPFile->get_current_folder(); fcbLCPFile->set_current_folder(lastFolder); - fcbLCPFile->set_filename(lastFolder + "/."); + fcbLCPFile->unselect_all(); bindCurrentFolder(*fcbLCPFile, options.lastLensProfileDir); updateDisabled(false); } else if (LCPStore::getInstance()->isValidLCPFileName(pp->lensProf.lcpFile)) { @@ -257,7 +257,7 @@ void LensProfilePanel::updateLensfunWarning() } } -void LensProfilePanel::setRawMeta(bool raw, const rtengine::ImageMetaData* pMeta) +void LensProfilePanel::setRawMeta(bool raw, const rtengine::FramesMetaData* pMeta) { if (!raw || pMeta->getFocusDist() <= 0) { disableListener(); @@ -582,13 +582,27 @@ bool LensProfilePanel::checkLensfunCanCorrect(bool automatch) //----------------------------------------------------------------------------- LensProfilePanel::LFDbHelper::LFDbHelper() +{ +#ifdef _OPENMP +#pragma omp parallel sections +#endif +{ +#ifdef _OPENMP +#pragma omp section +#endif { lensfunCameraModel = Gtk::TreeStore::create(lensfunModelCam); - lensfunLensModel = Gtk::TreeStore::create(lensfunModelLens); - fillLensfunCameras(); +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + lensfunLensModel = Gtk::TreeStore::create(lensfunModelLens); fillLensfunLenses(); } +} +} void LensProfilePanel::LFDbHelper::fillLensfunCameras() { diff --git a/rtgui/lensprofile.h b/rtgui/lensprofile.h index 1b1554cab..e70515470 100644 --- a/rtgui/lensprofile.h +++ b/rtgui/lensprofile.h @@ -38,7 +38,7 @@ protected: void updateDisabled(bool enable); bool allowFocusDep; bool isRaw; - const rtengine::ImageMetaData* metadata; + const rtengine::FramesMetaData* metadata; Gtk::RadioButton::Group corrGroup; Gtk::RadioButton *corrOff; @@ -94,7 +94,7 @@ public: void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setRawMeta (bool raw, const rtengine::ImageMetaData* pMeta); + void setRawMeta (bool raw, const rtengine::FramesMetaData* pMeta); void onLCPFileChanged (); void onUseDistChanged(); diff --git a/rtgui/options.cc b/rtgui/options.cc index 9517e2fbc..8a9e2e6a0 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -358,6 +358,7 @@ void Options::setDefaults () CPFontFamily = "default"; CPFontSize = 8; lastScale = 5; + lastShowAllExif = false; panAccelFactor = 5; rememberZoomAndPan = true; lastCropSize = 1; @@ -1324,6 +1325,10 @@ void Options::readFromFile (Glib::ustring fname) lastScale = keyFile.get_integer ("GUI", "LastPreviewScale"); } + if (keyFile.has_key ("GUI", "LastShowAllExif")) { + lastShowAllExif = keyFile.get_boolean ("GUI", "LastShowAllExif"); + } + if (keyFile.has_key ("GUI", "PanAccelFactor")) { panAccelFactor = keyFile.get_integer ("GUI", "PanAccelFactor"); } @@ -2054,6 +2059,7 @@ void Options::saveToFile (Glib::ustring fname) keyFile.set_string ("GUI", "CPFontFamily", CPFontFamily); keyFile.set_integer ("GUI", "CPFontSize", CPFontSize); keyFile.set_integer ("GUI", "LastPreviewScale", lastScale); + keyFile.set_boolean ("GUI", "LastShowAllExif", lastShowAllExif); keyFile.set_integer ("GUI", "PanAccelFactor", panAccelFactor); keyFile.set_boolean ("GUI", "RememberZoomAndPan", rememberZoomAndPan); keyFile.set_integer ("GUI", "LastCropSize", lastCropSize); diff --git a/rtgui/options.h b/rtgui/options.h index b60acd632..02b02cf52 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -170,6 +170,7 @@ public: int dirBrowserHeight; int preferencesWidth; int preferencesHeight; + bool lastShowAllExif; int lastScale; int panAccelFactor; int lastCropSize; diff --git a/rtgui/rtimage.cc b/rtgui/rtimage.cc index 16e8e3286..b24158b00 100644 --- a/rtgui/rtimage.cc +++ b/rtgui/rtimage.cc @@ -28,7 +28,7 @@ namespace { -std::map> pixbufCache; +std::map> pixbufCache; } diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index ff7e58d49..0cb53d0c2 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -160,6 +160,7 @@ void ThumbBrowserEntryBase::updateBackBuffer () // draw icons onto the thumbnail area bbIcons = getIconsOnImageArea (); + bbSpecificityIcons = getSpecificityIconsOnImageArea (); int infow, infoh; getTextSizes (infow, infoh); @@ -224,6 +225,19 @@ void ThumbBrowserEntryBase::updateBackBuffer () } } + if (!bbSpecificityIcons.empty()) { + int igap = 2; + int istartx2 = prex + prew - 1 + igap; + int istarty2 = prey + preh - igap - 1; + + for (size_t i = 0; i < bbSpecificityIcons.size(); ++i) { + istartx2 -= bbSpecificityIcons[i]->get_width() - igap; + Gdk::Cairo::set_source_pixbuf(cc, bbSpecificityIcons[i], istartx2, istarty2 - bbSpecificityIcons[i]->get_height()); + cc->rectangle(istartx2, istarty2 - bbSpecificityIcons[i]->get_height(), bbSpecificityIcons[i]->get_width(), bbSpecificityIcons[i]->get_height()); + cc->fill(); + } + } + if ( ( (parent->getLocation() != ThumbBrowserBase::THLOC_EDITOR && options.showFileNames) || (parent->getLocation() == ThumbBrowserBase::THLOC_EDITOR && options.filmStripShowFileNames)) && withFilename > WFNAME_NONE) { @@ -512,7 +526,9 @@ void ThumbBrowserEntryBase::draw (Cairo::RefPtr cc) } if (!backBuffer || selected != bbSelected || framed != bbFramed || preview != bbPreview - || exp_width != bbWidth || exp_height != bbHeight || getIconsOnImageArea () != bbIcons || backBuffer->isDirty()) { + || exp_width != bbWidth || exp_height != bbHeight || getIconsOnImageArea () != bbIcons + || getSpecificityIconsOnImageArea() != bbSpecificityIcons || backBuffer->isDirty()) + { updateBackBuffer (); } @@ -592,6 +608,11 @@ std::vector > ThumbBrowserEntryBase::getIconsOnImageAr return std::vector >(); } +std::vector > ThumbBrowserEntryBase::getSpecificityIconsOnImageArea() +{ + return std::vector >(); +} + void ThumbBrowserEntryBase::getIconSize(int& w, int& h) { w = 0; diff --git a/rtgui/thumbbrowserentrybase.h b/rtgui/thumbbrowserentrybase.h index f4779faa1..0ebf597e2 100644 --- a/rtgui/thumbbrowserentrybase.h +++ b/rtgui/thumbbrowserentrybase.h @@ -80,6 +80,7 @@ protected: bool bbSelected, bbFramed; guint8* bbPreview; std::vector > bbIcons; + std::vector > bbSpecificityIcons; CursorShape cursor_type; void drawFrame (Cairo::RefPtr cr, const Gdk::RGBA& bg, const Gdk::RGBA& fg); @@ -185,6 +186,7 @@ public: virtual void drawProgressBar (Glib::RefPtr win, const Gdk::RGBA& foregr, const Gdk::RGBA& backgr, int x, int w, int y, int h) {} virtual std::vector > getIconsOnImageArea (); + virtual std::vector > getSpecificityIconsOnImageArea (); virtual void getIconSize (int& w, int& h); virtual bool motionNotify (int x, int y); diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 2d8ae7106..a00a37809 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -133,20 +133,22 @@ void Thumbnail::_generateThumbnailImage () bool quick = false; rtengine::RawMetaDataLocation ri; + rtengine::eSensorType sensorType = rtengine::ST_NONE; if ( initial_ && options.internalThumbIfUntouched) { quick = true; - tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, tw, th, 1, TRUE); + tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, sensorType, tw, th, 1, TRUE); } if ( tpp == nullptr ) { quick = false; - tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, tw, th, 1, pparams.wb.equal, TRUE, pparams.raw.bayersensor.imageNum); + tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, sensorType, tw, th, 1, pparams.wb.equal, TRUE, pparams.raw.bayersensor.imageNum); } + cfs.sensortype = sensorType; if (tpp) { cfs.format = FT_Raw; cfs.thumbImgType = quick ? CacheImageData::QUICK_THUMBNAIL : CacheImageData::FULL_THUMBNAIL; - infoFromImage (fname, &ri); + infoFromImage (fname, std::unique_ptr(new rtengine::RawMetaDataLocation(ri))); } } @@ -228,14 +230,16 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu if (!run_cpb) { if (defProf == DEFPROFILE_DYNAMIC && create && cfs && cfs->exifValid) { - rtengine::ImageMetaData* imageMetaData; + rtengine::FramesMetaData* imageMetaData; if (getType() == FT_Raw) { - rtengine::RawMetaDataLocation metaData = rtengine::Thumbnail::loadMetaDataFromRaw(fname); - imageMetaData = rtengine::ImageMetaData::fromFile (fname, &metaData); + // Should we ask all frame's MetaData ? + imageMetaData = rtengine::FramesMetaData::fromFile (fname, std::unique_ptr(new rtengine::RawMetaDataLocation(rtengine::Thumbnail::loadMetaDataFromRaw(fname))), true); } else { - imageMetaData = rtengine::ImageMetaData::fromFile (fname, nullptr); + // Should we ask all frame's MetaData ? + imageMetaData = rtengine::FramesMetaData::fromFile (fname, nullptr, true); } PartialProfile *pp = ProfileStore::getInstance()->loadDynamicProfile(imageMetaData); + delete imageMetaData; int err = pp->pparams->save(outFName); pp->deleteInstance(); delete pp; @@ -250,25 +254,27 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu } } else { // First generate the communication file, with general values and EXIF metadata - rtengine::ImageMetaData* imageMetaData; + rtengine::FramesMetaData* imageMetaData; if (getType() == FT_Raw) { - rtengine::RawMetaDataLocation metaData = rtengine::Thumbnail::loadMetaDataFromRaw(fname); - imageMetaData = rtengine::ImageMetaData::fromFile (fname, &metaData); + // Should we ask all frame's MetaData ? + imageMetaData = rtengine::FramesMetaData::fromFile (fname, std::unique_ptr(new rtengine::RawMetaDataLocation(rtengine::Thumbnail::loadMetaDataFromRaw(fname))), true); } else { - imageMetaData = rtengine::ImageMetaData::fromFile (fname, nullptr); + // Should we ask all frame's MetaData ? + imageMetaData = rtengine::FramesMetaData::fromFile (fname, nullptr, true); } Glib::ustring tmpFileName( Glib::build_filename(options.cacheBaseDir, Glib::ustring::compose("CPB_temp_%1.txt", index++)) ); const rtexif::TagDirectory* exifDir = nullptr; - if (imageMetaData && (exifDir = imageMetaData->getExifData())) { + if (imageMetaData && (exifDir = imageMetaData->getRootExifData())) { exifDir->CPBDump(tmpFileName, fname, outFName, defaultPparamsPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(defaultPparamsPath, Glib::path_get_basename(defProf) + paramFileExtension), cfs, flaggingMode); } + delete imageMetaData; // For the filename etc. do NOT use streams, since they are not UTF8 safe Glib::ustring cmdLine = options.CPBPath + Glib::ustring(" \"") + tmpFileName + Glib::ustring("\""); @@ -285,8 +291,6 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu } g_remove (tmpFileName.c_str ()); - - delete imageMetaData; } if (returnParams && hasProcParams()) { @@ -498,6 +502,15 @@ bool Thumbnail::isEnqueued () return enqueueNumber > 0; } +bool Thumbnail::isPixelShift () +{ + return cfs.isPixelShift; +} +bool Thumbnail::isHDR () +{ + return cfs.isHDR; +} + void Thumbnail::increaseRef () { MyMutex::MyLock lock(mutex); @@ -604,7 +617,7 @@ rtengine::IImage8* Thumbnail::processThumbImage (const rtengine::procparams::Pro } else { // Full thumbnail: apply profile // image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.getCamera(), cfs.focalLen, cfs.focalLen35mm, cfs.focusDist, cfs.shutter, cfs.fnumber, cfs.iso, cfs.expcomp, scale ); - image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, &cfs, scale ); + image = tpp->processImage (pparams, static_cast(cfs.sensortype), h, rtengine::TI_Bilinear, &cfs, scale ); } tpp->getDimensions(lastW, lastH, lastScale); @@ -630,7 +643,7 @@ rtengine::IImage8* Thumbnail::upgradeThumbImage (const rtengine::procparams::Pro } // rtengine::IImage8* image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.getCamera(), cfs.focalLen, cfs.focalLen35mm, cfs.focusDist, cfs.shutter, cfs.fnumber, cfs.iso, cfs.expcomp, scale ); - rtengine::IImage8* image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, &cfs, scale ); + rtengine::IImage8* image = tpp->processImage (pparams, static_cast(cfs.sensortype), h, rtengine::TI_Bilinear, &cfs, scale ); tpp->getDimensions(lastW, lastH, lastScale); delete tpp; @@ -648,7 +661,7 @@ void Thumbnail::generateExifDateTimeStrings () return; } - exifString = Glib::ustring::compose ("f/%1 %2s %3%4 %5mm", Glib::ustring(rtengine::ImageData::apertureToString(cfs.fnumber)), Glib::ustring(rtengine::ImageData::shutterToString(cfs.shutter)), M("QINFO_ISO"), cfs.iso, Glib::ustring::format(std::setw(3), std::fixed, std::setprecision(2), cfs.focalLen)); + exifString = Glib::ustring::compose ("f/%1 %2s %3%4 %5mm", Glib::ustring(rtengine::FramesData::apertureToString(cfs.fnumber)), Glib::ustring(rtengine::FramesData::shutterToString(cfs.shutter)), M("QINFO_ISO"), cfs.iso, Glib::ustring::format(std::setw(3), std::fixed, std::setprecision(2), cfs.focalLen)); if (options.fbShowExpComp && cfs.expcomp != "0.00" && cfs.expcomp != "") { // don't show exposure compensation if it is 0.00EV;old cache iles do not have ExpComp, so value will not be displayed. exifString = Glib::ustring::compose ("%1 %2EV", exifString, cfs.expcomp); // append exposure compensation to exifString @@ -712,10 +725,9 @@ ThFileType Thumbnail::getType () return (ThFileType) cfs.format; } -int Thumbnail::infoFromImage (const Glib::ustring& fname, rtengine::RawMetaDataLocation* rml) +int Thumbnail::infoFromImage (const Glib::ustring& fname, std::unique_ptr rml) { - - rtengine::ImageMetaData* idata = rtengine::ImageMetaData::fromFile (fname, rml); + rtengine::FramesMetaData* idata = rtengine::FramesMetaData::fromFile (fname, std::move(rml)); if (!idata) { return 0; @@ -726,24 +738,28 @@ int Thumbnail::infoFromImage (const Glib::ustring& fname, rtengine::RawMetaDataL cfs.exifValid = false; if (idata->hasExif()) { - cfs.shutter = idata->getShutterSpeed (); - cfs.fnumber = idata->getFNumber (); - cfs.focalLen = idata->getFocalLen (); + cfs.shutter = idata->getShutterSpeed (); + cfs.fnumber = idata->getFNumber (); + cfs.focalLen = idata->getFocalLen (); cfs.focalLen35mm = idata->getFocalLen35mm (); - cfs.focusDist = idata->getFocusDist (); - cfs.iso = idata->getISOSpeed (); - cfs.expcomp = idata->expcompToString (idata->getExpComp(), false); // do not mask Zero expcomp - cfs.year = 1900 + idata->getDateTime().tm_year; - cfs.month = idata->getDateTime().tm_mon + 1; - cfs.day = idata->getDateTime().tm_mday; - cfs.hour = idata->getDateTime().tm_hour; - cfs.min = idata->getDateTime().tm_min; - cfs.sec = idata->getDateTime().tm_sec; - cfs.timeValid = true; - cfs.exifValid = true; - cfs.lens = idata->getLens(); - cfs.camMake = idata->getMake(); - cfs.camModel = idata->getModel(); + cfs.focusDist = idata->getFocusDist (); + cfs.iso = idata->getISOSpeed (); + cfs.expcomp = idata->expcompToString (idata->getExpComp(), false); // do not mask Zero expcomp + cfs.isHDR = idata->getHDR (); + cfs.isPixelShift = idata->getPixelShift (); + cfs.frameCount = idata->getFrameCount (); + cfs.sampleFormat = idata->getSampleFormat (); + cfs.year = 1900 + idata->getDateTime().tm_year; + cfs.month = idata->getDateTime().tm_mon + 1; + cfs.day = idata->getDateTime().tm_mday; + cfs.hour = idata->getDateTime().tm_hour; + cfs.min = idata->getDateTime().tm_min; + cfs.sec = idata->getDateTime().tm_sec; + cfs.timeValid = true; + cfs.exifValid = true; + cfs.lens = idata->getLens(); + cfs.camMake = idata->getMake(); + cfs.camModel = idata->getModel(); if (idata->getOrientation() == "Rotate 90 CW") { deg = 90; diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index eb9e38f7f..3ef094d6b 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -70,7 +70,7 @@ class Thumbnail void _loadThumbnail (bool firstTrial = true); void _saveThumbnail (); void _generateThumbnailImage (); - int infoFromImage (const Glib::ustring& fname, rtengine::RawMetaDataLocation* rml = nullptr); + int infoFromImage (const Glib::ustring& fname, std::unique_ptr rml = nullptr); void loadThumbnail (bool firstTrial = true); void generateExifDateTimeStrings (); @@ -107,6 +107,8 @@ public: void imageEnqueued (); void imageRemovedFromQueue (); bool isEnqueued (); + bool isPixelShift (); + bool isHDR (); // unsigned char* getThumbnailImage (int &w, int &h, int fixwh=1); // fixwh = 0: fix w and calculate h, =1: fix h and calculate w rtengine::IImage8* processThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale); diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 07344afc5..98df9f124 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -28,7 +28,7 @@ using namespace rtengine::procparams; -ToolPanelCoordinator::ToolPanelCoordinator () : ipc (nullptr), hasChanged (false), editDataProvider (nullptr) +ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), hasChanged (false), editDataProvider (nullptr) { exposurePanel = Gtk::manage (new ToolVBox ()); @@ -72,8 +72,10 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc (nullptr), hasChanged (false prsharpening = Gtk::manage (new PrSharpening()); crop = Gtk::manage (new Crop ()); icm = Gtk::manage (new ICMPanel ()); - exifpanel = Gtk::manage (new ExifPanel ()); - iptcpanel = Gtk::manage (new IPTCPanel ()); + if(!batch) { + exifpanel = Gtk::manage (new ExifPanel ()); + iptcpanel = Gtk::manage (new IPTCPanel ()); + } wavelet = Gtk::manage (new Wavelet ()); dirpyrequalizer = Gtk::manage (new DirPyrEqualizer ()); hsvequalizer = Gtk::manage (new HSVEqualizer ()); @@ -101,116 +103,69 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc (nullptr), hasChanged (false // Medium -> High ISO addPanel (colorPanel, whitebalance); - toolPanels.push_back (whitebalance); addPanel (exposurePanel, toneCurve); - toolPanels.push_back (toneCurve); addPanel (colorPanel, vibrance); - toolPanels.push_back (vibrance); addPanel (colorPanel, chmixer); - toolPanels.push_back (chmixer); // << TODO: Add "Enabled" addPanel (colorPanel, blackwhite); - toolPanels.push_back (blackwhite); addPanel (exposurePanel, shadowshighlights); - toolPanels.push_back (shadowshighlights); addPanel (detailsPanel, sharpening); - toolPanels.push_back (sharpening); addPanel (detailsPanel, sharpenEdge); - toolPanels.push_back (sharpenEdge); addPanel (detailsPanel, sharpenMicro); - toolPanels.push_back (sharpenMicro); addPanel (colorPanel, hsvequalizer); - toolPanels.push_back (hsvequalizer); // << TODO: Add "Enabled" addPanel (colorPanel, filmSimulation); - toolPanels.push_back (filmSimulation); addPanel (colorPanel, rgbcurves); - toolPanels.push_back (rgbcurves); // << TODO: Add "Enabled" addPanel (colorPanel, colortoning); - toolPanels.push_back (colortoning); addPanel (exposurePanel, epd); - toolPanels.push_back (epd); addPanel (exposurePanel, retinex); - toolPanels.push_back (retinex); addPanel (exposurePanel, pcvignette); - toolPanels.push_back (pcvignette); addPanel (exposurePanel, gradient); - toolPanels.push_back (gradient); addPanel (exposurePanel, lcurve); - toolPanels.push_back (lcurve); // << TODO: Add "Enabled" ??? -// addPanel (exposurePanel, locallab); -// toolPanels.push_back (locallab); - addPanel (exposurePanel, colorappearance); - toolPanels.push_back (colorappearance); addPanel (detailsPanel, impulsedenoise); - toolPanels.push_back (impulsedenoise); addPanel (detailsPanel, dirpyrdenoise); - toolPanels.push_back (dirpyrdenoise); addPanel (detailsPanel, defringe); - toolPanels.push_back (defringe); addPanel (detailsPanel, dirpyrequalizer); - toolPanels.push_back (dirpyrequalizer); addPanel (waveletPanel, wavelet); - toolPanels.push_back (wavelet); addPanel (locallabPanel, locallab); - toolPanels.push_back (locallab); addPanel (transformPanel, crop); - toolPanels.push_back (crop); addPanel (transformPanel, resize); - toolPanels.push_back (resize); addPanel (resize->getPackBox(), prsharpening, 2); - toolPanels.push_back (prsharpening); addPanel (transformPanel, lensgeom); - toolPanels.push_back (lensgeom); addPanel (lensgeom->getPackBox(), rotate, 2); - toolPanels.push_back (rotate); addPanel (lensgeom->getPackBox(), perspective, 2); - toolPanels.push_back (perspective); addPanel (lensgeom->getPackBox(), lensProf, 2); - toolPanels.push_back (lensProf); addPanel (lensgeom->getPackBox(), distortion, 2); - toolPanels.push_back (distortion); addPanel (lensgeom->getPackBox(), cacorrection, 2); - toolPanels.push_back (cacorrection); addPanel (lensgeom->getPackBox(), vignetting, 2); - toolPanels.push_back (vignetting); addPanel (colorPanel, icm); - toolPanels.push_back (icm); addPanel (rawPanel, sensorbayer); - toolPanels.push_back (sensorbayer); addPanel (sensorbayer->getPackBox(), bayerprocess, 2); - toolPanels.push_back (bayerprocess); addPanel (sensorbayer->getPackBox(), bayerrawexposure, 2); - toolPanels.push_back (bayerrawexposure); addPanel (sensorbayer->getPackBox(), bayerpreprocess, 2); - toolPanels.push_back (bayerpreprocess); addPanel (sensorbayer->getPackBox(), rawcacorrection, 2); - toolPanels.push_back (rawcacorrection); addPanel (rawPanel, sensorxtrans); - toolPanels.push_back (sensorxtrans); addPanel (sensorxtrans->getPackBox(), xtransprocess, 2); - toolPanels.push_back (xtransprocess); addPanel (sensorxtrans->getPackBox(), xtransrawexposure, 2); - toolPanels.push_back (xtransrawexposure); addPanel (rawPanel, rawexposure); - toolPanels.push_back (rawexposure); addPanel (rawPanel, preprocess); - toolPanels.push_back (preprocess); addPanel (rawPanel, darkframe); - toolPanels.push_back (darkframe); addPanel (rawPanel, flatfield); - toolPanels.push_back (flatfield); toolPanels.push_back (coarse); - toolPanels.push_back (exifpanel); - toolPanels.push_back (iptcpanel); - metadataPanel = Gtk::manage (new Gtk::Notebook ()); - metadataPanel->set_name ("MetaPanelNotebook"); + if(!batch) { + toolPanels.push_back (exifpanel); + toolPanels.push_back (iptcpanel); + metadataPanel = Gtk::manage (new Gtk::Notebook ()); + metadataPanel->set_name ("MetaPanelNotebook"); + metadataPanel->append_page (*exifpanel, M ("MAIN_TAB_EXIF")); + metadataPanel->append_page (*iptcpanel, M ("MAIN_TAB_IPTC")); + } else { + metadataPanel = nullptr; + } toolPanelNotebook = new Gtk::Notebook (); toolPanelNotebook->set_name ("ToolPanelNotebook"); - metadataPanel->append_page (*exifpanel, M ("MAIN_TAB_EXIF")); - metadataPanel->append_page (*iptcpanel, M ("MAIN_TAB_IPTC")); exposurePanelSW = Gtk::manage (new MyScrolledWindow ()); detailsPanelSW = Gtk::manage (new MyScrolledWindow ()); @@ -268,8 +223,12 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc (nullptr), hasChanged (false toiW = Gtk::manage (new TextOrIcon ("wavelet.png" , M ("MAIN_TAB_WAVELET") , M ("MAIN_TAB_WAVELET_TOOLTIP") , type)); toiL = Gtk::manage (new TextOrIcon ("openhand.png" , M ("MAIN_TAB_LOCALLAB") , M ("MAIN_TAB_LOCALLAB_TOOLTIP") , type)); toiT = Gtk::manage (new TextOrIcon ("transform.png", M ("MAIN_TAB_TRANSFORM"), M ("MAIN_TAB_TRANSFORM_TOOLTIP"), type)); - toiR = Gtk::manage (new TextOrIcon ("raw.png" , M ("MAIN_TAB_RAW") , M ("MAIN_TAB_RAW_TOOLTIP") , type)); - toiM = Gtk::manage (new TextOrIcon ("meta.png" , M ("MAIN_TAB_METADATA") , M ("MAIN_TAB_METADATA_TOOLTIP") , type)); + toiR = Gtk::manage (new TextOrIcon ("raw.png", M ("MAIN_TAB_RAW"), M ("MAIN_TAB_RAW_TOOLTIP"), type)); + if(!batch) { + toiM = Gtk::manage (new TextOrIcon ("meta.png", M ("MAIN_TAB_METADATA"), M ("MAIN_TAB_METADATA_TOOLTIP"), type)); + } else { + toiM = nullptr; + } toolPanelNotebook->append_page (*exposurePanelSW, *toiE); toolPanelNotebook->append_page (*detailsPanelSW, *toiD); @@ -278,7 +237,9 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc (nullptr), hasChanged (false toolPanelNotebook->append_page (*locallabPanelSW, *toiL); toolPanelNotebook->append_page (*transformPanelSW, *toiT); toolPanelNotebook->append_page (*rawPanelSW, *toiR); - toolPanelNotebook->append_page (*metadataPanel, *toiM); + if(!batch) { + toolPanelNotebook->append_page (*metadataPanel, *toiM); + } toolPanelNotebook->set_current_page (0); @@ -311,6 +272,7 @@ void ToolPanelCoordinator::addPanel (Gtk::Box* where, FoldableToolPanel* panel, expList.push_back (panel->getExpander()); where->pack_start (*panel->getExpander(), false, false); + toolPanels.push_back (panel); } ToolPanelCoordinator::~ToolPanelCoordinator () @@ -529,7 +491,7 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool toneCurve->enableListener (); if (ipc) { - const rtengine::ImageMetaData* pMetaData = ipc->getInitialImage()->getMetaData(); + const rtengine::FramesMetaData* pMetaData = ipc->getInitialImage()->getMetaData(); exifpanel->setImageData (pMetaData); iptcpanel->setImageData (pMetaData); @@ -548,7 +510,7 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool ipc->setImageTypeListener (this); flatfield->setShortcutPath (Glib::path_get_dirname (ipc->getInitialImage()->getFileName())); - icm->setRawMeta (raw, (const rtengine::ImageData*)pMetaData); + icm->setRawMeta (raw, (const rtengine::FramesData*)pMetaData); lensProf->setRawMeta (raw, pMetaData); } @@ -711,7 +673,7 @@ rtengine::RawImage* ToolPanelCoordinator::getDF() return nullptr; } - const rtengine::ImageMetaData *imd = ipc->getInitialImage()->getMetaData(); + const rtengine::FramesMetaData *imd = ipc->getInitialImage()->getMetaData(); if (imd) { int iso = imd->getISOSpeed(); @@ -732,7 +694,7 @@ rtengine::RawImage* ToolPanelCoordinator::getFF() return nullptr; } - const rtengine::ImageMetaData *imd = ipc->getInitialImage()->getMetaData(); + const rtengine::FramesMetaData *imd = ipc->getInitialImage()->getMetaData(); if (imd) { // int iso = imd->getISOSpeed(); temporarilly removed because unused diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index bf0ac3d4b..d9074b351 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -203,7 +203,7 @@ public: CoarsePanel* coarse; Gtk::Notebook* toolPanelNotebook; - ToolPanelCoordinator (); + ToolPanelCoordinator (bool batch = false); virtual ~ToolPanelCoordinator (); bool getChangedState () diff --git a/tools/osx/executable_loader.in b/tools/osx/executable_loader.in index b6025fe59..dcc0cabc4 100644 --- a/tools/osx/executable_loader.in +++ b/tools/osx/executable_loader.in @@ -48,6 +48,7 @@ esac #fi #ln -sf "${app}" /tmp +# Prevent crash when directory name contains special characters AppleLocale=`defaults read -g AppleLocale` export LANG=${AppleLocale%@*}.UTF-8 diff --git a/tools/source_icons/scalable/HDR-thumbnail.file b/tools/source_icons/scalable/HDR-thumbnail.file new file mode 100644 index 000000000..59f729498 --- /dev/null +++ b/tools/source_icons/scalable/HDR-thumbnail.file @@ -0,0 +1 @@ +HDR-thumbnail.png,w29,actions diff --git a/tools/source_icons/scalable/HDR-thumbnail.svg b/tools/source_icons/scalable/HDR-thumbnail.svg new file mode 100644 index 000000000..ef070f380 --- /dev/null +++ b/tools/source_icons/scalable/HDR-thumbnail.svg @@ -0,0 +1,352 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/tools/source_icons/scalable/PixelShift-thumbnail.file b/tools/source_icons/scalable/PixelShift-thumbnail.file new file mode 100644 index 000000000..a62809a4d --- /dev/null +++ b/tools/source_icons/scalable/PixelShift-thumbnail.file @@ -0,0 +1 @@ +PixelShift-thumbnail.png,w18,actions diff --git a/tools/source_icons/scalable/PixelShift-thumbnail.svg b/tools/source_icons/scalable/PixelShift-thumbnail.svg new file mode 100644 index 000000000..b606b24f8 --- /dev/null +++ b/tools/source_icons/scalable/PixelShift-thumbnail.svg @@ -0,0 +1,353 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + +