diff --git a/CMakeLists.txt b/CMakeLists.txt index 646dbf46f..e4ecf0903 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,6 +98,8 @@ option (BUILD_SHARED "Build rawtherapee with shared libraries" OFF) option (WITH_BZIP "Build with Bzip2 support" ON) option (WITH_MYFILE_MMAP "Build using memory mapped file" ON) option (WITH_LTO "Build with link-time optimizations" OFF) +option (WITH_SAN "Build with run-time sanitizer" OFF) +option (WITH_PROF "Build with profiling instrumentation" OFF) option (OPTION_OMP "Build with OpenMP support" ON) option (STRICT_MUTEX "True (recommended): MyMutex will behave like POSIX Mutex; False: MyMutex will behave like POSIX RecMutex; Note: forced to ON for Debug builds" ON) option (TRACE_MYRWMUTEX "Trace RT's custom R/W Mutex (Debug builds only); redirecting std::out to a file is strongly recommended!" OFF) @@ -243,7 +245,6 @@ pkg_check_modules (LCMS REQUIRED lcms2) find_package (EXPAT REQUIRED expat>=2.0) pkg_check_modules (FFTW3F REQUIRED fftw3f) pkg_check_modules (IPTCDATA REQUIRED libiptcdata) -pkg_check_modules(FFTW3 fftw3) find_package (JPEG REQUIRED) find_package (PNG REQUIRED) find_package (TIFF REQUIRED) @@ -274,6 +275,18 @@ if (WITH_LTO) SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") endif (WITH_LTO) +if (WITH_SAN) + SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${WITH_SAN}") + SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=${WITH_SAN}") + SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=${WITH_SAN}") +endif (WITH_SAN) + +if (WITH_PROF) + SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg") + SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") + SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") +endif (WITH_PROF) + if (OPTION_OMP) find_package(OpenMP) if (OPENMP_FOUND) @@ -297,7 +310,7 @@ set(OOSB_FILES "${PROJECT_SOURCE_DIR}/rtdata/rawtherapee.desktop" "${PROJECT_SOU if (OUT_OF_SOURCE_BUILD) foreach(f ${OOSB_FILES}) file (REMOVE "${f}") - endforeach(f) + endforeach(f) endif () # check for generated files in the source tree which should not be there when @@ -308,7 +321,7 @@ if (OUT_OF_SOURCE_BUILD) if (EXISTS "${f}") message (SEND_ERROR "Generated \"${f}\" found inside the source tree. Please remove it as it is a relic of the old build system and prevents valid compilation now.") endif () - endforeach(f) + endforeach(f) endif () ## BEGIN: Generating AboutThisBuild.txt diff --git a/LICENSE.txt b/LICENSE.txt index 0de1c6985..1e9ad695f 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,26 +1,23 @@ + RawTherapee - A powerful, cross-platform raw image processing program. + Copyright (C) 2004-2012 Gabor Horvath - RawTherapee - - -Copyright ©2004-2012 Gábor Horváth - -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 below for more details. + RawTherapee is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + RawTherapee is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - + Version 3, 29 June 2007 - Copyright ©2007 Free Software Foundation, Inc. + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -638,3 +635,4 @@ Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS + diff --git a/README.md b/README.md index d7ab40a5c..9dfd4c324 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,21 @@ ![RawTherapee logo](http://rawtherapee.com/images/logos/rawtherapee_logo_discuss.png) -RawTherapee is a powerful, cross-platform raw photo processing program, released under the GNU General Public License Version 3. It is written in C++ using a GTK+ front-end and a patched version of dcraw for reading raw files. It is notable for the advanced control it gives the user over the demosaicing and developing process. +RawTherapee is a powerful, cross-platform raw photo processing program, released under the [GNU General Public License Version 3](https://opensource.org/licenses/gpl-3.0.html) and written in C++ using a [GTK+](http://www.gtk.org/) front-end. It uses a patched version of [dcraw](http://www.cybercom.net/~dcoffin/dcraw/) for reading raw files, with an in-house solution which adds the highest quality support for certain camera models unsupported by dcraw and enhances the accuracy of certain raw files already supported by dcraw. It is notable for the advanced control it gives the user over the demosaicing and development process. -## Target audience and feature set +## Target audience -Rawtherapee is a free software (as in free beer) aimed at developing raw files from a broad range of camera (all files than can be decoded by *dcraw* from Dave Coffin), but can also edit standard image files (jpeg, png, tiff) and some HDR files. The targeted user base ranges from the enthusiast photographer with some basic technical knowledge in color science (it's not mandatory, but it's better if you e.g. know what a color profile is) to semi-professional users. +Rawtherapee is a [libre software](https://en.wikipedia.org/wiki/Free_software) designed for developing raw files from a broad range of digital cameras, as well as [HDR DNG](https://helpx.adobe.com/photoshop/digital-negative.html) files and non-raw image formats ([JPEG](https://en.wikipedia.org/wiki/JPEG), [TIFF](https://en.wikipedia.org/wiki/Tagged_Image_File_Format) and [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics)). The target audience ranges from enthusiast newcomers who whish to broaden their understanding of how digital imaging works to semi-professional photographers. Knowledge in color science is not compulsory, but it is recommended that you are eager to learn and ready to read our documentation ([RawPedia](http://rawpedia.rawtherapee.com/)) as well as look up basic concepts which lie outside the scope of RawPedia, such as [color balance](https://en.wikipedia.org/wiki/Color_balance), elsewhere. -Of course, professionals can use RawTherapee (for free) too, but will probably lack some peripheral features like Digital Assets Management, printing, uploading, etc. RawTherapee is not and probably will not be an all-in-one software in the foreseeable future. But the Open Source community is sufficiently developed now to offer you all that missing peripheral features. - -The general feature set includes : -* basic file handling (move, delete, review, ranking, tagging) through thumnails -* image editing through 32 bits floating points filters (called *Tools*) that affect the whole image uniformly (by opposition to local editing, which is planned but still on the TODO list) -* export to standard 8 bits image file, with possibility to automatically load the resulting image in you favorite image editor for local adjustment +Of course, professionals may use RawTherapee too while enjoying complete freedom, but will probably lack some peripheral features such as [Digital Asset Management](https://en.wikipedia.org/wiki/Digital_asset_management), printing, uploading, etc. RawTherapee is not aimed at being an inclusive all-in-one program, and the [open-source community](https://en.wikipedia.org/wiki/Open-source_movement) is sufficiently developed by now to offer all those peripheral features in other specialized software. ## Links Website: http://rawtherapee.com/ +Features: +http://rawpedia.rawtherapee.com/Features + Official documentation: http://rawpedia.rawtherapee.com/ diff --git a/rtdata/CMakeLists.txt b/rtdata/CMakeLists.txt index 9f6eee693..ad8fe3421 100644 --- a/rtdata/CMakeLists.txt +++ b/rtdata/CMakeLists.txt @@ -57,7 +57,7 @@ if (WIN32) include("${PROJECT_SOURCE_DIR}/ReleaseInfo.cmake") endif (REL_INFO_FILE STREQUAL REL_INFO_FILE-NOTFOUND) - configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/win/InnoSetup/WindowsInnoSetup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/WindowsInnoSetup.iss") + configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/../tools/win/InnoSetup/WindowsInnoSetup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/WindowsInnoSetup.iss") install (FILES "${CMAKE_CURRENT_BINARY_DIR}/WindowsInnoSetup.iss" DESTINATION ${BINDIR}) endif (WIN32) @@ -103,8 +103,8 @@ if (APPLE) elseif (PROC_BIT_DEPTH MATCHES 64) list (APPEND MACOSX_BUNDLE_COMMAND PROC_BIT_DEPTH=64) endif (PROC_BIT_DEPTH MATCHES 32) - list (APPEND MACOSX_BUNDLE_COMMAND sh "${PROJECT_SOURCE_DIR}/rtdata/osx/macosx_bundle.sh") - + list (APPEND MACOSX_BUNDLE_COMMAND sh "${PROJECT_SOURCE_DIR}/tools/osx/macosx_bundle.sh") + add_custom_target(macosx_bundle COMMAND ${MACOSX_BUNDLE_COMMAND} WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" diff --git a/rtdata/dcpprofiles/Canon EOS 6D.dcp b/rtdata/dcpprofiles/Canon EOS 6D.dcp new file mode 100644 index 000000000..65919144c Binary files /dev/null and b/rtdata/dcpprofiles/Canon EOS 6D.dcp differ diff --git a/rtdata/dcpprofiles/Canon PowerShot G7 X.dcp b/rtdata/dcpprofiles/Canon PowerShot G7 X.dcp index 4f3002d5d..3a6c7800f 100644 Binary files a/rtdata/dcpprofiles/Canon PowerShot G7 X.dcp and b/rtdata/dcpprofiles/Canon PowerShot G7 X.dcp differ diff --git a/rtdata/dcpprofiles/Canon PowerShot S110.dcp b/rtdata/dcpprofiles/Canon PowerShot S110.dcp index 50c65cd8d..7f310af24 100644 Binary files a/rtdata/dcpprofiles/Canon PowerShot S110.dcp and b/rtdata/dcpprofiles/Canon PowerShot S110.dcp differ diff --git a/rtdata/dcpprofiles/Fujifilm X-E1.dcp b/rtdata/dcpprofiles/Fujifilm X-E1.dcp new file mode 100644 index 000000000..71f8ce1ee Binary files /dev/null and b/rtdata/dcpprofiles/Fujifilm X-E1.dcp differ diff --git a/rtdata/dcpprofiles/Fujifilm X-E2.dcp b/rtdata/dcpprofiles/Fujifilm X-E2.dcp new file mode 100644 index 000000000..4f080062e Binary files /dev/null and b/rtdata/dcpprofiles/Fujifilm X-E2.dcp differ diff --git a/rtdata/dcpprofiles/Fujifilm X-T1.dcp b/rtdata/dcpprofiles/Fujifilm X-T1.dcp new file mode 100644 index 000000000..5d6c48b28 Binary files /dev/null and b/rtdata/dcpprofiles/Fujifilm X-T1.dcp differ diff --git a/rtdata/dcpprofiles/Fujifilm X-T10.dcp b/rtdata/dcpprofiles/Fujifilm X-T10.dcp new file mode 100644 index 000000000..9794624a5 Binary files /dev/null and b/rtdata/dcpprofiles/Fujifilm X-T10.dcp differ diff --git a/rtdata/dcpprofiles/Fujifilm X100T.dcp b/rtdata/dcpprofiles/Fujifilm X100T.dcp new file mode 100644 index 000000000..1fa827c5d Binary files /dev/null and b/rtdata/dcpprofiles/Fujifilm X100T.dcp differ diff --git a/rtdata/dcpprofiles/Nikon D7200.dcp b/rtdata/dcpprofiles/Nikon D7200.dcp new file mode 100644 index 000000000..01e5cfa13 Binary files /dev/null and b/rtdata/dcpprofiles/Nikon D7200.dcp differ diff --git a/rtdata/dcpprofiles/Pentax K-5 II.dcp b/rtdata/dcpprofiles/Pentax K-5 II.dcp index 22603c41f..6eef2206a 100644 Binary files a/rtdata/dcpprofiles/Pentax K-5 II.dcp and b/rtdata/dcpprofiles/Pentax K-5 II.dcp differ diff --git a/rtdata/dcpprofiles/Pentax K-5.dcp b/rtdata/dcpprofiles/Pentax K-5.dcp index f505634d9..52fbb7d85 100644 Binary files a/rtdata/dcpprofiles/Pentax K-5.dcp and b/rtdata/dcpprofiles/Pentax K-5.dcp differ diff --git a/rtdata/dcpprofiles/Pentax K10D.dcp b/rtdata/dcpprofiles/Pentax K10D.dcp index f9504b8a6..bad56c5d7 100644 Binary files a/rtdata/dcpprofiles/Pentax K10D.dcp and b/rtdata/dcpprofiles/Pentax K10D.dcp differ diff --git a/rtdata/dcpprofiles/Ricoh Pentax K-3.dcp b/rtdata/dcpprofiles/Ricoh Pentax K-3.dcp new file mode 100644 index 000000000..1eead1a2b Binary files /dev/null and b/rtdata/dcpprofiles/Ricoh Pentax K-3.dcp differ diff --git a/rtdata/dcpprofiles/Sony ILCE-6000.dcp b/rtdata/dcpprofiles/Sony ILCE-6000.dcp new file mode 100644 index 000000000..5ef8c4d31 Binary files /dev/null and b/rtdata/dcpprofiles/Sony ILCE-6000.dcp differ diff --git a/rtdata/dcpprofiles/Sony ILCE-7M2.dcp b/rtdata/dcpprofiles/Sony ILCE-7M2.dcp new file mode 100644 index 000000000..6d886e491 Binary files /dev/null and b/rtdata/dcpprofiles/Sony ILCE-7M2.dcp differ diff --git a/rtdata/iccprofiles/output/Rec2020.icm b/rtdata/iccprofiles/output/Rec2020.icm new file mode 100644 index 000000000..0decaf6dc Binary files /dev/null and b/rtdata/iccprofiles/output/Rec2020.icm differ diff --git a/rtdata/languages/Catala b/rtdata/languages/Catala index 513a55c9d..7ed78149f 100644 --- a/rtdata/languages/Catala +++ b/rtdata/languages/Catala @@ -128,7 +128,6 @@ FILEBROWSER_QUERYBUTTONHINT;Neteja la recerca FILEBROWSER_QUERYHINT;Escriviu part del nom d'un fitxer a cercar o bé llista amb comes com a separadort.\nE.g. 1001,1004,1199 \n\nCtrl-F entra a la finestra de text a cercar (en el gestor de fitxers).\nEnter comença a buscar.\nEscape neteja. FILEBROWSER_QUERYLABEL; Cerca: FILEBROWSER_RENAMEDLGLABEL;Reanomena fitxer -FILEBROWSER_RENAMEDLGMSG;Reanomena fitxer "%1" a: FILEBROWSER_SELECTDARKFRAME;Selecc. marc fosc... FILEBROWSER_SELECTFLATFIELD;Selecc. camp pla... FILEBROWSER_SHOWCOLORLABEL1HINT;Mostra imatges etiqueta vermella.\nDrecera: Alt-1 @@ -1302,6 +1301,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 !MAIN_BUTTON_NAVPREV_TOOLTIP;Navigate to the previous image relative to image opened in the Editor.\nShortcut: Shift-F3\n\nTo navigate to the previous image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F3 @@ -1315,7 +1315,6 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !MAIN_TAB_WAVELET;Wavelet !MAIN_TAB_WAVELET_TOOLTIP;Shortcut: Alt-w !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1506,6 +1505,10 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. !TP_COLORAPP_ADAPTVIEWING;Viewing luminosity (cd/m²) @@ -1748,6 +1751,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !TP_PREPROCESS_HOTPIXFILT_TOOLTIP;Tries to suppress hot pixels. !TP_PRSHARPENING_LABEL;Post-Resize Sharpening !TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red !TP_RAWEXPOS_BLACK_2;Blue @@ -1803,7 +1807,6 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Chinese (Simplified) b/rtdata/languages/Chinese (Simplified) index 115899bc0..5c6f5a39f 100644 --- a/rtdata/languages/Chinese (Simplified) +++ b/rtdata/languages/Chinese (Simplified) @@ -107,7 +107,6 @@ FILEBROWSER_RANK3_TOOLTIP;Rank 3 *\nShortcut: Shift-3 FILEBROWSER_RANK4_TOOLTIP;Rank 4 *\nShortcut: Shift-4 FILEBROWSER_RANK5_TOOLTIP;Rank 5 *\nShortcut: Shift-5 FILEBROWSER_RENAMEDLGLABEL;文件重命名 -FILEBROWSER_RENAMEDLGMSG;将"%1"更名为: FILEBROWSER_SELECTDARKFRAME;选择暗幅... FILEBROWSER_SELECTFLATFIELD;选择平场…… FILEBROWSER_SHOWDIRHINT;显示文件夹中所有图片 @@ -1219,6 +1218,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 !MAIN_BUTTON_NAVPREV_TOOLTIP;Navigate to the previous image relative to image opened in the Editor.\nShortcut: Shift-F3\n\nTo navigate to the previous image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F3 !MAIN_BUTTON_NAVSYNC_TOOLTIP;Synchronize the File Browser or Filmstrip with the Editor to reveal the thumbnail of the currently opened image, and clear any active filters.\nShortcut: x\n\nAs above, but without clearing active filters:\nShortcut: y\n(Note that the thumbnail of the opened image will not be shown if filtered out). @@ -1243,7 +1243,6 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !MAIN_TOOLTIP_PREVIEWG;Preview the Green channel.\nShortcut: g !MAIN_TOOLTIP_PREVIEWL;Preview the Luminosity.\nShortcut: v\n\n0.299*R + 0.587*G + 0.114*B !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !OPTIONS_DEFIMG_MISSING;The default profile for non-raw photos could not be found or is not set.\n\nPlease check your profiles' directory, it may be missing or damaged.\n\nDefault internal values will be used. !OPTIONS_DEFRAW_MISSING;The default profile for raw photos could not be found or is not set.\n\nPlease check your profiles' directory, it may be missing or damaged.\n\nDefault internal values will be used. !PARTIALPASTE_COLORTONING;Color toning @@ -1446,6 +1445,10 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !TP_BWMIX_SET_ROYGCBPMREL;Relative ROYGCBPM !TP_BWMIX_TCMODE_SATANDVALBLENDING;B&W Saturation and Value Blending !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHROMATABERR_LABEL;Chromatic Aberration !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. @@ -1708,6 +1711,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !TP_PREPROCESS_HOTPIXFILT_TOOLTIP;Tries to suppress hot pixels. !TP_PRSHARPENING_LABEL;Post-Resize Sharpening !TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1773,7 +1777,6 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Chinese (Traditional) b/rtdata/languages/Chinese (Traditional) index 6cf29d22a..c79d07525 100644 --- a/rtdata/languages/Chinese (Traditional) +++ b/rtdata/languages/Chinese (Traditional) @@ -52,7 +52,6 @@ FILEBROWSER_POPUPTRASH;Move to trash FILEBROWSER_POPUPUNRANK;Unrank FILEBROWSER_POPUPUNTRASH;Remove from trash FILEBROWSER_RENAMEDLGLABEL;Rename file -FILEBROWSER_RENAMEDLGMSG;Rename file "%1" to: FILEBROWSER_SHOWDIRHINT;Show all images of the directory FILEBROWSER_SHOWRANK1HINT;Show images ranked as 1 star FILEBROWSER_SHOWRANK2HINT;Show images ranked as 2 star @@ -954,6 +953,7 @@ TP_WBALANCE_TEMPERATURE;色溫 !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_FULLSCREEN;Fullscreen !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 @@ -999,7 +999,6 @@ TP_WBALANCE_TEMPERATURE;色溫 !MAIN_TOOLTIP_SHOWHIDETP1;Show/Hide the top panel.\nShortcut: Shift-l !MAIN_TOOLTIP_THRESHOLD;Threshold !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1304,6 +1303,10 @@ TP_WBALANCE_TEMPERATURE;色溫 !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHROMATABERR_LABEL;Chromatic Aberration !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. @@ -1666,6 +1669,7 @@ TP_WBALANCE_TEMPERATURE;色溫 !TP_RAWCACORR_AUTO;Auto-correction !TP_RAWCACORR_CABLUE;Blue !TP_RAWCACORR_CARED;Red +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1735,7 +1739,6 @@ TP_WBALANCE_TEMPERATURE;色溫 !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Czech b/rtdata/languages/Czech index b901a1513..e1c7bc704 100644 --- a/rtdata/languages/Czech +++ b/rtdata/languages/Czech @@ -191,7 +191,6 @@ FILEBROWSER_RANK3_TOOLTIP;Hodnocení 3 *\nZkratka: Shift-3 FILEBROWSER_RANK4_TOOLTIP;Hodnocení 4 *\nZkratka: Shift-4 FILEBROWSER_RANK5_TOOLTIP;Hodnocení 5 *\nZkratka: Shift-5 FILEBROWSER_RENAMEDLGLABEL;Přejmenování souboru -FILEBROWSER_RENAMEDLGMSG;Přejmenovat soubor "%1" na: FILEBROWSER_SELECTDARKFRAME;Výběr tmavého snímku... FILEBROWSER_SELECTFLATFIELD;Výběr Flat Field... FILEBROWSER_SHOWCOLORLABEL1HINT;Ukázat obrázky s červeným štítkem.\nZkratka: Alt-1 @@ -2011,18 +2010,23 @@ ZOOMPANEL_ZOOMOUT;Oddálit\nZkratka: - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !MAIN_BUTTON_SENDTOEDITOR;Edit image in external editor !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !PARTIALPASTE_PRSHARPENING;Post-resize sharpening !PREFERENCES_MONINTENT;Default monitor intent !PREFERENCES_MONPROFILE;Default monitor profile !PREFERENCES_PARSEDEXTDOWNHINT;Move selected extension down in the list. !PREFERENCES_PARSEDEXTUPHINT;Move selected extension up in the list. !PREFERENCES_PROFILE_NONE;None +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_ICM_PROFILEINTENT;Rendering Intent !TP_NEUTRAL;Reset +!TP_RAWCACORR_CASTR;Strength !TP_RETINEX_CONTEDIT_MAP;Mask equalizer !TP_RETINEX_CURVEEDITOR_MAP;L=f(L) !TP_RETINEX_CURVEEDITOR_MAP_TOOLTIP;This curve can be applied alone or with a Gaussian mask or wavelet mask.\nBeware of artifacts! @@ -2034,7 +2038,6 @@ ZOOMPANEL_ZOOMOUT;Oddálit\nZkratka: - !TP_RETINEX_ITER_TOOLTIP;Simulate a tone-mapping operator.\nHigh values increase the processing time. !TP_RETINEX_LABEL_MASK;Mask !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Dansk b/rtdata/languages/Dansk index 6c2e288e2..46e8049d6 100644 --- a/rtdata/languages/Dansk +++ b/rtdata/languages/Dansk @@ -50,7 +50,6 @@ FILEBROWSER_POPUPTRASH;Flyt til papirkurv FILEBROWSER_POPUPUNRANK;Fjern vurdering FILEBROWSER_POPUPUNTRASH;Fjern fra papirkurv FILEBROWSER_RENAMEDLGLABEL;Omdøb fil -FILEBROWSER_RENAMEDLGMSG;Omdøb filen "%1" til: FILEBROWSER_SHOWDIRHINT;Vis alle billeder i mappen FILEBROWSER_SHOWRANK1HINT;Vis billeder vurderet med 1 stjerne FILEBROWSER_SHOWRANK2HINT;Vis billeder vurderet med 2 stjerner @@ -950,6 +949,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_FULLSCREEN;Fullscreen !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 @@ -997,7 +997,6 @@ TP_WBALANCE_TEMPERATURE;Temperatur !MAIN_TOOLTIP_THRESHOLD;Threshold !MAIN_TOOLTIP_TOGGLE;Toggle the Before/After view.\nShortcut: Shift-b !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1302,6 +1301,10 @@ TP_WBALANCE_TEMPERATURE;Temperatur !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHROMATABERR_LABEL;Chromatic Aberration !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. @@ -1664,6 +1667,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !TP_RAWCACORR_AUTO;Auto-correction !TP_RAWCACORR_CABLUE;Blue !TP_RAWCACORR_CARED;Red +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1734,7 +1738,6 @@ TP_WBALANCE_TEMPERATURE;Temperatur !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 651fae931..48a293051 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -25,6 +25,8 @@ #25 2015-11-30 Korrekturen (TooWaBoo) RT4.2.507 #26 2015-12-13 Korrekturen (TooWaBoo) RT4.2.514 #26 2015-12-22 Korrekturen (TooWaBoo) RT4.2.536 +#27 2016-02-12 Retinexübersetzung (TooWaBoo) RT4.2.730 +#28 2016-03-19 Erweiterung/Korrekturen (TooWaBoo) RT4.2.880 ABOUT_TAB_BUILD;Version ABOUT_TAB_CREDITS;Danksagungen @@ -65,7 +67,7 @@ EDIT_OBJECT_TOOLTIP;Schaltet das Einstellungswerkzeug im Vorschaubild ein/aus EDIT_PIPETTE_TOOLTIP;Um einen Punkt der Kurve hinzuzufügen, halten Sie die Strg-Taste gedrückt und klicken mit der linke Maustaste auf die gewünschte Stelle in der Vorschau.\nUm den Punkt anzupassen, halten Sie die Strg-Taste gedrückt und klicken Sie mit der linken Maustaste auf den entsprechenden Bereich in der Vorschau. Dann lassen Sie die Strg-Taste los (es sei denn, Sie möchten eine Feineinstellung vornehmen) und bewegen die Maus bei gedrückter linker Maustaste nach oben oder unten, um den Punkt auf der Kurve zu bewegen. EXIFFILTER_APERTURE;Blende EXIFFILTER_CAMERA;Kamera -EXIFFILTER_EXPOSURECOMPENSATION;Belichtung\nBelichtungskorrektur (EV) +EXIFFILTER_EXPOSURECOMPENSATION;Belichtungskorrektur (EV) EXIFFILTER_FILETYPE;Dateityp EXIFFILTER_FOCALLEN;Brennweite EXIFFILTER_ISO;ISO @@ -119,9 +121,9 @@ FILEBROWSER_AUTODARKFRAME;Automatisches Dunkelbild FILEBROWSER_AUTOFLATFIELD;Automatisches Weißbild FILEBROWSER_BROWSEPATHBUTTONHINT;Ausgewählter Pfad öffnen FILEBROWSER_BROWSEPATHHINT;Einen Pfad eingeben:\nTaste:\nStrg + o Setzt den Cursor in das Eingabefeld\nEnter Öffnet den Pfad\nEsc Änderungen verwerfen\nUmschalt + Esc Eingabefeld verlassen\n\nSchnellnavigation:\nTaste:\n~ “Home“-Verzeichnis des Benutzers\n! Bilder-Verzeichnis des Benutzers -FILEBROWSER_CACHE;Zwischenspeicher -FILEBROWSER_CACHECLEARFROMFULL;Aus dem Zwischenspeicher entfernen (vollständig) -FILEBROWSER_CACHECLEARFROMPARTIAL;Aus dem Zwischenspeicher entfernen (teilweise) +FILEBROWSER_CACHE;Festplatten-Cache +FILEBROWSER_CACHECLEARFROMFULL;Aus dem Festplatten-Cache entfernen (vollständig) +FILEBROWSER_CACHECLEARFROMPARTIAL;Aus dem Festplatten-Cache entfernen (teilweise) FILEBROWSER_CLEARPROFILE;Profil löschen FILEBROWSER_COLORLABEL_TOOLTIP;Farbmarkierung\n\nTaste: Strg + Umschalt + 0 Ohne\nTaste: Strg + Umschalt + 1 Rot\nTaste: Strg + Umschalt + 2 Gelb\nTaste: Strg + Umschalt + 3 Grün\nTaste: Strg + Umschalt + 4 Blau\nTaste: Strg + Umschalt + 5 Violett FILEBROWSER_COPYPROFILE;Profil kopieren @@ -182,7 +184,6 @@ FILEBROWSER_RANK3_TOOLTIP;Bewertung 3 ***\nTaste: Umschalt + 3 FILEBROWSER_RANK4_TOOLTIP;Bewertung 4 ****\nTaste: Umschalt + 4 FILEBROWSER_RANK5_TOOLTIP;Bewertung 5 *****\nTaste: Umschalt + 5 FILEBROWSER_RENAMEDLGLABEL;Datei umbenennen -FILEBROWSER_RENAMEDLGMSG;Umbenennen der Datei "%1" in: FILEBROWSER_SELECTDARKFRAME;Dunkelbild wählen... FILEBROWSER_SELECTFLATFIELD;Weißbild wählen... FILEBROWSER_SHOWCOLORLABEL1HINT;Nur rot markierte Bilder anzeigen\nTaste: Alt + 1 @@ -224,21 +225,23 @@ FILECHOOSER_FILTER_SAME;Gleiche Format wie aktuelles Bild FILECHOOSER_FILTER_TIFF;TIFF-Dateien GENERAL_ABOUT;Über GENERAL_AFTER;Nachher +GENERAL_APPLY;Anwenden GENERAL_ASIMAGE;Als Bild GENERAL_AUTO;Automatisch GENERAL_BEFORE;Vorher -GENERAL_CANCEL;Abbruch +GENERAL_CANCEL;Abbrechen GENERAL_CLOSE;Schließen GENERAL_DISABLE;Deaktivieren GENERAL_DISABLED;Deaktiviert GENERAL_ENABLE;Aktivieren GENERAL_ENABLED;Aktiviert -GENERAL_FILE;Datei +GENERAL_FILE;Datei: GENERAL_LANDSCAPE;Quer GENERAL_NA;n/a GENERAL_NO;Nein GENERAL_NONE;Keine GENERAL_OK;OK +GENERAL_OPEN;Öffnen GENERAL_PORTRAIT;Portrait GENERAL_SAVE;Speichern GENERAL_UNCHANGED;(Unverändert) @@ -256,431 +259,445 @@ HISTORY_CUSTOMCURVE;Benutzerdefiniert HISTORY_DELSNAPSHOT;Entfernen HISTORY_FROMCLIPBOARD;Aus der Zwischenablage HISTORY_LABEL;Historie -HISTORY_MSG_1;Bild geladen -HISTORY_MSG_2;Profil geladen -HISTORY_MSG_3;Profil geändert -HISTORY_MSG_4;Historie durchsuchen -HISTORY_MSG_5;Belichtung - Helligkeit -HISTORY_MSG_6;Belichtung - Kontrast -HISTORY_MSG_7;Belichtung - Schwarzwert -HISTORY_MSG_8;Belichtung\nBelichtungskorrektur -HISTORY_MSG_9;Belichtung\nLichterkompression -HISTORY_MSG_10;Belichtung\nSchattenkompression -HISTORY_MSG_11;Belichtung\nTonwertkurve 1 -HISTORY_MSG_12;Belichtung - Auto -HISTORY_MSG_13;Belichtung\nAuto-Grenzwert -HISTORY_MSG_14;L*a*b* - Helligkeit -HISTORY_MSG_15;L*a*b* - Kontrast +HISTORY_MSG_1;(Bild geladen) +HISTORY_MSG_2;(Profil geladen) +HISTORY_MSG_3;(Profil geändert) +HISTORY_MSG_4;(Historie durchsuchen) +HISTORY_MSG_5;(Belichtung) - Helligkeit +HISTORY_MSG_6;(Belichtung) - Kontrast +HISTORY_MSG_7;(Belichtung) - Schwarzwert +HISTORY_MSG_8;(Belichtung)\nBelichtungskorrektur +HISTORY_MSG_9;(Belichtung)\nLichterkompression +HISTORY_MSG_10;(Belichtung)\nSchattenkompression +HISTORY_MSG_11;(Belichtung)\nTonwertkurve 1 +HISTORY_MSG_12;(Belichtung) - Auto +HISTORY_MSG_13;(Belichtung) - Clip-Faktor +HISTORY_MSG_14;(L*a*b*) - Helligkeit +HISTORY_MSG_15;(L*a*b*) - Kontrast HISTORY_MSG_16;- HISTORY_MSG_17;- HISTORY_MSG_18;- -HISTORY_MSG_19;L*a*b* - L-Kurve -HISTORY_MSG_20;Schärfung -HISTORY_MSG_21;Schärfung - USM\nRadius -HISTORY_MSG_22;Schärfung - USM\nIntensität -HISTORY_MSG_23;Schärfung - USM\nSchwellenwert -HISTORY_MSG_24;Schärfung - USM\nNur Kanten schärfen -HISTORY_MSG_25;Schärfung - USM\nKantenschärfung\nRadius -HISTORY_MSG_26;Schärfung - USM\nKantenschärfung\nKantentoleranz -HISTORY_MSG_27;Schärfung - USM\nHalokontrolle -HISTORY_MSG_28;Schärfung - USM\nHalokontrolle - Intensität -HISTORY_MSG_29;Schärfung - Methode -HISTORY_MSG_30;Schärfung - RLD\nRadius -HISTORY_MSG_31;Schärfung - RLD\nIntensität -HISTORY_MSG_32;Schärfung - RLD\nDämpfung -HISTORY_MSG_33;Schärfung - RLD\nIterationen -HISTORY_MSG_34;Objektivkorrektur\nProfil - Verzeichnung -HISTORY_MSG_35;Objektivkorrektur\nProfil - Vignettierung -HISTORY_MSG_36;Objektivkorrektur\nProfil - CA-Korrektur -HISTORY_MSG_37;Belichtung - Auto -HISTORY_MSG_38;Weißabgleich - Methode -HISTORY_MSG_39;Weißabgleich\nFarbtemperatur -HISTORY_MSG_40;Weißabgleich - Tönung -HISTORY_MSG_41;Belichtung\nTonwertkurve 1 - Modus -HISTORY_MSG_42;Belichtung\nTonwertkurve 2 -HISTORY_MSG_43;Belichtung\nTonwertkurve 2 - Modus -HISTORY_MSG_44;Luminanz-Rauschfilter\nRadius -HISTORY_MSG_45;Luminanz-Rauschfilter\nKantentoleranz -HISTORY_MSG_46;Farb-Rauschfilter -HISTORY_MSG_47;ICC Lichter aus Matrix\nüberlagern -HISTORY_MSG_48;Farbmanagement\nEingangsfarbprofil\nDCP - Tonwertkurve -HISTORY_MSG_49;Farbmanagement\nEingangsfarbprofil\nDCP - Illumination -HISTORY_MSG_50;Schatten/Lichter -HISTORY_MSG_51;Schatten/Lichter\nLichter -HISTORY_MSG_52;Schatten/Lichter\nSchatten -HISTORY_MSG_53;Schatten/Lichter\nTonwertbreite Lichter -HISTORY_MSG_54;Schatten/Lichter\nTonwertbreite Schatten -HISTORY_MSG_55;Schatten/Lichter\nLokaler Kontrast -HISTORY_MSG_56;Schatten/Lichter\nRadius -HISTORY_MSG_57;Grobe Drehung -HISTORY_MSG_58;Horizontal spiegeln -HISTORY_MSG_59;Vertikal spiegeln -HISTORY_MSG_60;Objektivkorrektur\nDrehen - Winkel -HISTORY_MSG_61;Objektivkorrektur\nAuto-Füllen -HISTORY_MSG_62;Objektivkorrektur\nVerzeichnung -HISTORY_MSG_63;Schnappschuss\nausgewählt -HISTORY_MSG_64;Ausschnitt -HISTORY_MSG_65;Objektivkorrektur\nFarbsaum entfernen -HISTORY_MSG_66;Belichtung\nLichter rekonstruieren -HISTORY_MSG_67;Belichtung\nLichterkompression\nUmfang -HISTORY_MSG_68;Belichtung\nLichterkompression\nMethode -HISTORY_MSG_69;Farbmanagement\nArbeitsfarbraum -HISTORY_MSG_70;Farbmanagement\nAusgabeprofil -HISTORY_MSG_71;Farbmanagement\nEingangsfarbprofil -HISTORY_MSG_72;Objektivkorrektur\nVignettierung - Intensität -HISTORY_MSG_73;RGB-Kanalmixer -HISTORY_MSG_74;Skalieren - Maßstab -HISTORY_MSG_75;Skalieren - Methode -HISTORY_MSG_76;Exif Metadaten -HISTORY_MSG_77;IPTC Metadaten +HISTORY_MSG_19;(L*a*b*) - L-Kurve +HISTORY_MSG_20;(Schärfung) +HISTORY_MSG_21;(Schärfung) - USM\nRadius +HISTORY_MSG_22;(Schärfung) - USM\nIntensität +HISTORY_MSG_23;(Schärfung) - USM\nSchwellenwert +HISTORY_MSG_24;(Schärfung) - USM\nNur Kanten schärfen +HISTORY_MSG_25;(Schärfung) - USM\nKantenschärfung\nRadius +HISTORY_MSG_26;(Schärfung) - USM\nKantenschärfung\nKantentoleranz +HISTORY_MSG_27;(Schärfung) - USM\nHalokontrolle +HISTORY_MSG_28;(Schärfung) - USM\nHalokontrolle - Intensität +HISTORY_MSG_29;(Schärfung) - Methode +HISTORY_MSG_30;(Schärfung) - RLD\nRadius +HISTORY_MSG_31;(Schärfung) - RLD\nIntensität +HISTORY_MSG_32;(Schärfung) - RLD\nDämpfung +HISTORY_MSG_33;(Schärfung) - RLD\nIterationen +HISTORY_MSG_34;(Objektivkorrektur)\nProfil - Verzeichnung +HISTORY_MSG_35;(Objektivkorrektur)\nProfil - Vignettierung +HISTORY_MSG_36;(Objektivkorrektur)\nProfil - CA-Korrektur +HISTORY_MSG_37;(Belichtung) - Auto +HISTORY_MSG_38;(Weißabgleich) - Methode +HISTORY_MSG_39;(Weißabgleich)\nFarbtemperatur +HISTORY_MSG_40;(Weißabgleich) - Tönung +HISTORY_MSG_41;(Belichtung)\nTonwertkurve 1 - Modus +HISTORY_MSG_42;(Belichtung)\nTonwertkurve 2 +HISTORY_MSG_43;(Belichtung)\nTonwertkurve 2 - Modus +HISTORY_MSG_44;(Luminanz-Rauschfilter)\nRadius +HISTORY_MSG_45;(Luminanz-Rauschfilter)\nKantentoleranz +HISTORY_MSG_46;(Farb-Rauschfilter) +HISTORY_MSG_47;(ICC Lichter aus Matrix\nüberlagern) +HISTORY_MSG_48;(Farbmanagement)\nEingangsfarbprofil\nDCP - Tonwertkurve +HISTORY_MSG_49;(Farbmanagement)\nEingangsfarbprofil\nDCP - Illumination +HISTORY_MSG_50;(Schatten/Lichter) +HISTORY_MSG_51;(Schatten/Lichter)\nLichter +HISTORY_MSG_52;(Schatten/Lichter)\nSchatten +HISTORY_MSG_53;(Schatten/Lichter)\nTonwertbreite Lichter +HISTORY_MSG_54;(Schatten/Lichter)\nTonwertbreite Schatten +HISTORY_MSG_55;(Schatten/Lichter)\nLokaler Kontrast +HISTORY_MSG_56;(Schatten/Lichter)\nRadius +HISTORY_MSG_57;(Grobe Drehung) +HISTORY_MSG_58;(Horizontal spiegeln) +HISTORY_MSG_59;(Vertikal spiegeln) +HISTORY_MSG_60;(Objektivkorrektur)\nDrehen - Winkel +HISTORY_MSG_61;(Objektivkorrektur)\nAuto-Füllen +HISTORY_MSG_62;(Objektivkorrektur)\nVerzeichnung +HISTORY_MSG_63;(Schnappschuss\nausgewählt) +HISTORY_MSG_64;(Ausschnitt) +HISTORY_MSG_65;(Objektivkorrektur)\nFarbsaum entfernen +HISTORY_MSG_66;(Belichtung)\nLichter rekonstruieren +HISTORY_MSG_67;(Belichtung)\nLichterkompression\nUmfang +HISTORY_MSG_68;(Belichtung)\nLichterkompression\nMethode +HISTORY_MSG_69;(Farbmanagement)\nArbeitsfarbraum +HISTORY_MSG_70;(Farbmanagement)\nAusgabeprofil +HISTORY_MSG_71;(Farbmanagement)\nEingangsfarbprofil +HISTORY_MSG_72;(Objektivkorrektur)\nVignettierung - Intensität +HISTORY_MSG_73;(RGB-Kanalmixer) +HISTORY_MSG_74;(Skalieren) - Maßstab +HISTORY_MSG_75;(Skalieren) - Methode +HISTORY_MSG_76;(Exif Metadaten) +HISTORY_MSG_77;(IPTC Metadaten) HISTORY_MSG_78;- -HISTORY_MSG_79;Skalieren - Breite -HISTORY_MSG_80;Skalieren - Höhe -HISTORY_MSG_81;Skalieren -HISTORY_MSG_82;Profil geändert -HISTORY_MSG_83;Schatten/Lichter\nSchärfemaske -HISTORY_MSG_84;Objektivkorrektur\nPerspektive -HISTORY_MSG_85;Objektivkorrektur\nProfil -HISTORY_MSG_86;RGB-Kurven\nHelligkeitsmodus -HISTORY_MSG_87;Impulsrauschred. -HISTORY_MSG_88;Impulsrauschred.\nSchwellenwert -HISTORY_MSG_89;Rauschreduzierung -HISTORY_MSG_90;Rauschreduzierung\nLuminanz -HISTORY_MSG_91;Rauschreduzierung\nChrominanz (Master) -HISTORY_MSG_92;Rauschreduzierung\nChrominanz - Gamma -HISTORY_MSG_93;Detailebenenkontrast\nWert -HISTORY_MSG_94;Detailebenenkontrast -HISTORY_MSG_95;L*a*b* - Chromatizität -HISTORY_MSG_96;L*a*b* - a-Kurve -HISTORY_MSG_97;L*a*b* - b-Kurve -HISTORY_MSG_98;Sensor-Matrix\nFarbinterpolation\nMethode -HISTORY_MSG_99;Vorverarbeitung\nHot-Pixel-Filter -HISTORY_MSG_100;Belichtung - Sättigung -HISTORY_MSG_101;HSV - Farbton (H) -HISTORY_MSG_102;HSV - Sättigung (S) -HISTORY_MSG_103;HSV - Dynamik (V) -HISTORY_MSG_104;HSV -HISTORY_MSG_105;Farbsaum entfernen -HISTORY_MSG_106;Farbsaum entfernen\nRadius -HISTORY_MSG_107;Farbsaum entfernen\nSchwellenwert -HISTORY_MSG_108;Belichtung\nLichterkompression\nSchwellenwert -HISTORY_MSG_109;Skalieren - Breite & Höhe -HISTORY_MSG_110;Skalieren - Anwenden auf: -HISTORY_MSG_111;L*a*b* - Farbverschiebung\nvermeiden +HISTORY_MSG_79;(Skalieren) - Breite +HISTORY_MSG_80;(Skalieren) - Höhe +HISTORY_MSG_81;(Skalieren) +HISTORY_MSG_82;(Profil geändert) +HISTORY_MSG_83;(Schatten/Lichter)\nSchärfemaske +HISTORY_MSG_84;(Objektivkorrektur)\nPerspektive +HISTORY_MSG_85;(Objektivkorrektur)\nProfil +HISTORY_MSG_86;(RGB-Kurven)\nHelligkeitsmodus +HISTORY_MSG_87;(Impulsrauschred.) +HISTORY_MSG_88;(Impulsrauschred.)\nSchwellenwert +HISTORY_MSG_89;(Rauschreduzierung) +HISTORY_MSG_90;(Rauschreduzierung)\nLuminanz +HISTORY_MSG_91;(Rauschreduzierung)\nChrominanz (Master) +HISTORY_MSG_92;(Rauschreduzierung)\nChrominanz - Gamma +HISTORY_MSG_93;(Detailebenenkontrast)\nWert +HISTORY_MSG_94;(Detailebenenkontrast) +HISTORY_MSG_95;(L*a*b*) - Chromatizität +HISTORY_MSG_96;(L*a*b*) - a-Kurve +HISTORY_MSG_97;(L*a*b*) - b-Kurve +HISTORY_MSG_98;(Sensor-Matrix)\nFarbinterpolation\nMethode +HISTORY_MSG_99;(Vorverarbeitung)\nHot-Pixel-Filter +HISTORY_MSG_100;(Belichtung) - Sättigung +HISTORY_MSG_101;(HSV) - Farbton (H) +HISTORY_MSG_102;(HSV) - Sättigung (S) +HISTORY_MSG_103;(HSV) - Dynamik (V) +HISTORY_MSG_104;(HSV) +HISTORY_MSG_105;(Farbsaum entfernen) +HISTORY_MSG_106;(Farbsaum entfernen)\nRadius +HISTORY_MSG_107;(Farbsaum entfernen)\nSchwellenwert +HISTORY_MSG_108;(Belichtung)\nLichterkompression\nSchwellenwert +HISTORY_MSG_109;(Skalieren) - Breite & Höhe +HISTORY_MSG_110;(Skalieren) - Anwenden auf: +HISTORY_MSG_111;(L*a*b*) - Farbverschiebung\nvermeiden HISTORY_MSG_112;--unused-- -HISTORY_MSG_113;L*a*b* - Hautfarbtöne\nschützen -HISTORY_MSG_114;Sensor Bayer-Matrix\nFarbinterpolation\nDCB-Iterationen -HISTORY_MSG_115;Sensor-Matrix\nFarbinterpolation\nFalschfarbenunterdrückung -HISTORY_MSG_116;Sensor Bayer-Matrix\nFarbinterpolation\nDCB-Verbesserung -HISTORY_MSG_117;Sensor Bayer-Matrix\nChromatische Aberration\nRot -HISTORY_MSG_118;Sensor Bayer-Matrix\nChromatische Aberration\nBlau -HISTORY_MSG_119;Sensor Bayer-Matrix\nVorverarbeitung\nZeilenrauschfilter -HISTORY_MSG_120;Sensor Bayer-Matrix\nVorverarbeitung\nGrün-Ausgleich -HISTORY_MSG_121;Sensor Bayer-Matrix\nChromatische Aberration\nAutomatische Korrektur -HISTORY_MSG_122;Dunkelbild\nAutomatische Auswahl -HISTORY_MSG_123;Dunkelbild - Datei -HISTORY_MSG_124;Weißpunkt\nKorrekturfaktor -HISTORY_MSG_125;Belichtungskorrektur\nLichter schützen -HISTORY_MSG_126;Weißbild - Datei -HISTORY_MSG_127;Weißbild\nAutomatische Auswahl -HISTORY_MSG_128;Weißbild\nUnschärferadius -HISTORY_MSG_129;Weißbild - Unschärfetyp -HISTORY_MSG_130;Autom. Verzeichnung -HISTORY_MSG_131;Rauschreduzierung\nLuminanz -HISTORY_MSG_132;Rauschreduzierung\nChrominanz -HISTORY_MSG_133;Farbmanagement\nAusgabeprofil\nAusgabe-Gamma -HISTORY_MSG_134;Farbmanagement\nAusgabeprofil\nGamma -HISTORY_MSG_135;Farbmanagement\nAusgabeprofil\nFreies Gamma -HISTORY_MSG_136;Farbmanagement\nAusgabeprofil\nGradient (linear) -HISTORY_MSG_137;Sensor Bayer-Matrix\nSchwarzpunkt - Grün 1 -HISTORY_MSG_138;Sensor Bayer-Matrix\nSchwarzpunkt - Rot -HISTORY_MSG_139;Sensor Bayer-Matrix\nSchwarzpunkt - Blau -HISTORY_MSG_140;Sensor Bayer-Matrix\nSchwarzpunkt - Grün 2 -HISTORY_MSG_141;Sensor Bayer-Matrix\nSchwarzpunkt\nGrün-Werte angleichen -HISTORY_MSG_142;Kantenschärfung\nIterationen -HISTORY_MSG_143;Kantenschärfung\nIntensität -HISTORY_MSG_144;Mikrokontrast\nIntensität -HISTORY_MSG_145;Mikrokontrast\nGleichmäßigkeit -HISTORY_MSG_146;Kantenschärfung -HISTORY_MSG_147;Kantenschärfung\nNur Luminanz -HISTORY_MSG_148;Mikrokontrast -HISTORY_MSG_149;Mikrokontrast\n3×3-Matrix -HISTORY_MSG_150;Artefakt-/Rauschred.\nnach Farbinterpolation -HISTORY_MSG_151;Dynamik -HISTORY_MSG_152;Dynamik - Pastelltöne -HISTORY_MSG_153;Dynamik\nGesättigte Töne -HISTORY_MSG_154;Dynamik\nHautfarbtöne schützen -HISTORY_MSG_155;Dynamik\nFarbverschiebungen\nvermeiden -HISTORY_MSG_156;Dynamik\nPastell und gesättigte\nTöne koppeln -HISTORY_MSG_157;Dynamik\nPastell/gesättigte Töne\nSchwellenwert -HISTORY_MSG_158;Dynamikkompression\nIntensität -HISTORY_MSG_159;Dynamikkompression\nKantenschutz -HISTORY_MSG_160;Dynamikkompression\nFaktor -HISTORY_MSG_161;Dynamikkompression\nIterationen -HISTORY_MSG_162;Dynamikkompression -HISTORY_MSG_163;RGB-Kurven - Rot -HISTORY_MSG_164;RGB-Kurven - Grün -HISTORY_MSG_165;RGB-Kurven - Blau -HISTORY_MSG_166;Belichtung - Zurücksetzen -HISTORY_MSG_167;Sensor-Matrix\nFarbinterpolation\nMethode -HISTORY_MSG_168;L*a*b* - CC-Kurve -HISTORY_MSG_169;L*a*b* - CH-Kurve -HISTORY_MSG_170;Dynamik - HH-Kurve -HISTORY_MSG_171;L*a*b* - LC-Kurve -HISTORY_MSG_172;L*a*b* - LC-Kurve\nbeschränken -HISTORY_MSG_173;Rauschreduzierung\nLuminanzdetails -HISTORY_MSG_174;CIECAM02 -HISTORY_MSG_175;CIECAM02 - Szene\nCAT02-Adaptation -HISTORY_MSG_176;CIECAM02\nBetrachtungsbed.\nUmgebung -HISTORY_MSG_177;CIECAM02 - Szene\nLeuchtstärke -HISTORY_MSG_178;CIECAM02\nBetrachtungsbed.\nLeuchtstärke -HISTORY_MSG_179;CIECAM02 - Szene\nWeißpunktmodell -HISTORY_MSG_180;CIECAM02 - Helligkeit (J) -HISTORY_MSG_181;CIECAM02 - Buntheit (H) -HISTORY_MSG_182;CIECAM02 - Szene\nCAT02-Automatisch -HISTORY_MSG_183;CIECAM02 - Kontrast (J) -HISTORY_MSG_184;CIECAM02 - Szene\nDunkle Umgebung -HISTORY_MSG_185;CIECAM02\nBetrachtungsbed.\nGamutkontrolle -HISTORY_MSG_186;CIECAM02 - Algorithmus -HISTORY_MSG_187;CIECAM02 - Hautfarbtöne\nschützen -HISTORY_MSG_188;CIECAM02 - Helligkeit (Q) -HISTORY_MSG_189;CIECAM02 - Kontrast (Q) -HISTORY_MSG_190;CIECAM02 - Sättigung (S) -HISTORY_MSG_191;CIECAM02 - Farbigkeit (M) -HISTORY_MSG_192;CIECAM02 - Farbton (H) -HISTORY_MSG_193;CIECAM02\nTonwertkurve 1 -HISTORY_MSG_194;CIECAM02\nTonwertkurve 2 -HISTORY_MSG_195;CIECAM02\nTonwertkurve 1 - Modus -HISTORY_MSG_196;CIECAM02\nTonwertkurve 2 - Modus -HISTORY_MSG_197;CIECAM02 - Farbkurve -HISTORY_MSG_198;CIECAM02 - Farbkurve\nModus -HISTORY_MSG_199;CIECAM02 - Ausgabe-\nHistogramm anzeigen -HISTORY_MSG_200;CIECAM02\nDynamikkompression -HISTORY_MSG_201;Rauschreduzierung\nDelta-Chrominanz\nRot/Grün -HISTORY_MSG_202;Rauschreduzierung\nDelta-Chrominanz\nBlau/Gelb -HISTORY_MSG_203;Rauschreduzierung\nMethode -HISTORY_MSG_204;Sensor Bayer-Matrix\nFarbinterpolation\nLMMSE-Verbesserung -HISTORY_MSG_205;CIECAM02\nBetrachtungsbed.\nHot/Bad-Pixelfilter -HISTORY_MSG_206;CIECAM02 - Szene\nAuto-Leuchtstärke -HISTORY_MSG_207;Farbsaum entfernen\nFarbtonkurve -HISTORY_MSG_208;Weißabgleich\nBlau/Rot-Korrektur -HISTORY_MSG_210;Grauverlaufsfilter\nRotationswinkel -HISTORY_MSG_211;Grauverlaufsfilter -HISTORY_MSG_212;Vignettierungsfilter\nIntensität -HISTORY_MSG_213;Vignettierungsfilter -HISTORY_MSG_214;Schwarz/Weiß -HISTORY_MSG_215;Schwarz/Weiß - Rot -HISTORY_MSG_216;Schwarz/Weiß - Grün -HISTORY_MSG_217;Schwarz/Weiß - Blau -HISTORY_MSG_218;Schwarz/Weiß\nGamma - Rot -HISTORY_MSG_219;Schwarz/Weiß\nGamma - Grün -HISTORY_MSG_220;Schwarz/Weiß\nGamma - Blau -HISTORY_MSG_221;Schwarz/Weiß\nFarbfilter -HISTORY_MSG_222;Schwarz/Weiß\nVorgaben -HISTORY_MSG_223;Schwarz/Weiß - Orange -HISTORY_MSG_224;Schwarz/Weiß - Gelb -HISTORY_MSG_225;Schwarz/Weiß - Cyan -HISTORY_MSG_226;Schwarz/Weiß - Magenta -HISTORY_MSG_227;Schwarz/Weiß - Violett -HISTORY_MSG_228;Schwarz/Weiß\nLuminanzequalizer -HISTORY_MSG_229;Schwarz/Weiß\nLuminanzequalizer -HISTORY_MSG_230;Schwarz/Weiß - Modus -HISTORY_MSG_231;Schwarz/Weiß\n“Bevor“-Kurve -HISTORY_MSG_232;Schwarz/Weiß\n“Bevor“-Kurventyp -HISTORY_MSG_233;Schwarz/Weiß\n“Danach“-Kurve -HISTORY_MSG_234;Schwarz/Weiß\n“Danach“-Kurventyp -HISTORY_MSG_235;Schwarz/Weiß\nAuto-Kanalmixer +HISTORY_MSG_113;(L*a*b*) - Hautfarbtöne\nschützen +HISTORY_MSG_114;(Sensor Bayer-Matrix)\nFarbinterpolation\nDCB-Iterationen +HISTORY_MSG_115;(Sensor-Matrix)\nFarbinterpolation\nFalschfarbenunterdrückung +HISTORY_MSG_116;(Sensor Bayer-Matrix)\nFarbinterpolation\nDCB-Verbesserung +HISTORY_MSG_117;(Sensor Bayer-Matrix)\nChromatische Aberration\nRot +HISTORY_MSG_118;(Sensor Bayer-Matrix)\nChromatische Aberration\nBlau +HISTORY_MSG_119;(Sensor Bayer-Matrix)\nVorverarbeitung\nZeilenrauschfilter +HISTORY_MSG_120;(Sensor Bayer-Matrix)\nVorverarbeitung\nGrün-Ausgleich +HISTORY_MSG_121;(Sensor Bayer-Matrix)\nChromatische Aberration\nAutomatische Korrektur +HISTORY_MSG_122;(Dunkelbild)\nAutomatische Auswahl +HISTORY_MSG_123;(Dunkelbild) - Datei +HISTORY_MSG_124;(Weißpunkt)\nKorrekturfaktor +HISTORY_MSG_125;(Belichtungskorrektur)\nLichter schützen +HISTORY_MSG_126;(Weißbild) - Datei +HISTORY_MSG_127;(Weißbild)\nAutomatische Auswahl +HISTORY_MSG_128;(Weißbild)\nUnschärferadius +HISTORY_MSG_129;(Weißbild) - Unschärfetyp +HISTORY_MSG_130;(Autom. Verzeichnung) +HISTORY_MSG_131;(Rauschreduzierung)\nLuminanz +HISTORY_MSG_132;(Rauschreduzierung)\nChrominanz +HISTORY_MSG_133;(Farbmanagement)\nAusgabeprofil\nAusgabe-Gamma +HISTORY_MSG_134;(Farbmanagement)\nAusgabeprofil\nGamma +HISTORY_MSG_135;(Farbmanagement)\nAusgabeprofil\nFreies Gamma +HISTORY_MSG_136;(Farbmanagement)\nAusgabeprofil\nGradient (linear) +HISTORY_MSG_137;(Sensor Bayer-Matrix)\nSchwarzpunkt - Grün 1 +HISTORY_MSG_138;(Sensor Bayer-Matrix)\nSchwarzpunkt - Rot +HISTORY_MSG_139;(Sensor Bayer-Matrix)\nSchwarzpunkt - Blau +HISTORY_MSG_140;(Sensor Bayer-Matrix)\nSchwarzpunkt - Grün 2 +HISTORY_MSG_141;(Sensor Bayer-Matrix)\nSchwarzpunkt\nGrün-Werte angleichen +HISTORY_MSG_142;(Kantenschärfung)\nIterationen +HISTORY_MSG_143;(Kantenschärfung)\nIntensität +HISTORY_MSG_144;(Mikrokontrast)\nIntensität +HISTORY_MSG_145;(Mikrokontrast)\nGleichmäßigkeit +HISTORY_MSG_146;(Kantenschärfung) +HISTORY_MSG_147;(Kantenschärfung)\nNur Luminanz +HISTORY_MSG_148;(Mikrokontrast) +HISTORY_MSG_149;(Mikrokontrast)\n3×3-Matrix +HISTORY_MSG_150;(Artefakt-/Rauschred.\nnach Farbinterpolation) +HISTORY_MSG_151;(Dynamik) +HISTORY_MSG_152;(Dynamik) - Pastelltöne +HISTORY_MSG_153;(Dynamik)\nGesättigte Töne +HISTORY_MSG_154;(Dynamik)\nHautfarbtöne schützen +HISTORY_MSG_155;(Dynamik)\nFarbverschiebungen\nvermeiden +HISTORY_MSG_156;(Dynamik)\nPastell und gesättigte\nTöne koppeln +HISTORY_MSG_157;(Dynamik)\nPastell/gesättigte Töne\nSchwellenwert +HISTORY_MSG_158;(Dynamikkompression)\nIntensität +HISTORY_MSG_159;(Dynamikkompression)\nKantenschutz +HISTORY_MSG_160;(Dynamikkompression)\nFaktor +HISTORY_MSG_161;(Dynamikkompression)\nIterationen +HISTORY_MSG_162;(Dynamikkompression) +HISTORY_MSG_163;(RGB-Kurven) - Rot +HISTORY_MSG_164;(RGB-Kurven) - Grün +HISTORY_MSG_165;(RGB-Kurven) - Blau +HISTORY_MSG_166;(Belichtung) - Zurücksetzen +HISTORY_MSG_167;(Sensor-Matrix)\nFarbinterpolation\nMethode +HISTORY_MSG_168;(L*a*b*) - CC-Kurve +HISTORY_MSG_169;(L*a*b*) - CH-Kurve +HISTORY_MSG_170;(Dynamik) - HH-Kurve +HISTORY_MSG_171;(L*a*b*) - LC-Kurve +HISTORY_MSG_172;(L*a*b*) - LC-Kurve\nbeschränken +HISTORY_MSG_173;(Rauschreduzierung)\nLuminanzdetails +HISTORY_MSG_174;(CIECAM02) +HISTORY_MSG_175;(CIECAM02) - Szene\nCAT02-Adaptation +HISTORY_MSG_176;(CIECAM02)\nBetrachtungsbed.\nUmgebung +HISTORY_MSG_177;(CIECAM02) - Szene\nLeuchtstärke +HISTORY_MSG_178;(CIECAM02)\nBetrachtungsbed.\nLeuchtstärke +HISTORY_MSG_179;(CIECAM02) - Szene\nWeißpunktmodell +HISTORY_MSG_180;(CIECAM02) - Helligkeit (J) +HISTORY_MSG_181;(CIECAM02) - Buntheit (H) +HISTORY_MSG_182;(CIECAM02) - Szene\nCAT02-Automatisch +HISTORY_MSG_183;(CIECAM02) - Kontrast (J) +HISTORY_MSG_184;(CIECAM02) - Szene\nDunkle Umgebung +HISTORY_MSG_185;(CIECAM02)\nBetrachtungsbed.\nGamutkontrolle +HISTORY_MSG_186;(CIECAM02) - Algorithmus +HISTORY_MSG_187;(CIECAM02) - Hautfarbtöne\nschützen +HISTORY_MSG_188;(CIECAM02) - Helligkeit (Q) +HISTORY_MSG_189;(CIECAM02) - Kontrast (Q) +HISTORY_MSG_190;(CIECAM02) - Sättigung (S) +HISTORY_MSG_191;(CIECAM02) - Farbigkeit (M) +HISTORY_MSG_192;(CIECAM02) - Farbton (H) +HISTORY_MSG_193;(CIECAM02)\nTonwertkurve 1 +HISTORY_MSG_194;(CIECAM02)\nTonwertkurve 2 +HISTORY_MSG_195;(CIECAM02)\nTonwertkurve 1 - Modus +HISTORY_MSG_196;(CIECAM02)\nTonwertkurve 2 - Modus +HISTORY_MSG_197;(CIECAM02) - Farbkurve +HISTORY_MSG_198;(CIECAM02) - Farbkurve\nModus +HISTORY_MSG_199;(CIECAM02) - Ausgabe-\nHistogramm anzeigen +HISTORY_MSG_200;(CIECAM02)\nDynamikkompression +HISTORY_MSG_201;(Rauschreduzierung)\nDelta-Chrominanz\nRot/Grün +HISTORY_MSG_202;(Rauschreduzierung)\nDelta-Chrominanz\nBlau/Gelb +HISTORY_MSG_203;(Rauschreduzierung)\nMethode +HISTORY_MSG_204;(Sensor Bayer-Matrix)\nFarbinterpolation\nLMMSE-Verbesserung +HISTORY_MSG_205;(CIECAM02)\nBetrachtungsbed.\nHot/Bad-Pixelfilter +HISTORY_MSG_206;(CIECAM02) - Szene\nAuto-Leuchtstärke +HISTORY_MSG_207;(Farbsaum entfernen)\nFarbtonkurve +HISTORY_MSG_208;(Weißabgleich)\nBlau/Rot-Korrektur +HISTORY_MSG_210;(Grauverlaufsfilter)\nRotationswinkel +HISTORY_MSG_211;(Grauverlaufsfilter) +HISTORY_MSG_212;(Vignettierungsfilter)\nIntensität +HISTORY_MSG_213;(Vignettierungsfilter) +HISTORY_MSG_214;(Schwarz/Weiß) +HISTORY_MSG_215;(Schwarz/Weiß) - Rot +HISTORY_MSG_216;(Schwarz/Weiß) - Grün +HISTORY_MSG_217;(Schwarz/Weiß) - Blau +HISTORY_MSG_218;(Schwarz/Weiß)\nGamma - Rot +HISTORY_MSG_219;(Schwarz/Weiß)\nGamma - Grün +HISTORY_MSG_220;(Schwarz/Weiß)\nGamma - Blau +HISTORY_MSG_221;(Schwarz/Weiß)\nFarbfilter +HISTORY_MSG_222;(Schwarz/Weiß)\nVorgaben +HISTORY_MSG_223;(Schwarz/Weiß) - Orange +HISTORY_MSG_224;(Schwarz/Weiß) - Gelb +HISTORY_MSG_225;(Schwarz/Weiß) - Cyan +HISTORY_MSG_226;(Schwarz/Weiß) - Magenta +HISTORY_MSG_227;(Schwarz/Weiß) - Violett +HISTORY_MSG_228;(Schwarz/Weiß)\nLuminanzequalizer +HISTORY_MSG_229;(Schwarz/Weiß)\nLuminanzequalizer +HISTORY_MSG_230;(Schwarz/Weiß) - Modus +HISTORY_MSG_231;(Schwarz/Weiß)\n“Bevor“-Kurve +HISTORY_MSG_232;(Schwarz/Weiß)\n“Bevor“-Kurventyp +HISTORY_MSG_233;(Schwarz/Weiß)\n“Danach“-Kurve +HISTORY_MSG_234;(Schwarz/Weiß)\n“Danach“-Kurventyp +HISTORY_MSG_235;(Schwarz/Weiß)\nAuto-Kanalmixer HISTORY_MSG_236;--unused-- -HISTORY_MSG_237;Schwarz/Weiß - Mixer -HISTORY_MSG_238;Grauverlaufsfilter\nBereich -HISTORY_MSG_239;Grauverlaufsfilter\nIntensität -HISTORY_MSG_240;Grauverlaufsfilter\nRotationsachsen -HISTORY_MSG_241;Vignettierungsfilter\nBereich -HISTORY_MSG_242;Vignettierungsfilter\nForm -HISTORY_MSG_243;Objektivkorrektur\nVignettierung - Radius -HISTORY_MSG_244;Objektivkorrektur\nVignettierung - Faktor -HISTORY_MSG_245;Objektivkorrektur\nVignettierung - Zentrum -HISTORY_MSG_246;L*a*b* - CL-Kurve -HISTORY_MSG_247;L*a*b* - LH-Kurve -HISTORY_MSG_248;L*a*b* - HH-Kurve -HISTORY_MSG_249;Detailebenenkontrast\nSchwellenwert -HISTORY_MSG_250;Rauschreduzierung\nVerbesserung -HISTORY_MSG_251;Schwarz/Weiß\nAlgorithmus -HISTORY_MSG_252;Detailebenenkontrast\nHautfarbtöne schützen -HISTORY_MSG_253;Detailebenenkontrast\nArtefakte reduzieren -HISTORY_MSG_254;Detailebenenkontrast\nHautfarbton -HISTORY_MSG_255;Rauschreduzierung\nMedianfilter -HISTORY_MSG_256;Rauschreduzierung\nMediantyp -HISTORY_MSG_257;Farbanpassungen -HISTORY_MSG_258;Farbanpassungen\nFarbkurve -HISTORY_MSG_259;Farbanpassungen\nDeckkraftkurve -HISTORY_MSG_260;Farbanpassungen\na*[b*]-Transparenz -HISTORY_MSG_261;Farbanpassungen\nMethode -HISTORY_MSG_262;Farbanpassungen\nb*-Transparenz -HISTORY_MSG_263;Farbanpassungen\nSchatten - Blau/Rot -HISTORY_MSG_264;Farbanpassungen\nSchatten - Cyan/Grün -HISTORY_MSG_265;Farbanpassungen\nSchatten - Gelb/Blau -HISTORY_MSG_266;Farbanpassungen\nMitten - Blau/Rot -HISTORY_MSG_267;Farbanpassungen\nMitten - Cyan/Grün -HISTORY_MSG_268;Farbanpassungen\nMitten - Gelb/Blau -HISTORY_MSG_269;Farbanpassungen\nLichter - Blau/Rot -HISTORY_MSG_270;Farbanpassungen\nLichter - Cyan/Grün -HISTORY_MSG_271;Farbanpassungen\nLichter - Gelb/Blau -HISTORY_MSG_272;Farbanpassungen\nFarbausgleich -HISTORY_MSG_273;Farbanpassungen\nZurücksetzen -HISTORY_MSG_274;Farbanpassungen\nSättigung Schatten -HISTORY_MSG_275;Farbanpassungen\nSättigung Lichter -HISTORY_MSG_276;Farbanpassungen\nDeckkraft +HISTORY_MSG_237;(Schwarz/Weiß) - Mixer +HISTORY_MSG_238;(Grauverlaufsfilter)\nBereich +HISTORY_MSG_239;(Grauverlaufsfilter)\nIntensität +HISTORY_MSG_240;(Grauverlaufsfilter)\nRotationsachsen +HISTORY_MSG_241;(Vignettierungsfilter)\nBereich +HISTORY_MSG_242;(Vignettierungsfilter)\nForm +HISTORY_MSG_243;(Objektivkorrektur)\nVignettierung - Radius +HISTORY_MSG_244;(Objektivkorrektur)\nVignettierung - Faktor +HISTORY_MSG_245;(Objektivkorrektur)\nVignettierung - Zentrum +HISTORY_MSG_246;(L*a*b*) - CL-Kurve +HISTORY_MSG_247;(L*a*b*) - LH-Kurve +HISTORY_MSG_248;(L*a*b*) - HH-Kurve +HISTORY_MSG_249;(Detailebenenkontrast)\nSchwellenwert +HISTORY_MSG_250;(Rauschreduzierung)\nVerbesserung +HISTORY_MSG_251;(Schwarz/Weiß)\nAlgorithmus +HISTORY_MSG_252;(Detailebenenkontrast)\nHautfarbtöne schützen +HISTORY_MSG_253;(Detailebenenkontrast)\nArtefakte reduzieren +HISTORY_MSG_254;(Detailebenenkontrast)\nHautfarbton +HISTORY_MSG_255;(Rauschreduzierung)\nMedianfilter +HISTORY_MSG_256;(Rauschreduzierung)\nMediantyp +HISTORY_MSG_257;(Farbanpassungen) +HISTORY_MSG_258;(Farbanpassungen)\nFarbkurve +HISTORY_MSG_259;(Farbanpassungen)\nDeckkraftkurve +HISTORY_MSG_260;(Farbanpassungen)\na*[b*]-Transparenz +HISTORY_MSG_261;(Farbanpassungen)\nMethode +HISTORY_MSG_262;(Farbanpassungen)\nb*-Transparenz +HISTORY_MSG_263;(Farbanpassungen)\nSchatten - Blau/Rot +HISTORY_MSG_264;(Farbanpassungen)\nSchatten - Cyan/Grün +HISTORY_MSG_265;(Farbanpassungen)\nSchatten - Gelb/Blau +HISTORY_MSG_266;(Farbanpassungen)\nMitten - Blau/Rot +HISTORY_MSG_267;(Farbanpassungen)\nMitten - Cyan/Grün +HISTORY_MSG_268;(Farbanpassungen)\nMitten - Gelb/Blau +HISTORY_MSG_269;(Farbanpassungen)\nLichter - Blau/Rot +HISTORY_MSG_270;(Farbanpassungen)\nLichter - Cyan/Grün +HISTORY_MSG_271;(Farbanpassungen)\nLichter - Gelb/Blau +HISTORY_MSG_272;(Farbanpassungen)\nFarbausgleich +HISTORY_MSG_273;(Farbanpassungen)\nZurücksetzen +HISTORY_MSG_274;(Farbanpassungen)\nSättigung Schatten +HISTORY_MSG_275;(Farbanpassungen)\nSättigung Lichter +HISTORY_MSG_276;(Farbanpassungen)\nDeckkraft HISTORY_MSG_277;--unused-- -HISTORY_MSG_278;Farbanpassungen\nLuminanz schützen -HISTORY_MSG_279;Farbanpassungen\nSchatten -HISTORY_MSG_280;Farbanpassungen\nLichter -HISTORY_MSG_281;Farbanpassungen\nSättigung schützen\nIntensität -HISTORY_MSG_282;Farbanpassungen\nSättigung schützen\nSchwellenwert -HISTORY_MSG_283;Farbanpassungen\nIntensität -HISTORY_MSG_284;Farbanpassungen\nSättigung schützen\nAutomatisch -HISTORY_MSG_285;Rauschreduzierung\nMedianmethode -HISTORY_MSG_286;Rauschreduzierung\nMediantyp -HISTORY_MSG_287;Rauschreduzierung\nMedianiterationen -HISTORY_MSG_288;Weißbild\nKontrolle zu heller Bereiche -HISTORY_MSG_289;Weißbild\nAuto-Kontrolle zu\nheller Bereiche -HISTORY_MSG_290;Sensor X-Trans-Matrix\nSchwarzpunkt - Rot -HISTORY_MSG_291;Sensor X-Trans-Matrix\nSchwarzpunkt - Grün -HISTORY_MSG_292;Sensor X-Trans-Matrix\nSchwarzpunkt - Blau -HISTORY_MSG_293;Filmsimulation -HISTORY_MSG_294;Filmsimulation\nIntensität -HISTORY_MSG_295;Filmsimulation - Film -HISTORY_MSG_296;Rauschreduzierung\nLuminanzkurve -HISTORY_MSG_297;Rauschreduzierung\nQualität -HISTORY_MSG_298;Vorverarbeitung\nDead-Pixel-Filter -HISTORY_MSG_299;Rauschreduzierung\nChrominanzkurve +HISTORY_MSG_278;(Farbanpassungen)\nLuminanz schützen +HISTORY_MSG_279;(Farbanpassungen)\nSchatten +HISTORY_MSG_280;(Farbanpassungen)\nLichter +HISTORY_MSG_281;(Farbanpassungen)\nSättigung schützen\nIntensität +HISTORY_MSG_282;(Farbanpassungen)\nSättigung schützen\nSchwellenwert +HISTORY_MSG_283;(Farbanpassungen)\nIntensität +HISTORY_MSG_284;(Farbanpassungen)\nSättigung schützen\nAutomatisch +HISTORY_MSG_285;(Rauschreduzierung)\nMedianmethode +HISTORY_MSG_286;(Rauschreduzierung)\nMediantyp +HISTORY_MSG_287;(Rauschreduzierung)\nMedianiterationen +HISTORY_MSG_288;(Weißbild)\nKontrolle zu heller Bereiche +HISTORY_MSG_289;(Weißbild)\nAuto-Kontrolle zu\nheller Bereiche +HISTORY_MSG_290;(Sensor X-Trans-Matrix)\nSchwarzpunkt - Rot +HISTORY_MSG_291;(Sensor X-Trans-Matrix)\nSchwarzpunkt - Grün +HISTORY_MSG_292;(Sensor X-Trans-Matrix)\nSchwarzpunkt - Blau +HISTORY_MSG_293;(Filmsimulation) +HISTORY_MSG_294;(Filmsimulation)\nIntensität +HISTORY_MSG_295;(Filmsimulation) - Film +HISTORY_MSG_296;(Rauschreduzierung)\nLuminanzkurve +HISTORY_MSG_297;(Rauschreduzierung)\nQualität +HISTORY_MSG_298;(Vorverarbeitung)\nDead-Pixel-Filter +HISTORY_MSG_299;(Rauschreduzierung)\nChrominanzkurve HISTORY_MSG_300;- -HISTORY_MSG_301;Rauschreduzierung\nLuminanzkontrolle -HISTORY_MSG_302;Rauschreduzierung\nChrominanz - Methode -HISTORY_MSG_303;Rauschreduzierung\nChrominanz - Methode -HISTORY_MSG_304;Wavelet\nKontrastebenen -HISTORY_MSG_305;Wavelet -HISTORY_MSG_306;Wavelet - Einstellungen\nVerarbeitungsebene -HISTORY_MSG_307;Wavelet - Einstellungen\nVerarbeitung -HISTORY_MSG_308;Wavelet - Einstellungen\nVerarbeitungsrichtung -HISTORY_MSG_309;Wavelet\nKantenschärfung\nDetails -HISTORY_MSG_310;Wavelet - Restbild\nHimmelsfarbtöne\nschützen -HISTORY_MSG_311;Wavelet - Einstellungen\nAnzahl der Ebenen -HISTORY_MSG_312;Wavelet - Restbild\nSchatten Schwellenwert -HISTORY_MSG_313;Wavelet - Farbe\nEbenengrenze -HISTORY_MSG_314;Wavelet - Gamut\nArtefakte reduzieren -HISTORY_MSG_315;Wavelet - Restbild\nKontrast -HISTORY_MSG_316;Wavelet - Gamut\nHautfarbtöne schützen -HISTORY_MSG_317;Wavelet - Gamut\nHautfarbton -HISTORY_MSG_318;Wavelet - Kontrast\nLichterebenen -HISTORY_MSG_319;Wavelet - Kontrast\nLichter-Luminanzbereich -HISTORY_MSG_320;Wavelet - Kontrast\nSchatten-Luminanzbereich -HISTORY_MSG_321;Wavelet - Kontrast\nSchattenebenen -HISTORY_MSG_322;Wavelet - Gamut\nFarbverschiebungen\nvermeiden -HISTORY_MSG_323;Wavelet\nKantenschärfung\nLokale Kontrastkurve -HISTORY_MSG_324;Wavelet - Farbe\nPastellfarben -HISTORY_MSG_325;Wavelet - Farbe\nGesättigte Farben -HISTORY_MSG_326;Wavelet - Farbe\nChrominanzethode -HISTORY_MSG_327;Wavelet - Kontrast\nAnwenden auf -HISTORY_MSG_328;Wavelet - Farbe\nFarb-Kontrast-\nVerknüpfung -HISTORY_MSG_329;Wavelet - Tönung\nDeckkraft Rot/Grün -HISTORY_MSG_330;Wavelet - Tönung\nDeckkraft Blau/Gelb -HISTORY_MSG_331;Wavelet\nKontrastebenen\nExtra -HISTORY_MSG_332;Wavelet- -Einstellungen\nKachelgröße -HISTORY_MSG_333;Wavelet - Restbild\nSchatten -HISTORY_MSG_334;Wavelet - Restbild\nBuntheit -HISTORY_MSG_335;Wavelet - Restbild\nLichter -HISTORY_MSG_336;Wavelet - Restbild\nLichter Schwellenwert -HISTORY_MSG_337;Wavelet - Restbild\nHimmelsfarbton -HISTORY_MSG_338;Wavelet\nKantenschärfung\nRadius -HISTORY_MSG_339;Wavelet\nKantenschärfung\nIntensität -HISTORY_MSG_340;Wavelet - Einstellungen\nIntensität -HISTORY_MSG_341;Wavelet - Einstellungen\nKantenperformance -HISTORY_MSG_342;Wavelet\nKantenschärfung\nErste Ebene -HISTORY_MSG_343;Wavelet - Farbe\nFarbebenen -HISTORY_MSG_344;Wavelet\nFarbmethode\nRegler/Kurve -HISTORY_MSG_345;Wavelet\nKantenschärfung\nLokaler Kontrast -HISTORY_MSG_346;Wavelet\nKantenschärfung\nLokale Kontrastmethode -HISTORY_MSG_347;Wavelet\nRauschreduzierung\nEbene 1 -HISTORY_MSG_348;Wavelet\nRauschreduzierung\nEbene 2 -HISTORY_MSG_349;Wavelet\nRauschreduzierung\nEbene 3 -HISTORY_MSG_350;Wavelet\nKantenschärfung\nKantenerkennung -HISTORY_MSG_351;Wavelet - Restbild\nHH-Kurve -HISTORY_MSG_352;Wavelet - Einstellungen\nHintergrund -HISTORY_MSG_353;Wavelet\nKantenschärfung\nGradientenempfindlichkeit -HISTORY_MSG_354;Wavelet\nKantenschärfung\nErweiterter Algorithmus -HISTORY_MSG_355;Wavelet\nKantenschärfung\nSchwellenwert niedrig -HISTORY_MSG_356;Wavelet\nKantenschärfung\nSchwellenwert hoch -HISTORY_MSG_357;Wavelet\nRauschreduzierung\nSchärfung verknüpfen -HISTORY_MSG_358;Wavelet - Gamut\nKontrastkurve -HISTORY_MSG_359;Vorverarbeitung\nHot/Dead-Pixel-Filter\nSchwellenwert -HISTORY_MSG_360;Dynamikkompression\nGamma -HISTORY_MSG_361;Wavelet - Endretusche\nFarbausgleich -HISTORY_MSG_362;Wavelet - Restbild\nKompression -HISTORY_MSG_363;Wavelet - Restbild\nKompression - Intensität -HISTORY_MSG_364;Wavelet - Endretusche\nKontrastausgleich -HISTORY_MSG_365;Wavelet - Endretusche\nDelta-Kontrastausgleich -HISTORY_MSG_366;Wavelet - Restbild\nGammakompression -HISTORY_MSG_367;Wavelet - Endretusche\n"Danach"-Kontrastkurve -HISTORY_MSG_368;Wavelet - Endretusche\nKontrastausgleichskurve -HISTORY_MSG_369;Wavelet - Endretusche\nKontrastmethode -HISTORY_MSG_370;Wavelet - Endretusche\nLokale Kontrastkurve -HISTORY_MSG_371;Skalieren - Schärfen -HISTORY_MSG_372;Skalieren - Schärfen\nUSM - Radius -HISTORY_MSG_373;Skalieren - Schärfen\nUSM - Intensität -HISTORY_MSG_374;Skalieren - Schärfen\nUSM - Schwellenwert -HISTORY_MSG_375;Skalieren - Schärfen\nUSM - Nur Kanten\nschärfen -HISTORY_MSG_376;Skalieren - Schärfen\nUSM - Kantenschärfung\nRadius -HISTORY_MSG_377;Skalieren - Schärfen\nUSM - Kantentoleranz -HISTORY_MSG_378;Skalieren - Schärfen\nUSM - Halokontrolle -HISTORY_MSG_379;Skalieren - Schärfen\nUSM - Halokontrolle\nIntensität -HISTORY_MSG_380;Skalieren - Schärfen\nMethode -HISTORY_MSG_381;Skalieren - Schärfen\nRLD - Radius -HISTORY_MSG_382;Skalieren - Schärfen\nRLD - Intensität -HISTORY_MSG_383;Skalieren - Schärfen\nRLD - Dämpfung -HISTORY_MSG_384;Skalieren - Schärfen\nRLD - Iterationen -HISTORY_MSG_385;Wavelet - Restbild\nFarbausgleich -HISTORY_MSG_386;Wavelet - Restbild\nFarbausgleich\nLichter Grün/Cyan -HISTORY_MSG_387;Wavelet - Restbild\nFarbausgleich\nLichter Blau/Gelb -HISTORY_MSG_388;Wavelet - Restbild\nFarbausgleich\nMitten Grün/Cyan -HISTORY_MSG_389;Wavelet - Restbild\nFarbausgleich\nMitten Blau/Gelb -HISTORY_MSG_390;Wavelet - Restbild\nFarbausgleich\nSchatten Grün/Cyan -HISTORY_MSG_391;Wavelet - Restbild\nFarbausgleich\nSchatten Blau/Gelb -HISTORY_MSG_392;Wavelet - Restbild\nFarbausgleich -HISTORY_MSG_393;Farbmanagement\nEingangsfarbprofil\nDCP - Look-Tabelle -HISTORY_MSG_394;Farbmanagement\nEingangsfarbprofil\nDCP - Ausgangsbelichtung -HISTORY_MSG_395;Farbmanagement\nEingangsfarbprofil\nDCP - Basistabelle -HISTORY_MSG_396;Wavelet - Kontrast -HISTORY_MSG_397;Wavelet - Farbe -HISTORY_MSG_398;Wavelet\nKantenschärfung -HISTORY_MSG_399;Wavelet - Restbild -HISTORY_MSG_400;Wavelet - Endretusche -HISTORY_MSG_401;Wavelet - Tönung -HISTORY_MSG_402;Wavelet\nRauschreduzierung -HISTORY_MSG_403;Wavelet\nKantenschärfung\nKantenempfindlichkeit -HISTORY_MSG_404;Wavelet\nKantenschärfung\nGrundverstärkung -HISTORY_MSG_405;Wavelet\nRauschreduzierung\nEbene 4 -HISTORY_MSG_406;Wavelet\nKantenschärfung\nBenachbarte Pixel -HISTORY_MSG_407;Retinex - Methode -HISTORY_MSG_408;Retinex\nBenachbarte Pixel -HISTORY_MSG_409;Retinex - Einstellungen\nVerstärkung -HISTORY_MSG_410;Retinex - Einstellungen\nVersatz -HISTORY_MSG_411;Retinex - Intensität -HISTORY_MSG_412;Retinex - Skalierung -HISTORY_MSG_413;Retinex - Abweichung -HISTORY_MSG_414;Retinex - Einstellungen\nLuminanz(L) - L*a*b* -HISTORY_MSG_415;Retinex - Einstellungen\nTransmissionskurve -HISTORY_MSG_416;Retinex -HISTORY_MSG_417;Retinex - Einstellungen\nTransmission Median-\nfilter -HISTORY_MSG_418;Retinex - Einstellungen\nTransmission\nSchwellenwert -HISTORY_MSG_419;Retinex - Farbraum -HISTORY_MSG_420;Retinex - Einstellungen\nHSL-Kurve -HISTORY_MSG_421;Retinex - Einstellungen\nGammakorrektur -HISTORY_MSG_422;Retinex - Einstellungen\nGamma -HISTORY_MSG_423;Retinex - Einstellungen\nGammasteigung -HISTORY_MSG_424;Retinex - Einstellungen\nHL-Schwellenwert -HISTORY_MSG_425;Retinex - Einstellungen\nBasis-Logarithmus -HISTORY_MSG_426;Retinex - Einstellungen\nFarbton (H) +HISTORY_MSG_301;(Rauschreduzierung)\nLuminanzkontrolle +HISTORY_MSG_302;(Rauschreduzierung)\nChrominanz - Methode +HISTORY_MSG_303;(Rauschreduzierung)\nChrominanz - Methode +HISTORY_MSG_304;(Wavelet)\nKontrastebenen +HISTORY_MSG_305;(Wavelet) +HISTORY_MSG_306;(Wavelet) - Einstellungen\nVerarbeitungsebene +HISTORY_MSG_307;(Wavelet) - Einstellungen\nVerarbeitung +HISTORY_MSG_308;(Wavelet) - Einstellungen\nVerarbeitungsrichtung +HISTORY_MSG_309;(Wavelet)\nKantenschärfung\nDetails +HISTORY_MSG_310;(Wavelet) - Restbild\nHimmelsfarbtöne\nschützen +HISTORY_MSG_311;(Wavelet) - Einstellungen\nAnzahl der Ebenen +HISTORY_MSG_312;(Wavelet) - Restbild\nSchatten Schwellenwert +HISTORY_MSG_313;(Wavelet) - Farbe\nEbenengrenze +HISTORY_MSG_314;(Wavelet) - Gamut\nArtefakte reduzieren +HISTORY_MSG_315;(Wavelet) - Restbild\nKontrast +HISTORY_MSG_316;(Wavelet) - Gamut\nHautfarbtöne schützen +HISTORY_MSG_317;(Wavelet) - Gamut\nHautfarbton +HISTORY_MSG_318;(Wavelet) - Kontrast\nLichterebenen +HISTORY_MSG_319;(Wavelet) - Kontrast\nLichter-Luminanzbereich +HISTORY_MSG_320;(Wavelet) - Kontrast\nSchatten-Luminanzbereich +HISTORY_MSG_321;(Wavelet) - Kontrast\nSchattenebenen +HISTORY_MSG_322;(Wavelet) - Gamut\nFarbverschiebungen\nvermeiden +HISTORY_MSG_323;(Wavelet)\nKantenschärfung\nLokale Kontrastkurve +HISTORY_MSG_324;(Wavelet) - Farbe\nPastellfarben +HISTORY_MSG_325;(Wavelet) - Farbe\nGesättigte Farben +HISTORY_MSG_326;(Wavelet) - Farbe\nChrominanzethode +HISTORY_MSG_327;(Wavelet) - Kontrast\nAnwenden auf +HISTORY_MSG_328;(Wavelet) - Farbe\nFarb-Kontrast-\nVerknüpfung +HISTORY_MSG_329;(Wavelet) - Tönung\nDeckkraft Rot/Grün +HISTORY_MSG_330;(Wavelet) - Tönung\nDeckkraft Blau/Gelb +HISTORY_MSG_331;(Wavelet)\nKontrastebenen\nExtra +HISTORY_MSG_332;(Wavelet)- -Einstellungen\nKachelgröße +HISTORY_MSG_333;(Wavelet) - Restbild\nSchatten +HISTORY_MSG_334;(Wavelet) - Restbild\nBuntheit +HISTORY_MSG_335;(Wavelet) - Restbild\nLichter +HISTORY_MSG_336;(Wavelet) - Restbild\nLichter Schwellenwert +HISTORY_MSG_337;(Wavelet) - Restbild\nHimmelsfarbton +HISTORY_MSG_338;(Wavelet)\nKantenschärfung\nRadius +HISTORY_MSG_339;(Wavelet)\nKantenschärfung\nIntensität +HISTORY_MSG_340;(Wavelet) - Einstellungen\nIntensität +HISTORY_MSG_341;(Wavelet) - Einstellungen\nKantenperformance +HISTORY_MSG_342;(Wavelet)\nKantenschärfung\nErste Ebene +HISTORY_MSG_343;(Wavelet) - Farbe\nFarbebenen +HISTORY_MSG_344;(Wavelet)\nFarbmethode\nRegler/Kurve +HISTORY_MSG_345;(Wavelet)\nKantenschärfung\nLokaler Kontrast +HISTORY_MSG_346;(Wavelet)\nKantenschärfung\nLokale Kontrastmethode +HISTORY_MSG_347;(Wavelet)\nRauschreduzierung\nEbene 1 +HISTORY_MSG_348;(Wavelet)\nRauschreduzierung\nEbene 2 +HISTORY_MSG_349;(Wavelet)\nRauschreduzierung\nEbene 3 +HISTORY_MSG_350;(Wavelet)\nKantenschärfung\nKantenerkennung +HISTORY_MSG_351;(Wavelet) - Restbild\nHH-Kurve +HISTORY_MSG_352;(Wavelet) - Einstellungen\nHintergrund +HISTORY_MSG_353;(Wavelet)\nKantenschärfung\nGradientenempfindlichkeit +HISTORY_MSG_354;(Wavelet)\nKantenschärfung\nErweiterter Algorithmus +HISTORY_MSG_355;(Wavelet)\nKantenschärfung\nSchwellenwert niedrig +HISTORY_MSG_356;(Wavelet)\nKantenschärfung\nSchwellenwert hoch +HISTORY_MSG_357;(Wavelet)\nRauschreduzierung\nSchärfung verknüpfen +HISTORY_MSG_358;(Wavelet) - Gamut\nKontrastkurve +HISTORY_MSG_359;(Vorverarbeitung)\nHot/Dead-Pixel-Filter\nSchwellenwert +HISTORY_MSG_360;(Dynamikkompression)\nGamma +HISTORY_MSG_361;(Wavelet) - Endretusche\nFarbausgleich +HISTORY_MSG_362;(Wavelet) - Restbild\nKompression +HISTORY_MSG_363;(Wavelet) - Restbild\nKompression - Intensität +HISTORY_MSG_364;(Wavelet) - Endretusche\nKontrastausgleich +HISTORY_MSG_365;(Wavelet) - Endretusche\nDelta-Kontrastausgleich +HISTORY_MSG_366;(Wavelet) - Restbild\nGammakompression +HISTORY_MSG_367;(Wavelet) - Endretusche\n"Danach"-Kontrastkurve +HISTORY_MSG_368;(Wavelet) - Endretusche\nKontrastausgleichskurve +HISTORY_MSG_369;(Wavelet) - Endretusche\nKontrastmethode +HISTORY_MSG_370;(Wavelet) - Endretusche\nLokale Kontrastkurve +HISTORY_MSG_371;(Skalieren) - Schärfen +HISTORY_MSG_372;(Skalieren) - Schärfen\nUSM - Radius +HISTORY_MSG_373;(Skalieren) - Schärfen\nUSM - Intensität +HISTORY_MSG_374;(Skalieren) - Schärfen\nUSM - Schwellenwert +HISTORY_MSG_375;(Skalieren) - Schärfen\nUSM - Nur Kanten\nschärfen +HISTORY_MSG_376;(Skalieren) - Schärfen\nUSM - Kantenschärfung\nRadius +HISTORY_MSG_377;(Skalieren) - Schärfen\nUSM - Kantentoleranz +HISTORY_MSG_378;(Skalieren) - Schärfen\nUSM - Halokontrolle +HISTORY_MSG_379;(Skalieren) - Schärfen\nUSM - Halokontrolle\nIntensität +HISTORY_MSG_380;(Skalieren) - Schärfen\nMethode +HISTORY_MSG_381;(Skalieren) - Schärfen\nRLD - Radius +HISTORY_MSG_382;(Skalieren) - Schärfen\nRLD - Intensität +HISTORY_MSG_383;(Skalieren) - Schärfen\nRLD - Dämpfung +HISTORY_MSG_384;(Skalieren) - Schärfen\nRLD - Iterationen +HISTORY_MSG_385;(Wavelet) - Restbild\nFarbausgleich +HISTORY_MSG_386;(Wavelet) - Restbild\nFarbausgleich\nLichter Grün/Cyan +HISTORY_MSG_387;(Wavelet) - Restbild\nFarbausgleich\nLichter Blau/Gelb +HISTORY_MSG_388;(Wavelet) - Restbild\nFarbausgleich\nMitten Grün/Cyan +HISTORY_MSG_389;(Wavelet) - Restbild\nFarbausgleich\nMitten Blau/Gelb +HISTORY_MSG_390;(Wavelet) - Restbild\nFarbausgleich\nSchatten Grün/Cyan +HISTORY_MSG_391;(Wavelet) - Restbild\nFarbausgleich\nSchatten Blau/Gelb +HISTORY_MSG_392;(Wavelet) - Restbild\nFarbausgleich +HISTORY_MSG_393;(Farbmanagement)\nEingangsfarbprofil\nDCP - Look-Tabelle +HISTORY_MSG_394;(Farbmanagement)\nEingangsfarbprofil\nDCP - Basisbelichtung +HISTORY_MSG_395;(Farbmanagement)\nEingangsfarbprofil\nDCP - Basistabelle +HISTORY_MSG_396;(Wavelet) - Kontrast +HISTORY_MSG_397;(Wavelet) - Farbe +HISTORY_MSG_398;(Wavelet)\nKantenschärfung +HISTORY_MSG_399;(Wavelet) - Restbild +HISTORY_MSG_400;(Wavelet) - Endretusche +HISTORY_MSG_401;(Wavelet) - Tönung +HISTORY_MSG_402;(Wavelet)\nRauschreduzierung +HISTORY_MSG_403;(Wavelet)\nKantenschärfung\nKantenempfindlichkeit +HISTORY_MSG_404;(Wavelet)\nKantenschärfung\nGrundverstärkung +HISTORY_MSG_405;(Wavelet)\nRauschreduzierung\nEbene 4 +HISTORY_MSG_406;(Wavelet)\nKantenschärfung\nBenachbarte Pixel +HISTORY_MSG_407;(Retinex) - Methode +HISTORY_MSG_408;(Retinex) - Radius +HISTORY_MSG_409;(Retinex) - Einstellungen\nKontrast +HISTORY_MSG_410;(Retinex) - Einstellungen\nHelligkeit +HISTORY_MSG_411;(Retinex) - Intensität +HISTORY_MSG_412;(Retinex)\nGaußscher Gradient +HISTORY_MSG_413;(Retinex) - Kontrast +HISTORY_MSG_414;(Retinex) - Einstellungen\nLuminanz(L) - L*a*b* +HISTORY_MSG_415;(Retinex) - Einstellungen\nTransmissionskurve +HISTORY_MSG_416;(Retinex) +HISTORY_MSG_417;(Retinex) - Einstellungen\nTransmission Median-\nfilter +HISTORY_MSG_418;(Retinex) - Einstellungen\nTransmission\nSchwellenwert +HISTORY_MSG_419;(Retinex) - Farbraum +HISTORY_MSG_420;(Retinex) - Einstellungen\nHSL-Kurve +HISTORY_MSG_421;(Retinex) - Einstellungen\nGammakorrektur +HISTORY_MSG_422;(Retinex) - Einstellungen\nGamma +HISTORY_MSG_423;(Retinex) - Einstellungen\nGammasteigung +HISTORY_MSG_424;(Retinex) - Einstellungen\nHL-Schwellenwert +HISTORY_MSG_425;(Retinex) - Einstellungen\nBasis-Logarithmus +HISTORY_MSG_426;(Retinex) - Einstellungen\nFarbton (H) +HISTORY_MSG_427;Ausgabe-Rendering-Intent +HISTORY_MSG_428;Monitor-Rendering-Intent +HISTORY_MSG_429;(Retinex) - Einstellungen\nIterationen +HISTORY_MSG_430;(Retinex) - Einstellungen\nTransmission Gradient +HISTORY_MSG_431;(Retinex) - Einstellungen\nIntensität Gradient +HISTORY_MSG_432;(Retinex) - Maske\nLichter +HISTORY_MSG_433;(Retinex) - Maske\nTonwertbreite Lichter +HISTORY_MSG_434;(Retinex) - Maske\nSchatten +HISTORY_MSG_435;(Retinex) - Maske\nTonwertbreite Schatten +HISTORY_MSG_436;(Retinex) - Maske\nRadius +HISTORY_MSG_437;(Retinex) - Maske\nMethode +HISTORY_MSG_438;(Retinex) - Maske\nKurve +HISTORY_MSG_439;(Retinex) - Vorschau +HISTORY_MSG_440;(Detailebenenkontrast)\nProzessreihenfolge HISTORY_NEWSNAPSHOT;Hinzufügen HISTORY_NEWSNAPSHOT_TOOLTIP;Taste: Alt + s HISTORY_SNAPSHOT;Schnappschuss @@ -798,6 +815,7 @@ MAIN_TOOLTIP_SHOWHIDERP1;Rechtes Bedienfeld ein-/ausblenden\nTaste: Alt + MAIN_TOOLTIP_SHOWHIDETP1;Oberes Bedienfeld ein-/ausblenden\nTaste: Umschalt + l MAIN_TOOLTIP_THRESHOLD;Schwellenwert MAIN_TOOLTIP_TOGGLE;Vorher/Nachher-Ansicht ein-/ausschalten\nTaste: Umschalt + b +MONITOR_PROFILE_SYSTEM;Systemvorgabe NAVIGATOR_B;B: NAVIGATOR_G;G: NAVIGATOR_H;H: @@ -812,28 +830,28 @@ NAVIGATOR_XY_FULL;Breite = %1, Höhe = %2 NAVIGATOR_XY_NA;x: --, y: -- OPTIONS_DEFIMG_MISSING;Die Standard-Profile für Nicht-RAW-Bilder wurden nicht gefunden oder nicht festgelegt.\n\nBitte prüfen Sie das Profil-Verzeichnis, es fehlt möglicherweise oder ist beschädigt.\n\nEs werden stattdessen interne Standardwerte verwendet. OPTIONS_DEFRAW_MISSING;Die Standard-Profile für RAW-Bilder wurden nicht gefunden oder nicht festgelegt.\n\nBitte prüfen Sie das Profil-Verzeichnis, es fehlt möglicherweise oder ist beschädigt.\n\nEs werden stattdessen interne Standardwerte verwendet. -PARTIALPASTE_BASICGROUP;Gruppe Basiseinstellungen +PARTIALPASTE_BASICGROUP;Grundeinstellungen PARTIALPASTE_CACORRECTION;Farbsaum entfernen PARTIALPASTE_CHANNELMIXER;RGB-Kanalmixer PARTIALPASTE_CHANNELMIXERBW;Schwarz/Weiß PARTIALPASTE_COARSETRANS;Drehen / Spiegeln PARTIALPASTE_COLORAPP;CIE Color Appearance Model 2002 -PARTIALPASTE_COLORGROUP;Gruppe Farbeinstellungen +PARTIALPASTE_COLORGROUP;Farbeinstellungen PARTIALPASTE_COLORTONING;Farbanpassungen PARTIALPASTE_COMMONTRANSFORMPARAMS;Auto-Füllen -PARTIALPASTE_COMPOSITIONGROUP;Gruppe Gestaltungseinstellungen +PARTIALPASTE_COMPOSITIONGROUP;Gestaltungseinstellungen PARTIALPASTE_CROP;Ausschnitt PARTIALPASTE_DARKFRAMEAUTOSELECT;Dunkelbild: Automatische Auswahl PARTIALPASTE_DARKFRAMEFILE;Dunkelbild: Datei PARTIALPASTE_DEFRINGE;Farbsaum entfernen (Defringe) -PARTIALPASTE_DETAILGROUP;Gruppe Detaileinstellungen +PARTIALPASTE_DETAILGROUP;Detaileinstellungen PARTIALPASTE_DIALOGLABEL;Selektives Einfügen des Bearbeitungsprofils PARTIALPASTE_DIRPYRDENOISE;Rauschreduzierung PARTIALPASTE_DIRPYREQUALIZER;Detailebenenkontrast PARTIALPASTE_DISTORTION;Verzeichnungskorrektur PARTIALPASTE_EPD;Dynamikkompression PARTIALPASTE_EQUALIZER;Anzahl der Ebenen -PARTIALPASTE_EVERYTHING;Alles +PARTIALPASTE_EVERYTHING;Alle Einstellungen aktivieren / deaktivieren PARTIALPASTE_EXIFCHANGES;Änderungen an Exif-Daten PARTIALPASTE_EXPOSURE;Belichtung PARTIALPASTE_FILMSIMULATION;Filmsimulation @@ -848,22 +866,23 @@ PARTIALPASTE_ICMSETTINGS;ICM-Einstellungen PARTIALPASTE_IMPULSEDENOISE;Impulsrauschreduzierung PARTIALPASTE_IPTCINFO;IPTC-Informationen PARTIALPASTE_LABCURVE;L*a*b* - Einstellungen -PARTIALPASTE_LENSGROUP;Gruppe Objektivkorrekturen +PARTIALPASTE_LENSGROUP;Objektivkorrekturen PARTIALPASTE_LENSPROFILE;Objektivkorrekturprofil -PARTIALPASTE_METAGROUP;Gruppe Metadaten +PARTIALPASTE_METAGROUP;Metadaten PARTIALPASTE_PCVIGNETTE;Vignettierungsfilter PARTIALPASTE_PERSPECTIVE;Perspektive PARTIALPASTE_PREPROCESS_DEADPIXFILT;Vorverarbeitung: Dead-Pixel-Filter PARTIALPASTE_PREPROCESS_GREENEQUIL;Vorverarbeitung: Grün-Ausgleich PARTIALPASTE_PREPROCESS_HOTPIXFILT;Vorverarbeitung: Hot-Pixel-Filter PARTIALPASTE_PREPROCESS_LINEDENOISE;Vorverarbeitung: Zeilenrauschfilter +PARTIALPASTE_PRSHARPENING;Schärfung nach Größenänderung PARTIALPASTE_RAWCACORR_AUTO;Chromatische Aberration: Automatische Korrektur PARTIALPASTE_RAWCACORR_CABLUE;Chromatische Aberration: Blau PARTIALPASTE_RAWCACORR_CARED;Chromatische Aberration: Rot PARTIALPASTE_RAWEXPOS_BLACK;Weißpunkt: Schwarzpegel PARTIALPASTE_RAWEXPOS_LINEAR;Weißpunkt: Korrekturfaktor PARTIALPASTE_RAWEXPOS_PRESER;Weißpunkt: Lichter schützen (EV) -PARTIALPASTE_RAWGROUP;Gruppe RAW +PARTIALPASTE_RAWGROUP;RAW PARTIALPASTE_RAW_DCBENHANCE;Farbinterpolation: DCB-Verbesserung PARTIALPASTE_RAW_DCBITERATIONS;Farbinterpolation: Anzahl der DCB-Iterationen PARTIALPASTE_RAW_DMETHOD;Farbinterpolation: Methode @@ -900,8 +919,8 @@ PREFERENCES_BLACKBODY;Wolfram PREFERENCES_CACHECLEARALL;Alles löschen PREFERENCES_CACHECLEARPROFILES;Profile löschen PREFERENCES_CACHECLEARTHUMBS;Miniaturbilder löschen -PREFERENCES_CACHEMAXENTRIES;Maximale Anzahl der Einträge im Zwischenspeicher -PREFERENCES_CACHEOPTS;Einstellungen des Zwischenspeichers auf der Festplatte für Miniaturbilder +PREFERENCES_CACHEMAXENTRIES;Maximale Anzahl der Miniaturbilder im Festplatten-Cache +PREFERENCES_CACHEOPTS;Einstellungen des Festplatten-Cache für Miniaturbilder PREFERENCES_CACHETHUMBHEIGHT;Maximale Höhe der Miniaturbilder PREFERENCES_CIEART;CIECAM02-Optimierung PREFERENCES_CIEART_FRAME;CIECAM02-spezifische Einstellungen @@ -948,7 +967,7 @@ PREFERENCES_EDITORLAYOUT;Editor-Layout PREFERENCES_EXPAUT;Experte PREFERENCES_EXTERNALEDITOR;Externer Editor PREFERENCES_FBROWSEROPTS;Bildinformationen und Miniaturbilder -PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Einzeilige Werkzeugleiste (Bei geringer Bildschirmauflösung deaktivieren) +PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Einzeilige Toolbar\n(Bei geringer Bildschirmauflösung deaktivieren) PREFERENCES_FILEFORMAT;Dateiformat PREFERENCES_FILMSIMULATION;Filmsimulation PREFERENCES_FLATFIELD;Weißbild @@ -1005,22 +1024,24 @@ PREFERENCES_MENUGROUPRANK;Untermenü Bewertung PREFERENCES_MENUOPTIONS;Menüoptionen PREFERENCES_METADATA;Metadaten PREFERENCES_MIN;Mini (100x115) +PREFERENCES_MONINTENT;Standard-Rendering-Intent +PREFERENCES_MONPROFILE;Standard-Monitor-Profil PREFERENCES_MULTITAB;Multi-Reitermodus PREFERENCES_MULTITABDUALMON;Multi-Reitermodus (auf zweitem Monitor, wenn verfügbar) PREFERENCES_NAVGUIDEBRUSH;Farbe der Navigationshilfe PREFERENCES_NAVIGATIONFRAME;Navigation PREFERENCES_NOISE;Rauschreduzierung PREFERENCES_OUTDIR;Ausgabeverzeichnis -PREFERENCES_OUTDIRFOLDER;Im Verzeichnis speichern +PREFERENCES_OUTDIRFOLDER;In dieses Verzeichnis speichern PREFERENCES_OUTDIRFOLDERHINT;Alle Dateien ausgewähltem Verzeichnis speichern. -PREFERENCES_OUTDIRTEMPLATE;Vorlage verwenden +PREFERENCES_OUTDIRTEMPLATE;Dynamisches Verzeichnis verwenden PREFERENCES_OUTDIRTEMPLATEHINT;Die folgenden Variablen können verwendet werden:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r, %s1, %s2, ...\n\nDiese Variablen beinhalten bestimmte Teile des Verzeichnispfades, in welchem sich das Bild befindet, oder Attribute des Bildes.\n\nWenn zum Beispiel /home/tom/photos/2010-10-31/dsc0042.nef geöffnet wurde, dann haben die Variablen den folgenden Inhalt:\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tom/photos/2010-10-31\n%p2 = /home/tom/photos\n%p3 = /home/tom\n%p4 = /home\n\nWenn Sie die Ausgabedatei in dasselbe Verzeichnis wie das Originalbild speichern wollen, dann wählen Sie:\n%p1/%f\n\nWenn Sie die Ausgabedatei in ein Unterverzeichnis mit dem Namen "converted" schreiben wollen, dann wählen Sie:\n%p1/converted/%f\n\nWenn Sie die Ausgabedatei im Verzeichnispfad "/home/tom/photos/converted" speichern wollen, dort jedoch in einem mit dem Namen des Ursprungsverzeichnisses betitelten Unterverzeichnis, dann wählen Sie:\n%p2/converted/%d1/%f\n\nDie Variable %r enthält die Bewertung des Bildes. PREFERENCES_OVERLAY_FILENAMES;Bildinformationen überlagern die Miniaturbilder in der Dateiverwaltung PREFERENCES_OVERLAY_FILENAMES_FILMSTRIP;Bildinformationen der Miniaturbilder im Filmstreifen anzeigen PREFERENCES_OVERWRITEOUTPUTFILE;Bestehende Ausgabedateien überschreiben PREFERENCES_PANFACTORLABEL;Mausgeschwindigkeit beim Bewegen von Bildern PREFERENCES_PARSEDEXT;Dateitypen anzeigen -PREFERENCES_PARSEDEXTADD;Dateityp\nhinzufügen +PREFERENCES_PARSEDEXTADD;Dateityp PREFERENCES_PARSEDEXTADDHINT;Dateityp zur Liste hinzufügen PREFERENCES_PARSEDEXTDELHINT;Ausgewählten Dateityp aus Liste entfernen PREFERENCES_PARSEDEXTDOWNHINT;Ausgewählten Dateityp nach unten verschieben. @@ -1035,6 +1056,7 @@ PREFERENCES_PROFILEPRCACHE;Bearbeitungsprofil im Zwischenspeicher PREFERENCES_PROFILEPRFILE;Bearbeitungsprofil, welches geladener Datei beiliegt (Sidecar) PREFERENCES_PROFILESAVECACHE;Verarbeitungsparameter im Zwischenspeicher speichern PREFERENCES_PROFILESAVEINPUT;Verarbeitungsparameter zusammen mit Datei speichern (Sidecar) +PREFERENCES_PROFILE_NONE;Kein Farbprofil PREFERENCES_PROPERTY;Eigenschaft PREFERENCES_PSPATH;Adobe Photoshop Installationsverzeichnis PREFERENCES_REMEMBERZOOMPAN;Zoom und Bildposition merken @@ -1043,7 +1065,7 @@ PREFERENCES_RGBDTL_LABEL;Maximale Anzahl Threads für Rauschreduzierung PREFERENCES_RGBDTL_TOOLTIP;Die Rauschreduzierung benötigt mindestens 128MB RAM für ein 10 Megapixel-Bild oder 512MB für ein 40 Megapixel-Bild, und zusätzlich 128MB RAM pro Thread. Je mehr Threads parallel ablaufen, desto schneller ist die Berechnung. Bei Einstellung "0" werden so viele Threads wie möglich benutzt. PREFERENCES_SELECTFONT;Schriftart PREFERENCES_SELECTLANG;Sprache -PREFERENCES_SELECTTHEME;Oberflächendesign +PREFERENCES_SELECTTHEME;Oberflächendesign (erfordert Neustart) PREFERENCES_SERIALIZE_TIFF_READ;TIFF-Bilder PREFERENCES_SERIALIZE_TIFF_READ_LABEL;Serialisiertes Lesen von TIFF-Bildern verwenden PREFERENCES_SERIALIZE_TIFF_READ_TOOLTIP;Beim Arbeiten mit Ordnern voll unkomprimierter TIFF-Bilder, kann diese Einstellung das Generieren von Miniaturbildern deutlich beschleunigen. @@ -1051,7 +1073,7 @@ PREFERENCES_SET;SETZEN PREFERENCES_SHOWBASICEXIF;Exif-Daten anzeigen PREFERENCES_SHOWDATETIME;Datum und Uhrzeit anzeigen PREFERENCES_SHOWEXPOSURECOMPENSATION;Belichtungskorrektur anfügen -PREFERENCES_SHOWFILMSTRIPTOOLBAR;Zeige Filmstreifenleiste +PREFERENCES_SHOWFILMSTRIPTOOLBAR;Toolbar oberhalb des Filmstreifens anzeigen PREFERENCES_SHTHRESHOLD;Schatten - Schwellenwert PREFERENCES_SIMPLAUT;Werkzeugmodus PREFERENCES_SINGLETAB;Ein-Reitermodus @@ -1059,9 +1081,9 @@ PREFERENCES_SINGLETABVERTAB;Ein-Reitermodus (vertikale Reiter) PREFERENCES_SLIMUI;Kompakte Oberfläche PREFERENCES_SMA;Klein (250x287) PREFERENCES_SND_BATCHQUEUEDONE;Warteschlange abgearbeitet -PREFERENCES_SND_HELP;Entweder einen Dateipfad zu einer Sounddatei oder einen Systemklang eingeben.\n\nBeispiele Systemklänge:\nWindows: SystemDefault, SystemAsterisk ...\nLinux: complete, window-attention ...\n +PREFERENCES_SND_HELP;Geben Sie einen Pfad zu einer Sounddatei oder einen Systemklang ein.\n\nBeispiel Systemklänge:\nWindows: SystemDefault, SystemAsterisk ...\nLinux: complete, window-attention ...\n PREFERENCES_SND_LNGEDITPROCDONE;Bearbeitung abgeschlossen -PREFERENCES_SND_TRESHOLDSECS;Nach Sekunden +PREFERENCES_SND_TRESHOLDSECS;Verzögerung in Sekunden PREFERENCES_STARTUPIMDIR;Bildverzeichnis beim Programmstart PREFERENCES_STDAUT;Standard PREFERENCES_TAB_BROWSER;Dateiverwaltung @@ -1075,7 +1097,7 @@ PREFERENCES_TINB;Anzahl Kacheln PREFERENCES_TISTD;Standard PREFERENCES_TP_LABEL;Werkzeugbereich: PREFERENCES_TP_USEICONORTEXT;Symbole statt Text in Karteireitern -PREFERENCES_TP_VSCROLLBAR;Keine vertikale Laufleiste +PREFERENCES_TP_VSCROLLBAR;Keine vertikale Scrollbar PREFERENCES_TUNNELMETADATA;Exif/XMP unverändert in die Ausgabedatei übernehmen. PREFERENCES_USEBUNDLEDPROFILES;Standardprofile verwenden PREFERENCES_USESYSTEMTHEME;Systemoberfläche verwenden @@ -1211,6 +1233,10 @@ TP_BWMIX_VAL;L TP_CACORRECTION_BLUE;Blau TP_CACORRECTION_LABEL;Farbsaum entfernen TP_CACORRECTION_RED;Rot +TP_CBDL_AFT;Nach Schwarz / Weiß +TP_CBDL_BEF;Vor Schwarz / Weiß +TP_CBDL_METHOD;Prozessreihenfolge +TP_CBDL_METHOD_TOOLTIP;Wählen Sie, ob der Detailebenenkontrast nach dem Schwarz/Weiß-Werkzeug abgearbeitet wird (ermöglicht das Arbeiten im L*a*b*-Farbraum), oder vor ihm (ermöglicht das Arbeiten im RGB-Farbraum). TP_CHMIXER_BLUE;Blau-Kanal TP_CHMIXER_GREEN;Grün-Kanal TP_CHMIXER_LABEL;RGB-Kanalmixer @@ -1252,7 +1278,7 @@ TP_COLORAPP_CURVEEDITOR2;Tonwertkurve 2 TP_COLORAPP_CURVEEDITOR2_TOOLTIP;Gleiche Verwendung wie bei der zweiten Belichtungstonwertkurve. TP_COLORAPP_CURVEEDITOR3;Farbkurve TP_COLORAPP_CURVEEDITOR3_TOOLTIP;Korrigiert Buntheit, Sättigung oder Farbigkeit.\n\nZeigt das Histogramm der Chromatizität (L*a*b* ) VOR den CIECAM02-Änderungen an.\nWenn "CIECAM02-Ausgabe-Histogramm in Kurven anzeigen" aktiviert ist, wird das Histogramm von C, S oder M NACH den CIECAM02-Änderungen angezeigt.\n\nC, S und M werden nicht im Haupt-Histogramm angezeigt.\nFür die endgültige Ausgabe verwenden Sie das Haupt-Histogramm. -TP_COLORAPP_DATACIE;CIECAM02-Ausgabe-Histogramm\nin Kurven anzeigen +TP_COLORAPP_DATACIE;CIECAM02-Ausgabe-Histogramm in\nKurven anzeigen TP_COLORAPP_DATACIE_TOOLTIP;Wenn aktiviert, zeigen die Histogramme der CIECAM02-Kurven die angenäherten Werte/Bereiche für J oder Q und C, S oder M NACH den CIECAM02-Anpassungen an. Das betrifft nicht das Haupt-Histogramm.\n\nWenn deaktiviert, zeigen die Histogramme der CIECAM02-Kurven die L*a*b*-Werte VOR den CIECAM02-Anpassungen an. TP_COLORAPP_DEGREE_AUTO_TOOLTIP;Wenn aktiviert (emfohlen), berechnet RT einen optimalen Wert der von CAT02 und CIECAM02 verwendet wird.\nUm den Wert manuell zu setzen, muss die Option deaktiviert sein (Werte über 64 sind empfohlen). TP_COLORAPP_DEGREE_TOOLTIP;Umfang der “CIE Chromatic Adaptation Transform 2002“ @@ -1328,7 +1354,7 @@ TP_COLORTONING_TWOALL;Spezial-Farbe TP_COLORTONING_TWOBY;Spezial a* und b* TP_COLORTONING_TWOCOLOR_TOOLTIP;Standardfarbe:\nLinearer Verlauf, a* = b*.\n\nSpezial-Farbe:\nLinearer Verlauf, a* = b*, aber nicht verbunden\n\nSpezial a* und b*:\nLinearer Verlauf, nicht verbunden, mit unterschiedlichen Kurven für a* und b*. Bevorzugt für spezielle Effekte.\n\nSpezial-Farbe (2 Farben):\nBesser vorhersehbar TP_COLORTONING_TWOSTD;Standardfarbe -TP_CROP_FIXRATIO;Festes\nVerhältnis: +TP_CROP_FIXRATIO;Format TP_CROP_GTDIAGONALS;Diagonalregel TP_CROP_GTEPASSPORT;Passfoto (biometrisch) TP_CROP_GTFRAME;Rahmen @@ -1446,7 +1472,7 @@ TP_EXPOSURE_AUTOLEVELS;Auto TP_EXPOSURE_AUTOLEVELS_TIP;Automatische Belichtungseinstellung basierend auf Bildanalyse TP_EXPOSURE_BLACKLEVEL;Schwarzwert TP_EXPOSURE_BRIGHTNESS;Helligkeit -TP_EXPOSURE_CLIP;Grenzwert +TP_EXPOSURE_CLIP;Clip %: TP_EXPOSURE_CLIP_TIP;Anteil der Pixel, die sich bei automatischer Belichtungseinstellung im Bereich der Spitzlichter und Schatten befinden sollen TP_EXPOSURE_COMPRHIGHLIGHTS;Lichterkompression TP_EXPOSURE_COMPRHIGHLIGHTSTHRESHOLD;Lichterkompression Schwellenwert @@ -1469,6 +1495,7 @@ TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Gewichteter Standard TP_EXPOS_BLACKPOINT_LABEL;Schwarzpunkt TP_EXPOS_WHITEPOINT_LABEL;Weißpunkt TP_FILMSIMULATION_LABEL;Filmsimulation +TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee sucht nach Hald-CLUT-Bildern, die für die Filmsimulation benötigt werden, in einem Ordner, der viel Zeit benötigt.\nGehen Sie zu\n< Einstellungen > Bildbearbeitung > Filmsimulation >\nund prüfen Sie welcher Order benutzt wird. Wählen Sie den Ordner aus, der nur die Hald-CLUT-Bilder beinhaltet, oder einen leeren Ordner, wenn Sie die Filsimulation nicht verwenden möchten.\n\nWeitere Informationen über die Film Simulation finden Sie auf RawPedia.\n\nMöchten Sie die Suche beenden? TP_FILMSIMULATION_STRENGTH;Intensität TP_FILMSIMULATION_ZEROCLUTSFOUND;HaldCLUT-Verzeichnis in den Einstellungen festlegen TP_FLATFIELD_AUTOSELECT;Automatische Auswahl @@ -1536,6 +1563,7 @@ TP_ICM_INPUTPROFILE;Eingangsfarbprofil TP_ICM_LABEL;Farbmanagement TP_ICM_NOICM;Kein ICM: sRGB-Ausgabe TP_ICM_OUTPUTPROFILE;Ausgabeprofil +TP_ICM_PROFILEINTENT;Rendering Intent TP_ICM_SAVEREFERENCE;Referenzbild für Profil speichern TP_ICM_SAVEREFERENCE_APPLYWB;Weißabgleich anwenden TP_ICM_SAVEREFERENCE_APPLYWB_TOOLTIP;Um ICC-Profile zu erstellen, den Weißabgleich beim Speichern anwenden. Um DCP-Profile zu erstellen, den Weißabgleich NICHT beim Speichern anwenden. @@ -1616,6 +1644,7 @@ TP_PRSHARPENING_TOOLTIP;Schärft das Bild nach der Größenänderung. Funktionie TP_RAWCACORR_AUTO;Automatische Korrektur TP_RAWCACORR_CABLUE;Blau TP_RAWCACORR_CARED;Rot +TP_RAWCACORR_CASTR;Intensität TP_RAWEXPOS_BLACKS;Schattenkompression TP_RAWEXPOS_BLACK_0;Grün 1 (Master) TP_RAWEXPOS_BLACK_1;Rot @@ -1660,12 +1689,15 @@ TP_RESIZE_WIDTH;Breite TP_RETINEX_CONTEDIT_HSL;HSL-Kurve TP_RETINEX_CONTEDIT_LAB;Luminanz (L) L*a*b* TP_RETINEX_CONTEDIT_LH;Farbton (H) +TP_RETINEX_CONTEDIT_MAP;Maskenkurve TP_RETINEX_CURVEEDITOR_CD;L=f(L) TP_RETINEX_CURVEEDITOR_CD_TOOLTIP;Luminanz in Abhängigkeit der Luminanz.\nKorrigiert direkt die RAW-Daten, um Halos und Artefakte zu verringern. TP_RETINEX_CURVEEDITOR_LH;Intensität=f(H) TP_RETINEX_CURVEEDITOR_LH_TOOLTIP;Intensität in Abhängigkeit des Farbtons (H)\nBei der Retinex-Methode "Spitzlichter" wirken sich die Änderungen auch auf die Chromakorrektur aus. +TP_RETINEX_CURVEEDITOR_MAP;L=f(L) +TP_RETINEX_CURVEEDITOR_MAP_TOOLTIP;Die Kurve kann entweder alleine, oder mit der Gaußschen- oder Waveletmaske angewendet werden.\nArtefakte beachten! TP_RETINEX_FREEGAMMA;Gamma -TP_RETINEX_GAIN;Verstärkung +TP_RETINEX_GAIN;Kontrast TP_RETINEX_GAIN_TOOLTIP;Wirkt sich auf das verarbeitete Bild aus. Wird für schwarze oder weiße Pixel verwendet und hilft das Histogramm auszugleichen. TP_RETINEX_GAMMA;Gammakorrektur TP_RETINEX_GAMMA_FREE;Benutzerdefiniert @@ -1674,24 +1706,39 @@ TP_RETINEX_GAMMA_LOW;Niedrig TP_RETINEX_GAMMA_MID;Mittel TP_RETINEX_GAMMA_NONE;Keine TP_RETINEX_GAMMA_TOOLTIP;Stellt Farbtöne vor und nach der Retinexverarbeitung durch eine Gammakorrektur wieder her. +TP_RETINEX_GRAD;Transmission Gradient +TP_RETINEX_GRADS;Intensität Gradient +TP_RETINEX_GRADS_TOOLTIP;Steht der Regler auf 0 sind alle Iterationen identisch.\nBei > 0 wird die Intensität reduziert und umgekehrt. +TP_RETINEX_GRAD_TOOLTIP;Steht der Regler auf 0 sind alle Iterationen identisch.\nBei > 0 werden Skalierung und Schwellenwert reduziert und umgekehrt. TP_RETINEX_HIGH;Lichter TP_RETINEX_HIGHLIG;Spitzlichter TP_RETINEX_HIGHLIGHT;Spitzlichter Schwellenwert TP_RETINEX_HIGHLIGHT_TOOLTIP;Benötigt unter Umständen Korrekturen der Einstellungen "Benachbarte Pixel" und "Weißpunkt" unter dem Reiter "RAW". TP_RETINEX_HSLSPACE_LIN;HSL-Linear TP_RETINEX_HSLSPACE_LOG;HSL-Logarithmisch +TP_RETINEX_ITER;Iterationen (Dynamikkompression) +TP_RETINEX_ITER_TOOLTIP;Simuliert eine Dynamikkompression.\nHöhere Werte erhöhen die Prozessorzeit. TP_RETINEX_LABEL;Retinex (Bildschleier entfernen) +TP_RETINEX_LABEL_MASK;Maske TP_RETINEX_LABSPACE;L*a*b* TP_RETINEX_LOW;Schatten +TP_RETINEX_MAP;Methode +TP_RETINEX_MAP_GAUS;Gaußschenmaske +TP_RETINEX_MAP_MAPP;Schärfemaske (Teil-Wavelet) +TP_RETINEX_MAP_MAPT;Schärfemaske (Wavelet) +TP_RETINEX_MAP_METHOD_TOOLTIP;Keine: Wendet die Maske, die mit der gaußschen Funktion (Radius, Methode) erstellt wurde an, um Halos und Artefakte zu reduzieren.\n\nNur Kurve: Wendet eine diagonale Kontrastkurve auf die Maske an.\nArtefakte beachten.\n\nGaußschenmaske: Wendet eine gaußsche Unschärfe auf die originale Maske an.\n(Schnell)\n\nSchärfemaske: Wendet ein Wavelet auf die originale Maske an.\n(Langsam) +TP_RETINEX_MAP_NONE;Keine TP_RETINEX_MEDIAN;Transmission Medianfilter TP_RETINEX_METHOD;Methode TP_RETINEX_METHOD_TOOLTIP;"Schatten" wirkt sich auf dunkle Bereiche aus.\n"Schatten & Lichter" wirkt sich auf dunkle und helle Bereiche aus.\n"Lichter" wirkt sich auf helle Bereiche aus.\n"Spitzlichter" wirkt sich auf sehr helle Bereiche aus und reduziert Magenta-Falschfarben. TP_RETINEX_MLABEL;Schleierreduzierung: Min=%1 Max=%2 TP_RETINEX_MLABEL_TOOLTIP;Sollte nahe bei Min=0 und Max=32768 sein -TP_RETINEX_NEIGHBOR;Benachbarte Pixel +TP_RETINEX_NEIGHBOR;Radius TP_RETINEX_NEUTRAL;Zurücksetzen TP_RETINEX_NEUTRAL_TIP;Setzt alle Regler und Kurven auf ihre Standardwerte zurück. -TP_RETINEX_OFFSET;Versatz +TP_RETINEX_OFFSET;Helligkeit +TP_RETINEX_SCALES;Gaußscher Gradient +TP_RETINEX_SCALES_TOOLTIP;Steht der Regler auf 0 sind alle Iterationen identisch.\nBei > 0 werden Skalierung und Radius reduziert und umgekehrt. TP_RETINEX_SETTINGS;Einstellungen TP_RETINEX_SLOPE;Gammasteigung TP_RETINEX_STRENGTH;Intensität @@ -1699,12 +1746,19 @@ TP_RETINEX_THRESHOLD;Transmission Schwellenwert TP_RETINEX_THRESHOLD_TOOLTIP;Limitiert den Bereich der Transmissionskurve. TP_RETINEX_TLABEL;T: Min=%1 Max=%2 Mittel=%3 Sigma=%4 TP_RETINEX_TLABEL2;T: Tmin=%1 Tmax=%2 -TP_RETINEX_TLABEL_TOOLTIP;Ergebis der Transmissionskurve: Min, Max, Mittel und Sigma\nMin und Max hat Einfluss auf die Abweichung.\n\nTmin = Kleinster Wert der Transmissionskurve\nTmax = Größter Wert der Transmissionskurve +TP_RETINEX_TLABEL_TOOLTIP;Ergebnis der Transmissionskurve: Min, Max, Mittel und Sigma\nMin und Max hat Einfluss auf die Abweichung.\n\nTmin = Kleinster Wert der Transmissionskurve\nTmax = Größter Wert der Transmissionskurve TP_RETINEX_TRANSMISSION;Transmissionskurve TP_RETINEX_TRANSMISSION_TOOLTIP;Transmission in Abhängigkeit der Transmission.\nx-Achse: Transmission negativer Werte (Min), Mittel und positiver Werte (Max).\ny-Achse: Verstärkung oder Reduzierung. TP_RETINEX_UNIFORM;Schatten & Lichter -TP_RETINEX_VARIANCE;Abweichung +TP_RETINEX_VARIANCE;Kontrast TP_RETINEX_VARIANCE_TOOLTIP;Niedrige Werte erhöhen den lokalen Kontrast und die Sättigung, können aber zu Artefakten führen. +TP_RETINEX_VIEW;Vorschau +TP_RETINEX_VIEW_MASK;Maske +TP_RETINEX_VIEW_METHOD_TOOLTIP;Standard: Normale Anzeige\n\nMaske: Zeigt die Maske an\n\nUnschärfemaske: Zeigt das Bild mit einem großen Unschärfemaskenradius an.\n\nTransmission-Auto/Fest: Zeigt die Transmissionskarte vor der Anwendung von Kontrast und Helligkeit an\n\nACHTUNG: Die Maske zeigt nicht das Endergebnis, sondern verstärkt den Effekt um ihn besser beurteilen zu können. +TP_RETINEX_VIEW_NONE;Standard +TP_RETINEX_VIEW_TRAN;Transmission - Auto +TP_RETINEX_VIEW_TRAN2;Transmission - Fest +TP_RETINEX_VIEW_UNSHARP;Unschärfemaske TP_RGBCURVES_BLUE;B TP_RGBCURVES_CHANNEL;Kanal TP_RGBCURVES_GREEN;G @@ -1760,7 +1814,7 @@ TP_VIBRANCE_LABEL;Dynamik TP_VIBRANCE_PASTELS;Pastelltöne TP_VIBRANCE_PASTSATTOG;Pastell und gesättigte Töne koppeln TP_VIBRANCE_PROTECTSKINS;Hautfarbtöne schützen -TP_VIBRANCE_PSTHRESHOLD;Pastell/gesättigte Töne\nSchwellenwert +TP_VIBRANCE_PSTHRESHOLD;Schwellenwert - Pastell/gesättigte Töne TP_VIBRANCE_PSTHRESHOLD_SATTHRESH;Sättigung Schwellenwert TP_VIBRANCE_PSTHRESHOLD_TOOLTIP;Die vertikale Achse steht für die Pastell (unten) und gesättigte Töne (oben).\nDie horizontale Achse entspricht dem Sättigungsbereich. TP_VIBRANCE_PSTHRESHOLD_WEIGTHING;Gewichtung des Übergangs pastell/gesättigt @@ -1883,7 +1937,7 @@ TP_WAVELET_LEVONE;Ebene 2 TP_WAVELET_LEVTHRE;Ebene 4 TP_WAVELET_LEVTWO;Ebene 3 TP_WAVELET_LEVZERO;Ebene 1 -TP_WAVELET_LINKEDG;Mit der Kantenschärfungsintensität verknüpfen +TP_WAVELET_LINKEDG;Mit der Kantenschärfung verbinden TP_WAVELET_LIPST;Erweiterter Algorithmus TP_WAVELET_LOWLIGHT;Schatten-Luminanzbereich TP_WAVELET_MEDGREINF;Erste Ebene @@ -1989,54 +2043,3 @@ 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. -!!!!!!!!!!!!!!!!!!!!!!!!! - -!HISTORY_MSG_427;Output rendering intent -!HISTORY_MSG_428;Monitor rendering intent -!HISTORY_MSG_429;Retinex - Iterations -!HISTORY_MSG_430;Retinex - Transmission Gradient -!HISTORY_MSG_431;Retinex - Strength Gradient -!HISTORY_MSG_432;Retinex - M - Highlights -!HISTORY_MSG_433;Retinex - M - Highlights TW -!HISTORY_MSG_434;Retinex - M - Shadows -!HISTORY_MSG_435;Retinex - M - Shadows TW -!HISTORY_MSG_436;Retinex - M - Radius -!HISTORY_MSG_437;Retinex - M - Method -!HISTORY_MSG_438;Retinex - M - Equalizer -!HISTORY_MSG_439;Retinex - Preview -!MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof -!PARTIALPASTE_PRSHARPENING;Post-resize sharpening -!PREFERENCES_MONINTENT;Default monitor intent -!PREFERENCES_MONPROFILE;Default monitor profile -!PREFERENCES_PROFILE_NONE;None -!TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? -!TP_ICM_PROFILEINTENT;Rendering Intent -!TP_RETINEX_CONTEDIT_MAP;Mask equalizer -!TP_RETINEX_CURVEEDITOR_MAP;L=f(L) -!TP_RETINEX_CURVEEDITOR_MAP_TOOLTIP;This curve can be applied alone or with a Gaussian mask or wavelet mask.\nBeware of artifacts! -!TP_RETINEX_GRAD;Transmission gradient -!TP_RETINEX_GRADS;Strength gradient -!TP_RETINEX_GRADS_TOOLTIP;If slider at 0, all iterations are identical.\nIf > 0 Strength is reduced when iterations increase, and conversely. -!TP_RETINEX_GRAD_TOOLTIP;If slider at 0, all iterations are identical.\nIf > 0 Variance and Threshold are reduced when iterations increase, and conversely. -!TP_RETINEX_ITER;Iterations (Tone-mapping) -!TP_RETINEX_ITER_TOOLTIP;Simulate a tone-mapping operator.\nHigh values increase the processing time. -!TP_RETINEX_LABEL_MASK;Mask -!TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only -!TP_RETINEX_MAP_GAUS;Gaussian mask -!TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) -!TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) -!TP_RETINEX_MAP_METHOD_TOOLTIP;Use the mask generated by the Gaussian function above (Radius, Method) to reduce halos and artifacts.\n\nCurve only: apply a diagonal contrast curve on the mask.\nBeware of artifacts!\n\nGaussian mask: generate and use a Gaussian blur of the original mask.\nQuick.\n\nSharp mask: generate and use a wavelet on the original mask.\nSlow. -!TP_RETINEX_MAP_NONE;None -!TP_RETINEX_SCALES;Gaussian gradient -!TP_RETINEX_SCALES_TOOLTIP;If slider at 0, all iterations are identical.\nIf > 0 Scale and radius are reduced when iterations increase, and conversely. -!TP_RETINEX_VIEW;Process -!TP_RETINEX_VIEW_MASK;Mask -!TP_RETINEX_VIEW_METHOD_TOOLTIP;Standard - Normal display.\nMask - Displays the mask.\nUnsharp mask - Displays the image with a high radius unsharp mask.\nTransmission - Auto/Fixed - Displays the file transmission-map, before any action on contrast and brightness.\n\nAttention: the mask does not correspond to reality, but is amplified to make it more visible. -!TP_RETINEX_VIEW_NONE;Standard -!TP_RETINEX_VIEW_TRAN;Transmission - Auto -!TP_RETINEX_VIEW_TRAN2;Transmission - Fixed -!TP_RETINEX_VIEW_UNSHARP;Unsharp mask diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index a4a175e2e..d0979941b 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -256,7 +256,6 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !FILEBROWSER_RANK4_TOOLTIP;Rank 4 *\nShortcut: Shift-4 !FILEBROWSER_RANK5_TOOLTIP;Rank 5 *\nShortcut: Shift-5 !FILEBROWSER_RENAMEDLGLABEL;Rename file -!FILEBROWSER_RENAMEDLGMSG;Rename file "%1" to: !FILEBROWSER_SELECTDARKFRAME;Select dark-frame... !FILEBROWSER_SELECTFLATFIELD;Select flat-field... !FILEBROWSER_SHOWCOLORLABEL1HINT;Show images labeled Red.\nShortcut: Alt-1 @@ -748,6 +747,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT;Add !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !HISTORY_SNAPSHOT;Snapshot @@ -862,7 +862,6 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !MAIN_TOOLTIP_THRESHOLD;Threshold !MAIN_TOOLTIP_TOGGLE;Toggle the Before/After view.\nShortcut: Shift-b !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1259,6 +1258,10 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !TP_CACORRECTION_BLUE;Blue !TP_CACORRECTION_LABEL;Chromatic Aberration Correction !TP_CACORRECTION_RED;Red +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHMIXER_BLUE;Blue channel !TP_CHMIXER_GREEN;Green channel !TP_CHMIXER_LABEL;Channel Mixer @@ -1625,6 +1628,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !TP_RAWCACORR_AUTO;Auto-correction !TP_RAWCACORR_CABLUE;Blue !TP_RAWCACORR_CARED;Red +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1702,7 +1706,6 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index c98fc36c1..677771240 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -159,7 +159,6 @@ !FILEBROWSER_RANK4_TOOLTIP;Rank 4 *\nShortcut: Shift-4 !FILEBROWSER_RANK5_TOOLTIP;Rank 5 *\nShortcut: Shift-5 !FILEBROWSER_RENAMEDLGLABEL;Rename file -!FILEBROWSER_RENAMEDLGMSG;Rename file "%1" to: !FILEBROWSER_SELECTDARKFRAME;Select dark-frame... !FILEBROWSER_SELECTFLATFIELD;Select flat-field... !FILEBROWSER_SHOWCOLORLABEL1HINT;Show images labeled Red.\nShortcut: Alt-1 @@ -671,6 +670,7 @@ !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT;Add !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !HISTORY_SNAPSHOT;Snapshot @@ -789,7 +789,6 @@ !MAIN_TOOLTIP_THRESHOLD;Threshold !MAIN_TOOLTIP_TOGGLE;Toggle the Before/After view.\nShortcut: Shift-b !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1207,6 +1206,10 @@ !TP_CACORRECTION_BLUE;Blue !TP_CACORRECTION_LABEL;Chromatic Aberration Correction !TP_CACORRECTION_RED;Red +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHMIXER_BLUE;Blue channel !TP_CHMIXER_GREEN;Green channel !TP_CHMIXER_LABEL;Channel Mixer @@ -1614,6 +1617,7 @@ !TP_RAWCACORR_AUTO;Auto-correction !TP_RAWCACORR_CABLUE;Blue !TP_RAWCACORR_CARED;Red +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1692,7 +1696,6 @@ !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Espanol b/rtdata/languages/Espanol index 66c15c3b4..7be7aa516 100644 --- a/rtdata/languages/Espanol +++ b/rtdata/languages/Espanol @@ -210,7 +210,6 @@ FILEBROWSER_RANK3_TOOLTIP;Rango 3 ***\nAtajoShift-3 FILEBROWSER_RANK4_TOOLTIP;Rango 4 ****\nAtajoShift-4 FILEBROWSER_RANK5_TOOLTIP;Rango 5 *****\nAtajoShift-5 FILEBROWSER_RENAMEDLGLABEL;Renombrar archivo -FILEBROWSER_RENAMEDLGMSG;Renombrar archivo "%1"a: FILEBROWSER_SELECTDARKFRAME;Seleccionar Toma Negra… FILEBROWSER_SELECTFLATFIELD;Seleccionar Campo Plano… FILEBROWSER_SHOWCOLORLABEL1HINT;Mostrar imágenes etiquetadas con Rojo Alt-1 @@ -1705,11 +1704,11 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !MAIN_TAB_INSPECT; Inspect !MAIN_TAB_WAVELET;Wavelet !MAIN_TAB_WAVELET_TOOLTIP;Shortcut: Alt-w !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1787,6 +1786,10 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !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. +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CROP_GTHARMMEANS;Harmonic Means !TP_CROP_GTTRIANGLE1;Golden Triangles 1 !TP_CROP_GTTRIANGLE2;Golden Triangles 2 @@ -1837,6 +1840,7 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !TP_NEUTRAL;Reset !TP_PRSHARPENING_LABEL;Post-Resize Sharpening !TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. +!TP_RAWCACORR_CASTR;Strength !TP_RAW_HD;Threshold !TP_RAW_HD_TOOLTIP;Lower values make hot/dead pixel detection more aggressive, but false positives may lead to artifacts. If you notice any artifacts appearing when enabling the Hot/Dead Pixel Filters, gradually increase the threshold value until they disappear. !TP_RETINEX_CONTEDIT_HSL;Histogram equalizer HSL @@ -1876,7 +1880,6 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Euskara b/rtdata/languages/Euskara index 39dc42e9f..251fa4673 100644 --- a/rtdata/languages/Euskara +++ b/rtdata/languages/Euskara @@ -50,7 +50,6 @@ FILEBROWSER_POPUPTRASH;Move to trash FILEBROWSER_POPUPUNRANK;Unrank FILEBROWSER_POPUPUNTRASH;Remove from trash FILEBROWSER_RENAMEDLGLABEL;Rename file -FILEBROWSER_RENAMEDLGMSG;Rename file "%1" to: FILEBROWSER_SHOWDIRHINT;Show all images of the directory FILEBROWSER_SHOWRANK1HINT;Show images ranked as 1 star FILEBROWSER_SHOWRANK2HINT;Show images ranked as 2 star @@ -950,6 +949,7 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_FULLSCREEN;Fullscreen !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 @@ -997,7 +997,6 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !MAIN_TOOLTIP_THRESHOLD;Threshold !MAIN_TOOLTIP_TOGGLE;Toggle the Before/After view.\nShortcut: Shift-b !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1302,6 +1301,10 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHROMATABERR_LABEL;Chromatic Aberration !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. @@ -1664,6 +1667,7 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !TP_RAWCACORR_AUTO;Auto-correction !TP_RAWCACORR_CABLUE;Blue !TP_RAWCACORR_CARED;Red +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1734,7 +1738,6 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index eac13228d..7cfe47960 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -156,7 +156,6 @@ FILEBROWSER_RANK3_TOOLTIP;Rang 3 *\nRaccourci: Shift-3 FILEBROWSER_RANK4_TOOLTIP;Rang 4 *\nRaccourci: Shift-4 FILEBROWSER_RANK5_TOOLTIP;Rang 5 *\nRaccourci: Shift-5 FILEBROWSER_RENAMEDLGLABEL;Renommage du fichier -FILEBROWSER_RENAMEDLGMSG;Renommer le fichier "%1" en: FILEBROWSER_SELECTDARKFRAME;Choisir une image de Trame Noire... FILEBROWSER_SELECTFLATFIELD;Sélectionner un Champ Uniforme... FILEBROWSER_SHOWCOLORLABEL1HINT;Afficher les images avec un label Rouge\nRaccourci: Alt-1 @@ -1924,9 +1923,9 @@ ZOOMPANEL_ZOOMOUT;Zoom Arrière\nRaccourci: - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !MAIN_BUTTON_SENDTOEDITOR;Edit image in external editor !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !PARTIALPASTE_PRSHARPENING;Post-resize sharpening !PARTIALPASTE_RETINEX;Retinex !PREFERENCES_MONINTENT;Default monitor intent @@ -1936,11 +1935,16 @@ ZOOMPANEL_ZOOMOUT;Zoom Arrière\nRaccourci: - !PREFERENCES_PROFILE_NONE;None !PREFERENCES_TUNNELMETADATA;Copy Exif/IPTC/XMP unchanged to output file !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. +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_COLORTONING_NEUTRAL;Reset sliders !TP_DIRPYRDENOISE_PASSES;Median iterations !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_ICM_PROFILEINTENT;Rendering Intent !TP_NEUTRAL;Reset +!TP_RAWCACORR_CASTR;Strength !TP_RETINEX_CONTEDIT_HSL;Histogram equalizer HSL !TP_RETINEX_CONTEDIT_LAB;Histogram equalizer L*a*b* !TP_RETINEX_CONTEDIT_LH;Hue equalizer @@ -1978,7 +1982,6 @@ ZOOMPANEL_ZOOMOUT;Zoom Arrière\nRaccourci: - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Greek b/rtdata/languages/Greek index 46b1fea4c..61a6f844f 100644 --- a/rtdata/languages/Greek +++ b/rtdata/languages/Greek @@ -50,7 +50,6 @@ FILEBROWSER_POPUPTRASH;Move to trash FILEBROWSER_POPUPUNRANK;Unrank FILEBROWSER_POPUPUNTRASH;Remove from trash FILEBROWSER_RENAMEDLGLABEL;Rename file -FILEBROWSER_RENAMEDLGMSG;Rename file "%1" to: FILEBROWSER_SHOWDIRHINT;Show all images of the directory FILEBROWSER_SHOWRANK1HINT;Show images ranked as 1 star FILEBROWSER_SHOWRANK2HINT;Show images ranked as 2 star @@ -949,6 +948,7 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_FULLSCREEN;Fullscreen !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 @@ -996,7 +996,6 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !MAIN_TOOLTIP_THRESHOLD;Threshold !MAIN_TOOLTIP_TOGGLE;Toggle the Before/After view.\nShortcut: Shift-b !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1301,6 +1300,10 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHROMATABERR_LABEL;Chromatic Aberration !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. @@ -1663,6 +1666,7 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !TP_RAWCACORR_AUTO;Auto-correction !TP_RAWCACORR_CABLUE;Blue !TP_RAWCACORR_CARED;Red +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1733,7 +1737,6 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Hebrew b/rtdata/languages/Hebrew index 0fd75743c..e007ebcd7 100644 --- a/rtdata/languages/Hebrew +++ b/rtdata/languages/Hebrew @@ -50,7 +50,6 @@ FILEBROWSER_POPUPTRASH;Move to trash FILEBROWSER_POPUPUNRANK;Unrank FILEBROWSER_POPUPUNTRASH;Remove from trash FILEBROWSER_RENAMEDLGLABEL;Rename file -FILEBROWSER_RENAMEDLGMSG;Rename file "%1" to: FILEBROWSER_SHOWDIRHINT;Show all images of the directory FILEBROWSER_SHOWRANK1HINT;Show images ranked as 1 star FILEBROWSER_SHOWRANK2HINT;Show images ranked as 2 star @@ -950,6 +949,7 @@ TP_WBALANCE_TEMPERATURE;מידת חום !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_FULLSCREEN;Fullscreen !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 @@ -997,7 +997,6 @@ TP_WBALANCE_TEMPERATURE;מידת חום !MAIN_TOOLTIP_THRESHOLD;Threshold !MAIN_TOOLTIP_TOGGLE;Toggle the Before/After view.\nShortcut: Shift-b !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1302,6 +1301,10 @@ TP_WBALANCE_TEMPERATURE;מידת חום !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHROMATABERR_LABEL;Chromatic Aberration !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. @@ -1664,6 +1667,7 @@ TP_WBALANCE_TEMPERATURE;מידת חום !TP_RAWCACORR_AUTO;Auto-correction !TP_RAWCACORR_CABLUE;Blue !TP_RAWCACORR_CARED;Red +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1734,7 +1738,6 @@ TP_WBALANCE_TEMPERATURE;מידת חום !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Italiano b/rtdata/languages/Italiano index 1561fe108..82061c24d 100644 --- a/rtdata/languages/Italiano +++ b/rtdata/languages/Italiano @@ -154,7 +154,6 @@ FILEBROWSER_RANK3_TOOLTIP;Punteggio 3 *\nScorciatoia: Shift-3 FILEBROWSER_RANK4_TOOLTIP;Punteggio 4 *\nScorciatoia: Shift-4 FILEBROWSER_RANK5_TOOLTIP;Punteggio 5 *\nScorciatoia: Shift-5 FILEBROWSER_RENAMEDLGLABEL;Rinomina il file -FILEBROWSER_RENAMEDLGMSG;Rinomina il file "%1" in: FILEBROWSER_SELECTDARKFRAME;Seleziona un Dark Frame... FILEBROWSER_SELECTFLATFIELD;Seleziona un Flat Field... FILEBROWSER_SHOWCOLORLABEL1HINT;Mostra le immagini con etichetta Rossa.\nScorciatoia: Alt-1 @@ -1570,12 +1569,12 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !MAIN_BUTTON_SENDTOEDITOR;Edit image in external editor !MAIN_TAB_INSPECT; Inspect !MAIN_TAB_WAVELET;Wavelet !MAIN_TAB_WAVELET_TOOLTIP;Shortcut: Alt-w !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !PARTIALPASTE_COLORTONING;Color toning !PARTIALPASTE_EQUALIZER;Wavelet levels !PARTIALPASTE_FILMSIMULATION;Film simulation @@ -1650,6 +1649,10 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !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. +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_COLORTONING_AB;o C/L !TP_COLORTONING_AUTOSAT;Automatic !TP_COLORTONING_BALANCE;Balance @@ -1767,6 +1770,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !TP_PREPROCESS_HOTPIXFILT_TOOLTIP;Tries to suppress hot pixels. !TP_PRSHARPENING_LABEL;Post-Resize Sharpening !TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red !TP_RAWEXPOS_BLACK_2;Blue @@ -1817,7 +1821,6 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Japanese b/rtdata/languages/Japanese index e0daeedae..78cfa3275 100644 --- a/rtdata/languages/Japanese +++ b/rtdata/languages/Japanese @@ -189,7 +189,6 @@ FILEBROWSER_RANK3_TOOLTIP;ランク 3 *\nショートカット: Shift-3 FILEBROWSER_RANK4_TOOLTIP;ランク 4 *\nショートカット: Shift-4 FILEBROWSER_RANK5_TOOLTIP;ランク 5 *\nショートカット: Shift-5 FILEBROWSER_RENAMEDLGLABEL;ファイル名変更 -FILEBROWSER_RENAMEDLGMSG;"%1" にファイル名変更: FILEBROWSER_SELECTDARKFRAME;ダークフレームの選択... FILEBROWSER_SELECTFLATFIELD;フラットフィールドの選択... FILEBROWSER_SHOWCOLORLABEL1HINT;レッド・ラベルの画像を表示\nショートカット: Alt-1 @@ -1958,9 +1957,9 @@ ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !MAIN_BUTTON_SENDTOEDITOR;Edit image in external editor !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !PARTIALPASTE_PRSHARPENING;Post-resize sharpening !PARTIALPASTE_RETINEX;Retinex !PREFERENCES_MONINTENT;Default monitor intent @@ -1970,9 +1969,14 @@ ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - !PREFERENCES_PROFILE_NONE;None !PREFERENCES_TUNNELMETADATA;Copy Exif/IPTC/XMP unchanged to output file !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. +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_ICM_PROFILEINTENT;Rendering Intent !TP_NEUTRAL;Reset +!TP_RAWCACORR_CASTR;Strength !TP_RETINEX_CONTEDIT_HSL;Histogram equalizer HSL !TP_RETINEX_CONTEDIT_LAB;Histogram equalizer L*a*b* !TP_RETINEX_CONTEDIT_LH;Hue equalizer @@ -2010,7 +2014,6 @@ ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Latvian b/rtdata/languages/Latvian index bbae23f2b..4d4415e58 100644 --- a/rtdata/languages/Latvian +++ b/rtdata/languages/Latvian @@ -50,7 +50,6 @@ FILEBROWSER_POPUPTRASH;Izmest atkritnē FILEBROWSER_POPUPUNRANK;Nevērtēt FILEBROWSER_POPUPUNTRASH;Izņemt no atkritnes FILEBROWSER_RENAMEDLGLABEL;Pārsaukt failu -FILEBROWSER_RENAMEDLGMSG;Pārsaukt failu "%1" uz: FILEBROWSER_SHOWDIRHINT;Rādīt visus direktorija attēlus FILEBROWSER_SHOWRANK1HINT;Rādīt attēlus ar 1 zvaigzni FILEBROWSER_SHOWRANK2HINT;Rādīt attēlus ar 2 zvaigznēm @@ -950,6 +949,7 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_FULLSCREEN;Fullscreen !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 @@ -997,7 +997,6 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !MAIN_TOOLTIP_THRESHOLD;Threshold !MAIN_TOOLTIP_TOGGLE;Toggle the Before/After view.\nShortcut: Shift-b !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1302,6 +1301,10 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHROMATABERR_LABEL;Chromatic Aberration !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. @@ -1664,6 +1667,7 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !TP_RAWCACORR_AUTO;Auto-correction !TP_RAWCACORR_CABLUE;Blue !TP_RAWCACORR_CARED;Red +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1734,7 +1738,6 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Magyar b/rtdata/languages/Magyar index 92af8a21d..9600eb0ce 100644 --- a/rtdata/languages/Magyar +++ b/rtdata/languages/Magyar @@ -123,7 +123,6 @@ FILEBROWSER_QUERYBUTTONHINT;Találati lista ürítése FILEBROWSER_QUERYHINT;Írd be a keresett állomány nevét vagy abból egy töredéket.\nCtrl-F megnyomásával (az állományböngészőben) a fókuszt a keresőmezőre helyezheted.\nEnter indítja a keresést. FILEBROWSER_QUERYLABEL; Keresés: FILEBROWSER_RENAMEDLGLABEL;Fájl átnevezése -FILEBROWSER_RENAMEDLGMSG;%1 új neve: FILEBROWSER_SELECTDARKFRAME;Referencia feketekép kiválasztása... FILEBROWSER_SELECTFLATFIELD;Flat field kép kiválasztása FILEBROWSER_SHOWCOLORLABEL1HINT;Piros címkéjű képek megjelenítése.\nGyorsbillentyű: Alt-1 @@ -1231,6 +1230,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 !MAIN_BUTTON_NAVPREV_TOOLTIP;Navigate to the previous image relative to image opened in the Editor.\nShortcut: Shift-F3\n\nTo navigate to the previous image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F3 @@ -1247,7 +1247,6 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !MAIN_TOOLTIP_BACKCOLOR1;Background color of the preview: Black\nShortcut: 9 !MAIN_TOOLTIP_BACKCOLOR2;Background color of the preview: White\nShortcut: 9 !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1457,6 +1456,10 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. !TP_COLORAPP_ADAPTVIEWING;Viewing luminosity (cd/m²) @@ -1741,6 +1744,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !TP_PREPROCESS_HOTPIXFILT_TOOLTIP;Tries to suppress hot pixels. !TP_PRSHARPENING_LABEL;Post-Resize Sharpening !TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red !TP_RAWEXPOS_BLACK_2;Blue @@ -1796,7 +1800,6 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Nederlands b/rtdata/languages/Nederlands index cdbc5cdc2..fa1dbcd09 100644 --- a/rtdata/languages/Nederlands +++ b/rtdata/languages/Nederlands @@ -169,7 +169,6 @@ FILEBROWSER_RANK3_TOOLTIP;Waardering 3 *\nSneltoets: Shift-3 FILEBROWSER_RANK4_TOOLTIP;Waardering 4 *\nSneltoets: Shift-4 FILEBROWSER_RANK5_TOOLTIP;Waardering 5 *\nSneltoets: Shift-5 FILEBROWSER_RENAMEDLGLABEL;Hernoem bestand -FILEBROWSER_RENAMEDLGMSG;Hernoem bestand "%1" naar: FILEBROWSER_SELECTDARKFRAME;Selecteer donkerframe... FILEBROWSER_SELECTFLATFIELD;Kies vlakveldopname... FILEBROWSER_SHOWCOLORLABEL1HINT;Toon foto's met label Rood\nSneltoets: Alt-1 @@ -1979,15 +1978,19 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !MAIN_BUTTON_SENDTOEDITOR;Edit image in external editor !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !PARTIALPASTE_PRSHARPENING;Post-resize sharpening !PREFERENCES_MONINTENT;Default monitor intent !PREFERENCES_MONPROFILE;Default monitor profile !PREFERENCES_PARSEDEXTDOWNHINT;Move selected extension down in the list. !PREFERENCES_PARSEDEXTUPHINT;Move selected extension up in the list. !PREFERENCES_PROFILE_NONE;None +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_COLORTONING_STR;Strength !TP_DIRPYRDENOISE_CUR;Curve !TP_DIRPYRDENOISE_LAB;L*a*b* @@ -1995,6 +1998,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_ICM_PROFILEINTENT;Rendering Intent !TP_NEUTRAL;Reset +!TP_RAWCACORR_CASTR;Strength !TP_RETINEX_CONTEDIT_MAP;Mask equalizer !TP_RETINEX_CURVEEDITOR_MAP;L=f(L) !TP_RETINEX_CURVEEDITOR_MAP_TOOLTIP;This curve can be applied alone or with a Gaussian mask or wavelet mask.\nBeware of artifacts! @@ -2008,7 +2012,6 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !TP_RETINEX_ITER_TOOLTIP;Simulate a tone-mapping operator.\nHigh values increase the processing time. !TP_RETINEX_LABEL_MASK;Mask !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Norsk BM b/rtdata/languages/Norsk BM index c79874196..105277339 100644 --- a/rtdata/languages/Norsk BM +++ b/rtdata/languages/Norsk BM @@ -50,7 +50,6 @@ FILEBROWSER_POPUPTRASH;Flytt til søpla FILEBROWSER_POPUPUNRANK;Fjern rangering FILEBROWSER_POPUPUNTRASH;Fjern fra søpla FILEBROWSER_RENAMEDLGLABEL;Bytt filnavn -FILEBROWSER_RENAMEDLGMSG;Bytt filnavn "%1" til: FILEBROWSER_SHOWDIRHINT;Vis alle bildene i folderen FILEBROWSER_SHOWRANK1HINT;Vis bilder rangert med 1 stjerne FILEBROWSER_SHOWRANK2HINT;Vis bilder rangert med 2 stjerne @@ -949,6 +948,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_FULLSCREEN;Fullscreen !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 @@ -996,7 +996,6 @@ TP_WBALANCE_TEMPERATURE;Temperatur !MAIN_TOOLTIP_THRESHOLD;Threshold !MAIN_TOOLTIP_TOGGLE;Toggle the Before/After view.\nShortcut: Shift-b !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1301,6 +1300,10 @@ TP_WBALANCE_TEMPERATURE;Temperatur !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHROMATABERR_LABEL;Chromatic Aberration !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. @@ -1663,6 +1666,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !TP_RAWCACORR_AUTO;Auto-correction !TP_RAWCACORR_CABLUE;Blue !TP_RAWCACORR_CARED;Red +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1733,7 +1737,6 @@ TP_WBALANCE_TEMPERATURE;Temperatur !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Polish b/rtdata/languages/Polish index 2e83d2950..5f3c30045 100644 --- a/rtdata/languages/Polish +++ b/rtdata/languages/Polish @@ -158,7 +158,6 @@ FILEBROWSER_RANK3_TOOLTIP;Oceń 3 *\nSkrót: Shift-3 FILEBROWSER_RANK4_TOOLTIP;Oceń 4 *\nSkrót: Shift-4 FILEBROWSER_RANK5_TOOLTIP;Oceń 5 *\nSkrót: Shift-5 FILEBROWSER_RENAMEDLGLABEL;Zmień nazwę pliku -FILEBROWSER_RENAMEDLGMSG;Zmień nazwę pliku "%1" na: FILEBROWSER_SELECTDARKFRAME;Wybierz czarną klatkę... FILEBROWSER_SELECTFLATFIELD;Wybierz puste pole... FILEBROWSER_SHOWCOLORLABEL1HINT;Pokazuje zdjęcia z czerwoną etykietą.\nSkrót: Alt-1 @@ -1662,12 +1661,12 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !MAIN_BUTTON_SENDTOEDITOR;Edit image in external editor !MAIN_TAB_INSPECT; Inspect !MAIN_TAB_WAVELET;Wavelet !MAIN_TAB_WAVELET_TOOLTIP;Shortcut: Alt-w !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !PARTIALPASTE_EQUALIZER;Wavelet levels !PARTIALPASTE_PRSHARPENING;Post-resize sharpening !PARTIALPASTE_RETINEX;Retinex @@ -1735,6 +1734,10 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !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. +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CROP_GTHARMMEANS;Harmonic Means !TP_CROP_GTTRIANGLE1;Golden Triangles 1 !TP_CROP_GTTRIANGLE2;Golden Triangles 2 @@ -1784,6 +1787,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_NEUTRAL;Reset !TP_PRSHARPENING_LABEL;Post-Resize Sharpening !TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. +!TP_RAWCACORR_CASTR;Strength !TP_RAW_HD;Threshold !TP_RAW_HD_TOOLTIP;Lower values make hot/dead pixel detection more aggressive, but false positives may lead to artifacts. If you notice any artifacts appearing when enabling the Hot/Dead Pixel Filters, gradually increase the threshold value until they disappear. !TP_RETINEX_CONTEDIT_HSL;Histogram equalizer HSL @@ -1823,7 +1827,6 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Polish (Latin Characters) b/rtdata/languages/Polish (Latin Characters) index 7bbd62950..79bf35bea 100644 --- a/rtdata/languages/Polish (Latin Characters) +++ b/rtdata/languages/Polish (Latin Characters) @@ -158,7 +158,6 @@ FILEBROWSER_RANK3_TOOLTIP;Ocen 3 *\nSkrot: Shift-3 FILEBROWSER_RANK4_TOOLTIP;Ocen 4 *\nSkrot: Shift-4 FILEBROWSER_RANK5_TOOLTIP;Ocen 5 *\nSkrot: Shift-5 FILEBROWSER_RENAMEDLGLABEL;Zmien nazwe pliku -FILEBROWSER_RENAMEDLGMSG;Zmien nazwe pliku "%1" na: FILEBROWSER_SELECTDARKFRAME;Wybierz czarna klatke... FILEBROWSER_SELECTFLATFIELD;Wybierz puste pole... FILEBROWSER_SHOWCOLORLABEL1HINT;Pokazuje zdjecia z czerwona etykieta.\nSkrot: Alt-1 @@ -1662,12 +1661,12 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !MAIN_BUTTON_SENDTOEDITOR;Edit image in external editor !MAIN_TAB_INSPECT; Inspect !MAIN_TAB_WAVELET;Wavelet !MAIN_TAB_WAVELET_TOOLTIP;Shortcut: Alt-w !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !PARTIALPASTE_EQUALIZER;Wavelet levels !PARTIALPASTE_PRSHARPENING;Post-resize sharpening !PARTIALPASTE_RETINEX;Retinex @@ -1735,6 +1734,10 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !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. +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CROP_GTHARMMEANS;Harmonic Means !TP_CROP_GTTRIANGLE1;Golden Triangles 1 !TP_CROP_GTTRIANGLE2;Golden Triangles 2 @@ -1784,6 +1787,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !TP_NEUTRAL;Reset !TP_PRSHARPENING_LABEL;Post-Resize Sharpening !TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. +!TP_RAWCACORR_CASTR;Strength !TP_RAW_HD;Threshold !TP_RAW_HD_TOOLTIP;Lower values make hot/dead pixel detection more aggressive, but false positives may lead to artifacts. If you notice any artifacts appearing when enabling the Hot/Dead Pixel Filters, gradually increase the threshold value until they disappear. !TP_RETINEX_CONTEDIT_HSL;Histogram equalizer HSL @@ -1823,7 +1827,6 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Portugues (Brasil) b/rtdata/languages/Portugues (Brasil) index 627e3765c..a665b17e4 100644 --- a/rtdata/languages/Portugues (Brasil) +++ b/rtdata/languages/Portugues (Brasil) @@ -50,7 +50,6 @@ FILEBROWSER_POPUPTRASH;Mover para a lixeira FILEBROWSER_POPUPUNRANK;Desclassificar FILEBROWSER_POPUPUNTRASH;Remover da lixeira FILEBROWSER_RENAMEDLGLABEL;Renomear arquivo -FILEBROWSER_RENAMEDLGMSG;Renomear arquivo "%1" como: FILEBROWSER_SHOWDIRHINT;Exibir todas as imagens do diretório FILEBROWSER_SHOWRANK1HINT;Exibir imagens classificadas como 1 estrela FILEBROWSER_SHOWRANK2HINT;Exibir imagens classificadas como 2 estrelas @@ -950,6 +949,7 @@ TP_WBALANCE_TEMPERATURE;Temperatura !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_FULLSCREEN;Fullscreen !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 @@ -997,7 +997,6 @@ TP_WBALANCE_TEMPERATURE;Temperatura !MAIN_TOOLTIP_THRESHOLD;Threshold !MAIN_TOOLTIP_TOGGLE;Toggle the Before/After view.\nShortcut: Shift-b !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1302,6 +1301,10 @@ TP_WBALANCE_TEMPERATURE;Temperatura !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHROMATABERR_LABEL;Chromatic Aberration !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. @@ -1664,6 +1667,7 @@ TP_WBALANCE_TEMPERATURE;Temperatura !TP_RAWCACORR_AUTO;Auto-correction !TP_RAWCACORR_CABLUE;Blue !TP_RAWCACORR_CARED;Red +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1734,7 +1738,6 @@ TP_WBALANCE_TEMPERATURE;Temperatura !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Russian b/rtdata/languages/Russian index 54639f5e1..778500cbb 100644 --- a/rtdata/languages/Russian +++ b/rtdata/languages/Russian @@ -153,7 +153,6 @@ FILEBROWSER_RANK3_TOOLTIP;Рейтинг 3 *\nГорячая клавиша: FILEBROWSER_RANK4_TOOLTIP;Рейтинг 4 *\nГорячая клавиша: Shift-4 FILEBROWSER_RANK5_TOOLTIP;Рейтинг 5 *\nГорячая клавиша: Shift-5 FILEBROWSER_RENAMEDLGLABEL;Переименовать файл -FILEBROWSER_RENAMEDLGMSG;Переименовать файл "%1" в: FILEBROWSER_SELECTDARKFRAME;Выбрать темновой кадр... FILEBROWSER_SELECTFLATFIELD;Выбрать плоское поле... FILEBROWSER_SHOWCOLORLABEL1HINT;Показать изображения, отмеченные Красным.\nГорячая клавиша: Alt-1 @@ -1513,13 +1512,13 @@ ZOOMPANEL_ZOOMOUT;Удалить - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !MAIN_BUTTON_SENDTOEDITOR;Edit image in external editor !MAIN_TAB_INSPECT; Inspect !MAIN_TAB_WAVELET;Wavelet !MAIN_TAB_WAVELET_TOOLTIP;Shortcut: Alt-w !MAIN_TOOLTIP_HIDEHP;Show/Hide the left panel (including the history).\nShortcut: l !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1611,6 +1610,10 @@ ZOOMPANEL_ZOOMOUT;Удалить - !TP_BWMIX_SET_RGBREL;Relative RGB !TP_BWMIX_SET_ROYGCBPMABS;Absolute ROYGCBPM !TP_BWMIX_SET_ROYGCBPMREL;Relative ROYGCBPM +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_COLORAPP_DATACIE_TOOLTIP;When enabled, histograms in CIECAM02 curves show approximate values/ranges for J or Q, and C, s or M after the CIECAM02 adjustments.\nThis selection does not impact the main histogram panel.\n\nWhen disabled, histograms in CIECAM02 curves show L*a*b* values before CIECAM02 adjustments. !TP_COLORAPP_DEGREE_AUTO_TOOLTIP;If the check-box is checked (recommended), RawTherapee calculates an optimum value, which is then used by CAT02, and also for the entire CIECAM02.\nTo set the value manually, uncheck the check-box first (values above 65 are recommended). !TP_COLORAPP_DEGREE_TOOLTIP;Amount of CIE Chromatic Adaptation Transform 2002. @@ -1769,6 +1772,7 @@ ZOOMPANEL_ZOOMOUT;Удалить - !TP_PREPROCESS_HOTPIXFILT_TOOLTIP;Tries to suppress hot pixels. !TP_PRSHARPENING_LABEL;Post-Resize Sharpening !TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red !TP_RAWEXPOS_BLACK_2;Blue @@ -1819,7 +1823,6 @@ ZOOMPANEL_ZOOMOUT;Удалить - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Serbian (Cyrilic Characters) b/rtdata/languages/Serbian (Cyrilic Characters) index d813e856b..c48c5528f 100644 --- a/rtdata/languages/Serbian (Cyrilic Characters) +++ b/rtdata/languages/Serbian (Cyrilic Characters) @@ -98,7 +98,6 @@ FILEBROWSER_QUERYBUTTONHINT;Очисти поље за претрагу FILEBROWSER_QUERYHINT;Унесите део имена датотеке за претрагу nCtrl-f поставља фокус (у Разгледачу датотека);nEnter претражује FILEBROWSER_QUERYLABEL; Тражи: FILEBROWSER_RENAMEDLGLABEL;Преименуј датотеку -FILEBROWSER_RENAMEDLGMSG;Преименуј датотеку „%1“ у: FILEBROWSER_SELECTDARKFRAME;Изабери тамни кадар... FILEBROWSER_SELECTFLATFIELD;Изабери равно поље... FILEBROWSER_SHOWCOLORLABEL1HINT;Приказује слике означене црвеном Alt-1 @@ -1154,6 +1153,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 !MAIN_BUTTON_NAVPREV_TOOLTIP;Navigate to the previous image relative to image opened in the Editor.\nShortcut: Shift-F3\n\nTo navigate to the previous image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F3 @@ -1178,7 +1178,6 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !MAIN_TOOLTIP_PREVIEWR;Preview the Red channel.\nShortcut: r !MAIN_TOOLTIP_THRESHOLD;Threshold !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1398,6 +1397,10 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. !TP_COLORAPP_ADAPTVIEWING;Viewing luminosity (cd/m²) @@ -1698,6 +1701,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !TP_PREPROCESS_HOTPIXFILT_TOOLTIP;Tries to suppress hot pixels. !TP_PRSHARPENING_LABEL;Post-Resize Sharpening !TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red !TP_RAWEXPOS_BLACK_2;Blue @@ -1753,7 +1757,6 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Serbian (Latin Characters) b/rtdata/languages/Serbian (Latin Characters) index 445cdd943..ee2df3cdf 100644 --- a/rtdata/languages/Serbian (Latin Characters) +++ b/rtdata/languages/Serbian (Latin Characters) @@ -98,7 +98,6 @@ FILEBROWSER_QUERYBUTTONHINT;Očisti polje za pretragu FILEBROWSER_QUERYHINT;Unesite deo imena datoteke za pretragu nCtrl-f postavlja fokus (u Razgledaču datoteka);nEnter pretražuje FILEBROWSER_QUERYLABEL; Traži: FILEBROWSER_RENAMEDLGLABEL;Preimenuj datoteku -FILEBROWSER_RENAMEDLGMSG;Preimenuj datoteku „%1“ u: FILEBROWSER_SELECTDARKFRAME;Izaberi tamni kadar... FILEBROWSER_SELECTFLATFIELD;Izaberi ravno polje... FILEBROWSER_SHOWCOLORLABEL1HINT;Prikazuje slike označene crvenom Alt-1 @@ -1154,6 +1153,7 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 !MAIN_BUTTON_NAVPREV_TOOLTIP;Navigate to the previous image relative to image opened in the Editor.\nShortcut: Shift-F3\n\nTo navigate to the previous image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F3 @@ -1178,7 +1178,6 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !MAIN_TOOLTIP_PREVIEWR;Preview the Red channel.\nShortcut: r !MAIN_TOOLTIP_THRESHOLD;Threshold !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1398,6 +1397,10 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. !TP_COLORAPP_ADAPTVIEWING;Viewing luminosity (cd/m²) @@ -1698,6 +1701,7 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !TP_PREPROCESS_HOTPIXFILT_TOOLTIP;Tries to suppress hot pixels. !TP_PRSHARPENING_LABEL;Post-Resize Sharpening !TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red !TP_RAWEXPOS_BLACK_2;Blue @@ -1753,7 +1757,6 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Slovak b/rtdata/languages/Slovak index 8a9a576c7..7ea5ead8a 100644 --- a/rtdata/languages/Slovak +++ b/rtdata/languages/Slovak @@ -66,7 +66,6 @@ FILEBROWSER_POPUPTRASH;Presunúť do koša FILEBROWSER_POPUPUNRANK;Zrušiť triedu FILEBROWSER_POPUPUNTRASH;Odstrániť z koša FILEBROWSER_RENAMEDLGLABEL;Premenovať súbor -FILEBROWSER_RENAMEDLGMSG;Premenovať súbor "%1" na: FILEBROWSER_SHOWDIRHINT;Ukázať všetky obrázky v adresári FILEBROWSER_SHOWEXIFINFO;Ukázať EXIF info i FILEBROWSER_SHOWRANK1HINT;Ukázať obrázky triedy 1 hviezda @@ -1013,6 +1012,7 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 !MAIN_BUTTON_NAVPREV_TOOLTIP;Navigate to the previous image relative to image opened in the Editor.\nShortcut: Shift-F3\n\nTo navigate to the previous image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F3 @@ -1053,7 +1053,6 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !MAIN_TOOLTIP_SHOWHIDETP1;Show/Hide the top panel.\nShortcut: Shift-l !MAIN_TOOLTIP_THRESHOLD;Threshold !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1341,6 +1340,10 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHROMATABERR_LABEL;Chromatic Aberration !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. @@ -1677,6 +1680,7 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. !TP_RAWCACORR_CABLUE;Blue !TP_RAWCACORR_CARED;Red +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1742,7 +1746,6 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Suomi b/rtdata/languages/Suomi index 0b827d81b..5017c2066 100644 --- a/rtdata/languages/Suomi +++ b/rtdata/languages/Suomi @@ -50,7 +50,6 @@ FILEBROWSER_POPUPTRASH;Siirrä roskakoriin FILEBROWSER_POPUPUNRANK;Poista arvostelu FILEBROWSER_POPUPUNTRASH;Pelasta roskakorista FILEBROWSER_RENAMEDLGLABEL;Nimeä uudelleen -FILEBROWSER_RENAMEDLGMSG;Tiedoston "%1" uusi nimi: FILEBROWSER_SHOWDIRHINT;Näytä hakemiston kaikki kuvat FILEBROWSER_SHOWRANK1HINT;Näytä 1 tähden kuvat FILEBROWSER_SHOWRANK2HINT;Näytä 2 tähden kuvat @@ -951,6 +950,7 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_FULLSCREEN;Fullscreen !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 @@ -998,7 +998,6 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !MAIN_TOOLTIP_THRESHOLD;Threshold !MAIN_TOOLTIP_TOGGLE;Toggle the Before/After view.\nShortcut: Shift-b !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1302,6 +1301,10 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHROMATABERR_LABEL;Chromatic Aberration !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. @@ -1664,6 +1667,7 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !TP_RAWCACORR_AUTO;Auto-correction !TP_RAWCACORR_CABLUE;Blue !TP_RAWCACORR_CARED;Red +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1734,7 +1738,6 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Swedish b/rtdata/languages/Swedish index 80975e68f..3f979abaf 100644 --- a/rtdata/languages/Swedish +++ b/rtdata/languages/Swedish @@ -154,7 +154,6 @@ FILEBROWSER_RANK3_TOOLTIP;Betyg 3 *\nKortkommando: Shift-3 FILEBROWSER_RANK4_TOOLTIP;Betyg 4 *\nKortkommando: Shift-4 FILEBROWSER_RANK5_TOOLTIP;Betyg 5 *\nKortkommando: Shift-5 FILEBROWSER_RENAMEDLGLABEL;Byt namn -FILEBROWSER_RENAMEDLGMSG;Byt namn på "%1" till: FILEBROWSER_SELECTDARKFRAME;Välj svartbild... FILEBROWSER_SELECTFLATFIELD;Välj plattfält... FILEBROWSER_SHOWCOLORLABEL1HINT;Visa bilder märkta som röda.\nKortkommando: Alt-1 @@ -1789,9 +1788,9 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !MAIN_BUTTON_SENDTOEDITOR;Edit image in external editor !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !PARTIALPASTE_COLORTONING;Color toning !PARTIALPASTE_FLATFIELDCLIPCONTROL;Flat-field clip control !PARTIALPASTE_PRSHARPENING;Post-resize sharpening @@ -1814,6 +1813,10 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !PREFERENCES_TUNNELMETADATA;Copy Exif/IPTC/XMP unchanged to output file !SAVEDLG_SUBSAMP;Subsampling !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. +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_COLORAPP_LABEL;CIE Color Appearance Model 2002 !TP_COLORTONING_CURVEEDITOR_CL_TOOLTIP;Chroma opacity as a function of luminance oC=f(L) !TP_COLORTONING_LAB;L*a*b* blending @@ -1864,6 +1867,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !TP_ICM_PROFILEINTENT;Rendering Intent !TP_NEUTRAL;Reset !TP_PRSHARPENING_LABEL;Post-Resize Sharpening +!TP_RAWCACORR_CASTR;Strength !TP_RAW_HD_TOOLTIP;Lower values make hot/dead pixel detection more aggressive, but false positives may lead to artifacts. If you notice any artifacts appearing when enabling the Hot/Dead Pixel Filters, gradually increase the threshold value until they disappear. !TP_RAW_SENSOR_XTRANS_DMETHOD_TOOLTIP;3-pass gives best results (recommended for low ISO images).\n1-pass is almost undistinguishable from 3-pass for high ISO images and is faster. !TP_RAW_SENSOR_XTRANS_LABEL;Sensor with X-Trans Matrix @@ -1904,7 +1908,6 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/Turkish b/rtdata/languages/Turkish index 58ab4b250..d7f6fa405 100644 --- a/rtdata/languages/Turkish +++ b/rtdata/languages/Turkish @@ -50,7 +50,6 @@ FILEBROWSER_POPUPTRASH;Move to trash FILEBROWSER_POPUPUNRANK;Unrank FILEBROWSER_POPUPUNTRASH;Remove from trash FILEBROWSER_RENAMEDLGLABEL;Rename file -FILEBROWSER_RENAMEDLGMSG;Rename file "%1" to: FILEBROWSER_SHOWDIRHINT;Show all images of the directory FILEBROWSER_SHOWRANK1HINT;Show images ranked as 1 star FILEBROWSER_SHOWRANK2HINT;Show images ranked as 2 star @@ -950,6 +949,7 @@ TP_WBALANCE_TEMPERATURE;Isı !HISTORY_MSG_437;Retinex - M - Method !HISTORY_MSG_438;Retinex - M - Equalizer !HISTORY_MSG_439;Retinex - Preview +!HISTORY_MSG_440;CbDL - Method !HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s !MAIN_BUTTON_FULLSCREEN;Fullscreen !MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the next image relative to image opened in the Editor.\nShortcut: Shift-F4\n\nTo navigate to the next image relative to the currently selected thumbnail in the File Browser or Filmstrip:\nShortcut: F4 @@ -997,7 +997,6 @@ TP_WBALANCE_TEMPERATURE;Isı !MAIN_TOOLTIP_THRESHOLD;Threshold !MAIN_TOOLTIP_TOGGLE;Toggle the Before/After view.\nShortcut: Shift-b !MONITOR_PROFILE_SYSTEM;System default -!MONITOR_SOFTPROOF;Soft-proof !NAVIGATOR_B;B: !NAVIGATOR_G;G: !NAVIGATOR_H;H: @@ -1301,6 +1300,10 @@ TP_WBALANCE_TEMPERATURE;Isı !TP_BWMIX_TCMODE_STANDARD;B&W Standard !TP_BWMIX_TCMODE_WEIGHTEDSTD;B&W Weighted Standard !TP_BWMIX_VAL;L +!TP_CBDL_AFT;After Black-and-White +!TP_CBDL_BEF;Before Black-and-White +!TP_CBDL_METHOD;Process located +!TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. !TP_CHROMATABERR_LABEL;Chromatic Aberration !TP_COLORAPP_ADAPTSCENE;Scene luminosity !TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environement (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. @@ -1663,6 +1666,7 @@ TP_WBALANCE_TEMPERATURE;Isı !TP_RAWCACORR_AUTO;Auto-correction !TP_RAWCACORR_CABLUE;Blue !TP_RAWCACORR_CARED;Red +!TP_RAWCACORR_CASTR;Strength !TP_RAWEXPOS_BLACKS;Black Levels !TP_RAWEXPOS_BLACK_0;Green 1 (lead) !TP_RAWEXPOS_BLACK_1;Red @@ -1733,7 +1737,6 @@ TP_WBALANCE_TEMPERATURE;Isı !TP_RETINEX_LABSPACE;L*a*b* !TP_RETINEX_LOW;Low !TP_RETINEX_MAP;Mask method -!TP_RETINEX_MAP_CURV;Curve only !TP_RETINEX_MAP_GAUS;Gaussian mask !TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) !TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtdata/languages/default b/rtdata/languages/default index 6c3561efb..f4b042ec7 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -158,7 +158,6 @@ FILEBROWSER_RANK3_TOOLTIP;Rank 3 *\nShortcut: Shift-3 FILEBROWSER_RANK4_TOOLTIP;Rank 4 *\nShortcut: Shift-4 FILEBROWSER_RANK5_TOOLTIP;Rank 5 *\nShortcut: Shift-5 FILEBROWSER_RENAMEDLGLABEL;Rename file -FILEBROWSER_RENAMEDLGMSG;Rename file "%1" to: FILEBROWSER_SELECTDARKFRAME;Select dark-frame... FILEBROWSER_SELECTFLATFIELD;Select flat-field... FILEBROWSER_SHOWCOLORLABEL1HINT;Show images labeled Red.\nShortcut: Alt-1 @@ -670,8 +669,9 @@ HISTORY_MSG_436;Retinex - M - Radius HISTORY_MSG_437;Retinex - M - Method HISTORY_MSG_438;Retinex - M - Equalizer HISTORY_MSG_439;Retinex - Preview -HISTORY_MSG_440;Retinex - Gain transmission -HISTORY_MSG_441;Retinex - Scale +HISTORY_MSG_440;CbDL - Method +HISTORY_MSG_441;Retinex - Gain transmission +HISTORY_MSG_442;Retinex - Scale HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOT;Snapshot @@ -790,7 +790,6 @@ MAIN_TOOLTIP_SHOWHIDETP1;Show/Hide the top panel.\nShortcut: Shift-l MAIN_TOOLTIP_THRESHOLD;Threshold MAIN_TOOLTIP_TOGGLE;Toggle the Before/After view.\nShortcut: Shift-b MONITOR_PROFILE_SYSTEM;System default -MONITOR_SOFTPROOF;Soft-proof NAVIGATOR_B;B: NAVIGATOR_G;G: NAVIGATOR_H;H: @@ -1208,6 +1207,10 @@ TP_BWMIX_VAL;L TP_CACORRECTION_BLUE;Blue TP_CACORRECTION_LABEL;Chromatic Aberration Correction TP_CACORRECTION_RED;Red +TP_CBDL_AFT;After Black-and-White +TP_CBDL_BEF;Before Black-and-White +TP_CBDL_METHOD;Process located +TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. TP_CHMIXER_BLUE;Blue channel TP_CHMIXER_GREEN;Green channel TP_CHMIXER_LABEL;Channel Mixer @@ -1615,6 +1618,7 @@ TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the " TP_RAWCACORR_AUTO;Auto-correction TP_RAWCACORR_CABLUE;Blue TP_RAWCACORR_CARED;Red +TP_RAWCACORR_CASTR;Strength TP_RAWEXPOS_BLACKS;Black Levels TP_RAWEXPOS_BLACK_0;Green 1 (lead) TP_RAWEXPOS_BLACK_1;Red @@ -1696,7 +1700,6 @@ TP_RETINEX_LABEL_MASK;Mask TP_RETINEX_LABSPACE;L*a*b* TP_RETINEX_LOW;Low TP_RETINEX_MAP;Mask method -TP_RETINEX_MAP_CURV;Curve only TP_RETINEX_MAP_GAUS;Gaussian mask TP_RETINEX_MAP_MAPP;Sharp mask (wavelet partial) TP_RETINEX_MAP_MAPT;Sharp mask (wavelet total) diff --git a/rtengine/CA_correct_RT.cc b/rtengine/CA_correct_RT.cc index eee21c18e..ab0b95a27 100644 --- a/rtengine/CA_correct_RT.cc +++ b/rtengine/CA_correct_RT.cc @@ -27,10 +27,9 @@ #include "rawimagesource.h" #include "rt_math.h" -using namespace std; -using namespace rtengine; +namespace { -int RawImageSource::LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* pfSolution) +bool LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* pfSolution) { //============================================================================== // return 1 if system not solving, 0 if system solved @@ -52,11 +51,11 @@ int RawImageSource::LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* for(k = 0; k < (nDim - 1); k++) { // base row of matrix // search of line with max element - fMaxElem = fabsf( pfMatr[k * nDim + k] ); + fMaxElem = fabs( pfMatr[k * nDim + k] ); m = k; for (i = k + 1; i < nDim; i++) { - if(fMaxElem < fabsf(pfMatr[i * nDim + k]) ) { + if(fMaxElem < fabs(pfMatr[i * nDim + k]) ) { fMaxElem = pfMatr[i * nDim + k]; m = i; } @@ -77,7 +76,7 @@ int RawImageSource::LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* if( pfMatr[k * nDim + k] == 0.) { //linear system has no solution - return 1; // needs improvement !!! + return false; // needs improvement !!! } // triangulation of matrix with coefficients @@ -102,24 +101,37 @@ int RawImageSource::LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* pfSolution[k] = pfSolution[k] / pfMatr[k * nDim + k]; } - return 0; + return true; } //end of linear equation solver //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +inline void pixSort(float &a, float &b) { + if (a > b) { + float temp = a; + a = b; + b = temp; + } +} -void RawImageSource::CA_correct_RT(double cared, double cablue) +} + +using namespace std; +using namespace rtengine; + +void RawImageSource::CA_correct_RT(const double cared, const double cablue, const double caautostrength) { -// multithreaded by Ingo Weyrich -#define TS 128 // Tile size -#define TSH 64 // Half Tile size -#define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } +// multithreaded and partly vectorized by Ingo Weyrich + constexpr int ts = 128; + constexpr int tsh = ts / 2; + //shifts to location of vertical and diagonal neighbors + constexpr int v1 = ts, v2 = 2 * ts, v3 = 3 * ts, v4 = 4 * ts; //, p1=-ts+1, p2=-2*ts+2, p3=-3*ts+3, m1=ts+1, m2=2*ts+2, m3=3*ts+3; // Test for RGB cfa for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) if(FC(i, j) == 3) { - printf("CA correction supports only RGB Color filter arrays\n"); + printf("CA correction supports only RGB Colour filter arrays\n"); return; } @@ -129,328 +141,265 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) plistener->setProgress (progress); } - bool autoCA = (cared == 0 && cablue == 0); + const bool autoCA = (cared == 0 && cablue == 0); // local variables - int width = W, height = H; + const int width = W, height = H; //temporary array to store simple interpolation of G - float (*Gtmp); - Gtmp = (float (*)) calloc ((height) * (width), sizeof * Gtmp); + float *Gtmp = (float (*)) calloc ((height) * (width), sizeof * Gtmp); // temporary array to avoid race conflicts, only every second pixel needs to be saved here - float (*RawDataTmp); - RawDataTmp = (float*) malloc( height * width * sizeof(float) / 2); + float *RawDataTmp = (float*) malloc( (height * width + ((height * width) & 1)) * sizeof(float) / 2); - float blockave[2][3] = {{0, 0, 0}, {0, 0, 0}}, blocksqave[2][3] = {{0, 0, 0}, {0, 0, 0}}, blockdenom[2][3] = {{0, 0, 0}, {0, 0, 0}}, blockvar[2][3]; + float blockave[2][2] = {{0, 0}, {0, 0}}, blocksqave[2][2] = {{0, 0}, {0, 0}}, blockdenom[2][2] = {{0, 0}, {0, 0}}, blockvar[2][2]; // Because we can't break parallel processing, we need a switch do handle the errors bool processpasstwo = true; + constexpr int border = 8; + constexpr int border2 = 16; + + const int vz1 = (height + border2) % (ts - border2) == 0 ? 1 : 0; + const int hz1 = (width + border2) % (ts - border2) == 0 ? 1 : 0; + const int vblsz = ceil((float)(height + border2) / (ts - border2) + 2 + vz1); + const int hblsz = ceil((float)(width + border2) / (ts - border2) + 2 + hz1); + + char *buffer1 = (char *) calloc(vblsz * hblsz * (2 * 2 + 1), sizeof(float)); + //block CA shift values and weight assigned to block - char *buffer1; // vblsz*hblsz*(3*2+1) - float (*blockwt); // vblsz*hblsz - float (*blockshifts)[3][2]; // vblsz*hblsz*3*2 + float *blockwt = (float*)buffer1; + float (*blockshifts)[2][2] = (float (*)[2][2])(buffer1 + (vblsz * hblsz * sizeof(float))); - - const int border = 8; - const int border2 = 16; - - int vz1, hz1; - - if((height + border2) % (TS - border2) == 0) { - vz1 = 1; - } else { - vz1 = 0; - } - - if((width + border2) % (TS - border2) == 0) { - hz1 = 1; - } else { - hz1 = 0; - } - - int vblsz, hblsz; - vblsz = ceil((float)(height + border2) / (TS - border2) + 2 + vz1); - hblsz = ceil((float)(width + border2) / (TS - border2) + 2 + hz1); - - buffer1 = (char *) malloc(vblsz * hblsz * (3 * 2 + 1) * sizeof(float)); - //merror(buffer1,"CA_correct()"); - memset(buffer1, 0, vblsz * hblsz * (3 * 2 + 1)*sizeof(float)); - // block CA shifts - blockwt = (float (*)) (buffer1); - blockshifts = (float (*)[3][2]) (buffer1 + (vblsz * hblsz * sizeof(float))); - - double fitparams[3][2][16]; + double fitparams[2][2][16]; //order of 2d polynomial fit (polyord), and numpar=polyord^2 int polyord = 4, numpar = 16; - #pragma omp parallel shared(Gtmp,width,height,blockave,blocksqave,blockdenom,blockvar,blockwt,blockshifts,fitparams,polyord,numpar) + constexpr float eps = 1e-5f, eps2 = 1e-10f; //tolerance to avoid dividing by zero + + #pragma omp parallel { int progresscounter = 0; - int rrmin, rrmax, ccmin, ccmax; - int top, left, row, col; - int rr, cc, c, indx, indx1, i, j, k, m, n, dir; - //number of pixels in a tile contributing to the CA shift diagnostic - int areawt[2][3]; //direction of the CA shift in a tile int GRBdir[2][3]; - //offset data of the plaquette where the optical R/B data are sampled - int offset[2][3]; + int shifthfloor[3], shiftvfloor[3], shifthceil[3], shiftvceil[3]; - //number of tiles in the image - int vblock, hblock; - //int verbose=1; - //flag indicating success or failure of polynomial fit - int res; - //shifts to location of vertical and diagonal neighbors - const int v1 = TS, v2 = 2 * TS, v3 = 3 * TS, v4 = 4 * TS; //, p1=-TS+1, p2=-2*TS+2, p3=-3*TS+3, m1=TS+1, m2=2*TS+2, m3=3*TS+3; - float eps = 1e-5f, eps2 = 1e-10f; //tolerance to avoid dividing by zero - - //adaptive weights for green interpolation - float wtu, wtd, wtl, wtr; //local quadratic fit to shift data within a tile - float coeff[2][3][3]; + float coeff[2][3][2]; //measured CA shift parameters for a tile - float CAshift[2][3]; + float CAshift[2][2]; //polynomial fit coefficients //residual CA shift amount within a plaquette float shifthfrac[3], shiftvfrac[3]; - //temporary storage for median filter - float temp, p[9]; - //temporary parameters for tile CA evaluation - float gdiff, deltgrb; - //interpolated G at edge of plaquette - float Ginthfloor, Ginthceil, Gint, RBint, gradwt; - //interpolated color difference at edge of plaquette - float grbdiffinthfloor, grbdiffinthceil, grbdiffint, grbdiffold; //per thread data for evaluation of block CA shift variance - float blockavethr[2][3] = {{0, 0, 0}, {0, 0, 0}}, blocksqavethr[2][3] = {{0, 0, 0}, {0, 0, 0}}, blockdenomthr[2][3] = {{0, 0, 0}, {0, 0, 0}}; //, blockvarthr[2][3]; - - //low and high pass 1D filters of G in vertical/horizontal directions - float glpfh, glpfv; - - //max allowed CA shift - const float bslim = 3.99; - //gaussians for low pass filtering of G and R/B - //static const float gaussg[5] = {0.171582, 0.15839, 0.124594, 0.083518, 0.0477063};//sig=2.5 - //static const float gaussrb[3] = {0.332406, 0.241376, 0.0924212};//sig=1.25 - - //block CA shift values and weight assigned to block - - char *buffer; // TS*TS*16 - //rgb data in a tile - float* rgb[3]; - //color differences - float (*grbdiff); // TS*TS*4 - //green interpolated to optical sample points for R/B - float (*gshift); // TS*TS*4 - //high pass filter for R/B in vertical direction - float (*rbhpfh); // TS*TS*4 - //high pass filter for R/B in horizontal direction - float (*rbhpfv); // TS*TS*4 - //low pass filter for R/B in horizontal direction - float (*rblpfh); // TS*TS*4 - //low pass filter for R/B in vertical direction - float (*rblpfv); // TS*TS*4 - //low pass filter for color differences in horizontal direction - float (*grblpfh); // TS*TS*4 - //low pass filter for color differences in vertical direction - float (*grblpfv); // TS*TS*4 - - - /* assign working space; this would not be necessary - if the algorithm is part of the larger pre-interpolation processing */ - buffer = (char *) malloc(3 * sizeof(float) * TS * TS + 8 * sizeof(float) * TS * TSH + 10 * 64 + 64); - //merror(buffer,"CA_correct()"); - memset(buffer, 0, 3 * sizeof(float)*TS * TS + 8 * sizeof(float)*TS * TSH + 10 * 64 + 64); - - char *data; - data = buffer; - -// buffers aligned to size of cacheline -// data = (char*)( ( uintptr_t(buffer) + uintptr_t(63)) / 64 * 64); + float blockavethr[2][2] = {{0, 0}, {0, 0}}, blocksqavethr[2][2] = {{0, 0}, {0, 0}}, blockdenomthr[2][2] = {{0, 0}, {0, 0}}; + // assign working space + constexpr int buffersize = 3 * sizeof(float) * ts * ts + 6 * sizeof(float) * ts * tsh + 8 * 64 + 63; + char *buffer = (char *) malloc(buffersize); + char *data = (char*)( ( uintptr_t(buffer) + uintptr_t(63)) / 64 * 64); // shift the beginning of all arrays but the first by 64 bytes to avoid cache miss conflicts on CPUs which have <=4-way associative L1-Cache - rgb[0] = (float (*)) data; - rgb[1] = (float (*)) (data + 1 * sizeof(float) * TS * TS + 1 * 64); - rgb[2] = (float (*)) (data + 2 * sizeof(float) * TS * TS + 2 * 64); - grbdiff = (float (*)) (data + 3 * sizeof(float) * TS * TS + 3 * 64); - gshift = (float (*)) (data + 3 * sizeof(float) * TS * TS + sizeof(float) * TS * TSH + 4 * 64); - rbhpfh = (float (*)) (data + 4 * sizeof(float) * TS * TS + 5 * 64); - rbhpfv = (float (*)) (data + 4 * sizeof(float) * TS * TS + sizeof(float) * TS * TSH + 6 * 64); - rblpfh = (float (*)) (data + 5 * sizeof(float) * TS * TS + 7 * 64); - rblpfv = (float (*)) (data + 5 * sizeof(float) * TS * TS + sizeof(float) * TS * TSH + 8 * 64); - grblpfh = (float (*)) (data + 6 * sizeof(float) * TS * TS + 9 * 64); - grblpfv = (float (*)) (data + 6 * sizeof(float) * TS * TS + sizeof(float) * TS * TSH + 10 * 64); + + //rgb data in a tile + float* rgb[3]; + rgb[0] = (float (*)) data; + rgb[1] = (float (*)) (data + 1 * sizeof(float) * ts * ts + 1 * 64); + rgb[2] = (float (*)) (data + 2 * sizeof(float) * ts * ts + 2 * 64); + + //high pass filter for R/B in vertical direction + float *rbhpfh = (float (*)) (data + 3 * sizeof(float) * ts * ts + 3 * 64); + //high pass filter for R/B in horizontal direction + float *rbhpfv = (float (*)) (data + 3 * sizeof(float) * ts * ts + sizeof(float) * ts * tsh + 4 * 64); + //low pass filter for R/B in horizontal direction + float *rblpfh = (float (*)) (data + 4 * sizeof(float) * ts * ts + 5 * 64); + //low pass filter for R/B in vertical direction + float *rblpfv = (float (*)) (data + 4 * sizeof(float) * ts * ts + sizeof(float) * ts * tsh + 6 * 64); + //low pass filter for colour differences in horizontal direction + float *grblpfh = (float (*)) (data + 5 * sizeof(float) * ts * ts + 7 * 64); + //low pass filter for colour differences in vertical direction + float *grblpfv = (float (*)) (data + 5 * sizeof(float) * ts * ts + sizeof(float) * ts * tsh + 8 * 64); + //colour differences + float *grbdiff = rbhpfh; // there is no overlap in buffer usage => share + //green interpolated to optical sample points for R/B + float *gshift = rbhpfv; // there is no overlap in buffer usage => share if (autoCA) { - // Main algorithm: Tile loop + // Main algorithm: Tile loop calculating correction parameters per tile #pragma omp for collapse(2) schedule(dynamic) nowait - for (top = -border ; top < height; top += TS - border2) - for (left = -border; left < width; left += TS - border2) { - vblock = ((top + border) / (TS - border2)) + 1; - hblock = ((left + border) / (TS - border2)) + 1; - int bottom = min(top + TS, height + border); - int right = min(left + TS, width + border); - int rr1 = bottom - top; - int cc1 = right - left; - - //t1_init = clock(); - if (top < 0) { - rrmin = border; - } else { - rrmin = 0; - } - - if (left < 0) { - ccmin = border; - } else { - ccmin = 0; - } - - if (bottom > height) { - rrmax = height - top; - } else { - rrmax = rr1; - } - - if (right > width) { - ccmax = width - left; - } else { - ccmax = cc1; - } + for (int top = -border ; top < height; top += ts - border2) + for (int left = -border; left < width; left += ts - border2) { + memset(buffer, 0, buffersize); + const int vblock = ((top + border) / (ts - border2)) + 1; + const int hblock = ((left + border) / (ts - border2)) + 1; + const int bottom = min(top + ts, height + border); + const int right = min(left + ts, width + border); + const int rr1 = bottom - top; + const int cc1 = right - left; + const int rrmin = top < 0 ? border : 0; + const int rrmax = bottom > height ? height - top : rr1; + const int ccmin = left < 0 ? border : 0; + const int ccmax = right > width ? width - left : cc1; // rgb from input CFA data - // rgb values should be floating point number between 0 and 1 + // rgb values should be floating point numbers between 0 and 1 // after white balance multipliers are applied - for (rr = rrmin; rr < rrmax; rr++) - for (row = rr + top, cc = ccmin; cc < ccmax; cc++) { - col = cc + left; - c = FC(rr, cc); - indx = row * width + col; - indx1 = rr * TS + cc; + for (int rr = rrmin; rr < rrmax; rr++) + for (int row = rr + top, cc = ccmin; cc < ccmax; cc++) { + int col = cc + left; + int c = FC(rr, cc); + int indx = row * width + col; + int indx1 = rr * ts + cc; rgb[c][indx1] = (rawData[row][col]) / 65535.0f; - //rgb[indx1][c] = image[indx][c]/65535.0f;//for dcraw implementation } // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //fill borders if (rrmin > 0) { - for (rr = 0; rr < border; rr++) - for (cc = ccmin; cc < ccmax; cc++) { - c = FC(rr, cc); - rgb[c][rr * TS + cc] = rgb[c][(border2 - rr) * TS + cc]; + for (int rr = 0; rr < border; rr++) + for (int cc = ccmin; cc < ccmax; cc++) { + int c = FC(rr, cc); + rgb[c][rr * ts + cc] = rgb[c][(border2 - rr) * ts + cc]; } } if (rrmax < rr1) { - for (rr = 0; rr < border; rr++) - for (cc = ccmin; cc < ccmax; cc++) { - c = FC(rr, cc); - rgb[c][(rrmax + rr)*TS + cc] = (rawData[(height - rr - 2)][left + cc]) / 65535.0f; - //rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+left+cc][c])/65535.0f;//for dcraw implementation + for (int rr = 0; rr < border; rr++) + for (int cc = ccmin; cc < ccmax; cc++) { + int c = FC(rr, cc); + rgb[c][(rrmax + rr)*ts + cc] = (rawData[(height - rr - 2)][left + cc]) / 65535.0f; } } if (ccmin > 0) { - for (rr = rrmin; rr < rrmax; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][rr * TS + cc] = rgb[c][rr * TS + border2 - cc]; + for (int rr = rrmin; rr < rrmax; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][rr * ts + cc] = rgb[c][rr * ts + border2 - cc]; } } if (ccmax < cc1) { - for (rr = rrmin; rr < rrmax; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][rr * TS + ccmax + cc] = (rawData[(top + rr)][(width - cc - 2)]) / 65535.0f; - //rgb[rr*TS+ccmax+cc][c] = (image[(top+rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation + for (int rr = rrmin; rr < rrmax; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][rr * ts + ccmax + cc] = (rawData[(top + rr)][(width - cc - 2)]) / 65535.0f; } } //also, fill the image corners if (rrmin > 0 && ccmin > 0) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rr)*TS + cc] = (rawData[border2 - rr][border2 - cc]) / 65535.0f; - //rgb[(rr)*TS+cc][c] = (rgb[(border2-rr)*TS+(border2-cc)][c]);//for dcraw implementation + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rr)*ts + cc] = (rawData[border2 - rr][border2 - cc]) / 65535.0f; } } if (rrmax < rr1 && ccmax < cc1) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rrmax + rr)*TS + ccmax + cc] = (rawData[(height - rr - 2)][(width - cc - 2)]) / 65535.0f; - //rgb[(rrmax+rr)*TS+ccmax+cc][c] = (image[(height-rr-2)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rrmax + rr)*ts + ccmax + cc] = (rawData[(height - rr - 2)][(width - cc - 2)]) / 65535.0f; } } if (rrmin > 0 && ccmax < cc1) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rr)*TS + ccmax + cc] = (rawData[(border2 - rr)][(width - cc - 2)]) / 65535.0f; - //rgb[(rr)*TS+ccmax+cc][c] = (image[(border2-rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rr)*ts + ccmax + cc] = (rawData[(border2 - rr)][(width - cc - 2)]) / 65535.0f; } } if (rrmax < rr1 && ccmin > 0) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rrmax + rr)*TS + cc] = (rawData[(height - rr - 2)][(border2 - cc)]) / 65535.0f; - //rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+(border2-cc)][c])/65535.0f;//for dcraw implementation + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rrmax + rr)*ts + cc] = (rawData[(height - rr - 2)][(border2 - cc)]) / 65535.0f; } } //end of border fill // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - for (j = 0; j < 2; j++) - for (k = 0; k < 3; k++) - for (c = 0; c < 3; c += 2) { - coeff[j][k][c] = 0; - } - //end of initialization - for (rr = 3; rr < rr1 - 3; rr++) - for (row = rr + top, cc = 3, indx = rr * TS + cc; cc < cc1 - 3; cc++, indx++) { - col = cc + left; - c = FC(rr, cc); +#ifdef __SSE2__ + vfloat onev = F2V(1.f); + vfloat epsv = F2V(eps); +#endif + for (int rr = 3; rr < rr1 - 3; rr++) { + int row = rr + top; + int cc = 3 + (FC(rr,3) & 1); + int indx = rr * ts + cc; + int c = FC(rr,cc); +#ifdef __SSE2__ + for (; cc < cc1 - 9; cc+=8, indx+=8) { + //compute directional weights using image gradients + vfloat wtuv = onev / SQRV(epsv + vabsf(LC2VFU(rgb[1][indx + v1]) - LC2VFU(rgb[1][indx - v1])) + vabsf(LC2VFU(rgb[c][indx]) - LC2VFU(rgb[c][indx - v2])) + vabsf(LC2VFU(rgb[1][indx - v1]) - LC2VFU(rgb[1][indx - v3]))); + vfloat wtdv = onev / SQRV(epsv + vabsf(LC2VFU(rgb[1][indx - v1]) - LC2VFU(rgb[1][indx + v1])) + vabsf(LC2VFU(rgb[c][indx]) - LC2VFU(rgb[c][indx + v2])) + vabsf(LC2VFU(rgb[1][indx + v1]) - LC2VFU(rgb[1][indx + v3]))); + vfloat wtlv = onev / SQRV(epsv + vabsf(LC2VFU(rgb[1][indx + 1]) - LC2VFU(rgb[1][indx - 1])) + vabsf(LC2VFU(rgb[c][indx]) - LC2VFU(rgb[c][indx - 2])) + vabsf(LC2VFU(rgb[1][indx - 1]) - LC2VFU(rgb[1][indx - 3]))); + vfloat wtrv = onev / SQRV(epsv + vabsf(LC2VFU(rgb[1][indx - 1]) - LC2VFU(rgb[1][indx + 1])) + vabsf(LC2VFU(rgb[c][indx]) - LC2VFU(rgb[c][indx + 2])) + vabsf(LC2VFU(rgb[1][indx + 1]) - LC2VFU(rgb[1][indx + 3]))); - if (c != 1) { - //compute directional weights using image gradients - wtu = 1.0 / SQR(eps + fabsf(rgb[1][indx + v1] - rgb[1][indx - v1]) + fabsf(rgb[c][indx] - rgb[c][indx - v2]) + fabsf(rgb[1][indx - v1] - rgb[1][indx - v3])); - wtd = 1.0 / SQR(eps + fabsf(rgb[1][indx - v1] - rgb[1][indx + v1]) + fabsf(rgb[c][indx] - rgb[c][indx + v2]) + fabsf(rgb[1][indx + v1] - rgb[1][indx + v3])); - wtl = 1.0 / SQR(eps + fabsf(rgb[1][indx + 1] - rgb[1][indx - 1]) + fabsf(rgb[c][indx] - rgb[c][indx - 2]) + fabsf(rgb[1][indx - 1] - rgb[1][indx - 3])); - wtr = 1.0 / SQR(eps + fabsf(rgb[1][indx - 1] - rgb[1][indx + 1]) + fabsf(rgb[c][indx] - rgb[c][indx + 2]) + fabsf(rgb[1][indx + 1] - rgb[1][indx + 3])); + //store in rgb array the interpolated G value at R/B grid points using directional weighted average + STC2VFU(rgb[1][indx], (wtuv * LC2VFU(rgb[1][indx - v1]) + wtdv * LC2VFU(rgb[1][indx + v1]) + wtlv * LC2VFU(rgb[1][indx - 1]) + wtrv * LC2VFU(rgb[1][indx + 1])) / (wtuv + wtdv + wtlv + wtrv)); + } - //store in rgb array the interpolated G value at R/B grid points using directional weighted average - rgb[1][indx] = (wtu * rgb[1][indx - v1] + wtd * rgb[1][indx + v1] + wtl * rgb[1][indx - 1] + wtr * rgb[1][indx + 1]) / (wtu + wtd + wtl + wtr); - } +#endif + for (; cc < cc1 - 3; cc+=2, indx+=2) { + //compute directional weights using image gradients + float wtu = 1.f / SQR(eps + fabsf(rgb[1][indx + v1] - rgb[1][indx - v1]) + fabsf(rgb[c][indx] - rgb[c][indx - v2]) + fabsf(rgb[1][indx - v1] - rgb[1][indx - v3])); + float wtd = 1.f / SQR(eps + fabsf(rgb[1][indx - v1] - rgb[1][indx + v1]) + fabsf(rgb[c][indx] - rgb[c][indx + v2]) + fabsf(rgb[1][indx + v1] - rgb[1][indx + v3])); + float wtl = 1.f / SQR(eps + fabsf(rgb[1][indx + 1] - rgb[1][indx - 1]) + fabsf(rgb[c][indx] - rgb[c][indx - 2]) + fabsf(rgb[1][indx - 1] - rgb[1][indx - 3])); + float wtr = 1.f / SQR(eps + fabsf(rgb[1][indx - 1] - rgb[1][indx + 1]) + fabsf(rgb[c][indx] - rgb[c][indx + 2]) + fabsf(rgb[1][indx + 1] - rgb[1][indx + 3])); - if (row > -1 && row < height && col > -1 && col < width) { + //store in rgb array the interpolated G value at R/B grid points using directional weighted average + rgb[1][indx] = (wtu * rgb[1][indx - v1] + wtd * rgb[1][indx + v1] + wtl * rgb[1][indx - 1] + wtr * rgb[1][indx + 1]) / (wtu + wtd + wtl + wtr); + } + + if (row > -1 && row < height) { + for(int col = max(left + 3, 0), indx = rr * ts + 3 - (left < 0 ? (left+3) : 0); col < min(cc1 + left - 3, width); col++, indx++) { Gtmp[row * width + col] = rgb[1][indx]; } } + } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#ifdef __SSE2__ + vfloat zd25v = F2V(0.25f); +#endif + for (int rr = 4; rr < rr1 - 4; rr++) { + int cc = 4 + (FC(rr, 2) & 1), indx = rr * ts + cc, c = FC(rr, cc); +#ifdef __SSE2__ + for (; cc < cc1 - 10; cc += 8, indx += 8) { + vfloat rgb1v = LC2VFU(rgb[1][indx]); + vfloat rgbcv = LC2VFU(rgb[c][indx]); + vfloat temp1v = vabsf(vabsf((rgb1v - rgbcv) - (LC2VFU(rgb[1][indx + v4]) - LC2VFU(rgb[c][indx + v4]))) + + vabsf(LC2VFU(rgb[1][indx - v4]) - LC2VFU(rgb[c][indx - v4]) - rgb1v + rgbcv) - + vabsf(LC2VFU(rgb[1][indx - v4]) - LC2VFU(rgb[c][indx - v4]) - LC2VFU(rgb[1][indx + v4]) + LC2VFU(rgb[c][indx + v4]))); + STVFU(rbhpfv[indx >> 1], temp1v); + vfloat temp2v = vabsf(vabsf((rgb1v - rgbcv) - (LC2VFU(rgb[1][indx + 4]) - LC2VFU(rgb[c][indx + 4]))) + + vabsf(LC2VFU(rgb[1][indx - 4]) - LC2VFU(rgb[c][indx - 4]) - rgb1v + rgbcv) - + vabsf(LC2VFU(rgb[1][indx - 4]) - LC2VFU(rgb[c][indx - 4]) - LC2VFU(rgb[1][indx + 4]) + LC2VFU(rgb[c][indx + 4]))); + STVFU(rbhpfh[indx >> 1], temp2v); - for (rr = 4; rr < rr1 - 4; rr++) - for (cc = 4 + (FC(rr, 2) & 1), indx = rr * TS + cc, c = FC(rr, cc); cc < cc1 - 4; cc += 2, indx += 2) { - + //low and high pass 1D filters of G in vertical/horizontal directions + rgb1v = vmul2f(rgb1v); + vfloat glpfvv = zd25v * (rgb1v + LC2VFU(rgb[1][indx + v2]) + LC2VFU(rgb[1][indx - v2])); + vfloat glpfhv = zd25v * (rgb1v + LC2VFU(rgb[1][indx + 2]) + LC2VFU(rgb[1][indx - 2])); + rgbcv = vmul2f(rgbcv); + STVFU(rblpfv[indx >> 1], epsv + vabsf(glpfvv - zd25v * (rgbcv + LC2VFU(rgb[c][indx + v2]) + LC2VFU(rgb[c][indx - v2])))); + STVFU(rblpfh[indx >> 1], epsv + vabsf(glpfhv - zd25v * (rgbcv + LC2VFU(rgb[c][indx + 2]) + LC2VFU(rgb[c][indx - 2])))); + STVFU(grblpfv[indx >> 1], glpfvv + zd25v * (rgbcv + LC2VFU(rgb[c][indx + v2]) + LC2VFU(rgb[c][indx - v2]))); + STVFU(grblpfh[indx >> 1], glpfhv + zd25v * (rgbcv + LC2VFU(rgb[c][indx + 2]) + LC2VFU(rgb[c][indx - 2]))); + } +#endif + for (; cc < cc1 - 4; cc += 2, indx += 2) { rbhpfv[indx >> 1] = fabsf(fabsf((rgb[1][indx] - rgb[c][indx]) - (rgb[1][indx + v4] - rgb[c][indx + v4])) + fabsf((rgb[1][indx - v4] - rgb[c][indx - v4]) - (rgb[1][indx] - rgb[c][indx])) - fabsf((rgb[1][indx - v4] - rgb[c][indx - v4]) - (rgb[1][indx + v4] - rgb[c][indx + v4]))); @@ -458,176 +407,148 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) fabsf((rgb[1][indx - 4] - rgb[c][indx - 4]) - (rgb[1][indx] - rgb[c][indx])) - fabsf((rgb[1][indx - 4] - rgb[c][indx - 4]) - (rgb[1][indx + 4] - rgb[c][indx + 4]))); - /*ghpfv = fabsf(fabsf(rgb[indx][1]-rgb[indx+v4][1])+fabsf(rgb[indx][1]-rgb[indx-v4][1]) - - fabsf(rgb[indx+v4][1]-rgb[indx-v4][1])); - ghpfh = fabsf(fabsf(rgb[indx][1]-rgb[indx+4][1])+fabsf(rgb[indx][1]-rgb[indx-4][1]) - - fabsf(rgb[indx+4][1]-rgb[indx-4][1])); - rbhpfv[indx] = fabsf(ghpfv - fabsf(fabsf(rgb[indx][c]-rgb[indx+v4][c])+fabsf(rgb[indx][c]-rgb[indx-v4][c]) - - fabsf(rgb[indx+v4][c]-rgb[indx-v4][c]))); - rbhpfh[indx] = fabsf(ghpfh - fabsf(fabsf(rgb[indx][c]-rgb[indx+4][c])+fabsf(rgb[indx][c]-rgb[indx-4][c]) - - fabsf(rgb[indx+4][c]-rgb[indx-4][c])));*/ - - glpfv = 0.25 * (2.0 * rgb[1][indx] + rgb[1][indx + v2] + rgb[1][indx - v2]); - glpfh = 0.25 * (2.0 * rgb[1][indx] + rgb[1][indx + 2] + rgb[1][indx - 2]); - rblpfv[indx >> 1] = eps + fabsf(glpfv - 0.25 * (2.0 * rgb[c][indx] + rgb[c][indx + v2] + rgb[c][indx - v2])); - rblpfh[indx >> 1] = eps + fabsf(glpfh - 0.25 * (2.0 * rgb[c][indx] + rgb[c][indx + 2] + rgb[c][indx - 2])); - grblpfv[indx >> 1] = glpfv + 0.25 * (2.0 * rgb[c][indx] + rgb[c][indx + v2] + rgb[c][indx - v2]); - grblpfh[indx >> 1] = glpfh + 0.25 * (2.0 * rgb[c][indx] + rgb[c][indx + 2] + rgb[c][indx - 2]); + //low and high pass 1D filters of G in vertical/horizontal directions + float glpfv = 0.25f * (2.f * rgb[1][indx] + rgb[1][indx + v2] + rgb[1][indx - v2]); + float glpfh = 0.25f * (2.f * rgb[1][indx] + rgb[1][indx + 2] + rgb[1][indx - 2]); + rblpfv[indx >> 1] = eps + fabsf(glpfv - 0.25f * (2.f * rgb[c][indx] + rgb[c][indx + v2] + rgb[c][indx - v2])); + rblpfh[indx >> 1] = eps + fabsf(glpfh - 0.25f * (2.f * rgb[c][indx] + rgb[c][indx + 2] + rgb[c][indx - 2])); + grblpfv[indx >> 1] = glpfv + 0.25f * (2.f * rgb[c][indx] + rgb[c][indx + v2] + rgb[c][indx - v2]); + grblpfh[indx >> 1] = glpfh + 0.25f * (2.f * rgb[c][indx] + rgb[c][indx + 2] + rgb[c][indx - 2]); } + } - areawt[0][0] = areawt[1][0] = 1; - areawt[0][2] = areawt[1][2] = 1; + for (int dir = 0; dir < 2; dir++) { + for (int k = 0; k < 3; k++) { + for (int c = 0; c < 2; c++) { + coeff[dir][k][c] = 0; + } + } + } - // along line segments, find the point along each segment that minimizes the color variance +#ifdef __SSE2__ + vfloat zd3125v = F2V(0.3125f); + vfloat zd09375v = F2V(0.09375f); + vfloat zd1v = F2V(0.1f); + vfloat zd125v = F2V(0.125f); +#endif + + // along line segments, find the point along each segment that minimizes the colour variance // averaged over the tile; evaluate for up/down and left/right away from R/B grid point - for (rr = 8; rr < rr1 - 8; rr++) - for (cc = 8 + (FC(rr, 2) & 1), indx = rr * TS + cc, c = FC(rr, cc); cc < cc1 - 8; cc += 2, indx += 2) { + for (int rr = 8; rr < rr1 - 8; rr++) { + int cc = 8 + (FC(rr, 2) & 1); + int indx = rr * ts + cc; + int c = FC(rr, cc); +#ifdef __SSE2__ + vfloat coeff00v = ZEROV; + vfloat coeff01v = ZEROV; + vfloat coeff02v = ZEROV; + vfloat coeff10v = ZEROV; + vfloat coeff11v = ZEROV; + vfloat coeff12v = ZEROV; + for (; cc < cc1 - 14; cc += 8, indx += 8) { -// areawt[0][c]=areawt[1][c]=0; - - //in linear interpolation, color differences are a quadratic function of interpolation position; - //solve for the interpolation position that minimizes color difference variance over the tile + //in linear interpolation, colour differences are a quadratic function of interpolation position; + //solve for the interpolation position that minimizes colour difference variance over the tile //vertical - gdiff = 0.3125 * (rgb[1][indx + TS] - rgb[1][indx - TS]) + 0.09375 * (rgb[1][indx + TS + 1] - rgb[1][indx - TS + 1] + rgb[1][indx + TS - 1] - rgb[1][indx - TS - 1]); - deltgrb = (rgb[c][indx] - rgb[1][indx]); + vfloat gdiffv = zd3125v * (LC2VFU(rgb[1][indx + ts]) - LC2VFU(rgb[1][indx - ts])) + zd09375v * (LC2VFU(rgb[1][indx + ts + 1]) - LC2VFU(rgb[1][indx - ts + 1]) + LC2VFU(rgb[1][indx + ts - 1]) - LC2VFU(rgb[1][indx - ts - 1])); + vfloat deltgrbv = LC2VFU(rgb[c][indx]) - LC2VFU(rgb[1][indx]); - gradwt = fabsf(0.25 * rbhpfv[indx >> 1] + 0.125 * (rbhpfv[(indx >> 1) + 1] + rbhpfv[(indx >> 1) - 1]) ) * (grblpfv[(indx >> 1) - v1] + grblpfv[(indx >> 1) + v1]) / (eps + 0.1 * grblpfv[(indx >> 1) - v1] + rblpfv[(indx >> 1) - v1] + 0.1 * grblpfv[(indx >> 1) + v1] + rblpfv[(indx >> 1) + v1]); + vfloat gradwtv = vabsf(zd25v * LVFU(rbhpfv[indx >> 1]) + zd125v * (LVFU(rbhpfv[(indx >> 1) + 1]) + LVFU(rbhpfv[(indx >> 1) - 1])) ) * (LVFU(grblpfv[(indx >> 1) - v1]) + LVFU(grblpfv[(indx >> 1) + v1])) / (epsv + zd1v * (LVFU(grblpfv[(indx >> 1) - v1]) + LVFU(grblpfv[(indx >> 1) + v1])) + LVFU(rblpfv[(indx >> 1) - v1]) + LVFU(rblpfv[(indx >> 1) + v1])); - coeff[0][0][c] += gradwt * deltgrb * deltgrb; - coeff[0][1][c] += gradwt * gdiff * deltgrb; - coeff[0][2][c] += gradwt * gdiff * gdiff; -// areawt[0][c]+=1; + coeff00v += gradwtv * deltgrbv * deltgrbv; + coeff01v += gradwtv * gdiffv * deltgrbv; + coeff02v += gradwtv * gdiffv * gdiffv; //horizontal - gdiff = 0.3125 * (rgb[1][indx + 1] - rgb[1][indx - 1]) + 0.09375 * (rgb[1][indx + 1 + TS] - rgb[1][indx - 1 + TS] + rgb[1][indx + 1 - TS] - rgb[1][indx - 1 - TS]); - deltgrb = (rgb[c][indx] - rgb[1][indx]); + gdiffv = zd3125v * (LC2VFU(rgb[1][indx + 1]) - LC2VFU(rgb[1][indx - 1])) + zd09375v * (LC2VFU(rgb[1][indx + 1 + ts]) - LC2VFU(rgb[1][indx - 1 + ts]) + LC2VFU(rgb[1][indx + 1 - ts]) - LC2VFU(rgb[1][indx - 1 - ts])); - gradwt = fabsf(0.25 * rbhpfh[indx >> 1] + 0.125 * (rbhpfh[(indx >> 1) + v1] + rbhpfh[(indx >> 1) - v1]) ) * (grblpfh[(indx >> 1) - 1] + grblpfh[(indx >> 1) + 1]) / (eps + 0.1 * grblpfh[(indx >> 1) - 1] + rblpfh[(indx >> 1) - 1] + 0.1 * grblpfh[(indx >> 1) + 1] + rblpfh[(indx >> 1) + 1]); + gradwtv = vabsf(zd25v * LVFU(rbhpfh[indx >> 1]) + zd125v * (LVFU(rbhpfh[(indx >> 1) + v1]) + LVFU(rbhpfh[(indx >> 1) - v1])) ) * (LVFU(grblpfh[(indx >> 1) - 1]) + LVFU(grblpfh[(indx >> 1) + 1])) / (epsv + zd1v * (LVFU(grblpfh[(indx >> 1) - 1]) + LVFU(grblpfh[(indx >> 1) + 1])) + LVFU(rblpfh[(indx >> 1) - 1]) + LVFU(rblpfh[(indx >> 1) + 1])); - coeff[1][0][c] += gradwt * deltgrb * deltgrb; - coeff[1][1][c] += gradwt * gdiff * deltgrb; - coeff[1][2][c] += gradwt * gdiff * gdiff; -// areawt[1][c]+=1; + coeff10v += gradwtv * deltgrbv * deltgrbv; + coeff11v += gradwtv * gdiffv * deltgrbv; + coeff12v += gradwtv * gdiffv * gdiffv; // In Mathematica, // f[x_]=Expand[Total[Flatten[ // ((1-x) RotateLeft[Gint,shift1]+x RotateLeft[Gint,shift2]-cfapad)^2[[dv;;-1;;2,dh;;-1;;2]]]]]; // extremum = -.5Coefficient[f[x],x]/Coefficient[f[x],x^2] } + coeff[0][0][c>>1] += vhadd(coeff00v); + coeff[0][1][c>>1] += vhadd(coeff01v); + coeff[0][2][c>>1] += vhadd(coeff02v); + coeff[1][0][c>>1] += vhadd(coeff10v); + coeff[1][1][c>>1] += vhadd(coeff11v); + coeff[1][2][c>>1] += vhadd(coeff12v); - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - /* - for (rr=4; rr < rr1-4; rr++) - for (cc=4+(FC(rr,2)&1), indx=rr*TS+cc, c = FC(rr,cc); cc < cc1-4; cc+=2, indx+=2) { +#endif + for (; cc < cc1 - 8; cc += 2, indx += 2) { - - rbhpfv[indx] = SQR(fabs((rgb[indx][1]-rgb[indx][c])-(rgb[indx+v4][1]-rgb[indx+v4][c])) + - fabs((rgb[indx-v4][1]-rgb[indx-v4][c])-(rgb[indx][1]-rgb[indx][c])) - - fabs((rgb[indx-v4][1]-rgb[indx-v4][c])-(rgb[indx+v4][1]-rgb[indx+v4][c]))); - rbhpfh[indx] = SQR(fabs((rgb[indx][1]-rgb[indx][c])-(rgb[indx+4][1]-rgb[indx+4][c])) + - fabs((rgb[indx-4][1]-rgb[indx-4][c])-(rgb[indx][1]-rgb[indx][c])) - - fabs((rgb[indx-4][1]-rgb[indx-4][c])-(rgb[indx+4][1]-rgb[indx+4][c]))); - - - glpfv = 0.25*(2*rgb[indx][1]+rgb[indx+v2][1]+rgb[indx-v2][1]); - glpfh = 0.25*(2*rgb[indx][1]+rgb[indx+2][1]+rgb[indx-2][1]); - rblpfv[indx] = eps+fabs(glpfv - 0.25*(2*rgb[indx][c]+rgb[indx+v2][c]+rgb[indx-v2][c])); - rblpfh[indx] = eps+fabs(glpfh - 0.25*(2*rgb[indx][c]+rgb[indx+2][c]+rgb[indx-2][c])); - grblpfv[indx] = glpfv + 0.25*(2*rgb[indx][c]+rgb[indx+v2][c]+rgb[indx-v2][c]); - grblpfh[indx] = glpfh + 0.25*(2*rgb[indx][c]+rgb[indx+2][c]+rgb[indx-2][c]); - } - - for (c=0;c<3;c++) {areawt[0][c]=areawt[1][c]=0;} - - // along line segments, find the point along each segment that minimizes the color variance - // averaged over the tile; evaluate for up/down and left/right away from R/B grid point - for (rr=rrmin+8; rr < rrmax-8; rr++) - for (cc=ccmin+8+(FC(rr,2)&1), indx=rr*TS+cc, c = FC(rr,cc); cc < ccmax-8; cc+=2, indx+=2) { - - if (rgb[indx][c]>0.8*clip_pt || Gtmp[indx]>0.8*clip_pt) continue; - - //in linear interpolation, color differences are a quadratic function of interpolation position; - //solve for the interpolation position that minimizes color difference variance over the tile + //in linear interpolation, colour differences are a quadratic function of interpolation position; + //solve for the interpolation position that minimizes colour difference variance over the tile //vertical - gdiff=0.3125*(rgb[indx+TS][1]-rgb[indx-TS][1])+0.09375*(rgb[indx+TS+1][1]-rgb[indx-TS+1][1]+rgb[indx+TS-1][1]-rgb[indx-TS-1][1]); - deltgrb=(rgb[indx][c]-rgb[indx][1])-0.5*((rgb[indx-v4][c]-rgb[indx-v4][1])+(rgb[indx+v4][c]-rgb[indx+v4][1])); + float gdiff = 0.3125f * (rgb[1][indx + ts] - rgb[1][indx - ts]) + 0.09375f * (rgb[1][indx + ts + 1] - rgb[1][indx - ts + 1] + rgb[1][indx + ts - 1] - rgb[1][indx - ts - 1]); + float deltgrb = (rgb[c][indx] - rgb[1][indx]); - gradwt=fabs(0.25*rbhpfv[indx]+0.125*(rbhpfv[indx+2]+rbhpfv[indx-2]) );// *(grblpfv[indx-v2]+grblpfv[indx+v2])/(eps+0.1*grblpfv[indx-v2]+rblpfv[indx-v2]+0.1*grblpfv[indx+v2]+rblpfv[indx+v2]); - if (gradwt>eps) { - coeff[0][0][c] += gradwt*deltgrb*deltgrb; - coeff[0][1][c] += gradwt*gdiff*deltgrb; - coeff[0][2][c] += gradwt*gdiff*gdiff; - areawt[0][c]++; - } + float gradwt = fabsf(0.25f * rbhpfv[indx >> 1] + 0.125f * (rbhpfv[(indx >> 1) + 1] + rbhpfv[(indx >> 1) - 1]) ) * (grblpfv[(indx >> 1) - v1] + grblpfv[(indx >> 1) + v1]) / (eps + 0.1f * (grblpfv[(indx >> 1) - v1] + grblpfv[(indx >> 1) + v1]) + rblpfv[(indx >> 1) - v1] + rblpfv[(indx >> 1) + v1]); + + coeff[0][0][c>>1] += gradwt * deltgrb * deltgrb; + coeff[0][1][c>>1] += gradwt * gdiff * deltgrb; + coeff[0][2][c>>1] += gradwt * gdiff * gdiff; //horizontal - gdiff=0.3125*(rgb[indx+1][1]-rgb[indx-1][1])+0.09375*(rgb[indx+1+TS][1]-rgb[indx-1+TS][1]+rgb[indx+1-TS][1]-rgb[indx-1-TS][1]); - deltgrb=(rgb[indx][c]-rgb[indx][1])-0.5*((rgb[indx-4][c]-rgb[indx-4][1])+(rgb[indx+4][c]-rgb[indx+4][1])); + gdiff = 0.3125f * (rgb[1][indx + 1] - rgb[1][indx - 1]) + 0.09375f * (rgb[1][indx + 1 + ts] - rgb[1][indx - 1 + ts] + rgb[1][indx + 1 - ts] - rgb[1][indx - 1 - ts]); - gradwt=fabs(0.25*rbhpfh[indx]+0.125*(rbhpfh[indx+v2]+rbhpfh[indx-v2]) );// *(grblpfh[indx-2]+grblpfh[indx+2])/(eps+0.1*grblpfh[indx-2]+rblpfh[indx-2]+0.1*grblpfh[indx+2]+rblpfh[indx+2]); - if (gradwt>eps) { - coeff[1][0][c] += gradwt*deltgrb*deltgrb; - coeff[1][1][c] += gradwt*gdiff*deltgrb; - coeff[1][2][c] += gradwt*gdiff*gdiff; - areawt[1][c]++; - } + gradwt = fabsf(0.25f * rbhpfh[indx >> 1] + 0.125f * (rbhpfh[(indx >> 1) + v1] + rbhpfh[(indx >> 1) - v1]) ) * (grblpfh[(indx >> 1) - 1] + grblpfh[(indx >> 1) + 1]) / (eps + 0.1f * (grblpfh[(indx >> 1) - 1] + grblpfh[(indx >> 1) + 1]) + rblpfh[(indx >> 1) - 1] + rblpfh[(indx >> 1) + 1]); + + coeff[1][0][c>>1] += gradwt * deltgrb * deltgrb; + coeff[1][1][c>>1] += gradwt * gdiff * deltgrb; + coeff[1][2][c>>1] += gradwt * gdiff * gdiff; // In Mathematica, // f[x_]=Expand[Total[Flatten[ // ((1-x) RotateLeft[Gint,shift1]+x RotateLeft[Gint,shift2]-cfapad)^2[[dv;;-1;;2,dh;;-1;;2]]]]]; // extremum = -.5Coefficient[f[x],x]/Coefficient[f[x],x^2] - }*/ - for (c = 0; c < 3; c += 2) { - for (j = 0; j < 2; j++) { // vert/hor - //printf("hblock %d vblock %d j %d c %d areawt %d \n",hblock,vblock,j,c,areawt[j][c]); - //printf("hblock %d vblock %d j %d c %d areawt %d ",hblock,vblock,j,c,areawt[j][c]); + } + } - if (areawt[j][c] > 0 && coeff[j][2][c] > eps2) { - CAshift[j][c] = coeff[j][1][c] / coeff[j][2][c]; - blockwt[vblock * hblsz + hblock] = areawt[j][c] * coeff[j][2][c] / (eps + coeff[j][0][c]) ; + for (int c = 0; c < 2; c++) { + for (int dir = 0; dir < 2; dir++) { // vert/hor + + // CAshift[dir][c] are the locations + // that minimize colour difference variances; + // This is the approximate _optical_ location of the R/B pixels + if (coeff[dir][2][c] > eps2) { + CAshift[dir][c] = coeff[dir][1][c] / coeff[dir][2][c]; + blockwt[vblock * hblsz + hblock] = coeff[dir][2][c] / (eps + coeff[dir][0][c]) ; } else { - CAshift[j][c] = 17.0; + CAshift[dir][c] = 17.0; blockwt[vblock * hblsz + hblock] = 0; } - //if (c==0 && j==0) printf("vblock= %d hblock= %d denom= %f areawt= %d \n",vblock,hblock,coeff[j][2][c],areawt[j][c]); + //data structure = CAshift[vert/hor][colour] + //dir : 0=vert, 1=hor - //printf("%f \n",CAshift[j][c]); - - //data structure = CAshift[vert/hor][color] - //j=0=vert, 1=hor - - //offset gives NW corner of square containing the min; j=0=vert, 1=hor - - if (fabsf(CAshift[j][c]) < 2.0f) { - blockavethr[j][c] += CAshift[j][c]; - blocksqavethr[j][c] += SQR(CAshift[j][c]); - blockdenomthr[j][c] += 1; + //offset gives NW corner of square containing the min; dir : 0=vert, 1=hor + if (fabsf(CAshift[dir][c]) < 2.0f) { + blockavethr[dir][c] += CAshift[dir][c]; + blocksqavethr[dir][c] += SQR(CAshift[dir][c]); + blockdenomthr[dir][c] += 1; } + //evaluate the shifts to the location that minimizes CA within the tile + blockshifts[vblock * hblsz + hblock][c][dir] = CAshift[dir][c]; //vert/hor CA shift for R/B + }//vert/hor - }//color - - /* CAshift[j][c] are the locations - that minimize color difference variances; - This is the approximate _optical_ location of the R/B pixels */ - - for (c = 0; c < 3; c += 2) { - //evaluate the shifts to the location that minimizes CA within the tile - blockshifts[(vblock)*hblsz + hblock][c][0] = (CAshift[0][c]); //vert CA shift for R/B - blockshifts[(vblock)*hblsz + hblock][c][1] = (CAshift[1][c]); //hor CA shift for R/B - //data structure: blockshifts[blocknum][R/B][v/h] - //if (c==0) printf("vblock= %d hblock= %d blockshiftsmedian= %f \n",vblock,hblock,blockshifts[(vblock)*hblsz+hblock][c][0]); - } + }//colour if(plistener) { progresscounter++; if(progresscounter % 8 == 0) - #pragma omp critical + #pragma omp critical (cadetectpass1) { - progress += (double)(8.0 * (TS - border2) * (TS - border2)) / (2 * height * width); + progress += (double)(8.0 * (ts - border2) * (ts - border2)) / (2 * height * width); if (progress > 1.0) { progress = 1.0; @@ -640,23 +561,23 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) } //end of diagnostic pass - #pragma omp critical + #pragma omp critical (cadetectpass2) { - for (j = 0; j < 2; j++) - for (c = 0; c < 3; c += 2) { - blockdenom[j][c] += blockdenomthr[j][c]; - blocksqave[j][c] += blocksqavethr[j][c]; - blockave[j][c] += blockavethr[j][c]; + for (int dir = 0; dir < 2; dir++) + for (int c = 0; c < 2; c++) { + blockdenom[dir][c] += blockdenomthr[dir][c]; + blocksqave[dir][c] += blocksqavethr[dir][c]; + blockave[dir][c] += blockavethr[dir][c]; } } #pragma omp barrier #pragma omp single { - for (j = 0; j < 2; j++) - for (c = 0; c < 3; c += 2) { - if (blockdenom[j][c]) { - blockvar[j][c] = blocksqave[j][c] / blockdenom[j][c] - SQR(blockave[j][c] / blockdenom[j][c]); + for (int dir = 0; dir < 2; dir++) + for (int c = 0; c < 2; c++) { + if (blockdenom[dir][c]) { + blockvar[dir][c] = blocksqave[dir][c] / blockdenom[dir][c] - SQR(blockave[dir][c] / blockdenom[dir][c]); } else { processpasstwo = false; printf ("blockdenom vanishes \n"); @@ -664,26 +585,23 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) } } - //printf ("tile variances %f %f %f %f \n",blockvar[0][0],blockvar[1][0],blockvar[0][2],blockvar[1][2] ); - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //now prepare for CA correction pass //first, fill border blocks of blockshift array if(processpasstwo) { - for (vblock = 1; vblock < vblsz - 1; vblock++) { //left and right sides - for (c = 0; c < 3; c += 2) { - for (i = 0; i < 2; i++) { + for (int vblock = 1; vblock < vblsz - 1; vblock++) { //left and right sides + for (int c = 0; c < 2; c++) { + for (int i = 0; i < 2; i++) { blockshifts[vblock * hblsz][c][i] = blockshifts[(vblock) * hblsz + 2][c][i]; blockshifts[vblock * hblsz + hblsz - 1][c][i] = blockshifts[(vblock) * hblsz + hblsz - 3][c][i]; } } } - for (hblock = 0; hblock < hblsz; hblock++) { //top and bottom sides - for (c = 0; c < 3; c += 2) { - for (i = 0; i < 2; i++) { + for (int hblock = 0; hblock < hblsz; hblock++) { //top and bottom sides + for (int c = 0; c < 2; c++) { + for (int i = 0; i < 2; i++) { blockshifts[hblock][c][i] = blockshifts[2 * hblsz + hblock][c][i]; blockshifts[(vblsz - 1)*hblsz + hblock][c][i] = blockshifts[(vblsz - 3) * hblsz + hblock][c][i]; } @@ -693,25 +611,26 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) //end of filling border pixels of blockshift array //initialize fit arrays - double polymat[3][2][256], shiftmat[3][2][16]; + double polymat[2][2][256], shiftmat[2][2][16]; - for (i = 0; i < 256; i++) { - polymat[0][0][i] = polymat[0][1][i] = polymat[2][0][i] = polymat[2][1][i] = 0; + for (int i = 0; i < 256; i++) { + polymat[0][0][i] = polymat[0][1][i] = polymat[1][0][i] = polymat[1][1][i] = 0; } - for (i = 0; i < 16; i++) { - shiftmat[0][0][i] = shiftmat[0][1][i] = shiftmat[2][0][i] = shiftmat[2][1][i] = 0; + for (int i = 0; i < 16; i++) { + shiftmat[0][0][i] = shiftmat[0][1][i] = shiftmat[1][0][i] = shiftmat[1][1][i] = 0; } - int numblox[3] = {0, 0, 0}; + int numblox[2] = {0, 0}; - float bstemp[2]; - - for (vblock = 1; vblock < vblsz - 1; vblock++) - for (hblock = 1; hblock < hblsz - 1; hblock++) { + for (int vblock = 1; vblock < vblsz - 1; vblock++) + for (int hblock = 1; hblock < hblsz - 1; hblock++) { // block 3x3 median of blockshifts for robustness - for (c = 0; c < 3; c += 2) { - for (dir = 0; dir < 2; dir++) { + for (int c = 0; c < 2; c ++) { + float bstemp[2]; + for (int dir = 0; dir < 2; dir++) { + //temporary storage for median filter + float p[9]; p[0] = blockshifts[(vblock - 1) * hblsz + hblock - 1][c][dir]; p[1] = blockshifts[(vblock - 1) * hblsz + hblock][c][dir]; p[2] = blockshifts[(vblock - 1) * hblsz + hblock + 1][c][dir]; @@ -721,57 +640,59 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) p[6] = blockshifts[(vblock + 1) * hblsz + hblock - 1][c][dir]; p[7] = blockshifts[(vblock + 1) * hblsz + hblock][c][dir]; p[8] = blockshifts[(vblock + 1) * hblsz + hblock + 1][c][dir]; - PIX_SORT(p[1], p[2]); - PIX_SORT(p[4], p[5]); - PIX_SORT(p[7], p[8]); - PIX_SORT(p[0], p[1]); - PIX_SORT(p[3], p[4]); - PIX_SORT(p[6], p[7]); - PIX_SORT(p[1], p[2]); - PIX_SORT(p[4], p[5]); - PIX_SORT(p[7], p[8]); - PIX_SORT(p[0], p[3]); - PIX_SORT(p[5], p[8]); - PIX_SORT(p[4], p[7]); - PIX_SORT(p[3], p[6]); - PIX_SORT(p[1], p[4]); - PIX_SORT(p[2], p[5]); - PIX_SORT(p[4], p[7]); - PIX_SORT(p[4], p[2]); - PIX_SORT(p[6], p[4]); - PIX_SORT(p[4], p[2]); + pixSort(p[1], p[2]); + pixSort(p[4], p[5]); + pixSort(p[7], p[8]); + pixSort(p[0], p[1]); + pixSort(p[3], p[4]); + pixSort(p[6], p[7]); + pixSort(p[1], p[2]); + pixSort(p[4], p[5]); + pixSort(p[7], p[8]); + pixSort(p[0], p[3]); + pixSort(p[5], p[8]); + pixSort(p[4], p[7]); + pixSort(p[3], p[6]); + pixSort(p[1], p[4]); + pixSort(p[2], p[5]); + pixSort(p[4], p[7]); + pixSort(p[4], p[2]); + pixSort(p[6], p[4]); + pixSort(p[4], p[2]); bstemp[dir] = p[4]; - //if (c==0 && dir==0) printf("vblock= %d hblock= %d blockshiftsmedian= %f \n",vblock,hblock,p[4]); } - //if (verbose) fprintf (stderr,_("tile vshift hshift (%d %d %4f %4f)...\n"),vblock, hblock, blockshifts[(vblock)*hblsz+hblock][c][0], blockshifts[(vblock)*hblsz+hblock][c][1]); - - //now prepare coefficient matrix; use only data points within two std devs of zero - if (SQR(bstemp[0]) > 4.0 * blockvar[0][c] || SQR(bstemp[1]) > 4.0 * blockvar[1][c]) { + //now prepare coefficient matrix; use only data points within caautostrength/2 std devs of zero + if (SQR(bstemp[0]) > caautostrength * blockvar[0][c] || SQR(bstemp[1]) > caautostrength * blockvar[1][c]) { continue; } numblox[c]++; - for (dir = 0; dir < 2; dir++) { - for (i = 0; i < polyord; i++) { - for (j = 0; j < polyord; j++) { - for (m = 0; m < polyord; m++) - for (n = 0; n < polyord; n++) { - polymat[c][dir][numpar * (polyord * i + j) + (polyord * m + n)] += (float)pow((double)vblock, i + m) * pow((double)hblock, j + n) * blockwt[vblock * hblsz + hblock]; + for (int dir = 0; dir < 2; dir++) { + double powVblockInit = 1.0; + for (int i = 0; i < polyord; i++) { + double powHblockInit = 1.0; + for (int j = 0; j < polyord; j++) { + double powVblock = powVblockInit; + for (int m = 0; m < polyord; m++) { + double powHblock = powHblockInit; + for (int n = 0; n < polyord; n++) { + polymat[c][dir][numpar * (polyord * i + j) + (polyord * m + n)] += powVblock * powHblock * blockwt[vblock * hblsz + hblock]; + powHblock *= hblock; } - - shiftmat[c][dir][(polyord * i + j)] += (float)pow((double)vblock, i) * pow((double)hblock, j) * bstemp[dir] * blockwt[vblock * hblsz + hblock]; + powVblock *= vblock; + } + shiftmat[c][dir][(polyord * i + j)] += powVblockInit * powHblockInit * bstemp[dir] * blockwt[vblock * hblsz + hblock]; + powHblockInit *= hblock; } - - //if (c==0 && dir==0) {printf("i= %d j= %d shiftmat= %f \n",i,j,shiftmat[c][dir][(polyord*i+j)]);} + powVblockInit *= vblock; }//monomials }//dir - }//c }//blocks - numblox[1] = min(numblox[0], numblox[2]); + numblox[1] = min(numblox[0], numblox[1]); //if too few data points, restrict the order of the fit to linear if (numblox[1] < 32) { @@ -788,12 +709,10 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) if(processpasstwo) //fit parameters to blockshifts - for (c = 0; c < 3; c += 2) - for (dir = 0; dir < 2; dir++) { - res = LinEqSolve(numpar, polymat[c][dir], shiftmat[c][dir], fitparams[c][dir]); - - if (res) { - printf("CA correction pass failed -- can't solve linear equations for color %d direction %d...\n", c, dir); + for (int c = 0; c < 2; c++) + for (int dir = 0; dir < 2; dir++) { + if (!LinEqSolve(numpar, polymat[c][dir], shiftmat[c][dir], fitparams[c][dir])) { + printf("CA correction pass failed -- can't solve linear equations for colour %d direction %d...\n", c, dir); processpasstwo = false; } } @@ -810,53 +729,33 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) if(processpasstwo) { #pragma omp for schedule(dynamic) collapse(2) nowait - for (top = -border; top < height; top += TS - border2) - for (left = -border; left < width; left += TS - border2) { - vblock = ((top + border) / (TS - border2)) + 1; - hblock = ((left + border) / (TS - border2)) + 1; - int bottom = min(top + TS, height + border); - int right = min(left + TS, width + border); - int rr1 = bottom - top; - int cc1 = right - left; + for (int top = -border; top < height; top += ts - border2) + for (int left = -border; left < width; left += ts - border2) { + memset(buffer, 0, buffersize); + float lblockshifts[2][2]; + const int vblock = ((top + border) / (ts - border2)) + 1; + const int hblock = ((left + border) / (ts - border2)) + 1; + const int bottom = min(top + ts, height + border); + const int right = min(left + ts, width + border); + const int rr1 = bottom - top; + const int cc1 = right - left; - //t1_init = clock(); - if (top < 0) { - rrmin = border; - } else { - rrmin = 0; - } - - if (left < 0) { - ccmin = border; - } else { - ccmin = 0; - } - - if (bottom > height) { - rrmax = height - top; - } else { - rrmax = rr1; - } - - if (right > width) { - ccmax = width - left; - } else { - ccmax = cc1; - } + const int rrmin = top < 0 ? border : 0; + const int rrmax = bottom > height ? height - top : rr1; + const int ccmin = left < 0 ? border : 0; + const int ccmax = right > width ? width - left : cc1; // rgb from input CFA data // rgb values should be floating point number between 0 and 1 // after white balance multipliers are applied - for (rr = rrmin; rr < rrmax; rr++) - for (row = rr + top, cc = ccmin; cc < ccmax; cc++) { - col = cc + left; - c = FC(rr, cc); - indx = row * width + col; - indx1 = rr * TS + cc; - //rgb[indx1][c] = image[indx][c]/65535.0f; + for (int rr = rrmin; rr < rrmax; rr++) + for (int row = rr + top, cc = ccmin; cc < ccmax; cc++) { + int col = cc + left; + int c = FC(rr, cc); + int indx = row * width + col; + int indx1 = rr * ts + cc; rgb[c][indx1] = (rawData[row][col]) / 65535.0f; - //rgb[indx1][c] = image[indx][c]/65535.0f;//for dcraw implementation if ((c & 1) == 0) { rgb[1][indx1] = Gtmp[indx]; @@ -866,87 +765,75 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //fill borders if (rrmin > 0) { - for (rr = 0; rr < border; rr++) - for (cc = ccmin; cc < ccmax; cc++) { - c = FC(rr, cc); - rgb[c][rr * TS + cc] = rgb[c][(border2 - rr) * TS + cc]; - rgb[1][rr * TS + cc] = rgb[1][(border2 - rr) * TS + cc]; + for (int rr = 0; rr < border; rr++) + for (int cc = ccmin; cc < ccmax; cc++) { + int c = FC(rr, cc); + rgb[c][rr * ts + cc] = rgb[c][(border2 - rr) * ts + cc]; + rgb[1][rr * ts + cc] = rgb[1][(border2 - rr) * ts + cc]; } } if (rrmax < rr1) { - for (rr = 0; rr < border; rr++) - for (cc = ccmin; cc < ccmax; cc++) { - c = FC(rr, cc); - rgb[c][(rrmax + rr)*TS + cc] = (rawData[(height - rr - 2)][left + cc]) / 65535.0f; - //rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+left+cc][c])/65535.0f;//for dcraw implementation - - rgb[1][(rrmax + rr)*TS + cc] = Gtmp[(height - rr - 2) * width + left + cc]; + for (int rr = 0; rr < border; rr++) + for (int cc = ccmin; cc < ccmax; cc++) { + int c = FC(rr, cc); + rgb[c][(rrmax + rr)*ts + cc] = (rawData[(height - rr - 2)][left + cc]) / 65535.0f; + rgb[1][(rrmax + rr)*ts + cc] = Gtmp[(height - rr - 2) * width + left + cc]; } } if (ccmin > 0) { - for (rr = rrmin; rr < rrmax; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][rr * TS + cc] = rgb[c][rr * TS + border2 - cc]; - rgb[1][rr * TS + cc] = rgb[1][rr * TS + border2 - cc]; + for (int rr = rrmin; rr < rrmax; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][rr * ts + cc] = rgb[c][rr * ts + border2 - cc]; + rgb[1][rr * ts + cc] = rgb[1][rr * ts + border2 - cc]; } } if (ccmax < cc1) { - for (rr = rrmin; rr < rrmax; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][rr * TS + ccmax + cc] = (rawData[(top + rr)][(width - cc - 2)]) / 65535.0f; - //rgb[rr*TS+ccmax+cc][c] = (image[(top+rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation - - rgb[1][rr * TS + ccmax + cc] = Gtmp[(top + rr) * width + (width - cc - 2)]; + for (int rr = rrmin; rr < rrmax; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][rr * ts + ccmax + cc] = (rawData[(top + rr)][(width - cc - 2)]) / 65535.0f; + rgb[1][rr * ts + ccmax + cc] = Gtmp[(top + rr) * width + (width - cc - 2)]; } } //also, fill the image corners if (rrmin > 0 && ccmin > 0) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rr)*TS + cc] = (rawData[border2 - rr][border2 - cc]) / 65535.0f; - //rgb[(rr)*TS+cc][c] = (rgb[(border2-rr)*TS+(border2-cc)][c]);//for dcraw implementation - - rgb[1][(rr)*TS + cc] = Gtmp[(border2 - rr) * width + border2 - cc]; + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rr)*ts + cc] = (rawData[border2 - rr][border2 - cc]) / 65535.0f; + rgb[1][(rr)*ts + cc] = Gtmp[(border2 - rr) * width + border2 - cc]; } } if (rrmax < rr1 && ccmax < cc1) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rrmax + rr)*TS + ccmax + cc] = (rawData[(height - rr - 2)][(width - cc - 2)]) / 65535.0f; - //rgb[(rrmax+rr)*TS+ccmax+cc][c] = (image[(height-rr-2)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation - - rgb[1][(rrmax + rr)*TS + ccmax + cc] = Gtmp[(height - rr - 2) * width + (width - cc - 2)]; + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rrmax + rr)*ts + ccmax + cc] = (rawData[(height - rr - 2)][(width - cc - 2)]) / 65535.0f; + rgb[1][(rrmax + rr)*ts + ccmax + cc] = Gtmp[(height - rr - 2) * width + (width - cc - 2)]; } } if (rrmin > 0 && ccmax < cc1) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rr)*TS + ccmax + cc] = (rawData[(border2 - rr)][(width - cc - 2)]) / 65535.0f; - //rgb[(rr)*TS+ccmax+cc][c] = (image[(border2-rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation - - rgb[1][(rr)*TS + ccmax + cc] = Gtmp[(border2 - rr) * width + (width - cc - 2)]; + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rr)*ts + ccmax + cc] = (rawData[(border2 - rr)][(width - cc - 2)]) / 65535.0f; + rgb[1][(rr)*ts + ccmax + cc] = Gtmp[(border2 - rr) * width + (width - cc - 2)]; } } if (rrmax < rr1 && ccmin > 0) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rrmax + rr)*TS + cc] = (rawData[(height - rr - 2)][(border2 - cc)]) / 65535.0f; - //rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+(border2-cc)][c])/65535.0f;//for dcraw implementation - - rgb[1][(rrmax + rr)*TS + cc] = Gtmp[(height - rr - 2) * width + (border2 - cc)]; + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rrmax + rr)*ts + cc] = (rawData[(height - rr - 2)][(border2 - cc)]) / 65535.0f; + rgb[1][(rrmax + rr)*ts + cc] = Gtmp[(height - rr - 2) * width + (border2 - cc)]; } } @@ -955,17 +842,17 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) if (!autoCA) { //manual CA correction; use red/blue slider values to set CA shift parameters - for (rr = 3; rr < rr1 - 3; rr++) - for (row = rr + top, cc = 3, indx = rr * TS + cc; cc < cc1 - 3; cc++, indx++) { - col = cc + left; - c = FC(rr, cc); + for (int rr = 3; rr < rr1 - 3; rr++) + for (int row = rr + top, cc = 3, indx = rr * ts + cc; cc < cc1 - 3; cc++, indx++) { + int col = cc + left; + int c = FC(rr, cc); if (c != 1) { //compute directional weights using image gradients - wtu = 1.0 / SQR(eps + fabsf(rgb[1][(rr + 1) * TS + cc] - rgb[1][(rr - 1) * TS + cc]) + fabsf(rgb[c][(rr) * TS + cc] - rgb[c][(rr - 2) * TS + cc]) + fabsf(rgb[1][(rr - 1) * TS + cc] - rgb[1][(rr - 3) * TS + cc])); - wtd = 1.0 / SQR(eps + fabsf(rgb[1][(rr - 1) * TS + cc] - rgb[1][(rr + 1) * TS + cc]) + fabsf(rgb[c][(rr) * TS + cc] - rgb[c][(rr + 2) * TS + cc]) + fabsf(rgb[1][(rr + 1) * TS + cc] - rgb[1][(rr + 3) * TS + cc])); - wtl = 1.0 / SQR(eps + fabsf(rgb[1][(rr) * TS + cc + 1] - rgb[1][(rr) * TS + cc - 1]) + fabsf(rgb[c][(rr) * TS + cc] - rgb[c][(rr) * TS + cc - 2]) + fabsf(rgb[1][(rr) * TS + cc - 1] - rgb[1][(rr) * TS + cc - 3])); - wtr = 1.0 / SQR(eps + fabsf(rgb[1][(rr) * TS + cc - 1] - rgb[1][(rr) * TS + cc + 1]) + fabsf(rgb[c][(rr) * TS + cc] - rgb[c][(rr) * TS + cc + 2]) + fabsf(rgb[1][(rr) * TS + cc + 1] - rgb[1][(rr) * TS + cc + 3])); + float wtu = 1.0 / SQR(eps + fabsf(rgb[1][(rr + 1) * ts + cc] - rgb[1][(rr - 1) * ts + cc]) + fabsf(rgb[c][(rr) * ts + cc] - rgb[c][(rr - 2) * ts + cc]) + fabsf(rgb[1][(rr - 1) * ts + cc] - rgb[1][(rr - 3) * ts + cc])); + float wtd = 1.0 / SQR(eps + fabsf(rgb[1][(rr - 1) * ts + cc] - rgb[1][(rr + 1) * ts + cc]) + fabsf(rgb[c][(rr) * ts + cc] - rgb[c][(rr + 2) * ts + cc]) + fabsf(rgb[1][(rr + 1) * ts + cc] - rgb[1][(rr + 3) * ts + cc])); + float wtl = 1.0 / SQR(eps + fabsf(rgb[1][(rr) * ts + cc + 1] - rgb[1][(rr) * ts + cc - 1]) + fabsf(rgb[c][(rr) * ts + cc] - rgb[c][(rr) * ts + cc - 2]) + fabsf(rgb[1][(rr) * ts + cc - 1] - rgb[1][(rr) * ts + cc - 3])); + float wtr = 1.0 / SQR(eps + fabsf(rgb[1][(rr) * ts + cc - 1] - rgb[1][(rr) * ts + cc + 1]) + fabsf(rgb[c][(rr) * ts + cc] - rgb[c][(rr) * ts + cc + 2]) + fabsf(rgb[1][(rr) * ts + cc + 1] - rgb[1][(rr) * ts + cc + 3])); //store in rgb array the interpolated G value at R/B grid points using directional weighted average rgb[1][indx] = (wtu * rgb[1][indx - v1] + wtd * rgb[1][indx + v1] + wtl * rgb[1][indx - 1] + wtr * rgb[1][indx + 1]) / (wtu + wtd + wtl + wtr); @@ -978,89 +865,105 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) float hfrac = -((float)(hblock - 0.5) / (hblsz - 2) - 0.5); float vfrac = -((float)(vblock - 0.5) / (vblsz - 2) - 0.5) * height / width; - blockshifts[(vblock)*hblsz + hblock][0][0] = 2 * vfrac * cared; - blockshifts[(vblock)*hblsz + hblock][0][1] = 2 * hfrac * cared; - blockshifts[(vblock)*hblsz + hblock][2][0] = 2 * vfrac * cablue; - blockshifts[(vblock)*hblsz + hblock][2][1] = 2 * hfrac * cablue; + lblockshifts[0][0] = 2 * vfrac * cared; + lblockshifts[0][1] = 2 * hfrac * cared; + lblockshifts[1][0] = 2 * vfrac * cablue; + lblockshifts[1][1] = 2 * hfrac * cablue; } else { //CA auto correction; use CA diagnostic pass to set shift parameters - blockshifts[(vblock)*hblsz + hblock][0][0] = blockshifts[(vblock) * hblsz + hblock][0][1] = 0; - blockshifts[(vblock)*hblsz + hblock][2][0] = blockshifts[(vblock) * hblsz + hblock][2][1] = 0; - - for (i = 0; i < polyord; i++) - for (j = 0; j < polyord; j++) { + lblockshifts[0][0] = lblockshifts[0][1] = 0; + lblockshifts[1][0] = lblockshifts[1][1] = 0; + double powVblock = 1.0; + for (int i = 0; i < polyord; i++) { + double powHblock = powVblock; + for (int j = 0; j < polyord; j++) { //printf("i= %d j= %d polycoeff= %f \n",i,j,fitparams[0][0][polyord*i+j]); - blockshifts[(vblock)*hblsz + hblock][0][0] += (float)pow((float)vblock, i) * pow((float)hblock, j) * fitparams[0][0][polyord * i + j]; - blockshifts[(vblock)*hblsz + hblock][0][1] += (float)pow((float)vblock, i) * pow((float)hblock, j) * fitparams[0][1][polyord * i + j]; - blockshifts[(vblock)*hblsz + hblock][2][0] += (float)pow((float)vblock, i) * pow((float)hblock, j) * fitparams[2][0][polyord * i + j]; - blockshifts[(vblock)*hblsz + hblock][2][1] += (float)pow((float)vblock, i) * pow((float)hblock, j) * fitparams[2][1][polyord * i + j]; + lblockshifts[0][0] += powHblock * fitparams[0][0][polyord * i + j]; + lblockshifts[0][1] += powHblock * fitparams[0][1][polyord * i + j]; + lblockshifts[1][0] += powHblock * fitparams[1][0][polyord * i + j]; + lblockshifts[1][1] += powHblock * fitparams[1][1][polyord * i + j]; + powHblock *= hblock; } - - blockshifts[(vblock)*hblsz + hblock][0][0] = LIM(blockshifts[(vblock) * hblsz + hblock][0][0], -bslim, bslim); - blockshifts[(vblock)*hblsz + hblock][0][1] = LIM(blockshifts[(vblock) * hblsz + hblock][0][1], -bslim, bslim); - blockshifts[(vblock)*hblsz + hblock][2][0] = LIM(blockshifts[(vblock) * hblsz + hblock][2][0], -bslim, bslim); - blockshifts[(vblock)*hblsz + hblock][2][1] = LIM(blockshifts[(vblock) * hblsz + hblock][2][1], -bslim, bslim); + powVblock *= vblock; + } + constexpr float bslim = 3.99; //max allowed CA shift + lblockshifts[0][0] = LIM(lblockshifts[0][0], -bslim, bslim); + lblockshifts[0][1] = LIM(lblockshifts[0][1], -bslim, bslim); + lblockshifts[1][0] = LIM(lblockshifts[1][0], -bslim, bslim); + lblockshifts[1][1] = LIM(lblockshifts[1][1], -bslim, bslim); }//end of setting CA shift parameters - //printf("vblock= %d hblock= %d vshift= %f hshift= %f \n",vblock,hblock,blockshifts[(vblock)*hblsz+hblock][0][0],blockshifts[(vblock)*hblsz+hblock][0][1]); - for (c = 0; c < 3; c += 2) { + for (int c = 0; c < 3; c += 2) { //some parameters for the bilinear interpolation - shiftvfloor[c] = floor((float)blockshifts[(vblock) * hblsz + hblock][c][0]); - shiftvceil[c] = ceil((float)blockshifts[(vblock) * hblsz + hblock][c][0]); - shiftvfrac[c] = blockshifts[(vblock) * hblsz + hblock][c][0] - shiftvfloor[c]; + shiftvfloor[c] = floor((float)lblockshifts[c>>1][0]); + shiftvceil[c] = ceil((float)lblockshifts[c>>1][0]); + shiftvfrac[c] = lblockshifts[c>>1][0] - shiftvfloor[c]; - shifthfloor[c] = floor((float)blockshifts[(vblock) * hblsz + hblock][c][1]); - shifthceil[c] = ceil((float)blockshifts[(vblock) * hblsz + hblock][c][1]); - shifthfrac[c] = blockshifts[(vblock) * hblsz + hblock][c][1] - shifthfloor[c]; + shifthfloor[c] = floor((float)lblockshifts[c>>1][1]); + shifthceil[c] = ceil((float)lblockshifts[c>>1][1]); + shifthfrac[c] = lblockshifts[c>>1][1] - shifthfloor[c]; - - if (blockshifts[(vblock)*hblsz + hblock][c][0] > 0) { - GRBdir[0][c] = 1; - } else { - GRBdir[0][c] = -1; - } - - if (blockshifts[(vblock)*hblsz + hblock][c][1] > 0) { - GRBdir[1][c] = 1; - } else { - GRBdir[1][c] = -1; - } + GRBdir[0][c] = lblockshifts[c>>1][0] > 0 ? 2 : -2; + GRBdir[1][c] = lblockshifts[c>>1][1] > 0 ? 2 : -2; } - for (rr = 4; rr < rr1 - 4; rr++) - for (cc = 4 + (FC(rr, 2) & 1), c = FC(rr, cc); cc < cc1 - 4; cc += 2) { - //perform CA correction using color ratios or color differences + for (int rr = 4; rr < rr1 - 4; rr++) { + int cc = 4 + (FC(rr, 2) & 1); + int c = FC(rr, cc); +#ifdef __SSE2__ + vfloat shifthfracv = F2V(shifthfrac[c]); + vfloat shiftvfracv = F2V(shiftvfrac[c]); + for (; cc < cc1 - 10; cc += 8) { + //perform CA correction using colour ratios or colour differences + vfloat Ginthfloorv = vintpf(shifthfracv, LC2VFU(rgb[1][(rr + shiftvfloor[c]) * ts + cc + shifthceil[c]]), LC2VFU(rgb[1][(rr + shiftvfloor[c]) * ts + cc + shifthfloor[c]])); + vfloat Ginthceilv = vintpf(shifthfracv, LC2VFU(rgb[1][(rr + shiftvceil[c]) * ts + cc + shifthceil[c]]), LC2VFU(rgb[1][(rr + shiftvceil[c]) * ts + cc + shifthfloor[c]])); + //Gint is bilinear interpolation of G at CA shift point + vfloat Gintv = vintpf(shiftvfracv, Ginthceilv, Ginthfloorv); - Ginthfloor = (1 - shifthfrac[c]) * rgb[1][(rr + shiftvfloor[c]) * TS + cc + shifthfloor[c]] + (shifthfrac[c]) * rgb[1][(rr + shiftvfloor[c]) * TS + cc + shifthceil[c]]; - Ginthceil = (1 - shifthfrac[c]) * rgb[1][(rr + shiftvceil[c]) * TS + cc + shifthfloor[c]] + (shifthfrac[c]) * rgb[1][(rr + shiftvceil[c]) * TS + cc + shifthceil[c]]; - //Gint is blinear interpolation of G at CA shift point - Gint = (1 - shiftvfrac[c]) * Ginthfloor + (shiftvfrac[c]) * Ginthceil; - - //determine R/B at grid points using color differences at shift point plus interpolated G value at grid point + //determine R/B at grid points using colour differences at shift point plus interpolated G value at grid point //but first we need to interpolate G-R/G-B to grid points... - grbdiff[((rr)*TS + cc) >> 1] = Gint - rgb[c][(rr) * TS + cc]; - gshift[((rr)*TS + cc) >> 1] = Gint; + STVFU(grbdiff[((rr)*ts + cc) >> 1], Gintv - LC2VFU(rgb[c][(rr) * ts + cc])); + STVFU(gshift[((rr)*ts + cc) >> 1], Gintv); } - for (rr = 8; rr < rr1 - 8; rr++) - for (cc = 8 + (FC(rr, 2) & 1), c = FC(rr, cc), indx = rr * TS + cc; cc < cc1 - 8; cc += 2, indx += 2) { +#endif + for (; cc < cc1 - 4; cc += 2) { + //perform CA correction using colour ratios or colour differences + float Ginthfloor = intp(shifthfrac[c], rgb[1][(rr + shiftvfloor[c]) * ts + cc + shifthceil[c]], rgb[1][(rr + shiftvfloor[c]) * ts + cc + shifthfloor[c]]); + float Ginthceil = intp(shifthfrac[c], rgb[1][(rr + shiftvceil[c]) * ts + cc + shifthceil[c]], rgb[1][(rr + shiftvceil[c]) * ts + cc + shifthfloor[c]]); + //Gint is bilinear interpolation of G at CA shift point + float Gint = intp(shiftvfrac[c], Ginthceil, Ginthfloor); - //if (rgb[indx][c]>clip_pt || Gtmp[indx]>clip_pt) continue; + //determine R/B at grid points using colour differences at shift point plus interpolated G value at grid point + //but first we need to interpolate G-R/G-B to grid points... + grbdiff[((rr)*ts + cc) >> 1] = Gint - rgb[c][(rr) * ts + cc]; + gshift[((rr)*ts + cc) >> 1] = Gint; + } + } - grbdiffold = rgb[1][indx] - rgb[c][indx]; + shifthfrac[0] /= 2.f; + shifthfrac[2] /= 2.f; + shiftvfrac[0] /= 2.f; + shiftvfrac[2] /= 2.f; - //interpolate color difference from optical R/B locations to grid locations - grbdiffinthfloor = (1.0f - shifthfrac[c] / 2.0f) * grbdiff[indx >> 1] + (shifthfrac[c] / 2.0f) * grbdiff[(indx - 2 * GRBdir[1][c]) >> 1]; - grbdiffinthceil = (1.0f - shifthfrac[c] / 2.0f) * grbdiff[((rr - 2 * GRBdir[0][c]) * TS + cc) >> 1] + (shifthfrac[c] / 2.0f) * grbdiff[((rr - 2 * GRBdir[0][c]) * TS + cc - 2 * GRBdir[1][c]) >> 1]; + // this loop does not deserve vectorization in mainly because the most expensive part with the divisions does not happen often (less than 1/10 in my tests) + for (int rr = 8; rr < rr1 - 8; rr++) + for (int cc = 8 + (FC(rr, 2) & 1), c = FC(rr, cc), indx = rr * ts + cc; cc < cc1 - 8; cc += 2, indx += 2) { + + float grbdiffold = rgb[1][indx] - rgb[c][indx]; + + //interpolate colour difference from optical R/B locations to grid locations + float grbdiffinthfloor = intp(shifthfrac[c], grbdiff[(indx - GRBdir[1][c]) >> 1], grbdiff[indx >> 1]); + float grbdiffinthceil = intp(shifthfrac[c], grbdiff[((rr - GRBdir[0][c]) * ts + cc - GRBdir[1][c]) >> 1], grbdiff[((rr - GRBdir[0][c]) * ts + cc) >> 1]); //grbdiffint is bilinear interpolation of G-R/G-B at grid point - grbdiffint = (1.0f - shiftvfrac[c] / 2.0f) * grbdiffinthfloor + (shiftvfrac[c] / 2.0f) * grbdiffinthceil; + float grbdiffint = intp(shiftvfrac[c], grbdiffinthceil, grbdiffinthfloor); - //now determine R/B at grid points using interpolated color differences and interpolated G value at grid point - RBint = rgb[1][indx] - grbdiffint; + //now determine R/B at grid points using interpolated colour differences and interpolated G value at grid point + float RBint = rgb[1][indx] - grbdiffint; if (fabsf(RBint - rgb[c][indx]) < 0.25f * (RBint + rgb[c][indx])) { if (fabsf(grbdiffold) > fabsf(grbdiffint) ) { @@ -1069,34 +972,33 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) } else { //gradient weights using difference from G at CA shift points and G at grid points - p[0] = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[indx >> 1])); - p[1] = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[(indx - 2 * GRBdir[1][c]) >> 1])); - p[2] = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[((rr - 2 * GRBdir[0][c]) * TS + cc) >> 1])); - p[3] = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[((rr - 2 * GRBdir[0][c]) * TS + cc - 2 * GRBdir[1][c]) >> 1])); + float p0 = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[indx >> 1])); + float p1 = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[(indx - GRBdir[1][c]) >> 1])); + float p2 = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[((rr - GRBdir[0][c]) * ts + cc) >> 1])); + float p3 = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[((rr - GRBdir[0][c]) * ts + cc - GRBdir[1][c]) >> 1])); - grbdiffint = (p[0] * grbdiff[indx >> 1] + p[1] * grbdiff[(indx - 2 * GRBdir[1][c]) >> 1] + - p[2] * grbdiff[((rr - 2 * GRBdir[0][c]) * TS + cc) >> 1] + p[3] * grbdiff[((rr - 2 * GRBdir[0][c]) * TS + cc - 2 * GRBdir[1][c]) >> 1]) / (p[0] + p[1] + p[2] + p[3]); + grbdiffint = (p0 * grbdiff[indx >> 1] + p1 * grbdiff[(indx - GRBdir[1][c]) >> 1] + + p2 * grbdiff[((rr - GRBdir[0][c]) * ts + cc) >> 1] + p3 * grbdiff[((rr - GRBdir[0][c]) * ts + cc - GRBdir[1][c]) >> 1]) / (p0 + p1 + p2 + p3) ; - //now determine R/B at grid points using interpolated color differences and interpolated G value at grid point + //now determine R/B at grid points using interpolated colour differences and interpolated G value at grid point if (fabsf(grbdiffold) > fabsf(grbdiffint) ) { rgb[c][indx] = rgb[1][indx] - grbdiffint; } } - //if color difference interpolation overshot the correction, just desaturate + //if colour difference interpolation overshot the correction, just desaturate if (grbdiffold * grbdiffint < 0) { rgb[c][indx] = rgb[1][indx] - 0.5f * (grbdiffold + grbdiffint); } } // copy CA corrected results to temporary image matrix - for (rr = border; rr < rr1 - border; rr++) { - c = FC(rr + top, left + border + FC(rr + top, 2) & 1); + for (int rr = border; rr < rr1 - border; rr++) { + int c = FC(rr + top, left + border + FC(rr + top, 2) & 1); - for (row = rr + top, cc = border + (FC(rr, 2) & 1), indx = (row * width + cc + left) >> 1; cc < cc1 - border; cc += 2, indx++) { - col = cc + left; - RawDataTmp[indx] = 65535.0f * rgb[c][(rr) * TS + cc] + 0.5f; - //image[indx][c] = CLIP((int)(65535.0*rgb[(rr)*TS+cc][c] + 0.5));//for dcraw implementation + for (int row = rr + top, cc = border + (FC(rr, 2) & 1), indx = (row * width + cc + left) >> 1; cc < cc1 - border; cc += 2, indx++) { + int col = cc + left; + RawDataTmp[indx] = 65535.0f * rgb[c][(rr) * ts + cc] + 0.5f; } } @@ -1104,9 +1006,9 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) progresscounter++; if(progresscounter % 8 == 0) - #pragma omp critical + #pragma omp critical (cacorrect) { - progress += (double)(8.0 * (TS - border2) * (TS - border2)) / (2 * height * width); + progress += (double)(8.0 * (ts - border2) * (ts - border2)) / (2 * height * width); if (progress > 1.0) { progress = 1.0; @@ -1122,8 +1024,8 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) // copy temporary image matrix back to image matrix #pragma omp for - for(row = 0; row < height; row++) - for(col = 0 + (FC(row, 0) & 1), indx = (row * width + col) >> 1; col < width; col += 2, indx++) { + for(int row = 0; row < height; row++) + for(int col = 0 + (FC(row, 0) & 1), indx = (row * width + col) >> 1; col < width; col += 2, indx++) { rawData[row][col] = RawDataTmp[indx]; } @@ -1142,8 +1044,4 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) if(plistener) { plistener->setProgress(1.0); } - -#undef TS -#undef TSH -#undef PIX_SORT } diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index bf9ec442b..1f4f3375f 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -7,11 +7,11 @@ link_directories ("${PROJECT_SOURCE_DIR}/rtexif" ${EXTRA_LIBDIR} ${GTHREAD_LIBRA set (CAMCONSTSFILE "camconst.json") -set (RTENGINESOURCEFILES safegtk.cc colortemp.cc curves.cc flatcurves.cc diagonalcurves.cc dcraw.cc iccstore.cc color.cc +set (RTENGINESOURCEFILES colortemp.cc curves.cc flatcurves.cc diagonalcurves.cc dcraw.cc iccstore.cc color.cc dfmanager.cc ffmanager.cc gauss.cc rawimage.cc image8.cc image16.cc imagefloat.cc imagedata.cc imageio.cc improcfun.cc init.cc dcrop.cc loadinitial.cc procparams.cc rawimagesource.cc demosaic_algos.cc shmap.cc simpleprocess.cc refreshmap.cc fast_demo.cc amaze_demosaic_RT.cc CA_correct_RT.cc cfa_linedn_RT.cc green_equil_RT.cc hilite_recon.cc expo_before_b.cc - stdimagesource.cc myfile.cc iccjpeg.cc hlmultipliers.cc improccoordinator.cc editbuffer.cc coord.cc + stdimagesource.cc myfile.cc iccjpeg.cc improccoordinator.cc pipettebuffer.cc coord.cc processingjob.cc rtthumbnail.cc utils.cc labimage.cc slicer.cc cieimage.cc iplab2rgb.cc ipsharpen.cc iptransform.cc ipresize.cc ipvibrance.cc imagedimensions.cc jpeg_memsrc.cc jdatasrc.cc iimage.cc diff --git a/rtengine/LUT.h b/rtengine/LUT.h index 965180c92..76bcf0ccd 100644 --- a/rtengine/LUT.h +++ b/rtengine/LUT.h @@ -52,6 +52,8 @@ * LUTf stands for LUT * LUTi stands for LUT * LUTu stands for LUT + * LUTd stands for LUT + * LUTuc stands for LUT */ #ifndef LUT_H_ @@ -65,6 +67,7 @@ #define LUTi LUT #define LUTu LUT #define LUTd LUT +#define LUTuc LUT #include #ifndef NDEBUG @@ -89,9 +92,9 @@ protected: private: unsigned int owner; #if defined( __SSE2__ ) && defined( __x86_64__ ) - vfloat maxsv __attribute__ ((aligned (16))); - vfloat sizev __attribute__ ((aligned (16))); - vint sizeiv __attribute__ ((aligned (16))); + vfloat maxsv ALIGNED16; + vfloat sizev ALIGNED16; + vint sizeiv ALIGNED16; #endif public: /// convenience flag! If one doesn't want to delete the buffer but want to flag it to be recomputed... @@ -254,6 +257,23 @@ public: return *this; } + + // handy to sum up per thread histograms. #pragma omp simd speeds up the loop by about factor 3 for LUTu (unsigned int). + LUT & operator+=(LUT &rhs) + { + if (rhs.size == this->size) { +#ifdef _OPENMP + #pragma omp simd +#endif + + for(unsigned int i = 0; i < this->size; i++) { + data[i] += rhs.data[i]; + } + } + + return *this; + } + // use with integer indices T& operator[](int index) const { diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc index e45a332e1..8290fe085 100644 --- a/rtengine/camconst.cc +++ b/rtengine/camconst.cc @@ -3,7 +3,6 @@ */ #include "camconst.h" #include "settings.h" -#include "safegtk.h" #include "rt_math.h" #include #include @@ -689,7 +688,7 @@ void CameraConstantsStore::init(Glib::ustring baseDir, Glib::ustring userSetting Glib::ustring userFile(Glib::build_filename(userSettingsDir, "camconst.json")); - if (safe_file_test(userFile, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test(userFile, Glib::FILE_TEST_EXISTS)) { parse_camera_constants_file(userFile); } } diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 1cfbfddf6..05e21576c 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -927,6 +927,13 @@ Quality X: unknown, ie we knowing to little about the camera properties to know "ranges": { "white": 4040 } }, + { // Quality B + "make_model": "FUJIFILM X-PRO2", + "dcraw_matrix": [ 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 ], // DNG_v9.4 D65 + "raw_crop": [ 0, 0, 6032, 4032 ], // full raw 6160,4032, Usable 6032,4032 - experimental crop + "ranges": { "white": 16100 } + }, + { // Quality B, Matrix from Adobe's dcp D65 instead of the internal in Leica's DNG "make_model": [ "LEICA SL (Typ 601)", "LEICA Q (Typ 116)" ], "dcraw_matrix": [ 10068,-4043,-1068,-5319,14268,1044,-765,1701,6522 ], // DCP D65 diff --git a/rtengine/ciecam02.cc b/rtengine/ciecam02.cc index ec9d6722d..83ff98f95 100644 --- a/rtengine/ciecam02.cc +++ b/rtengine/ciecam02.cc @@ -328,7 +328,7 @@ double Ciecam02::calculate_fl_from_la_ciecam02( double la ) k = k * k; k = k * k; - return (0.2 * k * la5) + (0.1 * (1.0 - k) * (1.0 - k) * pow(la5, 1.0 / 3.0)); + return (0.2 * k * la5) + (0.1 * (1.0 - k) * (1.0 - k) * std::cbrt(la5)); } float Ciecam02::calculate_fl_from_la_ciecam02float( float la ) @@ -340,7 +340,7 @@ float Ciecam02::calculate_fl_from_la_ciecam02float( float la ) k = k * k; k = k * k; - return (0.2f * k * la5) + (0.1f * (1.0f - k) * (1.0f - k) * pow_F(la5, 1.0f / 3.0f)); + return (0.2f * k * la5) + (0.1f * (1.0f - k) * (1.0f - k) * std::cbrt(la5)); } double Ciecam02::achromatic_response_to_white( double x, double y, double z, double d, double fl, double nbb, int gamu ) diff --git a/rtengine/clutstore.cc b/rtengine/clutstore.cc index b36fd7dfb..a0ea5afb4 100644 --- a/rtengine/clutstore.cc +++ b/rtengine/clutstore.cc @@ -1,7 +1,6 @@ #include "clutstore.h" #include "rt_math.h" #include "stdimagesource.h" -#include "safegtk.h" #include "../rtgui/options.h" rtengine::CLUTStore clutStore; @@ -154,7 +153,7 @@ Imagefloat* HaldCLUT::loadFile( Glib::ustring filename, Glib::ustring workingCol Imagefloat *result = 0; StdImageSource imgSrc; - if ( !safe_file_test( filename, Glib::FILE_TEST_EXISTS ) || imgSrc.load(filename) ) { + if ( !Glib::file_test( filename, Glib::FILE_TEST_EXISTS ) || imgSrc.load(filename) ) { return result; } diff --git a/rtengine/color.cc b/rtengine/color.cc index c0dbab4d3..f5a8c86a3 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -36,6 +36,7 @@ LUTf Color::cachef; LUTf Color::gamma2curve; LUTf Color::gammatab; +LUTuc Color::gammatabThumb; LUTf Color::igammatab_srgb; LUTf Color::gammatab_srgb; // LUTf Color::igammatab_709; @@ -133,129 +134,204 @@ void MunsellDebugInfo::reinitValues() void Color::init () { - int maxindex = 65536; - cachef(maxindex, LUT_CLIP_BELOW); - - gamma2curve(maxindex, LUT_CLIP_BELOW | LUT_CLIP_ABOVE); - - for (int i = 0; i < maxindex; i++) { - if (i > eps_max) { - cachef[i] = 327.68 * ( exp(1.0 / 3.0 * log((double)i / MAXVALF) )); - } else { - cachef[i] = 327.68 * ((kappa * i / MAXVALF + 16.0) / 116.0); - } - } - - for (int i = 0; i < maxindex; i++) { - gamma2curve[i] = (gamma2(i / 65535.0) * 65535.0); - } - /*******************************************/ - gammatab(65536, 0); - igammatab_srgb(65536, 0); - gammatab_srgb(65536, 0); - // igammatab_709(65536,0); - // gammatab_709(65536,0); - igammatab_55(65536, 0); - gammatab_55(65536, 0); - igammatab_4(65536, 0); - gammatab_4(65536, 0); + constexpr auto maxindex = 65536; - igammatab_26_11(65536, 0); - gammatab_26_11(65536, 0); - igammatab_24_17(65536, 0); - gammatab_24_17a(65536, LUT_CLIP_ABOVE | LUT_CLIP_BELOW); - gammatab_13_2(65536, 0); - igammatab_13_2(65536, 0); - gammatab_115_2(65536, 0); - igammatab_115_2(65536, 0); - gammatab_145_3(65536, 0); - igammatab_145_3(65536, 0); + cachef(maxindex, LUT_CLIP_BELOW); + gamma2curve(maxindex, LUT_CLIP_BELOW | LUT_CLIP_ABOVE); + gammatab(maxindex, 0); + gammatabThumb(maxindex, 0); - for (int i = 0; i < 65536; i++) { - gammatab_srgb[i] = (65535.0 * gamma2 (i / 65535.0)); + igammatab_srgb(maxindex, 0); + gammatab_srgb(maxindex, 0); + igammatab_55(maxindex, 0); + gammatab_55(maxindex, 0); + igammatab_4(maxindex, 0); + gammatab_4(maxindex, 0); + + igammatab_26_11(maxindex, 0); + gammatab_26_11(maxindex, 0); + igammatab_24_17(maxindex, 0); + gammatab_24_17a(maxindex, LUT_CLIP_ABOVE | LUT_CLIP_BELOW); + gammatab_13_2(maxindex, 0); + igammatab_13_2(maxindex, 0); + gammatab_115_2(maxindex, 0); + igammatab_115_2(maxindex, 0); + gammatab_145_3(maxindex, 0); + igammatab_145_3(maxindex, 0); + +#ifdef _OPENMP + #pragma omp parallel sections +#endif + { +#ifdef _OPENMP + #pragma omp section +#endif + { + int i = 0; + int epsmaxint = eps_max; + + for (; i <= epsmaxint; i++) + { + cachef[i] = 327.68 * ((kappa * i / MAXVALF + 16.0) / 116.0); + } + + for(; i < maxindex; i++) + { + cachef[i] = 327.68 * std::cbrt((double)i / MAXVALF); + } + } +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_srgb[i] = gamma2curve[i] = 65535.0 * gamma2(i / 65535.0); // two lookup tables with same content but one clips and one does not clip + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_srgb[i] = 65535.0 * igamma2 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + { + double rsRGBGamma = 1.0 / sRGBGamma; + + for (int i = 0; i < maxindex; i++) { + double val = pow (i / 65535.0, rsRGBGamma); + gammatab[i] = 65535.0 * val; + gammatabThumb[i] = (unsigned char)(255.0 * val); + } + } +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_55[i] = 65535.0 * gamma55 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_55[i] = 65535.0 * igamma55 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_4[i] = 65535.0 * gamma4 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_4[i] = 65535.0 * igamma4 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_13_2[i] = 65535.0 * gamma13_2 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_13_2[i] = 65535.0 * igamma13_2 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_115_2[i] = 65535.0 * gamma115_2 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_115_2[i] = 65535.0 * igamma115_2 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_145_3[i] = 65535.0 * gamma145_3 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_145_3[i] = 65535.0 * igamma145_3 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_26_11[i] = 65535.0 * gamma26_11 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_26_11[i] = 65535.0 * igamma26_11 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_24_17a[i] = gamma24_17(i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_24_17[i] = 65535.0 * igamma24_17 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + initMunsell(); + +#ifdef _OPENMP + #pragma omp section +#endif + linearGammaTRC = cmsBuildGamma(NULL, 1.0); } - - for (int i = 0; i < 65536; i++) { - igammatab_srgb[i] = (65535.0 * igamma2 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - gammatab[i] = (65535.0 * pow (i / 65535.0, 0.454545)); - } - - /* for (int i=0; i<65536; i++) - gammatab_709[i] = (65535.0 * gamma709 (i/65535.0)); - for (int i=0; i<65536; i++) - igammatab_709[i] = (65535.0 * igamma709 (i/65535.0)); - */ - for (int i = 0; i < 65536; i++) { - gammatab_55[i] = (65535.0 * gamma55 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - igammatab_55[i] = (65535.0 * igamma55 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - gammatab_4[i] = (65535.0 * gamma4 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - igammatab_4[i] = (65535.0 * igamma4 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - gammatab_13_2[i] = (65535.0 * gamma13_2 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - igammatab_13_2[i] = (65535.0 * igamma13_2 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - gammatab_115_2[i] = (65535.0 * gamma115_2 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - igammatab_115_2[i] = (65535.0 * igamma115_2 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - gammatab_145_3[i] = (65535.0 * gamma145_3 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - igammatab_145_3[i] = (65535.0 * igamma145_3 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - gammatab_26_11[i] = (65535.0 * gamma26_11 (i / 65535.0)); - } - -//gammatab_145_3 - for (int i = 0; i < 65536; i++) { - igammatab_26_11[i] = (65535.0 * igamma26_11 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - float j = (float)i / 65535.0f; - gammatab_24_17a[i] = gamma24_17(j); - } - - for (int i = 0; i < 65536; i++) { - igammatab_24_17[i] = (65535.0 * igamma24_17 (i / 65535.0)); - } - - /*FILE* f = fopen ("c.txt", "wt"); - for (int i=0; i<256; i++) - fprintf (f, "%g %g\n", i/255.0, clower (i/255.0, 2.0, 1.0)); - fclose (f);*/ - - initMunsell(); - - linearGammaTRC = cmsBuildGamma(NULL, 1.0); } void Color::cleanup () @@ -808,6 +884,15 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u float somm; float som = mixerRed + mixerGreen + mixerBlue; + if(som >= 0.f && som < 1.f) { + som = 1.f; + } + + if(som < 0.f && som > -1.f) { + som = -1.f; + } + + // rM = mixerRed, gM = mixerGreen, bM = mixerBlue ! //presets if (setting == "RGB-Abs" || setting == "ROYGCBPM-Abs") { @@ -869,6 +954,15 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u bbm = mixerBlue; somm = mixerRed + mixerGreen + mixerBlue; + + if(somm >= 0.f && somm < 1.f) { + somm = 1.f; + } + + if(somm < 0.f && somm > -1.f) { + somm = -1.f; + } + mixerRed = mixerRed / somm; mixerGreen = mixerGreen / somm; mixerBlue = mixerBlue / somm; @@ -1084,6 +1178,10 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u mixerGreen = mixerGreen * filgreen; mixerBlue = mixerBlue * filblue; + if(mixerRed + mixerGreen + mixerBlue == 0) { + mixerRed += 1.f; + } + mixerRed = filcor * mixerRed / (mixerRed + mixerGreen + mixerBlue); mixerGreen = filcor * mixerGreen / (mixerRed + mixerGreen + mixerBlue); mixerBlue = filcor * mixerBlue / (mixerRed + mixerGreen + mixerBlue); @@ -1091,6 +1189,14 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u if(filter != "None") { som = mixerRed + mixerGreen + mixerBlue; + if(som >= 0.f && som < 1.f) { + som = 1.f; + } + + if(som < 0.f && som > -1.f) { + som = -1.f; + } + if(setting == "RGB-Abs" || setting == "ROYGCBPM-Abs") { kcorec = kcorec * som; } @@ -1436,9 +1542,9 @@ void Color::Yuv2Lab(float Yin, float u, float v, float &L, float &a, float &b, d gamutmap(X, Y, Z, wp); - float fx = (X <= 65535.0 ? cachef[X] : (327.68 * exp(log(X / MAXVALF) / 3.0 ))); - float fy = (Y <= 65535.0 ? cachef[Y] : (327.68 * exp(log(Y / MAXVALF) / 3.0 ))); - float fz = (Z <= 65535.0 ? cachef[Z] : (327.68 * exp(log(Z / MAXVALF) / 3.0 ))); + float fx = (X <= 65535.0 ? cachef[X] : (327.68 * std::cbrt(X / MAXVALF))); + float fy = (Y <= 65535.0 ? cachef[Y] : (327.68 * std::cbrt(Y / MAXVALF))); + float fz = (Z <= 65535.0 ? cachef[Z] : (327.68 * std::cbrt(Z / MAXVALF))); L = (116.0 * fy - 5242.88); //5242.88=16.0*327.68; a = (500.0 * (fx - fy) ); @@ -1484,7 +1590,7 @@ void Color::XYZ2Luv (float X, float Y, float Z, float &L, float &u, float &v) Z /= 65535.f; if (Y > float(eps)) { - L = 116.f * pow(Y, 1.f / 3.f) - 16.f; + L = 116.f * std::cbrt(Y) - 16.f; } else { L = float(kappa) * Y; } diff --git a/rtengine/color.h b/rtengine/color.h index c179946f0..3f78692d8 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -130,8 +130,6 @@ public: // look-up tables for the standard srgb gamma and its inverse (filled by init()) static LUTf igammatab_srgb; static LUTf gammatab_srgb; -// static LUTf igammatab_709; -// static LUTf gammatab_709; static LUTf igammatab_55; static LUTf gammatab_55; static LUTf igammatab_4; @@ -150,6 +148,7 @@ public: // look-up tables for the simple exponential gamma static LUTf gammatab; + static LUTuc gammatabThumb; // for thumbnails static void init (); diff --git a/rtengine/colortemp.cc b/rtengine/colortemp.cc index d4f1c995f..2ccbcba8d 100644 --- a/rtengine/colortemp.cc +++ b/rtengine/colortemp.cc @@ -1414,19 +1414,19 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, // xr, yr , zr > epsilon if(xr[i] > epsilon) { - fx[i] = pow(xr[i], 0.333); + fx[i] = std::cbrt(xr[i]); } else { fx[i] = (903.3 * xr[i] + 16.0) / 116.0; } if(yr[i] > epsilon) { - fy[i] = pow(yr[i], 0.333); + fy[i] = std::cbrt(yr[i]); } else { fy[i] = (903.3 * yr[i] + 16.0) / 116.0; } if(zr[i] > epsilon) { - fz[i] = pow(zr[i], 0.333); + fz[i] = std::cbrt(zr[i]); } else { fz[i] = (903.3 * zr[i] + 16.0) / 116.0; } @@ -1663,19 +1663,19 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, // xr, yr , zr > epsilon if(xr[i] > epsilon) { - fx[i] = pow(xr[i], 0.333); + fx[i] = std::cbrt(xr[i]); } else { fx[i] = (903.3 * xr[i] + 16.0) / 116.0; } if(yr[i] > epsilon) { - fy[i] = pow(yr[i], 0.333); + fy[i] = std::cbrt(yr[i]); } else { fy[i] = (903.3 * yr[i] + 16.0) / 116.0; } if(zr[i] > epsilon) { - fz[i] = pow(zr[i], 0.333); + fz[i] = std::cbrt(zr[i]); } else { fz[i] = (903.3 * zr[i] + 16.0) / 116.0; } @@ -1695,19 +1695,19 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, // if(xr[i] > epsilon) { - fx[i] = pow(xr[i], 0.333); + fx[i] = std::cbrt(xr[i]); } else { fx[i] = (903.3 * xr[i] + 16.0) / 116.0; } if(yr[i] > epsilon) { - fy[i] = pow(yr[i], 0.333); + fy[i] = std::cbrt(yr[i]); } else { fy[i] = (903.3 * yr[i] + 16.0) / 116.0; } if(zr[i] > epsilon) { - fz[i] = pow(zr[i], 0.333); + fz[i] = std::cbrt(zr[i]); } else { fz[i] = (903.3 * zr[i] + 16.0) / 116.0; } diff --git a/rtengine/colortemp.h b/rtengine/colortemp.h index 82b161b25..c79ebb4bf 100644 --- a/rtengine/colortemp.h +++ b/rtengine/colortemp.h @@ -30,7 +30,7 @@ namespace rtengine #define MINTEMP 1500 #define MAXTEMP 60000 #define MINGREEN 0.02 -#define MAXGREEN 5.0 +#define MAXGREEN 10.0 #define MINEQUAL 0.8 #define MAXEQUAL 1.5 diff --git a/rtengine/coord.cc b/rtengine/coord.cc index c35d71e73..8a3d7d080 100644 --- a/rtengine/coord.cc +++ b/rtengine/coord.cc @@ -19,21 +19,49 @@ #include "coord.h" +#include "rt_math.h" + namespace rtengine { -void Coord::setFromPolar(PolarCoord polar) +Coord& Coord::operator= (const PolarCoord& other) { - while (polar.angle < 0.f) { - polar.angle += 360.f; - } + const auto radius = other.radius; + const auto angle = other.angle / 180.0 * M_PI; - while (polar.angle > 360.f) { - polar.angle -= 360.f; - } + x = radius * std::cos (angle); + y = radius * std::sin (angle); - x = polar.radius * cos(polar.angle / 180.f * M_PI); - y = polar.radius * sin(polar.angle / 180.f * M_PI); + return *this; +} + +PolarCoord& PolarCoord::operator= (const Coord& other) +{ + const double x = other.x; + const double y = other.y; + + radius = rtengine::norm2 (x, y); + angle = std::atan2 (y, x) * 180.0 / M_PI; + + return *this; +} + +/// @brief Clip the coord to stay in the width x height bounds +/// @return true if the x or y coordinate has changed +bool Coord::clip (const int width, const int height) +{ + const auto newX = rtengine::LIM (x, 0, width); + const auto newY = rtengine::LIM (y, 0, height); + + if (x != newX || y != newY) { + + x = newX; + y = newY; + + return true; + } else { + return false; + } } } diff --git a/rtengine/coord.h b/rtengine/coord.h index 0b134ce21..2242cec1e 100644 --- a/rtengine/coord.h +++ b/rtengine/coord.h @@ -16,205 +16,218 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ + #ifndef __COORD__ #define __COORD__ -#include "rt_math.h" - namespace rtengine { -class PolarCoord; +struct Coord; +struct PolarCoord; -// Do not confuse with rtengine::Coord2D, this one is for the GUI -class Coord +// Do not confuse with Coord2D, this one is used by the UI. +struct Coord { -public: - int x; - int y; + int x = 0; + int y = 0; - Coord() : x(-1), y(-1) {} - Coord(int x, int y) : x(x), y(y) {} + Coord () = default; + Coord (const int x, const int y); + Coord (const Coord& other) = default; + Coord (const PolarCoord& other); - void set (int x, int y) - { - this->x = x; - this->y = y; - } + Coord& operator= (const Coord& other) = default; + Coord& operator= (const PolarCoord& other); - void setFromPolar(PolarCoord polar); + void get (int& x, int& y) const; + void set (const int x, const int y); - /// @brief Clip the coord to stay in the width x height bounds - /// @return true if the x or y coordinate has changed - bool clip(int width, int height) - { - int trimmedX = rtengine::LIM(x, 0, width); - int trimmedY = rtengine::LIM(y, 0, height); - bool retval = trimmedX != x || trimmedY != y; - x = trimmedX; - y = trimmedY; - return retval; - } + bool clip (const int width, const int height); - bool operator== (const Coord& other) const - { - return other.x == x && other.y == y; - } - - bool operator!= (const Coord& other) const - { - return other.x != x || other.y != y; - } - - void operator+=(const Coord & rhs) - { - x += rhs.x; - y += rhs.y; - } - void operator-=(const Coord & rhs) - { - x -= rhs.x; - y -= rhs.y; - } - void operator*=(double scale) - { - x *= scale; - y *= scale; - } - Coord operator+(Coord & rhs) - { - Coord result(x + rhs.x, y + rhs.y); - return result; - } - Coord operator-(Coord & rhs) - { - Coord result(x - rhs.x, y - rhs.y); - return result; - } - Coord operator*(double scale) - { - Coord result(x * scale, y * scale); - return result; - } -}; - -class PolarCoord -{ -public: - double radius; - double angle; // degree - - PolarCoord() : radius(1.), angle(0.) {} - PolarCoord(double radius, double angle) : radius(radius), angle(angle) {} - PolarCoord(Coord start, Coord end) : radius(1.), angle(0.) - { - setFromCartesian(start, end); - } - PolarCoord(Coord delta) : radius(1.), angle(0.) - { - setFromCartesian(delta); - } - - void set (double radius, double angle) - { - this->radius = radius; - this->angle = angle; - } - - void setFromCartesian(Coord start, Coord end) - { - Coord delta(end.x - start.x, end.y - start.y); - setFromCartesian(delta); - } - - void setFromCartesian(Coord delta) - { - if (!delta.x && !delta.y) { - // null vector, we set to a default value - radius = 1.; - angle = 0.; - return; - } - - double x_ = double(delta.x); - double y_ = double(delta.y); - radius = sqrt(x_ * x_ + y_ * y_); - - if (delta.x > 0.) { - if (delta.y >= 0.) { - angle = atan(y_ / x_) / (2 * M_PI) * 360.; - } else if (delta.y < 0.) { - angle = (atan(y_ / x_) + 2 * M_PI) / (2 * M_PI) * 360.; - } - } else if (delta.x < 0.) { - angle = (atan(y_ / x_) + M_PI) / (2 * M_PI) * 360.; - } else if (delta.x == 0.) { - if (delta.y > 0.) { - angle = 90.; - } else { - angle = 270.; - } - } - } - - bool operator== (const PolarCoord& other) const - { - return other.radius == radius && other.angle == angle; - } - - bool operator!= (const PolarCoord& other) const - { - return other.radius != radius || other.angle != angle; - } - - void operator+=(const PolarCoord & rhs) - { - Coord thisCoord, rhsCoord; - thisCoord.setFromPolar(*this); - rhsCoord.setFromPolar(rhs); - thisCoord += rhsCoord; - setFromCartesian(thisCoord); - } - void operator-=(const PolarCoord & rhs) - { - Coord thisCoord, rhsCoord; - thisCoord.setFromPolar(*this); - rhsCoord.setFromPolar(rhs); - thisCoord -= rhsCoord; - setFromCartesian(thisCoord); - } - void operator*=(double scale) - { - radius *= scale; - } - PolarCoord operator+(PolarCoord & rhs) - { - Coord thisCoord, rhsCoord; - thisCoord.setFromPolar(*this); - rhsCoord.setFromPolar(rhs); - thisCoord += rhsCoord; - PolarCoord result; - result.setFromCartesian(thisCoord); - return result; - } - PolarCoord operator-(PolarCoord & rhs) - { - Coord thisCoord, rhsCoord; - thisCoord.setFromPolar(*this); - rhsCoord.setFromPolar(rhs); - thisCoord -= rhsCoord; - PolarCoord result; - result.setFromCartesian(thisCoord); - return result; - } - Coord operator*(double scale) - { - Coord result(radius * scale, angle); - return result; - } + Coord& operator+= (const Coord& other); + Coord& operator-= (const Coord& other); + Coord& operator*= (const double scale); }; +bool operator== (const Coord& lhs, const Coord& rhs); +bool operator!= (const Coord& lhs, const Coord& rhs); + +const Coord operator+ (const Coord& lhs, const Coord& rhs); +const Coord operator- (const Coord& lhs, const Coord& rhs); +const Coord operator* (const Coord& lhs, const Coord& rhs); + +struct PolarCoord +{ + double radius = 0.0; + double angle = 0.0; + + PolarCoord () = default; + PolarCoord (const double radius, const double angle); + PolarCoord (const PolarCoord& other) = default; + PolarCoord (const Coord& other); + + PolarCoord& operator= (const PolarCoord& other) = default; + PolarCoord& operator= (const Coord& other); + + void get (double& radius, double& angle) const; + void set (const double radius, const double angle); + + PolarCoord& operator+= (const PolarCoord& other); + PolarCoord& operator-= (const PolarCoord& other); + PolarCoord& operator*= (const double scale); + +}; + +bool operator== (const PolarCoord& lhs, const PolarCoord& rhs); +bool operator!= (const PolarCoord& lhs, const PolarCoord& rhs); + +const PolarCoord operator+ (const PolarCoord& lhs, const PolarCoord& rhs); +const PolarCoord operator- (const PolarCoord& lhs, const PolarCoord& rhs); +const PolarCoord operator* (const PolarCoord& lhs, const double rhs); +const PolarCoord operator* (const double lhs, const PolarCoord& rhs); + +inline Coord::Coord (const int x, const int y) : x (x), y (y) +{ +} + +inline Coord::Coord (const PolarCoord& other) +{ + *this = other; +} + +inline void Coord::get (int& x, int& y) const +{ + x = this->x; + y = this->y; +} + +inline void Coord::set (const int x, const int y) +{ + this->x = x; + this->y = y; +} + +inline Coord& Coord::operator+= (const Coord& other) +{ + x += other.x; + y += other.y; + return *this; +} + +inline Coord& Coord::operator-= (const Coord& other) +{ + x -= other.x; + y -= other.y; + return *this; +} + +inline Coord& Coord::operator*= (const double scale) +{ + x *= scale; + y *= scale; + return *this; +} + +inline bool operator== (const Coord& lhs, const Coord& rhs) +{ + return lhs.x == rhs.x && lhs.y == rhs.y; +} + +inline bool operator!= (const Coord& lhs, const Coord& rhs) +{ + return !(lhs == rhs); +} + +inline const Coord operator+ (const Coord& lhs, const Coord& rhs) +{ + return Coord (lhs) += rhs; +} + +inline const Coord operator- (const Coord& lhs, const Coord& rhs) +{ + return Coord (lhs) -= rhs; +} + +inline const Coord operator* (const Coord& lhs, const double rhs) +{ + return Coord (lhs) *= rhs; +} + +inline const Coord operator* (const double lhs, const Coord& rhs) +{ + return Coord (rhs) *= lhs; +} + +inline PolarCoord::PolarCoord (const double radius, const double angle) : radius (radius), angle (angle) +{ +} + +inline PolarCoord::PolarCoord (const Coord& other) +{ + *this = other; +} + +inline void PolarCoord::get (double& radius, double& angle) const +{ + radius = this->radius; + angle = this->angle; +} + +inline void PolarCoord::set (const double radius, const double angle) +{ + this->radius = radius; + this->angle = angle; +} + +inline PolarCoord& PolarCoord::operator+= (const PolarCoord& other) +{ + *this = Coord (*this) + Coord (other); + return *this; +} + +inline PolarCoord &PolarCoord::operator-= (const PolarCoord &other) +{ + *this = Coord (*this) - Coord (other); + return *this; +} + +inline PolarCoord &PolarCoord::operator*= (const double scale) +{ + radius *= scale; + return *this; +} + +inline bool operator== (const PolarCoord& lhs, const PolarCoord& rhs) +{ + return lhs.radius == rhs.radius && lhs.angle == rhs.angle; +} + +inline bool operator!= (const PolarCoord& lhs, const PolarCoord& rhs) +{ + return !(lhs == rhs); +} + +inline const PolarCoord operator+ (const PolarCoord& lhs, const PolarCoord& rhs) +{ + return PolarCoord (lhs) += rhs; +} + +inline const PolarCoord operator- (const PolarCoord& lhs, const PolarCoord& rhs) +{ + return PolarCoord (lhs) -= rhs; +} + +inline const PolarCoord operator* (const PolarCoord& lhs, const double rhs) +{ + return PolarCoord (lhs) *= rhs; +} + +inline const PolarCoord operator* (const double lhs, const PolarCoord& rhs) +{ + return PolarCoord (rhs) *= lhs; +} } diff --git a/rtengine/curves.cc b/rtengine/curves.cc index a0ac2c381..158086cfd 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -34,6 +34,7 @@ #include "curves.h" #include "opthelper.h" #include "ciecam02.h" +#include "color.h" #undef CLIPD #define CLIPD(a) ((a)>0.0f?((a)<1.0f?(a):1.0f):0.0f) @@ -2326,7 +2327,7 @@ void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurv { // increase chroma scaling slightly of shadows - float nL = gamma2curve[newLuminance]; // apply gamma so we make comparison and transition with a more perceptual lightness scale + float nL = Color::gamma2curve[newLuminance]; // apply gamma so we make comparison and transition with a more perceptual lightness scale float dark_scale_factor = 1.20f; //float dark_scale_factor = 1.0 + state.debug.p2 / 100.0f; const float lolim = 0.15f; @@ -2460,7 +2461,6 @@ void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurv float PerceptualToneCurve::cf_range[2]; float PerceptualToneCurve::cf[1000]; -LUTf PerceptualToneCurve::gamma2curve; float PerceptualToneCurve::f, PerceptualToneCurve::c, PerceptualToneCurve::nc, PerceptualToneCurve::yb, PerceptualToneCurve::la, PerceptualToneCurve::xw, PerceptualToneCurve::yw, PerceptualToneCurve::zw, PerceptualToneCurve::gamut; float PerceptualToneCurve::n, PerceptualToneCurve::d, PerceptualToneCurve::nbb, PerceptualToneCurve::ncb, PerceptualToneCurve::cz, PerceptualToneCurve::aw, PerceptualToneCurve::wh, PerceptualToneCurve::pfl, PerceptualToneCurve::fl, PerceptualToneCurve::pow1; @@ -2523,12 +2523,6 @@ void PerceptualToneCurve::init() cf_range[0] = in_x[0]; cf_range[1] = in_x[in_len - 1]; } - gamma2curve(65536, 0); - - for (int i = 0; i < 65536; i++) { - gamma2curve[i] = CurveFactory::gamma2(i / 65535.0); - } - } void PerceptualToneCurve::initApplyState(PerceptualToneCurveState & state, Glib::ustring workingSpace) const diff --git a/rtengine/curves.h b/rtengine/curves.h index 330b5c5ce..0adc735be 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -28,7 +28,7 @@ #include "../rtgui/mydiagonalcurve.h" #include "color.h" #include "procparams.h" -#include "editbuffer.h" +#include "pipettebuffer.h" #include "LUT.h" @@ -867,7 +867,6 @@ class PerceptualToneCurve : public ToneCurve private: static float cf_range[2]; static float cf[1000]; - static LUTf gamma2curve; // for ciecam02 static float f, c, nc, yb, la, xw, yw, zw, gamut; static float n, d, nbb, ncb, cz, aw, wh, pfl, fl, pow1; diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index 9dd01330b..c05230738 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -19,7 +19,6 @@ #include #include "dcp.h" -#include "safegtk.h" #include "iccmatrices.h" #include "iccstore.h" #include "rawimagesource.h" @@ -828,7 +827,7 @@ DCPProfile::DCPProfile(Glib::ustring fname) aDeltas1 = aDeltas2 = aLookTable = NULL; - FILE *pFile = safe_g_fopen(fname, "rb"); + FILE *pFile = g_fopen(fname.c_str (), "rb"); TagDirectory *tagDir = ExifManager::parseTIFF(pFile, false); @@ -1717,7 +1716,7 @@ void DCPStore::init (Glib::ustring rtProfileDir) Glib::Dir* dir = NULL; try { - if (!safe_file_test (dirname, Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (dirname, Glib::FILE_TEST_IS_DIR)) { return; } @@ -1733,7 +1732,7 @@ void DCPStore::init (Glib::ustring rtProfileDir) Glib::ustring sname = *i; // ignore directories - if (!safe_file_test (fname, Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (fname, Glib::FILE_TEST_IS_DIR)) { size_t lastdot = sname.find_last_of ('.'); if (lastdot != Glib::ustring::npos && lastdot <= sname.size() - 4 && (!sname.casefold().compare (lastdot, 4, ".dcp"))) { @@ -1781,7 +1780,7 @@ DCPProfile* DCPStore::getStdProfile(Glib::ustring camShortName) bool DCPStore::isValidDCPFileName(Glib::ustring filename) const { - if (!safe_file_test (filename, Glib::FILE_TEST_EXISTS) || safe_file_test (filename, Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (filename, Glib::FILE_TEST_EXISTS) || Glib::file_test (filename, Glib::FILE_TEST_IS_DIR)) { return false; } diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 09cdb8d0f..c0dbd816d 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -6682,7 +6682,7 @@ void CLASS parse_fuji (int offset) } else if (tag == 0xc000) { c = order; order = 0x4949; - if ((tag = get4()) > 10000) tag = get4(); + while ((tag = get4()) > 10000); width = tag; height = get4(); order = c; diff --git a/rtengine/dcraw.h b/rtengine/dcraw.h index e79b821b1..856da84d1 100644 --- a/rtengine/dcraw.h +++ b/rtengine/dcraw.h @@ -7,7 +7,7 @@ * 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 @@ -59,7 +59,7 @@ public: ,RT_blacklevel_from_constant(0) ,RT_matrix_from_constant(0) ,getbithuff(this,ifp,zero_after_ff) - ,ph1_bithuff(this,ifp,order) + ,ph1_bithuff(this,ifp,order) ,pana_bits(ifp,load_flags) { memset(&hbd, 0, sizeof(hbd)); @@ -100,7 +100,7 @@ protected: double gamm[6]; dcrawImage_t image; float bright, threshold, user_mul[4]; - + int half_size, four_color_rgb, document_mode, highlight; int verbose, use_auto_wb, use_camera_wb, use_camera_matrix; int output_color, output_bps, output_tiff, med_passes; @@ -111,7 +111,7 @@ protected: int RT_matrix_from_constant; float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4]; - + int histogram[4][0x2000]; void (DCraw::*write_thumb)(), (DCraw::*write_fun)(); void (DCraw::*load_raw)(), (DCraw::*thumb_load_raw)(); @@ -163,7 +163,7 @@ protected: int rat[10]; unsigned gps[26]; char desc[512], make[64], model[64], soft[32], date[20], artist[64]; - }; + }; protected: int fcol (int row, int col); @@ -362,7 +362,7 @@ void crop_masked_pixels(); void tiff_get (unsigned base, unsigned *tag, unsigned *type, unsigned *len, unsigned *save); void parse_thumb_note (int base, unsigned toff, unsigned tlen); -int parse_tiff_ifd (int base); +int parse_tiff_ifd (int base); void parse_makernote (int base, int uptag); void get_timestamp (int reversed); void parse_exif (int base); @@ -397,6 +397,19 @@ void identify(); void apply_profile (const char *input, const char *output); void jpeg_thumb() {} // not needed bool dcraw_coeff_overrides(const char make[], const char model[], int iso_speed, short trans[12], int *black_level, int *white_level); +void shiftXtransMatrix( const int offsy, const int offsx) { + char xtransTemp[6][6]; + for(int row = 0;row < 6; row++) { + for(int col = 0;col < 6; col++) { + xtransTemp[row][col] = xtrans[(row+offsy)%6][(col+offsx)%6]; + } + } + for(int row = 0;row < 6; row++) { + for(int col = 0;col < 6; col++) { + xtrans[row][col] = xtransTemp[row][col]; + } + } +} }; diff --git a/rtengine/dcraw.patch b/rtengine/dcraw.patch index ce2d186d8..88a56068c 100644 --- a/rtengine/dcraw.patch +++ b/rtengine/dcraw.patch @@ -1,5 +1,5 @@ ---- dcraw.c 2015-09-08 08:08:11.000000000 +0200 -+++ dcraw.cc 2016-01-08 15:37:02.884467080 +0100 +--- dcraw.c 2016-02-11 22:56:58.043957200 +0100 ++++ dcraw.cc 2016-02-11 23:13:28.708268000 +0100 @@ -1,3 +1,15 @@ +/*RT*/#include +/*RT*/#include @@ -1348,6 +1348,15 @@ strcpy (make, "Phase One"); if (model[0]) return; switch (raw_height) { +@@ -6658,7 +6682,7 @@ + } else if (tag == 0xc000) { + c = order; + order = 0x4949; +- if ((tag = get4()) > 10000) tag = get4(); ++ while ((tag = get4()) > 10000); + width = tag; + height = get4(); + order = c; @@ -6688,7 +6712,11 @@ order = get2(); hlen = get4(); diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 2220f68c5..77f0598b4 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -31,7 +31,7 @@ namespace rtengine extern const Settings* settings; Crop::Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow) - : EditBuffer(editDataProvider), origCrop(NULL), laboCrop(NULL), labnCrop(NULL), + : PipetteBuffer(editDataProvider), origCrop(NULL), laboCrop(NULL), labnCrop(NULL), cropImg(NULL), cbuf_real(NULL), cshmap(NULL), transCrop(NULL), cieCrop(NULL), cbuffer(NULL), updating(false), newUpdatePending(false), skip(10), cropx(0), cropy(0), cropw(-1), croph(-1), @@ -77,7 +77,7 @@ void Crop::setListener (DetailedCropListener* il) EditUniqueID Crop::getCurrEditID() { - EditSubscriber *subscriber = EditBuffer::dataProvider ? EditBuffer::dataProvider->getCurrSubscriber() : NULL; + EditSubscriber *subscriber = PipetteBuffer::dataProvider ? PipetteBuffer::dataProvider->getCurrSubscriber() : NULL; return subscriber ? subscriber->getEditID() : EUID_None; } @@ -90,32 +90,25 @@ void Crop::setEditSubscriber(EditSubscriber* newSubscriber) MyMutex::MyLock lock(cropMutex); // At this point, editCrop.dataProvider->currSubscriber is the old subscriber - EditSubscriber *oldSubscriber = EditBuffer::dataProvider ? EditBuffer::dataProvider->getCurrSubscriber() : NULL; + EditSubscriber *oldSubscriber = PipetteBuffer::dataProvider ? PipetteBuffer::dataProvider->getCurrSubscriber() : NULL; - if (newSubscriber == NULL || (oldSubscriber != NULL && oldSubscriber->getEditBufferType() != newSubscriber->getEditBufferType())) { - if (EditBuffer::imgFloatBuffer != NULL) { - delete EditBuffer::imgFloatBuffer; - EditBuffer::imgFloatBuffer = NULL; + if (newSubscriber == NULL || (oldSubscriber != NULL && oldSubscriber->getPipetteBufferType() != newSubscriber->getPipetteBufferType())) { + if (PipetteBuffer::imgFloatBuffer != NULL) { + delete PipetteBuffer::imgFloatBuffer; + PipetteBuffer::imgFloatBuffer = NULL; } - if (EditBuffer::LabBuffer != NULL) { - delete EditBuffer::LabBuffer; - EditBuffer::LabBuffer = NULL; + if (PipetteBuffer::LabBuffer != NULL) { + delete PipetteBuffer::LabBuffer; + PipetteBuffer::LabBuffer = NULL; } - if (EditBuffer::singlePlaneBuffer.getW() != -1) { - EditBuffer::singlePlaneBuffer.flushData(); + if (PipetteBuffer::singlePlaneBuffer.getW() != -1) { + PipetteBuffer::singlePlaneBuffer.flushData(); } } - if (newSubscriber == NULL && oldSubscriber != NULL && oldSubscriber->getEditingType() == ET_OBJECTS) { - printf("Free object buffers\n"); - EditBuffer::resize(0, 0); // This will delete the objects buffer - } else if (newSubscriber && newSubscriber->getEditingType() == ET_OBJECTS) { - EditBuffer::resize(cropw, croph, newSubscriber); - } - - // If oldSubscriber == NULL && newSubscriber != NULL -> the image will be allocated when necessary + // If oldSubscriber == NULL && newSubscriber != NULL && newSubscriber->getEditingType() == ET_PIPETTE-> the image will be allocated when necessary } void Crop::update (int todo) @@ -712,6 +705,17 @@ void Crop::update (int todo) transCrop = NULL; } + if ((todo & (M_TRANSFORM)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) { + + const int W = baseCrop->getWidth(); + const int H = baseCrop->getHeight(); + LabImage labcbdl(W, H); + parent->ipf.rgb2lab(*baseCrop, labcbdl, params.icm.working); + parent->ipf.dirpyrequalizer (&labcbdl, skip); + parent->ipf.lab2rgb(labcbdl, *baseCrop, params.icm.working); + + } + // blurmap for shadow & highlights if ((todo & M_BLURMAP) && params.sh.enabled) { double radius = sqrt (double(SKIPS(parent->fw, skip) * SKIPS(parent->fw, skip) + SKIPS(parent->fh, skip) * SKIPS(parent->fh, skip))) / 2.0; @@ -732,6 +736,7 @@ void Crop::update (int todo) } } + // shadows & highlights & tone curve & convert to cielab /*int xref,yref; xref=000;yref=000; @@ -838,12 +843,13 @@ void Crop::update (int todo) // if (skip==1) { WaveletParams WaveParams = params.wavelet; - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { - parent->ipf.dirpyrequalizer (labnCrop, skip); - // parent->ipf.Lanczoslab (labnCrop,labnCrop , 1.f/skip); + if(params.dirpyrequalizer.cbdlMethod == "aft") { + if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled))) { + parent->ipf.dirpyrequalizer (labnCrop, skip); + // parent->ipf.Lanczoslab (labnCrop,labnCrop , 1.f/skip); + } } - int kall = 0; int minwin = min(labnCrop->W, labnCrop->H); int maxlevelcrop = 10; @@ -984,7 +990,7 @@ void Crop::update (int todo) } // all pipette buffer processing should be finished now - EditBuffer::setReady(); + PipetteBuffer::setReady(); // switch back to rgb parent->ipf.lab2monitorRgb (labnCrop, cropImg); @@ -1085,7 +1091,7 @@ void Crop::freeAll () cshmap = NULL; } - EditBuffer::flush(); + PipetteBuffer::flush(); } cropAllocated = false; @@ -1157,6 +1163,13 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte printf ("setsizes starts (%d, %d, %d, %d, %d, %d)\n", orW, orH, trafw, trafh, cw, ch); } + EditType editType = ET_PIPETTE; + if (const auto editProvider = PipetteBuffer::getDataProvider ()) { + if (const auto editSubscriber = editProvider->getCurrSubscriber ()) { + editType = editSubscriber->getEditingType (); + } + } + if (cw != cropw || ch != croph || orW != trafw || orH != trafh) { cropw = cw; @@ -1223,7 +1236,11 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte cshmap = new SHMap (cropw, croph, true); } - EditBuffer::resize(cropw, croph); + if (editType == ET_PIPETTE) { + PipetteBuffer::resize(cropw, croph); + } else if (PipetteBuffer::bufferCreated()) { + PipetteBuffer::flush(); + } cropAllocated = true; diff --git a/rtengine/dcrop.h b/rtengine/dcrop.h index 57f388a51..f1230bf01 100644 --- a/rtengine/dcrop.h +++ b/rtengine/dcrop.h @@ -26,7 +26,7 @@ #include "image16.h" #include "imagesource.h" #include "procevents.h" -#include "editbuffer.h" +#include "pipettebuffer.h" #include "../rtgui/threadutils.h" namespace rtengine @@ -36,7 +36,7 @@ using namespace procparams; class ImProcCoordinator; -class Crop : public DetailedCrop, public EditBuffer +class Crop : public DetailedCrop, public PipetteBuffer { protected: @@ -57,6 +57,7 @@ protected: bool updating; /// Flag telling if an updater thread is currently processing bool newUpdatePending; /// Flag telling the updater thread that a new update is pending int skip; + int padding; /// Minimum space allowed around image in the display area int cropx, cropy, cropw, croph; /// size of the detail crop image ('skip' taken into account), with border int trafx, trafy, trafw, trafh; /// the size and position to get from the imagesource that is transformed to the requested crop area int rqcropx, rqcropy, rqcropw, rqcroph; /// size of the requested detail crop image (the image might be smaller) (without border) @@ -70,7 +71,7 @@ protected: ImProcCoordinator* parent; bool isDetailWindow; EditUniqueID getCurrEditID(); - bool setCropSizes (int cx, int cy, int cw, int ch, int skip, bool internal); + bool setCropSizes (int cropX, int cropY, int cropW, int cropH, int skip, bool internal); void freeAll (); public: @@ -91,9 +92,9 @@ public: return cropImageListener; } void update (int todo); - void setWindow (int cx, int cy, int cw, int ch, int skip) + void setWindow (int cropX, int cropY, int cropW, int cropH, int skip) { - setCropSizes (cx, cy, cw, ch, skip, false); + setCropSizes (cropX, cropY, cropW, cropH, skip, false); } /** @brief Synchronously look out if a full update is necessary @@ -109,6 +110,10 @@ public: { return skip; } + int getPadding () + { + return padding; + } int getLeftBorder () { return leftBorder; diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index 5f5e07139..c6d66e4bf 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -22,7 +22,6 @@ #include "rawimagesource.h" #include "rawimagesource_i.h" #include "jaggedarray.h" -#include "median.h" #include "rawimage.h" #include "mytime.h" #include "iccmatrices.h" @@ -37,7 +36,8 @@ #include "procparams.h" #include "sleef.c" #include "opthelper.h" - +//#define BENCHMARK +#include "StopWatch.h" #ifdef _OPENMP #include #endif @@ -90,17 +90,17 @@ void RawImageSource::eahd_demosaic () threshold = (int)(0.008856 * MAXVALD); for (int i = 0; i < maxindex; i++) { - cache[i] = exp(1.0 / 3.0 * log(double(i) / MAXVALD)); + cache[i] = std::cbrt(double(i) / MAXVALD); } // end of cielab preparation const JaggedArray - rh (W, 3), gh (W, 4), bh (W, 3), - rv (W, 3), gv (W, 4), bv (W, 3), - lLh (W, 3), lah (W, 3), lbh (W, 3), - lLv (W, 3), lav (W, 3), lbv (W, 3), - homh (W, 3), homv (W, 3); + rh (W, 3), gh (W, 4), bh (W, 3), + rv (W, 3), gv (W, 4), bv (W, 3), + lLh (W, 3), lah (W, 3), lbh (W, 3), + lLv (W, 3), lav (W, 3), lbv (W, 3), + homh (W, 3), homv (W, 3); // interpolate first two lines interpolate_row_g (gh[0], gv[0], 0); @@ -2703,7 +2703,7 @@ void RawImageSource::ahd_demosaic(int winx, int winy, int winw, int winh) for (i = 0; i < 0x10000; i++) { r = (double)i / 65535.0; - cbrt[i] = r > 0.008856 ? pow(r, 0.333333333) : 7.787 * r + 16 / 116.0; + cbrt[i] = r > 0.008856 ? std::cbrt(r) : 7.787 * r + 16 / 116.0; } for (i = 0; i < 3; i++) @@ -3887,17 +3887,14 @@ const float d65_white[3] = { 0.950456, 1, 1.088754 }; void RawImageSource::cielab (const float (*rgb)[3], float* l, float* a, float *b, const int width, const int height, const int labWidth, const float xyz_cam[3][3]) { - static float cbrt[0x10000]; + static LUTf cbrt(0x14000); static bool cbrtinit = false; if (!rgb) { - int i, j, k; - float r; - if(!cbrtinit) { - for (i = 0; i < 0x10000; i++) { - r = i / 65535.f; - cbrt[i] = r > 0.008856f ? xcbrtf(r) : 7.787f * r + 16.f / 116.f; + for (int i = 0; i < 0x14000; i++) { + double r = i / 65535.0; + cbrt[i] = r > 0.008856f ? std::cbrt(r) : 7.787f * r + 16.f / 116.f; } cbrtinit = true; @@ -3906,20 +3903,55 @@ void RawImageSource::cielab (const float (*rgb)[3], float* l, float* a, float *b return; } - int rgbOffset = (width - labWidth); +#if defined( __SSE2__ ) && defined( __x86_64__ ) + vfloat zd5v = F2V(0.5f); + vfloat c116v = F2V(116.f); + vfloat c16v = F2V(16.f); + vfloat c500v = F2V(500.f); + vfloat c200v = F2V(200.f); + vfloat xyz_camv[3][3]; + + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3; j++) { + xyz_camv[i][j] = F2V(xyz_cam[i][j]); + } + +#endif // __SSE2__ for(int i = 0; i < height; i++) { - for(int j = 0; j < labWidth; j++) { - float xyz[3] = {0.5f}; - int c; - FORC3 { - xyz[0] += xyz_cam[0][c] * rgb[i * width + j][c]; - xyz[1] += xyz_cam[1][c] * rgb[i * width + j][c]; - xyz[2] += xyz_cam[2][c] * rgb[i * width + j][c]; + int j = 0; +#if defined( __SSE2__ ) && defined( __x86_64__ ) // vectorized LUT access is restricted to __x86_64__ => we have to use the same restriction + + for(; j < labWidth - 3; j += 4) { + vfloat redv, greenv, bluev; + vconvertrgbrgbrgbrgb2rrrrggggbbbb(rgb[i * width + j], redv, greenv, bluev); + vfloat xyz0v = zd5v + redv * xyz_camv[0][0] + greenv * xyz_camv[0][1] + bluev * xyz_camv[0][2]; + vfloat xyz1v = zd5v + redv * xyz_camv[1][0] + greenv * xyz_camv[1][1] + bluev * xyz_camv[1][2]; + vfloat xyz2v = zd5v + redv * xyz_camv[2][0] + greenv * xyz_camv[2][1] + bluev * xyz_camv[2][2]; + xyz0v = cbrt[_mm_cvttps_epi32(xyz0v)]; + xyz1v = cbrt[_mm_cvttps_epi32(xyz1v)]; + xyz2v = cbrt[_mm_cvttps_epi32(xyz2v)]; + + STVFU(l[i * labWidth + j], c116v * xyz1v - c16v); + STVFU(a[i * labWidth + j], c500v * (xyz0v - xyz1v)); + STVFU(b[i * labWidth + j], c200v * (xyz1v - xyz2v)); + } + +#endif + + for(; j < labWidth; j++) { + float xyz[3] = {0.5f, 0.5f, 0.5f}; + + for(int c = 0; c < 3; c++) { + float val = rgb[i * width + j][c]; + xyz[0] += xyz_cam[0][c] * val; + xyz[1] += xyz_cam[1][c] * val; + xyz[2] += xyz_cam[2][c] * val; } - xyz[0] = cbrt[CLIP((int) xyz[0])]; - xyz[1] = cbrt[CLIP((int) xyz[1])]; - xyz[2] = cbrt[CLIP((int) xyz[2])]; + + xyz[0] = cbrt[(int) xyz[0]]; + xyz[1] = cbrt[(int) xyz[1]]; + xyz[2] = cbrt[(int) xyz[2]]; l[i * labWidth + j] = 116 * xyz[1] - 16; a[i * labWidth + j] = 500 * (xyz[0] - xyz[1]); @@ -3929,6 +3961,7 @@ void RawImageSource::cielab (const float (*rgb)[3], float* l, float* a, float *b } #define fcol(row,col) xtrans[(row)%6][(col)%6] +#define isgreen(row,col) (xtrans[(row)%3][(col)%3]&1) void RawImageSource::xtransborder_interpolate (int border) { @@ -3982,11 +4015,14 @@ void RawImageSource::xtransborder_interpolate (int border) Frank Markesteijn's algorithm for Fuji X-Trans sensors adapted to RT by Ingo Weyrich 2014 */ - -#define TS 122 /* Tile Size */ - -void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) +// override CLIP function to test unclipped output +#define CLIP(x) (x) +void RawImageSource::xtrans_interpolate (const int passes, const bool useCieLab) { + BENCHFUN + constexpr int ts = 114; /* Tile Size */ + constexpr int tsh = ts / 2; /* half of Tile Size */ + double progress = 0.0; const bool plistenerActive = plistener; @@ -3998,13 +4034,11 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) char xtrans[6][6]; ri->getXtransMatrix(xtrans); - static const short orth[12] = { 1, 0, 0, 1, -1, 0, 0, -1, 1, 0, 0, 1 }, + constexpr short orth[12] = { 1, 0, 0, 1, -1, 0, 0, -1, 1, 0, 0, 1 }, patt[2][16] = { { 0, 1, 0, -1, 2, 0, -1, 0, 1, 1, 1, -1, 0, 0, 0, 0 }, { 0, 1, 0, -2, 1, 0, -2, 0, 1, 1, -2, -2, 1, -1, -1, 1 } }, - dir[4] = { 1, TS, TS + 1, TS - 1 }; - - short allhex[2][3][3][8]; + dir[4] = { 1, ts, ts + 1, ts - 1 }; // sgrow/sgcol is the offset in the sensor matrix of the solitary // green pixels @@ -4032,15 +4066,16 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) } /* Map a green hexagon around each non-green pixel and vice versa: */ + short allhex[2][3][3][8]; { int gint, d, h, v, ng, row, col, c; for (row = 0; row < 3; row++) for (col = 0; col < 3; col++) { - gint = fcol(row, col) == 1; + gint = isgreen(row, col); for (ng = d = 0; d < 10; d += 2) { - if (fcol(row + orth[d] + 6, col + orth[d + 2] + 6) == 1) { + if (isgreen(row + orth[d] + 6, col + orth[d + 2] + 6)) { ng = 0; } else { ng++; @@ -4058,7 +4093,7 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) v = orth[d] * patt[gint][c * 2] + orth[d + 1] * patt[gint][c * 2 + 1]; h = orth[d + 2] * patt[gint][c * 2] + orth[d + 3] * patt[gint][c * 2 + 1]; allhex[0][row][col][c ^ (gint * 2 & d)] = h + v * width; - allhex[1][row][col][c ^ (gint * 2 & d)] = h + v * TS; + allhex[1][row][col][c ^ (gint * 2 & d)] = h + v * ts; } } } @@ -4071,7 +4106,7 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) } - double progressInc = 36.0 * (1.0 - progress) / ((H * W) / ((TS - 16) * (TS - 16))); + double progressInc = 36.0 * (1.0 - progress) / ((H * W) / ((ts - 16) * (ts - 16))); const int ndir = 4 << (passes > 1); cielab (0, 0, 0, 0, 0, 0, 0, 0); struct s_minmaxgreen { @@ -4079,109 +4114,145 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) float max; }; - int RightShift[6]; + int RightShift[3]; - for(int row = 0; row < 6; row++) { + for(int row = 0; row < 3; row++) { // count number of green pixels in three cols int greencount = 0; for(int col = 0; col < 3; col++) { - greencount += (fcol(row, col) == 1); + greencount += isgreen(row, col); } RightShift[row] = (greencount == 2); } - +#ifdef _OPENMP #pragma omp parallel +#endif { int progressCounter = 0; - short *hex; - int c, d, f, h, i, v, mrow, mcol; - int pass; - float color[3][8], g, val; - float (*rgb)[TS][TS][3], (*rix)[3]; - float (*lab)[TS - 8][TS - 8]; - float (*drv)[TS - 10][TS - 10], diff[6], tr; - s_minmaxgreen (*greenminmaxtile)[TS]; - uint8_t (*homo)[TS][TS]; - uint8_t (*homosum)[TS][TS]; - float *buffer; - buffer = (float *) malloc ((TS * TS * (ndir * 3 + 11) + 128) * sizeof(float)); - rgb = (float(*)[TS][TS][3]) buffer; - lab = (float (*) [TS - 8][TS - 8])(buffer + TS * TS * (ndir * 3)); - drv = (float (*)[TS - 10][TS - 10]) (buffer + TS * TS * (ndir * 3 + 3)); - homo = (uint8_t (*)[TS][TS]) (lab); // we can reuse the lab-buffer because they are not used together - greenminmaxtile = (s_minmaxgreen(*)[TS]) (lab); // we can reuse the lab-buffer because they are not used together - homosum = (uint8_t (*)[TS][TS]) (drv); // we can reuse the drv-buffer because they are not used together + int c; + float color[3][6]; + float *buffer = (float *) malloc ((ts * ts * (ndir * 4 + 3) + 128) * sizeof(float)); + float (*rgb)[ts][ts][3] = (float(*)[ts][ts][3]) buffer; + float (*lab)[ts - 8][ts - 8] = (float (*)[ts - 8][ts - 8])(buffer + ts * ts * (ndir * 3)); + float (*drv)[ts - 10][ts - 10] = (float (*)[ts - 10][ts - 10]) (buffer + ts * ts * (ndir * 3 + 3)); + uint8_t (*homo)[ts][ts] = (uint8_t (*)[ts][ts]) (lab); // we can reuse the lab-buffer because they are not used together + s_minmaxgreen (*greenminmaxtile)[tsh] = (s_minmaxgreen(*)[tsh]) (lab); // we can reuse the lab-buffer because they are not used together + uint8_t (*homosum)[ts][ts] = (uint8_t (*)[ts][ts]) (drv); // we can reuse the drv-buffer because they are not used together + uint8_t (*homosummax)[ts] = (uint8_t (*)[ts]) homo[ndir - 1]; // we can reuse the homo-buffer because they are not used together + +#ifdef _OPENMP #pragma omp for collapse(2) schedule(dynamic) nowait +#endif - for (int top = 3; top < height - 19; top += TS - 16) - for (int left = 3; left < width - 19; left += TS - 16) { - int mrow = MIN (top + TS, height - 3); - int mcol = MIN (left + TS, width - 3); - memset(rgb, 0, TS * TS * 3 * sizeof(float)); + for (int top = 3; top < height - 19; top += ts - 16) + for (int left = 3; left < width - 19; left += ts - 16) { + int mrow = MIN (top + ts, height - 3); + int mcol = MIN (left + ts, width - 3); + + /* Set greenmin and greenmax to the minimum and maximum allowed values: */ + for (int row = top; row < mrow; row++) { + // find first non-green pixel + int leftstart = left; + + for(; leftstart < mcol; leftstart++) + if(!isgreen(row, leftstart)) { + break; + } + + int coloffset = (RightShift[row % 3] == 1 ? 3 : 1 + (fcol(row, leftstart + 1) & 1)); + + if(coloffset == 3) { + short *hex = allhex[0][row % 3][leftstart % 3]; + + for (int col = leftstart; col < mcol; col += coloffset) { + float minval = FLT_MAX; + float maxval = 0.f; + float *pix = &rawData[row][col]; + + for(int c = 0; c < 6; c++) { + float val = pix[hex[c]]; + + minval = minval < val ? minval : val; + maxval = maxval > val ? maxval : val; + } + + greenminmaxtile[row - top][(col - left) >> 1].min = minval; + greenminmaxtile[row - top][(col - left) >> 1].max = maxval; + } + } else { + float minval = FLT_MAX; + float maxval = 0.f; + int col = leftstart; + + if(coloffset == 2) { + minval = FLT_MAX; + maxval = 0.f; + float *pix = &rawData[row][col]; + short *hex = allhex[0][row % 3][col % 3]; + + for(int c = 0; c < 6; c++) { + float val = pix[hex[c]]; + + minval = minval < val ? minval : val; + maxval = maxval > val ? maxval : val; + } + + greenminmaxtile[row - top][(col - left) >> 1].min = minval; + greenminmaxtile[row - top][(col - left) >> 1].max = maxval; + col += 2; + } + + short *hex = allhex[0][row % 3][col % 3]; + + for (; col < mcol - 1; col += 3) { + minval = FLT_MAX; + maxval = 0.f; + float *pix = &rawData[row][col]; + + for(int c = 0; c < 6; c++) { + float val = pix[hex[c]]; + + minval = minval < val ? minval : val; + maxval = maxval > val ? maxval : val; + } + + greenminmaxtile[row - top][(col - left) >> 1].min = minval; + greenminmaxtile[row - top][(col - left) >> 1].max = maxval; + greenminmaxtile[row - top][(col + 1 - left) >> 1].min = minval; + greenminmaxtile[row - top][(col + 1 - left) >> 1].max = maxval; + } + + if(col < mcol) { + minval = FLT_MAX; + maxval = 0.f; + float *pix = &rawData[row][col]; + + for(int c = 0; c < 6; c++) { + float val = pix[hex[c]]; + + minval = minval < val ? minval : val; + maxval = maxval > val ? maxval : val; + } + + greenminmaxtile[row - top][(col - left) >> 1].min = minval; + greenminmaxtile[row - top][(col - left) >> 1].max = maxval; + } + } + } + + memset(rgb, 0, ts * ts * 3 * sizeof(float)); for (int row = top; row < mrow; row++) for (int col = left; col < mcol; col++) { rgb[0][row - top][col - left][fcol(row, col)] = rawData[row][col]; } - FORC3 memcpy (rgb[c + 1], rgb[0], sizeof * rgb); - - /* Set green1 and green3 to the minimum and maximum allowed values: */ - for (int row = top; row < mrow; row++) { - float minval = FLT_MAX; - float maxval = 0.f; - int shiftindex = RightShift[(row) % 6]; - - for (int col = left; col < mcol; col++) { - if (fcol(row, col) == 1) { - minval = FLT_MAX; - maxval = 0.f; - continue; - } - - float *pix = &rawData[row][col]; - hex = allhex[0][row % 3][col % 3]; - - if (maxval == 0.f) - FORC(6) { - val = pix[hex[c]]; - - if (minval > val) { - minval = val; - } - - if (maxval < val) { - maxval = val; - } - } - - greenminmaxtile[row - top][(col - left) >> shiftindex].min = minval; - greenminmaxtile[row - top][(col - left) >> shiftindex].max = maxval; - - switch ((row - sgrow) % 3) { - case 1: - if (row < mrow - 1) { - row++; - shiftindex = RightShift[(row) % 6]; - col--; - } - - break; - - case 2: - minval = FLT_MAX; - maxval = 0.f; - - if ((col += 2) < mcol - 1 && row > top + 1) { - row--; - shiftindex = RightShift[(row) % 6]; - } - } - } + for(int c = 0; c < 3; c++) { + memcpy (rgb[c + 1], rgb[0], sizeof * rgb); } /* Interpolate green horizontally, vertically, and along both diagonals: */ @@ -4190,33 +4261,57 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) int leftstart = left; for(; leftstart < mcol; leftstart++) - if(fcol(row, leftstart) != 1) { + if(!isgreen(row, leftstart)) { break; } - const int shiftindex = RightShift[(row) % 6]; - const int coloffset = (shiftindex == 1 ? 3 : 1); + int coloffset = (RightShift[row % 3] == 1 ? 3 : 1 + (fcol(row, leftstart + 1) & 1)); - for (int col = leftstart; col < mcol; col += coloffset) { - if (fcol(row, col) == 1) { - continue; + if(coloffset == 3) { + short *hex = allhex[0][row % 3][leftstart % 3]; + + for (int col = leftstart; col < mcol; col += coloffset) { + float *pix = &rawData[row][col]; + float color[4]; + color[0] = 0.6796875f * (pix[hex[1]] + pix[hex[0]]) - + 0.1796875f * (pix[2 * hex[1]] + pix[2 * hex[0]]); + color[1] = 0.87109375f * pix[hex[3]] + pix[hex[2]] * 0.12890625f + + 0.359375f * (pix[0] - pix[-hex[2]]); + + for(int c = 0; c < 2; c++) + color[2 + c] = 0.640625f * pix[hex[4 + c]] + 0.359375f * pix[-2 * hex[4 + c]] + 0.12890625f * + (2.f * pix[0] - pix[3 * hex[4 + c]] - pix[-3 * hex[4 + c]]); + + for(int c = 0; c < 4; c++) { + rgb[c][row - top][col - left][1] = LIM(color[c], greenminmaxtile[row - top][(col - left) >> 1].min, greenminmaxtile[row - top][(col - left) >> 1].max); + } } + } else { + short *hexmod[2]; + hexmod[0] = allhex[0][row % 3][leftstart % 3]; + hexmod[1] = allhex[0][row % 3][(leftstart + coloffset) % 3]; - float *pix = &rawData[row][col]; - hex = allhex[0][row % 3][col % 3]; - color[1][0] = 0.6796875f * (pix[hex[1]] + pix[hex[0]]) - - 0.1796875f * (pix[2 * hex[1]] + pix[2 * hex[0]]); - color[1][1] = 0.87109375f * pix[hex[3]] + pix[hex[2]] * 0.12890625f + - 0.359375f * (pix[0] - pix[-hex[2]]); - FORC(2) - color[1][2 + c] = 0.640625f * pix[hex[4 + c]] + 0.359375f * pix[-2 * hex[4 + c]] + 0.12890625f * - (2.f * pix[0] - pix[3 * hex[4 + c]] - pix[-3 * hex[4 + c]]); - FORC(4) - rgb[c ^ !((row - sgrow) % 3)][row - top][col - left][1] = LIM(color[1][c], greenminmaxtile[row - top][(col - left) >> shiftindex].min, greenminmaxtile[row - top][(col - left) >> shiftindex].max); + for (int col = leftstart, hexindex = 0; col < mcol; col += coloffset, coloffset ^= 3, hexindex ^= 1) { + float *pix = &rawData[row][col]; + short *hex = hexmod[hexindex]; + float color[4]; + color[0] = 0.6796875f * (pix[hex[1]] + pix[hex[0]]) - + 0.1796875f * (pix[2 * hex[1]] + pix[2 * hex[0]]); + color[1] = 0.87109375f * pix[hex[3]] + pix[hex[2]] * 0.12890625f + + 0.359375f * (pix[0] - pix[-hex[2]]); + + for(int c = 0; c < 2; c++) + color[2 + c] = 0.640625f * pix[hex[4 + c]] + 0.359375f * pix[-2 * hex[4 + c]] + 0.12890625f * + (2.f * pix[0] - pix[3 * hex[4 + c]] - pix[-3 * hex[4 + c]]); + + for(int c = 0; c < 4; c++) { + rgb[c ^ 1][row - top][col - left][1] = LIM(color[c], greenminmaxtile[row - top][(col - left) >> 1].min, greenminmaxtile[row - top][(col - left) >> 1].max); + } + } } } - for (pass = 0; pass < passes; pass++) { + for (int pass = 0; pass < passes; pass++) { if (pass == 1) { memcpy (rgb += 4, buffer, 4 * sizeof * rgb); } @@ -4227,40 +4322,55 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) int leftstart = left + 2; for(; leftstart < mcol - 2; leftstart++) - if(fcol(row, leftstart) != 1) { + if(!isgreen(row, leftstart)) { break; } - const int shiftindex = RightShift[(row) % 6]; - const int coloffset = (shiftindex == 1 ? 3 : 1); + int coloffset = (RightShift[row % 3] == 1 ? 3 : 1 + (fcol(row, leftstart + 1) & 1)); - for (int col = leftstart; col < mcol - 2; col += coloffset) { - if ((f = fcol(row, col)) == 1) { - continue; + if(coloffset == 3) { + int f = fcol(row, leftstart); + short *hex = allhex[1][row % 3][leftstart % 3]; + + for (int col = leftstart; col < mcol - 2; col += coloffset, f ^= 2) { + for (int d = 3; d < 6; d++) { + float (*rix)[3] = &rgb[(d - 2)][row - top][col - left]; + float val = 0.33333333f * (rix[-2 * hex[d]][1] + 2 * (rix[hex[d]][1] - rix[hex[d]][f]) + - rix[-2 * hex[d]][f]) + rix[0][f]; + rix[0][1] = LIM(val, greenminmaxtile[row - top][(col - left) >> 1].min, greenminmaxtile[row - top][(col - left) >> 1].max); + } } + } else { + int f = fcol(row, leftstart); + short *hexmod[2]; + hexmod[0] = allhex[1][row % 3][leftstart % 3]; + hexmod[1] = allhex[1][row % 3][(leftstart + coloffset) % 3]; - hex = allhex[1][row % 3][col % 3]; + for (int col = leftstart, hexindex = 0; col < mcol - 2; col += coloffset, coloffset ^= 3, f = f ^ (coloffset & 2), hexindex ^= 1 ) { + short *hex = hexmod[hexindex]; - for (d = 3; d < 6; d++) { - rix = &rgb[(d - 2) ^ !((row - sgrow) % 3)][row - top][col - left]; - val = rix[-2 * hex[d]][1] + 2 * (rix[hex[d]][1] - rix[hex[d]][f]) - - rix[-2 * hex[d]][f] + 3 * rix[0][f]; - rix[0][1] = LIM((float)(val * .33333333f), greenminmaxtile[row - top][(col - left) >> shiftindex].min, greenminmaxtile[row - top][(col - left) >> shiftindex].max); + for (int d = 3; d < 6; d++) { + float (*rix)[3] = &rgb[(d - 2) ^ 1][row - top][col - left]; + float val = 0.33333333f * (rix[-2 * hex[d]][1] + 2 * (rix[hex[d]][1] - rix[hex[d]][f]) + - rix[-2 * hex[d]][f]) + rix[0][f]; + rix[0][1] = LIM(val, greenminmaxtile[row - top][(col - left) >> 1].min, greenminmaxtile[row - top][(col - left) >> 1].max); + } } } } } /* Interpolate red and blue values for solitary green pixels: */ - for (int row = (top - sgrow + 4) / 3 * 3 + sgrow; row < mrow - 2; row += 3) - for (int col = (left - sgcol + 4) / 3 * 3 + sgcol; col < mcol - 2; col += 3) { - rix = &rgb[0][row - top][col - left]; - h = fcol(row, col + 1); - memset (diff, 0, sizeof diff); + int sgstartcol = (left - sgcol + 4) / 3 * 3 + sgcol; - for (i = 1, d = 0; d < 6; d++, i ^= TS ^ 1, h ^= 2) { - for (c = 0; c < 2; c++, h ^= 2) { - g = rix[0][1] + rix[0][1] - rix[i << c][1] - rix[-i << c][1]; + for (int row = (top - sgrow + 4) / 3 * 3 + sgrow; row < mrow - 2; row += 3) { + for (int col = sgstartcol, h = fcol(row, col + 1); col < mcol - 2; col += 3, h ^= 2) { + float (*rix)[3] = &rgb[0][row - top][col - left]; + float diff[6] = {0.f}; + + for (int i = 1, d = 0; d < 6; d++, i ^= ts ^ 1, h ^= 2) { + for (int c = 0; c < 2; c++, h ^= 2) { + float g = rix[0][1] + rix[0][1] - rix[i << c][1] - rix[-i << c][1]; color[h][d] = g + rix[i << c][h] + rix[-i << c][h]; if (d > 1) @@ -4270,75 +4380,114 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) if (d > 2 && (d & 1)) // 3, 5 if (diff[d - 1] < diff[d]) - FORC(2) - color[c * 2][d] = color[c * 2][d - 1]; + for(int c = 0; c < 2; c++) { + color[c * 2][d] = color[c * 2][d - 1]; + } if ((d & 1) || d < 2) { // d: 0, 1, 3, 5 - FORC(2) - rix[0][c * 2] = CLIP(0.5f * color[c * 2][d]); - rix += TS * TS; + for(int c = 0; c < 2; c++) { + rix[0][c * 2] = CLIP(0.5f * color[c * 2][d]); + } + + rix += ts * ts; } } } + } /* Interpolate red for blue pixels and vice versa: */ for (int row = top + 3; row < mrow - 3; row++) { int leftstart = left + 3; for(; leftstart < mcol - 1; leftstart++) - if(fcol(row, leftstart) != 1) { + if(!isgreen(row, leftstart)) { break; } - const int coloffset = (RightShift[(row) % 6] == 1 ? 3 : 1); - c = (row - sgrow) % 3 ? TS : 1; - h = 3 * (c ^ TS ^ 1); + int coloffset = (RightShift[row % 3] == 1 ? 3 : 1); + c = (row - sgrow) % 3 ? ts : 1; + int h = 3 * (c ^ ts ^ 1); - for (int col = leftstart; col < mcol - 3; col += coloffset) { - if ((f = 2 - fcol(row, col)) == 1) { - continue; + if(coloffset == 3) { + int f = 2 - fcol(row, leftstart); + + for (int col = leftstart; col < mcol - 3; col += coloffset, f ^= 2) { + float (*rix)[3] = &rgb[0][row - top][col - left]; + + for (int d = 0; d < 4; d++, rix += ts * ts) { + int i = d > 1 || ((d ^ c) & 1) || + ((fabsf(rix[0][1] - rix[c][1]) + fabsf(rix[0][1] - rix[-c][1])) < 2.f * (fabsf(rix[0][1] - rix[h][1]) + fabsf(rix[0][1] - rix[-h][1]))) ? c : h; + + rix[0][f] = CLIP(rix[0][1] + 0.5f * (rix[i][f] + rix[-i][f] - rix[i][1] - rix[-i][1])); + } } + } else { + coloffset = fcol(row, leftstart + 1) == 1 ? 2 : 1; + int f = 2 - fcol(row, leftstart); - rix = &rgb[0][row - top][col - left]; + for (int col = leftstart; col < mcol - 3; col += coloffset, coloffset ^= 3, f = f ^ (coloffset & 2) ) { + float (*rix)[3] = &rgb[0][row - top][col - left]; - for (d = 0; d < 4; d++, rix += TS * TS) { - i = d > 1 || ((d ^ c) & 1) || - ((fabsf(rix[0][1] - rix[c][1]) + fabsf(rix[0][1] - rix[-c][1])) < 2.f * (fabsf(rix[0][1] - rix[h][1]) + fabsf(rix[0][1] - rix[-h][1]))) ? c : h; + for (int d = 0; d < 4; d++, rix += ts * ts) { + int i = d > 1 || ((d ^ c) & 1) || + ((fabsf(rix[0][1] - rix[c][1]) + fabsf(rix[0][1] - rix[-c][1])) < 2.f * (fabsf(rix[0][1] - rix[h][1]) + fabsf(rix[0][1] - rix[-h][1]))) ? c : h; - rix[0][f] = CLIP(0.5f * (rix[i][f] + rix[-i][f] + - rix[0][1] + rix[0][1] - rix[i][1] - rix[-i][1])); + rix[0][f] = CLIP(rix[0][1] + 0.5f * (rix[i][f] + rix[-i][f] - rix[i][1] - rix[-i][1])); + } } } } /* Fill in red and blue for 2x2 blocks of green: */ - for (int row = top + 2; row < mrow - 2; row++) - if ((row - sgrow) % 3) { - for (int col = left + 2; col < mcol - 2; col++) - if ((col - sgcol) % 3) { - rix = &rgb[0][row - top][col - left]; - hex = allhex[1][row % 3][col % 3]; + // Find first row of 2x2 green + int topstart = top + 2; - for (d = 0; d < ndir; d += 2, rix += TS * TS) - if (hex[d] + hex[d + 1]) { - g = 3 * rix[0][1] - 2 * rix[hex[d]][1] - rix[hex[d + 1]][1]; - - for (c = 0; c < 4; c += 2) { - rix[0][c] = CLIP((g + 2 * rix[hex[d]][c] + rix[hex[d + 1]][c]) * 0.33333333f); - } - } else { - g = 2 * rix[0][1] - rix[hex[d]][1] - rix[hex[d + 1]][1]; - - for (c = 0; c < 4; c += 2) { - rix[0][c] = CLIP((g + rix[hex[d]][c] + rix[hex[d + 1]][c]) * 0.5f); - } - } - } + for(; topstart < mrow - 2; topstart++) + if((topstart - sgrow) % 3) { + break; } + + int leftstart = left + 2; + + for(; leftstart < mcol - 2; leftstart++) + if((leftstart - sgcol) % 3) { + break; + } + + int coloffsetstart = 2 - (fcol(topstart, leftstart + 1) & 1); + + for (int row = topstart; row < mrow - 2; row++) { + if ((row - sgrow) % 3) { + short *hexmod[2]; + hexmod[0] = allhex[1][row % 3][leftstart % 3]; + hexmod[1] = allhex[1][row % 3][(leftstart + coloffsetstart) % 3]; + + for (int col = leftstart, coloffset = coloffsetstart, hexindex = 0; col < mcol - 2; col += coloffset, coloffset ^= 3, hexindex ^= 1) { + float (*rix)[3] = &rgb[0][row - top][col - left]; + short *hex = hexmod[hexindex]; + + for (int d = 0; d < ndir; d += 2, rix += ts * ts) { + if (hex[d] + hex[d + 1]) { + float g = 3 * rix[0][1] - 2 * rix[hex[d]][1] - rix[hex[d + 1]][1]; + + for (c = 0; c < 4; c += 2) { + rix[0][c] = CLIP((g + 2 * rix[hex[d]][c] + rix[hex[d + 1]][c]) * 0.33333333f); + } + } else { + float g = 2 * rix[0][1] - rix[hex[d]][1] - rix[hex[d + 1]][1]; + + for (c = 0; c < 4; c += 2) { + rix[0][c] = CLIP((g + rix[hex[d]][c] + rix[hex[d + 1]][c]) * 0.5f); + } + } + } + } + } + } } // end of multipass part - rgb = (float(*)[TS][TS][3]) buffer; + rgb = (float(*)[ts][ts][3]) buffer; mrow -= top; mcol -= left; @@ -4347,21 +4496,24 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) // Original dcraw algorithm uses CIELab as perceptual space // (presumably coming from original AHD) and converts taking // camera matrix into account. We use this in RT. - for (d = 0; d < ndir; d++) { + for (int d = 0; d < ndir; d++) { float *l = &lab[0][0][0]; float *a = &lab[1][0][0]; float *b = &lab[2][0][0]; - cielab(&rgb[d][4][4], l, a, b, TS, mrow - 8, TS - 8, xyz_cam); + cielab(&rgb[d][4][4], l, a, b, ts, mrow - 8, ts - 8, xyz_cam); int f = dir[d & 3]; f = f == 1 ? 1 : f - 8; for (int row = 5; row < mrow - 5; row++) +#ifdef _OPENMP + #pragma omp simd +#endif for (int col = 5; col < mcol - 5; col++) { float *l = &lab[0][row - 4][col - 4]; float *a = &lab[1][row - 4][col - 4]; float *b = &lab[2][row - 4][col - 4]; - g = 2 * l[0] - l[f] - l[-f]; + float g = 2 * l[0] - l[f] - l[-f]; drv[d][row - 5][col - 5] = SQR(g) + SQR((2 * a[0] - a[f] - a[-f] + g * 2.1551724f)) + SQR((2 * b[0] - b[f] - b[-f] - g * 0.86206896f)); @@ -4369,15 +4521,39 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) } } else { - // Now use YPbPr which requires much + // For 1-pass demosaic we use YPbPr which requires much // less code and is nearly indistinguishable. It assumes the // camera RGB is roughly linear. - // - for (d = 0; d < ndir; d++) { - float (*yuv)[TS - 8][TS - 8] = lab; // we use the lab buffer, which has the same dimensions + for (int d = 0; d < ndir; d++) { + float (*yuv)[ts - 8][ts - 8] = lab; // we use the lab buffer, which has the same dimensions +#ifdef __SSE2__ + vfloat zd2627v = F2V(0.2627f); + vfloat zd6780v = F2V(0.6780f); + vfloat zd0593v = F2V(0.0593f); + vfloat zd56433v = F2V(0.56433f); + vfloat zd67815v = F2V(0.67815f); +#endif - for (int row = 4; row < mrow - 4; row++) - for (int col = 4; col < mcol - 4; col++) { + for (int row = 4; row < mrow - 4; row++) { + int col = 4; +#ifdef __SSE2__ + + for (; col < mcol - 7; col += 4) { + // use ITU-R BT.2020 YPbPr, which is great, but could use + // a better/simpler choice? note that imageop.h provides + // dt_iop_RGB_to_YCbCr which uses Rec. 601 conversion, + // which appears less good with specular highlights + vfloat redv, greenv, bluev; + vconvertrgbrgbrgbrgb2rrrrggggbbbb(rgb[d][row][col], redv, greenv, bluev); + vfloat yv = zd2627v * redv + zd6780v * bluev + zd0593v * greenv; + STVFU(yuv[0][row - 4][col - 4], yv); + STVFU(yuv[1][row - 4][col - 4], (bluev - yv) * zd56433v); + STVFU(yuv[2][row - 4][col - 4], (redv - yv) * zd67815v); + } + +#endif + + for (; col < mcol - 4; col++) { // use ITU-R BT.2020 YPbPr, which is great, but could use // a better/simpler choice? note that imageop.h provides // dt_iop_RGB_to_YCbCr which uses Rec. 601 conversion, @@ -4387,6 +4563,7 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) yuv[1][row - 4][col - 4] = (rgb[d][row][col][2] - y) * 0.56433f; yuv[2][row - 4][col - 4] = (rgb[d][row][col][0] - y) * 0.67815f; } + } int f = dir[d & 3]; f = f == 1 ? 1 : f - 8; @@ -4404,79 +4581,188 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) } /* Build homogeneity maps from the derivatives: */ - memset(homo, 0, ndir * TS * TS * sizeof(uint8_t)); +#ifdef __SSE2__ + vfloat eightv = F2V(8.f); + vfloat zerov = F2V(0.f); + vfloat onev = F2V(1.f); +#endif - for (int row = 6; row < mrow - 6; row++) - for (int col = 6; col < mcol - 6; col++) { - for (tr = FLT_MAX, d = 0; d < ndir; d++) { + for (int row = 6; row < mrow - 6; row++) { + int col = 6; +#ifdef __SSE2__ + + for (; col < mcol - 9; col += 4) { + vfloat tr1v = vminf(LVFU(drv[0][row - 5][col - 5]), LVFU(drv[1][row - 5][col - 5])); + vfloat tr2v = vminf(LVFU(drv[2][row - 5][col - 5]), LVFU(drv[3][row - 5][col - 5])); + + if(ndir > 4) { + vfloat tr3v = vminf(LVFU(drv[4][row - 5][col - 5]), LVFU(drv[5][row - 5][col - 5])); + vfloat tr4v = vminf(LVFU(drv[6][row - 5][col - 5]), LVFU(drv[7][row - 5][col - 5])); + tr1v = vminf(tr1v, tr3v); + tr1v = vminf(tr1v, tr4v); + } + + tr1v = vminf(tr1v, tr2v); + tr1v = tr1v * eightv; + + for (int d = 0; d < ndir; d++) { + uint8_t tempstore[16]; + vfloat tempv = zerov; + + for (int v = -1; v <= 1; v++) { + for (int h = -1; h <= 1; h++) { + tempv += vselfzero(vmaskf_le(LVFU(drv[d][row + v - 5][col + h - 5]), tr1v), onev); + } + } + + _mm_storeu_si128((__m128i*)&tempstore, _mm_cvtps_epi32(tempv)); + homo[d][row][col] = tempstore[0]; + homo[d][row][col + 1] = tempstore[4]; + homo[d][row][col + 2] = tempstore[8]; + homo[d][row][col + 3] = tempstore[12]; + + } + } + +#endif + + for (; col < mcol - 6; col++) { + float tr = drv[0][row - 5][col - 5] < drv[1][row - 5][col - 5] ? drv[0][row - 5][col - 5] : drv[1][row - 5][col - 5]; + + for (int d = 2; d < ndir; d++) { tr = (drv[d][row - 5][col - 5] < tr ? drv[d][row - 5][col - 5] : tr); } tr *= 8; - for (d = 0; d < ndir; d++) - for (v = -1; v <= 1; v++) - for (h = -1; h <= 1; h++) { - homo[d][row][col] += (drv[d][row + v - 5][col + h - 5] <= tr ? 1 : 0) ; - } - } + for (int d = 0; d < ndir; d++) { + uint8_t temp = 0; - if (height - top < TS + 4) { + for (int v = -1; v <= 1; v++) { + for (int h = -1; h <= 1; h++) { + temp += (drv[d][row + v - 5][col + h - 5] <= tr ? 1 : 0); + } + } + + homo[d][row][col] = temp; + } + } + } + + if (height - top < ts + 4) { mrow = height - top + 2; } - if (width - left < TS + 4) { + if (width - left < ts + 4) { mcol = width - left + 2; } /* Build 5x5 sum of homogeneity maps */ - for(d = 0; d < ndir; d++) { + const int startcol = MIN(left, 8); + + for(int d = 0; d < ndir; d++) { for (int row = MIN(top, 8); row < mrow - 8; row++) { - int v5sum[5] = {0}; - const int startcol = MIN(left, 8); + int col = startcol; +#ifdef __SSE2__ + int endcol = row < mrow - 9 ? mcol - 8 : mcol - 23; - for(v = -2; v <= 2; v++) - for(h = -2; h <= 2; h++) { - v5sum[2 + h] += homo[d][row + v][startcol + h]; - } + // crunching 16 values at once is faster than summing up column sums + for (; col < endcol; col += 16) { + vint v5sumv = (vint)ZEROV; - int blocksum = v5sum[0] + v5sum[1] + v5sum[2] + v5sum[3] + v5sum[4]; - homosum[d][row][startcol] = blocksum; - int voffset = -1; + for(int v = -2; v <= 2; v++) + for(int h = -2; h <= 2; h++) { + v5sumv = _mm_adds_epu8( _mm_loadu_si128((vint*)&homo[d][row + v][col + h]), v5sumv); + } - // now we can subtract a column of five from blocksum and get new colsum of 5 - for (int col = startcol + 1; col < mcol - 8; col++) { - int colsum = homo[d][row - 2][col + 2]; + _mm_storeu_si128((vint*)&homosum[d][row][col], v5sumv); + } - for(v = -1; v <= 2; v++) { - colsum += homo[d][row + v][col + 2]; - } +#endif - voffset ++; - voffset = voffset == 5 ? 0 : voffset; // faster than voffset %= 5; - blocksum -= v5sum[voffset]; - blocksum += colsum; - v5sum[voffset] = colsum; + if(col < mcol - 8) { + int v5sum[5] = {0}; + + for(int v = -2; v <= 2; v++) + for(int h = -2; h <= 2; h++) { + v5sum[2 + h] += homo[d][row + v][col + h]; + } + + int blocksum = v5sum[0] + v5sum[1] + v5sum[2] + v5sum[3] + v5sum[4]; homosum[d][row][col] = blocksum; + col++; + + // now we can subtract a column of five from blocksum and get new colsum of 5 + for (int voffset = 0; col < mcol - 8; col++, voffset++) { + int colsum = homo[d][row - 2][col + 2] + homo[d][row - 1][col + 2] + homo[d][row][col + 2] + homo[d][row + 1][col + 2] + homo[d][row + 2][col + 2]; + voffset = voffset == 5 ? 0 : voffset; // faster than voffset %= 5; + blocksum -= v5sum[voffset]; + blocksum += colsum; + v5sum[voffset] = colsum; + homosum[d][row][col] = blocksum; + } } } } - /* Average the most homogenous pixels for the final result: */ + // calculate maximum of homogeneity maps per pixel. Vectorized calculation is a tiny bit faster than on the fly calculation in next step +#ifdef __SSE2__ + vint maskv = _mm_set1_epi8(31); +#endif + + for (int row = MIN(top, 8); row < mrow - 8; row++) { + int col = startcol; +#ifdef __SSE2__ + int endcol = row < mrow - 9 ? mcol - 8 : mcol - 23; + + for (; col < endcol; col += 16) { + vint maxval1 = _mm_max_epu8(_mm_loadu_si128((vint*)&homosum[0][row][col]), _mm_loadu_si128((vint*)&homosum[1][row][col])); + vint maxval2 = _mm_max_epu8(_mm_loadu_si128((vint*)&homosum[2][row][col]), _mm_loadu_si128((vint*)&homosum[3][row][col])); + + if(ndir > 4) { + vint maxval3 = _mm_max_epu8(_mm_loadu_si128((vint*)&homosum[4][row][col]), _mm_loadu_si128((vint*)&homosum[5][row][col])); + vint maxval4 = _mm_max_epu8(_mm_loadu_si128((vint*)&homosum[6][row][col]), _mm_loadu_si128((vint*)&homosum[7][row][col])); + maxval1 = _mm_max_epu8(maxval1, maxval3); + maxval1 = _mm_max_epu8(maxval1, maxval4); + } + + maxval1 = _mm_max_epu8(maxval1, maxval2); + // there is no shift intrinsic for epu8. Shift using epi32 and mask the wrong bits out + vint subv = _mm_srli_epi32( maxval1, 3 ); + subv = _mm_and_si128(subv, maskv); + maxval1 = _mm_subs_epu8(maxval1, subv); + _mm_storeu_si128((vint*)&homosummax[row][col], maxval1); + } + +#endif + + for (; col < mcol - 8; col ++) { + uint8_t maxval = homosum[0][row][col]; + + for(int d = 1; d < ndir; d++) { + maxval = maxval < homosum[d][row][col] ? homosum[d][row][col] : maxval; + } + + maxval -= maxval >> 3; + homosummax[row][col] = maxval; + } + } + + + /* Average the most homogeneous pixels for the final result: */ + uint8_t hm[8]; + for (int row = MIN(top, 8); row < mrow - 8; row++) for (int col = MIN(left, 8); col < mcol - 8; col++) { - uint8_t hm[8]; - uint8_t maxval = 0; + int d = 0; - for (d = 0; d < 4; d++) { + for (; d < 4; d++) { hm[d] = homosum[d][row][col]; - maxval = (maxval < hm[d] ? hm[d] : maxval); } for (; d < ndir; d++) { hm[d] = homosum[d][row][col]; - maxval = (maxval < hm[d] ? hm[d] : maxval); if (hm[d - 4] < hm[d]) { hm[d - 4] = 0; @@ -4485,18 +4771,19 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) } } - maxval -= maxval >> 3; float avg[4] = {0.f}; + uint8_t maxval = homosummax[row][col]; + for (d = 0; d < ndir; d++) if (hm[d] >= maxval) { FORC3 avg[c] += rgb[d][row][col][c]; avg[3]++; } - red[row + top][col + left] = (avg[0] / avg[3]); - green[row + top][col + left] = (avg[1] / avg[3]); - blue[row + top][col + left] = (avg[2] / avg[3]); + red[row + top][col + left] = avg[0] / avg[3]; + green[row + top][col + left] = avg[1] / avg[3]; + blue[row + top][col + left] = avg[2] / avg[3]; } if(plistenerActive && ((++progressCounter) % 32 == 0)) { @@ -4517,9 +4804,7 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) } } - -#undef TS - +#undef CLIP void RawImageSource::fast_xtrans_interpolate () { if (settings->verbose) { @@ -4579,7 +4864,7 @@ void RawImageSource::fast_xtrans_interpolate () } } #undef fcol - +#undef isgreen #undef TILEBORDER diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc index 19ab16cfb..10d2dff30 100644 --- a/rtengine/dfmanager.cc +++ b/rtengine/dfmanager.cc @@ -20,7 +20,6 @@ #include "../rtgui/options.h" #include #include "../rtgui/guiutils.h" -#include "safegtk.h" #include "rawimage.h" #include #include @@ -263,13 +262,21 @@ void dfInfo::updateBadPixelList( RawImage *df ) void DFManager::init( Glib::ustring pathname ) { std::vector names; - Glib::RefPtr dir = Gio::File::create_for_path (pathname); - if( dir && !dir->query_exists()) { + auto dir = Gio::File::create_for_path (pathname); + if (!dir || !dir->query_exists()) { return; } - safe_build_file_list (dir, names, pathname); + try { + + auto enumerator = dir->enumerate_children ("standard::name"); + + while (auto file = enumerator->next_file ()) { + names.emplace_back (Glib::build_filename (pathname, file->get_name ())); + } + + } catch (Glib::Exception&) {} dfList.clear(); bpList.clear(); @@ -320,65 +327,84 @@ void DFManager::init( Glib::ustring pathname ) return; } -dfInfo *DFManager::addFileInfo(const Glib::ustring &filename , bool pool ) +dfInfo* DFManager::addFileInfo (const Glib::ustring& filename, bool pool) { - Glib::RefPtr file = Gio::File::create_for_path(filename); + auto file = Gio::File::create_for_path (filename); - if (!file ) { + if (!file) { return 0; } - if( !file->query_exists()) { + if (!file->query_exists ()) { return 0; } - Glib::RefPtr info = safe_query_file_info(file); + try { - if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) { - size_t lastdot = info->get_name().find_last_of ('.'); + auto info = file->query_info (); - if (options.is_extention_enabled(lastdot != Glib::ustring::npos ? info->get_name().substr (lastdot + 1) : "")) { - RawImage ri(filename); - int res = ri.loadRaw(false); // Read informations about shot + if (!info && info->get_file_type () == Gio::FILE_TYPE_DIRECTORY) { + return 0; + } - if( !res ) { - dfList_t::iterator iter; + if (!options.fbShowHidden && info->is_hidden ()) { + return 0; + } - if(!pool) { - dfInfo n(filename, "", "", 0, 0, 0); - iter = dfList.insert(std::pair< std::string, dfInfo>( "", n ) ); - return &(iter->second); - } + Glib::ustring ext; - RawMetaDataLocation rml; - rml.exifBase = ri.get_exifBase(); - rml.ciffBase = ri.get_ciffBase(); - rml.ciffLength = ri.get_ciffLen(); - ImageData idata(filename, &rml); - /* 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 ); + auto lastdot = info->get_name ().find_last_of ('.'); + if (lastdot != Glib::ustring::npos) { + ext = info->get_name ().substr (lastdot + 1); + } - if( iter == dfList.end() ) { - dfInfo n(filename, ((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS() ); - iter = dfList.insert(std::pair< std::string, dfInfo>( key, n ) ); - } else { - while( iter != dfList.end() && iter->second.key() == key && ABS(iter->second.timestamp - idata.getDateTimeAsTS()) > 60 * 60 * 6 ) { // 6 hour difference - iter++; - } + if (!options.is_extention_enabled (ext)) { + return 0; + } - if( iter != dfList.end() ) { - iter->second.pathNames.push_back( filename ); - } else { - dfInfo n(filename, ((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS()); - iter = dfList.insert(std::pair< std::string, dfInfo>( key, n ) ); - } - } + RawImage ri (filename); + int res = ri.loadRaw (false); // Read informations about shot - return &(iter->second); + if (res != 0) { + return 0; + } + + dfList_t::iterator iter; + + if(!pool) { + dfInfo n(filename, "", "", 0, 0, 0); + iter = dfList.insert(std::pair< std::string, dfInfo>( "", n ) ); + return &(iter->second); + } + + RawMetaDataLocation rml; + rml.exifBase = ri.get_exifBase(); + rml.ciffBase = ri.get_ciffBase(); + rml.ciffLength = ri.get_ciffLen(); + ImageData idata(filename, &rml); + /* 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 ); + + if( iter == dfList.end() ) { + dfInfo n(filename, ((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS() ); + iter = dfList.insert(std::pair< std::string, dfInfo>( key, n ) ); + } else { + while( iter != dfList.end() && iter->second.key() == key && ABS(iter->second.timestamp - idata.getDateTimeAsTS()) > 60 * 60 * 6 ) { // 6 hour difference + iter++; + } + + if( iter != dfList.end() ) { + iter->second.pathNames.push_back( filename ); + } else { + dfInfo n(filename, ((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS()); + iter = dfList.insert(std::pair< std::string, dfInfo>( key, n ) ); } } - } + + return &(iter->second); + + } catch(Gio::Error&) {} return 0; } diff --git a/rtengine/dirpyr_equalizer.cc b/rtengine/dirpyr_equalizer.cc index ea9a4a46d..f82b7f8bf 100644 --- a/rtengine/dirpyr_equalizer.cc +++ b/rtengine/dirpyr_equalizer.cc @@ -418,7 +418,7 @@ SSEFUNCTION void ImProcFunctions::dirpyr_channel(float ** data_fine, float ** da __m128 thousandv = _mm_set1_ps( 1000.0f ); __m128 dirwtv, valv, normv, dftemp1v, dftemp2v; // multiplied each value of domkerv by 1000 to avoid multiplication by 1000 inside the loop - float domkerv[5][5][4] __attribute__ ((aligned (16))) = {{{1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}}}; + float domkerv[5][5][4] ALIGNED16 = {{{1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}}}; #endif // __SSE2__ int j; @@ -458,7 +458,7 @@ SSEFUNCTION void ImProcFunctions::dirpyr_channel(float ** data_fine, float ** da for (int jnbr = j - scalewin, indexjhlp = 0; jnbr <= j + scalewin; jnbr += scale, indexjhlp++) { dftemp2v = LVFU(data_fine[inbr][jnbr]); - dirwtv = _mm_load_ps((float*)&domkerv[indexihlp][indexjhlp]) / (vabsf(dftemp1v - dftemp2v) + thousandv); + dirwtv = LVF(domkerv[indexihlp][indexjhlp]) / (vabsf(dftemp1v - dftemp2v) + thousandv); valv += dirwtv * dftemp2v; normv += dirwtv; } diff --git a/rtengine/ffmanager.cc b/rtengine/ffmanager.cc index c311361e6..783c18bf7 100644 --- a/rtengine/ffmanager.cc +++ b/rtengine/ffmanager.cc @@ -19,7 +19,6 @@ #include "ffmanager.h" #include "../rtgui/options.h" #include -#include "safegtk.h" #include "rawimage.h" #include #include @@ -209,13 +208,21 @@ void ffInfo::updateRawImage() void FFManager::init( Glib::ustring pathname ) { std::vector names; - Glib::RefPtr dir = Gio::File::create_for_path (pathname); - if( dir && !dir->query_exists()) { + auto dir = Gio::File::create_for_path (pathname); + if (!dir || !dir->query_exists()) { return; } - safe_build_file_list (dir, names, pathname); + try { + + auto enumerator = dir->enumerate_children ("standard::name"); + + while (auto file = enumerator->next_file ()) { + names.emplace_back (Glib::build_filename (pathname, file->get_name ())); + } + + } catch (Glib::Exception&) {} ffList.clear(); @@ -253,65 +260,85 @@ void FFManager::init( Glib::ustring pathname ) return; } -ffInfo *FFManager::addFileInfo(const Glib::ustring &filename, bool pool ) +ffInfo* FFManager::addFileInfo (const Glib::ustring& filename, bool pool) { - Glib::RefPtr file = Gio::File::create_for_path(filename); + auto file = Gio::File::create_for_path (filename); if (!file ) { return 0; } - if( !file->query_exists()) { + if (!file->query_exists ()) { return 0; } - Glib::RefPtr info = safe_query_file_info(file); + try { - if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) { - size_t lastdot = info->get_name().find_last_of ('.'); + auto info = file->query_info (); - if (options.is_extention_enabled(lastdot != Glib::ustring::npos ? info->get_name().substr (lastdot + 1) : "")) { - RawImage ri(filename); - int res = ri.loadRaw(false); // Read informations about shot + if (!info || info->get_file_type () == Gio::FILE_TYPE_DIRECTORY) { + return 0; + } - if( !res ) { - ffList_t::iterator iter; + if (!options.fbShowHidden && info->is_hidden ()) { + return 0; + } - if(!pool) { - ffInfo n(filename, "", "", "", 0, 0, 0); - iter = ffList.insert(std::pair< std::string, ffInfo>( "", n ) ); - return &(iter->second); - } + Glib::ustring ext; - RawMetaDataLocation rml; - rml.exifBase = ri.get_exifBase(); - rml.ciffBase = ri.get_ciffBase(); - rml.ciffLength = ri.get_ciffLen(); - ImageData idata(filename, &rml); - /* 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 ); + auto lastdot = info->get_name ().find_last_of ('.'); + if (lastdot != Glib::ustring::npos) { + ext = info->get_name ().substr (lastdot + 1); + } - if( iter == ffList.end() ) { - ffInfo n(filename, idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber(), idata.getDateTimeAsTS()); - iter = ffList.insert(std::pair< std::string, ffInfo>( key, n ) ); - } else { - while( iter != ffList.end() && iter->second.key() == key && ABS(iter->second.timestamp - ri.get_timestamp()) > 60 * 60 * 6 ) { // 6 hour difference - iter++; - } + if (!options.is_extention_enabled (ext)) { + return 0; + } - if( iter != ffList.end() ) { - iter->second.pathNames.push_back( filename ); - } else { - ffInfo n(filename, idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber(), idata.getDateTimeAsTS()); - iter = ffList.insert(std::pair< std::string, ffInfo>( key, n ) ); - } - } - return &(iter->second); + RawImage ri (filename); + int res = ri.loadRaw (false); // Read informations about shot + + if (res != 0) { + return 0; + } + + ffList_t::iterator iter; + + if(!pool) { + ffInfo n(filename, "", "", "", 0, 0, 0); + iter = ffList.insert(std::pair< std::string, ffInfo>( "", n ) ); + return &(iter->second); + } + + RawMetaDataLocation rml; + rml.exifBase = ri.get_exifBase(); + rml.ciffBase = ri.get_ciffBase(); + rml.ciffLength = ri.get_ciffLen(); + ImageData idata(filename, &rml); + /* 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 ); + + if( iter == ffList.end() ) { + ffInfo n(filename, idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber(), idata.getDateTimeAsTS()); + iter = ffList.insert(std::pair< std::string, ffInfo>( key, n ) ); + } else { + while( iter != ffList.end() && iter->second.key() == key && ABS(iter->second.timestamp - ri.get_timestamp()) > 60 * 60 * 6 ) { // 6 hour difference + iter++; + } + + if( iter != ffList.end() ) { + iter->second.pathNames.push_back( filename ); + } else { + ffInfo n(filename, idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber(), idata.getDateTimeAsTS()); + iter = ffList.insert(std::pair< std::string, ffInfo>( key, n ) ); } } - } + + return &(iter->second); + + } catch (Gio::Error&) {} return 0; } diff --git a/rtengine/helpersse2.h b/rtengine/helpersse2.h index 3e4365e99..da1691748 100644 --- a/rtengine/helpersse2.h +++ b/rtengine/helpersse2.h @@ -21,19 +21,19 @@ typedef __m128i vint2; // #ifdef __GNUC__ -#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) || __GNUC__ > 4 -#define LVF(x) _mm_load_ps(&x) +#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 9) || __GNUC__ > 4) && (!defined(WIN32) || defined( __x86_64__ )) +#define LVF(x) _mm_load_ps((float*)&x) #define LVFU(x) _mm_loadu_ps(&x) #define STVF(x,y) _mm_store_ps(&x,y) #define STVFU(x,y) _mm_storeu_ps(&x,y) -#else // there is a bug in gcc 4.7.x when using openmp and aligned memory and -O3 -#define LVF(x) _mm_loadu_ps(&x) +#else // there is a bug in gcc 4.7.x when using openmp and aligned memory and -O3, also need to map the aligned functions to unaligned functions for WIN32 builds +#define LVF(x) _mm_loadu_ps((float*)&x) #define LVFU(x) _mm_loadu_ps(&x) #define STVF(x,y) _mm_storeu_ps(&x,y) #define STVFU(x,y) _mm_storeu_ps(&x,y) #endif #else -#define LVF(x) _mm_load_ps(&x) +#define LVF(x) _mm_load_ps((float*)&x) #define LVFU(x) _mm_loadu_ps(&x) #define STVF(x,y) _mm_store_ps(&x,y) #define STVFU(x,y) _mm_storeu_ps(&x,y) diff --git a/rtengine/iccmatrices.h b/rtengine/iccmatrices.h index 9e9682a73..292f45612 100644 --- a/rtengine/iccmatrices.h +++ b/rtengine/iccmatrices.h @@ -54,7 +54,7 @@ const double sRGB_xyz[3][3] = {{3.13593293538656, -1.61878246026431, // Color space conversion to/from XYZ; color spaces adapted to D50 using Bradford transform -const double xyz_sRGB[3][3] = {{0.4360747, 0.3850649, 0.1430804}, +const double xyz_sRGB[3][3] = {{0.4360747, 0.3850649, 0.1430804}, {0.2225045, 0.7168786, 0.0606169}, {0.0139322, 0.0971045, 0.7141733} }; @@ -83,6 +83,26 @@ const double prophoto_xyz[3][3] = {{1.3459433, -0.2556075, -0.0511118}, { -0.5445989, 1.5081673, 0.0205351}, {0.0000000, 0.0000000, 1.2118128} }; +/* +const double xyz_rec2020[3][3] = {{0.636958, 0.144617, 0.168881}, + {0.262700, 0.677998, 0.059302}, + {0.0000000, 0.028073, 1.060985} +}; + +const double rec2020_xyz[3][3] = {{1.716651, -0.355671, -0.253366}, + { -0.666684, 1.616481, 0.015769}, + {0.017640, -0.042771, 0.942103} +}; +*/ +const double xyz_rec2020[3][3] = {{0.6734241, 0.1656411, 0.1251286}, + {0.2790177, 0.6753402, 0.0456377}, + { -0.0019300, 0.0299784, 0.7973330} +}; + +const double rec2020_xyz[3][3] = {{1.6473376, -0.3935675, -0.2359961}, + { -0.6826036, 1.6475887, 0.0128190}, + {0.0296524, -0.0628993, 1.2531279} +}; const double xyz_widegamut[3][3] = {{0.7161046, 0.1009296, 0.1471858}, {0.2581874, 0.7249378, 0.0168748}, diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index ff29c72ab..66099199c 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -16,18 +16,21 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ +#include "iccstore.h" + +#include + #ifdef WIN32 #include #else #include #endif -#include "iccstore.h" -#include "iccmatrices.h" -#include -#include "safegtk.h" -#include "../rtgui/options.h" -#include +#include + +#include "iccmatrices.h" + +#include "../rtgui/options.h" namespace { @@ -38,8 +41,9 @@ void loadProfiles (const Glib::ustring& dirName, std::map* profileNames, bool nameUpper, bool onlyRgb) { - if (dirName.empty ()) + if (dirName.empty ()) { return; + } try { @@ -49,23 +53,27 @@ void loadProfiles (const Glib::ustring& dirName, const Glib::ustring fileName = *entry; - if (fileName.size () < 4) + if (fileName.size () < 4) { continue; + } const Glib::ustring extension = fileName.substr (fileName.size () - 4).casefold (); - if (extension.compare (".icc") != 0 && extension.compare (".icm") != 0) + if (extension.compare (".icc") != 0 && extension.compare (".icm") != 0) { continue; + } const Glib::ustring filePath = Glib::build_filename (dirName, fileName); - if (!safe_file_test (filePath, Glib::FILE_TEST_IS_REGULAR)) + if (!Glib::file_test (filePath, Glib::FILE_TEST_IS_REGULAR)) { continue; + } Glib::ustring name = fileName.substr (0, fileName.size() - 4); - if (nameUpper) + if (nameUpper) { name = name.uppercase (); + } if (profiles) { const rtengine::ProfileContent content (filePath); @@ -74,28 +82,31 @@ void loadProfiles (const Glib::ustring& dirName, if (profile && (!onlyRgb || cmsGetColorSpace (profile) == cmsSigRgbData)) { profiles->insert (std::make_pair (name, profile)); - if (profileContents) + if (profileContents) { profileContents->insert (std::make_pair (name, content)); + } } } - if (profileNames) + if (profileNames) { profileNames->insert (std::make_pair (name, filePath)); + } } - } - catch (Glib::Exception&) {} + } catch (Glib::Exception&) {} } inline void getSupportedIntent (cmsHPROFILE profile, cmsUInt32Number intent, cmsUInt32Number direction, std::uint8_t& result) { - if (cmsIsIntentSupported (profile, intent, direction)) + if (cmsIsIntentSupported (profile, intent, direction)) { result |= 1 << intent; + } } inline std::uint8_t getSupportedIntents (cmsHPROFILE profile, cmsUInt32Number direction) { - if (!profile) + if (!profile) { return 0; + } std::uint8_t result = 0; @@ -113,9 +124,9 @@ inline cmsHPROFILE createXYZProfile () return rtengine::ICCStore::createFromMatrix (mat, false, "XYZ"); } -const double (*wprofiles[])[3] = {xyz_sRGB, xyz_adobe, xyz_prophoto, xyz_widegamut, xyz_bruce, xyz_beta, xyz_best}; -const double (*iwprofiles[])[3] = {sRGB_xyz, adobe_xyz, prophoto_xyz, widegamut_xyz, bruce_xyz, beta_xyz, best_xyz}; -const char* wpnames[] = {"sRGB", "Adobe RGB", "ProPhoto", "WideGamut", "BruceRGB", "Beta RGB", "BestRGB"}; +const double (*wprofiles[])[3] = {xyz_sRGB, xyz_adobe, xyz_prophoto, xyz_widegamut, xyz_bruce, xyz_beta, xyz_best, xyz_rec2020}; +const double (*iwprofiles[])[3] = {sRGB_xyz, adobe_xyz, prophoto_xyz, widegamut_xyz, bruce_xyz, beta_xyz, best_xyz, rec2020_xyz}; +const char* wpnames[] = {"sRGB", "Adobe RGB", "ProPhoto", "WideGamut", "BruceRGB", "Beta RGB", "BestRGB", "Rec2020"}; const char* wpgamma[] = {"default", "BT709_g2.2_s4.5", "sRGB_g2.4_s12.92", "linear_g1.0", "standard_g2.2", "standard_g1.8", "High_g1.3_s3.35", "Low_g2.6_s6.9"}; //gamma free //default = gamma inside profile //BT709 g=2.22 s=4.5 sRGB g=2.4 s=12.92 @@ -160,8 +171,9 @@ std::vector ICCStore::getProfiles () const std::vector res; - for (ProfileMap::const_iterator profile = fileProfiles.begin (); profile != fileProfiles.end (); ++profile) + for (ProfileMap::const_iterator profile = fileProfiles.begin (); profile != fileProfiles.end (); ++profile) { res.push_back (profile->first); + } return res; } @@ -178,8 +190,9 @@ std::vector ICCStore::getProfilesFromDir (const Glib::ustring& di loadProfiles (profilesDir, &profiles, NULL, NULL, false, true); loadProfiles (dirName, &profiles, NULL, NULL, false, true); - for (ProfileMap::const_iterator profile = profiles.begin (); profile != profiles.end (); ++profile) + for (ProfileMap::const_iterator profile = profiles.begin (); profile != profiles.end (); ++profile) { res.push_back (profile->first); + } return res; } @@ -356,8 +369,9 @@ cmsHPROFILE ICCStore::getProfile (const Glib::ustring& name) const const ProfileMap::const_iterator r = fileProfiles.find (name); - if (r != fileProfiles.end ()) + if (r != fileProfiles.end ()) { return r->second; + } if (name.compare (0, 5, "file:") == 0) { const ProfileContent content (name.substr (5)); @@ -371,7 +385,7 @@ cmsHPROFILE ICCStore::getProfile (const Glib::ustring& name) const } } - return NULL; + return nullptr; } cmsHPROFILE ICCStore::getStdProfile (const Glib::ustring& name) const @@ -384,22 +398,25 @@ cmsHPROFILE ICCStore::getStdProfile (const Glib::ustring& name) const const ProfileMap::const_iterator r = fileStdProfiles.find (nameUpper); // return profile from store - if (r != fileStdProfiles.end ()) + if (r != fileStdProfiles.end ()) { return r->second; + } // profile is not yet in store const NameMap::const_iterator f = fileStdProfilesFileNames.find (nameUpper); // profile does not exist - if (f == fileStdProfilesFileNames.end ()) + if (f == fileStdProfilesFileNames.end ()) { return NULL; + } // but there exists one => load it const ProfileContent content (f->second); const cmsHPROFILE profile = content.toProfile (); - if (profile) + if (profile) { const_cast(fileStdProfiles).insert (std::make_pair (f->first, profile)); + } // profile is not valid or it is now stored => remove entry from fileStdProfilesFileNames const_cast(fileStdProfilesFileNames).erase (f); @@ -418,7 +435,6 @@ ProfileContent ICCStore::getContent (const Glib::ustring& name) const std::uint8_t ICCStore::getInputIntents (cmsHPROFILE profile) const { - MyMutex::MyLock lock (mutex_); return getSupportedIntents (profile, LCMS_USED_AS_INPUT); @@ -426,7 +442,6 @@ std::uint8_t ICCStore::getInputIntents (cmsHPROFILE profile) const std::uint8_t ICCStore::getOutputIntents (cmsHPROFILE profile) const { - MyMutex::MyLock lock (mutex_); return getSupportedIntents (profile, LCMS_USED_AS_OUTPUT); @@ -434,7 +449,6 @@ std::uint8_t ICCStore::getOutputIntents (cmsHPROFILE profile) const std::uint8_t ICCStore::getProofIntents (cmsHPROFILE profile) const { - MyMutex::MyLock lock (mutex_); return getSupportedIntents (profile, LCMS_USED_AS_PROOF); @@ -480,6 +494,7 @@ void ICCStore::findDefaultMonitorProfile () defaultMonitorProfile = Glib::ustring(profileName); defaultMonitorProfile = Glib::path_get_basename(defaultMonitorProfile); size_t pos = defaultMonitorProfile.rfind("."); + if (pos != Glib::ustring::npos) { defaultMonitorProfile = defaultMonitorProfile.substr(0, pos); } @@ -503,7 +518,7 @@ void ICCStore::findDefaultMonitorProfile () ProfileContent::ProfileContent (const Glib::ustring& fileName) : data(NULL), length(0) { - FILE* f = safe_g_fopen (fileName, "rb"); + FILE* f = g_fopen (fileName.c_str (), "rb"); if (!f) { return; diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 93c6b6604..c0da10761 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -19,12 +19,25 @@ #include "imagedata.h" #include "iptcpairs.h" #include -#include "safegtk.h" using namespace rtengine; extern "C" IptcData *iptc_data_new_from_jpeg_file (FILE* infile); +namespace +{ + +Glib::ustring to_utf8 (const std::string& str) +{ + try { + return Glib::locale_to_utf8 (str); + } catch (Glib::Error&) { + return Glib::convert_with_fallback (str, "UTF-8", "ISO-8859-1", "?"); + } +} + +} + ImageMetaData* ImageMetaData::fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml) { @@ -39,7 +52,7 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) iptc = NULL; if (ri && (ri->exifBase >= 0 || ri->ciffBase >= 0)) { - FILE* f = safe_g_fopen (fname, "rb"); + FILE* f = g_fopen (fname.c_str (), "rb"); if (f) { if (ri->exifBase >= 0) { @@ -60,18 +73,18 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) extractInfo (); } } else if ((dotpos < fname.size() - 3 && !fname.casefold().compare (dotpos, 4, ".jpg")) || (dotpos < fname.size() - 4 && !fname.casefold().compare (dotpos, 5, ".jpeg"))) { - FILE* f = safe_g_fopen (fname, "rb"); + FILE* f = g_fopen (fname.c_str (), "rb"); if (f) { root = rtexif::ExifManager::parseJPEG (f); extractInfo (); fclose (f); - FILE* ff = safe_g_fopen (fname, "rb"); + FILE* ff = g_fopen (fname.c_str (), "rb"); iptc = iptc_data_new_from_jpeg_file (ff); fclose (ff); } } else if ((dotpos < fname.size() - 3 && !fname.casefold().compare (dotpos, 4, ".tif")) || (dotpos < fname.size() - 4 && !fname.casefold().compare (dotpos, 5, ".tiff"))) { - FILE* f = safe_g_fopen (fname, "rb"); + FILE* f = g_fopen (fname.c_str (), "rb"); if (f) { root = rtexif::ExifManager::parseTIFF (f); @@ -271,176 +284,183 @@ void ImageData::extractInfo () } else if(!make.compare (0, 4, "SONY")) { if (iso_speed == 65535 || iso_speed == 0) { rtexif::Tag* isoTag = exif->getTag ("RecommendedExposureIndex"); - if(isoTag) + + if(isoTag) { iso_speed = isoTag->toDouble(); + } } } - else if (root->findTag("MakerNote")) { - rtexif::TagDirectory* mnote = root->findTag("MakerNote")->getDirectory(); - if (mnote && !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"); + if (lens == "Unknown") { + rtexif::Tag* mnoteTag = root->findTag("MakerNote"); - if (isoTag) { - iso_speed = isoTag->toInt(); + if (mnoteTag) { + rtexif::TagDirectory* mnote = mnoteTag->getDirectory(); + + if (mnote && !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"); + + if (isoTag) { + iso_speed = isoTag->toInt(); + } } - } - bool lensOk = false; + bool lensOk = false; - if (mnote->getTag ("LensData")) { - std::string ldata = mnote->getTag ("LensData")->valueToString (); - int pos; + if (mnote->getTag ("LensData")) { + std::string ldata = mnote->getTag ("LensData")->valueToString (); + int pos; - if (ldata.size() > 10 && (pos = ldata.find ("Lens = ")) != Glib::ustring::npos) { - lens = ldata.substr (pos + 7); + if (ldata.size() > 10 && (pos = ldata.find ("Lens = ")) != Glib::ustring::npos) { + lens = ldata.substr (pos + 7); - if (lens.compare (0, 7, "Unknown")) { - lensOk = true; - } else { - int pos = lens.find("$FL$"); // is there a placeholder for focallength? + if (lens.compare (0, 7, "Unknown")) { + lensOk = true; + } else { + int pos = lens.find("$FL$"); // is there a placeholder for focallength? - if(pos != Glib::ustring::npos) { // then fill in focallength - lens = lens.replace(pos, 4, exif->getTag ("FocalLength")->valueToString ()); + if(pos != Glib::ustring::npos) { // then fill in focallength + lens = lens.replace(pos, 4, exif->getTag ("FocalLength")->valueToString ()); - if(mnote->getTag ("LensType")) { - std::string ltype = mnote->getTag ("LensType")->valueToString (); + if(mnote->getTag ("LensType")) { + std::string ltype = mnote->getTag ("LensType")->valueToString (); - if(ltype.find("MF = Yes") != Glib::ustring::npos) { // check, whether it's a MF lens, should be always - lens = lens.replace(0, 7, "MF"); + if(ltype.find("MF = Yes") != Glib::ustring::npos) { // check, whether it's a MF lens, should be always + lens = lens.replace(0, 7, "MF"); + } + + lensOk = true; } - - lensOk = true; } } } } - } - if (!lensOk && mnote->getTag ("Lens")) { - std::string ldata = mnote->getTag ("Lens")->valueToString (); - size_t i = 0, j = 0; - double n[4]; + if (!lensOk && mnote->getTag ("Lens")) { + std::string ldata = mnote->getTag ("Lens")->valueToString (); + size_t i = 0, j = 0; + double n[4]; - for (int m = 0; m < 4; m++) { - while (i < ldata.size() && ldata[i] != '/') { + for (int m = 0; m < 4; m++) { + while (i < ldata.size() && ldata[i] != '/') { + i++; + } + + int nom = atoi(ldata.substr(j, i).c_str()); + j = i + 1; i++; + + while (i < ldata.size() && ldata[i] != ',') { + i++; + } + + int den = atoi(ldata.substr(j, i).c_str()); + j = i + 2; + i += 2; + n[m] = (double) nom / den; } - int nom = atoi(ldata.substr(j, i).c_str()); - j = i + 1; - i++; + std::ostringstream str; - while (i < ldata.size() && ldata[i] != ',') { - i++; - } - - int den = atoi(ldata.substr(j, i).c_str()); - j = i + 2; - i += 2; - n[m] = (double) nom / den; - } - - std::ostringstream str; - - if (n[0] == n[1]) { - str << "Unknown " << n[0] << "mm F/" << n[2]; - } else if (n[2] == n[3]) { - str << "Unknown " << n[0] << "-" << n[1] << "mm F/" << n[2]; - } else { - str << "Unknown " << n[0] << "-" << n[1] << "mm F/" << n[2] << "-" << n[3]; - } - - lens = str.str(); - - // Look whether it's MF or AF - if(mnote->getTag ("LensType")) { - std::string ltype = mnote->getTag ("LensType")->valueToString (); - - if(ltype.find("MF = Yes") != Glib::ustring::npos) { // check, whether it's a MF lens - lens = lens.replace(0, 7, "MF"); // replace 'Unknwon' with 'MF' + if (n[0] == n[1]) { + str << "Unknown " << n[0] << "mm F/" << n[2]; + } else if (n[2] == n[3]) { + str << "Unknown " << n[0] << "-" << n[1] << "mm F/" << n[2]; } else { - lens = lens.replace(0, 7, "AF"); // replace 'Unknwon' with 'AF' + str << "Unknown " << n[0] << "-" << n[1] << "mm F/" << n[2] << "-" << n[3]; + } + + lens = str.str(); + + // Look whether it's MF or AF + if(mnote->getTag ("LensType")) { + std::string ltype = mnote->getTag ("LensType")->valueToString (); + + if(ltype.find("MF = Yes") != Glib::ustring::npos) { // check, whether it's a MF lens + lens = lens.replace(0, 7, "MF"); // replace 'Unknwon' with 'MF' + } else { + lens = lens.replace(0, 7, "AF"); // replace 'Unknwon' with 'AF' + } } } - } - } else if (mnote && !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"); + } else if (mnote && !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"); - if (baseIsoTag) { - iso_speed = baseIsoTag->toInt(); + if (baseIsoTag) { + iso_speed = baseIsoTag->toInt(); + } } - } - int found = false; - // canon EXIF have a string for lens model - rtexif::Tag *lt = mnote->getTag("LensType"); - - if ( lt ) { - std::string ldata = lt->valueToString (); - - if (ldata.size() > 1) { - found = true; - lens = "Canon " + ldata; - } - } - - if( !found || lens.substr(lens.find(' ')).length() < 7 ) { - lt = mnote->findTag("LensID"); + int found = false; + // canon EXIF have a string for lens model + rtexif::Tag *lt = mnote->getTag("LensType"); if ( lt ) { std::string ldata = lt->valueToString (); if (ldata.size() > 1) { - lens = ldata; + found = true; + lens = "Canon " + ldata; + } + } + + if( !found || lens.substr(lens.find(' ')).length() < 7 ) { + lt = mnote->findTag("LensID"); + + if ( lt ) { + std::string ldata = lt->valueToString (); + + if (ldata.size() > 1) { + lens = ldata; + } + } + } + } else if (mnote && (!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX")))) { + if (mnote->getTag ("LensType")) { + lens = mnote->getTag ("LensType")->valueToString (); + } + + // Try to get the FocalLength from the LensInfo structure, where length below 10mm will be correctly set + rtexif::Tag* flt = mnote->getTagP ("LensInfo/FocalLength"); + + if (flt) { + // Don't replace Exif focal_len if Makernotes focal_len is 0 + if (flt->toDouble() > 0) { + focal_len = flt->toDouble (); + } + } else if ((flt = mnote->getTagP ("FocalLength"))) { + rtexif::Tag* flt = mnote->getTag ("FocalLength"); + focal_len = flt->toDouble (); + } + + if (mnote->getTag ("FocalLengthIn35mmFilm")) { + focal_len35mm = mnote->getTag ("FocalLengthIn35mmFilm")->toDouble (); + } + } else if (mnote && (!make.compare (0, 4, "SONY") || !make.compare (0, 6, "KONICA"))) { + if (mnote->getTag ("LensID")) { + lens = mnote->getTag ("LensID")->valueToString (); + } + } else if (mnote && !make.compare (0, 7, "OLYMPUS")) { + if (mnote->getTag ("Equipment")) { + rtexif::TagDirectory* eq = mnote->getTag ("Equipment")->getDirectory (); + + if (eq->getTag ("LensType")) { + lens = eq->getTag ("LensType")->valueToString (); } } } - } else if (mnote && (!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX")))) { - if (mnote->getTag ("LensType")) { - lens = mnote->getTag ("LensType")->valueToString (); - } - - // Try to get the FocalLength from the LensInfo structure, where length below 10mm will be correctly set - rtexif::Tag* flt = mnote->getTagP ("LensInfo/FocalLength"); - - if (flt) { - // Don't replace Exif focal_len if Makernotes focal_len is 0 - if (flt->toDouble() > 0) { - focal_len = flt->toDouble (); - } - } else if ((flt = mnote->getTagP ("FocalLength"))) { - rtexif::Tag* flt = mnote->getTag ("FocalLength"); - focal_len = flt->toDouble (); - } - - if (mnote->getTag ("FocalLengthIn35mmFilm")) { - focal_len35mm = mnote->getTag ("FocalLengthIn35mmFilm")->toDouble (); - } - } else if (mnote && (!make.compare (0, 4, "SONY") || !make.compare (0, 6, "KONICA"))) { - if (mnote->getTag ("LensID")) { - lens = mnote->getTag ("LensID")->valueToString (); - } - } else if (mnote && !make.compare (0, 7, "OLYMPUS")) { - if (mnote->getTag ("Equipment")) { - rtexif::TagDirectory* eq = mnote->getTag ("Equipment")->getDirectory (); - - if (eq->getTag ("LensType")) { - lens = eq->getTag ("LensType")->valueToString (); - } - } + } else if (exif->getTag ("DNGLensInfo")) { + lens = exif->getTag ("DNGLensInfo")->valueToString (); + } else if (exif->getTag ("LensModel")) { + lens = exif->getTag ("LensModel")->valueToString (); + } else if (exif->getTag ("LensInfo")) { + lens = exif->getTag ("LensInfo")->valueToString (); } - } else if (exif->getTag ("DNGLensInfo")) { - lens = exif->getTag ("DNGLensInfo")->valueToString (); - } else if (exif->getTag ("LensModel")) { - lens = exif->getTag ("LensModel")->valueToString (); - } else if (exif->getTag ("LensInfo")) { - lens = exif->getTag ("LensInfo")->valueToString (); } } } @@ -472,7 +492,7 @@ const procparams::IPTCPairs ImageData::getIPTCData () const if (ds) { iptc_dataset_get_data (ds, buffer, 2100); std::vector icValues; - icValues.push_back (safe_locale_to_utf8((char*)buffer)); + icValues.push_back (to_utf8((char*)buffer)); iptcc[strTags[i].field] = icValues; iptc_dataset_unref (ds); @@ -484,7 +504,7 @@ const procparams::IPTCPairs ImageData::getIPTCData () const 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 (safe_locale_to_utf8((char*)buffer)); + keywords.push_back (to_utf8((char*)buffer)); } iptcc["Keywords"] = keywords; @@ -493,7 +513,7 @@ const procparams::IPTCPairs ImageData::getIPTCData () const 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 (safe_locale_to_utf8((char*)buffer)); + suppCategories.push_back (to_utf8((char*)buffer)); iptc_dataset_unref (ds); } diff --git a/rtengine/imagedimensions.h b/rtengine/imagedimensions.h index 0b50d71c1..e3b98f7c5 100644 --- a/rtengine/imagedimensions.h +++ b/rtengine/imagedimensions.h @@ -48,11 +48,11 @@ public: { return height; } - int getWidth () + int getWidth () const { return width; } - int getHeight () + int getHeight () const { return height; } diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index db289ca1a..4fa5a5a93 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -36,7 +36,6 @@ #endif #include "imageio.h" -#include "safegtk.h" #include "iptcpairs.h" #include "iccjpeg.h" #include "color.h" @@ -47,9 +46,46 @@ using namespace std; using namespace rtengine; using namespace rtengine::procparams; -Glib::ustring safe_locale_to_utf8 (const std::string& src); -Glib::ustring ImageIO::errorMsg[6] = {"Success", "Cannot read file.", "Invalid header.", "Error while reading header.", "File reading error", "Image format not supported."}; +namespace +{ +// Opens a file for binary writing and request exclusive lock (cases were you need "wb" mode plus locking) +FILE* g_fopen_withBinaryAndLock(const Glib::ustring& fname) +{ + FILE* f = NULL; + +#ifdef WIN32 + + // Use native function to disallow sharing, i.e. lock the file for exclusive access. + // This is important to e.g. prevent Windows Explorer from crashing RT due to concurrently scanning an image file. + std::unique_ptr wfname (reinterpret_cast(g_utf8_to_utf16 (fname.c_str (), -1, NULL, NULL, NULL)), g_free); + + HANDLE hFile = CreateFileW ( wfname.get (), GENERIC_READ | GENERIC_WRITE, 0 /* no sharing allowed */, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + f = _fdopen (_open_osfhandle ((intptr_t)hFile, 0), "wb"); + } + +#else + + f = ::g_fopen (fname.c_str (), "wb"); + +#endif + + return f; +} + +Glib::ustring to_utf8 (const std::string& str) +{ + try { + return Glib::locale_to_utf8 (str); + } catch (Glib::Error&) { + return Glib::convert_with_fallback (str, "UTF-8", "ISO-8859-1", "?"); + } +} + +} + +Glib::ustring ImageIO::errorMsg[6] = {"Success", "Cannot read file.", "Invalid header.", "Error while reading header.", "File reading error", "Image format not supported."}; // For only copying the raw input data void ImageIO::setMetadata (const rtexif::TagDirectory* eroot) @@ -77,12 +113,6 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr // store exif info exifChange.clear(); exifChange = exif; - /*unsigned int j=0; - for (rtengine::procparams::ExifPairs::const_iterator i=exif.begin(); i!=exif.end(); i++) { - exifChange.at(j).first = i->first; - exifChange.at(j).second = i->second; - j++; - }*/ if (exifRoot != NULL) { delete exifRoot; @@ -110,7 +140,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr for (unsigned int j = 0; j < i->second.size(); j++) { IptcDataSet * ds = iptc_dataset_new (); iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_KEYWORDS); - std::string loc = safe_locale_to_utf8(i->second.at(j)); + std::string loc = to_utf8(i->second.at(j)); iptc_dataset_set_data (ds, (unsigned char*)loc.c_str(), min(static_cast(64), loc.size()), IPTC_DONT_VALIDATE); iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); @@ -121,7 +151,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr for (unsigned int j = 0; j < i->second.size(); j++) { IptcDataSet * ds = iptc_dataset_new (); iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_SUPPL_CATEGORY); - std::string loc = safe_locale_to_utf8(i->second.at(j)); + std::string loc = to_utf8(i->second.at(j)); iptc_dataset_set_data (ds, (unsigned char*)loc.c_str(), min(static_cast(32), loc.size()), IPTC_DONT_VALIDATE); iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); @@ -134,7 +164,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr if (i->first == strTags[j].field && !(i->second.empty())) { IptcDataSet * ds = iptc_dataset_new (); iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, strTags[j].tag); - std::string loc = safe_locale_to_utf8(i->second.at(0)); + std::string loc = to_utf8(i->second.at(0)); iptc_dataset_set_data (ds, (unsigned char*)loc.c_str(), min(strTags[j].size, loc.size()), IPTC_DONT_VALIDATE); iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); @@ -177,7 +207,7 @@ void png_flush(png_struct_def *png_ptr); int ImageIO::getPNGSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, IIOSampleArrangement &sArrangement) { - FILE *file = safe_g_fopen (fname, "rb"); + FILE *file = g_fopen (fname.c_str (), "rb"); if (!file) { return IMIO_CANNOTREADFILE; @@ -251,7 +281,7 @@ int ImageIO::getPNGSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, int ImageIO::loadPNG (Glib::ustring fname) { - FILE *file = safe_g_fopen (fname, "rb"); + FILE *file = g_fopen (fname.c_str (), "rb"); if (!file) { return IMIO_CANNOTREADFILE; @@ -500,7 +530,7 @@ int ImageIO::loadJPEGFromMemory (const char* buffer, int bufsize) int ImageIO::loadJPEG (Glib::ustring fname) { - FILE *file = safe_g_fopen(fname, "rb"); + FILE *file = g_fopen(fname.c_str (), "rb"); if (!file) { return IMIO_CANNOTREADFILE; @@ -888,7 +918,7 @@ int ImageIO::loadPPMFromMemory(const char* buffer, int width, int height, bool s int ImageIO::savePNG (Glib::ustring fname, int compression, volatile int bps) { - FILE *file = safe_g_fopen_WriteBinLock (fname); + FILE *file = g_fopen_withBinaryAndLock (fname); if (!file) { return IMIO_CANNOTWRITEFILE; @@ -982,7 +1012,7 @@ int ImageIO::savePNG (Glib::ustring fname, int compression, volatile int bps) int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) { - FILE *file = safe_g_fopen_WriteBinLock (fname); + FILE *file = g_fopen_withBinaryAndLock (fname); if (!file) { return IMIO_CANNOTWRITEFILE; @@ -1011,7 +1041,7 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) */ jpeg_destroy_compress(&cinfo); fclose(file); - safe_g_remove(fname); + g_remove (fname.c_str()); return IMIO_CANNOTWRITEFILE; } @@ -1130,7 +1160,7 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) delete [] row; jpeg_destroy_compress(&cinfo); fclose(file); - safe_g_remove(fname); + g_remove (fname.c_str()); return IMIO_CANNOTWRITEFILE; } @@ -1142,7 +1172,7 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) jpeg_destroy_compress (&cinfo); delete [] row; fclose (file); - safe_g_remove(fname); + g_remove (fname.c_str()); return IMIO_CANNOTWRITEFILE; } @@ -1183,7 +1213,7 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) // TODO the following needs to be looked into - do we really need two ways to write a Tiff file ? if (exifRoot && uncompressed) { - FILE *file = safe_g_fopen_WriteBinLock (fname); + FILE *file = g_fopen_withBinaryAndLock (fname); if (!file) { delete [] linebuffer; @@ -1370,7 +1400,7 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) if(writeOk) { return IMIO_SUCCESS; } else { - safe_g_remove(fname); + g_remove (fname.c_str()); return IMIO_CANNOTWRITEFILE; } } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index d24427be9..b6862ab66 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -388,8 +388,16 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, fw, fh, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), false); - readyphase++; + if ((todo & (M_TRANSFORM)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) { + const int W = oprevi->getWidth(); + const int H = oprevi->getHeight(); + LabImage labcbdl(W, H); + ipf.rgb2lab(*oprevi, labcbdl, params.icm.working); + ipf.dirpyrequalizer (&labcbdl, scale); + ipf.lab2rgb(labcbdl, *oprevi, params.icm.working); + } + readyphase++; progress ("Preparing shadow/highlight map...", 100 * readyphase / numofphases); if ((todo & M_BLURMAP) && params.sh.enabled) { @@ -407,6 +415,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) shmap->update (oprevi, shradius, ipf.lumimul, params.sh.hq, scale); } + + readyphase++; if (todo & M_AUTOEXP) { @@ -439,6 +449,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, scale == 1 ? 1 : 1); CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, scale == 1 ? 1 : 1); + TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); double wp[3][3] = { {wprof[0][0], wprof[0][1], wprof[0][2]}, @@ -656,15 +667,15 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) } } */ - //if (scale==1) { - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { - progress ("Pyramid wavelet...", 100 * readyphase / numofphases); - ipf.dirpyrequalizer (nprevl, scale); - //ipf.Lanczoslab (ip_wavelet(LabImage * lab, LabImage * dst, const procparams::EqualizerParams & eqparams), nprevl, 1.f/scale); - readyphase++; + if(params.dirpyrequalizer.cbdlMethod == "aft") { + if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) ) { + progress ("Pyramid wavelet...", 100 * readyphase / numofphases); + ipf.dirpyrequalizer (nprevl, scale); + //ipf.Lanczoslab (ip_wavelet(LabImage * lab, LabImage * dst, const procparams::EqualizerParams & eqparams), nprevl, 1.f/scale); + readyphase++; + } } - //} wavcontlutili = false; //CurveFactory::curveWavContL ( wavcontlutili,params.wavelet.lcurve, wavclCurve, LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,int skip); diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index b1f47c3a9..989d9c6a7 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -23,9 +23,6 @@ #include "rtengine.h" #include "improcfun.h" #include "curves.h" -#include "colorclip.h" -#include "gauss.h" -#include "bilateral2.h" #include "mytime.h" #include "iccstore.h" #include "impulse_denoise.h" @@ -52,45 +49,7 @@ namespace rtengine using namespace procparams; -#undef ABS -#undef CLIPS -#undef CLIPC - -#define ABS(a) ((a)<0?-(a):(a)) -#define CLIPS(a) ((a)>-32768?((a)<32767?(a):32767):-32768) -#define CLIPC(a) ((a)>-32000?((a)<32000?(a):32000):-32000) -#define CLIP2(a) ((a)0.0?((a)<65535.5?(a):65535.5):0.0) - - extern const Settings* settings; -LUTf ImProcFunctions::cachef; -LUTf ImProcFunctions::gamma2curve; -void ImProcFunctions::initCache () -{ - - const int maxindex = 65536; - cachef(maxindex, 0/*LUT_CLIP_BELOW*/); - - gamma2curve(maxindex, 0); - - for (int i = 0; i < maxindex; i++) { - if (i > Color::eps_max) { - cachef[i] = 327.68 * ( exp(1.0 / 3.0 * log((double)i / MAXVALD) )); - } else { - cachef[i] = 327.68 * ((Color::kappa * i / MAXVALD + 16.0) / 116.0); - } - } - - for (int i = 0; i < maxindex; i++) { - gamma2curve[i] = (CurveFactory::gamma2(i / 65535.0) * 65535.0); - } -} - -void ImProcFunctions::cleanupCache () -{ - -} ImProcFunctions::~ImProcFunctions () { @@ -3106,15 +3065,15 @@ filmlike_clip(float *r, float *g, float *b) } } -void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, +void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clToningcurve, LUTf & cl2Toningcurve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf ) { - rgbProc (working, lab, editBuffer, hltonecurve, shtonecurve, tonecurve, shmap, sat, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, params->toneCurve.expcomp, params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh, dcpProf); + rgbProc (working, lab, pipetteBuffer, hltonecurve, shtonecurve, tonecurve, shmap, sat, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, params->toneCurve.expcomp, params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh, dcpProf); } // Process RGB image and convert to LAB space -void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, +void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clToningcurve, LUTf & cl2Toningcurve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh, DCPProfile *dcpProf) { @@ -3125,20 +3084,20 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e Imagefloat* editImgFloat = NULL; LabImage* editLab = NULL; PlanarWhateverData* editWhatever = NULL; - EditUniqueID editID = editBuffer ? editBuffer->getEditID() : EUID_None; + EditUniqueID editID = pipetteBuffer ? pipetteBuffer->getEditID() : EUID_None; if (editID != EUID_None) { - switch (editBuffer->getDataProvider()->getCurrSubscriber()->getEditBufferType()) { + switch (pipetteBuffer->getDataProvider()->getCurrSubscriber()->getPipetteBufferType()) { case (BT_IMAGEFLOAT): - editImgFloat = editBuffer->getImgFloatBuffer(); + editImgFloat = pipetteBuffer->getImgFloatBuffer(); break; case (BT_LABIMAGE): - editLab = editBuffer->getLabBuffer(); + editLab = pipetteBuffer->getLabBuffer(); break; case (BT_SINGLEPLANE_FLOAT): - editWhatever = editBuffer->getSinglePlaneBuffer(); + editWhatever = pipetteBuffer->getSinglePlaneBuffer(); break; } } @@ -3421,10 +3380,22 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e fGammaLUTf[i] = CurveFactory::gamma2 (float(i) / 65535.f) * 65535.f; } - if (hasColorToning || blackwhite) { + if (hasColorToning || blackwhite || (params->dirpyrequalizer.cbdlMethod == "bef" && params->dirpyrequalizer.enabled)) { tmpImage = new Imagefloat(working->width, working->height); } + int W = working->width; + int H = working->height; + + + + + + + + + + #define TS 112 #ifdef _OPENMP @@ -3447,7 +3418,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e int tW; int tH; - // Allocating buffer for the EditBuffer + // Allocating buffer for the PipetteBuffer float *editIFloatTmpR, *editIFloatTmpG, *editIFloatTmpB, *editWhateverTmp; if (editImgFloat) { @@ -3806,9 +3777,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e y = toxyz[1][0] * r1 + toxyz[1][1] * g1 + toxyz[1][2] * b1; z = toxyz[2][0] * r1 + toxyz[2][1] * g1 + toxyz[2][2] * b1; - fx = (x < 65535.0f ? cachef[std::max(x, 0.f)] : (327.68f * float(exp(log(x / MAXVALF) / 3.0f )))); - fy = (y < 65535.0f ? cachef[std::max(y, 0.f)] : (327.68f * float(exp(log(y / MAXVALF) / 3.0f )))); - fz = (z < 65535.0f ? cachef[std::max(z, 0.f)] : (327.68f * float(exp(log(z / MAXVALF) / 3.0f )))); + fx = (x < 65535.0f ? Color::cachef[std::max(x, 0.f)] : 327.68f * std::cbrt(x / MAXVALF)); + fy = (y < 65535.0f ? Color::cachef[std::max(y, 0.f)] : 327.68f * std::cbrt(y / MAXVALF)); + fz = (z < 65535.0f ? Color::cachef[std::max(z, 0.f)] : 327.68f * std::cbrt(z / MAXVALF)); L_1 = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; a_1 = (500.0f * (fx - fy) ); @@ -3836,7 +3807,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e // Luminosity after // only Luminance in Lab yy = toxyz[1][0] * r2 + toxyz[1][1] * g2 + toxyz[1][2] * b2; - fyy = (yy < 65535.0f ? cachef[std::max(yy, 0.f)] : (327.68f * float(exp(log(yy / MAXVALF) / 3.0f )))); + fyy = (yy < 65535.0f ? Color::cachef[std::max(yy, 0.f)] : 327.68f * std::cbrt(yy / MAXVALF)); L_2 = (116.0f * fyy - 5242.88f); //gamut control @@ -4217,48 +4188,6 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e } } - //Film Simulations - if ( colorLUT ) { - for (int i = istart, ti = 0; i < tH; i++, ti++) { - for (int j = jstart, tj = 0; j < tW; j++, tj++) { - float &sourceR = rtemp[ti * TS + tj]; - float &sourceG = gtemp[ti * TS + tj]; - float &sourceB = btemp[ti * TS + tj]; - - if (!clutAndWorkingProfilesAreSame) { - //convert from working to clut profile - float x, y, z; - Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, work2xyz ); - Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2clut ); - } - - //appply gamma sRGB (default RT) - sourceR = CLIP( Color::gamma_srgb( sourceR ) ); - sourceG = CLIP( Color::gamma_srgb( sourceG ) ); - sourceB = CLIP( Color::gamma_srgb( sourceB ) ); - - float r, g, b; - colorLUT->getRGB( sourceR, sourceG, sourceB, r, g, b ); - // apply strength - sourceR = r * filmSimCorrectedStrength + sourceR * filmSimSourceStrength; - sourceG = g * filmSimCorrectedStrength + sourceG * filmSimSourceStrength; - sourceB = b * filmSimCorrectedStrength + sourceB * filmSimSourceStrength; - // apply inverse gamma sRGB - sourceR = Color::igamma_srgb( sourceR ); - sourceG = Color::igamma_srgb( sourceG ); - sourceB = Color::igamma_srgb( sourceB ); - - if (!clutAndWorkingProfilesAreSame) { - //convert from clut to working profile - float x, y, z; - Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, clut2xyz ); - Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2work ); - } - - } - } - } - //black and white if(blackwhite) { if (hasToneCurvebw1) { @@ -4405,6 +4334,50 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e } } + + //Film Simulations + if ( colorLUT ) { + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + float &sourceR = rtemp[ti * TS + tj]; + float &sourceG = gtemp[ti * TS + tj]; + float &sourceB = btemp[ti * TS + tj]; + + if (!clutAndWorkingProfilesAreSame) { + //convert from working to clut profile + float x, y, z; + Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, work2xyz ); + Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2clut ); + } + + //appply gamma sRGB (default RT) + sourceR = CLIP( Color::gamma_srgb( sourceR ) ); + sourceG = CLIP( Color::gamma_srgb( sourceG ) ); + sourceB = CLIP( Color::gamma_srgb( sourceB ) ); + + float r, g, b; + colorLUT->getRGB( sourceR, sourceG, sourceB, r, g, b ); + // apply strength + sourceR = r * filmSimCorrectedStrength + sourceR * filmSimSourceStrength; + sourceG = g * filmSimCorrectedStrength + sourceG * filmSimSourceStrength; + sourceB = b * filmSimCorrectedStrength + sourceB * filmSimSourceStrength; + // apply inverse gamma sRGB + sourceR = Color::igamma_srgb( sourceR ); + sourceG = Color::igamma_srgb( sourceG ); + sourceB = Color::igamma_srgb( sourceB ); + + if (!clutAndWorkingProfilesAreSame) { + //convert from clut to working profile + float x, y, z; + Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, clut2xyz ); + Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2work ); + } + + } + } + } + + if(!blackwhite) { // ready, fill lab for (int i = istart, ti = 0; i < tH; i++, ti++) { @@ -4429,9 +4402,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e float fx, fy, fz; - fx = (x < 65535.0f ? cachef[std::max(x, 0.f)] : (327.68f * float(exp(log(x / MAXVALF) / 3.0f )))); - fy = (y < 65535.0f ? cachef[std::max(y, 0.f)] : (327.68f * float(exp(log(y / MAXVALF) / 3.0f )))); - fz = (z < 65535.0f ? cachef[std::max(z, 0.f)] : (327.68f * float(exp(log(z / MAXVALF) / 3.0f )))); + fx = (x < 65535.0f ? Color::cachef[std::max(x, 0.f)] : 327.68f * std::cbrt(x / MAXVALF)); + fy = (y < 65535.0f ? Color::cachef[std::max(y, 0.f)] : 327.68f * std::cbrt(y / MAXVALF)); + fz = (z < 65535.0f ? Color::cachef[std::max(z, 0.f)] : 327.68f * std::cbrt(z / MAXVALF)); lab->L[i][j] = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; lab->a[i][j] = (500.0f * (fx - fy) ); @@ -4879,9 +4852,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e float fx, fy, fz; - fx = (x < 65535.0f ? cachef[std::max(x, 0.f)] : (327.68f * float(exp(log(x / MAXVALF) / 3.0f )))); - fy = (y < 65535.0f ? cachef[std::max(y, 0.f)] : (327.68f * float(exp(log(y / MAXVALF) / 3.0f )))); - fz = (z < 65535.0f ? cachef[std::max(z, 0.f)] : (327.68f * float(exp(log(z / MAXVALF) / 3.0f )))); + fx = (x < 65535.0f ? Color::cachef[std::max(x, 0.f)] : 327.68f * std::cbrt(x / MAXVALF)); + fy = (y < 65535.0f ? Color::cachef[std::max(y, 0.f)] : 327.68f * std::cbrt(y / MAXVALF)); + fz = (z < 65535.0f ? Color::cachef[std::max(z, 0.f)] : 327.68f * std::cbrt(z / MAXVALF)); lab->L[i][j] = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; lab->a[i][j] = (500.0f * (fx - fy) ); @@ -5552,7 +5525,7 @@ void ImProcFunctions::luminanceCurve (LabImage* lold, LabImage* lnew, LUTf & cur -SSEFUNCTION void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf & acurve, LUTf & bcurve, LUTf & satcurve, LUTf & lhskcurve, LUTf & clcurve, LUTf & curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLLCurve, LUTu &histLCurve) +SSEFUNCTION void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf & acurve, LUTf & bcurve, LUTf & satcurve, LUTf & lhskcurve, LUTf & clcurve, LUTf & curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLLCurve, LUTu &histLCurve) { int W = lold->W; int H = lold->H; @@ -5566,23 +5539,23 @@ SSEFUNCTION void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, EditUniqueID editID = EUID_None; bool editPipette = false; - if (editBuffer) { - editID = editBuffer->getEditID(); + if (pipetteBuffer) { + editID = pipetteBuffer->getEditID(); if (editID != EUID_None) { editPipette = true; - switch (editBuffer->getDataProvider()->getCurrSubscriber()->getEditBufferType()) { + switch (pipetteBuffer->getDataProvider()->getCurrSubscriber()->getPipetteBufferType()) { case (BT_IMAGEFLOAT): - editImgFloat = editBuffer->getImgFloatBuffer(); + editImgFloat = pipetteBuffer->getImgFloatBuffer(); break; case (BT_LABIMAGE): - editLab = editBuffer->getLabBuffer(); + editLab = pipetteBuffer->getLabBuffer(); break; case (BT_SINGLEPLANE_FLOAT): - editWhatever = editBuffer->getSinglePlaneBuffer(); + editWhatever = pipetteBuffer->getSinglePlaneBuffer(); break; } } @@ -6483,7 +6456,6 @@ void ImProcFunctions::badpixlab(LabImage* lab, double rad, int thr, int mode, fl void ImProcFunctions::dirpyrequalizer (LabImage* lab, int scale) { - if (params->dirpyrequalizer.enabled && lab->W >= 8 && lab->H >= 8) { float b_l = static_cast(params->dirpyrequalizer.hueskin.value[0]) / 100.0f; float t_l = static_cast(params->dirpyrequalizer.hueskin.value[1]) / 100.0f; @@ -7091,8 +7063,79 @@ double ImProcFunctions::getAutoDistor (const Glib::ustring &fname, int thumb_si } } +void ImProcFunctions::rgb2lab(const Imagefloat &src, LabImage &dst, const Glib::ustring &workingSpace) +{ + TMatrix wprof = iccStore->workingSpaceMatrix( workingSpace ); + const float wp[3][3] = { + {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])}, + {static_cast(wprof[1][0]), static_cast(wprof[1][1]), static_cast(wprof[1][2])}, + {static_cast(wprof[2][0]), static_cast(wprof[2][1]), static_cast(wprof[2][2])} + }; + + const int W = src.getWidth(); + const int H = src.getHeight(); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for(int i = 0; i < H; i++) { + for(int j = 0; j < W; j++) { + float X, Y, Z; + Color::rgbxyz(src.r(i, j), src.g(i, j), src.b(i, j), X, Y, Z, wp); + //convert Lab + Color::XYZ2Lab(X, Y, Z, dst.L[i][j], dst.a[i][j], dst.b[i][j]); + } + } +} + +SSEFUNCTION void ImProcFunctions::lab2rgb(const LabImage &src, Imagefloat &dst, const Glib::ustring &workingSpace) +{ + TMatrix wiprof = iccStore->workingSpaceInverseMatrix( workingSpace ); + const float wip[3][3] = { + {static_cast(wiprof[0][0]), static_cast(wiprof[0][1]), static_cast(wiprof[0][2])}, + {static_cast(wiprof[1][0]), static_cast(wiprof[1][1]), static_cast(wiprof[1][2])}, + {static_cast(wiprof[2][0]), static_cast(wiprof[2][1]), static_cast(wiprof[2][2])} + }; + + const int W = dst.getWidth(); + const int H = dst.getHeight(); +#ifdef __SSE2__ + vfloat wipv[3][3]; + + for(int i = 0; i < 3; i++) { + for(int j = 0; j < 3; j++) { + wipv[i][j] = F2V(wiprof[i][j]); + } + } +#endif + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for(int i = 0; i < H; i++) { + int j = 0; +#ifdef __SSE2__ + for(; j < W - 3; j += 4) { + vfloat X, Y, Z; + vfloat R,G,B; + Color::Lab2XYZ(LVFU(src.L[i][j]), LVFU(src.a[i][j]), LVFU(src.b[i][j]), X, Y, Z); + Color::xyz2rgb(X, Y, Z, R, G, B, wipv); + STVFU(dst.r(i, j), R); + STVFU(dst.g(i, j), G); + STVFU(dst.b(i, j), B); + } + +#endif + for(; j < W; j++) { + float X, Y, Z; + Color::Lab2XYZ(src.L[i][j], src.a[i][j], src.b[i][j], X, Y, Z); + Color::xyz2rgb(X, Y, Z, dst.r(i, j), dst.g(i, j), dst.b(i, j), wip); + } + } +} + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% } -#undef PIX_SORT -#undef med3x3 diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 44224fa2e..90a046149 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -33,7 +33,7 @@ #include "dcp.h" #include "curves.h" #include "cplx_wavelet_dec.h" -#include "editbuffer.h" +#include "pipettebuffer.h" #define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } @@ -57,7 +57,6 @@ using namespace procparams; class ImProcFunctions { - static LUTf gamma2curve; cmsHTRANSFORM monitorTransform; cmsHTRANSFORM lab2outputTransform; @@ -201,7 +200,6 @@ class ImProcFunctions public: - static LUTf cachef; double lumimul[3]; // float chau; // float chred; @@ -221,8 +219,6 @@ public: // float maxblueresid;//used by noise_residual // int comptlevel; - static void initCache (); - static void cleanupCache (); ImProcFunctions (const ProcParams* iparams, bool imultiThread = true) : monitorTransform(NULL), lab2outputTransform(NULL), output2monitorTransform(NULL), params(iparams), scale(1), multiThread(imultiThread) {} @@ -235,10 +231,10 @@ public: void firstAnalysis (Imagefloat* working, const ProcParams* params, LUTu & vhist16); void updateColorProfiles (const ColorManagementParams& icm, const Glib::ustring& monitorProfile, RenderingIntent monitorIntent); - void rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, + void rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf); - void rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, + void rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh, DCPProfile *dcpProf); @@ -259,7 +255,7 @@ public: void ciecam_02 (CieImage* ncie, double adap, int begh, int endh, int pW, int pwb, LabImage* lab, const ProcParams* params, const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve, const ColorAppearance & customColCurve3, LUTu &histLCAM, LUTu &histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, double &d, int scalecd, int rtt); - void chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf &acurve, LUTf &bcurve, LUTf & satcurve, LUTf & satclcurve, LUTf &clcurve, LUTf &curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLCurve, LUTu &histLurve); + void chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf &acurve, LUTf &bcurve, LUTf & satcurve, LUTf & satclcurve, LUTf &clcurve, LUTf &curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLCurve, LUTu &histLurve); void vibrance (LabImage* lab);//Jacques' vibrance void colorCurve (LabImage* lold, LabImage* lnew); void sharpening (LabImage* lab, float** buffer, SharpeningParams &sharpenParam); @@ -286,6 +282,7 @@ public: void dirpyrdenoise (LabImage* src);//Emil's pyramid denoise void dirpyrequalizer (LabImage* lab, int scale);//Emil's wavelet + void EPDToneMapResid(float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params& cp, int W_L, int H_L, float max0, float min0); float *CompressDR(float *Source, int skip, struct cont_params &cp, int W_L, int H_L, float Compression, float DetailBoost, float max0, float min0, float ave, float ah, float bh, float al, float bl, float factorx, float *Compressed); void ContrastResid(float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params &cp, int W_L, int H_L, float max0, float min0, float ave, float ah, float bh, float al, float bl, float factorx); @@ -383,6 +380,8 @@ public: static void getAutoExp (LUTu & histogram, int histcompr, double defgain, double clip, double& expcomp, int& bright, int& contr, int& black, int& hlcompr, int& hlcomprthresh); static double getAutoDistor (const Glib::ustring& fname, int thumb_size); double getTransformAutoFill (int oW, int oH, const LCPMapper *pLCPMap = NULL); + void rgb2lab(const Imagefloat &src, LabImage &dst, const Glib::ustring &workingSpace); + void lab2rgb(const LabImage &src, Imagefloat &dst, const Glib::ustring &workingSpace); }; } #endif diff --git a/rtengine/impulse_denoise.h b/rtengine/impulse_denoise.h index ba596559c..9d3b73b79 100644 --- a/rtengine/impulse_denoise.h +++ b/rtengine/impulse_denoise.h @@ -24,6 +24,7 @@ #include "cieimage.h" #include "sleef.c" #include "opthelper.h" +#include "gauss.h" using namespace std; diff --git a/rtengine/init.cc b/rtengine/init.cc index 9fa5c48ee..d2509b620 100644 --- a/rtengine/init.cc +++ b/rtengine/init.cc @@ -39,11 +39,9 @@ MyMutex* lcmsMutex = NULL; int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir) { - settings = s; iccStore->init (s->iccDirectory, baseDir + "/iccprofiles"); iccStore->findDefaultMonitorProfile(); - dcpStore->init (baseDir + "/dcpprofiles"); CameraConstantsStore::getInstance ()->init (baseDir, userSettingsDir); @@ -52,8 +50,6 @@ int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDi Color::init (); PerceptualToneCurve::init (); RawImageSource::init (); - ImProcFunctions::initCache (); - Thumbnail::initGamma (); delete lcmsMutex; lcmsMutex = new MyMutex; dfm.init( s->darkFramesPath ); @@ -66,8 +62,6 @@ void cleanup () ProcParams::cleanup (); Color::cleanup (); - ImProcFunctions::cleanupCache (); - Thumbnail::cleanupGamma (); RawImageSource::cleanup (); } diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index 89deac08f..21e5ca794 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -117,9 +117,9 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) /* copy RGB */ //int R1=((int)gamma2curve[(R)]) - data[ix++] = ((int)gamma2curve[CLIP(R)]) >> 8; - data[ix++] = ((int)gamma2curve[CLIP(G)]) >> 8; - data[ix++] = ((int)gamma2curve[CLIP(B)]) >> 8; + data[ix++] = ((int)Color::gamma2curve[CLIP(R)]) >> 8; + data[ix++] = ((int)Color::gamma2curve[CLIP(G)]) >> 8; + data[ix++] = ((int)Color::gamma2curve[CLIP(B)]) >> 8; } } } @@ -229,9 +229,9 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Color::xyz2rgb(x_, y_, z_, R, G, B, rgb_xyz); - image->data[ix++] = (int)gamma2curve[CLIP(R)] >> 8; - image->data[ix++] = (int)gamma2curve[CLIP(G)] >> 8; - image->data[ix++] = (int)gamma2curve[CLIP(B)] >> 8; + image->data[ix++] = (int)Color::gamma2curve[CLIP(R)] >> 8; + image->data[ix++] = (int)Color::gamma2curve[CLIP(G)] >> 8; + image->data[ix++] = (int)Color::gamma2curve[CLIP(B)] >> 8; } } } @@ -331,9 +331,9 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int Color::xyz2srgb(x_, y_, z_, R, G, B); - image->r(i - cy, j - cx) = (int)gamma2curve[CLIP(R)]; - image->g(i - cy, j - cx) = (int)gamma2curve[CLIP(G)]; - image->b(i - cy, j - cx) = (int)gamma2curve[CLIP(B)]; + image->r(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(R)]; + image->g(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(G)]; + image->b(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(B)]; } } } @@ -429,6 +429,14 @@ Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int p5 = 0.1300; p6 = 0.0350; select_temp = 1; + } else if (profi == "Rec2020") { + p1 = 0.7080; // Rec2020 primaries + p2 = 0.2920; + p3 = 0.1700; + p4 = 0.7970; + p5 = 0.1310; + p6 = 0.0460; + select_temp = 2; } else { p1 = 0.7347; //ProPhoto and default primaries p2 = 0.2653; @@ -511,7 +519,7 @@ Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int if(select_temp == 1) { t50 = 5003; // for Widegamut, Prophoto Best, Beta D50 } else if (select_temp == 2) { - t50 = 6504; // for sRGB, AdobeRGB, Bruce D65 + t50 = 6504; // for sRGB, AdobeRGB, Bruce Rec2020 D65 } cmsCIExyY xyD; @@ -601,9 +609,9 @@ Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int Color::xyz2srgb(x_, y_, z_, R, G, B); - image->r(i - cy, j - cx) = (int)gamma2curve[CLIP(R)]; - image->g(i - cy, j - cx) = (int)gamma2curve[CLIP(G)]; - image->b(i - cy, j - cx) = (int)gamma2curve[CLIP(B)]; + image->r(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(R)]; + image->g(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(G)]; + image->b(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(B)]; } } } diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index a3d624b65..279b77762 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -170,7 +170,6 @@ void ImProcFunctions::sharpening (LabImage* lab, float** b2, SharpeningParams &s // Rest is UNSHARP MASK int W = lab->W, H = lab->H; float** b3 = nullptr; - float** labCopy = nullptr; if (sharpenParam.edgesonly) { b3 = new float*[H]; @@ -180,15 +179,6 @@ void ImProcFunctions::sharpening (LabImage* lab, float** b2, SharpeningParams &s } } - if (sharpenParam.halocontrol && !sharpenParam.edgesonly) { - // We only need the lab channel copy in this special case - labCopy = new float*[H]; - - for( int i = 0; i < H; i++ ) { - labCopy[i] = new float[W]; - } - } - #ifdef _OPENMP #pragma omp parallel #endif @@ -200,55 +190,60 @@ void ImProcFunctions::sharpening (LabImage* lab, float** b2, SharpeningParams &s bilateral (lab->L, (float**)b3, b2, W, H, sharpenParam.edges_radius / scale, sharpenParam.edges_tolerance, multiThread); gaussianBlur (b3, b2, W, H, sharpenParam.radius / scale); } + } + float** base = lab->L; - float** base = lab->L; + if (sharpenParam.edgesonly) { + base = b3; + } - if (sharpenParam.edgesonly) { - base = b3; - } - - if (sharpenParam.halocontrol == false) { + if (!sharpenParam.halocontrol) { #ifdef _OPENMP - #pragma omp for + #pragma omp parallel for #endif - for (int i = 0; i < H; i++) - for (int j = 0; j < W; j++) { - const float upperBound = 2000.f; // WARNING: Duplicated value, it's baaaaaad ! - float diff = base[i][j] - b2[i][j]; - float delta = sharpenParam.threshold.multiply( - min(ABS(diff), upperBound), // X axis value = absolute value of the difference, truncated to the max value of this field - sharpenParam.amount * diff * 0.01f // Y axis max value - ); - lab->L[i][j] = lab->L[i][j] + delta; - } - } else { - if (!sharpenParam.edgesonly) { - // make a deep copy of lab->L -#ifdef _OPENMP - #pragma omp for -#endif + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + const float upperBound = 2000.f; // WARNING: Duplicated value, it's baaaaaad ! + float diff = base[i][j] - b2[i][j]; + float delta = sharpenParam.threshold.multiply( + min(ABS(diff), upperBound), // X axis value = absolute value of the difference, truncated to the max value of this field + sharpenParam.amount * diff * 0.01f // Y axis max value + ); + lab->L[i][j] = lab->L[i][j] + delta; + } + } else { + float** labCopy = nullptr; - for( int i = 0; i < H; i++ ) - for( int j = 0; j < W; j++ ) { - labCopy[i][j] = lab->L[i][j]; - } + if (!sharpenParam.edgesonly) { + // make a deep copy of lab->L + labCopy = new float*[H]; - base = labCopy; + for( int i = 0; i < H; i++ ) { + labCopy[i] = new float[W]; } - sharpenHaloCtrl (lab->L, b2, base, W, H, sharpenParam); +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for( int i = 0; i < H; i++ ) + for( int j = 0; j < W; j++ ) { + labCopy[i][j] = lab->L[i][j]; + } + + base = labCopy; } - } // end parallel + sharpenHaloCtrl (lab->L, b2, base, W, H, sharpenParam); - if (sharpenParam.halocontrol && !sharpenParam.edgesonly) { - // delete the deep copy - for( int i = 0; i < H; i++ ) { - delete[] labCopy[i]; + if (labCopy) { + for( int i = 0; i < H; i++ ) { + delete[] labCopy[i]; + } + + delete[] labCopy; } - - delete[] labCopy; } if (sharpenParam.edgesonly) { @@ -268,7 +263,7 @@ void ImProcFunctions::sharpenHaloCtrl (float** luminance, float** blurmap, float float** nL = base; #ifdef _OPENMP - #pragma omp for + #pragma omp parallel for #endif for (int i = 2; i < H - 2; i++) { @@ -940,7 +935,6 @@ void ImProcFunctions::sharpeningcam (CieImage* ncie, float** b2) int W = ncie->W, H = ncie->H; float** b3; - float** ncieCopy; if (params->sharpening.edgesonly) { b3 = new float*[H]; @@ -950,15 +944,6 @@ void ImProcFunctions::sharpeningcam (CieImage* ncie, float** b2) } } - if (params->sharpening.halocontrol && !params->sharpening.edgesonly) { - // We only need the lab parameter copy in this special case - ncieCopy = new float*[H]; - - for( int i = 0; i < H; i++ ) { - ncieCopy[i] = new float[W]; - } - } - #ifdef _OPENMP #pragma omp parallel #endif @@ -970,58 +955,64 @@ void ImProcFunctions::sharpeningcam (CieImage* ncie, float** b2) bilateral (ncie->sh_p, (float**)b3, b2, W, H, params->sharpening.edges_radius / scale, params->sharpening.edges_tolerance, multiThread); gaussianBlur (b3, b2, W, H, params->sharpening.radius / scale); } + } - float** base = ncie->sh_p; + float** base = ncie->sh_p; - if (params->sharpening.edgesonly) { - base = b3; - } + if (params->sharpening.edgesonly) { + base = b3; + } - if (params->sharpening.halocontrol == false) { + if (!params->sharpening.halocontrol) { #ifdef _OPENMP - #pragma omp for + #pragma omp parallel for #endif - for (int i = 0; i < H; i++) - for (int j = 0; j < W; j++) { - const float upperBound = 2000.f; // WARNING: Duplicated value, it's baaaaaad ! - float diff = base[i][j] - b2[i][j]; - float delta = params->sharpening.threshold.multiply( - min(ABS(diff), upperBound), // X axis value = absolute value of the difference, truncated to the max value of this field - params->sharpening.amount * diff * 0.01f // Y axis max value - ); + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + const float upperBound = 2000.f; // WARNING: Duplicated value, it's baaaaaad ! + float diff = base[i][j] - b2[i][j]; + float delta = params->sharpening.threshold.multiply( + min(ABS(diff), upperBound), // X axis value = absolute value of the difference, truncated to the max value of this field + params->sharpening.amount * diff * 0.01f // Y axis max value + ); - if(ncie->J_p[i][j] > 8.0f && ncie->J_p[i][j] < 92.0f) { - ncie->sh_p[i][j] = ncie->sh_p[i][j] + delta; - } + if(ncie->J_p[i][j] > 8.0f && ncie->J_p[i][j] < 92.0f) { + ncie->sh_p[i][j] = ncie->sh_p[i][j] + delta; } - } else { - if (!params->sharpening.edgesonly) { - // make a deep copy of lab->L -#ifdef _OPENMP - #pragma omp for -#endif + } + } else { + float** ncieCopy = nullptr; - for( int i = 0; i < H; i++ ) - for( int j = 0; j < W; j++ ) { - ncieCopy[i][j] = ncie->sh_p[i][j]; - } + if (!params->sharpening.edgesonly) { + // make deep copy of ncie->sh_p + ncieCopy = new float*[H]; - base = ncieCopy; + for( int i = 0; i < H; i++ ) { + ncieCopy[i] = new float[W]; } - sharpenHaloCtrl (ncie->sh_p, b2, base, W, H, params->sharpening); +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for( int i = 0; i < H; i++ ) + for( int j = 0; j < W; j++ ) { + ncieCopy[i][j] = ncie->sh_p[i][j]; + } + + base = ncieCopy; } - } // end parallel + sharpenHaloCtrl (ncie->sh_p, b2, base, W, H, params->sharpening); - if (params->sharpening.halocontrol && !params->sharpening.edgesonly) { - // delete the deep copy - for( int i = 0; i < H; i++ ) { - delete[] ncieCopy[i]; + if(ncieCopy) { + for( int i = 0; i < H; i++ ) { + delete[] ncieCopy[i]; + } + + delete[] ncieCopy; } - - delete[] ncieCopy; } if (params->sharpening.edgesonly) { diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index a1078e84f..547ebf69c 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -236,7 +236,7 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, LCPMapper *pLCPMap = NULL; - if (needsLCP() && focalLen > 0) { + if (needsLCP()) { // don't check focal length to allow distortion correction for lenses without chip LCPProfile *pLCPProf = lcpStore->getProfile(params->lensProf.lcpFile); if (pLCPProf) pLCPMap = new LCPMapper(pLCPProf, focalLen, focalLen35mm, focusDist, 0, false, params->lensProf.useDist, diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index 903e54a0a..1ed601301 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -19,7 +19,6 @@ #include #include "lcp.h" -#include "safegtk.h" #include "iccmatrices.h" #include "iccstore.h" #include "rawimagesource.h" @@ -303,7 +302,7 @@ LCPProfile::LCPProfile(Glib::ustring fname) persModelCount = 0; *inInvalidTag = 0; - FILE *pFile = safe_g_fopen(fname, "rb"); + FILE *pFile = g_fopen(fname.c_str (), "rb"); bool done; @@ -807,7 +806,7 @@ LCPProfile* LCPStore::getProfile (Glib::ustring filename) bool LCPStore::isValidLCPFileName(Glib::ustring filename) const { - if (!safe_file_test (filename, Glib::FILE_TEST_EXISTS) || safe_file_test (filename, Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (filename, Glib::FILE_TEST_EXISTS) || Glib::file_test (filename, Glib::FILE_TEST_IS_DIR)) { return false; } @@ -828,7 +827,7 @@ Glib::ustring LCPStore::getDefaultCommonDirectory() const WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); Glib::ustring fullDir = Glib::ustring(pathA) + Glib::ustring("\\Adobe\\CameraRaw\\LensProfiles\\1.0"); - if (safe_file_test(fullDir, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (fullDir, Glib::FILE_TEST_IS_DIR)) { dir = fullDir; } } diff --git a/rtengine/median.h b/rtengine/median.h index 61da0d5a0..d5e88d9de 100644 --- a/rtengine/median.h +++ b/rtengine/median.h @@ -16,207 +16,95 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#define SORT3(a1,a2,a3,b1,b2,b3) \ - { \ - if ((a1)<(a2)) { \ - if ((a2)<(a3)) { \ - (b1) = (a1); (b2) = (a2); (b3) = (a3); \ - } \ - else if ((a1)<(a3)) { \ - (b1) = (a1); (b2) = (a3); (b3) = (a2); \ - } \ - else { \ - (b1) = (a3); (b2) = (a1); (b3) = (a2); \ - } \ - } \ - else { \ - if ((a3)<(a2)) { \ - (b1) = (a3); (b2) = (a2); (b3) = (a1); \ - } \ - else if ((a3)<(a1)) { \ - (b1) = (a2); (b2) = (a3); (b3) = (a1); \ - } \ - else { \ - (b1) = (a2); (b2) = (a1); (b3) = (a3); \ - } \ - } \ - } +#include "rt_math.h" -#define MERGESORT(a1,a2,a3,b1,b2,b3,c1,c2,c3,c4,c5,c6) \ - {\ - if (a1 #include -#include "safegtk.h" #ifdef BZIP_SUPPORT #include #endif @@ -58,6 +57,7 @@ int munmap(void *start, size_t length) #else // WIN32 +#include #include #include @@ -68,7 +68,25 @@ int munmap(void *start, size_t length) IMFILE* fopen (const char* fname) { - int fd = safe_open_ReadOnly(fname); + int fd = -1; + +#ifdef WIN32 + + { + // First convert UTF8 to UTF16, then use Windows function to open the file and convert back to file descriptor. + std::unique_ptr wfname (reinterpret_cast(g_utf8_to_utf16 (fname, -1, NULL, NULL, NULL)), g_free); + + HANDLE hFile = CreateFileW (wfname.get (), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + fd = _open_osfhandle((intptr_t)hFile, 0); + } + } + +#else + + fd = ::g_open (fname, O_RDONLY); + +#endif if ( fd < 0 ) { return 0; @@ -78,7 +96,7 @@ IMFILE* fopen (const char* fname) if ( fstat(fd, &stat_buffer) < 0 ) { printf("no stat\n"); - close(fd); + close (fd); return 0; } diff --git a/rtengine/opthelper.h b/rtengine/opthelper.h index fc49ad12e..bee97f6b2 100644 --- a/rtengine/opthelper.h +++ b/rtengine/opthelper.h @@ -55,10 +55,10 @@ #define RESTRICT __restrict__ #define LIKELY(x) __builtin_expect (!!(x), 1) #define UNLIKELY(x) __builtin_expect (!!(x), 0) - #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) || __GNUC__ > 4 + #if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 9) || __GNUC__ > 4) && (!defined(WIN32) || defined( __x86_64__ )) #define ALIGNED64 __attribute__ ((aligned (64))) #define ALIGNED16 __attribute__ ((aligned (16))) - #else // there is a bug in gcc 4.7.x when using openmp and aligned memory and -O3 + #else // there is a bug in gcc 4.7.x when using openmp and aligned memory and -O3, also needed for WIN32 builds #define ALIGNED64 #define ALIGNED16 #endif @@ -69,7 +69,7 @@ #define ALIGNED64 #define ALIGNED16 #endif - #ifndef __clang__ - #define _RT_NESTED_OPENMP _OPENMP + #if !defined(__clang__) && defined _OPENMP + #define _RT_NESTED_OPENMP #endif #endif diff --git a/rtengine/editbuffer.cc b/rtengine/pipettebuffer.cc similarity index 50% rename from rtengine/editbuffer.cc rename to rtengine/pipettebuffer.cc index caf657070..d76589e99 100644 --- a/rtengine/editbuffer.cc +++ b/rtengine/pipettebuffer.cc @@ -17,16 +17,15 @@ * along with RawTherapee. If not, see . */ -#include "editbuffer.h" +#include "pipettebuffer.h" namespace rtengine { -EditBuffer::EditBuffer(::EditDataProvider *dataProvider) : - objectMap(NULL), objectMap2(NULL), objectMode(OM_255), dataProvider(dataProvider), - imgFloatBuffer(NULL), LabBuffer(NULL), singlePlaneBuffer(), ready(false) {} +PipetteBuffer::PipetteBuffer(::EditDataProvider *dataProvider) : + dataProvider(dataProvider), imgFloatBuffer(NULL), LabBuffer(NULL), singlePlaneBuffer(), ready(false) {} -EditBuffer::~EditBuffer() +PipetteBuffer::~PipetteBuffer() { flush(); #ifndef NDEBUG @@ -37,13 +36,13 @@ EditBuffer::~EditBuffer() #endif } -void EditBuffer::createBuffer(int width, int height) +void PipetteBuffer::createBuffer(int width, int height) { //printf("Appel de createBuffer %d x %d\n", width, height); resize (width, height); } -void EditBuffer::flush() +void PipetteBuffer::flush() { if (imgFloatBuffer) { delete imgFloatBuffer; @@ -59,29 +58,7 @@ void EditBuffer::flush() ready = false; } -/* Upgrade or downgrade the objectModeType; we're assuming that objectMap has been allocated */ -void EditBuffer::setObjectMode(ObjectMode newType) -{ - switch (newType) { - case (OM_255): - if (objectMap2) { - objectMap2->unreference(); - } - - objectMode = OM_255; - break; - - case (OM_65535): - if (!objectMap2) { - objectMap2 = Cairo::ImageSurface::create(Cairo::FORMAT_A8, objectMap->get_width(), objectMap->get_height()); - } - - objectMode = OM_65535; - break; - } -} - -EditUniqueID EditBuffer::getEditID() +EditUniqueID PipetteBuffer::getEditID() { if (dataProvider && dataProvider->getCurrSubscriber()) { return dataProvider->getCurrSubscriber()->getEditID(); @@ -90,58 +67,17 @@ EditUniqueID EditBuffer::getEditID() } } -void EditBuffer::resize(int newWidth, int newHeight) +void PipetteBuffer::resize(int newWidth, int newHeight) { resize(newWidth, newHeight, dataProvider ? dataProvider->getCurrSubscriber() : NULL); } // Resize buffers if they already exist -void EditBuffer::resize(int newWidth, int newHeight, EditSubscriber* newSubscriber) +void PipetteBuffer::resize(int newWidth, int newHeight, EditSubscriber* newSubscriber) { if (newSubscriber) { - if (newSubscriber->getEditingType() == ET_OBJECTS) { - if (objectMap && (objectMap->get_width() != newWidth || objectMap->get_height() != newHeight)) { - objectMap.clear(); - } - - if (!objectMap && newWidth && newHeight) { - objectMap = Cairo::ImageSurface::create(Cairo::FORMAT_A8, newWidth, newHeight); - } - - if (objectMode == OM_65535) { - if (objectMap2) { - if (objectMap2->get_width() != newWidth || objectMap2->get_height() != newHeight) { - objectMap2.clear(); - } - } - - if (!objectMap2 && newWidth && newHeight) { - objectMap2 = Cairo::ImageSurface::create(Cairo::FORMAT_A8, newWidth, newHeight); - } - } - // OM_255 -> deleting objectMap2, if any - else if (objectMap2) { - objectMap2.clear(); - } - - // Should never happen! - if (imgFloatBuffer) { - delete imgFloatBuffer; - imgFloatBuffer = NULL; - } - - if (LabBuffer) { - delete LabBuffer; - LabBuffer = NULL; - } - - if (singlePlaneBuffer.data) { - singlePlaneBuffer.allocate(0, 0); - } - } - if (newSubscriber->getEditingType() == ET_PIPETTE) { - if (newSubscriber->getEditBufferType() == BT_IMAGEFLOAT) { + if (newSubscriber->getPipetteBufferType() == BT_IMAGEFLOAT) { if (!imgFloatBuffer) { imgFloatBuffer = new Imagefloat(newWidth, newHeight); } else { @@ -152,7 +88,7 @@ void EditBuffer::resize(int newWidth, int newHeight, EditSubscriber* newSubscrib imgFloatBuffer = NULL; } - if (newSubscriber->getEditBufferType() == BT_LABIMAGE) { + if (newSubscriber->getPipetteBufferType() == BT_LABIMAGE) { if (LabBuffer && (LabBuffer->W != newWidth && LabBuffer->H != newHeight)) { delete LabBuffer; LabBuffer = NULL; @@ -166,73 +102,46 @@ void EditBuffer::resize(int newWidth, int newHeight, EditSubscriber* newSubscrib LabBuffer = NULL; } - if (newSubscriber->getEditBufferType() == BT_SINGLEPLANE_FLOAT) { + if (newSubscriber->getPipetteBufferType() == BT_SINGLEPLANE_FLOAT) { singlePlaneBuffer.allocate(newWidth, newHeight); } else if (singlePlaneBuffer.data) { singlePlaneBuffer.allocate(0, 0); } - - // Should never happen! - if (objectMap ) { - objectMap.clear(); - } - - if (objectMap2) { - objectMap2.clear(); - } + } else { + // Should never happen + flush(); } } ready = false; } -bool EditBuffer::bufferCreated() +bool PipetteBuffer::bufferCreated() { EditSubscriber* subscriber; if (dataProvider && (subscriber = dataProvider->getCurrSubscriber())) { - switch (subscriber->getEditingType()) { - case ET_PIPETTE: - switch (dataProvider->getCurrSubscriber()->getEditBufferType()) { + if (subscriber->getEditingType() == ET_PIPETTE) { + switch (dataProvider->getCurrSubscriber()->getPipetteBufferType()) { case (BT_IMAGEFLOAT): return imgFloatBuffer != NULL; - case (BT_LABIMAGE): return LabBuffer != NULL; - case (BT_SINGLEPLANE_FLOAT): return singlePlaneBuffer.data != NULL; } - - break; - - case (ET_OBJECTS): - return bool(objectMap); + } else { + return false; } } return false; } -int EditBuffer::getObjectID(const Coord& location) -{ - int id = 0; - - if (objectMap && location.x > 0 && location.y > 0 && location.x < objectMap->get_width() && location.y < objectMap->get_height()) { - id = (unsigned short)(*( objectMap->get_data() + location.y * objectMap->get_stride() + location.x )); - - if (objectMap2) { - id |= (unsigned short)(*( objectMap->get_data() + location.y * objectMap->get_stride() + location.x )) << 8; - } - } - - return id - 1; -} - -void EditBuffer::getPipetteData(float* v, int x, int y, int squareSize) +void PipetteBuffer::getPipetteData(float* v, int x, int y, int squareSize) { if (ready && dataProvider && dataProvider->getCurrSubscriber()) { - switch (dataProvider->getCurrSubscriber()->getEditBufferType()) { + switch (dataProvider->getCurrSubscriber()->getPipetteBufferType()) { case (BT_IMAGEFLOAT): if (imgFloatBuffer) { imgFloatBuffer->getPipetteData(v[0], v[1], v[2], x, y, squareSize, 0); diff --git a/rtengine/editbuffer.h b/rtengine/pipettebuffer.h similarity index 57% rename from rtengine/editbuffer.h rename to rtengine/pipettebuffer.h index 1a55a39ed..e6db8eb68 100644 --- a/rtengine/editbuffer.h +++ b/rtengine/pipettebuffer.h @@ -16,8 +16,8 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#ifndef _EDITBUFFER_H_ -#define _EDITBUFFER_H_ +#ifndef _PIPETTEBUFFER_H_ +#define _PIPETTEBUFFER_H_ #include "../rtgui/edit.h" #include "array2D.h" @@ -28,16 +28,8 @@ namespace rtengine { /// @brief Structure that contains information about and pointers to the Edit buffer -class EditBuffer +class PipetteBuffer { -private: - - // Used to draw the objects where the color correspond to the object's ID, in order to find the correct object when hovering - Cairo::RefPtr objectMap; - // If more than 254 objects has to be handled, objectMap2 contains the "upper part" of the 16 bit int value. objectMap2 will be NULL otherwise. - Cairo::RefPtr objectMap2; - ObjectMode objectMode; - protected: // To avoid duplicated information, we points to a EditDataProvider that contains the current EditSubscriber @@ -52,39 +44,38 @@ protected: bool ready; // flag that indicates if the _pipette_ buffer is ready - void createBuffer(int width, int height); - void resize(int newWidth, int newHeight, EditSubscriber* newSubscriber); - void resize(int newWidth, int newHeight); - void flush(); + void createBuffer(int width, int height); + void resize(int newWidth, int newHeight, EditSubscriber* newSubscriber); + void resize(int newWidth, int newHeight); + void flush(); public: - EditBuffer(::EditDataProvider *dataProvider); - ~EditBuffer(); + PipetteBuffer(::EditDataProvider *dataProvider); + ~PipetteBuffer(); /** @brief Getter to know if the pipette buffer is correctly filled */ - bool isReady() + bool isReady() { return ready; } /** @brief Setter to tell that the pipette buffer is correctly filled * You have to use this method once the pipette is filled, so it can be read. */ - void setReady() + void setReady() { ready = true; } - void setObjectMode(ObjectMode newType); - ::EditDataProvider* getDataProvider() + ::EditDataProvider* getDataProvider() { return dataProvider; } - EditUniqueID getEditID(); - Imagefloat* getImgFloatBuffer() + EditUniqueID getEditID(); + Imagefloat* getImgFloatBuffer() { return imgFloatBuffer; } - LabImage* getLabBuffer() + LabImage* getLabBuffer() { return LabBuffer; } @@ -92,26 +83,12 @@ public: { return &singlePlaneBuffer; } - ObjectMode getObjectMode() - { - return objectMode; - } - - Cairo::RefPtr &getObjectMap () - { - return objectMap; - } - Cairo::RefPtr &getObjectMap2() - { - return objectMap2; - } // return true if the buffer has been allocated - bool bufferCreated(); + bool bufferCreated(); - int getObjectID(const Coord& location); // get the pipette values - void getPipetteData(float* v, int x, int y, int squareSize); + void getPipetteData(float* v, int x, int y, int squareSize); }; } diff --git a/rtengine/previewimage.cc b/rtengine/previewimage.cc index 5f7ea8ad6..f9f6c12a1 100644 --- a/rtengine/previewimage.cc +++ b/rtengine/previewimage.cc @@ -23,7 +23,6 @@ #include "iimage.h" #include "rtthumbnail.h" #include "rawimagesource.h" -#include "StopWatch.h" using namespace rtengine; using namespace procparams; @@ -144,9 +143,7 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext rawImage.getImage (wb, TR_NONE, image, pp, params.toneCurve, params.icm, params.raw); output = new Image8(fw, fh); rawImage.convertColorSpace(image, params.icm, wb); - StopWatch Stop1("inspector loop"); #pragma omp parallel for schedule(dynamic, 10) - for (int i = 0; i < fh; ++i) for (int j = 0; j < fw; ++j) { image->r(i, j) = Color::gamma2curve[image->r(i, j)]; @@ -154,7 +151,6 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext image->b(i, j) = Color::gamma2curve[image->b(i, j)]; } - Stop1.stop(); image->resizeImgTo(fw, fh, TI_Nearest, output); data = output->getData(); diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 2a12516ce..62d2a4ac1 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -466,9 +466,11 @@ enum ProcEvent { EvmapMethod = 436, EvRetinexmapcurve = 437, EvviewMethod = 438, - EvRetinexgaintransmission = 439, - EvLskal = 440, + EvcbdlMethod = 439, + EvRetinexgaintransmission = 440, + EvLskal = 441, NUMOFEVENTS + }; } #endif diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 7575564c5..67b02a650 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -16,11 +16,9 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -//#include +#include #include "procparams.h" #include "rt_math.h" -#include "safegtk.h" -#include "safekeyfile.h" #include "dcp.h" #include "../rtgui/multilangmgr.h" #include "../rtgui/version.h" @@ -910,6 +908,7 @@ void RAWParams::setDefaults() ff_clipControl = 0; cared = 0; cablue = 0; + caautostrength = 2; ca_autocorrect = false; hotPixelFilter = false; deadPixelFilter = false; @@ -1239,6 +1238,8 @@ void ProcParams::setDefaults () dirpyrequalizer.enabled = false; dirpyrequalizer.gamutlab = false; + dirpyrequalizer.cbdlMethod = "bef"; + for(int i = 0; i < 6; i ++) { dirpyrequalizer.mult[i] = 1.0; @@ -1323,11 +1324,15 @@ static Glib::ustring relativePathIfInside(Glib::ustring procparams_fname, bool f int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsolute, ParamsEdited* pedited) { - if (!fname.length() && !fname2.length()) { + if (fname.empty () && fname2.empty ()) { return 0; } - SafeKeyFile keyFile; + Glib::ustring sPParams; + + try { + + Glib::KeyFile keyFile; keyFile.set_string ("Version", "AppVersion", APPVERSION); keyFile.set_integer ("Version", "Version", PPVERSION); @@ -3053,6 +3058,10 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol keyFile.set_boolean ("Directional Pyramid Equalizer", "Gamutlab", dirpyrequalizer.gamutlab); } + if (!pedited || pedited->dirpyrequalizer.cbdlMethod) { + keyFile.set_string ("Directional Pyramid Equalizer", "cbdlMethod", dirpyrequalizer.cbdlMethod); + } + for(int i = 0; i < 6; i++) { std::stringstream ss; ss << "Mult" << i; @@ -3273,6 +3282,10 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol keyFile.set_boolean ("RAW", "CA", raw.ca_autocorrect ); } + if (!pedited || pedited->raw.caAutoStrength) { + keyFile.set_double ("RAW", "CAAutoStrength", raw.caautostrength ); + } + if (!pedited || pedited->raw.caRed) { keyFile.set_double ("RAW", "CARed", raw.cared ); } @@ -3388,12 +3401,18 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol } } - Glib::ustring sPParams = keyFile.to_data(); + sPParams = keyFile.to_data(); + + } catch(Glib::KeyFileError&) {} + + if (sPParams.empty ()) { + return 1; + } int error1, error2; - error1 = write (fname , sPParams); + error1 = write (fname, sPParams); - if (fname2.length()) { + if (!fname2.empty ()) { error2 = write (fname2, sPParams); // If at least one file has been saved, it's a success @@ -3410,7 +3429,7 @@ int ProcParams::write (Glib::ustring &fname, Glib::ustring &content) const if (fname.length()) { FILE *f; - f = safe_g_fopen (fname, "wt"); + f = g_fopen (fname.c_str (), "wt"); if (f == NULL) { error = 1; @@ -3431,15 +3450,15 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) return 1; } - SafeKeyFile keyFile; + Glib::KeyFile keyFile; try { - //setDefaults (); + if (pedited) { pedited->set(false); } - FILE* f = safe_g_fopen (fname, "rt"); + FILE* f = g_fopen (fname.c_str (), "rt"); if (!f) { return 1; @@ -3475,8 +3494,6 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) } } -//printf("ProcParams::load called ppVersion=%i\n",ppVersion); - if (keyFile.has_group ("General")) { if (keyFile.has_key ("General", "Rank")) { rank = keyFile.get_integer ("General", "Rank"); @@ -6645,6 +6662,16 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) } } + + if (keyFile.has_key ("Directional Pyramid Equalizer", "cbdlMethod")) { + dirpyrequalizer.cbdlMethod = keyFile.get_string ("Directional Pyramid Equalizer", "cbdlMethod"); + + if (pedited) { + pedited->dirpyrequalizer.cbdlMethod = true; + } + } + + // if (keyFile.has_key ("Directional Pyramid Equalizer", "Algorithm")) { dirpyrequalizer.algo = keyFile.get_string ("Directional Pyramid Equalizer", "Algorithm"); if (pedited) pedited->dirpyrequalizer.algo = true; } if (keyFile.has_key ("Directional Pyramid Equalizer", "Hueskin")) { Glib::ArrayHandle thresh = keyFile.get_integer_list ("Directional Pyramid Equalizer", "Hueskin"); @@ -7093,6 +7120,14 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) } } + if (keyFile.has_key ("RAW", "CAAutoStrength")) { + raw.caautostrength = keyFile.get_double ("RAW", "CAAutoStrength" ); + + if (pedited) { + pedited->raw.caAutoStrength = true; + } + } + if (keyFile.has_key ("RAW", "CARed")) { raw.cared = keyFile.get_double ("RAW", "CARed" ); @@ -7462,9 +7497,11 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) return 0; } catch (const Glib::Error& e) { printf ("-->%s\n", e.what().c_str()); + setDefaults (); return 1; } catch (...) { printf ("-->unknown exception!\n"); + setDefaults (); return 1; } @@ -7813,6 +7850,7 @@ bool ProcParams::operator== (const ProcParams& other) && raw.expos == other.raw.expos && raw.preser == other.raw.preser && raw.ca_autocorrect == other.raw.ca_autocorrect + && raw.caautostrength == other.raw.caautostrength && raw.cared == other.raw.cared && raw.cablue == other.raw.cablue && raw.hotPixelFilter == other.raw.hotPixelFilter @@ -7916,6 +7954,7 @@ bool ProcParams::operator== (const ProcParams& other) // && dirpyrequalizer.algo == other.dirpyrequalizer.algo && dirpyrequalizer.hueskin == other.dirpyrequalizer.hueskin && dirpyrequalizer.threshold == other.dirpyrequalizer.threshold + && dirpyrequalizer.cbdlMethod == other.dirpyrequalizer.cbdlMethod && dirpyrequalizer.skinprotect == other.dirpyrequalizer.skinprotect && hsvequalizer.hcurve == other.hsvequalizer.hcurve && hsvequalizer.scurve == other.hsvequalizer.scurve diff --git a/rtengine/procparams.h b/rtengine/procparams.h index f07de9523..7f30f0cc9 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1110,7 +1110,7 @@ public: double skinprotect; Threshold hueskin; //Glib::ustring algo; - + Glib::ustring cbdlMethod; DirPyrEqualizerParams() : hueskin(20, 80, 2000, 1200, false) {}; }; @@ -1222,6 +1222,7 @@ public: int ff_clipControl; bool ca_autocorrect; + double caautostrength; double cared; double cablue; diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index 3b491eab5..3f4b2ac3f 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -13,7 +13,6 @@ #else #include #endif -#include "safegtk.h" namespace rtengine { @@ -88,17 +87,17 @@ void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblac float val; double dsum[8], dmin, dmax; - if ((this->get_cblack(4) + 1) / 2 == 1 && (this->get_cblack(5) + 1) / 2 == 1) { - for (int c = 0; c < 4; c++) { - cblack_[FC(c / 2, c % 2)] = this->get_cblack(6 + c / 2 % this->get_cblack(4) * this->get_cblack(5) + c % 2 % this->get_cblack(5)); - pre_mul_[c] = this->get_pre_mul(c); - } - } else if(isXtrans()) { + if(isXtrans()) { // for xtrans files dcraw stores black levels in cblack[6] .. cblack[41], but all are equal, so we just use cblack[6] for (int c = 0; c < 4; c++) { cblack_[c] = (float) this->get_cblack(6); pre_mul_[c] = this->get_pre_mul(c); } + } else if ((this->get_cblack(4) + 1) / 2 == 1 && (this->get_cblack(5) + 1) / 2 == 1) { + for (int c = 0; c < 4; c++) { + cblack_[FC(c / 2, c % 2)] = this->get_cblack(6 + c / 2 % this->get_cblack(4) * this->get_cblack(5) + c % 2 % this->get_cblack(5)); + pre_mul_[c] = this->get_pre_mul(c); + } } else { for (int c = 0; c < 4; c++) { cblack_[c] = (float) this->get_cblack(c); @@ -495,11 +494,13 @@ int RawImage::loadRaw (bool loadData, bool closeFile, ProgressListener *plistene if (cc && cc->has_rawCrop()) { int lm, tm, w, h; cc->get_rawCrop(lm, tm, w, h); - - if(((int)top_margin - tm) & 1) { // we have an odd border difference - filters = (filters << 4) | (filters >> 28); // left rotate filters by 4 bits + if(isXtrans()) { + shiftXtransMatrix(6 - ((top_margin - tm)%6), 6 - ((left_margin - lm)%6)); + } else { + if(((int)top_margin - tm) & 1) { // we have an odd border difference + filters = (filters << 4) | (filters >> 28); // left rotate filters by 4 bits + } } - left_margin = lm; top_margin = tm; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index b29348c9f..27ddb6b3c 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -37,6 +37,8 @@ #include #endif #include "opthelper.h" +//#define BENCHMARK +#include "StopWatch.h" #define clipretinex( val, minv, maxv ) (( val = (val < minv ? minv : val ) ) > maxv ? maxv : val ) #undef CLIPD #define CLIPD(a) ((a)>0.0f?((a)<1.0f?(a):1.0f):0.0f) @@ -1761,8 +1763,8 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le if (!hasFlatField && lensProf.useVign) { LCPProfile *pLCPProf = lcpStore->getProfile(lensProf.lcpFile); - if (pLCPProf && idata->getFocalLen() > 0.f) { - LCPMapper map(pLCPProf, idata->getFocalLen(), idata->getFocalLen35mm(), idata->getFocusDist(), idata->getFNumber(), true, false, W, H, coarse, -1); + if (pLCPProf) { // don't check focal length to allow distortion correction for lenses without chip, also pass dummy focal length 1 in case of 0 + LCPMapper map(pLCPProf, max(idata->getFocalLen(),1.0), idata->getFocalLen35mm(), idata->getFocusDist(), idata->getFNumber(), true, false, W, H, coarse, -1); #ifdef _OPENMP #pragma omp parallel for @@ -1866,7 +1868,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le plistener->setProgress (0.0); } - CA_correct_RT(raw.cared, raw.cablue); + CA_correct_RT(raw.cared, raw.cablue, 10.0 - raw.caautostrength); } if ( raw.expos != 1 ) { @@ -3452,31 +3454,30 @@ int RawImageSource::defTransform (int tran) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Thread called part -void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, int row_from, int row_to) +void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, array2D &rbconv_Y, array2D &rbconv_I, array2D &rbconv_Q, array2D &rbout_I, array2D &rbout_Q, const int row_from, const int row_to) { - int W = im->width; + const int W = im->width; + constexpr float onebynine = 1.f / 9.f; - array2D rbconv_Y (W, 3); - array2D rbconv_I (W, 3); - array2D rbconv_Q (W, 3); - array2D rbout_I (W, 3); - array2D rbout_Q (W, 3); +#ifdef __SSE2__ + vfloat buffer[12]; + vfloat* pre1 = &buffer[0]; + vfloat* pre2 = &buffer[3]; + vfloat* post1 = &buffer[6]; + vfloat* post2 = &buffer[9]; - float* row_I = new float[W]; - float* row_Q = new float[W]; + vfloat middle[6]; - float* pre1_I = new float[3]; - float* pre2_I = new float[3]; - float* post1_I = new float[3]; - float* post2_I = new float[3]; - float middle_I[6]; - float* pre1_Q = new float[3]; - float* pre2_Q = new float[3]; - float* post1_Q = new float[3]; - float* post2_Q = new float[3]; - float middle_Q[6]; - float* tmp; +#else + float buffer[12]; + float* pre1 = &buffer[0]; + float* pre2 = &buffer[3]; + float* post1 = &buffer[6]; + float* post2 = &buffer[9]; + + float middle[6]; +#endif int px = (row_from - 1) % 3, cx = row_from % 3, nx = 0; @@ -3496,117 +3497,152 @@ void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, int row convert_row_to_YIQ (im->r(i + 1), im->g(i + 1), im->b(i + 1), rbconv_Y[nx], rbconv_I[nx], rbconv_Q[nx], W); - SORT3(rbconv_I[px][0], rbconv_I[cx][0], rbconv_I[nx][0], pre1_I[0], pre1_I[1], pre1_I[2]); - SORT3(rbconv_I[px][1], rbconv_I[cx][1], rbconv_I[nx][1], pre2_I[0], pre2_I[1], pre2_I[2]); - SORT3(rbconv_Q[px][0], rbconv_Q[cx][0], rbconv_Q[nx][0], pre1_Q[0], pre1_Q[1], pre1_Q[2]); - SORT3(rbconv_Q[px][1], rbconv_Q[cx][1], rbconv_Q[nx][1], pre2_Q[0], pre2_Q[1], pre2_Q[2]); +#ifdef __SSE2__ + pre1[0] = _mm_setr_ps(rbconv_I[px][0], rbconv_Q[px][0], 0, 0) , pre1[1] = _mm_setr_ps(rbconv_I[cx][0], rbconv_Q[cx][0], 0, 0), pre1[2] = _mm_setr_ps(rbconv_I[nx][0], rbconv_Q[nx][0], 0, 0); + pre2[0] = _mm_setr_ps(rbconv_I[px][1], rbconv_Q[px][1], 0, 0) , pre2[1] = _mm_setr_ps(rbconv_I[cx][1], rbconv_Q[cx][1], 0, 0), pre2[2] = _mm_setr_ps(rbconv_I[nx][1], rbconv_Q[nx][1], 0, 0); + vfloat temp[7]; + + // fill first element in rbout_I and rbout_Q + rbout_I[cx][0] = rbconv_I[cx][0]; + rbout_Q[cx][0] = rbconv_Q[cx][0]; // median I channel for (int j = 1; j < W - 2; j += 2) { - SORT3(rbconv_I[px][j + 1], rbconv_I[cx][j + 1], rbconv_I[nx][j + 1], post1_I[0], post1_I[1], post1_I[2]); - SORT3(rbconv_I[px][j + 2], rbconv_I[cx][j + 2], rbconv_I[nx][j + 2], post2_I[0], post2_I[1], post2_I[2]); - MERGESORT(pre2_I[0], pre2_I[1], pre2_I[2], post1_I[0], post1_I[1], post1_I[2], middle_I[0], middle_I[1], middle_I[2], middle_I[3], middle_I[4], middle_I[5]); - MEDIAN7(pre1_I[0], pre1_I[1], pre1_I[2], middle_I[1], middle_I[2], middle_I[3], middle_I[4], rbout_I[cx][j]); - MEDIAN7(post2_I[0], post2_I[1], post2_I[2], middle_I[1], middle_I[2], middle_I[3], middle_I[4], rbout_I[cx][j + 1]); - tmp = pre1_I; - pre1_I = post1_I; - post1_I = tmp; - tmp = pre2_I; - pre2_I = post2_I; - post2_I = tmp; - + post1[0] = _mm_setr_ps(rbconv_I[px][j + 1], rbconv_Q[px][j + 1], 0, 0), post1[1] = _mm_setr_ps(rbconv_I[cx][j + 1], rbconv_Q[cx][j + 1], 0, 0), post1[2] = _mm_setr_ps(rbconv_I[nx][j + 1], rbconv_Q[nx][j + 1], 0, 0); + VMIDDLE4OF6(pre2[0], pre2[1], pre2[2], post1[0], post1[1], post1[2], middle[0], middle[1], middle[2], middle[3], middle[4], middle[5], temp[0]); + vfloat medianval; + VMEDIAN7(pre1[0], pre1[1], pre1[2], middle[1], middle[2], middle[3], middle[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], medianval); + rbout_I[cx][j] = medianval[0]; + rbout_Q[cx][j] = medianval[1]; + post2[0] = _mm_setr_ps(rbconv_I[px][j + 2], rbconv_Q[px][j + 2], 0, 0), post2[1] = _mm_setr_ps(rbconv_I[cx][j + 2], rbconv_Q[cx][j + 2], 0, 0), post2[2] = _mm_setr_ps(rbconv_I[nx][j + 2], rbconv_Q[nx][j + 2], 0, 0); + VMEDIAN7(post2[0], post2[1], post2[2], middle[1], middle[2], middle[3], middle[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], medianval); + rbout_I[cx][j + 1] = medianval[0]; + rbout_Q[cx][j + 1] = medianval[1]; + std::swap(pre1, post1); + std::swap(pre2, post2); } - // median Q channel - for (int j = 1; j < W - 2; j += 2) { - SORT3(rbconv_Q[px][j + 1], rbconv_Q[cx][j + 1], rbconv_Q[nx][j + 1], post1_Q[0], post1_Q[1], post1_Q[2]); - SORT3(rbconv_Q[px][j + 2], rbconv_Q[cx][j + 2], rbconv_Q[nx][j + 2], post2_Q[0], post2_Q[1], post2_Q[2]); - MERGESORT(pre2_Q[0], pre2_Q[1], pre2_Q[2], post1_Q[0], post1_Q[1], post1_Q[2], middle_Q[0], middle_Q[1], middle_Q[2], middle_Q[3], middle_Q[4], middle_Q[5]); - MEDIAN7(pre1_Q[0], pre1_Q[1], pre1_Q[2], middle_Q[1], middle_Q[2], middle_Q[3], middle_Q[4], rbout_Q[cx][j]); - MEDIAN7(post2_Q[0], post2_Q[1], post2_Q[2], middle_Q[1], middle_Q[2], middle_Q[3], middle_Q[4], rbout_Q[cx][j + 1]); - tmp = pre1_Q; - pre1_Q = post1_Q; - post1_Q = tmp; - tmp = pre2_Q; - pre2_Q = post2_Q; - post2_Q = tmp; - } - - // fill first and last element in rbout - rbout_I[cx][0] = rbconv_I[cx][0]; + // fill last elements in rbout_I and rbout_Q rbout_I[cx][W - 1] = rbconv_I[cx][W - 1]; rbout_I[cx][W - 2] = rbconv_I[cx][W - 2]; - rbout_Q[cx][0] = rbconv_Q[cx][0]; rbout_Q[cx][W - 1] = rbconv_Q[cx][W - 1]; rbout_Q[cx][W - 2] = rbconv_Q[cx][W - 2]; +#else + pre1[0] = rbconv_I[px][0], pre1[1] = rbconv_I[cx][0], pre1[2] = rbconv_I[nx][0]; + pre2[0] = rbconv_I[px][1], pre2[1] = rbconv_I[cx][1], pre2[2] = rbconv_I[nx][1]; + float temp[7]; + + // fill first element in rbout_I + rbout_I[cx][0] = rbconv_I[cx][0]; + + // median I channel + for (int j = 1; j < W - 2; j += 2) { + post1[0] = rbconv_I[px][j + 1], post1[1] = rbconv_I[cx][j + 1], post1[2] = rbconv_I[nx][j + 1]; + MIDDLE4OF6(pre2[0], pre2[1], pre2[2], post1[0], post1[1], post1[2], middle[0], middle[1], middle[2], middle[3], middle[4], middle[5], temp[0]); + MEDIAN7(pre1[0], pre1[1], pre1[2], middle[1], middle[2], middle[3], middle[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], rbout_I[cx][j]); + post2[0] = rbconv_I[px][j + 2], post2[1] = rbconv_I[cx][j + 2], post2[2] = rbconv_I[nx][j + 2]; + MEDIAN7(post2[0], post2[1], post2[2], middle[1], middle[2], middle[3], middle[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], rbout_I[cx][j + 1]); + std::swap(pre1, post1); + std::swap(pre2, post2); + } + + // fill last elements in rbout_I + rbout_I[cx][W - 1] = rbconv_I[cx][W - 1]; + rbout_I[cx][W - 2] = rbconv_I[cx][W - 2]; + + pre1[0] = rbconv_Q[px][0], pre1[1] = rbconv_Q[cx][0], pre1[2] = rbconv_Q[nx][0]; + pre2[0] = rbconv_Q[px][1], pre2[1] = rbconv_Q[cx][1], pre2[2] = rbconv_Q[nx][1]; + + // fill first element in rbout_Q + rbout_Q[cx][0] = rbconv_Q[cx][0]; + + // median Q channel + for (int j = 1; j < W - 2; j += 2) { + post1[0] = rbconv_Q[px][j + 1], post1[1] = rbconv_Q[cx][j + 1], post1[2] = rbconv_Q[nx][j + 1]; + MIDDLE4OF6(pre2[0], pre2[1], pre2[2], post1[0], post1[1], post1[2], middle[0], middle[1], middle[2], middle[3], middle[4], middle[5], temp[0]); + MEDIAN7(pre1[0], pre1[1], pre1[2], middle[1], middle[2], middle[3], middle[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], rbout_Q[cx][j]); + post2[0] = rbconv_Q[px][j + 2], post2[1] = rbconv_Q[cx][j + 2], post2[2] = rbconv_Q[nx][j + 2]; + MEDIAN7(post2[0], post2[1], post2[2], middle[1], middle[2], middle[3], middle[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], rbout_Q[cx][j + 1]); + std::swap(pre1, post1); + std::swap(pre2, post2); + } + + // fill last elements in rbout_Q + rbout_Q[cx][W - 1] = rbconv_Q[cx][W - 1]; + rbout_Q[cx][W - 2] = rbconv_Q[cx][W - 2]; +#endif + // blur i-1th row if (i > row_from) { + convert_to_RGB (im->r(i - 1, 0), im->g(i - 1, 0), im->b(i - 1, 0), rbconv_Y[px][0], rbout_I[px][0], rbout_Q[px][0]); + +#ifdef _OPENMP + #pragma omp simd +#endif + for (int j = 1; j < W - 1; j++) { - row_I[j] = (rbout_I[px][j - 1] + rbout_I[px][j] + rbout_I[px][j + 1] + rbout_I[cx][j - 1] + rbout_I[cx][j] + rbout_I[cx][j + 1] + rbout_I[nx][j - 1] + rbout_I[nx][j] + rbout_I[nx][j + 1]) / 9; - row_Q[j] = (rbout_Q[px][j - 1] + rbout_Q[px][j] + rbout_Q[px][j + 1] + rbout_Q[cx][j - 1] + rbout_Q[cx][j] + rbout_Q[cx][j + 1] + rbout_Q[nx][j - 1] + rbout_Q[nx][j] + rbout_Q[nx][j + 1]) / 9; + float I = (rbout_I[px][j - 1] + rbout_I[px][j] + rbout_I[px][j + 1] + rbout_I[cx][j - 1] + rbout_I[cx][j] + rbout_I[cx][j + 1] + rbout_I[nx][j - 1] + rbout_I[nx][j] + rbout_I[nx][j + 1]) * onebynine; + float Q = (rbout_Q[px][j - 1] + rbout_Q[px][j] + rbout_Q[px][j + 1] + rbout_Q[cx][j - 1] + rbout_Q[cx][j] + rbout_Q[cx][j + 1] + rbout_Q[nx][j - 1] + rbout_Q[nx][j] + rbout_Q[nx][j + 1]) * onebynine; + convert_to_RGB (im->r(i - 1, j), im->g(i - 1, j), im->b(i - 1, j), rbconv_Y[px][j], I, Q); } - row_I[0] = rbout_I[px][0]; - row_Q[0] = rbout_Q[px][0]; - row_I[W - 1] = rbout_I[px][W - 1]; - row_Q[W - 1] = rbout_Q[px][W - 1]; - convert_row_to_RGB (im->r(i - 1), im->g(i - 1), im->b(i - 1), rbconv_Y[px], row_I, row_Q, W); + convert_to_RGB (im->r(i - 1, W - 1), im->g(i - 1, W - 1), im->b(i - 1, W - 1), rbconv_Y[px][W - 1], rbout_I[px][W - 1], rbout_Q[px][W - 1]); } } // blur last 3 row and finalize H-1th row + convert_to_RGB (im->r(row_to - 1, 0), im->g(row_to - 1, 0), im->b(row_to - 1, 0), rbconv_Y[cx][0], rbout_I[cx][0], rbout_Q[cx][0]); +#ifdef _OPENMP + #pragma omp simd +#endif + for (int j = 1; j < W - 1; j++) { - row_I[j] = (rbout_I[px][j - 1] + rbout_I[px][j] + rbout_I[px][j + 1] + rbout_I[cx][j - 1] + rbout_I[cx][j] + rbout_I[cx][j + 1] + rbconv_I[nx][j - 1] + rbconv_I[nx][j] + rbconv_I[nx][j + 1]) / 9; - row_Q[j] = (rbout_Q[px][j - 1] + rbout_Q[px][j] + rbout_Q[px][j + 1] + rbout_Q[cx][j - 1] + rbout_Q[cx][j] + rbout_Q[cx][j + 1] + rbconv_Q[nx][j - 1] + rbconv_Q[nx][j] + rbconv_Q[nx][j + 1]) / 9; + float I = (rbout_I[px][j - 1] + rbout_I[px][j] + rbout_I[px][j + 1] + rbout_I[cx][j - 1] + rbout_I[cx][j] + rbout_I[cx][j + 1] + rbconv_I[nx][j - 1] + rbconv_I[nx][j] + rbconv_I[nx][j + 1]) * onebynine; + float Q = (rbout_Q[px][j - 1] + rbout_Q[px][j] + rbout_Q[px][j + 1] + rbout_Q[cx][j - 1] + rbout_Q[cx][j] + rbout_Q[cx][j + 1] + rbconv_Q[nx][j - 1] + rbconv_Q[nx][j] + rbconv_Q[nx][j + 1]) * onebynine; + convert_to_RGB (im->r(row_to - 1, j), im->g(row_to - 1, j), im->b(row_to - 1, j), rbconv_Y[cx][j], I, Q); } - row_I[0] = rbout_I[cx][0]; - row_Q[0] = rbout_Q[cx][0]; - row_I[W - 1] = rbout_I[cx][W - 1]; - row_Q[W - 1] = rbout_Q[cx][W - 1]; - convert_row_to_RGB (im->r(row_to - 1), im->g(row_to - 1), im->b(row_to - 1), rbconv_Y[cx], row_I, row_Q, W); - - delete [] row_I; - delete [] row_Q; - delete [] pre1_I; - delete [] pre2_I; - delete [] post1_I; - delete [] post2_I; - delete [] pre1_Q; - delete [] pre2_Q; - delete [] post1_Q; - delete [] post2_Q; + convert_to_RGB (im->r(row_to - 1, W - 1), im->g(row_to - 1, W - 1), im->b(row_to - 1, W - 1), rbconv_Y[cx][W - 1], rbout_I[cx][W - 1], rbout_Q[cx][W - 1]); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // correction_YIQ_LQ -void RawImageSource::processFalseColorCorrection (Imagefloat* im, int steps) +void RawImageSource::processFalseColorCorrection (Imagefloat* im, const int steps) { - if (im->height < 4) { + if (im->height < 4 || steps < 1) { return; } - for (int t = 0; t < steps; t++) { #ifdef _OPENMP - #pragma omp parallel - { - int tid = omp_get_thread_num(); - int nthreads = omp_get_num_threads(); - int blk = (im->height - 2) / nthreads; + #pragma omp parallel + { + multi_array2D buffer (W, 3); + int tid = omp_get_thread_num(); + int nthreads = omp_get_num_threads(); + int blk = (im->height - 2) / nthreads; - if (tid < nthreads - 1) - { - processFalseColorCorrectionThread (im, 1 + tid * blk, 1 + (tid + 1)*blk); - } else - { processFalseColorCorrectionThread (im, 1 + tid * blk, im->height - 1); } + for (int t = 0; t < steps; t++) { + + if (tid < nthreads - 1) { + processFalseColorCorrectionThread (im, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], 1 + tid * blk, 1 + (tid + 1)*blk); + } else { + processFalseColorCorrectionThread (im, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], 1 + tid * blk, im->height - 1); + } + + #pragma omp barrier } -#else - processFalseColorCorrectionThread (im, 1 , im->height - 1); -#endif } +#else + multi_array2D buffer (W, 3); + + for (int t = 0; t < steps; t++) { + processFalseColorCorrectionThread (im, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], 1 , im->height - 1); + } + +#endif } // Some camera input profiles need gamma preprocessing @@ -4275,14 +4311,14 @@ void RawImageSource::HLRecovery_CIELab (float* rin, float* gin, float* bin, floa float go = min(g, maxval); float bo = min(b, maxval); float yy = xyz_cam[1][0] * r + xyz_cam[1][1] * g + xyz_cam[1][2] * b; - float fy = (yy < 65535.0 ? ImProcFunctions::cachef[yy] / 327.68 : (exp(log(yy / MAXVALD) / 3.0 ))); + float fy = (yy < 65535.0 ? Color::cachef[yy] / 327.68 : std::cbrt(yy / MAXVALD)); // compute LCH decompostion of the clipped pixel (only color information, thus C and H will be used) float x = xyz_cam[0][0] * ro + xyz_cam[0][1] * go + xyz_cam[0][2] * bo; float y = xyz_cam[1][0] * ro + xyz_cam[1][1] * go + xyz_cam[1][2] * bo; float z = xyz_cam[2][0] * ro + xyz_cam[2][1] * go + xyz_cam[2][2] * bo; - x = (x < 65535.0 ? ImProcFunctions::cachef[x] / 327.68 : (exp(log(x / MAXVALD) / 3.0 ))); - y = (y < 65535.0 ? ImProcFunctions::cachef[y] / 327.68 : (exp(log(y / MAXVALD) / 3.0 ))); - z = (z < 65535.0 ? ImProcFunctions::cachef[z] / 327.68 : (exp(log(z / MAXVALD) / 3.0 ))); + x = (x < 65535.0 ? Color::cachef[x] / 327.68 : std::cbrt(x / MAXVALD)); + y = (y < 65535.0 ? Color::cachef[y] / 327.68 : std::cbrt(y / MAXVALD)); + z = (z < 65535.0 ? Color::cachef[z] / 327.68 : std::cbrt(z / MAXVALD)); // convert back to rgb double fz = fy - y + z; double fx = fy + x - y; @@ -4329,11 +4365,12 @@ void RawImageSource::hlRecovery (std::string method, float* red, float* green, f void RawImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) { - +BENCHFUN histcompr = 3; histogram(65536 >> histcompr); histogram.clear(); + const float refwb[3] = {static_cast(refwb_red),static_cast(refwb_green),static_cast(refwb_blue)}; #ifdef _OPENMP #pragma omp parallel @@ -4351,27 +4388,15 @@ void RawImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) if (ri->getSensorType() == ST_BAYER) { for (int j = start; j < end; j++) { - if (ri->ISGREEN(i, j)) { - tmphistogram[CLIP((int)(refwb_green * rawData[i][j])) >> histcompr] += 4; - } else if (ri->ISRED(i, j)) { - tmphistogram[CLIP((int)(refwb_red * rawData[i][j])) >> histcompr] += 4; - } else if (ri->ISBLUE(i, j)) { - tmphistogram[CLIP((int)(refwb_blue * rawData[i][j])) >> histcompr] += 4; - } + tmphistogram[(int)(refwb[ri->FC(i,j)] * rawData[i][j]) >> histcompr] += 4; } } else if (ri->getSensorType() == ST_FUJI_XTRANS) { for (int j = start; j < end; j++) { - if (ri->ISXTRANSGREEN(i, j)) { - tmphistogram[CLIP((int)(refwb_green * rawData[i][j])) >> histcompr] += 4; - } else if (ri->ISXTRANSRED(i, j)) { - tmphistogram[CLIP((int)(refwb_red * rawData[i][j])) >> histcompr] += 4; - } else if (ri->ISXTRANSBLUE(i, j)) { - tmphistogram[CLIP((int)(refwb_blue * rawData[i][j])) >> histcompr] += 4; - } + tmphistogram[(int)(refwb[ri->XTRANSFC(i,j)] * rawData[i][j]) >> histcompr] += 4; } } else if (ri->get_colors() == 1) { for (int j = start; j < end; j++) { - tmphistogram[CLIP((int)(refwb_red * rawData[i][j])) >> histcompr]++; + tmphistogram[(int)(refwb_red * rawData[i][j]) >> histcompr]++; } } else { for (int j = start; j < end; j++) { @@ -4386,9 +4411,7 @@ void RawImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) #pragma omp critical #endif { - for(int i = 0; i < (65536 >> histcompr); i++) { - histogram[i] += tmphistogram[i]; - } + histogram += tmphistogram; } } } @@ -4396,7 +4419,7 @@ void RawImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) // Histogram MUST be 256 in size; gamma is applied, blackpoint and gain also void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw) { - +BENCHFUN histRedRaw.clear(); histGreenRaw.clear(); histBlueRaw.clear(); @@ -4406,6 +4429,22 @@ void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LU 65535.0f / ri->get_white(3) }; + const bool fourColours = ri->getSensorType() == ST_BAYER && ((mult[1] != mult[3] || cblacksom[1] != cblacksom[3]) || FC(0,0) == 3 || FC(0,1) == 3 || FC(1,0) == 3 || FC(1,1) == 3); + + LUTu hist[4]; + hist[0](65536); + hist[0].clear(); + if (ri->get_colors() > 1) { + hist[1](65536); + hist[1].clear(); + hist[2](65536); + hist[2].clear(); + } + if (fourColours) { + hist[3](65536); + hist[3].clear(); + } + #ifdef _OPENMP int numThreads; // reduce the number of threads under certain conditions to avoid overhaed of too many critical regions @@ -4419,13 +4458,16 @@ void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LU LUTu tmphist[4]; tmphist[0](65536); tmphist[0].clear(); - tmphist[1](65536); - tmphist[1].clear(); - tmphist[2](65536); - tmphist[2].clear(); - tmphist[3](65536); - tmphist[3].clear(); - + if (ri->get_colors() > 1) { + tmphist[1](65536); + tmphist[1].clear(); + tmphist[2](65536); + tmphist[2].clear(); + if (fourColours) { + tmphist[3](65536); + tmphist[3].clear(); + } + } #ifdef _OPENMP #pragma omp for nowait #endif @@ -4437,9 +4479,9 @@ void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LU if (ri->getSensorType() == ST_BAYER) { int j; int c1 = FC(i, start); - c1 = ( c1 == 1 && !(i & 1) ) ? 3 : c1; + c1 = ( fourColours && c1 == 1 && !(i & 1) ) ? 3 : c1; int c2 = FC(i, start + 1); - c2 = ( c2 == 1 && !(i & 1) ) ? 3 : c2; + c2 = ( fourColours && c2 == 1 && !(i & 1) ) ? 3 : c2; for (j = start; j < end - 1; j += 2) { tmphist[c1][(int)ri->data[i][j]]++; @@ -4451,9 +4493,7 @@ void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LU } } else if (ri->get_colors() == 1) { for (int j = start; j < end; j++) { - for (int c = 0; c < 3; c++) { - tmphist[c][(int)ri->data[i][j]]++; - } + tmphist[0][(int)ri->data[i][j]]++; } } else if(ri->getSensorType() == ST_FUJI_XTRANS) { for (int j = start; j < end - 1; j += 2) { @@ -4473,20 +4513,32 @@ void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LU #pragma omp critical #endif { - for(int i = 0; i < 65536; i++) { - int idx; - idx = CLIP((int)Color::gamma(mult[0] * (i - (cblacksom[0]/*+black_lev[0]*/)))); - histRedRaw[idx >> 8] += tmphist[0][i]; - idx = CLIP((int)Color::gamma(mult[1] * (i - (cblacksom[1]/*+black_lev[1]*/)))); - histGreenRaw[idx >> 8] += tmphist[1][i]; - idx = CLIP((int)Color::gamma(mult[3] * (i - (cblacksom[3]/*+black_lev[3]*/)))); - histGreenRaw[idx >> 8] += tmphist[3][i]; - idx = CLIP((int)Color::gamma(mult[2] * (i - (cblacksom[2]/*+black_lev[2]*/)))); - histBlueRaw[idx >> 8] += tmphist[2][i]; + hist[0] += tmphist[0]; + if (ri->get_colors() > 1) { + hist[1] += tmphist[1]; + hist[2] += tmphist[2]; + if (fourColours) { + hist[3] += tmphist[3]; + } } } // end of critical region } // end of parallel region + for(int i = 0; i < 65536; i++) { + int idx; + idx = CLIP((int)Color::gamma(mult[0] * (i - (cblacksom[0]/*+black_lev[0]*/)))); + histRedRaw[idx >> 8] += hist[0][i]; + if (ri->get_colors() > 1) { + idx = CLIP((int)Color::gamma(mult[1] * (i - (cblacksom[1]/*+black_lev[1]*/)))); + histGreenRaw[idx >> 8] += hist[1][i]; + if (fourColours) { + idx = CLIP((int)Color::gamma(mult[3] * (i - (cblacksom[3]/*+black_lev[3]*/)))); + histGreenRaw[idx >> 8] += hist[3][i]; + } + idx = CLIP((int)Color::gamma(mult[2] * (i - (cblacksom[2]/*+black_lev[2]*/)))); + histBlueRaw[idx >> 8] += hist[2][i]; + } + } if (ri->getSensorType() == ST_BAYER) // since there are twice as many greens, correct for it for (int i = 0; i < 256; i++) { @@ -4496,7 +4548,10 @@ void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LU for (int i = 0; i < 256; i++) { histGreenRaw[i] = (histGreenRaw[i] * 2) / 5; } - + else if(ri->get_colors() == 1) { // monochrome sensor => set all histograms equal + histGreenRaw += histRedRaw; + histBlueRaw += histRedRaw; + } } @@ -4517,7 +4572,8 @@ void RawImageSource::getRowStartEnd (int x, int &start, int &end) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) { - + BENCHFUN + constexpr double clipHigh = 64000.0; if (ri->get_colors() == 1) { rm = gm = bm = 1; return; @@ -4554,7 +4610,7 @@ void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) double dg = CLIP(initialGain * (rawData[i][3 * j + 1])); double db = CLIP(initialGain * (rawData[i][3 * j + 2])); - if (dr > 64000. || dg > 64000. || db > 64000.) { + if (dr > clipHigh || dg > clipHigh || db > clipHigh) { continue; } @@ -4566,7 +4622,7 @@ void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) int c = FC( i, j); double d = CLIP(initialGain * (rawData[i][j])); - if (d > 64000.) { + if (d > clipHigh) { continue; } @@ -4587,42 +4643,46 @@ void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) } else { if (ri->getSensorType() != ST_BAYER) { if(ri->getSensorType() == ST_FUJI_XTRANS) { - for (int i = 32; i < H - 32; i++) - for (int j = 32; j < W - 32; j++) { - // each loop read 1 rgb triplet value - if(ri->ISXTRANSRED(i, j)) { - float dr = CLIP(initialGain * (rawData[i][j])); + const double compval = clipHigh / initialGain; +#ifdef _OPENMP + #pragma omp parallel +#endif + { + double avg_c[3] = {0.0}; + int cn[3] = {0}; +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) nowait +#endif + for (int i = 32; i < H - 32; i++) { + for (int j = 32; j < W - 32; j++) { + // each loop read 1 rgb triplet value + double d = rawData[i][j]; - if (dr > 64000.f) { + if (d > compval) { continue; } - avg_r += dr; - rn ++; - } - - if(ri->ISXTRANSGREEN(i, j)) { - float dg = CLIP(initialGain * (rawData[i][j])); - - if (dg > 64000.f) { - continue; - } - - avg_g += dg; - gn ++; - } - - if(ri->ISXTRANSBLUE(i, j)) { - float db = CLIP(initialGain * (rawData[i][j])); - - if (db > 64000.f) { - continue; - } - - avg_b += db; - bn ++; + int c = ri->XTRANSFC(i, j); + avg_c[c] += d; + cn[c]++; } } + +#ifdef _OPENMP + #pragma omp critical +#endif + { + avg_r += avg_c[0]; + avg_g += avg_c[1]; + avg_b += avg_c[2]; + rn += cn[0]; + gn += cn[1]; + bn += cn[2]; + } + } + avg_r *= initialGain; + avg_g *= initialGain; + avg_b *= initialGain; } else { for (int i = 32; i < H - 32; i++) for (int j = 32; j < W - 32; j++) { @@ -4632,7 +4692,7 @@ void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) double dg = CLIP(initialGain * (rawData[i][3 * j + 1])); double db = CLIP(initialGain * (rawData[i][3 * j + 2])); - if (dr > 64000. || dg > 64000. || db > 64000.) { + if (dr > clipHigh || dg > clipHigh || db > clipHigh) { continue; } @@ -4667,36 +4727,45 @@ void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) } } - double d[2][2]; + const double compval = clipHigh / initialGain; +#ifdef _OPENMP + #pragma omp parallel for reduction(+:avg_r,avg_g,avg_b,rn,gn,bn) schedule(dynamic,8) +#endif for (int i = 32; i < H - 32; i += 2) for (int j = 32; j < W - 32; j += 2) { //average each Bayer quartet component individually if non-clipped - d[0][0] = CLIP(initialGain * (rawData[i][j] )); - d[0][1] = CLIP(initialGain * (rawData[i][j + 1] )); - d[1][0] = CLIP(initialGain * (rawData[i + 1][j] )); - d[1][1] = CLIP(initialGain * (rawData[i + 1][j + 1])); + double d[2][2]; + d[0][0] = rawData[i][j]; + d[0][1] = rawData[i][j + 1]; + d[1][0] = rawData[i + 1][j]; + d[1][1] = rawData[i + 1][j + 1]; - if (d[ey][ex] <= 64000.) { + if (d[ey][ex] <= compval) { avg_r += d[ey][ex]; rn++; } - if (d[1 - ey][ex] <= 64000.) { + if (d[1 - ey][ex] <= compval) { avg_g += d[1 - ey][ex]; gn++; } - if (d[ey][1 - ex] <= 64000.) { + if (d[ey][1 - ex] <= compval) { avg_g += d[ey][1 - ex]; gn++; } - if (d[1 - ey][1 - ex] <= 64000.) { + if (d[1 - ey][1 - ex] <= compval) { avg_b += d[1 - ey][1 - ex]; bn++; } } + + avg_r *= initialGain; + avg_g *= initialGain; + avg_b *= initialGain; + } } diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 0f4ca2402..222735432 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -95,7 +95,7 @@ protected: void hphd_vertical (float** hpmap, int col_from, int col_to); void hphd_horizontal (float** hpmap, int row_from, int row_to); void hphd_green (float** hpmap); - void processFalseColorCorrectionThread (Imagefloat* im, int row_from, int row_to); + void processFalseColorCorrectionThread (Imagefloat* im, array2D &rbconv_Y, array2D &rbconv_I, array2D &rbconv_Q, array2D &rbout_I, array2D &rbout_Q, const int row_from, const int row_to); void hlRecovery (std::string method, float* red, float* green, float* blue, int i, int sx1, int width, int skip, const RAWParams &raw, float* hlmax); int defTransform (int tran); void transformRect (PreviewProps pp, int tran, int &sx1, int &sy1, int &width, int &height, int &fw); @@ -206,17 +206,17 @@ public: protected: typedef unsigned short ushort; - void processFalseColorCorrection (Imagefloat* i, int steps); - inline void convert_row_to_YIQ (float* r, float* g, float* b, float* Y, float* I, float* Q, int W); - inline void convert_row_to_RGB (float* r, float* g, float* b, float* Y, float* I, float* Q, int W); + void processFalseColorCorrection (Imagefloat* i, const int steps); + inline void convert_row_to_YIQ (const float* const r, const float* const g, const float* const b, float* Y, float* I, float* Q, const int W); + inline void convert_row_to_RGB (float* r, float* g, float* b, const float* const Y, const float* const I, const float* const Q, const int W); + inline void convert_to_RGB (float &r, float &g, float &b, const float Y, const float I, const float Q); inline void convert_to_cielab_row (float* ar, float* ag, float* ab, float* oL, float* oa, float* ob); inline void interpolate_row_g (float* agh, float* agv, int i); inline void interpolate_row_rb (float* ar, float* ab, float* pg, float* cg, float* ng, int i); inline void interpolate_row_rb_mul_pp (float* ar, float* ab, float* pg, float* cg, float* ng, int i, float r_mul, float g_mul, float b_mul, int x1, int width, int skip); - int LinEqSolve( int nDim, double* pfMatr, double* pfVect, double* pfSolution);//Emil's CA auto correction - void CA_correct_RT (double cared, double cablue); + void CA_correct_RT (const double cared, const double cablue, const double caautostrength); void ddct8x8s(int isgn, float a[8][8]); void processRawWhitepoint (float expos, float preser); // exposure before interpolation @@ -259,7 +259,7 @@ protected: void dcb_color_full(float (*image)[4], int x0, int y0, float (*chroma)[2]); void cielab (const float (*rgb)[3], float* l, float* a, float *b, const int width, const int height, const int labWidth, const float xyz_cam[3][3]); void xtransborder_interpolate (int border); - void xtrans_interpolate (int passes, bool useCieLab); + void xtrans_interpolate (const int passes, const bool useCieLab); void fast_xtrans_interpolate (); void hflip (Imagefloat* im); void vflip (Imagefloat* im); diff --git a/rtengine/rawimagesource_i.h b/rtengine/rawimagesource_i.h index a3cd28253..f5685b0ef 100644 --- a/rtengine/rawimagesource_i.h +++ b/rtengine/rawimagesource_i.h @@ -22,29 +22,42 @@ #include "rawimagesource.h" -#include "curves.h" - namespace rtengine { -inline void RawImageSource::convert_row_to_YIQ (float* r, float* g, float* b, float* Y, float* I, float* Q, int W) +inline void RawImageSource::convert_row_to_YIQ (const float* const r, const float* const g, const float* const b, float* Y, float* I, float* Q, const int W) { +#ifdef _OPENMP + #pragma omp simd +#endif + for (int j = 0; j < W; j++) { - Y[j] = .299 * r[j] + .587 * g[j] + .114 * b[j]; - I[j] = .596 * r[j] - .275 * g[j] - .321 * b[j]; - Q[j] = .212 * r[j] - .523 * g[j] + .311 * b[j]; + Y[j] = .299f * r[j] + .587f * g[j] + .114f * b[j]; + I[j] = .596f * r[j] - .275f * g[j] - .321f * b[j]; + Q[j] = .212f * r[j] - .523f * g[j] + .311f * b[j]; } } -inline void RawImageSource::convert_row_to_RGB (float* r, float* g, float* b, float* Y, float* I, float* Q, int W) +inline void RawImageSource::convert_row_to_RGB (float* r, float* g, float* b, const float* const Y, const float* const I, const float* const Q, const int W) { +#ifdef _OPENMP + #pragma omp simd +#endif + for (int j = 1; j < W - 1; j++) { - r[j] = Y[j] + 0.956 * I[j] + 0.621 * Q[j]; - g[j] = Y[j] - 0.272 * I[j] - 0.647 * Q[j]; - b[j] = Y[j] - 1.105 * I[j] + 1.702 * Q[j]; + r[j] = Y[j] + 0.956f * I[j] + 0.621f * Q[j]; + g[j] = Y[j] - 0.272f * I[j] - 0.647f * Q[j]; + b[j] = Y[j] - 1.105f * I[j] + 1.702f * Q[j]; } } +inline void RawImageSource::convert_to_RGB (float &r, float &g, float &b, const float Y, const float I, const float Q) +{ + r = Y + 0.956f * I + 0.621f * Q; + g = Y - 0.272f * I - 0.647f * Q; + b = Y - 1.105f * I + 1.702f * Q; +} + inline void RawImageSource::convert_to_cielab_row (float* ar, float* ag, float* ab, float* oL, float* oa, float* ob) { diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 240c871b5..5175836e4 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -119,8 +119,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = { ALLNORAW, // EvDPDNLuma, ALLNORAW, // EvDPDNChroma, ALLNORAW, // EvDPDNGamma, - DIRPYREQUALIZER, // EvDirPyrEqualizer, - DIRPYREQUALIZER, // EvDirPyrEqlEnabled, + ALLNORAW, // EvDirPyrEqualizer, + ALLNORAW, // EvDirPyrEqlEnabled, LUMINANCECURVE, // EvLSaturation, LUMINANCECURVE, // EvLaCurve, LUMINANCECURVE, // EvLbCurve, @@ -141,7 +141,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, // EvCBSatLimiter, LUMINANCECURVE, // EvCBSatLimit, DEMOSAIC, // EvDemosaicDCBIter - DEMOSAIC, // EvDemosaicFalseColorIter + ALLNORAW, // EvDemosaicFalseColorIter DEMOSAIC, // EvDemosaicDCBEnhanced DARKFRAME, // EvPreProcessCARed DARKFRAME, // EvPreProcessCABlue @@ -200,7 +200,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, // EvLLCCurve LUMINANCECURVE, // EvLLCredsk ALLNORAW, // EvDPDNLdetail - LUMINANCECURVE, // EvCATEnabled + ALLNORAW, // EvCATEnabled LUMINANCECURVE, // EvCATDegree LUMINANCECURVE, // EvCATMethodsur LUMINANCECURVE, // EvCATAdapscen @@ -275,12 +275,12 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, // EvLCLCurve LUMINANCECURVE, // EvLLHCurve LUMINANCECURVE, // EvLHHCurve - DIRPYREQUALIZER, // EvDirPyrEqualizerThreshold + ALLNORAW, // EvDirPyrEqualizerThreshold ALLNORAW, // EvDPDNenhance RGBCURVE, // EvBWMethodalg - DIRPYREQUALIZER, // EvDirPyrEqualizerSkin - DIRPYREQUALIZER, // EvDirPyrEqlgamutlab - DIRPYREQUALIZER, // EvDirPyrEqualizerHueskin + ALLNORAW, // EvDirPyrEqualizerSkin + ALLNORAW, // EvDirPyrEqlgamutlab + ALLNORAW, // EvDirPyrEqualizerHueskin ALLNORAW, // EvDPDNmedian ALLNORAW, // EvDPDNmedmet RGBCURVE, // EvColorToningEnabled @@ -466,6 +466,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = { RETINEX, // EvmapMethod DEMOSAIC, // EvRetinexmapcurve DEMOSAIC, // EvviewMethod + ALLNORAW, // EvcbdlMethod RETINEX, // EvRetinexgaintransmission RETINEX //EvLskal diff --git a/rtengine/rt_math.h b/rtengine/rt_math.h index 44c29fd97..898f1397c 100644 --- a/rtengine/rt_math.h +++ b/rtengine/rt_math.h @@ -80,7 +80,8 @@ inline const _Tp& max(const _Tp& a, const _Tp& b, const _Tp& c, const _Tp& d) } template -inline const _Tp intp(const _Tp a, const _Tp b, const _Tp c) { +inline const _Tp intp(const _Tp a, const _Tp b, const _Tp c) +{ // calculate a * b + (1 - a) * c // following is valid: // intp(a, b+x, c+x) = intp(a, b, c) + x @@ -88,5 +89,23 @@ inline const _Tp intp(const _Tp a, const _Tp b, const _Tp c) { return a * (b-c) + c; } +template +T norm1(const T& x, const T& y) +{ + return std::abs(x) + std::abs(y); +} + +template +T norm2(const T& x, const T& y) +{ + return std::sqrt(x * x + y * y); +} + +template< typename T > +T norminf(const T& x, const T& y) +{ + return std::max(std::abs(x), std::abs(y)); +} + } #endif diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 1f81012ad..e20efdbdd 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -33,8 +33,6 @@ #include "stdimagesource.h" #include #include -#include "safekeyfile.h" -#include "safegtk.h" #include "rawimage.h" #include "jpeg.h" #include "../rtgui/ppversion.h" @@ -327,7 +325,7 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati // locate first green location in the first row if(ri->getSensorType() == ST_BAYER) - while (!FISGREEN(filter, 1, firstgreen)) { + while (!FISGREEN(filter, 1, firstgreen) && firstgreen < 3) { firstgreen++; } @@ -720,30 +718,6 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati #undef FISGREEN #undef FISBLUE - -unsigned short *Thumbnail::igammatab = 0; -unsigned char *Thumbnail::gammatab = 0; - -void Thumbnail::initGamma () -{ - igammatab = new unsigned short[256]; - gammatab = new unsigned char[65536]; - - for (int i = 0; i < 256; i++) { - igammatab[i] = (unsigned short)(255.0 * pow((double)i / 255.0, Color::sRGBGamma)); - } - - for (int i = 0; i < 65536; i++) { - gammatab[i] = (unsigned char)(255.0 * pow((double)i / 65535.0, 1.f / Color::sRGBGamma)); - } -} - -void Thumbnail::cleanupGamma () -{ - delete [] igammatab; - delete [] gammatab; -} - void Thumbnail::init () { @@ -1456,9 +1430,9 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) image->convertTo(image->r(i, j), r_); image->convertTo(image->g(i, j), g_); image->convertTo(image->b(i, j), b_); - int r = gammatab[min(r_, static_cast(max_)) * scaleForSave >> 13]; - int g = gammatab[min(g_, static_cast(max_)) * scaleForSave >> 13]; - int b = gammatab[min(b_, static_cast(max_)) * scaleForSave >> 13]; + int r = Color::gammatabThumb[min(r_, static_cast(max_)) * scaleForSave >> 13]; + int g = Color::gammatabThumb[min(g_, static_cast(max_)) * scaleForSave >> 13]; + int b = Color::gammatabThumb[min(b_, static_cast(max_)) * scaleForSave >> 13]; tmpdata[ix++] = (r * 19595 + g * 38469 + b * 7472) >> 16; } } else if (thumbImg->getType() == sImage16) { @@ -1470,9 +1444,9 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) image->convertTo(image->r(i, j), r_); image->convertTo(image->g(i, j), g_); image->convertTo(image->b(i, j), b_); - int r = gammatab[min(r_, static_cast(max_)) * scaleForSave >> 13]; - int g = gammatab[min(g_, static_cast(max_)) * scaleForSave >> 13]; - int b = gammatab[min(b_, static_cast(max_)) * scaleForSave >> 13]; + int r = Color::gammatabThumb[min(r_, static_cast(max_)) * scaleForSave >> 13]; + int g = Color::gammatabThumb[min(g_, static_cast(max_)) * scaleForSave >> 13]; + int b = Color::gammatabThumb[min(b_, static_cast(max_)) * scaleForSave >> 13]; tmpdata[ix++] = (r * 19595 + g * 38469 + b * 7472) >> 16; } } else if (thumbImg->getType() == sImagefloat) { @@ -1484,9 +1458,9 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) image->convertTo(image->r(i, j), r_); image->convertTo(image->g(i, j), g_); image->convertTo(image->b(i, j), b_); - int r = gammatab[min(r_, static_cast(max_)) * scaleForSave >> 13]; - int g = gammatab[min(g_, static_cast(max_)) * scaleForSave >> 13]; - int b = gammatab[min(b_, static_cast(max_)) * scaleForSave >> 13]; + int r = Color::gammatabThumb[min(r_, static_cast(max_)) * scaleForSave >> 13]; + int g = Color::gammatabThumb[min(g_, static_cast(max_)) * scaleForSave >> 13]; + int b = Color::gammatabThumb[min(b_, static_cast(max_)) * scaleForSave >> 13]; tmpdata[ix++] = (r * 19595 + g * 38469 + b * 7472) >> 16; } } @@ -1653,7 +1627,7 @@ bool Thumbnail::writeImage (const Glib::ustring& fname, int format) Glib::ustring fullFName = fname + ".rtti"; - FILE* f = safe_g_fopen (fullFName, "wb"); + FILE* f = g_fopen (fullFName.c_str (), "wb"); if (!f) { return false; @@ -1692,11 +1666,11 @@ bool Thumbnail::readImage (const Glib::ustring& fname) Glib::ustring fullFName = fname + ".rtti"; - if (!safe_file_test (fullFName, Glib::FILE_TEST_EXISTS)) { + if (!Glib::file_test (fullFName, Glib::FILE_TEST_EXISTS)) { return false; } - FILE* f = safe_g_fopen (fullFName, "rb"); + FILE* f = g_fopen (fullFName.c_str (), "rb"); if (!f) { return false; @@ -1738,12 +1712,14 @@ bool Thumbnail::readImage (const Glib::ustring& fname) bool Thumbnail::readData (const Glib::ustring& fname) { setlocale(LC_NUMERIC, "C"); // to set decimal point to "." - SafeKeyFile keyFile; + Glib::KeyFile keyFile; try { MyMutex::MyLock thmbLock(thumbMutex); - if (!keyFile.load_from_file (fname)) { + try { + keyFile.load_from_file (fname); + } catch (Glib::Error&) { return false; } @@ -1831,16 +1807,38 @@ bool Thumbnail::readData (const Glib::ustring& fname) bool Thumbnail::writeData (const Glib::ustring& fname) { - - SafeKeyFile keyFile; - MyMutex::MyLock thmbLock(thumbMutex); + Glib::ustring keyData; + try { - if( safe_file_test(fname, Glib::FILE_TEST_EXISTS) ) { + + Glib::KeyFile keyFile; + + try { keyFile.load_from_file (fname); - } - } catch (Glib::Error &err) { + } catch (Glib::Error&) {} + + keyFile.set_double ("LiveThumbData", "CamWBRed", camwbRed); + keyFile.set_double ("LiveThumbData", "CamWBGreen", camwbGreen); + keyFile.set_double ("LiveThumbData", "CamWBBlue", camwbBlue); + keyFile.set_double ("LiveThumbData", "RedAWBMul", redAWBMul); + keyFile.set_double ("LiveThumbData", "GreenAWBMul", greenAWBMul); + keyFile.set_double ("LiveThumbData", "BlueAWBMul", blueAWBMul); + keyFile.set_integer ("LiveThumbData", "AEHistCompression", aeHistCompression); + keyFile.set_double ("LiveThumbData", "RedMultiplier", redMultiplier); + keyFile.set_double ("LiveThumbData", "GreenMultiplier", greenMultiplier); + keyFile.set_double ("LiveThumbData", "BlueMultiplier", blueMultiplier); + keyFile.set_double ("LiveThumbData", "Scale", scale); + keyFile.set_double ("LiveThumbData", "DefaultGain", defGain); + keyFile.set_integer ("LiveThumbData", "ScaleForSave", scaleForSave); + keyFile.set_boolean ("LiveThumbData", "GammaCorrected", gammaCorrected); + Glib::ArrayHandle cm ((double*)colorMatrix, 9, Glib::OWNERSHIP_NONE); + keyFile.set_double_list ("LiveThumbData", "ColorMatrix", cm); + + keyData = keyFile.to_data (); + + } catch (Glib::Error& err) { if (options.rtSettings.verbose) { printf("Thumbnail::writeData / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str()); } @@ -1850,24 +1848,11 @@ bool Thumbnail::writeData (const Glib::ustring& fname) } } - keyFile.set_double ("LiveThumbData", "CamWBRed", camwbRed); - keyFile.set_double ("LiveThumbData", "CamWBGreen", camwbGreen); - keyFile.set_double ("LiveThumbData", "CamWBBlue", camwbBlue); - keyFile.set_double ("LiveThumbData", "RedAWBMul", redAWBMul); - keyFile.set_double ("LiveThumbData", "GreenAWBMul", greenAWBMul); - keyFile.set_double ("LiveThumbData", "BlueAWBMul", blueAWBMul); - keyFile.set_integer ("LiveThumbData", "AEHistCompression", aeHistCompression); - keyFile.set_double ("LiveThumbData", "RedMultiplier", redMultiplier); - keyFile.set_double ("LiveThumbData", "GreenMultiplier", greenMultiplier); - keyFile.set_double ("LiveThumbData", "BlueMultiplier", blueMultiplier); - keyFile.set_double ("LiveThumbData", "Scale", scale); - keyFile.set_double ("LiveThumbData", "DefaultGain", defGain); - keyFile.set_integer ("LiveThumbData", "ScaleForSave", scaleForSave); - keyFile.set_boolean ("LiveThumbData", "GammaCorrected", gammaCorrected); - Glib::ArrayHandle cm ((double*)colorMatrix, 9, Glib::OWNERSHIP_NONE); - keyFile.set_double_list ("LiveThumbData", "ColorMatrix", cm); + if (keyData.empty ()) { + return false; + } - FILE *f = safe_g_fopen (fname, "wt"); + FILE *f = g_fopen (fname.c_str (), "wt"); if (!f) { if (options.rtSettings.verbose) { @@ -1876,7 +1861,7 @@ bool Thumbnail::writeData (const Glib::ustring& fname) return false; } else { - fprintf (f, "%s", keyFile.to_data().c_str()); + fprintf (f, "%s", keyData.c_str ()); fclose (f); } @@ -1886,7 +1871,7 @@ bool Thumbnail::writeData (const Glib::ustring& fname) bool Thumbnail::readEmbProfile (const Glib::ustring& fname) { - FILE* f = safe_g_fopen (fname, "rb"); + FILE* f = g_fopen (fname.c_str (), "rb"); if (!f) { embProfileData = NULL; @@ -1910,7 +1895,7 @@ bool Thumbnail::writeEmbProfile (const Glib::ustring& fname) { if (embProfileData) { - FILE* f = safe_g_fopen(fname, "wb"); + FILE* f = g_fopen(fname.c_str (), "wb"); if (f) { fwrite (embProfileData, 1, embProfileLength, f); @@ -1925,7 +1910,7 @@ bool Thumbnail::writeEmbProfile (const Glib::ustring& fname) bool Thumbnail::readAEHistogram (const Glib::ustring& fname) { - FILE* f = safe_g_fopen (fname, "rb"); + FILE* f = g_fopen (fname.c_str (), "rb"); if (!f) { aeHistogram(0); @@ -1943,7 +1928,7 @@ bool Thumbnail::writeAEHistogram (const Glib::ustring& fname) { if (aeHistogram) { - FILE* f = safe_g_fopen (fname, "wb"); + FILE* f = g_fopen (fname.c_str (), "wb"); if (f) { fwrite (&aeHistogram[0], 1, (65536 >> aeHistCompression)*sizeof(aeHistogram[0]), f); diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h index dd9d8e9ca..bc367522d 100644 --- a/rtengine/rtthumbnail.h +++ b/rtengine/rtthumbnail.h @@ -42,9 +42,6 @@ class Thumbnail void transformPixel (int x, int y, int tran, int& tx, int& ty); - static unsigned short *igammatab; - static unsigned char *gammatab; - ImageIO* thumbImg; double camwbRed; double camwbGreen; @@ -72,8 +69,6 @@ public: ~Thumbnail (); Thumbnail (); - static void initGamma (); - static void cleanupGamma (); void init (); IImage8* processImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, std::string camName, diff --git a/rtengine/safegtk.cc b/rtengine/safegtk.cc deleted file mode 100644 index 844afe40a..000000000 --- a/rtengine/safegtk.cc +++ /dev/null @@ -1,437 +0,0 @@ -/* - * This file is part of RawTherapee. - * - * Copyright (c) 2004-2010 Gabor Horvath - * Copyright (c) 2010 Sasha Vasko - * Copyright (c) 2010 Oliver Duis - * - * RawTherapee is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RawTherapee is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - */ - -#include "safegtk.h" -#include "../rtgui/guiutils.h" -#include -#include -#ifdef WIN32 -#include -// for GCC32 -#ifndef _WIN32_IE -#define _WIN32_IE 0x0600 -#endif -#include -#include -#else -#include -#endif -#include "../rtgui/rtimage.h" -#include - - -Glib::RefPtr safe_create_from_file(const Glib::ustring& filename) -{ - Glib::RefPtr res; - Glib::ustring path = RTImage::findIconAbsolutePath(filename); - - if (path.length()) { - try { - res = Gdk::Pixbuf::create_from_file (path); - } catch (Glib::Exception& ex) { - printf ("ERROR: (ustring) File \"%s\" not found.\n", ex.what().c_str()); - } - } - - return res; -} - -Cairo::RefPtr safe_create_from_png(const Glib::ustring& filename) -{ - Cairo::RefPtr res; - Glib::ustring path = RTImage::findIconAbsolutePath(filename); - - if (path.length()) { - // files_test need a std::string which (as stated in its proto) but will only work if - // we use the Glib::ustring filename !? - try { - // create_from_png need a std::string converted from UTF8 with safe_locale_from_utf8 - res = Cairo::ImageSurface::create_from_png (safe_locale_from_utf8(path)); - } catch (...) { - printf("ERROR: (ustring) File \"%s\" not found.\n", path.c_str()); - } - } - - return res; -} - -Glib::RefPtr safe_query_file_info (Glib::RefPtr &file) -{ - Glib::RefPtr info; - - try { - info = file->query_info(); - } catch (...) { } - - return info; -} - -Glib::RefPtr safe_next_file (Glib::RefPtr &dirList) -{ - Glib::RefPtr info; - - bool retry; - Glib::ustring last_error = ""; - - do { - retry = false; - - try { - info = dirList->next_file(); - } catch (Glib::Exception& ex) { - printf ("%s\n", ex.what().c_str()); - // API problem: not possible to differ between error looking at particular entry or - // general error scanning the directory. We do a hack by retrying and see if the - // error changes, if it does we can assume it's about the current filename and we - // should look at the next. More likely if a single file error is that the next - // retry is okay of course. - retry = (ex.what() != last_error); - last_error = ex.what(); - } - } while (retry); - - return info; -} - -# define SAFE_ENUMERATOR_CODE_START(attributes) \ - do{try { if ((dirList = dir->enumerate_children ((attributes)))) \ - for (Glib::RefPtr info = safe_next_file(dirList); info; info = safe_next_file(dirList)) { - -# define SAFE_ENUMERATOR_CODE_END \ - }} catch (Glib::Exception& ex) { printf ("%s\n", ex.what().c_str()); }}while(0) - -/* - * safe_build_file_list can now filter out at the source all files that don't have the extensions specified (if provided) - */ -void safe_build_file_list (Glib::RefPtr &dir, std::vector &names, const Glib::ustring &directory, const std::vector *extensions) -{ - Glib::RefPtr dirList; - - if (dir) { - if (!extensions) { - SAFE_ENUMERATOR_CODE_START("standard::name") - names.push_back (Glib::build_filename (directory, info->get_name())); - SAFE_ENUMERATOR_CODE_END; - } else { - // convert extensions to lowercase in a new vector list - std::vector lcExtensions; - - for (unsigned int i = 0; i < extensions->size(); i++) { - lcExtensions.push_back ((*extensions)[i].lowercase()); - } - - SAFE_ENUMERATOR_CODE_START("standard::name") - // convert the current filename to lowercase in a new ustring - Glib::ustring fname = Glib::ustring(info->get_name()).lowercase(); - - size_t pos = fname.find_last_of('.'); - - if (pos < (fname.length() - 1)) { - // there is an extension to the filename - - Glib::ustring lcFileExt = fname.substr(pos + 1).lowercase(); - - // look out if it has one of the retained extensions - for (size_t i = 0; i < lcExtensions.size(); i++) { - if (lcFileExt == lcExtensions[i]) { - names.push_back (Glib::build_filename (directory, info->get_name())); - break; - } - } - } - - SAFE_ENUMERATOR_CODE_END; - } - } -} - - -void safe_build_subdir_list (Glib::RefPtr &dir, std::vector &subDirs, bool add_hidden) -{ - Glib::RefPtr dirList; - - if (dir) { - // CD-ROMs with no drive inserted are reported, but do not exist, causing RT to crash - if (!safe_file_test(dir->get_path(), Glib::FILE_TEST_EXISTS)) { - return; - } - - SAFE_ENUMERATOR_CODE_START("standard::name,standard::type,standard::is_hidden") - - if (info->get_file_type() == Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || add_hidden)) { - subDirs.push_back (info->get_name()); - } - - SAFE_ENUMERATOR_CODE_END; - } -} - -/* - * For an unknown reason, Glib::filename_to_utf8 doesn't work on Windows, so we're using - * Glib::filename_to_utf8 for Linux/Apple and Glib::locale_to_utf8 for Windows - */ -Glib::ustring safe_filename_to_utf8 (const std::string& src) -{ - Glib::ustring utf8_str; - -#ifdef WIN32 - - try { - utf8_str = Glib::locale_to_utf8(src); - } catch (const Glib::Error& e) { - utf8_str = Glib::convert_with_fallback(src, "UTF-8", "ISO-8859-1", "?"); - } - -#else - - utf8_str = Glib::filename_to_utf8(src); - -#endif - - return utf8_str; -} - -Glib::ustring safe_locale_to_utf8 (const std::string& src) -{ - Glib::ustring utf8_str; - - try { - utf8_str = Glib::locale_to_utf8(src); - } catch (const Glib::Error& e) { - utf8_str = Glib::convert_with_fallback(src, "UTF-8", "ISO-8859-1", "?"); - } - - return utf8_str; -} - -std::string safe_locale_from_utf8 (const Glib::ustring& utf8_str) -{ - std::string str; - - try { - str = Glib::locale_from_utf8(utf8_str); - } catch (Glib::Error&) {} - - return str; -} - -bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8) -{ - std::string cmd; - bool success = false; - - try { - cmd = Glib::filename_from_utf8(cmd_utf8); - printf ("command line: %s\n", cmd.c_str()); - Glib::spawn_command_line_async (cmd.c_str()); - success = true; - } catch (Glib::Exception& ex) { - printf ("%s\n", ex.what().c_str()); - } - - return success; -} - -bool safe_spawn_command_line_sync (const Glib::ustring& cmd_utf8) -{ - int exitStatus = -1; - - try { - //cmd = Glib::filename_from_utf8(cmd_utf8); - printf ("command line: %s\n", cmd_utf8.c_str()); - - // if it crashes here on windows, make sure you have the GTK runtime files gspawn-win32-helper*.exe files in RT directory - Glib::spawn_command_line_sync (cmd_utf8, NULL, NULL, &exitStatus); - } catch (Glib::Exception& ex) { - printf ("%s\n", ex.what().c_str()); - } - - return (exitStatus == 0); -} - -// Opens a file for binary writing and request exclusive lock (cases were you need "wb" mode plus locking) -// (Important on Windows to prevent Explorer to crash RT when parallel scanning e.g. a currently written image file) -FILE * safe_g_fopen_WriteBinLock(const Glib::ustring& fname) -{ - FILE* f = NULL; - -#ifdef WIN32 - // g_fopen just uses _wfopen internally on Windows, does not lock access and has no options to set this - // so use a native function to work around this problem - wchar_t *wFname = (wchar_t*)g_utf8_to_utf16 (fname.c_str(), -1, NULL, NULL, NULL); - HANDLE hFile = CreateFileW(wFname, GENERIC_READ | GENERIC_WRITE, 0 /* no sharing allowed */, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - g_free(wFname); - - if (hFile == INVALID_HANDLE_VALUE) { - f = NULL; - } else { - f = _fdopen( _open_osfhandle((intptr_t)hFile, 0) , "wb"); - } - -#else - f = safe_g_fopen(fname, "wb"); -#endif - - return f; -} - -// Covers old UNIX ::open, which expects ANSI instead of UTF8 on Windows -int safe_open_ReadOnly(const char *fname) -{ - int fd = -1; - -#ifdef WIN32 - // First convert UTF8 to UTF16, then use Windows function to open - wchar_t *wFname = (wchar_t*)g_utf8_to_utf16 (fname, -1, NULL, NULL, NULL); - HANDLE hFile = CreateFileW(wFname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - g_free(wFname); - - // convert back to old file descriptor format - if (hFile != INVALID_HANDLE_VALUE) { - fd = _open_osfhandle((intptr_t)hFile, 0); - } - -#else - fd = ::open(fname, O_RDONLY); -#endif - - return fd; -} - - -FILE * safe_g_fopen(const Glib::ustring& src, const gchar *mode) -{ - return g_fopen(src.c_str(), mode); -} - -bool safe_file_test (const Glib::ustring& filename, Glib::FileTest test) -{ - return Glib::file_test (filename, test); -} - -int safe_g_remove(const Glib::ustring& filename) -{ - return ::g_remove(filename.c_str()); -} - -int safe_g_rename(const Glib::ustring& oldFilename, const Glib::ustring& newFilename) -{ - return ::g_rename(oldFilename.c_str(), newFilename.c_str()); -} - -int safe_g_mkdir_with_parents(const Glib::ustring& dirName, int mode) -{ - return ::g_mkdir_with_parents(dirName.c_str(), mode); -} - -Glib::ustring safe_get_user_picture_dir() -{ -#ifdef WIN32 - // get_user_special_dir/pictures crashes on some Windows configurations. - // so we use the safe native functions here - WCHAR pathW[MAX_PATH] = {0}; - - if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_MYPICTURES, false)) { - char pathA[MAX_PATH]; - WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); - return Glib::ustring(pathA); - } else { - return Glib::ustring("C:\\"); - } - -#else - - return Glib::get_user_special_dir (G_USER_DIRECTORY_PICTURES); - -#endif -} - -Glib::ustring safe_get_user_home_dir() -{ -#ifdef WIN32 - // get_user_special_dir/pictures crashes on some Windows configurations. - // so we use the safe native functions here - WCHAR pathW[MAX_PATH] = {0}; - - if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_PERSONAL, false)) { - char pathA[MAX_PATH]; - WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); - return Glib::ustring(pathA); - } else { - return Glib::ustring("C:\\"); - } - -#else - - return Glib::get_home_dir(); - -#endif -} - -#ifdef WIN32 -Glib::ustring safe_get_user_profile_dir() -{ - WCHAR pathW[MAX_PATH] = {0}; - - if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_PROFILE, false)) { - char pathA[MAX_PATH]; - WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); - return Glib::ustring(pathA); - } else { - return Glib::ustring("C:\\"); - } -} -#endif - - -Glib::ustring safe_get_user_desktop_dir() -{ -#ifdef WIN32 - // get_user_special_dir/pictures crashes on some Windows configurations. - // so we use the safe native functions here - WCHAR pathW[MAX_PATH] = {0}; - - if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_DESKTOP, false)) { - char pathA[MAX_PATH]; - WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); - return Glib::ustring(pathA); - } else { - return Glib::ustring("C:\\"); - } - -#else - - return Glib::get_user_special_dir (G_USER_DIRECTORY_DESKTOP); - -#endif -} - -#ifdef WIN32 -/* - * Test if the path is a root path based on the content of the string - * - * Warning: this function is a workaround for Windows platform, and not necessarily bullet proof - */ -bool safe_is_shortcut_dir (const Glib::ustring& path) -{ - return PathIsRootA(path.c_str()) || safe_get_user_home_dir() == path || safe_get_user_desktop_dir() == path || safe_get_user_profile_dir() == path; // || safe_get_user_picture_dir() == path; -} -#endif diff --git a/rtengine/safegtk.h b/rtengine/safegtk.h deleted file mode 100644 index 768d55148..000000000 --- a/rtengine/safegtk.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef SAFE_GTK_H_INCLUDED -#define SAFE_GTK_H_INCLUDED - -#include -#include -#include - -Glib::RefPtr safe_create_from_file(const Glib::ustring& filename); -Cairo::RefPtr safe_create_from_png(const Glib::ustring& filename); - -Glib::RefPtr safe_query_file_info (Glib::RefPtr &file); -void safe_build_file_list (Glib::RefPtr &dir, std::vector &names, const Glib::ustring &directory = "", const std::vector *extensions = NULL); -void safe_build_subdir_list (Glib::RefPtr &dir, std::vector &subDirs, bool add_hidden); - -bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8); -bool safe_spawn_command_line_sync (const Glib::ustring& cmd_utf8); - -Glib::ustring safe_filename_to_utf8 (const std::string& src); -Glib::ustring safe_locale_to_utf8 (const std::string& src); // from rtengine -std::string safe_locale_from_utf8 (const Glib::ustring& utf8_str); -std::string safe_filename_from_utf8 (const Glib::ustring& utf8_str); - -FILE * safe_g_fopen(const Glib::ustring& src, const gchar *mode); -FILE * safe_g_fopen_WriteBinLock(const Glib::ustring& fname); -int safe_open_ReadOnly(const char *fname); - -bool safe_file_test (const Glib::ustring& filename, Glib::FileTest test); -int safe_g_remove(const Glib::ustring& filename); -int safe_g_rename(const Glib::ustring& oldFilename, const Glib::ustring& newFilename); -int safe_g_mkdir_with_parents(const Glib::ustring& dirName, int mode); - -Glib::ustring safe_get_user_picture_dir(); -Glib::ustring safe_get_user_home_dir(); -Glib::ustring safe_get_user_desktop_dir(); - -#ifdef WIN32 -Glib::ustring safe_get_user_profile_dir(); -bool safe_is_shortcut_dir (const Glib::ustring& filename); -#endif - -#endif diff --git a/rtengine/safekeyfile.h b/rtengine/safekeyfile.h deleted file mode 100644 index 8a934240e..000000000 --- a/rtengine/safekeyfile.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef SAFE_KEY_FILE_H_INCLUDED -#define SAFE_KEY_FILE_H_INCLUDED - -#include -namespace rtengine -{ - -class SafeKeyFile : public Glib::KeyFile -{ -public : - -#ifdef GLIBMM_EXCEPTIONS_ENABLED -#define SAFE_KEY_FILE_METHOD_CODE(method,method_err) \ - do { try { res = Glib::KeyFile::method; }catch (const Glib::KeyFileError& e) { } ; \ - return res; }while(0) -#else -#define SAFE_KEY_FILE_METHOD_CODE(method,method_err) \ - do { std::auto_ptr error; \ - res = Glib::KeyFile::method_err; \ - if (error.get()){/* TODO */}; \ - return res;} while(0) -#endif //GLIBMM_EXCEPTIONS_ENABLED -#define SAFE_KEY_FILE_METHOD(method,method_err,ret_type) \ - { ret_type res = (ret_type)0; SAFE_KEY_FILE_METHOD_CODE(method,method_err);} - -#define SAFE_KEY_FILE_METHOD_NOINIT(method,method_err,ret_type) \ - { ret_type res; SAFE_KEY_FILE_METHOD_CODE(method,method_err);} - - Glib::ustring to_data() - SAFE_KEY_FILE_METHOD_NOINIT(to_data(), to_data(error), Glib::ustring); - - bool load_from_data(const Glib::ustring& data, Glib::KeyFileFlags flags = Glib::KEY_FILE_NONE) - SAFE_KEY_FILE_METHOD(load_from_data(data, flags), load_from_data(data, flags, error), bool); - - bool load_from_file(const std::string& filename, Glib::KeyFileFlags flags = Glib::KEY_FILE_NONE) - SAFE_KEY_FILE_METHOD(load_from_file(filename, flags), load_from_file(filename, flags, error), bool); - - bool has_key(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD(has_key(group_name, key), has_key(group_name, key, error), bool); - - bool get_boolean(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD(get_boolean(group_name, key), get_boolean(group_name, key, error), bool); - - int get_integer(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD(get_integer(group_name, key), get_integer(group_name, key, error), int); - - - - double get_double(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD(get_double(group_name, key), get_double(group_name, key, error), double); - - typedef std::vector DoubleArrayType; - - DoubleArrayType get_double_list(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD_NOINIT(get_double_list(group_name, key), get_double_list(group_name, key, error), DoubleArrayType); - - typedef std::vector IntArrayType; - - IntArrayType get_integer_list(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD_NOINIT(get_integer_list(group_name, key), get_integer_list(group_name, key, error), IntArrayType); - - Glib::ustring get_string(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD_NOINIT(get_string(group_name, key), get_string(group_name, key, error), Glib::ustring); - /* - double get_double(const Glib::ustring& group_name, const Glib::ustring& key) const { - Glib::ustring temp = get_string( group_name, key); - if(!temp.empty()) { - double tmpdbl; - if(sscanf(temp.c_str(), "%lf", &tmpdbl)) - return tmpdbl; - else - return 0.0; - } - return 0.0; - } - */ - typedef std::vector StringArrayType; - - StringArrayType get_string_list(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD_NOINIT(get_string_list(group_name, key), get_string_list(group_name, key, error), StringArrayType); - /* - typedef std::vector DoubleArrayType; - - DoubleArrayType get_double_list(const Glib::ustring& group_name, const Glib::ustring& key) const { - StringArrayType temp = get_string_list(group_name, key); - DoubleArrayType tempdouble; - unsigned int n = temp.size(); - if(n) { - tempdouble.reserve(n); - for (unsigned int i=0; igetWidth(); + const int H = baseImg->getHeight(); + LabImage labcbdl(W, H); + ipf.rgb2lab(*baseImg, labcbdl, params.icm.working); + ipf.dirpyrequalizer (&labcbdl, 1); + ipf.lab2rgb(labcbdl, *baseImg, params.icm.working); + } + // update blurmap SHMap* shmap = NULL; @@ -983,9 +997,12 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL ); + // directional pyramid wavelet - if((params.colorappearance.enabled && !settings->autocielab) || !params.colorappearance.enabled) { - ipf.dirpyrequalizer (labView, 1); //TODO: this is the luminance tonecurve, not the RGB one + if(params.dirpyrequalizer.cbdlMethod == "aft") { + if((params.colorappearance.enabled && !settings->autocielab) || !params.colorappearance.enabled) { + ipf.dirpyrequalizer (labView, 1); //TODO: this is the luminance tonecurve, not the RGB one + } } int kall = 2; @@ -1165,11 +1182,11 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p useLCMS = false; bool pro = false; Glib::ustring chpro, outProfile; - bool present_space[9] = {false, false, false, false, false, false, false, false, false}; + bool present_space[10] = {false, false, false, false, false, false, false, false, false, false}; std::vector opnames = iccStore->getProfiles (); //test if files are in system - for (int j = 0; j < 9; j++) { + for (int j = 0; j < 10; j++) { // one can modify "option" [Color Management] to adapt the profile's name if they are different for windows, MacOS, Linux ?? // some of them are actually provided by RT, thanks to Jacques Desmis if (j == 0) { @@ -1190,6 +1207,8 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p chpro = options.rtSettings.srgb10; //gamma 1.0 } else if(j == 8) { chpro = options.rtSettings.prophoto10; //gamma 1.0 + } else if(j == 9) { + chpro = options.rtSettings.rec2020; } for (unsigned int i = 0; i < opnames.size(); i++) { @@ -1229,6 +1248,8 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p outProfile = options.rtSettings.srgb10; } else if (params.icm.working == "ProPhoto" && present_space[8] && pro) { outProfile = options.rtSettings.prophoto10; + } else if (params.icm.working == "Rec2020" && present_space[9]) { + outProfile = options.rtSettings.rec2020; } else { // Should not occurs if (settings->verbose) { diff --git a/rtengine/sleefsseavx.c b/rtengine/sleefsseavx.c index 6fed6d3d1..1d15e1e41 100644 --- a/rtengine/sleefsseavx.c +++ b/rtengine/sleefsseavx.c @@ -1388,5 +1388,12 @@ static INLINE vfloat vadivapb (vfloat a, vfloat b) { return a / (a+b); } +static INLINE void vconvertrgbrgbrgbrgb2rrrrggggbbbb (const float * src, vfloat &rv, vfloat &gv, vfloat &bv) { // cool function name, isn't it ? :P + // converts a sequence of 4 float RGB triplets to 3 red, green and blue quadruples + rv = _mm_setr_ps(src[0],src[3],src[6],src[9]); + gv = _mm_setr_ps(src[1],src[4],src[7],src[10]); + bv = _mm_setr_ps(src[2],src[5],src[8],src[11]); +} + #endif // __SSE2__ #endif // SLEEFSSEAVX diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index be442945d..f61d90c08 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -25,9 +25,11 @@ #include #include -#include "../rtgui/cacheimagedata.h" +#include + #include "rtexif.h" -#include "../rtengine/safegtk.h" + +#include "../rtgui/cacheimagedata.h" #include "../rtgui/version.h" #include "../rtgui/ppversion.h" @@ -247,17 +249,10 @@ void TagDirectory::printAll (unsigned int level) const * * @return True if everything went fine, false otherwise */ -bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring &imageFName, const Glib::ustring &profileFName, const Glib::ustring &defaultPParams, const CacheImageData* cfs, const bool flagMode, - rtengine::SafeKeyFile *keyFile, Glib::ustring tagDirName) const +bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring &imageFName, const Glib::ustring &profileFName, const Glib::ustring &defaultPParams, + const CacheImageData* cfs, const bool flagMode, Glib::KeyFile *keyFile, Glib::ustring tagDirName) const { - - rtengine::SafeKeyFile *kf; - - if (!keyFile) { - kf = new rtengine::SafeKeyFile(); - } else { - kf = keyFile; - } + const auto kf = keyFile ? keyFile : new Glib::KeyFile; if (!kf) { return false; @@ -274,7 +269,7 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring if (!keyFile) { // open the file in write mode - f = safe_g_fopen (commFName, "wt"); + f = g_fopen (commFName.c_str (), "wt"); if (f == NULL) { printf("TagDirectory::keyFileDump(\"%s\") >>> Error: unable to open file with write access!\n", commFName.c_str()); @@ -282,21 +277,25 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring return false; } - kf->set_string ("RT General", "CachePath", options.cacheBaseDir); - kf->set_string ("RT General", "AppVersion", VERSION); - kf->set_integer("RT General", "ProcParamsVersion", PPVERSION); - kf->set_string ("RT General", "ImageFileName", imageFName); - kf->set_string ("RT General", "OutputProfileFileName", profileFName); - kf->set_string ("RT General", "DefaultProcParams", defaultPParams); - kf->set_boolean("RT General", "FlaggingMode", flagMode); + try { - kf->set_double ("Common Data", "FNumber", cfs->fnumber); - kf->set_double ("Common Data", "Shutter", cfs->shutter); - kf->set_double ("Common Data", "FocalLength", cfs->focalLen); - kf->set_integer("Common Data", "ISO", cfs->iso); - kf->set_string ("Common Data", "Lens", cfs->lens); - kf->set_string ("Common Data", "Make", cfs->camMake); - kf->set_string ("Common Data", "Model", cfs->camModel); + kf->set_string ("RT General", "CachePath", options.cacheBaseDir); + kf->set_string ("RT General", "AppVersion", VERSION); + kf->set_integer("RT General", "ProcParamsVersion", PPVERSION); + kf->set_string ("RT General", "ImageFileName", imageFName); + kf->set_string ("RT General", "OutputProfileFileName", profileFName); + kf->set_string ("RT General", "DefaultProcParams", defaultPParams); + kf->set_boolean("RT General", "FlaggingMode", flagMode); + + kf->set_double ("Common Data", "FNumber", cfs->fnumber); + kf->set_double ("Common Data", "Shutter", cfs->shutter); + kf->set_double ("Common Data", "FocalLength", cfs->focalLen); + kf->set_integer("Common Data", "ISO", cfs->iso); + kf->set_string ("Common Data", "Lens", cfs->lens); + kf->set_string ("Common Data", "Make", cfs->camMake); + kf->set_string ("Common Data", "Model", cfs->camModel); + + } catch (Glib::KeyFileError&) {} } // recursively iterate over the tag list @@ -308,10 +307,15 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring // Accumulating the TagDirectories to dump later tagDirPaths.push_back( Glib::ustring( tagDirName + "/" + getDumpKey(tags[i]->getID(), tagName) ) ); tagDirList.push_back(tags[i]->getDirectory(j)); - kf->set_string (tagDirName, getDumpKey(tags[i]->getID(), tagName), "$subdir"); + + try { + kf->set_string (tagDirName, getDumpKey(tags[i]->getID(), tagName), "$subdir"); + } catch (Glib::KeyFileError&) {} } else { - kf->set_string (tagDirName, getDumpKey(tags[i]->getID(), tagName), tags[i]->valueToString()); + try { + kf->set_string (tagDirName, getDumpKey(tags[i]->getID(), tagName), tags[i]->valueToString()); + } catch (Glib::KeyFileError&) {} } } @@ -321,7 +325,10 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring } if (!keyFile) { - fprintf (f, "%s", kf->to_data().c_str()); + try { + fprintf (f, "%s", kf->to_data().c_str()); + } catch (Glib::KeyFileError&) {} + fclose (f); delete kf; } diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index d7c13f77a..2d6c800fc 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -29,7 +29,6 @@ #include #include #include "../rtengine/procparams.h" -#include "../rtengine/safekeyfile.h" class CacheImageData; @@ -156,7 +155,7 @@ public: 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, - const CacheImageData* cfs, const bool flagMode, rtengine::SafeKeyFile *keyFile = NULL, Glib::ustring tagDirName = "") const; + const CacheImageData* cfs, const bool flagMode, Glib::KeyFile *keyFile = NULL, Glib::ustring tagDirName = "") const; virtual void sort (); }; diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h index 244c22946..580874e5a 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -4,119 +4,119 @@ // UPDATE THE DEFAULT VALUE IN OPTIONS.CC int babehav[] TOO !!! +enum { + ADDSET_TC_EXPCOMP, + ADDSET_TC_BRIGHTNESS, + ADDSET_TC_BLACKLEVEL, + ADDSET_TC_CONTRAST, + ADDSET_SH_HIGHLIGHTS, + ADDSET_SH_SHADOWS, + ADDSET_SH_LOCALCONTRAST, + ADDSET_LC_BRIGHTNESS, + ADDSET_LC_CONTRAST, + ADDSET_SHARP_AMOUNT, + ADDSET_WB_TEMPERATURE, + ADDSET_WB_GREEN, + ADDSET_ROTATE_DEGREE, + ADDSET_DIST_AMOUNT, + ADDSET_PERSPECTIVE, + ADDSET_CA, + ADDSET_VIGN_AMOUNT, + ADDSET_VIGN_RADIUS, + ADDSET_VIGN_STRENGTH, + ADDSET_VIGN_CENTER, + ADDSET_LC_CHROMATICITY, + ADDSET_TC_SATURATION, + ADDSET_TC_HLCOMPAMOUNT, + ADDSET_TC_HLCOMPTHRESH, + ADDSET_TC_SHCOMP, + ADDSET_DIRPYREQ, + ADDSET_DIRPYRDN_LUMA, + ADDSET_DIRPYRDN_LUMDET, + ADDSET_DIRPYRDN_CHROMA, + ADDSET_DIRPYRDN_CHROMARED, + ADDSET_DIRPYRDN_CHROMABLUE, + ADDSET_DIRPYRDN_GAMMA, + ADDSET_CHMIXER, + ADDSET_PREPROCESS_GREENEQUIL, + ADDSET_PREPROCESS_LINEDENOISE, + ADDSET_RAWCACORR, + ADDSET_RAWEXPOS_LINEAR, + ADDSET_RAWEXPOS_PRESER, + ADDSET_RAWEXPOS_BLACKS, + ADDSET_SHARPENEDGE_AMOUNT, + ADDSET_SHARPENMICRO_AMOUNT, + ADDSET_SHARPENEDGE_PASS, + ADDSET_SHARPENMICRO_UNIFORMITY, + ADDSET_VIBRANCE_PASTELS, + ADDSET_VIBRANCE_SATURATED, + ADDSET_FREE_OUPUT_GAMMA, + ADDSET_FREE_OUTPUT_SLOPE, + ADDSET_CAT_DEGREE, + ADDSET_CAT_ADAPTSCENE, + ADDSET_CAT_ADAPTVIEWING, + ADDSET_CAT_LIGHT, + ADDSET_CAT_CHROMA, + ADDSET_CAT_CONTRAST, + ADDSET_CAT_RSTPRO, + ADDSET_CAT_BRIGHT, + ADDSET_CAT_CONTRAST_Q, + ADDSET_CAT_CHROMA_S, + ADDSET_CAT_CHROMA_M, + ADDSET_CAT_HUE, + ADDSET_CAT_BADPIX, + ADDSET_WB_EQUAL, + ADDSET_GRADIENT_DEGREE, + ADDSET_GRADIENT_FEATHER, + ADDSET_GRADIENT_STRENGTH, + ADDSET_GRADIENT_CENTER, + ADDSET_PCVIGNETTE_STRENGTH, + ADDSET_PCVIGNETTE_FEATHER, + ADDSET_PCVIGNETTE_ROUNDNESS, + ADDSET_BLACKWHITE_HUES, + ADDSET_BLACKWHITE_GAMMA, + ADDSET_DIRPYREQ_THRESHOLD, + ADDSET_DIRPYREQ_SKINPROTECT, + ADDSET_COLORTONING_SPLIT, + ADDSET_COLORTONING_SATTHRESHOLD, + ADDSET_COLORTONING_SATOPACITY, + ADDSET_COLORTONING_BALANCE, + ADDSET_COLORTONING_STRENGTH, + ADDSET_DIRPYRDN_PASSES, + ADDSET_RAWFFCLIPCONTROL, + ADDSET_FILMSIMULATION_STRENGTH, + ADDSET_WA, + ADDSET_WA_SKINPROTECT, + ADDSET_WA_THRR, + ADDSET_WA_THRRH, + ADDSET_WA_THRES, + ADDSET_WA_THRESHOLD, + ADDSET_WA_THRESHOLD2, + ADDSET_WA_CHRO, + ADDSET_WA_CHROMA, + ADDSET_WA_CONTRAST, + ADDSET_WA_RESCON, + ADDSET_WA_RESCONH, + ADDSET_WA_RESCHRO, + ADDSET_WA_SKYPROTECT, + ADDSET_WA_EDGRAD, + ADDSET_WA_EDGVAL, + ADDSET_WA_STRENGTH, + ADDSET_WA_EDGEDETECT, + ADDSET_WA_EDGEDETECTTHR, + ADDSET_WA_EDGEDETECTTHR2, + ADDSET_WA_TMRS, + ADDSET_WA_GAMMA, + ADDSET_RETI_STR, + ADDSET_RETI_NEIGH, + ADDSET_RETI_LIMD, + ADDSET_RETI_GAIN, + ADDSET_RETI_OFFS, + ADDSET_RETI_VART, + ADDSET_RETI_GAM, + ADDSET_RETI_SLO, -#define ADDSET_TC_EXPCOMP 0 -#define ADDSET_TC_BRIGHTNESS 1 -#define ADDSET_TC_BLACKLEVEL 2 -#define ADDSET_TC_CONTRAST 3 -#define ADDSET_SH_HIGHLIGHTS 4 -#define ADDSET_SH_SHADOWS 5 -#define ADDSET_SH_LOCALCONTRAST 6 -#define ADDSET_LC_BRIGHTNESS 7 -#define ADDSET_LC_CONTRAST 8 -#define ADDSET_SHARP_AMOUNT 9 -#define ADDSET_WB_TEMPERATURE 10 -#define ADDSET_WB_GREEN 11 -#define ADDSET_ROTATE_DEGREE 12 -#define ADDSET_DIST_AMOUNT 13 -#define ADDSET_PERSPECTIVE 14 -#define ADDSET_CA 15 -#define ADDSET_VIGN_AMOUNT 16 -#define ADDSET_VIGN_RADIUS 17 -#define ADDSET_VIGN_STRENGTH 18 -#define ADDSET_VIGN_CENTER 19 -#define ADDSET_LC_CHROMATICITY 20 -#define ADDSET_TC_SATURATION 21 -#define ADDSET_TC_HLCOMPAMOUNT 22 -#define ADDSET_TC_HLCOMPTHRESH 23 -#define ADDSET_TC_SHCOMP 24 -#define ADDSET_DIRPYREQ 25 -#define ADDSET_DIRPYRDN_LUMA 26 -#define ADDSET_DIRPYRDN_LUMDET 27 -#define ADDSET_DIRPYRDN_CHROMA 28 -#define ADDSET_DIRPYRDN_CHROMARED 29 -#define ADDSET_DIRPYRDN_CHROMABLUE 30 -#define ADDSET_DIRPYRDN_GAMMA 31 -#define ADDSET_CHMIXER 32 -#define ADDSET_PREPROCESS_GREENEQUIL 33 -#define ADDSET_PREPROCESS_LINEDENOISE 34 -#define ADDSET_RAWCACORR 35 -#define ADDSET_RAWEXPOS_LINEAR 36 -#define ADDSET_RAWEXPOS_PRESER 37 -#define ADDSET_RAWEXPOS_BLACKS 38 -#define ADDSET_SHARPENEDGE_AMOUNT 39 -#define ADDSET_SHARPENMICRO_AMOUNT 40 -#define ADDSET_SHARPENEDGE_PASS 41 -#define ADDSET_SHARPENMICRO_UNIFORMITY 42 -#define ADDSET_VIBRANCE_PASTELS 43 -#define ADDSET_VIBRANCE_SATURATED 44 -#define ADDSET_FREE_OUPUT_GAMMA 45 -#define ADDSET_FREE_OUTPUT_SLOPE 46 -#define ADDSET_CAT_DEGREE 47 -#define ADDSET_CAT_ADAPTSCENE 48 -#define ADDSET_CAT_ADAPTVIEWING 49 -#define ADDSET_CAT_LIGHT 50 -#define ADDSET_CAT_CHROMA 51 -#define ADDSET_CAT_CONTRAST 52 -#define ADDSET_CAT_RSTPRO 53 -#define ADDSET_CAT_BRIGHT 54 -#define ADDSET_CAT_CONTRAST_Q 55 -#define ADDSET_CAT_CHROMA_S 56 -#define ADDSET_CAT_CHROMA_M 57 -#define ADDSET_CAT_HUE 58 -#define ADDSET_CAT_BADPIX 59 -#define ADDSET_WB_EQUAL 60 -#define ADDSET_GRADIENT_DEGREE 61 -#define ADDSET_GRADIENT_FEATHER 62 -#define ADDSET_GRADIENT_STRENGTH 63 -#define ADDSET_GRADIENT_CENTER 64 -#define ADDSET_PCVIGNETTE_STRENGTH 65 -#define ADDSET_PCVIGNETTE_FEATHER 66 -#define ADDSET_PCVIGNETTE_ROUNDNESS 67 -#define ADDSET_BLACKWHITE_HUES 68 -#define ADDSET_BLACKWHITE_GAMMA 69 -#define ADDSET_DIRPYREQ_THRESHOLD 70 -#define ADDSET_DIRPYREQ_SKINPROTECT 71 -#define ADDSET_COLORTONING_SPLIT 72 -#define ADDSET_COLORTONING_SATTHRESHOLD 73 -#define ADDSET_COLORTONING_SATOPACITY 74 -#define ADDSET_COLORTONING_BALANCE 75 -#define ADDSET_COLORTONING_STRENGTH 76 -#define ADDSET_DIRPYRDN_PASSES 77 -#define ADDSET_RAWFFCLIPCONTROL 78 -#define ADDSET_FILMSIMULATION_STRENGTH 79 -#define ADDSET_WA 80 -#define ADDSET_WA_SKINPROTECT 81 -#define ADDSET_WA_THRR 82 -#define ADDSET_WA_THRRH 83 -#define ADDSET_WA_THRES 84 -#define ADDSET_WA_THRESHOLD 85 -#define ADDSET_WA_THRESHOLD2 86 -#define ADDSET_WA_CHRO 87 -#define ADDSET_WA_CHROMA 88 -#define ADDSET_WA_CONTRAST 89 -#define ADDSET_WA_RESCON 90 -#define ADDSET_WA_RESCONH 91 -#define ADDSET_WA_RESCHRO 92 -#define ADDSET_WA_SKYPROTECT 93 -#define ADDSET_WA_EDGRAD 94 -#define ADDSET_WA_EDGVAL 95 -#define ADDSET_WA_STRENGTH 96 -#define ADDSET_WA_EDGEDETECT 97 -#define ADDSET_WA_EDGEDETECTTHR 98 -#define ADDSET_WA_EDGEDETECTTHR2 99 -#define ADDSET_WA_TMRS 100 -#define ADDSET_WA_GAMMA 101 -#define ADDSET_RETI_STR 102 -#define ADDSET_RETI_NEIGH 103 -#define ADDSET_RETI_LIMD 104 -#define ADDSET_RETI_GAIN 105 -#define ADDSET_RETI_OFFS 106 -#define ADDSET_RETI_VART 107 -#define ADDSET_RETI_GAM 108 -#define ADDSET_RETI_SLO 109 - -// When adding items, make sure to update ADDSET_PARAM_NUM -#define ADDSET_PARAM_NUM 110 // THIS IS USED AS A DELIMITER!! + ADDSET_PARAM_NUM // THIS IS USED AS A DELIMITER!! +}; #endif diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc index fd2af2074..7c63fce11 100644 --- a/rtgui/batchqueue.cc +++ b/rtgui/batchqueue.cc @@ -33,7 +33,6 @@ #include "filecatalog.h" #include "batchqueuebuttonset.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" using namespace std; @@ -376,7 +375,7 @@ Glib::ustring BatchQueue::getTempFilenameForParams( const Glib::ustring filename strftime (stringTimestamp, sizeof(stringTimestamp), "_%Y%m%d%H%M%S_", timeinfo); Glib::ustring savedParamPath; savedParamPath = options.rtdir + "/batch/"; - safe_g_mkdir_with_parents (savedParamPath, 0755); + g_mkdir_with_parents (savedParamPath.c_str (), 0755); savedParamPath += Glib::path_get_basename (filename); savedParamPath += stringTimestamp; savedParamPath += paramFileExtension; @@ -385,8 +384,11 @@ Glib::ustring BatchQueue::getTempFilenameForParams( const Glib::ustring filename int cancelItemUI (void* data) { - safe_g_remove( (static_cast(data))->savedParamsFile ); - delete static_cast(data); + const auto bqe = static_cast(data); + + g_remove (bqe->savedParamsFile.c_str ()); + delete bqe; + return 0; } @@ -671,24 +673,31 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) processing->removeButtonSet (); } - if (saveBatchQueue( )) { - safe_g_remove( processedParams ); - // Delete all files in directory \batch when finished, just to be sure to remove zombies + if (saveBatchQueue ()) { + ::g_remove (processedParams.c_str ()); - // Not sure that locking is necessary, but it should be safer - MYREADERLOCK(l, entryRW); + // Delete all files in directory batch when finished, just to be sure to remove zombies + auto isEmpty = false; - if( fd.empty() ) { - MYREADERLOCK_RELEASE(l); + { + MYREADERLOCK(l, entryRW); + isEmpty = fd.empty(); + } - std::vector names; - Glib::ustring batchdir = Glib::build_filename(options.rtdir, "batch"); - Glib::RefPtr dir = Gio::File::create_for_path (batchdir); - safe_build_file_list (dir, names, batchdir); + if (isEmpty) { - for(std::vector::iterator iter = names.begin(); iter != names.end(); iter++ ) { - safe_g_remove( *iter ); - } + const auto batchdir = Glib::build_filename (options.rtdir, "batch"); + + try { + + auto dir = Gio::File::create_for_path (batchdir); + auto enumerator = dir->enumerate_children ("standard::name"); + + while (auto file = enumerator->next_file ()) { + ::g_remove (Glib::build_filename (batchdir, file->get_name ()).c_str ()); + } + + } catch (Glib::Exception&) {} } } @@ -834,8 +843,8 @@ Glib::ustring BatchQueue::autoCompleteFileName (const Glib::ustring& fileName, c Glib::ustring fname; // create directory, if does not exist - if (safe_g_mkdir_with_parents (dstdir, 0755) ) { - return ""; + if (g_mkdir_with_parents (dstdir.c_str (), 0755)) { + return Glib::ustring (); } // In overwrite mode we TRY to delete the old file first. @@ -849,10 +858,10 @@ Glib::ustring BatchQueue::autoCompleteFileName (const Glib::ustring& fileName, c fname = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir, dstfname), tries, format); } - int fileExists = safe_file_test (fname, Glib::FILE_TEST_EXISTS); + int fileExists = Glib::file_test (fname, Glib::FILE_TEST_EXISTS); if (inOverwriteMode && fileExists) { - if (safe_g_remove(fname) == -1) { + if (::g_remove (fname.c_str ()) != 0) { inOverwriteMode = false; // failed to delete- revert to old naming scheme } else { fileExists = false; // deleted now diff --git a/rtgui/batchqueuebuttonset.cc b/rtgui/batchqueuebuttonset.cc index 380c4abe3..1f8bc7ac8 100644 --- a/rtgui/batchqueuebuttonset.cc +++ b/rtgui/batchqueuebuttonset.cc @@ -17,8 +17,9 @@ * along with RawTherapee. If not, see . */ #include "batchqueuebuttonset.h" + #include "multilangmgr.h" -#include "../rtengine/safegtk.h" +#include "rtimage.h" extern Glib::ustring argv0; @@ -32,9 +33,9 @@ BatchQueueButtonSet::BatchQueueButtonSet (BatchQueueEntry* myEntry) { if (!iconsLoaded) { - cancelIcon = safe_create_from_png ("gtk-close.png"); - headIcon = safe_create_from_png ("toleftend.png"); - tailIcon = safe_create_from_png ("torightend.png"); + cancelIcon = RTImage::createFromPng ("gtk-close.png"); + headIcon = RTImage::createFromPng ("toleftend.png"); + tailIcon = RTImage::createFromPng ("torightend.png"); iconsLoaded = true; } diff --git a/rtgui/batchqueueentry.cc b/rtgui/batchqueueentry.cc index 94117252d..0e8b66136 100644 --- a/rtgui/batchqueueentry.cc +++ b/rtgui/batchqueueentry.cc @@ -17,13 +17,14 @@ * along with RawTherapee. If not, see . */ #include "batchqueueentry.h" -#include "thumbbrowserbase.h" #include + #include "guiutils.h" #include "threadutils.h" -#include "../rtengine/safegtk.h" +#include "rtimage.h" #include "multilangmgr.h" +#include "thumbbrowserbase.h" bool BatchQueueEntry::iconsLoaded(false); Glib::RefPtr BatchQueueEntry::savedAsIcon; @@ -46,7 +47,7 @@ BatchQueueEntry::BatchQueueEntry (rtengine::ProcessingJob* pjob, const rtengine: #endif if (!iconsLoaded) { - savedAsIcon = safe_create_from_file ("gtk-save.png"); + savedAsIcon = RTImage::createFromFile ("gtk-save.png"); iconsLoaded = true; } diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index e4400d449..2c7f81729 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -22,7 +22,6 @@ #include "multilangmgr.h" #include "rtwindow.h" #include "soundman.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" struct BQProcessLoaded { @@ -39,7 +38,7 @@ int processLoadedBatchQueueUIThread (void* data) static Glib::ustring makeFolderLabel(Glib::ustring path) { - if (!safe_file_test (path, Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) { return "(" + M("GENERAL_NONE") + ")"; } @@ -115,7 +114,7 @@ BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) outdirFolder->signal_current_folder_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::pathFolderChanged)); outdirFolder->set_tooltip_markup (M("PREFERENCES_OUTDIRFOLDERHINT")); - if (safe_file_test (options.savePathFolder, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (options.savePathFolder, Glib::FILE_TEST_IS_DIR)) { outdirFolder->set_current_folder (options.savePathFolder); } @@ -325,7 +324,7 @@ void BatchQueuePanel::saveOptions () void BatchQueuePanel::pathFolderButtonPressed () { - Gtk::FileChooserDialog fc(M("PREFERENCES_OUTDIRFOLDER"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); + Gtk::FileChooserDialog fc (getToplevelWindow (this), M("PREFERENCES_OUTDIRFOLDER"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); fc.add_button( Gtk::StockID("gtk-ok"), Gtk::RESPONSE_OK); fc.set_filename(options.savePathFolder); @@ -333,8 +332,8 @@ void BatchQueuePanel::pathFolderButtonPressed () int result = fc.run(); if (result == Gtk::RESPONSE_OK) { - if (safe_file_test(fc.get_filename(), Glib::FILE_TEST_IS_DIR)) { - options.savePathFolder = fc.get_filename(); + if (Glib::file_test(fc.get_current_folder(), Glib::FILE_TEST_IS_DIR)) { + options.savePathFolder = fc.get_filename (); outdirFolderButton->set_label(makeFolderLabel(options.savePathFolder)); } } diff --git a/rtgui/bayerpreprocess.cc b/rtgui/bayerpreprocess.cc index cce51cca3..51a0cb62a 100644 --- a/rtgui/bayerpreprocess.cc +++ b/rtgui/bayerpreprocess.cc @@ -18,7 +18,6 @@ */ #include "bayerpreprocess.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include using namespace rtengine; diff --git a/rtgui/bayerrawexposure.cc b/rtgui/bayerrawexposure.cc index ca376eb64..ee9b4fc4d 100644 --- a/rtgui/bayerrawexposure.cc +++ b/rtgui/bayerrawexposure.cc @@ -18,7 +18,6 @@ */ #include "bayerrawexposure.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include using namespace rtengine; diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 4b276a03b..75a6ab75a 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -19,8 +19,6 @@ #include "cacheimagedata.h" #include #include -#include "../rtengine/safekeyfile.h" -#include "../rtengine/safegtk.h" #include "version.h" #include @@ -36,7 +34,8 @@ CacheImageData::CacheImageData () int CacheImageData::load (const Glib::ustring& fname) { setlocale(LC_NUMERIC, "C"); // to set decimal point to "." - rtengine::SafeKeyFile keyFile; + + Glib::KeyFile keyFile; try { if (keyFile.load_from_file (fname)) { @@ -165,10 +164,6 @@ int CacheImageData::load (const Glib::ustring& fname) if (keyFile.has_key ("ExtraRawInfo", "ThumbImageType")) { thumbImgType = keyFile.get_integer ("ExtraRawInfo", "ThumbImageType"); } - - if (keyFile.has_key ("ExtraRawInfo", "ThumbImageOffset")) { - thumbOffset = keyFile.get_integer ("ExtraRawInfo", "ThumbImageOffset"); - } } else { rotate = 0; thumbImgType = 0; @@ -195,21 +190,15 @@ int CacheImageData::load (const Glib::ustring& fname) int CacheImageData::save (const Glib::ustring& fname) { - rtengine::SafeKeyFile keyFile; + Glib::ustring keyData; - if (safe_file_test(fname, Glib::FILE_TEST_EXISTS)) { - try { - keyFile.load_from_file (fname); - } catch (Glib::Error &err) { - if (options.rtSettings.verbose) { - printf("CacheImageData::save / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str()); - } - } catch (...) { - if (options.rtSettings.verbose) { - printf("CacheImageData::save / Unknown exception while trying to save \"%s\"!\n", fname.c_str()); - } - } - } + try { + + Glib::KeyFile keyFile; + + try { + keyFile.load_from_file (fname); + } catch (Glib::Error&) {} keyFile.set_string ("General", "MD5", md5); keyFile.set_string ("General", "Version", VERSION); // Application's version @@ -254,10 +243,25 @@ int CacheImageData::save (const Glib::ustring& fname) if (format == FT_Raw) { keyFile.set_integer ("ExtraRawInfo", "ThumbImageType", thumbImgType); - keyFile.set_integer ("ExtraRawInfo", "ThumbImageOffset", thumbOffset); } - FILE *f = safe_g_fopen (fname, "wt"); + keyData = keyFile.to_data (); + + } catch (Glib::Error &err) { + if (options.rtSettings.verbose) { + printf("CacheImageData::save / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str()); + } + } catch (...) { + if (options.rtSettings.verbose) { + printf("CacheImageData::save / Unknown exception while trying to save \"%s\"!\n", fname.c_str()); + } + } + + if (keyData.empty ()) { + return 1; + } + + FILE *f = g_fopen (fname.c_str (), "wt"); if (!f) { if (options.rtSettings.verbose) { @@ -266,7 +270,7 @@ int CacheImageData::save (const Glib::ustring& fname) return 1; } else { - fprintf (f, "%s", keyFile.to_data().c_str()); + fprintf (f, "%s", keyData.c_str ()); fclose (f); return 0; } diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index 91a31ce4f..f655bd88b 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -65,7 +65,6 @@ public: // additional info on raw images int rotate; int thumbImgType; - int thumbOffset; enum { FULL_THUMBNAIL = 0, // was the thumbnail generated from whole file diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc index 4342c4973..a76f23717 100644 --- a/rtgui/crophandler.cc +++ b/rtgui/crophandler.cc @@ -24,13 +24,16 @@ #include "cropwindow.h" #include "../rtengine/dcrop.h" #include "../rtengine/refreshmap.h" +#include "../rtengine/rt_math.h" using namespace rtengine; CropHandler::CropHandler () - : zoom(10), ww(0), wh(0), cx(0), cy(0), cw(0), ch(0), - cropX(0), cropY(0), cropW(0), cropH(0), enabled(false), - cropimg(NULL), cropimgtrue(NULL), ipc(NULL), crop(NULL), listener(NULL), isLowUpdatePriority(false) + : zoom(10), ww(0), wh(0), imx(-1), imy(-1), imw(0), imh(0), cax(-1), cay(-1), + cx(0), cy(0), cw(0), ch(0), cropX(0), cropY(0), cropW(0), cropH(0), enabled(false), + cropimg(NULL), cropimgtrue(NULL), cropimg_width(0), cropimg_height(0), + initial(false), isLowUpdatePriority(false), ipc(NULL), crop(NULL), + displayHandler(NULL) { chi = new CropHandlerIdleHelper; @@ -82,7 +85,7 @@ void CropHandler::newImage (StagedImageProcessor* ipc_, bool isDetailWindow) } EditDataProvider *editDataProvider = NULL; - CropWindow *cropWin = listener ? static_cast(listener) : NULL; + CropWindow *cropWin = displayHandler ? static_cast(displayHandler) : NULL; if (cropWin) { editDataProvider = cropWin->getImageArea(); @@ -126,16 +129,29 @@ double CropHandler::getFitZoom () void CropHandler::setZoom (int z, int centerx, int centery) { + assert (ipc); - int x = cx + cw / 2; - int y = cy + ch / 2; + int oldZoom = zoom; + float oldScale = zoom >= 1000 ? float(zoom / 1000) : 1.f / float(zoom); + float newScale = z >= 1000 ? float(z / 1000) : 1.f / float(z); - if (centerx >= 0) { - x = centerx; + int oldcax = cax; + int oldcay = cay; + + if (centerx == -1) { + cax = ipc->getFullWidth () / 2; + } else { + float distToAnchor = float(cax - centerx); + distToAnchor = distToAnchor / newScale * oldScale; + cax = centerx + int(distToAnchor); } - if (centery >= 0) { - y = centery; + if (centery == -1) { + cay = ipc->getFullHeight () / 2; + } else { + float distToAnchor = float(cay - centery); + distToAnchor = distToAnchor / newScale * oldScale; + cay = centery + int(distToAnchor); } // maybe demosaic etc. if we cross the border to >100% @@ -151,13 +167,20 @@ void CropHandler::setZoom (int z, int centerx, int centery) ch = wh * zoom; } - cx = x - cw / 2; - cy = y - ch / 2; + cx = cax - cw / 2; + cy = cay - ch / 2; + + + int oldCropX = cropX; + int oldCropY = cropY; + int oldCropW = cropW; + int oldCropH = cropH; compDim (); - if (enabled) { + if (enabled && (oldZoom != zoom || oldcax != cax || oldcay != cay || oldCropX != cropX || oldCropY != cropY || oldCropW != cropW || oldCropH != cropH)) { if (needsFullRefresh) { + cropPixbuf.clear (); ipc->startProcessing(M_HIGHQUAL); } else { update (); @@ -194,11 +217,44 @@ void CropHandler::getWSize (int& w, int &h) h = wh; } -void CropHandler::setPosition (int x, int y, bool update_) +void CropHandler::getAnchorPosition (int& x, int& y) { + x = cax; + y = cay; +} - cx = x; - cy = y; +void CropHandler::setAnchorPosition (int x, int y, bool update_) +{ + cax = x; + cay = y; + + compDim (); + + if (enabled && update_) { + update (); + } +} + +void CropHandler::moveAnchor (int deltaX, int deltaY, bool update_) +{ + cax += deltaX; + cay += deltaY; + + compDim (); + + if (enabled && update_) { + update (); + } +} + +void CropHandler::centerAnchor (bool update_) +{ + assert (ipc); + + // Computes the crop's size and position given the anchor's position and display size + + cax = ipc->getFullWidth() / 2; + cay = ipc->getFullHeight() / 2; compDim (); @@ -280,11 +336,11 @@ int createpixbufs (void* data) ch->cimg.unlock (); - if (ch->listener) { - ch->listener->cropImageUpdated (); + if (ch->displayHandler) { + ch->displayHandler->cropImageUpdated (); if (ch->initial) { - ch->listener->initialImageArrived (); + ch->displayHandler->initialImageArrived (); ch->initial = false; } } @@ -365,7 +421,7 @@ bool CropHandler::getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip) void CropHandler::update () { - if (crop) { + if (crop && enabled) { // crop->setWindow (cropX, cropY, cropW, cropH, zoom>=1000 ? 1 : zoom); --> we use the "getWindow" hook instead of setting the size before crop->setListener (this); cropPixbuf.clear (); @@ -428,41 +484,78 @@ void CropHandler::getFullImageSize (int& w, int& h) void CropHandler::compDim () { + assert (ipc && displayHandler); - cropX = cx; - cropY = cy; - cropW = cw; - cropH = ch; + // Computes the crop's size and position given the anchor's position and display size - cutRectToImgBounds (cropX, cropY, cropW, cropH); -} + int fullW = ipc->getFullWidth(); + int fullH = ipc->getFullHeight(); + int imgX = -1, imgY = -1; + //int scaledFullW, scaledFullH; + int scaledCAX, scaledCAY; + int wwImgSpace; + int whImgSpace; -void CropHandler::cutRectToImgBounds (int& x, int& y, int& w, int& h) -{ + cax = rtengine::LIM(cax, 0, fullW-1); + cay = rtengine::LIM(cay, 0, fullH-1); - if (ipc) { - if (w > ipc->getFullWidth()) { - w = ipc->getFullWidth(); - } - - if (h > ipc->getFullHeight()) { - h = ipc->getFullHeight(); - } - - if (x < 0) { - x = 0; - } - - if (y < 0) { - y = 0; - } - - if (x + w >= ipc->getFullWidth()) { - x = ipc->getFullWidth() - w; - } - - if (y + h >= ipc->getFullHeight()) { - y = ipc->getFullHeight() - h; - } + if (zoom >= 1000) { + wwImgSpace = int(float(ww) / float(zoom/1000) + 0.5f); + whImgSpace = int(float(wh) / float(zoom/1000) + 0.5f); + //scaledFullW = fullW * (zoom/1000); + //scaledFullH = fullH * (zoom/1000); + scaledCAX = cax * (zoom/1000); + scaledCAY = cay * (zoom/1000); + } else { + wwImgSpace = int(float(ww) * float(zoom) + 0.5f); + whImgSpace = int(float(wh) * float(zoom) + 0.5f); + //scaledFullW = fullW / zoom; + //scaledFullH = fullH / zoom; + scaledCAX = cax / zoom; + scaledCAY = cay / zoom; } + + imgX = ww / 2 - scaledCAX; + if (imgX < 0) { + imgX = 0; + } + imgY = wh / 2 - scaledCAY; + if (imgY < 0) { + imgY = 0; + } + + cropX = cax - (wwImgSpace/2); + cropY = cay - (whImgSpace/2); + cropW = wwImgSpace; + cropH = whImgSpace; + + if (cropX + cropW > fullW) { + cropW = fullW - cropX; + } + + if (cropY + cropH > fullH) { + cropH = fullH - cropY; + } + + if (cropX < 0) { + cropW += cropX; + cropX = 0; + } + + if (cropY < 0) { + cropH += cropY; + cropY = 0; + } + + // Should be good already, but this will correct eventual rounding error + + if (cropW > fullW) { + cropW = fullW; + } + + if (cropH > fullH) { + cropH = fullH; + } + + displayHandler->setDisplayPosition(imgX, imgY); } diff --git a/rtgui/crophandler.h b/rtgui/crophandler.h index 60d7956ca..6e479bb16 100644 --- a/rtgui/crophandler.h +++ b/rtgui/crophandler.h @@ -24,14 +24,15 @@ #include "edit.h" #include -class CropHandlerListener +class CropDisplayHandler { public: - virtual ~CropHandlerListener() {} + virtual ~CropDisplayHandler() {} virtual void cropImageUpdated () {} virtual void cropWindowChanged () {} virtual void initialImageArrived () {} + virtual void setDisplayPosition (int x, int y) {} }; class CropHandler; @@ -41,16 +42,22 @@ struct CropHandlerIdleHelper { int pending; }; +/** + * This class handle the displayed part of the image, ask for the initial data and process it so it can display it. + * Its position on the preview is handled not set by this class but by the CropHandlerListener (i.e. CropWindow) with which it works closely. + */ class CropHandler : public rtengine::DetailedCropListener, public rtengine::SizeListener { friend int createpixbufs (void* data); protected: - int zoom; - int ww, wh; // size of the crop view on the screen - int cx, cy, cw, ch; // position and size of the requested crop - int cropX, cropY, cropW, cropH; // position and size of the crop corresponding to cropPixbuf + int zoom; // scale factor (e.g. 5 if 1:5 scale) ; if 1:1 scale and bigger, factor is multiplied by 1000 (i.e. 1000 for 1:1 scale, 2000 for 2:1, etc...) + int ww, wh; // size of the crop's canvas on the screen ; might be bigger than the displayed image, but not smaller + int imx, imy, imw, imh; // this is a copy of the cropwindow's parameters + int cax, cay; // clamped crop anchor's coordinate, i.e. point of the image that coincide to the center of the display area, expressed in image coordinates; cannot be outside the image's bounds; but if cax==cay==-1, designate the center of the image + int cx, cy, cw, ch; // position and size of the requested crop ; position expressed in image coordinates, so cx and cy might be negative and cw and ch higher than the image's 1:1 size + int cropX, cropY, cropW, cropH; // cropPixbuf's displayed area (position and size), i.e. coordinates in 1:1 scale, i.e. cx, cy, cw & ch trimmed to the image's bounds bool enabled; unsigned char* cropimg; unsigned char* cropimgtrue; @@ -61,7 +68,7 @@ protected: rtengine::StagedImageProcessor* ipc; rtengine::DetailedCrop* crop; - CropHandlerListener* listener; + CropDisplayHandler* displayHandler; CropHandlerIdleHelper* chi; void compDim (); @@ -81,9 +88,9 @@ public: CropHandler (); ~CropHandler (); - void setCropHandlerListener (CropHandlerListener* l) + void setDisplayHandler (CropDisplayHandler* l) { - listener = l; + displayHandler = l; } void setEditSubscriber (EditSubscriber* newSubscriber); @@ -93,7 +100,10 @@ public: double getFitCropZoom(); void setWSize (int w, int h); void getWSize (int& w, int &h); - void setPosition (int x, int y, bool update = true); + void getAnchorPosition (int& x, int& y); + void setAnchorPosition (int x, int y, bool update = true); + void moveAnchor (int deltaX, int deltaY, bool update = true); + void centerAnchor (bool update = true); void getPosition (int& x, int& y); void getSize (int& w, int& h); void getFullImageSize (int& w, int& h); @@ -112,8 +122,6 @@ public: bool getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip); // SizeListener interface void sizeChanged (int w, int h, int ow, int oh); - - void cutRectToImgBounds (int& x, int& y, int& w, int& h); }; #endif diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index 1c5b62a33..da0e2e00c 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -16,19 +16,21 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ +#include "cropwindow.h" + #include -#include "cropwindow.h" -#include "options.h" -#include "guiutils.h" -#include "threadutils.h" #include "../rtengine/mytime.h" -#include "imagearea.h" -#include "cursormanager.h" -#include "../rtengine/safegtk.h" #include "../rtengine/rt_math.h" #include "../rtengine/dcrop.h" +#include "guiutils.h" +#include "threadutils.h" +#include "rtimage.h" +#include "cursormanager.h" +#include "options.h" +#include "imagearea.h" + using namespace rtengine; struct ZoomStep { @@ -64,31 +66,30 @@ ZoomStep zoomSteps[] = { #define ZOOM11INDEX 13 CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, bool isLowUpdatePriority_, bool isDetailWindow) - : onResizeArea(false), deleted(false), fitZoomEnabled(true), fitZoom(false), isLowUpdatePriority(isLowUpdatePriority_), - backColor(options.bgcolor), decorated(true), titleHeight(30), - sideBorderWidth(3), lowerBorderWidth(3), upperBorderWidth(1), sepWidth(2), - xpos(30), ypos(30), imgX(0), imgY(0), imgW(1), imgH(1), iarea(parent), - cropZoom(0), cropgl(NULL), pmlistener(NULL), observedCropWin(NULL), ipc(ipc_), isFlawnOver(false) + : ObjectMOBuffer(parent), state(SNormal), press_x(0), press_y(0), action_x(0), action_y(0), pickedObject(-1), pickModifierKey(0), rot_deg(0), onResizeArea(false), deleted(false), + fitZoomEnabled(true), fitZoom(false), isLowUpdatePriority(isLowUpdatePriority_), cropLabel(Glib::ustring("100%")), + backColor(options.bgcolor), decorated(true), isFlawnOver(false), titleHeight(30), sideBorderWidth(3), lowerBorderWidth(3), + upperBorderWidth(1), sepWidth(2), xpos(30), ypos(30), width(0), height(0), imgAreaX(0), imgAreaY(0), imgAreaW(0), imgAreaH(0), + imgX(-1), imgY(-1), imgW(1), imgH(1), iarea(parent), cropZoom(0), zoomVersion(0), exposeVersion(0), cropgl(NULL), + pmlistener(NULL), pmhlistener(NULL), observedCropWin(NULL), ipc(ipc_) { Glib::RefPtr context = parent->get_pango_context () ; Pango::FontDescription fontd = context->get_font_description (); fontd.set_weight (Pango::WEIGHT_BOLD); fontd.set_size(8 * Pango::SCALE); context->set_font_description (fontd); - cropLabel = "100%"; Glib::RefPtr cllayout = parent->create_pango_layout("1000%"); - exposeVersion = zoomVersion = 0; int iw, ih; cllayout->get_pixel_size (iw, ih); titleHeight = ih; - bZoomOut = new LWButton (safe_create_from_png ("gtk-zoom-out-small.png"), 0, NULL, LWButton::Left, LWButton::Center, "Zoom Out"); - bZoomIn = new LWButton (safe_create_from_png ("gtk-zoom-in-small.png"), 1, NULL, LWButton::Left, LWButton::Center, "Zoom In"); - bZoom100 = new LWButton (safe_create_from_png ("gtk-zoom-100-small.png"), 2, NULL, LWButton::Left, LWButton::Center, "Zoom 100/%"); - //bZoomFit = new LWButton (safe_create_from_png ("gtk-zoom-fit.png"), 3, NULL, LWButton::Left, LWButton::Center, "Zoom Fit"); - bClose = new LWButton (safe_create_from_png ("gtk-close-small.png"), 4, NULL, LWButton::Right, LWButton::Center, "Close"); + bZoomOut = new LWButton (RTImage::createFromPng ("gtk-zoom-out-small.png"), 0, NULL, LWButton::Left, LWButton::Center, "Zoom Out"); + bZoomIn = new LWButton (RTImage::createFromPng ("gtk-zoom-in-small.png"), 1, NULL, LWButton::Left, LWButton::Center, "Zoom In"); + bZoom100 = new LWButton (RTImage::createFromPng ("gtk-zoom-100-small.png"), 2, NULL, LWButton::Left, LWButton::Center, "Zoom 100/%"); + //bZoomFit = new LWButton (RTImage::createFromPng ("gtk-zoom-fit.png"), 3, NULL, LWButton::Left, LWButton::Center, "Zoom Fit"); + bClose = new LWButton (RTImage::createFromPng ("gtk-close-small.png"), 4, NULL, LWButton::Right, LWButton::Center, "Close"); buttonSet.add (bZoomOut); buttonSet.add (bZoomIn); @@ -107,10 +108,8 @@ CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, minWidth = bsw + iw + 2 * sideBorderWidth; - cropHandler.setCropHandlerListener (this); + cropHandler.setDisplayHandler(this); cropHandler.newImage (ipc_, isDetailWindow); - - state = SNormal; } void CropWindow::enable() @@ -158,36 +157,27 @@ void CropWindow::getCropPosition (int& x, int& y) void CropWindow::getCropRectangle (int& x, int& y, int& w, int& h) { - int cropX, cropY, cropW, cropH; - cropHandler.getPosition (cropX, cropY); - cropHandler.getSize (cropW, cropH); - - if (state != SCropImgMove) { - x = cropX; - y = cropY; - } else { - x = cropX + action_x; - y = cropY + action_y; - } - - if (state != SCropWinResize) { - w = cropW; - h = cropH; - } else { - w = imgAreaW; - h = imgAreaH; - } - - cropHandler.cutRectToImgBounds (x, y, w, h); + cropHandler.getPosition (x, y); + cropHandler.getSize (w, h); } void CropWindow::setCropPosition (int x, int y, bool update) { - cropHandler.setPosition (x, y, update); + cropHandler.setAnchorPosition (x, y, update); - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropPositionChanged (this); + for (auto listener : listeners) { + listener->cropPositionChanged (this); + } +} + +void CropWindow::centerCrop (bool update) +{ + + cropHandler.centerAnchor (update); + + for (auto listener : listeners) { + listener->cropPositionChanged (this); } } @@ -220,6 +210,7 @@ void CropWindow::setSize (int w, int h, bool norefresh) } if (!norefresh) { + ObjectMOBuffer::resize(imgAreaW, imgAreaH); cropHandler.setWSize (imgAreaW, imgAreaH); } @@ -240,6 +231,16 @@ void CropWindow::getCropSize (int& w, int& h) h = imgAreaH; } +void CropWindow::getCropAnchorPosition (int& x, int& y) +{ + cropHandler.getAnchorPosition(x, y); +} + +void CropWindow::setCropAnchorPosition (int& x, int& y) +{ + cropHandler.setAnchorPosition(x, y); +} + bool CropWindow::isInside (int x, int y) { @@ -268,114 +269,182 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) { bool needRedraw = true; // most common case ; not redrawing are exceptions + const auto editSubscriber = iarea->getCurrSubscriber(); iarea->grabFocus (this); - if (button == 1 && type == GDK_2BUTTON_PRESS && onArea (CropImage, x, y) && (state == SNormal || state == SCropImgMove)) { - if (fitZoomEnabled) { - if (fitZoom) { - state = SNormal; - zoomVersion = exposeVersion; - screenCoordToImage (x, y, action_x, action_y); - changeZoom (ZOOM11INDEX, true, action_x, action_y); - fitZoom = false; + if (button == 1) { + if (type == GDK_2BUTTON_PRESS && onArea (CropImage, x, y) && (state == SNormal || state == SCropImgMove)) { + if (fitZoomEnabled) { + if (fitZoom) { + state = SNormal; + zoomVersion = exposeVersion; + screenCoordToImage (x, y, action_x, action_y); + changeZoom (ZOOM11INDEX, true, action_x, action_y); + fitZoom = false; + } else { + zoomFit (); + } } else { - zoomFit (); + zoom11 (); } - } else { - zoom11 (); - } - state = SNormal; - } - //below code is no longer working/needed after adding buttons for each of the backColor values - /*else if (button==1 && type==GDK_2BUTTON_PRESS && onArea (CropBorder, x, y)) { - backColor = (backColor+1) % 3; - options.bgcolor = backColor; - }*/ - else if (button == 1 && type == GDK_BUTTON_PRESS && state == SNormal && onArea (CropToolBar, x, y)) { - if (!decorated || !buttonSet.pressNotify (x, y)) { - state = SCropWinMove; - action_x = x; - action_y = y; - press_x = xpos; - press_y = ypos; + state = SNormal; } - } else if (button == 1 && type == GDK_BUTTON_PRESS && state == SNormal && onArea (CropResize, x, y)) { - state = SCropWinResize; - action_x = x; - action_y = y; - press_x = width; - press_y = height; - } else if (button == 1 && type == GDK_BUTTON_PRESS && state == SNormal && onArea (CropImage, x, y)) { - if (onArea (CropTopLeft, x, y)) { - state = SResizeTL; - press_x = x; - action_x = cropHandler.cropParams.x; - press_y = y; - action_y = cropHandler.cropParams.y; - } else if (onArea (CropTopRight, x, y)) { - state = SResizeTR; - press_x = x; - action_x = cropHandler.cropParams.w; - press_y = y; - action_y = cropHandler.cropParams.y; - } else if (onArea (CropBottomLeft, x, y)) { - state = SResizeBL; - press_x = x; - action_x = cropHandler.cropParams.x; - press_y = y; - action_y = cropHandler.cropParams.h; - } else if (onArea (CropBottomRight, x, y)) { - state = SResizeBR; - press_x = x; - action_x = cropHandler.cropParams.w; - press_y = y; - action_y = cropHandler.cropParams.h; - } else if (onArea (CropTop, x, y)) { - state = SResizeH1; - press_y = y; - action_y = cropHandler.cropParams.y; - } else if (onArea (CropBottom, x, y)) { - state = SResizeH2; - press_y = y; - action_y = cropHandler.cropParams.h; - } else if (onArea (CropLeft, x, y)) { - state = SResizeW1; - press_x = x; - action_x = cropHandler.cropParams.x; - } else if (onArea (CropRight, x, y)) { - state = SResizeW2; - press_x = x; - action_x = cropHandler.cropParams.w; - } else if ((bstate & GDK_SHIFT_MASK) && onArea (CropInside, x, y)) { - state = SCropMove; - press_x = x; - press_y = y; - action_x = cropHandler.cropParams.x; - action_y = cropHandler.cropParams.y; - } else if (iarea->getToolMode () == TMHand) { + else if (type == GDK_BUTTON_PRESS && state == SNormal) { + if (onArea (CropToolBar, x, y)) { + if (!decorated || !buttonSet.pressNotify (x, y)) { + state = SCropWinMove; + action_x = x; + action_y = y; + press_x = xpos; + press_y = ypos; + } + } else if (onArea (CropResize, x, y)) { + state = SCropWinResize; + action_x = x; + action_y = y; + press_x = width; + press_y = height; + } else { + if (onArea (CropImage, x, y)) { // events inside of the image domain + if (onArea (CropTopLeft, x, y)) { + state = SResizeTL; + press_x = x; + action_x = cropHandler.cropParams.x; + press_y = y; + action_y = cropHandler.cropParams.y; + } else if (onArea (CropTopRight, x, y)) { + state = SResizeTR; + press_x = x; + action_x = cropHandler.cropParams.w; + press_y = y; + action_y = cropHandler.cropParams.y; + } else if (onArea (CropBottomLeft, x, y)) { + state = SResizeBL; + press_x = x; + action_x = cropHandler.cropParams.x; + press_y = y; + action_y = cropHandler.cropParams.h; + } else if (onArea (CropBottomRight, x, y)) { + state = SResizeBR; + press_x = x; + action_x = cropHandler.cropParams.w; + press_y = y; + action_y = cropHandler.cropParams.h; + } else if (onArea (CropTop, x, y)) { + state = SResizeH1; + press_y = y; + action_y = cropHandler.cropParams.y; + } else if (onArea (CropBottom, x, y)) { + state = SResizeH2; + press_y = y; + action_y = cropHandler.cropParams.h; + } else if (onArea (CropLeft, x, y)) { + state = SResizeW1; + press_x = x; + action_x = cropHandler.cropParams.x; + } else if (onArea (CropRight, x, y)) { + state = SResizeW2; + press_x = x; + action_x = cropHandler.cropParams.w; + } else if ((bstate & GDK_SHIFT_MASK) && onArea (CropInside, x, y)) { + state = SCropMove; + press_x = x; + press_y = y; + action_x = cropHandler.cropParams.x; + action_y = cropHandler.cropParams.y; + } else if (onArea (CropObserved, x, y)) { + state = SObservedMove; + press_x = x; + press_y = y; + action_x = 0; + action_y = 0; + } else if (iarea->getToolMode () == TMStraighten) { + state = SRotateSelecting; + press_x = x; + press_y = y; + action_x = x; + action_y = y; + rot_deg = 0; + } else if (iarea->getToolMode () == TMSpotWB) { + int spotx, spoty; + screenCoordToImage (x, y, spotx, spoty); + iarea->spotWBSelected (spotx, spoty); + } else if (iarea->getToolMode () == TMCropSelect && cropgl) { + state = SCropSelecting; + screenCoordToImage (x, y, press_x, press_y); + cropHandler.cropParams.enabled = true; + cropHandler.cropParams.x = press_x; + cropHandler.cropParams.y = press_y; + cropHandler.cropParams.w = cropHandler.cropParams.h = 1; + cropgl->cropInit (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h); + } else if (iarea->getToolMode () == TMHand) { + if (editSubscriber) { + needRedraw = editSubscriber->button1Pressed(bstate); + if ((cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && (editSubscriber->getEditingType() == ET_PIPETTE && (bstate & GDK_CONTROL_MASK))) || editSubscriber->getEditingType() == ET_OBJECTS) { + if (editSubscriber->isDragging()) { + state = SEditDrag1; + } else if (editSubscriber->isPicking()) { + state = SEditPick1; + pickedObject = iarea->object; + pickModifierKey = bstate; + } + press_x = x; + press_y = y; + action_x = 0; + action_y = 0; + } + } + if (state != SEditDrag1) { + state = SCropImgMove; + press_x = x; + press_y = y; + action_x = 0; + action_y = 0; + } + } else { // if(zoomSteps[cropZoom].zoom > cropHandler.getFitZoom()) { // only allow move when image is only partial visible + state = SCropImgMove; + press_x = x; + press_y = y; + action_x = 0; + action_y = 0; + } + + } else if (iarea->getToolMode () == TMHand) { // events outside of the image domain + EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); + + if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) { + needRedraw = editSubscriber->button1Pressed(bstate); + + if (editSubscriber->isDragging()) { + state = SEditDrag1; + } else if (editSubscriber->isPicking()) { + state = SEditPick1; + pickedObject = iarea->object; + pickModifierKey = bstate; + } + + press_x = x; + press_y = y; + action_x = 0; + action_y = 0; + } + } + } + } + } else if (button == 2) { + if (iarea->getToolMode () == TMHand) { EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); + if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) { + needRedraw = editSubscriber->button2Pressed(bstate); - if (editSubscriber && cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && (editSubscriber->getEditingType() == ET_OBJECTS)) { - if (button == 1) { - needRedraw = editSubscriber->button1Pressed(bstate); - - if (editSubscriber->isDragging()) { - state = SEditDrag1; - } - } else if (button == 2) { - needRedraw = editSubscriber->button2Pressed(bstate); - - if (editSubscriber->isDragging()) { - state = SEditDrag2; - } - } else if (button == 3) { - needRedraw = editSubscriber->button3Pressed(bstate); - - if (editSubscriber->isDragging()) { - state = SEditDrag3; - } + if (editSubscriber->isDragging()) { + state = SEditDrag2; + } else if (editSubscriber->isPicking()) { + state = SEditPick2; + pickedObject = iarea->object; + pickModifierKey = bstate; } press_x = x; @@ -383,68 +452,26 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) action_x = 0; action_y = 0; } + } + } else if (button == 3) { + if (iarea->getToolMode () == TMHand) { + EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); + if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) { + needRedraw = editSubscriber->button3Pressed(bstate); - if (state != SEditDrag1 && state != SEditDrag2 && state != SEditDrag3) { - if (onArea (CropObserved, x, y)) { - state = SObservedMove; - press_x = x; - press_y = y; - action_x = 0; - action_y = 0; - } else if (button == 1 && editSubscriber && cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && (editSubscriber->getEditingType() == ET_PIPETTE && (bstate & GDK_CONTROL_MASK)) ) { - editSubscriber->button1Pressed(bstate); - state = SEditDrag1; - press_x = x; - press_y = y; - action_x = 0; - action_y = 0; - } else if(zoomSteps[cropZoom].zoom > cropHandler.getFitZoom()) { // only allow move when image is only partial visible - state = SCropImgMove; - press_x = x; - press_y = y; - action_x = 0; - action_y = 0; + if (editSubscriber->isDragging()) { + state = SEditDrag3; + } else if (editSubscriber->isPicking()) { + state = SEditPick3; + pickedObject = iarea->object; + pickModifierKey = bstate; } + + press_x = x; + press_y = y; + action_x = 0; + action_y = 0; } - } else if (onArea (CropObserved, x, y)) { - state = SObservedMove; - press_x = x; - press_y = y; - } else if (iarea->getToolMode () == TMStraighten) { - state = SRotateSelecting; - press_x = x; - press_y = y; - action_x = x; - action_y = y; - rot_deg = 0; - } else if (iarea->getToolMode () == TMSpotWB) { - int spotx, spoty; - screenCoordToImage (x, y, spotx, spoty); - iarea->spotWBSelected (spotx, spoty); - } else if (iarea->getToolMode () == TMCropSelect && cropgl) { - state = SCropSelecting; - screenCoordToImage (x, y, press_x, press_y); - cropHandler.cropParams.enabled = true; - cropHandler.cropParams.x = press_x; - cropHandler.cropParams.y = press_y; - cropHandler.cropParams.w = cropHandler.cropParams.h = 1; - cropgl->cropInit (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h); - } - } - - if (button == 3) { - iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f; - EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); - - if (editSubscriber && editSubscriber->getEditingType() == ET_PIPETTE) { - editSubscriber->mouseOver(0); - } - - state = SNormal; - iarea->setToolHand (); - - if (pmhlistener) { - pmhlistener->toggleFreeze(); } } @@ -474,16 +501,14 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) state = SNormal; - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropWindowSizeChanged (this); + for (auto listener : listeners) { + listener->cropWindowSizeChanged (this); } needRedraw = true; } else if (state == SCropImgMove) { - int cropX, cropY; - cropHandler.getPosition (cropX, cropY); - cropHandler.setPosition (cropX + action_x, cropY + action_y); - cropHandler.getPosition (cropX, cropY); + cropHandler.update (); + state = SNormal; for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { @@ -500,7 +525,7 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) state = SNormal; needRedraw = true; } else if (state == SEditDrag1 || state == SEditDrag2 || state == SEditDrag3) { - if (state == SEditDrag1) { + if (state == SEditDrag1) { needRedraw = editSubscriber->button1Released(); } else if (state == SEditDrag2) { needRedraw = editSubscriber->button2Released(); @@ -519,9 +544,9 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) iarea->posScreen.set(x, y); Coord cropPos; - screenCoordToCropBuffer(x, y, cropPos.x, cropPos.y); - if (state == SEditDrag1 && editSubscriber->getEditingType() == ET_PIPETTE) { + screenCoordToCropBuffer (x, y, cropPos.x, cropPos.y); + iarea->object = onArea (CropImage, x, y) && !onArea (CropObserved, x, y) ? 1 : 0; //iarea->object = cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) ? 1 : 0; @@ -532,11 +557,8 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f; } } else if (editSubscriber->getEditingType() == ET_OBJECTS) { - if (onArea (CropImage, x, y)) { - iarea->object = crop->getObjectID(cropPos); - } else { - iarea->object = -1; - } + screenCoordToCropCanvas (x, y, cropPos.x, cropPos.y); + iarea->object = ObjectMOBuffer::getObjectID(cropPos); } needRedraw |= editSubscriber->mouseOver(bstate); @@ -548,7 +570,38 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) iarea->deltaScreen.set(0, 0); iarea->deltaPrevImage.set(0, 0); iarea->deltaPrevScreen.set(0, 0); - state = SNormal; + } else if (state == SEditPick1 || state == SEditPick2 || state == SEditPick3) { + if (editSubscriber) { + Coord imgPos; + action_x = x; + action_y = y; + screenCoordToImage (x, y, imgPos.x, imgPos.y); + + iarea->posImage.set (imgPos.x, imgPos.y); + iarea->posScreen.set (x, y); + + Coord cropPos; + screenCoordToCropCanvas (x, y, cropPos.x, cropPos.y); + + iarea->object = ObjectMOBuffer::getObjectID(cropPos); + + bool elemPicked = iarea->object == pickedObject && bstate == pickModifierKey; + + if (state == SEditPick1) { + needRedraw = editSubscriber->pick1 (elemPicked); + } else if (state == SEditPick2) { + needRedraw = editSubscriber->pick2 (elemPicked); + } else if (state == SEditPick3) { + needRedraw = editSubscriber->pick3 (elemPicked); + } + + iarea->object = pickedObject = -1; + pickModifierKey = 0; + + needRedraw |= editSubscriber->mouseOver (bstate); + } else { + iarea->object = 0; + } } if (cropgl && (state == SCropSelecting || state == SResizeH1 || state == SResizeH2 || state == SResizeW1 || state == SResizeW2 || state == SResizeTL || state == SResizeTR || state == SResizeBL || state == SResizeBR || state == SCropMove)) { @@ -567,6 +620,22 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) return; } + if (state != SEditDrag3 && state != SEditPick3 && button == 3 && !(bstate & (GDK_SHIFT_MASK|GDK_CONTROL_MASK))) { + iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f; + + needRedraw = iarea->object == 1; + + if (editSubscriber && editSubscriber->getEditingType() == ET_PIPETTE) { + editSubscriber->mouseOver(0); + } + + iarea->setToolHand (); + + if (pmhlistener) { + pmhlistener->toggleFreeze(); + } + } + state = SNormal; iarea->grabFocus (NULL); @@ -588,8 +657,8 @@ void CropWindow::pointerMoved (int bstate, int x, int y) } else if (state == SCropWinResize) { setSize (press_x + x - action_x, press_y + y - action_y, true); - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropWindowSizeChanged (this); + for (auto listener : listeners) { + listener->cropWindowSizeChanged (this); } iarea->redraw (); @@ -602,11 +671,19 @@ void CropWindow::pointerMoved (int bstate, int x, int y) factor = 1.0; } - action_x = (press_x - x) / zoomSteps[cropZoom].zoom * factor; - action_y = (press_y - y) / zoomSteps[cropZoom].zoom * factor; + int newAction_x = (press_x - x) / zoomSteps[cropZoom].zoom * factor; + int newAction_y = (press_y - y) / zoomSteps[cropZoom].zoom * factor; - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropPositionChanged (this); + int deltaX = newAction_x - action_x; + int deltaY = newAction_y - action_y; + + action_x = newAction_x; + action_y = newAction_y; + + cropHandler.moveAnchor(deltaX, deltaY, false); + + for (auto listener : listeners) { + listener->cropPositionChanged (this); } iarea->redraw (); @@ -695,12 +772,16 @@ void CropWindow::pointerMoved (int bstate, int x, int y) iarea->redraw (); } else if (state == SObservedMove) { - observedCropWin->remoteMove ((x - press_x) / zoomSteps[cropZoom].zoom, (y - press_y) / zoomSteps[cropZoom].zoom); + int new_action_x = x - press_x; + int new_action_y = y - press_y; + observedCropWin->remoteMove ((new_action_x - action_x) / zoomSteps[cropZoom].zoom, (new_action_y - action_y) / zoomSteps[cropZoom].zoom); + action_x = new_action_x; + action_y = new_action_y; iarea->redraw (); } else if (editSubscriber) { rtengine::Crop* crop = static_cast(cropHandler.getCrop()); - if (state == SNormal) { + if (state == SNormal || state == SEditPick1 || state == SEditPick2 || state == SEditPick3) { Coord imgPos; action_x = x; action_y = y; @@ -710,9 +791,10 @@ void CropWindow::pointerMoved (int bstate, int x, int y) iarea->posScreen.set(x, y); Coord cropPos; - screenCoordToCropBuffer(x, y, cropPos.x, cropPos.y); if (editSubscriber->getEditingType() == ET_PIPETTE) { + screenCoordToCropBuffer (x, y, cropPos.x, cropPos.y); + iarea->object = onArea (CropImage, x, y) && !onArea (CropObserved, x, y) ? 1 : 0; //iarea->object = cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) ? 1 : 0; @@ -723,11 +805,8 @@ void CropWindow::pointerMoved (int bstate, int x, int y) iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f; } } else if (editSubscriber->getEditingType() == ET_OBJECTS) { - if (onArea (CropImage, x, y)) { - iarea->object = crop->getObjectID(cropPos); - } else { - iarea->object = -1; - } + screenCoordToCropCanvas (x, y, cropPos.x, cropPos.y); + iarea->object = ObjectMOBuffer::getObjectID(cropPos); } if (editSubscriber->mouseOver(bstate)) { @@ -839,7 +918,7 @@ void CropWindow::pointerMoved (int bstate, int x, int y) bool CropWindow::onArea (CursorArea a, int x, int y) { - int CROPRESIZEBORDER = 6 / zoomSteps[cropZoom].zoom; + int CROPRESIZEBORDER = rtengine::max(9 / zoomSteps[cropZoom].zoom, 3); int x1, y1, w, h; switch (a) { @@ -850,7 +929,7 @@ bool CropWindow::onArea (CursorArea a, int x, int y) return x > xpos && y > ypos && x < xpos + width - 1 && y < ypos + imgAreaY; case CropImage: - return x >= xpos + imgX && y >= ypos + imgY && x < xpos + imgX + imgW && y < ypos + imgY + imgH; + return x >= xpos + imgX + imgAreaX && y >= ypos + imgY + imgAreaY && x < xpos + imgX + imgAreaX + imgW && y < ypos + imgY + imgAreaY + imgH; case CropBorder: return @@ -985,10 +1064,10 @@ void CropWindow::updateCursor (int x, int y) } else if (onArea (CropImage, x, y)) { int objectID = -1; - if (editSubscriber) { + if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) { Coord cropPos; - screenCoordToCropBuffer(iarea->posScreen.x, iarea->posScreen.y, cropPos.x, cropPos.y); - objectID = static_cast(cropHandler.getCrop())->getObjectID(cropPos); + screenCoordToCropCanvas (iarea->posScreen.x, iarea->posScreen.y, cropPos.x, cropPos.y); + objectID = ObjectMOBuffer::getObjectID(cropPos); } if (objectID > -1) { @@ -1007,7 +1086,19 @@ void CropWindow::updateCursor (int x, int y) cursorManager.setCursor (iarea->get_window(), CSStraighten); } } else { - cursorManager.setCursor (iarea->get_window(), CSArrow); + int objectID = -1; + + if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) { + Coord cropPos; + screenCoordToCropCanvas (iarea->posScreen.x, iarea->posScreen.y, cropPos.x, cropPos.y); + objectID = ObjectMOBuffer::getObjectID(cropPos); + } + + if (objectID > -1) { + cursorManager.setCursor (iarea->get_window(), editSubscriber->getCursor(objectID)); + } else { + cursorManager.setCursor (iarea->get_window(), CSArrow); + } } } else if (state == SCropSelecting) { cursorManager.setCursor (iarea->get_window(), CSCropSelect); @@ -1042,7 +1133,7 @@ void CropWindow::expose (Cairo::RefPtr cr) drawDecoration (cr); } - int x = xpos, y = ypos, h = height, w = width; + int x = xpos, y = ypos; // draw the background backColor = iarea->previewModePanel->GetbackColor(); @@ -1069,15 +1160,10 @@ void CropWindow::expose (Cairo::RefPtr cr) int cropX, cropY; cropHandler.getPosition (cropX, cropY); - if (state == SCropImgMove) { - cropX += action_x; - cropY += action_y; - } - Glib::RefPtr rough = iarea->getPreviewHandler()->getRoughImage (cropX, cropY, imgAreaW, imgAreaH, zoomSteps[cropZoom].zoom); if (rough) { - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x + imgAreaX + (imgAreaW - rough->get_width()) / 2, y + imgAreaY + (imgAreaH - rough->get_height()) / 2, -1, -1, Gdk::RGB_DITHER_NORMAL, 0, 0); + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x + imgAreaX + imgX, y + imgAreaY + imgY, rtengine::min (rough->get_width (), imgAreaW-imgX), rtengine::min (rough->get_height (), imgAreaH-imgY), Gdk::RGB_DITHER_NORMAL, 0, 0); // if (cropHandler.cropParams.enabled) // drawCrop (cr, x+imgX, y+imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams); } @@ -1089,8 +1175,6 @@ void CropWindow::expose (Cairo::RefPtr cr) if (cropHandler.cropPixbuf) { imgW = cropHandler.cropPixbuf->get_width (); imgH = cropHandler.cropPixbuf->get_height (); - imgX = imgAreaX + (imgAreaW - imgW) / 2; - imgY = imgAreaY + (imgAreaH - imgH) / 2; exposeVersion++; bool showcs = iarea->indClippedPanel->showClippedShadows(); @@ -1240,8 +1324,8 @@ void CropWindow::expose (Cairo::RefPtr cr) } } - float sum_L2 = tmpLsum[i * bWidth + j]; - float sumsq_L2 = tmpLsumSq[i * bWidth + j]; + //float sum_L2 = tmpLsum[i * bWidth + j]; + //float sumsq_L2 = tmpLsumSq[i * bWidth + j]; //************* // averages // Optimized formulas to avoid divisions @@ -1484,16 +1568,15 @@ void CropWindow::expose (Cairo::RefPtr cr) } } -//printf("zoomSteps[cropZoom].zoom=%d\n",zoomSteps[cropZoom].zoom); - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), tmp, 0, 0, x + imgX, y + imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), tmp, 0, 0, x + imgAreaX + imgX, y + imgAreaY + imgY, rtengine::min (tmp->get_width (), imgAreaW-imgX), rtengine::min (tmp->get_height (), imgAreaH-imgY), Gdk::RGB_DITHER_NORMAL, 0, 0); } else { - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), cropHandler.cropPixbuf, 0, 0, x + imgX, y + imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), cropHandler.cropPixbuf, 0, 0, x + imgAreaX + imgX, y + imgAreaY + imgY, rtengine::min (cropHandler.cropPixbuf->get_width (), imgAreaW-imgX), rtengine::min (cropHandler.cropPixbuf->get_height (), imgAreaH-imgY), Gdk::RGB_DITHER_NORMAL, 0, 0); } if (cropHandler.cropParams.enabled) { int cropX, cropY; cropHandler.getPosition (cropX, cropY); - drawCrop (cr, x + imgX, y + imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams, (this == iarea->mainCropWindow), true, zoomSteps[cropZoom].zoom <= cropHandler.getFitZoom() ); + drawCrop (cr, x + imgAreaX + imgX, y + imgAreaY + imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams, (this == iarea->mainCropWindow), true, zoomSteps[cropZoom].zoom <= cropHandler.getFitZoom() ); } if (observedCropWin) { @@ -1501,13 +1584,11 @@ void CropWindow::expose (Cairo::RefPtr cr) } EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); - rtengine::Crop* crop = static_cast(cropHandler.getCrop()); - - if (editSubscriber && crop->bufferCreated()) { + if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS && bufferCreated()) { if (this != iarea->mainCropWindow) { cr->set_line_width (0.); - cr->rectangle (x + imgX, y + imgY, imgW, imgH); + cr->rectangle (x + imgAreaX, y + imgAreaY, imgAreaW, imgAreaH); cr->clip(); } @@ -1518,90 +1599,47 @@ void CropWindow::expose (Cairo::RefPtr cr) cr->set_line_join(Cairo::LINE_JOIN_ROUND); // drawing outer lines - for (std::vector::const_iterator i = visibleGeom.begin(); i != visibleGeom.end(); ++i) { - (*i)->drawOuterGeometry(cr, crop, *this); + for (auto geom : visibleGeom) { + geom->drawOuterGeometry(cr, this, *this); } // drawing inner lines - for (std::vector::const_iterator i = visibleGeom.begin(); i != visibleGeom.end(); ++i) { - (*i)->drawInnerGeometry(cr, crop, *this); + for (auto geom : visibleGeom) { + geom->drawInnerGeometry(cr, this, *this); } + // drawing to the "mouse over" channel + const auto mouseOverGeom = editSubscriber->getMouseOverGeometry(); + if (mouseOverGeom.size()) { + if (mouseOverGeom.size() > 65534) { + // once it has been switched to OM_65535, it won't return back to OM_255 + // to avoid constant memory allocations in some particular situation. + // It will return to OM_255 on a new editing session + setObjectMode(OM_65535); + } + + Cairo::RefPtr crMO = Cairo::Context::create(ObjectMOBuffer::getObjectMap()); + crMO->set_antialias(Cairo::ANTIALIAS_NONE); + crMO->set_line_cap(Cairo::LINE_CAP_SQUARE); + crMO->set_line_join(Cairo::LINE_JOIN_ROUND); + crMO->set_operator(Cairo::OPERATOR_SOURCE); + + // clear the bitmap + crMO->set_source_rgba(0., 0., 0., 0.); + crMO->rectangle(0., 0., ObjectMOBuffer::getObjectMap()->get_width(), ObjectMOBuffer::getObjectMap()->get_height()); + crMO->set_line_width(0.); + crMO->fill(); + + int a=0; + for (auto moGeom : mouseOverGeom) { + moGeom->drawToMOChannel(crMO, a, this, *this); + ++a; + } + } if (this != iarea->mainCropWindow) { cr->reset_clip(); } - // drawing to the "mouse over" channel - if (editSubscriber->getEditingType() == ET_OBJECTS) { - const std::vector mouseOverGeom = editSubscriber->getMouseOverGeometry(); - - if (mouseOverGeom.size()) { - //printf("ObjectMap (%d x %d)\n", crop->getObjectMap()->get_width(), crop->getObjectMap()->get_height()); - Cairo::RefPtr crMO = Cairo::Context::create(crop->getObjectMap()); - crMO->set_antialias(Cairo::ANTIALIAS_NONE); - crMO->set_line_cap(Cairo::LINE_CAP_SQUARE); - crMO->set_line_join(Cairo::LINE_JOIN_ROUND); - crMO->set_operator(Cairo::OPERATOR_SOURCE); - - // clear the bitmap - crMO->set_source_rgba(0., 0., 0., 0.); - crMO->rectangle(0., 0., crop->getObjectMap()->get_width(), crop->getObjectMap()->get_height()); - crMO->set_line_width(0.); - crMO->fill(); - - Cairo::RefPtr crMO2; - - if (crop->getObjectMode() > OM_255) { - crMO2 = Cairo::Context::create(crop->getObjectMap2()); - crMO2->set_antialias(Cairo::ANTIALIAS_NONE); - crMO2->set_line_cap(Cairo::LINE_CAP_SQUARE); - crMO2->set_line_join(Cairo::LINE_JOIN_ROUND); - crMO2->set_operator(Cairo::OPERATOR_SOURCE); - - // clear the bitmap - crMO2->set_source_rgba(0., 0., 0., 0.); - crMO2->rectangle(0., 0., crop->getObjectMap2()->get_width(), crop->getObjectMap2()->get_height()); - crMO2->set_line_width(0.); - crMO2->fill(); - } - - std::vector::const_iterator i; - int a; - - for (a = 0, i = mouseOverGeom.begin(); i != mouseOverGeom.end(); ++i, ++a) { - (*i)->drawToMOChannel(crMO, crMO2, a, crop, *this); - } - - // Debug code: save the "mouse over" image to a new file at each occurrence -#if 0 - { - static unsigned int count = 0; - int w = crop->getObjectMap()->get_width(); - int h = crop->getObjectMap()->get_height(); - Glib::RefPtr img = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, false, 8, w, h); - guint8 *dst = img->get_pixels(); - unsigned char *src1 = crop->getObjectMap()->get_data(); - unsigned char *src2 = crop->getObjectMode() > OM_255 ? crop->getObjectMap()->get_data() : NULL; - memcpy(dst, src1, w * h); - - for (int n = 0, n3 = 0; n < w * h;) { - dst[n3++] = src1[n]; - - if (src2) { - dst[n3++] = src2[n]; - } else { - dst[n3++] = 0; - } - - dst[n3++] = 0; - ++n; - } - - img->save(Glib::ustring::compose("mouseOverImage-%1.png", count++), "png"); - } -#endif - } - } } } else { // cropHandler.cropPixbuf is null @@ -1610,14 +1648,14 @@ void CropWindow::expose (Cairo::RefPtr cr) Glib::RefPtr rough = iarea->getPreviewHandler()->getRoughImage (cropX, cropY, imgAreaW, imgAreaH, zoomSteps[cropZoom].zoom); if (rough) { - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x + imgAreaX + (imgAreaW - rough->get_width()) / 2, y + imgAreaY + (imgAreaH - rough->get_height()) / 2, -1, -1, Gdk::RGB_DITHER_NORMAL, 0, 0); + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x + imgAreaX + imgX, y + imgAreaY + imgY, rtengine::min (rough->get_width (), imgAreaW-imgX), rtengine::min (rough->get_height (), imgAreaH-imgY), Gdk::RGB_DITHER_NORMAL, 0, 0); if (cropHandler.cropParams.enabled) { - drawCrop (cr, x + imgAreaX + (imgAreaW - rough->get_width()) / 2, y + imgAreaY + (imgAreaH - rough->get_height()) / 2, rough->get_width(), rough->get_height(), cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams, (this == iarea->mainCropWindow), true, zoomSteps[cropZoom].zoom <= cropHandler.getFitZoom()); + drawCrop (cr, x + imgAreaX + imgX, y + imgAreaY + imgY, rough->get_width(), rough->get_height(), cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams, (this == iarea->mainCropWindow), true, zoomSteps[cropZoom].zoom <= cropHandler.getFitZoom()); } if (observedCropWin) { - drawObservedFrame (cr, rough->get_width(), rough->get_height()); + drawObservedFrame (cr); } } } @@ -1641,24 +1679,14 @@ void CropWindow::expose (Cairo::RefPtr cr) // printf ("etime --> %d, %d\n", t2.etime (t1), t4.etime (t3)); } -// calculate the center of the zoomed in/out preview given a cursor position -void CropWindow::findCenter (int deltaZoom, int& x, int& y) -{ - int cursorX, cursorY; - screenCoordToImage(x, y, cursorX, cursorY); - - int cropX, cropY, cropW, cropH, skip; - cropHandler.getWindow (cropX, cropY, cropW, cropH, skip); - - int currCenterX = cropX + cropW / 2; - int currCenterY = cropY + cropH / 2; - - int deltaX = currCenterX - cursorX; - int deltaY = currCenterY - cursorY; - - double factor = zoomSteps[cropZoom].zoom / zoomSteps[cropZoom + deltaZoom].zoom; - x = cursorX + (int)((double)(deltaX) * factor); - y = cursorY + (int)((double)(deltaY) * factor); +void CropWindow::setEditSubscriber (EditSubscriber* newSubscriber) { + // Delete, create, update all buffers based upon newSubscriber's type + if (newSubscriber) { + ObjectMOBuffer::resize (imgAreaW, imgAreaH); + } else { + ObjectMOBuffer::flush (); + } + cropHandler.setEditSubscriber(newSubscriber); } // zoom* is called from the zoomPanel or the scroll wheel in the preview area @@ -1806,7 +1834,7 @@ double CropWindow::getZoomFitVal () } -void CropWindow::zoomFit (bool skipZoomIfUnchanged) +void CropWindow::zoomFit () { double z = cropHandler.getFitZoom (); @@ -1822,7 +1850,7 @@ void CropWindow::zoomFit (bool skipZoomIfUnchanged) } zoomVersion = exposeVersion; - changeZoom (cz, true, -1, -1, skipZoomIfUnchanged); + changeZoom (cz, true, -1, -1); fitZoom = true; } @@ -1845,7 +1873,8 @@ void CropWindow::zoomFitCrop () int centerX, centerY; centerX = cropHandler.cropParams.x + cropHandler.cropParams.w / 2; centerY = cropHandler.cropParams.y + cropHandler.cropParams.h / 2; - changeZoom (cz, true, centerX, centerY, false); + setCropAnchorPosition(centerX, centerY); + changeZoom (cz, true, centerX, centerY); fitZoom = false; } } @@ -1874,7 +1903,7 @@ void CropWindow::redrawNeeded (LWButton* button) iarea->redraw (); } -void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery, bool skipZoomIfUnchanged) +void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery) { if (zoom < 0) { @@ -1883,19 +1912,14 @@ void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery, b zoom = MAXZOOMSTEPS; } - if (cropZoom == zoom && skipZoomIfUnchanged) { - // We are already at the start/end of the zoom range, so we do nothing - return; - } - cropZoom = zoom; cropLabel = zoomSteps[cropZoom].label; cropHandler.setZoom (zoomSteps[cropZoom].czoom, centerx, centery); if (notify) - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropZoomChanged (this); + for (auto listener : listeners) { + listener->cropZoomChanged (this); } iarea->redraw (); @@ -1905,8 +1929,8 @@ void CropWindow::screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& c { rtengine::Crop* crop = static_cast(cropHandler.getCrop()); - cropx = phyx - xpos - imgX; - cropy = phyy - ypos - imgY; + cropx = phyx - xpos - imgX - imgAreaX; + cropy = phyy - ypos - imgY - imgAreaY; if (zoomSteps[cropZoom].zoom > 1.) { cropx = int(double(cropx) / zoomSteps[cropZoom].zoom); @@ -1926,11 +1950,11 @@ void CropWindow::screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy) imgy = cropY + (phyy - ypos - imgY) / zoomSteps[cropZoom].zoom; } -void CropWindow::screenCoordToPreview (int phyx, int phyy, int& prevx, int& prevy) +void CropWindow::screenCoordToCropCanvas (int phyx, int phyy, int& prevx, int& prevy) { - prevx = phyx - xpos - imgX; - prevy = phyy - ypos - imgY; + prevx = phyx - xpos - imgAreaX; + prevy = phyy - ypos - imgAreaY; } void CropWindow::imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) @@ -1938,9 +1962,17 @@ void CropWindow::imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) int cropX, cropY; cropHandler.getPosition (cropX, cropY); - phyx = (imgx - cropX) * zoomSteps[cropZoom].zoom + xpos + imgX; - phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom + ypos + imgY; - // printf("imgx:%d / imgy:%d / cropX:%d / cropY:%d / xpos:%d / ypos:%d / imgX:%d / imgY:%d / leftBorder: %d / upperBorder:%d / phyx:%d / phyy:%d\n", imgx, imgy, cropX, cropY, xpos, ypos, imgX, imgY, crop->getLeftBorder(), crop->getUpperBorder(), phyx, phyy); + phyx = (imgx - cropX) * zoomSteps[cropZoom].zoom + xpos + imgX + imgAreaX; + phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom + ypos + imgY + imgAreaY; +} + +void CropWindow::imageCoordToCropCanvas (int imgx, int imgy, int& phyx, int& phyy) +{ + + int cropX, cropY; + cropHandler.getPosition (cropX, cropY); + phyx = (imgx - cropX) * zoomSteps[cropZoom].zoom + imgX; + phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom + imgY; } void CropWindow::imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy) @@ -1950,7 +1982,6 @@ void CropWindow::imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phy cropHandler.getPosition (cropX, cropY); phyx = (imgx - cropX) * zoomSteps[cropZoom].zoom + /*xpos + imgX +*/ crop->getLeftBorder(); phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom + /*ypos + imgY +*/ crop->getUpperBorder(); - //printf("imgx:%d / imgy:%d / cropX:%d / cropY:%d / xpos:%d / ypos:%d / imgX:%d / imgY:%d / leftBorder: %d / upperBorder:%d / phyx:%d / phyy:%d\n", imgx, imgy, cropX, cropY, xpos, ypos, imgX, imgY, crop->getLeftBorder(), crop->getUpperBorder(), phyx, phyy); } int CropWindow::scaleValueToImage (int value) @@ -1968,17 +1999,17 @@ double CropWindow::scaleValueToImage (double value) return value / zoomSteps[cropZoom].zoom; } -int CropWindow::scaleValueToScreen (int value) +int CropWindow::scaleValueToCanvas (int value) { return int(double(value) * zoomSteps[cropZoom].zoom); } -float CropWindow::scaleValueToScreen (float value) +float CropWindow::scaleValueToCanvas (float value) { return float(double(value) * zoomSteps[cropZoom].zoom); } -double CropWindow::scaleValueToScreen (double value) +double CropWindow::scaleValueToCanvas (double value) { return value * zoomSteps[cropZoom].zoom; } @@ -2113,7 +2144,7 @@ void CropWindow::drawScaledSpotRectangle (Cairo::RefPtr cr, int int x2 = action_x / zoomSteps[cropZoom].zoom + rectSize; cr->set_line_width (1.0); - cr->rectangle (xpos + imgX - 0.5, ypos + imgY - 0.5, imgW, imgH); + cr->rectangle (xpos + imgX + imgAreaX - 0.5, ypos + imgY + imgAreaY - 0.5, imgAreaW, imgAreaH); cr->clip (); cr->set_source_rgb (1.0, 1.0, 1.0); @@ -2135,7 +2166,7 @@ void CropWindow::drawUnscaledSpotRectangle (Cairo::RefPtr cr, in int x2 = action_x + rectSize; cr->set_line_width (1.0); - cr->rectangle (xpos + imgX - 0.5, ypos + imgY - 0.5, imgW, imgH); + cr->rectangle (xpos + imgX + imgAreaX - 0.5, ypos + imgY + imgAreaY - 0.5, imgAreaW, imgAreaH); cr->clip (); cr->set_source_rgb (1.0, 1.0, 1.0); @@ -2151,22 +2182,22 @@ void CropWindow::drawUnscaledSpotRectangle (Cairo::RefPtr cr, in void CropWindow::getObservedFrameArea (int& x, int& y, int& w, int& h, int rw, int rh) { - int cropX, cropY, cropW, cropH; - observedCropWin->getCropRectangle (cropX, cropY, cropW, cropH); - int myCropX, myCropY, myCropW, myCropH; - getCropRectangle (myCropX, myCropY, myCropW, myCropH); + int observedCropX, observedCropY, observedCropW, observedCropH; + observedCropWin->getCropRectangle (observedCropX, observedCropY, observedCropW, observedCropH); + int mainCropX, mainCropY, mainCropW, mainCropH; + getCropRectangle (mainCropX, mainCropY, mainCropW, mainCropH); // translate it to screen coordinates - if (rw) { - x = xpos + imgAreaX + (imgAreaW - rw) / 2 + (cropX - myCropX) * zoomSteps[cropZoom].zoom; - y = ypos + imgAreaY + (imgAreaH - rh) / 2 + (cropY - myCropY) * zoomSteps[cropZoom].zoom; + if (rw) { // rw and rh are the rough image's dimension + x = xpos + imgAreaX + (imgAreaW - rw) / 2 + (observedCropX - mainCropX) * zoomSteps[cropZoom].zoom; + y = ypos + imgAreaY + (imgAreaH - rh) / 2 + (observedCropY - mainCropY) * zoomSteps[cropZoom].zoom; } else { - x = xpos + imgX + (cropX - myCropX) * zoomSteps[cropZoom].zoom; - y = ypos + imgY + (cropY - myCropY) * zoomSteps[cropZoom].zoom; + x = xpos + imgX + (observedCropX - mainCropX) * zoomSteps[cropZoom].zoom; + y = ypos + imgY + (observedCropY - mainCropY) * zoomSteps[cropZoom].zoom; } - w = cropW * zoomSteps[cropZoom].zoom; - h = cropH * zoomSteps[cropZoom].zoom; + w = observedCropW * zoomSteps[cropZoom].zoom; + h = observedCropH * zoomSteps[cropZoom].zoom; } void CropWindow::drawObservedFrame (Cairo::RefPtr cr, int rw, int rh) @@ -2206,35 +2237,35 @@ void CropWindow::cropWindowChanged () void CropWindow::initialImageArrived () { - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->initialImageArrived (this); + for (auto listener : listeners) { + listener->initialImageArrived (this); } } +void CropWindow::setDisplayPosition (int x, int y) { + imgX = x; + imgY = y; +} void CropWindow::remoteMove (int deltaX, int deltaY) { state = SCropImgMove; - action_x = deltaX; - action_y = deltaY; + cropHandler.moveAnchor(deltaX, deltaY, false); - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropPositionChanged (this); + for (auto listener : listeners) { + listener->cropPositionChanged (this); } } void CropWindow::remoteMoveReady () { - int cropX, cropY; - cropHandler.getPosition (cropX, cropY); - cropHandler.setPosition (cropX + action_x, cropY + action_y); - cropHandler.getPosition (cropX, cropY); + cropHandler.update (); state = SNormal; - for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { - (*i)->cropPositionChanged (this); + for (auto listener : listeners) { + listener->cropPositionChanged (this); } } diff --git a/rtgui/cropwindow.h b/rtgui/cropwindow.h index aad6b9ef5..d9f738f66 100644 --- a/rtgui/cropwindow.h +++ b/rtgui/cropwindow.h @@ -28,6 +28,7 @@ #include #include "cropguilistener.h" #include "pointermotionlistener.h" +#include "edit.h" class CropWindow; class CropWindowListener @@ -42,12 +43,15 @@ public: }; class ImageArea; -class CropWindow : public LWButtonListener, public CropHandlerListener, public EditCoordSystem +class CropWindow : public LWButtonListener, public CropDisplayHandler, public EditCoordSystem, public ObjectMOBuffer { // state management ImgEditState state; // current state of user (see enum State) - int action_x, action_y, press_x, press_y; + int press_x, press_y; // position of the cursor in the GUI space on button press + int action_x, action_y; // parameter that will evolve during a pan or drag action + int pickedObject; + int pickModifierKey; double rot_deg; bool onResizeArea; bool deleted; @@ -85,7 +89,7 @@ class CropWindow : public LWButtonListener, public CropHandlerListener, public E PointerMotionListener* pmhlistener; std::list listeners; - CropWindow* observedCropWin; + CropWindow* observedCropWin; // Pointer to the currently active detail CropWindow rtengine::StagedImageProcessor* ipc; bool onArea (CursorArea a, int x, int y); @@ -95,7 +99,9 @@ class CropWindow : public LWButtonListener, public CropHandlerListener, public E void drawScaledSpotRectangle (Cairo::RefPtr cr, int rectSize); void drawUnscaledSpotRectangle (Cairo::RefPtr cr, int rectSize); void drawObservedFrame (Cairo::RefPtr cr, int rw = 0, int rh = 0); - void changeZoom (int zoom, bool notify = true, int centerx = -1, int centery = -1, bool skipZoomIfUnchanged = true); + void changeZoom (int zoom, bool notify = true, int centerx = -1, int centery = -1); + + // Used by the mainCropWindow only void getObservedFrameArea (int& x, int& y, int& w, int& h, int rw = 0, int rh = 0); public: @@ -117,15 +123,16 @@ public: void screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& cropy); void screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy); - void screenCoordToPreview (int phyx, int phyy, int& prevx, int& prevy); + void screenCoordToCropCanvas (int phyx, int phyy, int& prevx, int& prevy); + void imageCoordToCropCanvas (int imgx, int imgy, int& phyx, int& phyy); void imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy); void imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy); int scaleValueToImage (int value); float scaleValueToImage (float value); double scaleValueToImage (double value); - int scaleValueToScreen (int value); - float scaleValueToScreen (float value); - double scaleValueToScreen (double value); + int scaleValueToCanvas (int value); + float scaleValueToCanvas (float value); + double scaleValueToCanvas (double value); double getZoomFitVal (); void setPosition (int x, int y); void getPosition (int& x, int& y); @@ -140,14 +147,13 @@ public: void zoomIn (bool toCursor = false, int cursorX = -1, int cursorY = -1); void zoomOut (bool toCursor = false, int cursorX = -1, int cursorY = -1); void zoom11 (); - void zoomFit (bool skipZoomIfUnchanged = true); + void zoomFit (); void zoomFitCrop (); double getZoom (); bool isMinZoom (); bool isMaxZoom (); void setZoom (double zoom); - void findCenter (int deltaZoom, int& x, int& y); bool isInside (int x, int y); @@ -157,15 +163,20 @@ public: void expose (Cairo::RefPtr cr); + void setEditSubscriber (EditSubscriber* newSubscriber); + // interface lwbuttonlistener void buttonPressed (LWButton* button, int actionCode, void* actionData); void redrawNeeded (LWButton* button); // crop handling - void getCropRectangle (int& x, int& y, int& w, int& h); - void getCropPosition (int& x, int& y); - void setCropPosition (int x, int y, bool update = true); - void getCropSize (int& w, int& h); + void getCropRectangle (int& x, int& y, int& w, int& h); + void getCropPosition (int& x, int& y); + void setCropPosition (int x, int y, bool update = true); + void centerCrop (bool update = true); + void getCropSize (int& w, int& h); + void getCropAnchorPosition (int& w, int& h); + void setCropAnchorPosition (int& w, int& h); // listeners void setCropGUIListener (CropGUIListener* cgl) @@ -192,6 +203,7 @@ public: void cropImageUpdated (); void cropWindowChanged (); void initialImageArrived (); + void setDisplayPosition (int x, int y); void remoteMove (int deltaX, int deltaY); void remoteMoveReady (); diff --git a/rtgui/cursormanager.cc b/rtgui/cursormanager.cc index 45426a557..e011fd969 100644 --- a/rtgui/cursormanager.cc +++ b/rtgui/cursormanager.cc @@ -17,8 +17,8 @@ * along with RawTherapee. If not, see . */ #include "cursormanager.h" + #include "options.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" CursorManager cursorManager; @@ -41,14 +41,14 @@ void CursorManager::init (Glib::RefPtr mainWin) cAdd = new Gdk::Cursor (Gdk::PLUS); cWait = new Gdk::Cursor (Gdk::CLOCK); - Glib::RefPtr hand = safe_create_from_file("cross.png"); - Glib::RefPtr close_hand = safe_create_from_file("closedhand.png"); - Glib::RefPtr wbpick = safe_create_from_file("gtk-color-picker-small.png"); - Glib::RefPtr empty = safe_create_from_file("empty.png"); - Glib::RefPtr move2D = safe_create_from_file("move-2D.png"); - Glib::RefPtr move1DH = safe_create_from_file("move-1D-h.png"); - Glib::RefPtr move1DV = safe_create_from_file("move-1D-v.png"); - Glib::RefPtr moveRotate = safe_create_from_file("move-rotate.png"); + Glib::RefPtr hand = RTImage::createFromFile ("cross.png"); + Glib::RefPtr close_hand = RTImage::createFromFile ("closedhand.png"); + Glib::RefPtr wbpick = RTImage::createFromFile ("gtk-color-picker-small.png"); + Glib::RefPtr empty = RTImage::createFromFile ("empty.png"); + Glib::RefPtr move2D = RTImage::createFromFile ("move-2D.png"); + Glib::RefPtr move1DH = RTImage::createFromFile ("move-1D-h.png"); + Glib::RefPtr move1DV = RTImage::createFromFile ("move-1D-v.png"); + Glib::RefPtr moveRotate = RTImage::createFromFile ("move-rotate.png"); cHand = hand ? new Gdk::Cursor (cAdd->get_display(), hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2); cClosedHand = close_hand ? new Gdk::Cursor (cAdd->get_display(), close_hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2); diff --git a/rtgui/curveeditor.cc b/rtgui/curveeditor.cc index 3cfe335b2..c9d02d9a3 100644 --- a/rtgui/curveeditor.cc +++ b/rtgui/curveeditor.cc @@ -392,7 +392,7 @@ void CurveEditor::switchOffEditMode () EditSubscriber::switchOffEditMode(); // disconnect } -bool CurveEditor::mouseOver(int modifierKey) +bool CurveEditor::mouseOver(const int modifierKey) { EditDataProvider* provider = getEditProvider(); subGroup->pipetteMouseOver(provider, modifierKey); @@ -400,13 +400,16 @@ bool CurveEditor::mouseOver(int modifierKey) return true; // return true will ask the preview to be redrawn, for the cursor } -bool CurveEditor::button1Pressed(int modifierKey) +bool CurveEditor::button1Pressed(const int modifierKey) { EditDataProvider* provider = getEditProvider(); if (provider->object) { - subGroup->pipetteButton1Pressed(provider, modifierKey); - remoteDrag = true; + remoteDrag = subGroup->pipetteButton1Pressed(provider, modifierKey); + } + + if (remoteDrag) { + action = ES_ACTION_DRAGGING; } subGroup->refresh(this); @@ -422,7 +425,7 @@ bool CurveEditor::button1Released() return true; } -bool CurveEditor::drag1(int modifierKey) +bool CurveEditor::drag1(const int modifierKey) { EditDataProvider* provider = getEditProvider(); subGroup->pipetteDrag(provider, modifierKey); @@ -430,7 +433,7 @@ bool CurveEditor::drag1(int modifierKey) return false; } -CursorShape CurveEditor::getCursor(int objectID) +CursorShape CurveEditor::getCursor(const int objectID) { if (remoteDrag) { return CSResizeHeight; diff --git a/rtgui/curveeditor.h b/rtgui/curveeditor.h index 10e3d9668..a3ba68436 100644 --- a/rtgui/curveeditor.h +++ b/rtgui/curveeditor.h @@ -127,11 +127,11 @@ public: sigc::signal signal_curvepoint_release(); void switchOffEditMode (); - bool mouseOver(int modifierKey); - bool button1Pressed(int modifierKey); + bool mouseOver(const int modifierKey); + bool button1Pressed(const int modifierKey); bool button1Released(); - bool drag1(int modifierKey); - CursorShape getCursor(int objectID); + bool drag1(const int modifierKey); + CursorShape getCursor(const int objectID); }; diff --git a/rtgui/curveeditorgroup.cc b/rtgui/curveeditorgroup.cc index d524e0c4d..f703169ed 100644 --- a/rtgui/curveeditorgroup.cc +++ b/rtgui/curveeditorgroup.cc @@ -24,7 +24,6 @@ #include "diagonalcurveeditorsubgroup.h" #include "flatcurveeditorsubgroup.h" #include "multilangmgr.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" CurveEditorGroup::CurveEditorGroup (Glib::ustring& curveDir, Glib::ustring groupLabel) : curveDir(curveDir), curve_reset(NULL), @@ -422,7 +421,7 @@ void CurveEditorSubGroup::updateEditButton(CurveEditor* curve, Gtk::ToggleButton Glib::ustring CurveEditorSubGroup::outputFile () { - Gtk::FileChooserDialog dialog(M("CURVEEDITOR_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); + Gtk::FileChooserDialog dialog (getToplevelWindow (parent), M("CURVEEDITOR_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); bindCurrentFolder (dialog, curveDir); dialog.set_current_name (lastFilename); @@ -467,7 +466,7 @@ Glib::ustring CurveEditorSubGroup::outputFile () Glib::ustring CurveEditorSubGroup::inputFile () { - Gtk::FileChooserDialog dialog(M("CURVEEDITOR_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN); + Gtk::FileChooserDialog dialog (getToplevelWindow (parent), M("CURVEEDITOR_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN); bindCurrentFolder (dialog, curveDir); dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); diff --git a/rtgui/curveeditorgroup.h b/rtgui/curveeditorgroup.h index 1f1120f83..09cbb8167 100644 --- a/rtgui/curveeditorgroup.h +++ b/rtgui/curveeditorgroup.h @@ -141,7 +141,7 @@ public: virtual void stopNumericalAdjustment() = 0; virtual void pipetteMouseOver(EditDataProvider *provider, int modifierKey) = 0; - virtual void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) = 0; + virtual bool pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) = 0; virtual void pipetteButton1Released(EditDataProvider *provider) = 0; virtual void pipetteDrag(EditDataProvider *provider, int modifierKey) = 0; diff --git a/rtgui/darkframe.cc b/rtgui/darkframe.cc index 9edde1bbc..1e01b4b95 100644 --- a/rtgui/darkframe.cc +++ b/rtgui/darkframe.cc @@ -19,7 +19,6 @@ #include "darkframe.h" #include "options.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include #include "rtimage.h" @@ -81,7 +80,7 @@ void DarkFrame::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi dfAuto->set_inconsistent(!pedited->raw.dfAuto ); } - if (safe_file_test (pp->raw.dark_frame, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test (pp->raw.dark_frame, Glib::FILE_TEST_EXISTS)) { darkFrameFile->set_filename (pp->raw.dark_frame); } else { darkFrameReset(); diff --git a/rtgui/diagonalcurveeditorsubgroup.cc b/rtgui/diagonalcurveeditorsubgroup.cc index 4ca2bb159..657186a12 100644 --- a/rtgui/diagonalcurveeditorsubgroup.cc +++ b/rtgui/diagonalcurveeditorsubgroup.cc @@ -468,13 +468,15 @@ void DiagonalCurveEditorSubGroup::pipetteMouseOver(EditDataProvider *provider, i } } -void DiagonalCurveEditorSubGroup::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) +bool DiagonalCurveEditorSubGroup::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) { CurveEditor *curveEditor = static_cast(parent->displayedCurve); + bool isDragging = false; + switch((DiagonalCurveType)(curveEditor->curveType->getSelected())) { case (DCT_Spline): - customCurve->pipetteButton1Pressed(provider, modifierKey); + isDragging = customCurve->pipetteButton1Pressed(provider, modifierKey); break; case (DCT_Parametric): @@ -485,13 +487,15 @@ void DiagonalCurveEditorSubGroup::pipetteButton1Pressed(EditDataProvider *provid break; case (DCT_NURBS): - NURBSCurve->pipetteButton1Pressed(provider, modifierKey); + isDragging = NURBSCurve->pipetteButton1Pressed(provider, modifierKey); break; default: // (DCT_Linear, DCT_Unchanged) // ... do nothing break; } + + return isDragging; } void DiagonalCurveEditorSubGroup::pipetteButton1Released(EditDataProvider *provider) diff --git a/rtgui/diagonalcurveeditorsubgroup.h b/rtgui/diagonalcurveeditorsubgroup.h index 8178eb56a..5b6d845d5 100644 --- a/rtgui/diagonalcurveeditorsubgroup.h +++ b/rtgui/diagonalcurveeditorsubgroup.h @@ -83,7 +83,7 @@ public: void refresh(CurveEditor *curveToRefresh); void editModeSwitchedOff (); void pipetteMouseOver(EditDataProvider *provider, int modifierKey); - void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); + bool pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); void pipetteButton1Released(EditDataProvider *provider); void pipetteDrag(EditDataProvider *provider, int modifierKey); void showCoordinateAdjuster(CoordinateProvider *provider); diff --git a/rtgui/dirbrowser.cc b/rtgui/dirbrowser.cc index b79bb2c0f..040985e16 100644 --- a/rtgui/dirbrowser.cc +++ b/rtgui/dirbrowser.cc @@ -17,27 +17,57 @@ * along with RawTherapee. If not, see . */ #include "dirbrowser.h" + +#include + #ifdef WIN32 #define _WIN32_WINNT 0x0600 #include #endif -#include "options.h" -#include "multilangmgr.h" -#include "../rtengine/safegtk.h" -#include #include "guiutils.h" #include "rtimage.h" +#include "multilangmgr.h" +#include "options.h" -#define CHECKTIME 5000 +namespace +{ + +std::vector listSubDirs (const Glib::RefPtr& dir, bool addHidden) +{ + std::vector subDirs; + + try { + + // CD-ROM with no disc inserted are reported, but do not exist. + if (!Glib::file_test (dir->get_path (), Glib::FILE_TEST_EXISTS)) { + return subDirs; + } + + auto enumerator = dir->enumerate_children ("standard::name,standard::type,standard::is-hidden"); + + while (auto file = enumerator->next_file ()) { + if (file->get_file_type () != Gio::FILE_TYPE_DIRECTORY) { + continue; + } + if (!addHidden && file->is_hidden ()) { + continue; + } + subDirs.push_back (file->get_name ()); + } + + } catch (const Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to list subdirectories of \"" << dir << "\": " << exception.what () << std::endl; + } -struct DirNameComparator { - template - bool operator()(T const &firstDir, T const &secondDir) const - { - return options.dirBrowserSortType == Gtk::SORT_ASCENDING ? firstDir < secondDir : firstDir > secondDir; } -}; + + return subDirs; +} + +} DirBrowser::DirBrowser () : dirTreeModel(), dtColumns(), @@ -72,13 +102,13 @@ DirBrowser::DirBrowser () : dirTreeModel(), void DirBrowser::fillDirTree () { - openfolder = safe_create_from_file ("gtk-open.png"); - closedfolder = safe_create_from_file ("folder.png"); - icdrom = safe_create_from_file ("drive-optical.png"); - ifloppy = safe_create_from_file ("drive-removable-media.png"); - ihdd = safe_create_from_file ("drive-harddisk.png"); - iremovable = safe_create_from_file ("media-usb.png"); - inetwork = safe_create_from_file ("network.png"); + openfolder = RTImage::createFromFile ("gtk-open.png"); + closedfolder = RTImage::createFromFile ("folder.png"); + icdrom = RTImage::createFromFile ("drive-optical.png"); + ifloppy = RTImage::createFromFile ("drive-removable-media.png"); + ihdd = RTImage::createFromFile ("drive-harddisk.png"); + iremovable = RTImage::createFromFile ("media-usb.png"); + inetwork = RTImage::createFromFile ("network.png"); //Create the Tree model: dirTreeModel = Gtk::TreeStore::create(dtColumns); @@ -221,7 +251,7 @@ void DirBrowser::fillRoot () } // since sigc++ is not thread safe, we have to use the glib function - g_timeout_add (CHECKTIME, updateVolumesUI, this); + g_timeout_add (5000, updateVolumesUI, this); #else Gtk::TreeModel::Row rootRow = *(dirTreeModel->append()); rootRow[dtColumns.filename] = "/"; @@ -244,19 +274,15 @@ void DirBrowser::row_expanded (const Gtk::TreeModel::iterator& iter, const Gtk:: // We will disable model's sorting because it decreases speed of inserting new items // in list tree dramatically. Therefore will do: // 1) Disable sorting in model - // 2) Manually sort data by DirNameComparator + // 2) Manually sort data in the order determined by the options // 3) Enable sorting in model again for UI (sorting by click on header) int prevSortColumn; Gtk::SortType prevSortType; dirTreeModel->get_sort_column_id(prevSortColumn, prevSortType); dirTreeModel->set_sort_column(Gtk::TreeSortable::DEFAULT_UNSORTED_COLUMN_ID, Gtk::SORT_ASCENDING); - typedef std::vector DirPathType; - - DirPathType subDirs; - Glib::RefPtr dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname)); - - safe_build_subdir_list (dir, subDirs, options.fbShowHidden); + auto dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname)); + auto subDirs = listSubDirs (dir, options.fbShowHidden); if (subDirs.empty()) { dirtree->collapse_row(path); @@ -264,14 +290,22 @@ void DirBrowser::row_expanded (const Gtk::TreeModel::iterator& iter, const Gtk:: Gtk::TreeNodeChildren children = iter->children(); std::list forErase(children.begin(), children.end()); - DirNameComparator comparator; - sort(subDirs.begin(), subDirs.end(), comparator); + std::sort (subDirs.begin (), subDirs.end (), [] (const Glib::ustring& firstDir, const Glib::ustring& secondDir) + { + switch (options.dirBrowserSortType) { + default: + case Gtk::SORT_ASCENDING: + return firstDir < secondDir; + case Gtk::SORT_DESCENDING: + return firstDir > secondDir; + } + }); - for (DirPathType::const_iterator it = subDirs.begin(), end = subDirs.end(); it != end; ++it) { + for (auto it = subDirs.begin(), end = subDirs.end(); it != end; ++it) { addDir(iter, *it); } - for (std::list::const_iterator it = forErase.begin(), end = forErase.end(); it != end; ++it) { + for (auto it = forErase.begin(), end = forErase.end(); it != end; ++it) { dirTreeModel->erase(*it); } @@ -300,8 +334,8 @@ void DirBrowser::updateDir (const Gtk::TreeModel::iterator& iter) change = false; for (Gtk::TreeModel::iterator it = iter->children().begin(); it != iter->children().end(); it++) - if (!safe_file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_EXISTS) - || !safe_file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_EXISTS) + || !Glib::file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_IS_DIR)) { GThreadLock lock; dirTreeModel->erase (it); change = true; @@ -310,9 +344,8 @@ void DirBrowser::updateDir (const Gtk::TreeModel::iterator& iter) } // test if new files are created - std::vector subDirs; - Glib::RefPtr dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname)); - safe_build_subdir_list (dir, subDirs, options.fbShowHidden); + auto dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname)); + auto subDirs = listSubDirs (dir, options.fbShowHidden); for (int i = 0; i < subDirs.size(); i++) { bool found = false; @@ -346,7 +379,7 @@ void DirBrowser::row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewC Glib::ustring dname = dirTreeModel->get_iter (path)->get_value (dtColumns.dirname); - if (safe_file_test (dname, Glib::FILE_TEST_IS_DIR)) + if (Glib::file_test (dname, Glib::FILE_TEST_IS_DIR)) dirSelectionSignal (dname, Glib::ustring()); } @@ -443,7 +476,7 @@ void DirBrowser::open (const Glib::ustring& dirname, const Glib::ustring& fileNa void DirBrowser::file_changed (const Glib::RefPtr& file, const Glib::RefPtr& other_file, Gio::FileMonitorEvent event_type, const Gtk::TreeModel::iterator& iter, const Glib::ustring& dirName) { - if (!file || !safe_file_test (dirName, Glib::FILE_TEST_IS_DIR) || event_type == Gio::FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED) { + if (!file || !Glib::file_test (dirName, Glib::FILE_TEST_IS_DIR) || event_type == Gio::FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED) { return; } diff --git a/rtgui/dirpyrequalizer.cc b/rtgui/dirpyrequalizer.cc index 5d8a7011e..7996a340e 100644 --- a/rtgui/dirpyrequalizer.cc +++ b/rtgui/dirpyrequalizer.cc @@ -51,6 +51,24 @@ DirPyrEqualizer::DirPyrEqualizer () : FoldableToolPanel(this, "dirpyrequalizer", Color::hsv2rgb01(0.3240, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(1. , r, g, b) ); // hsv: 0.324 rad: 2.5 + Gtk::VBox * cbVBox = Gtk::manage ( new Gtk::VBox()); + cbVBox->set_border_width(4); + cbVBox->set_spacing(2); + + cdbox = Gtk::manage (new Gtk::HBox ()); + labmcd = Gtk::manage (new Gtk::Label (M("TP_CBDL_METHOD") + ":")); + cdbox->pack_start (*labmcd, Gtk::PACK_SHRINK, 1); + + cbdlMethod = Gtk::manage (new MyComboBoxText ()); + cbdlMethod->append_text (M("TP_CBDL_BEF")); + cbdlMethod->append_text (M("TP_CBDL_AFT")); + cbdlMethod->set_active(0); + cbdlMethodConn = cbdlMethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrEqualizer::cbdlMethodChanged) ); + cbdlMethod->set_tooltip_markup (M("TP_CBDL_METHOD_TOOLTIP")); + cdbox->pack_start(*cbdlMethod); + cbVBox->pack_start(*cdbox); + pack_start(*cbVBox); + setEnabledTooltipMarkup(M("TP_SHARPENING_TOOLTIP")); Gtk::HBox * buttonBox1 = Gtk::manage (new Gtk::HBox(true, 10)); @@ -146,12 +164,17 @@ void DirPyrEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) { disableListener (); + cbdlMethodConn.block(true); if (pedited) { set_inconsistent (multiImage && !pedited->dirpyrequalizer.enabled); gamutlab->set_inconsistent (!pedited->dirpyrequalizer.gamutlab); + if (!pedited->dirpyrequalizer.cbdlMethod) { + cbdlMethod->set_active_text(M("GENERAL_UNCHANGED")); + } + for(int i = 0; i < 6; i++) { multiplier[i]->setEditedState (pedited->dirpyrequalizer.mult[i] ? Edited : UnEdited); } @@ -187,6 +210,15 @@ void DirPyrEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) skinprotect->setValue(pp->dirpyrequalizer.skinprotect); hueskin->setValue(pp->dirpyrequalizer.hueskin); + if (pp->dirpyrequalizer.cbdlMethod == "bef") { + cbdlMethod->set_active (0); + } else if (pp->dirpyrequalizer.cbdlMethod == "aft") { + cbdlMethod->set_active (1); + } + + cbdlMethodChanged (); + cbdlMethodConn.block(false); + enableListener (); } @@ -208,6 +240,7 @@ void DirPyrEqualizer::write (ProcParams* pp, ParamsEdited* pedited) pedited->dirpyrequalizer.enabled = !get_inconsistent(); pedited->dirpyrequalizer.hueskin = hueskin->getEditedState (); + pedited->dirpyrequalizer.cbdlMethod = cbdlMethod->get_active_text() != M("GENERAL_UNCHANGED"); for(int i = 0; i < 6; i++) { pedited->dirpyrequalizer.mult[i] = multiplier[i]->getEditedState(); @@ -218,6 +251,13 @@ void DirPyrEqualizer::write (ProcParams* pp, ParamsEdited* pedited) // pedited->dirpyrequalizer.algo = algo->get_active_text()!=M("GENERAL_UNCHANGED"); } + + if (cbdlMethod->get_active_row_number() == 0) { + pp->dirpyrequalizer.cbdlMethod = "bef"; + } else if (cbdlMethod->get_active_row_number() == 1) { + pp->dirpyrequalizer.cbdlMethod = "aft"; + } + /* if (algo->get_active_row_number()==0) pp->dirpyrequalizer.algo = "FI"; else if (algo->get_active_row_number()==1) @@ -282,6 +322,16 @@ void DirPyrEqualizer::setBatchMode (bool batchMode) // algo->append_text (M("GENERAL_UNCHANGED")); } +void DirPyrEqualizer::cbdlMethodChanged() +{ + + if (listener) { + listener->panelChanged (EvcbdlMethod, cbdlMethod->get_active_text ()); + } +} + + + void DirPyrEqualizer::adjusterChanged (Adjuster* a, double newval) { diff --git a/rtgui/dirpyrequalizer.h b/rtgui/dirpyrequalizer.h index 6c0a4613d..9b806989c 100644 --- a/rtgui/dirpyrequalizer.h +++ b/rtgui/dirpyrequalizer.h @@ -45,6 +45,10 @@ protected: sigc::connection lumaneutralPressedConn; sigc::connection lumacontrastPlusPressedConn; sigc::connection lumacontrastMinusPressedConn; + sigc::connection cbdlMethodConn; + Gtk::Label* labmcd; + Gtk::HBox* cdbox; + MyComboBoxText* cbdlMethod; bool lastgamutlab; @@ -61,7 +65,7 @@ public: void trimValues (rtengine::procparams::ProcParams* pp); void adjusterChanged (ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight); // void algoChanged (); - + void cbdlMethodChanged(); void adjusterChanged (Adjuster* a, double newval); void enabledChanged(); void gamutlabToggled (); diff --git a/rtgui/edit.cc b/rtgui/edit.cc index 3efdea7f4..95831db7a 100644 --- a/rtgui/edit.cc +++ b/rtgui/edit.cc @@ -18,9 +18,115 @@ */ #include "edit.h" -#include "../rtengine/editbuffer.h" #include "rtimage.h" +ObjectMOBuffer::ObjectMOBuffer(EditDataProvider *dataProvider) : objectMap(NULL), objectMode(OM_255), dataProvider(dataProvider) {} + +ObjectMOBuffer::~ObjectMOBuffer() +{ + flush(); +} + + +/* Upgrade or downgrade the objectModeType */ +void ObjectMOBuffer::setObjectMode(ObjectMode newType) +{ + if (!objectMap) { + objectMode = newType; + return; + } + + int w = objectMap->get_width (); + int h = objectMap->get_height (); + if (w && h) { + switch (newType) { + case (OM_255): + if (objectMode==OM_65535) { + objectMap->unreference(); + objectMap = Cairo::ImageSurface::create(Cairo::FORMAT_A8, w, h); + } + break; + + case (OM_65535): + if (objectMode==OM_255) { + objectMap->unreference(); + objectMap = Cairo::ImageSurface::create(Cairo::FORMAT_RGB16_565, w, h); + } + break; + } + } + objectMode = newType; +} + +void ObjectMOBuffer::flush() +{ + if (objectMap ) { + objectMap.clear(); + } +} + +EditSubscriber *ObjectMOBuffer::getEditSubscriber () { + if (dataProvider) { + return dataProvider->getCurrSubscriber(); + } else { + return NULL; + } +} + + +// Resize buffers if they already exist +void ObjectMOBuffer::resize(int newWidth, int newHeight) +{ + if (!dataProvider) { + return; + } + + if (const auto currSubscriber = dataProvider->getCurrSubscriber ()) { + if (currSubscriber->getEditingType() == ET_OBJECTS) { + if (objectMap && (objectMap->get_width() != newWidth || objectMap->get_height() != newHeight)) { + objectMap.clear(); + } + + if (!objectMap && newWidth>0 && newHeight>0) { + objectMap = Cairo::ImageSurface::create(objectMode==OM_255?Cairo::FORMAT_A8:Cairo::FORMAT_RGB16_565, newWidth, newHeight); + } + + } else { + flush(); + } + } else { + flush(); + } +} + +int ObjectMOBuffer::getObjectID(const rtengine::Coord& location) +{ + int id = 0; + + if (!objectMap || location.x < 0 || location.y < 0 || location.x >= objectMap->get_width() || location.y >= objectMap->get_height()) { + return -1; + } + + if (objectMode == OM_255) { + id = (unsigned char)(*( objectMap->get_data() + location.y * objectMap->get_stride() + location.x )); + } else { + id = (unsigned short)(*( objectMap->get_data() + location.y * objectMap->get_stride() + location.x )); + } + + return id - 1; +} + +bool ObjectMOBuffer::bufferCreated() +{ + EditSubscriber* subscriber; + + if (dataProvider && (subscriber = dataProvider->getCurrSubscriber())) { + return subscriber->getEditingType() == ET_OBJECTS ? bool(objectMap) : false; + } + + return false; +} + RGBColor Geometry::getInnerLineColor () { RGBColor color; @@ -60,7 +166,7 @@ RGBColor Geometry::getOuterLineColor () return color; } -void Circle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Circle::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_VISIBLE) && state != INSENSITIVE) { RGBColor color; @@ -75,14 +181,14 @@ void Circle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::Edit cr->set_line_width( getOuterLineWidth() ); rtengine::Coord center_ = center; - double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius); + double radius_ = radiusInImageSpace ? coordSystem.scaleValueToCanvas(double(radius)) : double(radius); if (datum == IMAGE) { - coordSystem.imageCoordToScreen(center.x, center.y, center_.x, center_.y); + coordSystem.imageCoordToScreen (center.x, center.y, center_.x, center_.y); } else if (datum == CLICKED_POINT) { - center_ += editBuffer->getDataProvider()->posScreen; + center_ += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + center_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*M_PI); @@ -90,7 +196,7 @@ void Circle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::Edit } } -void Circle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Circle::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if (flags & F_VISIBLE) { if (state != INSENSITIVE) { @@ -108,14 +214,14 @@ void Circle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::Edit cr->set_line_width( innerLineWidth ); rtengine::Coord center_ = center; - double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius); + double radius_ = radiusInImageSpace ? coordSystem.scaleValueToCanvas(double(radius)) : double(radius); if (datum == IMAGE) { - coordSystem.imageCoordToScreen(center.x, center.y, center_.x, center_.y); + coordSystem.imageCoordToScreen (center.x, center.y, center_.x, center_.y); } else if (datum == CLICKED_POINT) { - center_ += editBuffer->getDataProvider()->posScreen; + center_ += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + center_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (filled && state != INSENSITIVE) { @@ -147,24 +253,27 @@ void Circle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::Edit } } -void Circle::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Circle::drawToMOChannel (Cairo::RefPtr &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if (flags & F_HOVERABLE) { cr->set_line_width( getMouseOverLineWidth() ); rtengine::Coord center_ = center; - double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius); + double radius_ = radiusInImageSpace ? coordSystem.scaleValueToCanvas(double(radius)) : double(radius); if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(center.x, center.y, center_.x, center_.y); + coordSystem.imageCoordToCropCanvas (center.x, center.y, center_.x, center_.y); } else if (datum == CLICKED_POINT) { - center_ += editBuffer->getDataProvider()->posScreen; + center_ += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + center_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } - // drawing the lower byte's value - unsigned short a = (id + 1) & 0xFF; - cr->set_source_rgba (0., 0., 0., double(a) / 255.); + // setting the color to the objet's ID + if (objectBuffer->getObjectMode() == OM_255) { + cr->set_source_rgba (0., 0., 0., ((id + 1) & 0xFF) / 255.); + } else { + cr->set_source_rgba (0., 0., 0., (id + 1) / 65535.); + } cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0, 2.*M_PI); if (filled) { @@ -177,28 +286,10 @@ void Circle::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtrstroke(); } - - // drawing the higher byte's value - if (editBuffer->getObjectMode() == OM_65535) { - a = (id + 1) >> 8; - cr2->set_source_rgba (0., 0., 0., double(a) / 255.); - cr2->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0, 2.*M_PI); - - if (filled) { - if (innerLineWidth > 0.) { - cr2->fill_preserve(); - cr2->stroke(); - } else { - cr2->fill(); - } - } else { - cr2->stroke(); - } - } } } -void Line::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Line::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_VISIBLE) && state != INSENSITIVE) { RGBColor color; @@ -216,14 +307,14 @@ void Line::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBu rtengine::Coord end_ = end; if (datum == IMAGE) { - coordSystem.imageCoordToScreen(begin.x, begin.y, begin_.x, begin_.y); - coordSystem.imageCoordToScreen(end.x, end.y, end_.x, end_.y); + coordSystem.imageCoordToScreen (begin.x, begin.y, begin_.x, begin_.y); + coordSystem.imageCoordToScreen (end.x, end.y, end_.x, end_.y); } else if (datum == CLICKED_POINT) { - begin_ += editBuffer->getDataProvider()->posScreen; - end_ += editBuffer->getDataProvider()->posScreen; + begin_ += objectBuffer->getDataProvider()->posScreen; + end_ += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; - end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + begin_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; + end_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } cr->move_to(begin_.x + 0.5, begin_.y + 0.5); @@ -232,7 +323,7 @@ void Line::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBu } } -void Line::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Line::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_VISIBLE) && innerLineWidth > 0.) { if (state != INSENSITIVE) { @@ -253,14 +344,14 @@ void Line::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBu rtengine::Coord end_ = end; if (datum == IMAGE) { - coordSystem.imageCoordToScreen(begin.x, begin.y, begin_.x, begin_.y); - coordSystem.imageCoordToScreen(end.x, end.y, end_.x, end_.y); + coordSystem.imageCoordToScreen (begin.x, begin.y, begin_.x, begin_.y); + coordSystem.imageCoordToScreen (end.x, end.y, end_.x, end_.y); } else if (datum == CLICKED_POINT) { - begin_ += editBuffer->getDataProvider()->posScreen; - end_ += editBuffer->getDataProvider()->posScreen; + begin_ += objectBuffer->getDataProvider()->posScreen; + end_ += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; - end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + begin_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; + end_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } cr->move_to(begin_.x + 0.5, begin_.y + 0.5); @@ -282,9 +373,7 @@ void Line::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBu } } -void Line::drawToMOChannel(Cairo::RefPtr &cr, - Cairo::RefPtr &cr2, unsigned short id, - rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Line::drawToMOChannel(Cairo::RefPtr &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if (flags & F_HOVERABLE) { cr->set_line_width( getMouseOverLineWidth() ); @@ -292,35 +381,29 @@ void Line::drawToMOChannel(Cairo::RefPtr &cr, rtengine::Coord end_ = end; if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(begin.x, begin.y, begin_.x, begin_.y); - coordSystem.imageCoordToCropBuffer(end.x, end.y, end_.x, end_.y); + coordSystem.imageCoordToCropCanvas (begin.x, begin.y, begin_.x, begin_.y); + coordSystem.imageCoordToCropCanvas (end.x, end.y, end_.x, end_.y); } else if (datum == CLICKED_POINT) { - begin_ += editBuffer->getDataProvider()->posScreen; - end_ += editBuffer->getDataProvider()->posScreen; + begin_ += objectBuffer->getDataProvider()->posScreen; + end_ += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; - end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + begin_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; + end_ += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } - // drawing the lower byte's value - unsigned short a = (id + 1) & 0xFF; - cr->set_source_rgba (0., 0., 0., double(a) / 255.); + // setting the color to the objet's ID + if (objectBuffer->getObjectMode() == OM_255) { + cr->set_source_rgba (0., 0., 0., ((id + 1) & 0xFF) / 255.); + } else { + cr->set_source_rgba (0., 0., 0., (id + 1) / 65535.); + } cr->move_to(begin_.x + 0.5, begin_.y + 0.5); cr->line_to(end_.x + 0.5, end_.y + 0.5); cr->stroke(); - - // drawing the higher byte's value - if (editBuffer->getObjectMode() == OM_65535) { - a = (id + 1) >> 8; - cr2->set_source_rgba (0., 0., 0., double(a) / 255.); - cr2->move_to(begin_.x + 0.5, begin_.y + 0.5); - cr2->line_to(end_.x + 0.5, end_.y + 0.5); - cr2->stroke(); - } } } -void Polyline::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Polyline::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_VISIBLE) && state != INSENSITIVE && points.size() > 1) { RGBColor color; @@ -340,11 +423,11 @@ void Polyline::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::Ed currPos = points.at(i); if (datum == IMAGE) { - coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y); + coordSystem.imageCoordToScreen (points.at(i).x, points.at(i).y, currPos.x, currPos.y); } else if (datum == CLICKED_POINT) { - currPos += editBuffer->getDataProvider()->posScreen; + currPos += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + currPos += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (!i) { @@ -363,7 +446,7 @@ void Polyline::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::Ed } } -void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_VISIBLE) && points.size() > 1) { if (state != INSENSITIVE) { @@ -387,11 +470,11 @@ void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::Ed currPos = points.at(i); if (datum == IMAGE) { - coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y); + coordSystem.imageCoordToScreen (points.at(i).x, points.at(i).y, currPos.x, currPos.y); } else if (datum == CLICKED_POINT) { - currPos += editBuffer->getDataProvider()->posScreen; + currPos += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + currPos += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (!i) { @@ -414,11 +497,11 @@ void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::Ed currPos = points.at(i); if (datum == IMAGE) { - coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y); + coordSystem.imageCoordToScreen (points.at(i).x, points.at(i).y, currPos.x, currPos.y); } else if (datum == CLICKED_POINT) { - currPos += editBuffer->getDataProvider()->posScreen; + currPos += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + currPos += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (!i) { @@ -445,25 +528,28 @@ void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::Ed } } -void Polyline::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Polyline::drawToMOChannel (Cairo::RefPtr &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_HOVERABLE) && points.size() > 1) { rtengine::Coord currPos; - // drawing the lower byte's value - unsigned short a = (id + 1) & 0xFF; - cr->set_source_rgba (0., 0., 0., double(a) / 255.); + // setting the color to the objet's ID + if (objectBuffer->getObjectMode() == OM_255) { + cr->set_source_rgba (0., 0., 0., ((id + 1) & 0xFF) / 255.); + } else { + cr->set_source_rgba (0., 0., 0., (id + 1) / 65535.); + } for (unsigned int i = 0; i < points.size(); ++i) { cr->set_line_width( getMouseOverLineWidth() ); currPos = points.at(i); if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(points.at(i).x, points.at(i).y, currPos.x, currPos.y); + coordSystem.imageCoordToCropCanvas (points.at(i).x, points.at(i).y, currPos.x, currPos.y); } else if (datum == CLICKED_POINT) { - currPos += editBuffer->getDataProvider()->posScreen; + currPos += objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + currPos += objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (!i) { @@ -483,42 +569,6 @@ void Polyline::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr } else { cr->stroke(); } - - // drawing the higher byte's value - if (editBuffer->getObjectMode() == OM_65535) { - a = (id + 1) >> 8; - cr2->set_source_rgba (0., 0., 0., double(a) / 255.); - - for (unsigned int i = 0; i < points.size(); ++i) { - cr2->set_line_width( getMouseOverLineWidth() ); - currPos = points.at(i); - - if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(points.at(i).x, points.at(i).y, currPos.x, currPos.y); - } else if (datum == CLICKED_POINT) { - currPos += editBuffer->getDataProvider()->posScreen; - } else if (datum == CURSOR) { - currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; - } - - if (!i) { - cr2->move_to(currPos.x + 0.5, currPos.y + 0.5); - } else { - cr2->line_to(currPos.x + 0.5, currPos.y + 0.5); - } - } - - if (filled) { - if (innerLineWidth > 0.) { - cr2->fill_preserve(); - cr2->stroke(); - } else { - cr2->fill(); - } - } else { - cr2->stroke(); - } - } } } @@ -546,7 +596,7 @@ void Rectangle::setXYXY(rtengine::Coord topLeft, rtengine::Coord bottomRight) this->bottomRight = bottomRight; } -void Rectangle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Rectangle::drawOuterGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if ((flags & F_VISIBLE) && state != INSENSITIVE) { RGBColor color; @@ -563,19 +613,19 @@ void Rectangle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::E rtengine::Coord tl, br; if (datum == IMAGE) { - coordSystem.imageCoordToScreen(topLeft.x, topLeft.y, tl.x, tl.y); + coordSystem.imageCoordToScreen (topLeft.x, topLeft.y, tl.x, tl.y); } else if (datum == CLICKED_POINT) { - tl = topLeft + editBuffer->getDataProvider()->posScreen; + tl = topLeft + objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - tl = topLeft + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + tl = topLeft + objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (datum == IMAGE) { - coordSystem.imageCoordToScreen(bottomRight.x, bottomRight.y, br.x, br.y); + coordSystem.imageCoordToScreen (bottomRight.x, bottomRight.y, br.x, br.y); } else if (datum == CLICKED_POINT) { - br = bottomRight + editBuffer->getDataProvider()->posScreen; + br = bottomRight + objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - br = bottomRight + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + br = bottomRight + objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } cr->rectangle(tl.x + 0.5, tl.y + 0.5, br.x - tl.x, br.y - tl.y); @@ -589,7 +639,7 @@ void Rectangle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::E } } -void Rectangle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Rectangle::drawInnerGeometry(Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if (flags & F_VISIBLE) { if (state != INSENSITIVE) { @@ -609,19 +659,19 @@ void Rectangle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::E rtengine::Coord tl, br; if (datum == IMAGE) { - coordSystem.imageCoordToScreen(topLeft.x, topLeft.y, tl.x, tl.y); + coordSystem.imageCoordToScreen (topLeft.x, topLeft.y, tl.x, tl.y); } else if (datum == CLICKED_POINT) { - tl = topLeft + editBuffer->getDataProvider()->posScreen; + tl = topLeft + objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - tl = topLeft + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + tl = topLeft + objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (datum == IMAGE) { - coordSystem.imageCoordToScreen(bottomRight.x, bottomRight.y, br.x, br.y); + coordSystem.imageCoordToScreen (bottomRight.x, bottomRight.y, br.x, br.y); } else if (datum == CLICKED_POINT) { - br = bottomRight + editBuffer->getDataProvider()->posScreen; + br = bottomRight + objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - br = bottomRight + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + br = bottomRight + objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (filled && state != INSENSITIVE) { @@ -653,7 +703,7 @@ void Rectangle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::E } } -void Rectangle::drawToMOChannel(Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +void Rectangle::drawToMOChannel(Cairo::RefPtr &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) { if (flags & F_HOVERABLE) { cr->set_line_width( getMouseOverLineWidth() ); @@ -661,24 +711,27 @@ void Rectangle::drawToMOChannel(Cairo::RefPtr &cr, Cairo::RefPtr rtengine::Coord tl, br; if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(topLeft.x, topLeft.y, tl.x, tl.y); + coordSystem.imageCoordToCropCanvas (topLeft.x, topLeft.y, tl.x, tl.y); } else if (datum == CLICKED_POINT) { - tl = topLeft + editBuffer->getDataProvider()->posScreen; + tl = topLeft + objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - tl = topLeft + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + tl = topLeft + objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(bottomRight.x, bottomRight.y, br.x, br.y); + coordSystem.imageCoordToCropCanvas (bottomRight.x, bottomRight.y, br.x, br.y); } else if (datum == CLICKED_POINT) { - br = bottomRight + editBuffer->getDataProvider()->posScreen; + br = bottomRight + objectBuffer->getDataProvider()->posScreen; } else if (datum == CURSOR) { - br = bottomRight + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaScreen; + br = bottomRight + objectBuffer->getDataProvider()->posScreen + objectBuffer->getDataProvider()->deltaScreen; } - // drawing the lower byte's value - unsigned short a = (id + 1) & 0xFF; - cr->set_source_rgba (0., 0., 0., double(a) / 255.); + // setting the color to the objet's ID + if (objectBuffer->getObjectMode() == OM_255) { + cr->set_source_rgba (0., 0., 0., ((id + 1) & 0xFF) / 255.); + } else { + cr->set_source_rgba (0., 0., 0., (id + 1) / 65535.); + } cr->rectangle(tl.x + 0.5, tl.y + 0.5, br.x - tl.x, br.y - tl.y); if (filled) { @@ -691,28 +744,298 @@ void Rectangle::drawToMOChannel(Cairo::RefPtr &cr, Cairo::RefPtr } else { cr->stroke(); } + } +} - // drawing the higher byte's value - if (editBuffer->getObjectMode() == OM_65535) { - a = (id + 1) >> 8; - cr2->set_source_rgba (0., 0., 0., double(a) / 255.); - cr->rectangle(tl.x + 0.5, tl.y + 0.5, br.x - tl.x, br.y - tl.y); +void OPIcon::drivenPointToRectangle(const rtengine::Coord &pos, + rtengine::Coord &topLeft, rtengine::Coord &bottomRight, int W, int H) +{ + switch (drivenPoint) { + case (DP_CENTERCENTER): + topLeft.x = pos.x - W / 2; + topLeft.y = pos.y - H / 2; + break; - if (filled) { - if (innerLineWidth > 0.) { - cr2->fill_preserve(); - cr2->stroke(); - } else { - cr2->fill(); - } + case (DP_TOPLEFT): + topLeft.x = pos.x; + topLeft.y = pos.y; + break; + + case (DP_TOPCENTER): + topLeft.x = pos.x - W / 2; + topLeft.y = pos.y; + break; + + case (DP_TOPRIGHT): + topLeft.x = pos.x - W; + topLeft.y = pos.y; + break; + + case (DP_CENTERRIGHT): + topLeft.x = pos.x - W; + topLeft.y = pos.y - H / 2; + break; + + case (DP_BOTTOMRIGHT): + topLeft.x = pos.x - W; + topLeft.y = pos.y - H; + break; + + case (DP_BOTTOMCENTER): + topLeft.x = pos.x - W / 2; + topLeft.y = pos.y - H; + break; + + case (DP_BOTTOMLEFT): + topLeft.x = pos.x; + topLeft.y = pos.y - H; + break; + + case (DP_CENTERLEFT): + topLeft.x = pos.x; + topLeft.y = pos.y - H / 2; + break; + } + + bottomRight.x = topLeft.x + W - 1; + bottomRight.y = topLeft.y + H - 1; +} + +OPIcon::OPIcon(const Cairo::RefPtr &normal, + const Cairo::RefPtr &active, + const Cairo::RefPtr &prelight, + const Cairo::RefPtr &dragged, + const Cairo::RefPtr &insensitive, + DrivenPoint drivenPoint) : + drivenPoint(drivenPoint) +{ + if (normal) { + normalImg = normal; + } + + if (prelight) { + prelightImg = prelight; + } + + if (active) { + activeImg = active; + } + + if (dragged) { + draggedImg = active; + } + + if (insensitive) { + insensitiveImg = insensitive; + } +} + +OPIcon::OPIcon(Glib::ustring normalImage, Glib::ustring activeImage, Glib::ustring prelightImage, + Glib::ustring draggedImage, Glib::ustring insensitiveImage, DrivenPoint drivenPoint) : drivenPoint(drivenPoint) +{ + if (!normalImage.empty()) { + normalImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(normalImage) ); + } + + if (!prelightImage.empty()) { + prelightImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(prelightImage) ); + } + + if (!activeImage.empty()) { + activeImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(activeImage) ); + } + + if (!draggedImage.empty()) { + draggedImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(draggedImage) ); + } + + if (!insensitiveImage.empty()) { + insensitiveImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(insensitiveImage) ); + } +} + +const Cairo::RefPtr OPIcon::getNormalImg() +{ + return normalImg; +} +const Cairo::RefPtr OPIcon::getPrelightImg() +{ + return prelightImg; +} +const Cairo::RefPtr OPIcon::getActiveImg() +{ + return activeImg; +} +const Cairo::RefPtr OPIcon::getDraggedImg() +{ + return draggedImg; +} +const Cairo::RefPtr OPIcon::getInsensitiveImg() +{ + return insensitiveImg; +} + +void OPIcon::drawImage(const Cairo::RefPtr &img, + Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, + EditCoordSystem &coordSystem) +{ + int imgW = img->get_width(); + int imgH = img->get_height(); + + rtengine::Coord pos; + + if (datum == IMAGE) { + coordSystem.imageCoordToScreen(position.x, position.y, pos.x, pos.y); + } else if (datum == CLICKED_POINT) { + pos = position + objectBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) + pos = position + objectBuffer->getDataProvider()->posScreen + + objectBuffer->getDataProvider()->deltaScreen; + + rtengine::Coord tl, br; // Coordinate of the rectangle in the CropBuffer coordinate system + drivenPointToRectangle(pos, tl, br, imgW, imgH); + + cr->set_source(img, tl.x, tl.y); + cr->set_line_width(0.); + cr->rectangle(tl.x, tl.y, imgW, imgH); + cr->fill(); +} + +void OPIcon::drawMOImage(const Cairo::RefPtr &img, Cairo::RefPtr &cr, + unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) +{ + // test of F_HOVERABLE has already been done + + int imgW = img->get_width(); + int imgH = img->get_height(); + + rtengine::Coord pos; + + if (datum == IMAGE) + coordSystem.imageCoordToCropCanvas (position.x, position.y, pos.x, pos.y); + else if (datum == CLICKED_POINT) { + pos = position + objectBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) + pos = position + objectBuffer->getDataProvider()->posScreen + + objectBuffer->getDataProvider()->deltaScreen; + + rtengine::Coord tl, br; // Coordinate of the rectangle in the CropBuffer coordinate system + drivenPointToRectangle(pos, tl, br, imgW, imgH); + + // drawing the lower byte's value + if (objectBuffer->getObjectMode() == OM_255) { + cr->set_source_rgba (0., 0., 0., ((id + 1) & 0xFF) / 255.); + } else { + cr->set_source_rgba (0., 0., 0., (id + 1) / 65535.); + } + cr->set_line_width(0.); + cr->rectangle(tl.x, tl.y, imgW, imgH); + cr->fill(); +} + +void OPIcon::drawOuterGeometry(Cairo::RefPtr &cr, + ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) {} + +void OPIcon::drawInnerGeometry(Cairo::RefPtr &cr, + ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) +{ + if (flags & F_VISIBLE) { + // Here we will handle fall-back solutions + + State tmpState = state; // can be updated through the successive test + + if (tmpState == INSENSITIVE) { + if (!insensitiveImg) { + tmpState = NORMAL; } else { - cr2->stroke(); + OPIcon::drawImage(insensitiveImg, cr, objectBuffer, coordSystem); + return; } } + + if (tmpState == DRAGGED) { + if (!draggedImg) { + tmpState = ACTIVE; + } else { + OPIcon::drawImage(draggedImg, cr, objectBuffer, coordSystem); + return; + } + } + + if (tmpState == ACTIVE) { + if (!activeImg) { + tmpState = PRELIGHT; + } else { + OPIcon::drawImage(activeImg, cr, objectBuffer, coordSystem); + return; + } + } + + if (tmpState == PRELIGHT) { + if (!prelightImg) { + tmpState = NORMAL; + } else { + OPIcon::drawImage(prelightImg, cr, objectBuffer, coordSystem); + return; + } + } + + if (tmpState == NORMAL && normalImg) { + OPIcon::drawImage(normalImg, cr, objectBuffer, coordSystem); + } } } -EditSubscriber::EditSubscriber (EditType editType) : ID(EUID_None), editingType(editType), bufferType(BT_SINGLEPLANE_FLOAT), provider(NULL), dragging(false) {} +void OPIcon::drawToMOChannel(Cairo::RefPtr &cr, unsigned short id, + ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) +{ + if (flags & F_HOVERABLE) { + // Here we will handle fallback solutions + State tmpState = state; + + if (tmpState == INSENSITIVE) { + if (!insensitiveImg) { + tmpState = NORMAL; + } else { + OPIcon::drawMOImage(insensitiveImg, cr, id, objectBuffer, coordSystem); + return; + } + } + + if (tmpState == DRAGGED) { + if (!draggedImg) { + tmpState = ACTIVE; + } else { + OPIcon::drawMOImage(draggedImg, cr, id, objectBuffer, coordSystem); + return; + } + } + + if (tmpState == ACTIVE) { + if (!activeImg) { + tmpState = PRELIGHT; + } else { + OPIcon::drawMOImage(activeImg, cr, id, objectBuffer, coordSystem); + return; + } + } + + if (tmpState == PRELIGHT) { + if (!prelightImg) { + tmpState = NORMAL; + } else { + OPIcon::drawMOImage(prelightImg, cr, id, objectBuffer, coordSystem); + return; + } + } + + if (tmpState == NORMAL && normalImg) { + OPIcon::drawMOImage(normalImg, cr, id, objectBuffer, coordSystem); + } + } +} + +EditSubscriber::EditSubscriber (EditType editType) : ID(EUID_None), editingType(editType), bufferType(BT_SINGLEPLANE_FLOAT), provider(NULL), action(ES_ACTION_NONE) {} void EditSubscriber::setEditProvider(EditDataProvider *provider) { @@ -766,14 +1089,19 @@ EditType EditSubscriber::getEditingType() return editingType; } -BufferType EditSubscriber::getEditBufferType() +BufferType EditSubscriber::getPipetteBufferType() { return bufferType; } bool EditSubscriber::isDragging() { - return dragging; + return action == ES_ACTION_DRAGGING; +} + +bool EditSubscriber::isPicking() +{ + return action == ES_ACTION_PICKING; } //-------------------------------------------------------------------------------------------------- diff --git a/rtgui/edit.h b/rtgui/edit.h index c8b8090fb..c49c45408 100644 --- a/rtgui/edit.h +++ b/rtgui/edit.h @@ -29,11 +29,7 @@ #include "options.h" class EditDataProvider; - -namespace rtengine -{ -class EditBuffer; -} +class EditSubscriber; /** @file * @@ -41,9 +37,6 @@ class EditBuffer; * Subscribers will be tools that need to create some graphics in the preview area, to let the user interact * with it in a more user friendly way. * - * Subscribers will be tools that need to create some graphics in the preview area, to let the user interact - * with it in a more user friendly way. - * * Do not confuse with _local_ editing, which is another topic implemented in another class. The Edit feature * is also not supported in batch editing from the File Browser. * @@ -70,10 +63,10 @@ class EditBuffer; * ### Event handling * * The mouseOver method is called on each mouse movement, excepted when dragging a point. This method can then access - * the pipetteVal array values, which contain the mean of the pixel read in the buffer, or -1 of the cursor is outside + * the pipetteVal array values, which contain the mean of the pixel read in the buffer, or -1 if the cursor is outside * of the image. In this case, EditDataProvider::object is also set to 0 (and 1 if over the image). * - * When the user will click on the left mouse button while pressing the CTRL key, the button1Pressed will be called. + * When the user will click on the left mouse button while pressing the CTRL key, button1Pressed will be called. * Setting "dragging" to true (or false) is not required for the pipette type editing. * * The drag1 method will be called on all subsequent mouse move. The pipetteVal[3] array will already be filled with @@ -84,15 +77,15 @@ class EditBuffer; * * ## Object edition * - * By using this class, object can be drawn and manipulated on the preview. + * By using this class, objects can be drawn and manipulated on the preview. * - * The developer has to handle the buttonPress, buttonRelease, drag and mouseOver method that he needs. There + * The developer has to handle the buttonPress, buttonRelease, drag and mouseOver methods that he needs. There * are buttonPress, buttonRelease and drag methods dedicated to each mouse button, for better flexibility * (e.g.button2Press, button2Release, drag2 will handle event when mouse button 2 is used first). RT actually * does not handle multiple mouse button event (e.g. button1 + button2), only one at a time. The first button pressed * set the mechanism, all other combined button press are ignored. * - * The developer also have to fill 2 display list with object of the Geometry subclass. Each geometrical shape + * The developer also have to fill 2 display list with object of the Geometry subclass. Each geometric shape * _can_ be used in one or the other, or both list at a time. * * The first list (visibleGeometry) is used to be displayed on the preview. The developer will have to set their state @@ -100,10 +93,11 @@ class EditBuffer; * specific values. To be displayed, the F_VISIBLE flag has to be set through the setActive or setVisible methods. * * The second list (mouseOverGeometry) is used in a backbuffer, the color used to draw the shape being the id of the - * mouseOverGeometry. As an example, you could use a circle line to represent the line to the user, but use another - * Circle object, filled, to be used as mouseOver detection. The association between both shape (visible and mouseOver) + * mouseOverGeometry. As an example, you could create a line to be shown in the preview, but create 2 filled Circle object + * to be used as mouseOver detection, one on each end of the line. The association between both shape (visible and mouseOver) * is handled by the developer. To be displayed on this backbuffer, the F_HOVERABLE flag has to be set through the - * setActive or setHoverable methods. + * setActive or setHoverable methods. For overlapping mouse over geometry, the priority is set by the order in the list : + * the last item is detected first (think of it like a stack piled up). * * * ### Event handling @@ -113,17 +107,28 @@ class EditBuffer; * * RT will call the mouseOver method on each mouse movement where no mouse button is pressed. * - * On mouse button press over a mouseOverGeometry, it will call the button press method corresponding to the button - * (e.g. button1Pressed for mouse button 1), with the modifier key as parameter. Any other mouse button pressed at - * the same time will be ignored. It's up to the developer to decide whether it leads to a drag movement or not, - * by setting the "dragging" boolean to true. + * On mouse button press over a mouseOverGeometry (that has F_HOVERABLE set), it will call the button press method corresponding + * to the button (e.g. button1Pressed for mouse button 1), with the modifier key as parameter. Any other mouse button pressed at + * the same time will be ignored. It's up to the developer to decide whether this action is starting a 'drag' or 'pick' action, + * by setting the 'action' parameter to the appropriated value. * - * In this case, RT will then sent drag1 event (to stay with our button 1 pressed example) on each mouse movement. It's up - * to the developer of the tool to handle the dragging. The EditProvider class will help you in this by handling the actual - * position in various coordinate system and ways. + * If the user sets action to ES_ACTION_DRAGGING, RT will then send drag1 events (to stay with our button 1 pressed example) on each + * mouse movement. It's up to the developer of the tool to handle the dragging. The EditProvider class will help you in this by + * handling the actual position in various coordinate system and ways. * * When the user will release the mouse button, RT will call the button1Release event (in our example). The developer have - * then to set the "dragging" flag to false. + * then to set action to ES_ACTION_NONE. + * + * If the user sets action to ES_ACTION_PICKING, RT will keep in memory the mouseOver object that was selected when pressing the mouse + * (e.g. button 1), as well as the modifier keys. + * + * The element is said to be picked when the mouse button is released over the same mouse over object and with the same active + * modifier keys. In this case, the corresponding picked event (e.g. picked1 in our example) and the 'picked' flag will be true. + * If any of those condition is false, picked1 will still be be called to terminate the initiated picking action, but 'picked' + * will be false. This is necessary because the user may want to update the geometry if the picking is aborted. The developer have + * then to set action to ES_ACTION_NONE. + * + * Picking an on-screen element correspond to single-clicking on it. No double click is supported so far. * * Each of these methods have to returns a boolean value saying that the preview has to be refreshed or not (i.e. the displayed * geometry). @@ -141,17 +146,53 @@ class EditBuffer; * the HSV tool, the Hue and Saturation and Value curves are applied on the current state of the image. That's why the pipette * of the H, S and V curve will share the same data of this "current state", otherwise the read value would be wrong. * - * When the mouse button 1 is pressed while pressing the CTRL key, the button1Pressed method will be called. - * * When the Edit process stops, the Subscriber is removed from the DataProvider, so buffers can be freed up. * A new ToolPanelListener::panelChanged event is also thrown to update the preview again, without the tool's - * graphical objects. The Edit button is also toggled off (by the user or programmatically). + * graphical objects. The Edit button is also toggled off (by the user or programatically). * * It means that each Edit buttons toggled on will start an update of the preview which might or might not create * a new History entry, depending on the ProcEvent used. * */ + + +class ObjectMOBuffer +{ +private: + + // Used to draw the objects where the color correspond to the object's ID, in order to find the correct object when hovering + Cairo::RefPtr objectMap; + ObjectMode objectMode; + +protected: + + // To avoid duplicated information, we points to a EditDataProvider that contains the current EditSubscriber + // instead of pointing to the EditSubscriber directly + EditDataProvider* dataProvider; + + void createBuffer(int width, int height); + void resize(int newWidth, int newHeight); + void flush(); + EditSubscriber *getEditSubscriber (); + +public: + explicit ObjectMOBuffer (EditDataProvider *dataProvider); + ~ObjectMOBuffer(); + + EditDataProvider* getDataProvider (); + void setObjectMode (ObjectMode newType); + ObjectMode getObjectMode (); + + Cairo::RefPtr& getObjectMap (); + + // return true if the buffer has been allocated + bool bufferCreated(); + + int getObjectID(const rtengine::Coord& location); +}; + + /** @brief Coordinate system where the widgets will be drawn * * The EditCoordSystem is used to define a screen and an image coordinate system. @@ -167,6 +208,8 @@ public: virtual void screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy) = 0; /// Convert the image coords to the widget's DrawingArea (i.e. preview area) coords virtual void imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) = 0; + /// Convert the image coords to the crop's canvas coords + virtual void imageCoordToCropCanvas (int imgx, int imgy, int& phyx, int& phyy) = 0; /// Convert the image coords to the edit buffer coords virtual void imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy) = 0; /// Convert a size value from the preview's scale to the image's scale @@ -176,11 +219,11 @@ public: /// Convert a size value from the preview's scale to the image's scale virtual double scaleValueToImage (double value) = 0; /// Convert a size value from the image's scale to the preview's scale - virtual int scaleValueToScreen (int value) = 0; + virtual int scaleValueToCanvas (int value) = 0; /// Convert a size value from the image's scale to the preview's scale - virtual float scaleValueToScreen (float value) = 0; + virtual float scaleValueToCanvas (float value) = 0; /// Convert a size value from the image's scale to the preview's scale - virtual double scaleValueToScreen (double value) = 0; + virtual double scaleValueToCanvas (double value) = 0; }; class RGBColor @@ -190,36 +233,16 @@ class RGBColor double b; public: - RGBColor () : r(0.), g(0.), b(0.) {} - explicit RGBColor (double r, double g, double b) : r(r), g(g), b(b) {} - explicit RGBColor (char r, char g, char b) : r(double(r) / 255.), g(double(g) / 255.), b(double(b) / 255.) {} + RGBColor (); + explicit RGBColor (double r, double g, double b); + explicit RGBColor (char r, char g, char b); - void setColor(double r, double g, double b) - { - this->r = r; - this->g = g; - this->b = b; - } + void setColor (double r, double g, double b); + void setColor (char r, char g, char b); - void setColor(char r, char g, char b) - { - this->r = double(r) / 255.; - this->g = double(g) / 255.; - this->b = double(b) / 255.; - } - - double getR() - { - return r; - } - double getG() - { - return g; - } - double getB() - { - return b; - } + double getR (); + double getG (); + double getB (); }; class RGBAColor : public RGBColor @@ -227,26 +250,14 @@ class RGBAColor : public RGBColor double a; public: - RGBAColor () : RGBColor(0., 0., 0.), a(0.) {} - explicit RGBAColor (double r, double g, double b, double a) : RGBColor(r, g, b), a(a) {} - explicit RGBAColor (char r, char g, char b, char a) : RGBColor(r, g, b), a(double(a) / 255.) {} + RGBAColor (); + explicit RGBAColor (double r, double g, double b, double a); + explicit RGBAColor (char r, char g, char b, char a); - void setColor(double r, double g, double b, double a) - { - RGBColor::setColor(r, g, b); - this->a = a; - } + void setColor (double r, double g, double b, double a); + void setColor (char r, char g, char b, char a); - void setColor(char r, char g, char b, char a) - { - RGBColor::setColor(r, g, b); - this->a = double(a) / 255.; - } - - double getA() - { - return a; - } + double getA (); }; /// @brief Displayable and MouseOver geometry base class @@ -297,85 +308,30 @@ public: Datum datum; State state; // set by the Subscriber - Geometry () : innerLineColor(char(255), char(255), char(255)), outerLineColor(char(0), char(0), char(0)), flags(F_VISIBLE | F_HOVERABLE | F_AUTO_COLOR), innerLineWidth(1.5f), datum(IMAGE), state(NORMAL) {} + Geometry (); virtual ~Geometry() {} - void setInnerLineColor (double r, double g, double b) - { - innerLineColor.setColor(r, g, b); - flags &= ~F_AUTO_COLOR; - } - void setInnerLineColor (char r, char g, char b) - { - innerLineColor.setColor(r, g, b); - flags &= ~F_AUTO_COLOR; - } - RGBColor getInnerLineColor (); - void setOuterLineColor (double r, double g, double b) - { - outerLineColor.setColor(r, g, b); - flags &= ~F_AUTO_COLOR; - } - void setOuterLineColor (char r, char g, char b) - { - outerLineColor.setColor(r, g, b); - flags &= ~F_AUTO_COLOR; - } - RGBColor getOuterLineColor (); - double getOuterLineWidth () - { - return double(innerLineWidth) + 2.; - } - double getMouseOverLineWidth () - { - return getOuterLineWidth() + 2.; - } - void setAutoColor (bool aColor) - { - if (aColor) { - flags |= F_AUTO_COLOR; - } else { - flags &= ~F_AUTO_COLOR; - } - } - bool isVisible () - { - return flags & F_VISIBLE; - } - void setVisible (bool visible) - { - if (visible) { - flags |= F_VISIBLE; - } else { - flags &= ~F_VISIBLE; - } - } - bool isHoverable () - { - return flags & F_HOVERABLE; - } - void setHoverable (bool visible) - { - if (visible) { - flags |= F_HOVERABLE; - } else { - flags &= ~F_HOVERABLE; - } - } + void setInnerLineColor (double r, double g, double b); + void setInnerLineColor (char r, char g, char b); + RGBColor getInnerLineColor (); + void setOuterLineColor (double r, double g, double b); + void setOuterLineColor (char r, char g, char b); + RGBColor getOuterLineColor (); + double getOuterLineWidth (); + double getMouseOverLineWidth (); + void setAutoColor (bool aColor); + bool isVisible (); + void setVisible (bool visible); + bool isHoverable (); + void setHoverable (bool visible); + // setActive will enable/disable the visible and hoverable flags in one shot! - void setActive (bool active) - { - if (active) { - flags |= (F_VISIBLE | F_HOVERABLE); - } else { - flags &= ~(F_VISIBLE | F_HOVERABLE); - } - } + void setActive (bool active); - virtual void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *parent, EditCoordSystem &coordSystem) = 0; - virtual void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *parent, EditCoordSystem &coordSystem) = 0; - virtual void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) = 0; + virtual void drawOuterGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) = 0; + virtual void drawInnerGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) = 0; + virtual void drawToMOChannel (Cairo::RefPtr &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) = 0; }; class Circle : public Geometry @@ -386,13 +342,13 @@ public: bool filled; bool radiusInImageSpace; /// If true, the radius depend on the image scale; if false, it is a fixed 'screen' size - Circle () : center(100, 100), radius(10), filled(false), radiusInImageSpace(false) {} - Circle (rtengine::Coord ¢er, int radius, bool filled = false, bool radiusInImageSpace = false) : center(center), radius(radius), filled(filled), radiusInImageSpace(radiusInImageSpace) {} - Circle (int centerX, int centerY, int radius, bool filled = false, bool radiusInImageSpace = false) : center(centerX, centerY), radius(radius), filled(filled), radiusInImageSpace(radiusInImageSpace) {} + Circle (); + Circle (rtengine::Coord& center, int radius, bool filled = false, bool radiusInImageSpace = false); + Circle (int centerX, int centerY, int radius, bool filled = false, bool radiusInImageSpace = false); - void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawOuterGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); + void drawInnerGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); + void drawToMOChannel (Cairo::RefPtr &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); }; class Line : public Geometry @@ -401,13 +357,13 @@ public: rtengine::Coord begin; rtengine::Coord end; - Line () : begin(10, 10), end(100, 100) {} - Line (rtengine::Coord &begin, rtengine::Coord &end) : begin(begin), end(end) {} - Line (int beginX, int beginY, int endX, int endY) : begin(beginX, beginY), end(endX, endY) {} + Line (); + Line (rtengine::Coord& begin, rtengine::Coord& end); + Line (int beginX, int beginY, int endX, int endY); - void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawOuterGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); + void drawInnerGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); + void drawToMOChannel (Cairo::RefPtr &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); }; class Polyline : public Geometry @@ -416,11 +372,11 @@ public: std::vector points; bool filled; - Polyline() : filled(false) {} + Polyline (); - void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawOuterGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); + void drawInnerGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); + void drawToMOChannel (Cairo::RefPtr &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); }; class Rectangle : public Geometry @@ -430,15 +386,59 @@ public: rtengine::Coord bottomRight; bool filled; - Rectangle() : topLeft(0, 0), bottomRight(10, 10), filled(false) {} + Rectangle (); void setXYWH(int left, int top, int width, int height); void setXYXY(int left, int top, int right, int bottom); void setXYWH(rtengine::Coord topLeft, rtengine::Coord widthHeight); void setXYXY(rtengine::Coord topLeft, rtengine::Coord bottomRight); - void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawOuterGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); + void drawInnerGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); + void drawToMOChannel (Cairo::RefPtr &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); +}; + +class OPIcon : public Geometry // OP stands for "On Preview" +{ + +private: + Cairo::RefPtr normalImg; + Cairo::RefPtr prelightImg; + Cairo::RefPtr activeImg; + Cairo::RefPtr draggedImg; + Cairo::RefPtr insensitiveImg; + + static void setPaths(Options &opt); + static void updateImages(); + void changeImage(Glib::ustring &newImage); + static Glib::ustring findIconAbsolutePath(const Glib::ustring &iconFName); + void drawImage (const Cairo::RefPtr &img, Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); + void drawMOImage (const Cairo::RefPtr &img, Cairo::RefPtr &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); + void drivenPointToRectangle(const rtengine::Coord &pos, rtengine::Coord &topLeft, rtengine::Coord &bottomRight, int W, int H); + +public: + DrivenPoint drivenPoint; + rtengine::Coord position; + + OPIcon (const Cairo::RefPtr &normal, + const Cairo::RefPtr &active, + const Cairo::RefPtr &prelight = {}, + const Cairo::RefPtr &dragged = {}, + const Cairo::RefPtr &insensitive = {}, + DrivenPoint drivenPoint = DP_CENTERCENTER); + OPIcon (Glib::ustring normalImage, Glib::ustring activeImage, Glib::ustring prelightImage = "", Glib::ustring draggedImage = "", Glib::ustring insensitiveImage = "", DrivenPoint drivenPoint = DP_CENTERCENTER); + const Cairo::RefPtr getNormalImg(); + const Cairo::RefPtr getPrelightImg(); + const Cairo::RefPtr getActiveImg(); + const Cairo::RefPtr getDraggedImg(); + const Cairo::RefPtr getInsensitiveImg(); + void drawOuterGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); + void drawInnerGeometry (Cairo::RefPtr &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); + void drawToMOChannel (Cairo::RefPtr &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem); +}; + +class OPAdjuster : public Geometry // OP stands for "On Preview" +{ + }; /// @brief Method for client tools needing Edit information @@ -456,127 +456,108 @@ private: protected: std::vector visibleGeometry; /// displayed geometry std::vector mouseOverGeometry; /// mouseOver geometry, drawn in a hidden buffer - bool dragging; /// in object mode, set this to true in buttonPressed events to start dragging and ask for drag event (ignored in pipette mode) + enum { + ES_ACTION_NONE, /// + ES_ACTION_DRAGGING, /// set action to this value in the buttonPressed event to start dragging and ask for drag event + ES_ACTION_PICKING /// set action to this value in the buttonPressed event whenever the user is picking something through a single click. In this case, the pickX events will be called INSTEAD of buttonXReleased ! + } action; /// object mode only, ignored in Pipette mode public: EditSubscriber (EditType editType); virtual ~EditSubscriber () {} - void setEditProvider(EditDataProvider *provider); - EditDataProvider* getEditProvider() - { - return provider; - } - void setEditID(EditUniqueID ID, BufferType buffType); - bool isCurrentSubscriber(); - virtual void subscribe(); - virtual void unsubscribe(); - virtual void switchOffEditMode (); /// Occurs when the user want to stop the editing mode - EditUniqueID getEditID(); - EditType getEditingType(); - BufferType getEditBufferType(); - bool isDragging(); /// Returns true if something is being dragged and drag events has to be sent (object mode only) + void setEditProvider(EditDataProvider *provider); + EditDataProvider* getEditProvider (); + void setEditID(EditUniqueID ID, BufferType buffType); + bool isCurrentSubscriber(); + virtual void subscribe(); + virtual void unsubscribe(); + virtual void switchOffEditMode (); /// Occurs when the user want to stop the editing mode + EditUniqueID getEditID(); + EditType getEditingType(); + BufferType getPipetteBufferType(); + bool isDragging(); /// Returns true if something is being dragged and drag events has to be sent (object mode only) + bool isPicking(); /// Returns true if something is being picked /** @brief Get the cursor to be displayed when above handles @param objectID object currently "hovered" */ - virtual CursorShape getCursor(int objectID) - { - return CSOpenHand; - } + virtual CursorShape getCursor (const int objectID); /** @brief Triggered when the mouse is moving over an object This method is also triggered when the cursor is moving over the image in ET_PIPETTE mode @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) - @param editBuffer buffer to get the pipette values and the from @return true if the preview has to be redrawn, false otherwise */ - virtual bool mouseOver(int modifierKey) - { - return false; - } + virtual bool mouseOver (const int modifierKey); /** @brief Triggered when mouse button 1 is pressed, together with the CTRL modifier key if the subscriber is of type ET_PIPETTE Once the key is pressed, RT will enter in drag1 mode on subsequent mouse movements @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) @return true if the preview has to be redrawn, false otherwise */ - virtual bool button1Pressed(int modifierKey) - { - return false; - } + virtual bool button1Pressed (const int modifierKey); /** @brief Triggered when mouse button 1 is released @return true if the preview has to be redrawn, false otherwise */ - virtual bool button1Released() - { - return false; - } + virtual bool button1Released (); /** @brief Triggered when mouse button 2 is pressed (middle button) Once the key is pressed, RT will enter in drag2 mode on subsequent mouse movements @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) @return true if the preview has to be redrawn, false otherwise */ - virtual bool button2Pressed(int modifierKey) - { - return false; - } + virtual bool button2Pressed (const int modifierKey); /** @brief Triggered when mouse button 2 is released (middle button) @return true if the preview has to be redrawn, false otherwise */ - virtual bool button2Released() - { - return false; - } + virtual bool button2Released (); /** @brief Triggered when mouse button 3 is pressed (right button) Once the key is pressed, RT will enter in drag3 mode on subsequent mouse movements @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) @return true if the preview has to be redrawn, false otherwise */ - virtual bool button3Pressed(int modifierKey) - { - return false; - } + virtual bool button3Pressed (const int modifierKey); /** @brief Triggered when mouse button 3 is released (right button) @return true if the preview has to be redrawn, false otherwise */ - virtual bool button3Released() - { - return false; - } + virtual bool button3Released (); /** @brief Triggered when the user is moving while holding down mouse button 1 @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) @return true if the preview has to be redrawn, false otherwise */ - virtual bool drag1(int modifierKey) - { - return false; - } + virtual bool drag1 (const int modifierKey); /** @brief Triggered when the user is moving while holding down mouse button 2 @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) @return true if the preview has to be redrawn, false otherwise */ - virtual bool drag2(int modifierKey) - { - return false; - } + virtual bool drag2 (const int modifierKey); /** @brief Triggered when the user is moving while holding down mouse button 3 @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) @return true if the preview has to be redrawn, false otherwise */ - virtual bool drag3(int modifierKey) - { - return false; - } + virtual bool drag3 (const int modifierKey); + + /** @brief Triggered when the user is releasing mouse button 1 while in action==ES_ACTION_PICKING mode + No modifier key is provided, since having a different modifier key than on button press will set picked to false. + @param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys. + If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected. + @return true if the preview has to be redrawn, false otherwise */ + virtual bool pick1 (const bool picked); + + /** @brief Triggered when the user is releasing mouse button 2 while in action==ES_ACTION_PICKING mode + @param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys. + If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected. + @return true if the preview has to be redrawn, false otherwise */ + virtual bool pick2 (const bool picked); + + /** @brief Triggered when the user is releasing mouse button 3 while in action==ES_ACTION_PICKING mode + @param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys. + If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected. + @return true if the preview has to be redrawn, false otherwise */ + virtual bool pick3 (const bool picked); /** @brief Get the geometry to be shown to the user */ - const std::vector & getVisibleGeometry() - { - return visibleGeometry; - } + const std::vector& getVisibleGeometry (); /** @brief Get the geometry to be drawn in the "mouse over" channel, hidden from the user */ - const std::vector & getMouseOverGeometry() - { - return mouseOverGeometry; - } + const std::vector& getMouseOverGeometry (); }; /** @brief Class to handle the furniture of data to the subscribers. @@ -608,12 +589,267 @@ public: virtual void unsubscribe(); /// Occurs when the subscriber has been switched off first virtual void switchOffEditMode (); /// Occurs when the user want to stop the editing mode virtual CursorShape getCursor(int objectID); - int getPipetteRectSize() - { - return 8; // TODO: make a GUI - } + int getPipetteRectSize (); EditSubscriber* getCurrSubscriber(); virtual void getImageSize (int &w, int&h) = 0; }; +inline EditDataProvider* ObjectMOBuffer::getDataProvider () { + return dataProvider; +} + +inline ObjectMode ObjectMOBuffer::getObjectMode () { + return objectMode; +} + +inline Cairo::RefPtr& ObjectMOBuffer::getObjectMap () { + return objectMap; +} + +inline void RGBColor::setColor (double r, double g, double b) { + this->r = r; + this->g = g; + this->b = b; +} + +inline void RGBColor::setColor (char r, char g, char b) { + this->r = double (r) / 255.; + this->g = double (g) / 255.; + this->b = double (b) / 255.; +} + +inline double RGBColor::getR () { + return r; +} + +inline double RGBColor::getG () { + return g; +} + +inline double RGBColor::getB () { + return b; +} + +inline void RGBAColor::setColor (double r, double g, double b, double a) { + RGBColor::setColor (r, g, b); + this->a = a; +} + +inline void RGBAColor::setColor (char r, char g, char b, char a) { + RGBColor::setColor (r, g, b); + this->a = double (a) / 255.; +} + +inline double RGBAColor::getA () { + return a; +} + +inline void Geometry::setInnerLineColor (double r, double g, double b) { + innerLineColor.setColor (r, g, b); + flags &= ~F_AUTO_COLOR; +} + +inline void Geometry::setInnerLineColor (char r, char g, char b) { + innerLineColor.setColor (r, g, b); + flags &= ~F_AUTO_COLOR; +} + +inline void Geometry::setOuterLineColor (double r, double g, double b) { + outerLineColor.setColor (r, g, b); + flags &= ~F_AUTO_COLOR; +} + +inline double Geometry::getOuterLineWidth () { + return double (innerLineWidth) + 2.; +} + +inline void Geometry::setOuterLineColor (char r, char g, char b) { + outerLineColor.setColor (r, g, b); + flags &= ~F_AUTO_COLOR; +} + +inline double Geometry::getMouseOverLineWidth () { + return getOuterLineWidth () + 2.; +} + +inline void Geometry::setAutoColor (bool aColor) { + if (aColor) { + flags |= F_AUTO_COLOR; + } else { + flags &= ~F_AUTO_COLOR; + } +} + +inline bool Geometry::isVisible () { + return flags & F_VISIBLE; +} + +inline void Geometry::setVisible (bool visible) { + if (visible) { + flags |= F_VISIBLE; + } else { + flags &= ~F_VISIBLE; + } +} + +inline bool Geometry::isHoverable () { + return flags & F_HOVERABLE; +} + +inline void Geometry::setHoverable (bool hoverable) { + if (hoverable) { + flags |= F_HOVERABLE; + } else { + flags &= ~F_HOVERABLE; + } +} + +inline void Geometry::setActive (bool active) { + if (active) { + flags |= (F_VISIBLE | F_HOVERABLE); + } else { + flags &= ~(F_VISIBLE | F_HOVERABLE); + } +} + +inline EditDataProvider* EditSubscriber::getEditProvider () { + return provider; +} + +inline CursorShape EditSubscriber::getCursor (const int objectID) { + return CSOpenHand; +} + +inline bool EditSubscriber::mouseOver (const int modifierKey) { + return false; +} + +inline bool EditSubscriber::button1Pressed (const int modifierKey) { + return false; +} + +inline bool EditSubscriber::button1Released () { + return false; +} + +inline bool EditSubscriber::button2Pressed (const int modifierKey) { + return false; +} + +inline bool EditSubscriber::button2Released () { + return false; +} + +inline bool EditSubscriber::button3Pressed (const int modifierKey) { + return false; +} + +inline bool EditSubscriber::button3Released () { + return false; +} + +inline bool EditSubscriber::drag1 (const int modifierKey) { + return false; +} + +inline bool EditSubscriber::drag2 (const int modifierKey) { + return false; +} + +inline bool EditSubscriber::drag3 (const int modifierKey) { + return false; +} + +inline bool EditSubscriber::pick1 (const bool picked) { + return false; +} + +inline bool EditSubscriber::pick2 (const bool picked) { + return false; +} + +inline bool EditSubscriber::pick3 (const bool picked) { + return false; +} + +inline const std::vector& EditSubscriber::getVisibleGeometry () { + return visibleGeometry; +} + +inline const std::vector& EditSubscriber::getMouseOverGeometry () { + return mouseOverGeometry; +} + +inline int EditDataProvider::getPipetteRectSize () { + return 8; // TODO: make a GUI +} + +inline Geometry::Geometry () : + innerLineColor (char (255), char (255), char (255)), outerLineColor ( + char (0), char (0), char (0)), flags ( + F_VISIBLE | F_HOVERABLE | F_AUTO_COLOR), innerLineWidth (1.5f), datum ( + IMAGE), state (NORMAL) { +} + +inline Circle::Circle () : + center (100, 100), radius (10), filled (false), radiusInImageSpace ( + false) { +} + +inline Rectangle::Rectangle () : + topLeft (0, 0), bottomRight (10, 10), filled (false) { +} + +inline Polyline::Polyline () : + filled (false) { +} + +inline Line::Line () : + begin (10, 10), end (100, 100) { +} + +inline RGBAColor::RGBAColor () : + RGBColor (0., 0., 0.), a (0.) { +} + +inline RGBColor::RGBColor () : + r (0.), g (0.), b (0.) { +} + +inline RGBColor::RGBColor (double r, double g, double b) : + r (r), g (g), b (b) { +} + +inline RGBColor::RGBColor (char r, char g, char b) : + r (double (r) / 255.), g (double (g) / 255.), b (double (b) / 255.) { +} + +inline RGBAColor::RGBAColor (double r, double g, double b, double a) : + RGBColor (r, g, b), a (a) { +} + +inline RGBAColor::RGBAColor (char r, char g, char b, char a) : + RGBColor (r, g, b), a (double (a) / 255.) { +} + +inline Circle::Circle (rtengine::Coord& center, int radius, bool filled, + bool radiusInImageSpace) : + center (center), radius (radius), filled (filled), radiusInImageSpace ( + radiusInImageSpace) { +} + +inline Circle::Circle (int centerX, int centerY, int radius, bool filled, + bool radiusInImageSpace) : + center (centerX, centerY), radius (radius), filled (filled), radiusInImageSpace ( + radiusInImageSpace) { +} + +inline Line::Line (rtengine::Coord& begin, rtengine::Coord& end) : + begin (begin), end (end) { +} + +inline Line::Line (int beginX, int beginY, int endX, int endY) : + begin (beginX, beginY), end (endX, endY) { +} + #endif diff --git a/rtgui/editenums.h b/rtgui/editenums.h index e51918426..557912222 100644 --- a/rtgui/editenums.h +++ b/rtgui/editenums.h @@ -20,7 +20,8 @@ #define _EDITENUMS_ enum ImgEditState {SNormal, SCropMove, SHandMove, SResizeW1, SResizeW2, SResizeH1, SResizeH2, SResizeTL, SResizeTR, SResizeBL, SResizeBR, - SCropSelecting, SRotateSelecting, SCropWinMove, SCropFrameMove, SCropImgMove, SCropWinResize, SObservedMove, SEditDrag1, SEditDrag2, SEditDrag3 + SCropSelecting, SRotateSelecting, SCropWinMove, SCropFrameMove, SCropImgMove, SCropWinResize, SObservedMove, + SEditDrag1, SEditDrag2, SEditDrag3, SEditPick1, SEditPick2, SEditPick3 }; enum CursorArea {CropWinButtons, CropToolBar, CropImage, CropBorder, CropTop, CropTopLeft, CropTopRight, CropBottom, CropBottomLeft, CropBottomRight, CropLeft, CropRight, CropInside, CropResize, CropObserved diff --git a/rtgui/editid.h b/rtgui/editid.h index 6bc808c87..c4f9315c0 100644 --- a/rtgui/editid.h +++ b/rtgui/editid.h @@ -57,9 +57,9 @@ enum EditType { /// @brief Buffer type for ET_PIPETTE type editing enum BufferType { - BT_IMAGEFLOAT, - BT_LABIMAGE, - BT_SINGLEPLANE_FLOAT + BT_IMAGEFLOAT, /// Imagefloat buffer type (3 channels of float values) + BT_LABIMAGE, /// LabImage buffer type (3 channels of float values) + BT_SINGLEPLANE_FLOAT /// All purpose, 1 channel buffer of float values }; /// @brief Number of object to be handled (for optimization purpose) diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index b9f123ac5..80dc3dfae 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -18,18 +18,20 @@ * along with RawTherapee. If not, see . */ #include "editorpanel.h" -#include "options.h" -#include "progressconnector.h" -#include "rtwindow.h" -#include "guiutils.h" -#include "procparamchangers.h" -#include "../rtengine/safegtk.h" + +#include + #include "../rtengine/imagesource.h" #include "../rtengine/iccstore.h" #include "soundman.h" #include "rtimage.h" -#include +#include "rtwindow.h" +#include "guiutils.h" #include "popupbutton.h" +#include "options.h" +#include "progressconnector.h" +#include "procparamchangers.h" +#include "placesbrowser.h" using namespace rtengine::procparams; @@ -489,7 +491,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) show_all (); /* // save as dialog - if (safe_file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) + if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) saveAsDialog = new SaveAsDialog (options.lastSaveAsPath); else saveAsDialog = new SaveAsDialog (safe_get_user_picture_dir()); @@ -786,7 +788,7 @@ void EditorPanel::close () navigator->previewWindow->setPreviewHandler (NULL); // If the file was deleted somewhere, the openThm.descreaseRef delete the object, but we don't know here - if (safe_file_test(fname, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test(fname, Glib::FILE_TEST_EXISTS)) { openThm->removeThumbnailListener (this); openThm->decreaseRef (); } @@ -800,7 +802,7 @@ void EditorPanel::saveProfile () } // If the file was deleted, do not generate ghost entries - if (safe_file_test(fname, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test(fname, Glib::FILE_TEST_EXISTS)) { ProcParams params; ipc->getParams (¶ms); @@ -1540,10 +1542,10 @@ void EditorPanel::saveAsPressed () SaveAsDialog* saveAsDialog; - if (safe_file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) { saveAsDialog = new SaveAsDialog (options.lastSaveAsPath); } else { - saveAsDialog = new SaveAsDialog (safe_get_user_picture_dir()); + saveAsDialog = new SaveAsDialog (PlacesBrowser::userPicturesDir ()); } saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight); @@ -1587,7 +1589,7 @@ void EditorPanel::saveAsPressed () fnameTemp = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir, dstfname), tries, dstext); } - if (!safe_file_test (fnameTemp, Glib::FILE_TEST_EXISTS)) { + if (!Glib::file_test (fnameTemp, Glib::FILE_TEST_EXISTS)) { fnameOut = fnameTemp; fnameOK = true; break; @@ -1700,7 +1702,7 @@ bool EditorPanel::idle_sendToGimp( ProgressConnector *pc, G int tries = 1; - while (safe_file_test (fileName, Glib::FILE_TEST_EXISTS) && tries < 1000) { + while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries < 1000) { fileName = Glib::ustring::compose("%1-%2.%3", fname, tries, sf.format); tries++; } @@ -1737,99 +1739,21 @@ bool EditorPanel::idle_sentToGimp(ProgressConnector *pc, rtengine::IImage16 parent->setProgressStr(""); parent->setProgress(0.); bool success = false; - Glib::ustring cmdLine; - Glib::ustring executable; - // start gimp if (options.editorToSendTo == 1) { -#ifdef WIN32 - executable = Glib::build_filename (Glib::build_filename(options.gimpDir, "bin"), "gimp-win-remote"); - cmdLine = Glib::ustring("\"") + executable + Glib::ustring("\" gimp-2.4.exe ") + Glib::ustring("\"") + filename + Glib::ustring("\""); - - if ( safe_file_test(executable, (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_EXECUTABLE)) ) { - success = safe_spawn_command_line_async (cmdLine); - } - -#elif defined __APPLE__ - cmdLine = Glib::ustring("open -a /Applications/GIMP.app \'") + filename + Glib::ustring("\'"); - success = safe_spawn_command_line_async (cmdLine); - std::cout << cmdLine << std::endl; -#else - cmdLine = Glib::ustring("gimp \"") + filename + Glib::ustring("\""); - success = safe_spawn_command_line_async (cmdLine); - std::cout << cmdLine << std::endl; -#endif - - if (!success) { -#ifdef WIN32 - int ver = 12; - - while (!success && ver) { - executable = Glib::build_filename (Glib::build_filename(options.gimpDir, "bin"), Glib::ustring::compose(Glib::ustring("gimp-2.%1.exe"), ver)); - - if ( safe_file_test(executable, (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_EXECUTABLE)) ) { - cmdLine = Glib::ustring("\"") + executable + Glib::ustring("\" \"") + filename + Glib::ustring("\""); - success = safe_spawn_command_line_async (cmdLine); - } - - ver--; - } - -#elif defined __APPLE__ - cmdLine = Glib::ustring("open -a /Applications/Gimp.app/Contents/Resources/start \'") + filename + Glib::ustring("\'"); - success = safe_spawn_command_line_async (cmdLine); - std::cout << cmdLine << std::endl; -#else - cmdLine = Glib::ustring("gimp-remote \"") + filename + Glib::ustring("\""); - success = safe_spawn_command_line_async (cmdLine); - std::cout << cmdLine << std::endl; -#endif - } + success = ExtProgStore::openInGimp (filename); } else if (options.editorToSendTo == 2) { -#ifdef WIN32 - executable = Glib::build_filename(options.psDir, "Photoshop.exe"); - - if ( safe_file_test(executable, (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_EXECUTABLE)) ) { - cmdLine = Glib::ustring("\"") + executable + Glib::ustring("\" \"") + filename + Glib::ustring("\""); - success = safe_spawn_command_line_async (cmdLine); - } - -#else -#ifdef __APPLE__ - cmdLine = Glib::ustring("open -a \'") + Glib::build_filename(options.psDir, "Photoshop.app\' ") + Glib::ustring("\'") + filename + Glib::ustring("\'"); -#else - cmdLine = Glib::ustring("\"") + Glib::build_filename(options.psDir, "Photoshop.exe") + Glib::ustring("\" \"") + filename + Glib::ustring("\""); -#endif - success = safe_spawn_command_line_async (cmdLine); - std::cout << cmdLine << std::endl; -#endif + success = ExtProgStore::openInPhotoshop (filename); } else if (options.editorToSendTo == 3) { -#ifdef WIN32 - - if ( safe_file_test(options.customEditorProg, (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_EXECUTABLE)) ) { - cmdLine = Glib::ustring("\"") + options.customEditorProg + Glib::ustring("\" \"") + filename + Glib::ustring("\""); - success = safe_spawn_command_line_async (cmdLine); - } - -#else -#ifdef __APPLE__ - cmdLine = options.customEditorProg + Glib::ustring(" \"") + filename + Glib::ustring("\""); -#else - cmdLine = Glib::ustring("\"") + options.customEditorProg + Glib::ustring("\" \"") + filename + Glib::ustring("\""); -#endif - success = safe_spawn_command_line_async (cmdLine); - std::cout << cmdLine << std::endl; -#endif + success = ExtProgStore::openInCustomEditor (filename); } if (!success) { - Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, M("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd->set_secondary_text (M("MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY")); - msgd->set_title (M("MAIN_BUTTON_SENDTOEDITOR")); - msgd->run (); - delete msgd; + Gtk::MessageDialog msgd (*parent, M("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.set_secondary_text (M("MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY")); + msgd.set_title (M("MAIN_BUTTON_SENDTOEDITOR")); + msgd.run (); } - } return false; diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 987cd42d7..8c39edc02 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -17,7 +17,7 @@ * along with RawTherapee. If not, see . */ #include "exifpanel.h" -#include "../rtengine/safegtk.h" + #include "guiutils.h" #include "rtimage.h" @@ -47,9 +47,9 @@ ExifPanel::ExifPanel () : idata(NULL) exifTreeModel = Gtk::TreeStore::create(exifColumns); exifTree->set_model (exifTreeModel); - delicon = safe_create_from_file ("gtk-close.png"); - keepicon = safe_create_from_file ("gtk-apply.png"); - editicon = safe_create_from_file ("gtk-add.png"); + 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 ()); diff --git a/rtgui/exportpanel.cc b/rtgui/exportpanel.cc index 67ea092f2..2e25ab6cf 100644 --- a/rtgui/exportpanel.cc +++ b/rtgui/exportpanel.cc @@ -151,12 +151,12 @@ ExportPanel::ExportPanel () : listener (NULL) MaxWidth->set_digits (0); MaxWidth->set_increments (1, 100); MaxWidth->set_value (options.fastexport_resize_width); - MaxWidth->set_range (32, 3000); + MaxWidth->set_range (32, 10000); MaxHeight->set_digits (0); MaxHeight->set_increments (1, 100); MaxHeight->set_value (options.fastexport_resize_height); - MaxHeight->set_range (32, 3000); + MaxHeight->set_range (32, 10000); // Buttons btnFastExport = Gtk::manage ( new Gtk::Button (M("EXPORT_PUTTOQUEUEFAST")) ); diff --git a/rtgui/extprog.cc b/rtgui/extprog.cc index b6ef31255..4f0018ab9 100644 --- a/rtgui/extprog.cc +++ b/rtgui/extprog.cc @@ -16,183 +16,317 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#include - #include "extprog.h" -#include "multilangmgr.h" -#include "../rtengine/safegtk.h" + +#include +#include + #ifdef WIN32 #include -// for GCC32 -#ifndef _WIN32_IE -#define _WIN32_IE 0x0600 -#endif #include #endif -using namespace std; +#include "options.h" +#include "multilangmgr.h" -ExtProgAction::ExtProgAction() {} - -ExtProgAction::ExtProgAction(const ExtProgAction* other, int target) - : target(target), filePathEXE(other->filePathEXE), preparams(other->preparams), name(other->name) { } - -Glib::ustring ExtProgAction::GetFullName() +Glib::ustring ExtProgAction::getFullName () const { return name + " [" + M(Glib::ustring::compose("EXTPROGTARGET_%1", target)) + "]"; } -bool ExtProgAction::Execute(std::vector fileNames) +bool ExtProgAction::execute (const std::vector& fileNames) const { - if (fileNames.empty()) { + if (fileNames.empty ()) { return false; } - // Check if they all exists (maybe not precessed yet) - for (int i = 0; i < fileNames.size(); i++) { - if (!safe_file_test(fileNames[i], Glib::FILE_TEST_EXISTS)) { - Gtk::MessageDialog msgd (M("MAIN_MSG_IMAGEUNPROCESSED"), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); - return false; + // Check if they all exists as they may not be processed yet. + for (const auto& fileName : fileNames) { + + if (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS)) { + continue; } + + Gtk::MessageDialog (M("MAIN_MSG_IMAGEUNPROCESSED"), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true).run (); + return false; } Glib::ustring cmdLine = "\"" + filePathEXE + "\""; - if (preparams.length() > 0) { + if (!preparams.empty()) { cmdLine += " " + preparams; } - for (int i = 0; i < fileNames.size(); i++) { - cmdLine += " \"" + fileNames[i] + "\""; + for (const auto& fileName : fileNames) { + cmdLine += " \"" + fileName + "\""; } - return safe_spawn_command_line_async (cmdLine); + return ExtProgStore::spawnCommandAsync (cmdLine); } - -// Generates as singleton ExtProgStore* ExtProgStore::getInstance() { static ExtProgStore instance_; return &instance_; } -ExtProgStore::~ExtProgStore() -{ - for (list::iterator it = lActions.begin(); it != lActions.end(); it++) { - delete *it; - } -} - // Reads all profiles from the given profiles dir void ExtProgStore::init () { MyMutex::MyLock lock(mtx); - lActions.clear(); + actions.clear (); #ifdef WIN32 - SearchProg("Photoshop", "Adobe\\Adobe Photoshop CS%1 (64 Bit)\\Photoshop.exe", "Adobe\\Adobe Photoshop CS%1\\Photoshop.exe", 9, false, true); - SearchProg("Photomatix Pro", "PhotomatixPro%1\\PhotomatixPro.exe", "", 9, true, true); - SearchProg("Paint.NET", "Paint.NET\\PaintDotNet.exe", "", 0, false, true); - SearchProg("MS Image Composition Editor", "Microsoft Research\\Image Composite Editor\\ICE.exe", "", 0, false, true); - SearchProg("PTGui", "PTGui\\PTGui.exe", "", 0, false, true); - SearchProg("GeoSetter", "GeoSetter\\GeoSetter.exe", "", 0, true, true); - SearchProg("FastStone Image Viewer", "FastStone Image Viewer\\FSViewer.exe", "", 0, true, true); - SearchProg("FastPictureViewer", "FastPictureViewer\\FastPictureViewer.exe", "", 0, true, true); + // Please do not add obscure little tools here, only widely used programs. + // They should also have a proper setup program and therefore a standard path. - if (!SearchProg("Autopano Giga 3", "Kolor\\Autopano Giga 3.%1\\AutopanoGiga_x64.exe", "Kolor\\Autopano Giga 3.%1\\AutopanoGiga.exe", 15, true, true)) { - if ( !SearchProg("Autopano Pro 3", "Kolor\\Autopano Pro 3.%1\\AutopanoPro_x64.exe", "Kolor\\Autopano Pro 3.%1\\AutopanoPro.exe", 15, true, true)) { - if (!SearchProg("Autopano Giga 2", "Kolor\\Autopano Giga 2.%1\\AutopanoGiga_x64.exe", "Kolor\\Autopano Giga 2.%1\\AutopanoGiga.exe", 6, true, true)) { - SearchProg("Autopano Pro 2", "Kolor\\Autopano Pro 2.%1\\AutopanoPro_x64.exe", "Kolor\\Autopano Pro 2.%1\\AutopanoPro.exe", 6, true, true); + searchProgram ("Photoshop", "Adobe\\Adobe Photoshop CS%1 (64 Bit)\\Photoshop.exe", "Adobe\\Adobe Photoshop CS%1\\Photoshop.exe", 9, false, true); + searchProgram ("Photomatix Pro", "PhotomatixPro%1\\PhotomatixPro.exe", "", 9, true, true); + searchProgram ("Paint.NET", "Paint.NET\\PaintDotNet.exe", "", 0, false, true); + searchProgram ("MS Image Composition Editor", "Microsoft Research\\Image Composite Editor\\ICE.exe", "", 0, false, true); + searchProgram ("PTGui", "PTGui\\PTGui.exe", "", 0, false, true); + searchProgram ("GeoSetter", "GeoSetter\\GeoSetter.exe", "", 0, true, true); + searchProgram ("FastStone Image Viewer", "FastStone Image Viewer\\FSViewer.exe", "", 0, true, true); + searchProgram ("FastPictureViewer", "FastPictureViewer\\FastPictureViewer.exe", "", 0, true, true); + + if (!searchProgram ("Autopano Giga 3", "Kolor\\Autopano Giga 3.%1\\AutopanoGiga_x64.exe", "Kolor\\Autopano Giga 3.%1\\AutopanoGiga.exe", 15, true, true)) { + if (!searchProgram ("Autopano Pro 3", "Kolor\\Autopano Pro 3.%1\\AutopanoPro_x64.exe", "Kolor\\Autopano Pro 3.%1\\AutopanoPro.exe", 15, true, true)) { + if (!searchProgram ("Autopano Giga 2", "Kolor\\Autopano Giga 2.%1\\AutopanoGiga_x64.exe", "Kolor\\Autopano Giga 2.%1\\AutopanoGiga.exe", 6, true, true)) { + searchProgram ("Autopano Pro 2", "Kolor\\Autopano Pro 2.%1\\AutopanoPro_x64.exe", "Kolor\\Autopano Pro 2.%1\\AutopanoPro.exe", 6, true, true); } } } - // DO NOT add obscure little tools here, only widely used programs with proper setup program to have a standard path #endif } -bool ExtProgStore::SearchProg(Glib::ustring name, Glib::ustring exePath, Glib::ustring exePath86, int maxVer, bool allowRaw, bool allowQueueProcess) +bool ExtProgStore::searchProgram (const Glib::ustring& name, + const Glib::ustring& exePath, + const Glib::ustring& exePath86, + int maxVer, + bool allowRaw, + bool allowQueueProcess) { - bool found = false; #ifdef WIN32 // get_user_special_dir crashes on some Windows configurations. - // so we use the safe native functions here static Glib::ustring progFilesDir, progFilesDirx86; - if (progFilesDir.empty()) { - WCHAR pathW[MAX_PATH] = {0}; + if (progFilesDir.empty ()) { + WCHAR pathW[MAX_PATH]; char pathA[MAX_PATH]; - // First prio folder (64bit, otherwise 32bit) - if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_PROGRAM_FILES, false)) { - char pathA[MAX_PATH]; - WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); - progFilesDir = Glib::ustring(pathA); + if (SHGetSpecialFolderPathW (NULL, pathW, CSIDL_PROGRAM_FILES, false)) { + if (WideCharToMultiByte (CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0)) { + progFilesDir = pathA; + } } - if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_PROGRAM_FILESX86, false)) { - WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); - progFilesDirx86 = Glib::ustring(pathA); + if (SHGetSpecialFolderPathW (NULL, pathW, CSIDL_PROGRAM_FILESX86, false)) { + if (WideCharToMultiByte (CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0)) { + progFilesDirx86 = pathA; + } } } - if (exePath86.empty()) { - exePath86 = exePath; - } + ExtProgAction action; + action.name = name; + action.target = (allowRaw ? 1 : 2); - ExtProgAction *pAct = new ExtProgAction(); - pAct->name = name; - pAct->target = (allowRaw ? 1 : 2); + auto& filePath = action.filePathEXE; if (maxVer > 0) { - for (int verNo = maxVer; verNo >= 0; verNo--) { - pAct->filePathEXE = progFilesDir + "\\" + Glib::ustring::compose(exePath, verNo); - if (safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) { + for (auto ver = maxVer; ver >= 0; ver--) { + + filePath = progFilesDir + "\\" + Glib::ustring::compose(exePath, ver); + + if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) { break; } - pAct->filePathEXE = progFilesDirx86 + "\\" + Glib::ustring::compose(exePath86, verNo); + if (!exePath86.empty ()) { - if (safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) { - break; + filePath = progFilesDirx86 + "\\" + Glib::ustring::compose(exePath86, ver); + + if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) { + break; + } } - pAct->filePathEXE = ""; + filePath.clear (); } } else { - pAct->filePathEXE = progFilesDir + "\\" + exePath; - if (!safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) { + do { - pAct->filePathEXE = progFilesDirx86 + "\\" + exePath86; + filePath = progFilesDir + "\\" + exePath; - if (!safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) { - pAct->filePathEXE = ""; + if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) { + break; } - } + + if (!exePath86.empty ()) { + + filePath = progFilesDirx86 + "\\" + exePath86; + + if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) { + break; + } + } + + filePath.clear (); + + } while (false); } - if (pAct->filePathEXE.length() > 0) { - lActions.push_back(pAct); + if (!action.filePathEXE.empty ()) { + + actions.push_back (action); - // Copy for second target if (allowRaw && allowQueueProcess) { - lActions.push_back(new ExtProgAction(pAct, 2)); + + action.target = 2; + actions.push_back (action); } - found = true; - } else { - delete pAct; + return true; } #endif - return found; + return false; +} + +bool ExtProgStore::spawnCommandAsync (const Glib::ustring& cmd) +{ + try { + + const auto encodedCmd = Glib::filename_from_utf8 (cmd); + Glib::spawn_command_line_async (encodedCmd.c_str ()); + + return true; + + } catch (const Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to execute \"" << cmd << "\": " << exception.what() << std::endl; + } + + return false; + + } +} + +bool ExtProgStore::spawnCommandSync (const Glib::ustring& cmd) +{ + auto exitStatus = -1; + + try { + + Glib::spawn_command_line_sync (cmd, NULL, NULL, &exitStatus); + + } catch (const Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to execute \"" << cmd << "\": " << exception.what() << std::endl; + } + + } + + return exitStatus == 0; +} + +bool ExtProgStore::openInGimp (const Glib::ustring& fileName) +{ +#if defined WIN32 + + auto executable = Glib::build_filename (options.gimpDir, "bin", "gimp-win-remote"); + auto cmdLine = Glib::ustring::compose ("\"%1\" gimp-2.4.exe \"%2\"", executable, fileName); + auto success = spawnCommandAsync (cmdLine); + +#elif defined __APPLE__ + + auto cmdLine = Glib::ustring("open -a /Applications/GIMP.app \'") + fileName + Glib::ustring("\'"); + auto success = spawnCommandAsync (cmdLine); + +#else + + auto cmdLine = Glib::ustring("gimp \"") + fileName + Glib::ustring("\""); + auto success = spawnCommandAsync (cmdLine); + +#endif + + if (success) { + return true; + } + +#ifdef WIN32 + + for (auto ver = 12; ver >= 0; --ver) { + + executable = Glib::build_filename (options.gimpDir, "bin", Glib::ustring::compose (Glib::ustring("gimp-2.%1.exe"), ver)); + cmdLine = Glib::ustring::compose ("\"%1\" \"%2\"", executable, fileName); + success = spawnCommandAsync (cmdLine); + + if (success) { + return true; + } + } + +#elif defined __APPLE__ + + cmdLine = Glib::ustring("open -a /Applications/Gimp.app/Contents/Resources/start \'") + fileName + Glib::ustring("\'"); + success = ExtProgStore::spawnCommandAsync (cmdLine); + +#else + + cmdLine = Glib::ustring("gimp-remote \"") + fileName + Glib::ustring("\""); + success = ExtProgStore::spawnCommandAsync (cmdLine); + +#endif + + return success; +} + +bool ExtProgStore::openInPhotoshop (const Glib::ustring& fileName) +{ +#if defined WIN32 + + const auto executable = Glib::build_filename(options.psDir, "Photoshop.exe"); + const auto cmdLine = Glib::ustring("\"") + executable + Glib::ustring("\" \"") + fileName + Glib::ustring("\""); + +#elif defined __APPLE__ + + const auto cmdLine = Glib::ustring("open -a \'") + Glib::build_filename(options.psDir, "Photoshop.app\' ") + Glib::ustring("\'") + fileName + Glib::ustring("\'"); + +#else + + const auto cmdLine = Glib::ustring("\"") + Glib::build_filename(options.psDir, "Photoshop.exe") + Glib::ustring("\" \"") + fileName + Glib::ustring("\""); + +#endif + + return spawnCommandAsync (cmdLine); +} + +bool ExtProgStore::openInCustomEditor (const Glib::ustring& fileName) +{ +#if defined WIN32 + + const auto cmdLine = Glib::ustring("\"") + options.customEditorProg + Glib::ustring("\" \"") + fileName + Glib::ustring("\""); + +#elif defined __APPLE__ + + const auto cmdLine = options.customEditorProg + Glib::ustring(" \"") + fileName + Glib::ustring("\""); + +#else + + const auto cmdLine = Glib::ustring("\"") + options.customEditorProg + Glib::ustring("\" \"") + fileName + Glib::ustring("\""); + +#endif + + return spawnCommandAsync (cmdLine); } diff --git a/rtgui/extprog.h b/rtgui/extprog.h index 2069bc8e8..fe7375ce7 100644 --- a/rtgui/extprog.h +++ b/rtgui/extprog.h @@ -20,42 +20,58 @@ #ifndef _EXTPROG_ #define _EXTPROG_ -#include -#include +#include + +#include + #include "threadutils.h" -class ExtProgAction +struct ExtProgAction { -public: - ExtProgAction(); - ExtProgAction(const ExtProgAction* other, int target); - Glib::ustring filePathEXE; Glib::ustring preparams; // after EXE and before file names Glib::ustring name; // already localized if necessary int target; // 1=RAW files, 2=batch converted files - Glib::ustring GetFullName(); // e.g. "Photoshop (RAW)" + Glib::ustring getFullName () const; // e.g. "Photoshop (RAW)" - virtual bool Execute(std::vector fileNames); + bool execute (const std::vector& fileNames) const; }; // Stores all external programs that could be called by the user class ExtProgStore { MyMutex mtx; // covers actions + std::vector actions; - bool SearchProg(Glib::ustring name, Glib::ustring exePath, Glib::ustring exePath86, int maxVer, bool allowRaw, bool allowQueueProcess); + bool searchProgram (const Glib::ustring& name, + const Glib::ustring& exePath, + const Glib::ustring& exePath86, + int maxVer, + bool allowRaw, + bool allowQueueProcess); public: - ~ExtProgStore(); - - void init(); // searches computer for installed standard programs static ExtProgStore* getInstance(); - std::list lActions; + // searches computer for installed standard programs + void init(); + + const std::vector& getActions () const; + + static bool spawnCommandAsync (const Glib::ustring& cmd); + static bool spawnCommandSync (const Glib::ustring& cmd); + + static bool openInGimp (const Glib::ustring& fileName); + static bool openInPhotoshop (const Glib::ustring& fileName); + static bool openInCustomEditor (const Glib::ustring& fileName); }; #define extProgStore ExtProgStore::getInstance() +inline const std::vector& ExtProgStore::getActions () const +{ + return actions; +} + #endif diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index 73fd4b4d6..f8a8f225f 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -232,11 +232,9 @@ FileBrowser::FileBrowser () mMenuExtProgs.clear(); amiExtProg = NULL; - for (std::list::iterator it = extProgStore->lActions.begin(); it != extProgStore->lActions.end(); it++) { - ExtProgAction* pAct = *it; - - if (pAct->target == 1 || pAct->target == 2) { - mMenuExtProgs[pAct->GetFullName()] = pAct; + for (const auto& action : extProgStore->getActions ()) { + if (action.target == 1 || action.target == 2) { + mMenuExtProgs[action.getFullName ()] = &action; } } @@ -255,7 +253,7 @@ FileBrowser::FileBrowser () p++; } - for (std::map::iterator it = mMenuExtProgs.begin(); it != mMenuExtProgs.end(); it++, itemNo++) { + for (auto it = mMenuExtProgs.begin(); it != mMenuExtProgs.end(); it++, itemNo++) { submenuExtProg->attach (*Gtk::manage(amiExtProg[itemNo] = new Gtk::MenuItem ((*it).first)), 0, 1, p, p + 1); p++; } @@ -268,7 +266,7 @@ FileBrowser::FileBrowser () p++; } - for (std::map::iterator it = mMenuExtProgs.begin(); it != mMenuExtProgs.end(); it++, itemNo++) { + for (auto it = mMenuExtProgs.begin(); it != mMenuExtProgs.end(); it++, itemNo++) { pmenu->attach (*Gtk::manage(amiExtProg[itemNo] = new Gtk::MenuItem ((*it).first)), 0, 1, p, p + 1); p++; } @@ -752,7 +750,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) for (int j = 0; j < mMenuExtProgs.size(); j++) { if (m == amiExtProg[j]) { - ExtProgAction* pAct = mMenuExtProgs[m->get_label()]; + const auto pAct = mMenuExtProgs[m->get_label()]; // Build vector of all file names std::vector selFileNames; @@ -768,7 +766,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) selFileNames.push_back(fn); } - pAct->Execute(selFileNames); + pAct->execute (selFileNames); return; } } @@ -835,7 +833,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) } else if (m == selectDF) { if( !mselected.empty() ) { rtengine::procparams::ProcParams pp = mselected[0]->thumbnail->getProcParams(); - Gtk::FileChooserDialog fc("Dark Frame", Gtk::FILE_CHOOSER_ACTION_OPEN ); + Gtk::FileChooserDialog fc (getToplevelWindow (this), "Dark Frame", Gtk::FILE_CHOOSER_ACTION_OPEN ); bindCurrentFolder (fc, options.lastDarkframeDir); fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); fc.add_button( Gtk::StockID("gtk-apply"), Gtk::RESPONSE_APPLY); @@ -911,7 +909,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) } else if (m == selectFF) { if( !mselected.empty() ) { rtengine::procparams::ProcParams pp = mselected[0]->thumbnail->getProcParams(); - Gtk::FileChooserDialog fc("Flat Field", Gtk::FILE_CHOOSER_ACTION_OPEN ); + Gtk::FileChooserDialog fc (getToplevelWindow (this), "Flat Field", Gtk::FILE_CHOOSER_ACTION_OPEN ); bindCurrentFolder (fc, options.lastFlatfieldDir); fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); fc.add_button( Gtk::StockID("gtk-apply"), Gtk::RESPONSE_APPLY); diff --git a/rtgui/filebrowser.h b/rtgui/filebrowser.h index a444b0a0e..e037363c9 100644 --- a/rtgui/filebrowser.h +++ b/rtgui/filebrowser.h @@ -93,7 +93,7 @@ protected: Gtk::MenuItem* menuExtProg; Gtk::MenuItem** amiExtProg; Gtk::MenuItem* miOpenDefaultViewer; - std::map mMenuExtProgs; // key is menuitem label + std::map mMenuExtProgs; // key is menuitem label Gtk::MenuItem* menuDF; Gtk::MenuItem* selectDF; diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc index 2e2b0ccb1..f2977b742 100644 --- a/rtgui/filebrowserentry.cc +++ b/rtgui/filebrowserentry.cc @@ -17,16 +17,17 @@ * along with RawTherapee. If not, see . */ #include "filebrowserentry.h" -#include "thumbbrowserbase.h" -#include "cursormanager.h" + #include +#include + #include "guiutils.h" #include "threadutils.h" -#include "../rtengine/safegtk.h" +#include "rtimage.h" +#include "cursormanager.h" +#include "thumbbrowserbase.h" #include "inspector.h" -#include - #define CROPRESIZEBORDER 4 bool FileBrowserEntry::iconsLoaded(false); @@ -51,9 +52,9 @@ FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname) scale = 1; if (!iconsLoaded) { - editedIcon = safe_create_from_file ("edited.png"); - recentlySavedIcon = safe_create_from_file ("recent-save.png"); - enqueuedIcon = safe_create_from_file ("processing.png"); + editedIcon = RTImage::createFromFile ("edited.png"); + recentlySavedIcon = RTImage::createFromFile ("recent-save.png"); + enqueuedIcon = RTImage::createFromFile ("processing.png"); iconsLoaded = true; } diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index 8b9f299d8..3ed7608f1 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -17,22 +17,25 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#include +#include "filecatalog.h" + #include #include + +#include + #include "../rtengine/rt_math.h" -#include "filecatalog.h" -#include "filepanel.h" +#include "guiutils.h" #include "options.h" +#include "rtimage.h" #include "cachemanager.h" #include "multilangmgr.h" -#include "guiutils.h" +#include "filepanel.h" #include "renamedlg.h" #include "thumbimageupdater.h" -#include "../rtengine/safegtk.h" #include "batchqueue.h" -#include "rtimage.h" +#include "placesbrowser.h" using namespace std; @@ -538,11 +541,44 @@ void FileCatalog::closeDir () std::vector FileCatalog::getFileList () { - std::vector names; - Glib::RefPtr dir = Gio::File::create_for_path (selectedDirectory); - safe_build_file_list (dir, names, selectedDirectory, &(options.parsedExtensions)); -// Issue 2406 std::sort (names.begin(), names.end()); + + std::set extensions; + for (const auto& parsedExt : options.parsedExtensions) { + extensions.emplace (parsedExt.lowercase ()); + } + + try { + + auto dir = Gio::File::create_for_path (selectedDirectory); + + auto enumerator = dir->enumerate_children ("standard::name"); + + while (auto file = enumerator->next_file ()) { + + const Glib::ustring fname = file->get_name (); + + auto lastdot = fname.find_last_of ('.'); + if (lastdot >= fname.length () - 1) { + continue; + } + + const auto fext = fname.substr (lastdot + 1).lowercase (); + if (extensions.count (fext) == 0) { + continue; + } + + names.emplace_back (Glib::build_filename (selectedDirectory, fname)); + } + + } catch (Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to list directory \"" << selectedDirectory << "\": " << exception.what() << std::endl; + } + + } + return names; } @@ -899,35 +935,26 @@ void FileCatalog::deleteRequested (std::vector tbe, bool inc if (msd.run() == Gtk::RESPONSE_YES) { for (unsigned int i = 0; i < tbe.size(); i++) { - Glib::ustring fname = tbe[i]->filename; + const auto fname = tbe[i]->filename; // remove from browser - FileBrowserEntry* t = fileBrowser->delEntry (fname); -// t->thumbnail->decreaseRef (); - delete t; + delete fileBrowser->delEntry (fname); // remove from cache cacheMgr->deleteEntry (fname); // delete from file system - safe_g_remove (fname); + ::g_remove (fname.c_str ()); // delete paramfile if found - safe_g_remove (Glib::ustring(fname + paramFileExtension)); - safe_g_remove (Glib::ustring(removeExtension(fname) + paramFileExtension)); + ::g_remove ((fname + paramFileExtension).c_str ()); + ::g_remove ((removeExtension(fname) + paramFileExtension).c_str ()); // delete .thm file - safe_g_remove (Glib::ustring(removeExtension(fname) + ".thm")); - safe_g_remove (Glib::ustring(removeExtension(fname) + ".THM")); + ::g_remove ((removeExtension(fname) + ".thm").c_str ()); + ::g_remove ((removeExtension(fname) + ".THM").c_str ()); if (inclBatchProcessed) { Glib::ustring procfName = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format); + ::g_remove (procfName.c_str ()); - if (safe_file_test (procfName, Glib::FILE_TEST_EXISTS)) { - safe_g_remove (procfName); - } - - // delete paramfile if found Glib::ustring procfNameParamFile = Glib::ustring::compose ("%1.%2.out%3", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format, paramFileExtension); - - if (safe_file_test (procfNameParamFile, Glib::FILE_TEST_EXISTS)) { - safe_g_remove (procfNameParamFile); - } + ::g_remove (procfNameParamFile.c_str ()); } previewsLoaded--; @@ -955,7 +982,7 @@ void FileCatalog::copyMoveRequested (std::vector tbe, bool m fc_title = M("FILEBROWSER_POPUPCOPYTO"); } - Gtk::FileChooserDialog fc(fc_title, Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); + Gtk::FileChooserDialog fc (getToplevelWindow (this), fc_title, Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); fc.add_button( Gtk::StockID("gtk-ok"), Gtk::RESPONSE_OK); // open dialog at the 1-st file's path @@ -998,7 +1025,7 @@ void FileCatalog::copyMoveRequested (std::vector tbe, bool m while(!filecopymovecomplete) { // check for filename conflicts at destination - prevent overwriting (actually RT will crash on overwriting attempt) - if (!safe_file_test(dest_fPath, Glib::FILE_TEST_EXISTS) && !safe_file_test(dest_fPath_param, Glib::FILE_TEST_EXISTS)) { + if (!Glib::file_test(dest_fPath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(dest_fPath_param, Glib::FILE_TEST_EXISTS)) { // copy/move file to destination Glib::RefPtr dest_file = Gio::File::create_for_path ( dest_fPath ); @@ -1019,15 +1046,15 @@ void FileCatalog::copyMoveRequested (std::vector tbe, bool m // attempt to copy/move paramFile only if it exist next to the src Glib::RefPtr scr_param = Gio::File::create_for_path ( src_fPath + paramFileExtension ); - if (safe_file_test( src_fPath + paramFileExtension, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test( src_fPath + paramFileExtension, Glib::FILE_TEST_EXISTS)) { Glib::RefPtr dest_param = Gio::File::create_for_path ( dest_fPath_param); // copy/move paramFile to destination if (moveRequested) { - if (safe_file_test( dest_fPath + paramFileExtension, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test( dest_fPath + paramFileExtension, Glib::FILE_TEST_EXISTS)) { // profile already got copied to destination from cache after cacheMgr->renameEntry // delete source profile as cleanup - safe_g_remove (src_fPath + paramFileExtension); + ::g_remove ((src_fPath + paramFileExtension).c_str ()); } else { scr_param->move(dest_param); } @@ -1229,16 +1256,16 @@ void FileCatalog::renameRequested (std::vector tbe) Glib::ustring nfname = Glib::build_filename (dirName, nBaseName); /* check if filename already exists*/ - if (safe_file_test (nfname, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test (nfname, Glib::FILE_TEST_EXISTS)) { Glib::ustring msg_ = Glib::ustring("") + nfname + ": " + M("MAIN_MSG_ALREADYEXISTS") + ""; Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); msgd.run (); } else { success = true; - if (!safe_g_rename (ofname, nfname)) { + if (::g_rename (ofname.c_str (), nfname.c_str ()) == 0) { cacheMgr->renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname); - safe_g_remove(ofname + paramFileExtension); + ::g_remove((ofname + paramFileExtension).c_str ()); reparseDirectory (); } } @@ -1251,53 +1278,6 @@ void FileCatalog::renameRequested (std::vector tbe) } delete renameDlg; - /* // ask for new file name - Gtk::Dialog dialog (M("FILEBROWSER_RENAMEDLGLABEL"), *((Gtk::Window*)get_toplevel()), true, true); - - dialog.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); - dialog.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); - - Gtk::Label l; - dialog.get_vbox()->pack_start (l, Gtk::PACK_SHRINK); - - Gtk::Entry nfentry; - - dialog.get_vbox()->pack_start (nfentry, Gtk::PACK_SHRINK); - dialog.get_vbox()->show_all (); - - nfentry.set_activates_default (true); - dialog.set_default_response (Gtk::RESPONSE_OK); - - for (int i=0; ifilename; - Glib::ustring dirName = Glib::path_get_dirname (tbe[i]->filename); - Glib::ustring baseName = Glib::path_get_basename (tbe[i]->filename); - - l.set_markup (Glib::ustring("") + Glib::ustring::compose (M("FILEBROWSER_RENAMEDLGMSG"), baseName) + Glib::ustring("")); - nfentry.set_text (baseName); - nfentry.select_region (0, baseName.size()); - - if (dialog.run ()== Gtk::RESPONSE_OK) { - Glib::ustring nBaseName = nfentry.get_text (); - // if path has directory components, exit - if (Glib::path_get_dirname (nBaseName) != ".") - continue; - // if no extension is given, concatenate the extension of the original file - if (nBaseName.find ('.')==nBaseName.npos) { - size_t lastdot = baseName.find_last_of ('.'); - nBaseName += "." + (lastdot!=Glib::ustring::npos ? baseName.substr (lastdot+1) : ""); - } - Glib::ustring nfname = Glib::build_filename (dirName, nBaseName); - if (!safe_g_rename (ofname, nfname)) { - cacheMgr->renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname); - // the remaining part (removing old and adding new entry) is done by the directory monitor - reparseDirectory (); - // on_dir_changed (Gio::File::create_for_path (nfname), Gio::File::create_for_path (nfname), Gio::FILE_MONITOR_EVENT_CHANGED, true); - } - } - } - */ } void FileCatalog::clearFromCacheRequested (std::vector tbe, bool leavenotrace) @@ -1722,7 +1702,7 @@ void FileCatalog::reparseDirectory () return; } - if (!safe_file_test (selectedDirectory, Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (selectedDirectory, Glib::FILE_TEST_IS_DIR)) { closeDir (); return; } @@ -1734,7 +1714,7 @@ void FileCatalog::reparseDirectory () std::vector fileNamesToDel; for (size_t i = 0; i < t.size(); i++) - if (!safe_file_test (t[i]->filename, Glib::FILE_TEST_EXISTS)) { + if (!Glib::file_test (t[i]->filename, Glib::FILE_TEST_EXISTS)) { fileNamesToDel.push_back (t[i]->filename); } @@ -1799,63 +1779,91 @@ void FileCatalog::on_dir_changed (const Glib::RefPtr& file, const Gli void FileCatalog::checkAndAddFile (Glib::RefPtr file) { - - if (!file ) { + if (!file) { return; } - if( !file->query_exists()) { + if (!file->query_exists()) { return; } - Glib::RefPtr info = safe_query_file_info(file); + try { - if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) { - size_t lastdot = info->get_name().find_last_of ('.'); + auto info = file->query_info (); - if (options.is_extention_enabled(lastdot != Glib::ustring::npos ? info->get_name().substr (lastdot + 1) : "")) { - previewLoader->add (selectedDirectoryId, file->get_parse_name(), this); - previewsToLoad++; + if (!info || info->get_file_type () == Gio::FILE_TYPE_DIRECTORY) { + return; } - } + + if (!options.fbShowHidden && info->is_hidden ()) { + return; + } + + Glib::ustring ext; + + const auto lastdot = info->get_name ().find_last_of ('.'); + if (lastdot != Glib::ustring::npos) { + ext = info->get_name ().substr (lastdot + 1); + } + + if (!options.is_extention_enabled (ext)) { + return; + } + + previewLoader->add (selectedDirectoryId, file->get_parse_name (), this); + previewsToLoad++; + + } catch(Gio::Error&) {} } void FileCatalog::addAndOpenFile (const Glib::ustring& fname) { - - Glib::RefPtr file = Gio::File::create_for_path (fname); + auto file = Gio::File::create_for_path (fname); if (!file ) { return; } - if( !file->query_exists()) { + if (!file->query_exists ()) { return; } - Glib::RefPtr info = safe_query_file_info(file); + try { - if( !info ) { - return; - } + auto info = file->query_info (); - size_t lastdot = info->get_name().find_last_of ('.'); - - if (options.is_extention_enabled(lastdot != Glib::ustring::npos ? info->get_name().substr (lastdot + 1) : "")) { - // if supported, load thumbnail first - Thumbnail* tmb = cacheMgr->getEntry (file->get_parse_name()); - - if (tmb) { - FileBrowserEntry* entry = new FileBrowserEntry (tmb, file->get_parse_name()); - previewReady (selectedDirectoryId, entry); - // open the file - FCOIParams* params = new FCOIParams; - params->catalog = this; - params->tmb.push_back (tmb); - tmb->increaseRef (); - g_idle_add (openRequestedUI, params); + if (!info) { + return; } - } + + Glib::ustring ext; + + auto lastdot = info->get_name().find_last_of ('.'); + if (lastdot != Glib::ustring::npos) { + ext = info->get_name ().substr (lastdot + 1); + } + + if (!options.is_extention_enabled(ext)) { + return; + } + + // if supported, load thumbnail first + const auto tmb = cacheMgr->getEntry (file->get_parse_name ()); + + if (!tmb) { + return; + } + + FileBrowserEntry* entry = new FileBrowserEntry (tmb, file->get_parse_name ()); + previewReady (selectedDirectoryId, entry); + // open the file + FCOIParams* params = new FCOIParams; + params->catalog = this; + params->tmb.push_back (tmb); + tmb->increaseRef (); + g_idle_add (openRequestedUI, params); + + } catch(Gio::Error&) {} } void FileCatalog::emptyTrash () @@ -2027,10 +2035,9 @@ void FileCatalog::buttonBrowsePathPressed () FirstChar = BrowsePathValue.substr (0, 1); if (FirstChar == "~") { // home directory - DecodedPathPrefix = Glib::get_home_dir(); + DecodedPathPrefix = PlacesBrowser::userHomeDir (); } else if (FirstChar == "!") { // user's pictures directory - //DecodedPathPrefix = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES); - DecodedPathPrefix = safe_get_user_picture_dir(); + DecodedPathPrefix = PlacesBrowser::userPicturesDir (); } if (!DecodedPathPrefix.empty()) { @@ -2041,7 +2048,7 @@ void FileCatalog::buttonBrowsePathPressed () // handle shortcuts in the BrowsePath -- END // validate the path - if (safe_file_test(BrowsePathValue, Glib::FILE_TEST_IS_DIR) && selectDir) { + if (Glib::file_test(BrowsePathValue, Glib::FILE_TEST_IS_DIR) && selectDir) { selectDir (BrowsePathValue); } else // error, likely path not found: show red arrow diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index 0069a6dbd..fd53db555 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -1,4 +1,3 @@ - /* * This file is part of RawTherapee. * @@ -18,9 +17,10 @@ * along with RawTherapee. If not, see . */ #include "filepanel.h" + #include "rtwindow.h" -#include "../rtengine/safegtk.h" #include "inspector.h" +#include "placesbrowser.h" int FilePanelInitUI (void* data) { @@ -177,19 +177,19 @@ void FilePanel::init () dirBrowser->fillDirTree (); placesBrowser->refreshPlacesList (); - if (argv1 != "" && safe_file_test (argv1, Glib::FILE_TEST_IS_DIR)) { + if (argv1 != "" && Glib::file_test (argv1, Glib::FILE_TEST_IS_DIR)) { dirBrowser->open (argv1); } else { if (options.startupDir == STARTUPDIR_HOME) { - dirBrowser->open (safe_get_user_picture_dir()); + dirBrowser->open (PlacesBrowser::userPicturesDir ()); } else if (options.startupDir == STARTUPDIR_CURRENT) { dirBrowser->open (argv0); } else if (options.startupDir == STARTUPDIR_CUSTOM || options.startupDir == STARTUPDIR_LAST) { - if (options.startupPath.length() && safe_file_test(options.startupPath, Glib::FILE_TEST_EXISTS) && safe_file_test(options.startupPath, Glib::FILE_TEST_IS_DIR)) { + if (options.startupPath.length() && Glib::file_test(options.startupPath, Glib::FILE_TEST_EXISTS) && Glib::file_test(options.startupPath, Glib::FILE_TEST_IS_DIR)) { dirBrowser->open (options.startupPath); } else { // Fallback option if the path is empty or the folder doesn't exist - dirBrowser->open (safe_get_user_picture_dir()); + dirBrowser->open (PlacesBrowser::userPicturesDir ()); } } } @@ -322,9 +322,9 @@ void FilePanel::saveOptions () void FilePanel::open (const Glib::ustring& d) { - if (safe_file_test (d, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (d, Glib::FILE_TEST_IS_DIR)) { dirBrowser->open (d.c_str()); - } else if (safe_file_test (d, Glib::FILE_TEST_EXISTS)) { + } else if (Glib::file_test (d, Glib::FILE_TEST_EXISTS)) { dirBrowser->open (Glib::path_get_dirname(d), Glib::path_get_basename(d)); } } diff --git a/rtgui/filethumbnailbuttonset.cc b/rtgui/filethumbnailbuttonset.cc index e9970b177..286324bdf 100644 --- a/rtgui/filethumbnailbuttonset.cc +++ b/rtgui/filethumbnailbuttonset.cc @@ -17,8 +17,9 @@ * along with RawTherapee. If not, see . */ #include "filethumbnailbuttonset.h" + +#include "rtimage.h" #include "multilangmgr.h" -#include "../rtengine/safegtk.h" extern Glib::ustring argv0; @@ -41,19 +42,19 @@ FileThumbnailButtonSet::FileThumbnailButtonSet (FileBrowserEntry* myEntry) { if (!iconsLoaded) { - unRankIcon = safe_create_from_png ("ratednotg.png"); - rankIcon = safe_create_from_png ("rated.png"); - gRankIcon = safe_create_from_png ("grayrated.png"); - trashIcon = safe_create_from_png ("trash-thumbnail.png"); - unTrashIcon = safe_create_from_png ("undelete-thumbnail.png"); - processIcon = safe_create_from_png ("processing-thumbnail.png"); + unRankIcon = RTImage::createFromPng ("ratednotg.png"); + rankIcon = RTImage::createFromPng ("rated.png"); + gRankIcon = RTImage::createFromPng ("grayrated.png"); + trashIcon = RTImage::createFromPng ("trash-thumbnail.png"); + unTrashIcon = RTImage::createFromPng ("undelete-thumbnail.png"); + processIcon = RTImage::createFromPng ("processing-thumbnail.png"); - colorLabelIcon_0 = safe_create_from_png ("cglabel0.png"); //("nocolorlabel.png"); - colorLabelIcon_1 = safe_create_from_png ("clabel1.png"); - colorLabelIcon_2 = safe_create_from_png ("clabel2.png"); - colorLabelIcon_3 = safe_create_from_png ("clabel3.png"); - colorLabelIcon_4 = safe_create_from_png ("clabel4.png"); - colorLabelIcon_5 = safe_create_from_png ("clabel5.png"); + colorLabelIcon_0 = RTImage::createFromPng ("cglabel0.png"); //("nocolorlabel.png"); + colorLabelIcon_1 = RTImage::createFromPng ("clabel1.png"); + colorLabelIcon_2 = RTImage::createFromPng ("clabel2.png"); + colorLabelIcon_3 = RTImage::createFromPng ("clabel3.png"); + colorLabelIcon_4 = RTImage::createFromPng ("clabel4.png"); + colorLabelIcon_5 = RTImage::createFromPng ("clabel5.png"); iconsLoaded = true; } diff --git a/rtgui/filmsimulation.cc b/rtgui/filmsimulation.cc index 93abe18fb..07f85df94 100644 --- a/rtgui/filmsimulation.cc +++ b/rtgui/filmsimulation.cc @@ -4,7 +4,6 @@ #include "options.h" #include "../rtengine/clutstore.h" -#include "../rtengine/safegtk.h" using namespace rtengine; using namespace rtengine::procparams; diff --git a/rtgui/flatcurveeditorsubgroup.cc b/rtgui/flatcurveeditorsubgroup.cc index 691fbe3dd..fd975de5e 100644 --- a/rtgui/flatcurveeditorsubgroup.cc +++ b/rtgui/flatcurveeditorsubgroup.cc @@ -216,13 +216,15 @@ void FlatCurveEditorSubGroup::pipetteMouseOver(EditDataProvider *provider, int m } } -void FlatCurveEditorSubGroup::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) +bool FlatCurveEditorSubGroup::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) { CurveEditor *curveEditor = static_cast(parent->displayedCurve); + bool isDragging = false; + switch((FlatCurveType)(curveEditor->curveType->getSelected())) { case (FCT_MinMaxCPoints): - CPointsCurve->pipetteButton1Pressed(provider, modifierKey); + isDragging = CPointsCurve->pipetteButton1Pressed(provider, modifierKey); CPointsCurve->setDirty(true); break; @@ -230,6 +232,8 @@ void FlatCurveEditorSubGroup::pipetteButton1Pressed(EditDataProvider *provider, // ... do nothing break; } + + return isDragging; } void FlatCurveEditorSubGroup::pipetteButton1Released(EditDataProvider *provider) diff --git a/rtgui/flatcurveeditorsubgroup.h b/rtgui/flatcurveeditorsubgroup.h index 8cd2a6d9a..7772dcebd 100644 --- a/rtgui/flatcurveeditorsubgroup.h +++ b/rtgui/flatcurveeditorsubgroup.h @@ -54,7 +54,7 @@ public: void refresh(CurveEditor *curveToRefresh); void editModeSwitchedOff(); void pipetteMouseOver(EditDataProvider *provider, int modifierKey); - void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); + bool pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); void pipetteButton1Released(EditDataProvider *provider); void pipetteDrag(EditDataProvider *provider, int modifierKey); void showCoordinateAdjuster(CoordinateProvider *provider); diff --git a/rtgui/flatfield.cc b/rtgui/flatfield.cc index 8609bea73..da78cda3c 100644 --- a/rtgui/flatfield.cc +++ b/rtgui/flatfield.cc @@ -19,7 +19,6 @@ #include "flatfield.h" #include "options.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include #include "rtimage.h" @@ -140,7 +139,7 @@ void FlatField::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi } } - if (safe_file_test (pp->raw.ff_file, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test (pp->raw.ff_file, Glib::FILE_TEST_EXISTS)) { flatFieldFile->set_filename (pp->raw.ff_file); } else { flatFieldFile_Reset(); @@ -392,28 +391,21 @@ void FlatField::flatFieldAutoSelectChanged() } -void FlatField::setShortcutPath(Glib::ustring path) +void FlatField::setShortcutPath(const Glib::ustring& path) { - if (path == "") { + if (path.empty ()) { return; } -#ifdef WIN32 + try { - // Dirty workaround, waiting for a clean solution by using exceptions! - if (!safe_is_shortcut_dir(path)) -#endif - { - if (lastShortcutPath != "") { - try { - flatFieldFile->remove_shortcut_folder(lastShortcutPath); - } catch (Glib::Error &err) {} + if (!lastShortcutPath.empty ()) { + flatFieldFile->remove_shortcut_folder (lastShortcutPath); } + flatFieldFile->add_shortcut_folder (path); + lastShortcutPath = path; - try { - flatFieldFile->add_shortcut_folder(path); - } catch (Glib::Error &err) {} - } + } catch (Glib::Error&) {} } diff --git a/rtgui/flatfield.h b/rtgui/flatfield.h index 162360b9a..b85b154da 100644 --- a/rtgui/flatfield.h +++ b/rtgui/flatfield.h @@ -75,7 +75,7 @@ public: void flatFieldFile_Reset (); void flatFieldAutoSelectChanged (); void flatFieldBlurTypeChanged (); - void setShortcutPath(Glib::ustring path); + void setShortcutPath (const Glib::ustring& path); void setFFProvider (FFProvider* p) { ffp = p; diff --git a/rtgui/gradient.cc b/rtgui/gradient.cc index 49cc3ee59..50625251e 100644 --- a/rtgui/gradient.cc +++ b/rtgui/gradient.cc @@ -136,88 +136,72 @@ void Gradient::read (const ProcParams* pp, const ParamsEdited* pedited) enableListener (); } -void Gradient::updateGeometry(int centerX_, int centerY_, double feather_, double degree_) +void Gradient::updateGeometry(const int centerX, const int centerY, const double feather, const double degree, const int fullWidth, const int fullHeight) { EditDataProvider* dataProvider = getEditProvider(); - if (dataProvider) { - int imW, imH; - PolarCoord polCoord1, polCoord2; - dataProvider->getImageSize(imW, imH); - double decay = feather_ * sqrt(double(imW) * double(imW) + double(imH) * double(imH)) / 200.; - - rtengine::Coord origin(imW / 2 + centerX_ * imW / 200.f, imH / 2 + centerY_ * imH / 200.f); - - Line *currLine; - Circle *currCircle; - // update horizontal line - currLine = static_cast(visibleGeometry.at(0)); - polCoord1.set(1500.f, float(-degree_ + 180)); - currLine->begin.setFromPolar(polCoord1); - currLine->begin += origin; - polCoord1.set(1500.f, float(-degree_ )); - currLine->end.setFromPolar (polCoord1); - currLine->end += origin; - currLine = static_cast(mouseOverGeometry.at(0)); - polCoord1.set(1500.f, float(-degree_ + 180)); - currLine->begin.setFromPolar(polCoord1); - currLine->begin += origin; - polCoord1.set(1500.f, float(-degree_ )); - currLine->end.setFromPolar (polCoord1); - currLine->end += origin; - // update vertical line - currLine = static_cast(visibleGeometry.at(1)); - polCoord1.set( 700.f, float(-degree_ + 90 )); - currLine->begin.setFromPolar(polCoord1); - currLine->begin += origin; - polCoord1.set( 700.f, float(-degree_ + 270)); - currLine->end.setFromPolar (polCoord1); - currLine->end += origin; - currLine = static_cast(mouseOverGeometry.at(1)); - polCoord1.set( 700.f, float(-degree_ + 90 )); - currLine->begin.setFromPolar(polCoord1); - currLine->begin += origin; - polCoord1.set( 700.f, float(-degree_ + 270)); - currLine->end.setFromPolar (polCoord1); - currLine->end += origin; - // update upper feather line - currLine = static_cast(visibleGeometry.at(2)); - polCoord2.set(decay, float(-degree_ + 270)); - polCoord1.set(350.f, float(-degree_ + 180)); - currLine->begin.setFromPolar(polCoord1 + polCoord2); - currLine->begin += origin; - polCoord1.set(350.f, float(-degree_ )); - currLine->end.setFromPolar (polCoord1 + polCoord2); - currLine->end += origin; - currLine = static_cast(mouseOverGeometry.at(2)); - polCoord1.set(350.f, float(-degree_ + 180)); - currLine->begin.setFromPolar(polCoord1 + polCoord2); - currLine->begin += origin; - polCoord1.set(350.f, float(-degree_ )); - currLine->end.setFromPolar (polCoord1 + polCoord2); - currLine->end += origin; - // update lower feather line - currLine = static_cast(visibleGeometry.at(3)); - polCoord2.set(decay, float(-degree_ + 90)); - polCoord1.set(350.f, float(-degree_ + 180)); - currLine->begin.setFromPolar(polCoord1 + polCoord2); - currLine->begin += origin; - polCoord1.set(350.f, float(-degree_ )); - currLine->end.setFromPolar (polCoord1 + polCoord2); - currLine->end += origin; - currLine = static_cast(mouseOverGeometry.at(3)); - polCoord1.set(350.f, float(-degree_ + 180)); - currLine->begin.setFromPolar(polCoord1 + polCoord2); - currLine->begin += origin; - polCoord1.set(350.f, float(-degree_ )); - currLine->end.setFromPolar (polCoord1 + polCoord2); - currLine->end += origin; - // update circle's position - currCircle = static_cast(visibleGeometry.at(4)); - currCircle->center = origin; - currCircle = static_cast(mouseOverGeometry.at(4)); - currCircle->center = origin; + if (!dataProvider) { + return; } + + int imW=0; + int imH=0; + if (fullWidth != -1 && fullHeight != -1) { + imW = fullWidth; + imH = fullHeight; + } else { + dataProvider->getImageSize(imW, imH); + if (!imW || !imH) { + return; + } + } + + const auto decay = feather * rtengine::norm2 (imW, imH) / 200.0; + rtengine::Coord origin (imW / 2 + centerX * imW / 200, imH / 2 + centerY * imH / 200); + + const auto updateLine = [&](Geometry* geometry, const float radius, const float begin, const float end) + { + const auto line = static_cast(geometry); + line->begin = PolarCoord(radius, -degree + begin); + line->begin += origin; + line->end = PolarCoord(radius, -degree + end); + line->end += origin; + }; + + const auto updateLineWithDecay = [&](Geometry* geometry, const float radius, const float offSetAngle) + { + const auto line = static_cast(geometry); + line->begin = PolarCoord (radius, -degree + 180.) + PolarCoord (decay, -degree + offSetAngle); + line->begin += origin; + line->end = PolarCoord (radius, -degree) + PolarCoord (decay, -degree + offSetAngle); + line->end += origin; + }; + + const auto updateCircle = [&](Geometry* geometry) + { + const auto circle = static_cast(geometry); + circle->center = origin; + }; + + // update horizontal line + updateLine (visibleGeometry.at(0), 1500., 0., 180.); + updateLine (mouseOverGeometry.at(0), 1500., 0., 180.); + + // update vertical line + updateLine (visibleGeometry.at(1), 700., 90., 270.); + updateLine (mouseOverGeometry.at(1), 700., 90., 270.); + + // update upper feather line + updateLineWithDecay (visibleGeometry.at(2), 350., 270.); + updateLineWithDecay (mouseOverGeometry.at(2), 350., 270.); + + // update lower feather line + updateLineWithDecay (visibleGeometry.at(3), 350., 90.); + updateLineWithDecay (mouseOverGeometry.at(3), 350., 90.); + + // update circle's position + updateCircle (visibleGeometry.at(4)); + updateCircle (mouseOverGeometry.at(4)); } void Gradient::write (ProcParams* pp, ParamsEdited* pedited) @@ -339,7 +323,7 @@ void Gradient::editToggled () } } -CursorShape Gradient::getCursor(int objectID) +CursorShape Gradient::getCursor(const int objectID) { switch (objectID) { case (0): @@ -365,7 +349,7 @@ CursorShape Gradient::getCursor(int objectID) } } -bool Gradient::mouseOver(int modifierKey) +bool Gradient::mouseOver(const int modifierKey) { EditDataProvider* editProvider = getEditProvider(); @@ -395,8 +379,12 @@ bool Gradient::mouseOver(int modifierKey) return false; } -bool Gradient::button1Pressed(int modifierKey) +bool Gradient::button1Pressed(const int modifierKey) { + if (lastObject < 0) { + return false; + } + EditDataProvider *provider = getEditProvider(); if (!(modifierKey & GDK_CONTROL_MASK)) { @@ -415,7 +403,7 @@ bool Gradient::button1Pressed(int modifierKey) p1.y = p2.y; p2.y = p; - pCoord.setFromCartesian(p1, p2); + pCoord = p2 - p1; draggedPointOldAngle = pCoord.angle; //printf("\ndraggedPointOldAngle=%.3f\n\n", draggedPointOldAngle); draggedPointAdjusterAngle = degree->getValue(); @@ -434,7 +422,7 @@ bool Gradient::button1Pressed(int modifierKey) centerPos.y = currPos.y; currPos.y = p; - draggedPoint.setFromCartesian(centerPos, currPos); + draggedPoint = currPos - centerPos; // compute the projected value of the dragged point draggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle - degree->getValue()) / 180.*M_PI); @@ -445,32 +433,32 @@ bool Gradient::button1Pressed(int modifierKey) draggedFeatherOffset -= (feather->getValue() / 200. * diagonal); } - EditSubscriber::dragging = true; + EditSubscriber::action = ES_ACTION_DRAGGING; return false; - } else { + } else { // should theoretically always be true // this will let this class ignore further drag events - if (lastObject > -1) { // should theoretically always be true - if (lastObject == 2 || lastObject == 3) { - EditSubscriber::visibleGeometry.at(2)->state = Geometry::NORMAL; - EditSubscriber::visibleGeometry.at(3)->state = Geometry::NORMAL; - } else { - EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL; - } + if (lastObject == 2 || lastObject == 3) { + EditSubscriber::visibleGeometry.at(2)->state = Geometry::NORMAL; + EditSubscriber::visibleGeometry.at(3)->state = Geometry::NORMAL; + } else { + EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL; } lastObject = -1; return true; } + + return false; } bool Gradient::button1Released() { draggedPointOldAngle = -1000.; - EditSubscriber::dragging = false; + EditSubscriber::action = ES_ACTION_NONE; return true; } -bool Gradient::drag1(int modifierKey) +bool Gradient::drag1(const int modifierKey) { // compute the polar coordinate of the mouse position EditDataProvider *provider = getEditProvider(); @@ -492,7 +480,7 @@ bool Gradient::drag1(int modifierKey) centerPos.y = currPos.y; currPos.y = p; - draggedPoint.setFromCartesian(centerPos, currPos); + draggedPoint = currPos - centerPos; double deltaAngle = draggedPoint.angle - draggedPointOldAngle; if (deltaAngle > 180.) { // crossing the boundary (0->360) @@ -537,7 +525,7 @@ bool Gradient::drag1(int modifierKey) centerPos.y = currPos.y; currPos.y = p; - draggedPoint.setFromCartesian(centerPos, currPos); + draggedPoint = currPos - centerPos; double currDraggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle - degree->getValue()) / 180.*M_PI); if (lastObject == 2) diff --git a/rtgui/gradient.h b/rtgui/gradient.h index 4117c3859..d1acb764b 100644 --- a/rtgui/gradient.h +++ b/rtgui/gradient.h @@ -42,21 +42,20 @@ public: void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); - void updateGeometry (int centerX_, int centerY_, double feather_, double degree_); - void adjusterChanged (Adjuster* a, double newval); void enabledChanged (); void setAdjusterBehavior (bool degreeadd, bool featheradd, bool strengthadd, bool centeradd); void trimValues (rtengine::procparams::ProcParams* pp); + void updateGeometry (const int centerX, const int centerY, const double feather, const double degree, const int fullWidth=-1, const int fullHeight=-1); void setEditProvider (EditDataProvider* provider); // EditSubscriber interface - CursorShape getCursor(int objectID); - bool mouseOver(int modifierKey); - bool button1Pressed(int modifierKey); + CursorShape getCursor(const int objectID); + bool mouseOver(const int modifierKey); + bool button1Pressed(const int modifierKey); bool button1Released(); - bool drag1(int modifierKey); + bool drag1(const int modifierKey); void switchOffEditMode (); }; diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index d3af3c597..c984a03f1 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -21,7 +21,6 @@ #include "options.h" #include "../rtengine/rt_math.h" #include "../rtengine/utils.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" #include "multilangmgr.h" @@ -131,7 +130,7 @@ bool confirmOverwrite (Gtk::Window& parent, const std::string& filename) { bool safe = true; - if (safe_file_test (filename, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test (filename, Glib::FILE_TEST_EXISTS)) { Glib::ustring msg_ = Glib::ustring ("\"") + Glib::path_get_basename (filename) + "\": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE"); Gtk::MessageDialog msgd (parent, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true); diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index c43d85b07..f91bb0245 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -490,4 +490,9 @@ inline void setActiveTextOrIndex (Gtk::ComboBoxText& comboBox, const Glib::ustri comboBox.set_active (index); } +inline Gtk::Window& getToplevelWindow (Gtk::Widget* widget) +{ + return *static_cast (widget->get_toplevel ()); +} + #endif diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index b21ebf751..efce343c0 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -20,7 +20,6 @@ #include "icmpanel.h" #include "options.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include "../rtengine/iccstore.h" #include "../rtengine/dcp.h" #include "rtimage.h" @@ -598,7 +597,7 @@ void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited) } else if (icameraICC->get_active ()) { pp->icm.input = "(cameraICC)"; } else { - if (safe_file_test (ipDialog->get_filename (), Glib::FILE_TEST_EXISTS) && !safe_file_test (ipDialog->get_filename (), Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (ipDialog->get_filename (), Glib::FILE_TEST_EXISTS) && !Glib::file_test (ipDialog->get_filename (), Glib::FILE_TEST_IS_DIR)) { pp->icm.input = "file:" + ipDialog->get_filename (); } else { pp->icm.input = ""; // just a directory @@ -944,7 +943,7 @@ void ICMPanel::saveReferencePressed () return; } - Gtk::FileChooserDialog dialog(M("TP_ICM_SAVEREFERENCE"), Gtk::FILE_CHOOSER_ACTION_SAVE); + Gtk::FileChooserDialog dialog (getToplevelWindow (this), M("TP_ICM_SAVEREFERENCE"), Gtk::FILE_CHOOSER_ACTION_SAVE); bindCurrentFolder (dialog, options.lastProfilingReferenceDir); dialog.set_current_name (lastRefFilename); diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index b77e90f09..5383058e3 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -56,8 +56,8 @@ ImageArea::ImageArea (ImageAreaPanel* p) : parent(p), firstOpen(true) ImageArea::~ImageArea () { - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { - delete *i; + for (auto cropWin : cropWins) { + delete cropWin; } cropWins.clear (); @@ -96,10 +96,10 @@ void ImageArea::on_resized (Gtk::Allocation& req) mainCropWindow->setPointerMotionListener (pmlistener); mainCropWindow->setPointerMotionHListener (pmhlistener); mainCropWindow->setPosition (0, 0); - mainCropWindow->setSize (get_width(), get_height(), false); // this execute the refresh itself + mainCropWindow->setSize (get_width(), get_height()); // this execute the refresh itself mainCropWindow->enable(); // start processing ! } else { - mainCropWindow->setSize (get_width(), get_height()); + mainCropWindow->setSize (get_width(), get_height()); // this execute the refresh itself } parent->syncBeforeAfterViews(); @@ -110,10 +110,9 @@ void ImageArea::setImProcCoordinator (rtengine::StagedImageProcessor* ipc_) { if( !ipc_ ) { focusGrabber = NULL; - std::list::iterator i = cropWins.begin(); - for( ; i != cropWins.end(); i++ ) { - delete *i; + for (auto cropWin : cropWins) { + delete cropWin; } cropWins.clear(); @@ -170,10 +169,11 @@ CropWindow* ImageArea::getCropWindow (int x, int y) CropWindow* cw = mainCropWindow; - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) - if ((*i)->isInside (x, y)) { - return *i; + for (auto cropWin : cropWins) { + if (cropWin->isInside (x, y)) { + return cropWin; } + } return cw; } @@ -200,7 +200,6 @@ bool ImageArea::on_expose_event(GdkEventExpose* event) Cairo::RefPtr cr = get_window()->create_cairo_context(); if (mainCropWindow) { - //printf("MainCropWindow (%d x %d)\n", window->get_width(), window->get_height()); mainCropWindow->expose (cr); } @@ -275,11 +274,11 @@ bool ImageArea::on_scroll_event (GdkEventScroll* event) int newCenterX = (int)event->x; int newCenterY = (int)event->y; + cw->screenCoordToImage(newCenterX, newCenterY, newCenterX, newCenterY); + if (event->direction == GDK_SCROLL_UP && !cw->isMaxZoom()) { - cw->findCenter (1, newCenterX, newCenterY); cw->zoomIn (true, newCenterX, newCenterY); } else if (!cw->isMinZoom()) { - cw->findCenter (-1, newCenterX, newCenterY); cw->zoomOut (true, newCenterX, newCenterY); } } @@ -327,19 +326,18 @@ bool ImageArea::on_leave_notify_event (GdkEventCrossing* event) void ImageArea::subscribe(EditSubscriber *subscriber) { - mainCropWindow->cropHandler.setEditSubscriber(subscriber); - - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { - (*i)->cropHandler.setEditSubscriber(subscriber); - } - EditDataProvider::subscribe(subscriber); + mainCropWindow->setEditSubscriber(subscriber); + for (auto cropWin : cropWins) { + cropWin->setEditSubscriber(subscriber); + } + if (listener && listener->getToolBar()) { listener->getToolBar()->startEditMode (); } - if (subscriber->getEditingType() == ET_OBJECTS) { + if (subscriber && subscriber->getEditingType() == ET_OBJECTS) { // In this case, no need to reprocess the image, so we redraw the image to display the geometry queue_draw(); } @@ -355,11 +353,11 @@ void ImageArea::unsubscribe() } EditDataProvider::unsubscribe(); - // Ask the Crops to free-up edit mode buffers - mainCropWindow->cropHandler.setEditSubscriber(NULL); - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { - (*i)->cropHandler.setEditSubscriber(NULL); + // Ask the Crops to free-up edit mode buffers + mainCropWindow->setEditSubscriber(NULL); + for (auto cropWin : cropWins) { + cropWin->setEditSubscriber(NULL); } setToolHand(); @@ -473,12 +471,16 @@ void ImageArea::addCropWindow () y = cropheight * (N % maxRows); cw->setPosition (x, y); + cw->setEditSubscriber (getCurrSubscriber()); cw->enable(); // start processing! - int x0, y0, w, h, wc, hc; - mainCropWindow->getCropRectangle(x0, y0, w, h ); - cw->getCropSize(wc, hc); - cw->setCropPosition(x0 + w / 2 - wc / 2, y0 + h / 2 - hc / 2); + { + int anchorX = 0; + int anchorY = 0; + mainCropWindow->getCropAnchorPosition(anchorX, anchorY); + cw->setCropAnchorPosition(anchorX, anchorY); + } + mainCropWindow->setObservedCropWin (cropWins.front()); if(cropWins.size() == 1) { // after first detail window we already have high quality @@ -539,9 +541,8 @@ void ImageArea::getScrollImageSize (int& w, int& h) { if (mainCropWindow && ipc) { - double z = mainCropWindow->getZoom (); - w = ipc->getFullWidth() * z; - h = ipc->getFullHeight() * z; + w = ipc->getFullWidth(); + h = ipc->getFullHeight(); } else { w = h = 0; } @@ -551,10 +552,7 @@ void ImageArea::getScrollPosition (int& x, int& y) { if (mainCropWindow) { - int cropX, cropY; - mainCropWindow->getCropPosition (cropX, cropY); - x = cropX * mainCropWindow->getZoom (); - y = cropY * mainCropWindow->getZoom (); + mainCropWindow->getCropAnchorPosition (x, y); } else { x = y = 0; } @@ -565,7 +563,7 @@ void ImageArea::setScrollPosition (int x, int y) if (mainCropWindow) { mainCropWindow->delCropWindowListener (this); - mainCropWindow->setCropPosition (x / mainCropWindow->getZoom (), y / mainCropWindow->getZoom ()); + mainCropWindow->setCropAnchorPosition (x, y); mainCropWindow->addCropWindowListener (this); } } @@ -618,19 +616,15 @@ void ImageArea::initialImageArrived (CropWindow* cw) if (mainCropWindow) { if(firstOpen || options.prevdemo != PD_Sidecar || (!options.rememberZoomAndPan) ) { - mainCropWindow->zoomFit (false); + mainCropWindow->zoomFit (); firstOpen = false; mainCropWindow->cropHandler.getFullImageSize(fullImageWidth, fullImageHeight); } else { int w, h; mainCropWindow->cropHandler.getFullImageSize(w, h); - if(w == fullImageWidth && h == fullImageHeight) { // && mainCropWindow->getZoom() != mainCropWindow->getZoomFitVal()) { - int x, y; - mainCropWindow->getCropPosition(x, y); - mainCropWindow->setCropPosition(x, y, false); - } else { - mainCropWindow->zoomFit (false); + if(w != fullImageWidth || h != fullImageHeight) { + mainCropWindow->zoomFit (); } fullImageWidth = w; @@ -649,8 +643,8 @@ void ImageArea::setCropGUIListener (CropGUIListener* l) cropgl = l; - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { - (*i)->setCropGUIListener (cropgl); + for (auto cropWin : cropWins) { + cropWin->setCropGUIListener (cropgl); } if (mainCropWindow) { @@ -663,8 +657,8 @@ void ImageArea::setPointerMotionListener (PointerMotionListener* pml) pmlistener = pml; - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { - (*i)->setPointerMotionListener (pml); + for (auto cropWin : cropWins) { + cropWin->setPointerMotionListener (pml); } if (mainCropWindow) { @@ -677,8 +671,8 @@ void ImageArea::setPointerMotionHListener (PointerMotionListener* pml) pmhlistener = pml; - for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { - (*i)->setPointerMotionHListener (pml); + for (auto cropWin : cropWins) { + cropWin->setPointerMotionHListener (pml); } if (mainCropWindow) { diff --git a/rtgui/imageareapanel.cc b/rtgui/imageareapanel.cc index b456de2c7..9a351d66a 100644 --- a/rtgui/imageareapanel.cc +++ b/rtgui/imageareapanel.cc @@ -84,9 +84,7 @@ void ImageAreaPanel::synchronize () after->imageArea->getScrollPosition (x, y); if (imgw > 0 && imgh > 0) { - int bimgw, bimgh; - imageArea->getScrollImageSize (bimgw, bimgh); - imageArea->setScrollPosition (x * bimgw / imgw, y * bimgh / imgh); + imageArea->setScrollPosition (x, y); imageArea->queue_draw (); } } else if (before && this == after) { @@ -95,9 +93,7 @@ void ImageAreaPanel::synchronize () before->imageArea->getScrollPosition (x, y); if (imgw > 0 && imgh > 0) { - int bimgw, bimgh; - imageArea->getScrollImageSize (bimgw, bimgh); - imageArea->setScrollPosition (x * bimgw / imgw, y * bimgh / imgh); + imageArea->setScrollPosition (x, y); imageArea->queue_draw (); } } diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc index 291339414..6c4891249 100644 --- a/rtgui/inspector.cc +++ b/rtgui/inspector.cc @@ -22,14 +22,13 @@ #include "cursormanager.h" #include "guiutils.h" #include "options.h" -#include "../rtengine/safegtk.h" #include "../rtengine/previewimage.h" extern Options options; InspectorBuffer::InspectorBuffer(const Glib::ustring &imagePath) : currTransform(0), fromRaw(false) { - if (!imagePath.empty() && safe_file_test(imagePath, Glib::FILE_TEST_EXISTS) && !safe_file_test(imagePath, Glib::FILE_TEST_IS_DIR)) { + if (!imagePath.empty() && Glib::file_test(imagePath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(imagePath, Glib::FILE_TEST_IS_DIR)) { imgPath = imagePath; // generate thumbnail image diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index f85fb79c0..eda3992c3 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -19,7 +19,6 @@ #include #include "lensprofile.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include "../rtengine/lcp.h" #include #include "rtimage.h" diff --git a/rtgui/main.cc b/rtgui/main.cc index 03b85654e..4a4511f34 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -54,8 +54,6 @@ #include "conio.h" #endif -#include "../rtengine/safegtk.h" - extern Options options; // stores path to data files @@ -66,6 +64,29 @@ Glib::ustring argv1; bool simpleEditor; Glib::Thread* mainThread; +namespace +{ + +// For an unknown reason, Glib::filename_to_utf8 doesn't work on reliably Windows, +// so we're using Glib::filename_to_utf8 for Linux/Apple and Glib::locale_to_utf8 for Windows. +Glib::ustring fname_to_utf8 (const char* fname) +{ +#ifdef WIN32 + + try { + return Glib::locale_to_utf8 (fname); + } catch (Glib::Error&) { + return Glib::convert_with_fallback (fname, "UTF-8", "ISO-8859-1", "?"); + } + +#else + + return Glib::filename_to_utf8 (fname); + +#endif +} + +} // This recursive mutex will be used by gdk_threads_enter/leave instead of a simple mutex #ifdef WIN32 @@ -170,7 +191,7 @@ int main(int argc, char **argv) bool consoleOpened = false; if (argc > 1 || options.rtSettings.verbose) { - if(options.rtSettings.verbose || ( !safe_file_test( safe_filename_to_utf8(argv[1]), Glib::FILE_TEST_EXISTS ) && !safe_file_test( safe_filename_to_utf8(argv[1]), Glib::FILE_TEST_IS_DIR ))) { + if (options.rtSettings.verbose || ( !Glib::file_test (fname_to_utf8 (argv[1]), Glib::FILE_TEST_EXISTS ) && !Glib::file_test (fname_to_utf8 (argv[1]), Glib::FILE_TEST_IS_DIR))) { bool stdoutRedirectedtoFile = (GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == 0x0001); bool stderrRedirectedtoFile = (GetFileType(GetStdHandle(STD_ERROR_HANDLE)) == 0x0001); @@ -263,8 +284,8 @@ int main(int argc, char **argv) #ifndef WIN32 // Move the old path to the new one if the new does not exist - if (safe_file_test(Glib::build_filename(options.rtdir, "cache"), Glib::FILE_TEST_IS_DIR) && !safe_file_test(options.cacheBaseDir, Glib::FILE_TEST_IS_DIR)) { - safe_g_rename(Glib::build_filename(options.rtdir, "cache"), options.cacheBaseDir); + if (Glib::file_test(Glib::build_filename(options.rtdir, "cache"), Glib::FILE_TEST_IS_DIR) && !Glib::file_test(options.cacheBaseDir, Glib::FILE_TEST_IS_DIR)) { + g_rename(Glib::build_filename (options.rtdir, "cache").c_str (), options.cacheBaseDir.c_str ()); } #endif @@ -272,7 +293,7 @@ int main(int argc, char **argv) simpleEditor = false; if( !argv1.empty() ) - if( safe_file_test(argv1, Glib::FILE_TEST_EXISTS) && !safe_file_test(argv1, Glib::FILE_TEST_IS_DIR)) { + if( Glib::file_test(argv1, Glib::FILE_TEST_EXISTS) && !Glib::file_test(argv1, Glib::FILE_TEST_IS_DIR)) { simpleEditor = true; } @@ -395,9 +416,9 @@ int processLineParams( int argc, char **argv ) case 'o': // outputfile or dir if( iArg + 1 < argc ) { iArg++; - outputPath = safe_filename_to_utf8 (argv[iArg]); + outputPath = fname_to_utf8 (argv[iArg]); - if( safe_file_test (outputPath, Glib::FILE_TEST_IS_DIR)) { + if( Glib::file_test (outputPath, Glib::FILE_TEST_IS_DIR)) { outputDirectory = true; } } @@ -409,7 +430,7 @@ int processLineParams( int argc, char **argv ) // RT stop if any of them can't be loaded for any reason. if( iArg + 1 < argc ) { iArg++; - Glib::ustring fname = safe_filename_to_utf8 ( argv[iArg] ); + Glib::ustring fname = fname_to_utf8 (argv[iArg]); if (fname.at(0) == '-') { std::cerr << "Error: filename missing next to the -p switch" << std::endl; @@ -497,39 +518,54 @@ int processLineParams( int argc, char **argv ) break; case 'c': // MUST be last option - while( iArg + 1 < argc ) { + while (iArg + 1 < argc) { iArg++; - if( !safe_file_test( safe_filename_to_utf8(argv[iArg]), Glib::FILE_TEST_EXISTS )) { - std::cerr << argv[iArg] << " doesn't exist." << std::endl; + const auto argument = fname_to_utf8 (argv[iArg]); + + if (Glib::file_test (argument, Glib::FILE_TEST_IS_REGULAR)) { + inputFiles.emplace_back (argument); continue; } - if( safe_file_test( safe_filename_to_utf8(argv[iArg]), Glib::FILE_TEST_IS_DIR )) { - std::vector names; - Glib::RefPtr dir = Gio::File::create_for_path ( argv[iArg] ); - safe_build_file_list (dir, names, argv[iArg] ); + if (Glib::file_test (argument, Glib::FILE_TEST_IS_DIR)) { - for(size_t iFile = 0; iFile < names.size(); iFile++ ) { - if( !safe_file_test( names[iFile] , Glib::FILE_TEST_IS_DIR)) { - // skip files without extension and without sidecar files - Glib::ustring s(names[iFile]); - Glib::ustring::size_type ext = s.find_last_of('.'); - - if( Glib::ustring::npos == ext ) { - continue; - } - - if( ! s.substr(ext).compare( paramFileExtension )) { - continue; - } - - inputFiles.push_back( names[iFile] ); - } + auto dir = Gio::File::create_for_path (argument); + if (!dir || !dir->query_exists()) { + continue; } - } else { - inputFiles.push_back( safe_filename_to_utf8 (argv[iArg]) ); + + try { + + auto enumerator = dir->enumerate_children (); + + while (auto file = enumerator->next_file ()) { + + const auto fileName = Glib::build_filename (argument, file->get_name ()); + + if (Glib::file_test (fileName, Glib::FILE_TEST_IS_DIR)) { + continue; + } + + // skip files without extension and sidecar files + auto lastdot = fileName.find_last_of('.'); + if (lastdot == Glib::ustring::npos) { + continue; + } + + if (fileName.substr (lastdot).compare (paramFileExtension) == 0) { + continue; + } + + inputFiles.emplace_back (fileName); + } + + } catch (Glib::Exception&) {} + + continue; } + + std::cerr << "\"" << argument << "\" is neither a regular file nor a directory." << std::endl; } break; @@ -600,7 +636,7 @@ int processLineParams( int argc, char **argv ) } } } else { - argv1 = safe_filename_to_utf8 ( argv[iArg] ); + argv1 = fname_to_utf8 (argv[iArg]); if( outputDirectory ) { options.savePathFolder = outputPath; @@ -701,7 +737,7 @@ int processLineParams( int argc, char **argv ) continue; } - if( !overwriteFiles && safe_file_test( outputFile , Glib::FILE_TEST_EXISTS ) ) { + if( !overwriteFiles && Glib::file_test( outputFile , Glib::FILE_TEST_EXISTS ) ) { std::cerr << outputFile << " already exists: use -Y option to overwrite. This image has been skipped." << std::endl; continue; } @@ -742,7 +778,7 @@ int processLineParams( int argc, char **argv ) Glib::ustring sideProcessingParams = inputFile + paramFileExtension; // the "load" method don't reset the procparams values anymore, so values found in the procparam file override the one of currentParams - if( !safe_file_test( sideProcessingParams, Glib::FILE_TEST_EXISTS ) || currentParams.load ( sideProcessingParams )) { + if( !Glib::file_test( sideProcessingParams, Glib::FILE_TEST_EXISTS ) || currentParams.load ( sideProcessingParams )) { std::cerr << "Warning: sidecar file requested but not found for: " << sideProcessingParams << std::endl; } else { sideCarFound = true; diff --git a/rtgui/mycurve.h b/rtgui/mycurve.h index 96574e12a..ba3158ac9 100644 --- a/rtgui/mycurve.h +++ b/rtgui/mycurve.h @@ -146,7 +146,7 @@ public: virtual void reset (const std::vector &resetCurve, double identityValue = 0.5) = 0; virtual void pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey) = 0; - virtual void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) = 0; + virtual bool pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) = 0; virtual void pipetteButton1Released(EditDataProvider *provider) = 0; virtual void pipetteDrag(EditDataProvider *provider, int modifierKey) = 0; diff --git a/rtgui/mydiagonalcurve.cc b/rtgui/mydiagonalcurve.cc index 98eb6c283..2a70e9b7c 100644 --- a/rtgui/mydiagonalcurve.cc +++ b/rtgui/mydiagonalcurve.cc @@ -1071,11 +1071,11 @@ void MyDiagonalCurve::pipetteMouseOver (CurveEditor *ce, EditDataProvider *provi } } - -void MyDiagonalCurve::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) +// returns true if a point is being dragged +bool MyDiagonalCurve::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) { if (edited_point > 1) { - return; + return false; } int num = (int)curve.x.size(); @@ -1086,7 +1086,7 @@ void MyDiagonalCurve::pipetteButton1Pressed(EditDataProvider *provider, int modi double minDistanceX = double(MIN_DISTANCE) / double(graphW - 1); if ((graphW < 0) || (graphH < 0)) { - return; + return false; } snapToElmt = -100; @@ -1141,7 +1141,11 @@ void MyDiagonalCurve::pipetteButton1Pressed(EditDataProvider *provider, int modi lit_point = closest_point; ugpX = curve.x.at(closest_point); ugpY = curve.y.at(closest_point); + + return true; } + + return false; } void MyDiagonalCurve::pipetteButton1Released(EditDataProvider *provider) diff --git a/rtgui/mydiagonalcurve.h b/rtgui/mydiagonalcurve.h index 033ba9f95..45b23e965 100644 --- a/rtgui/mydiagonalcurve.h +++ b/rtgui/mydiagonalcurve.h @@ -90,7 +90,7 @@ public: void updateBackgroundHistogram (LUTu & hist); void pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey); - void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); + bool pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); void pipetteButton1Released(EditDataProvider *provider); void pipetteDrag(EditDataProvider *provider, int modifierKey); diff --git a/rtgui/myflatcurve.cc b/rtgui/myflatcurve.cc index 474756834..fe53565d2 100644 --- a/rtgui/myflatcurve.cc +++ b/rtgui/myflatcurve.cc @@ -1288,10 +1288,11 @@ void MyFlatCurve::pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, } } -void MyFlatCurve::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) +// returns true if a point is being dragged +bool MyFlatCurve::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) { if (edited_point > -1) { - return; + return false; } buttonPressed = true; @@ -1368,6 +1369,7 @@ void MyFlatCurve::pipetteButton1Pressed(EditDataProvider *provider, int modifier break; } + return true; } void MyFlatCurve::pipetteButton1Released(EditDataProvider *provider) diff --git a/rtgui/myflatcurve.h b/rtgui/myflatcurve.h index cd08edf89..7949a4df6 100644 --- a/rtgui/myflatcurve.h +++ b/rtgui/myflatcurve.h @@ -130,7 +130,7 @@ public: //void updateBackgroundHistogram (unsigned int* hist); void pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey); - void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); + bool pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); void pipetteButton1Released(EditDataProvider *provider); void pipetteDrag(EditDataProvider *provider, int modifierKey); diff --git a/rtgui/options.cc b/rtgui/options.cc index a94fb0945..e723361be 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -21,10 +21,8 @@ #include #include #include "multilangmgr.h" -#include "../rtengine/safekeyfile.h" #include "addsetids.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include "version.h" #ifdef _OPENMP @@ -70,13 +68,13 @@ inline bool Options::checkProfilePath(Glib::ustring &path) Glib::ustring p = getUserProfilePath(); - if (!p.empty() && safe_file_test (path + paramFileExtension, Glib::FILE_TEST_EXISTS)) { + if (!p.empty() && Glib::file_test (path + paramFileExtension, Glib::FILE_TEST_EXISTS)) { return true; } p = getGlobalProfilePath(); - if (!p.empty() && safe_file_test (path + paramFileExtension, Glib::FILE_TEST_EXISTS)) { + if (!p.empty() && Glib::file_test (path + paramFileExtension, Glib::FILE_TEST_EXISTS)) { return true; } else { return false; @@ -85,7 +83,7 @@ inline bool Options::checkProfilePath(Glib::ustring &path) bool Options::checkDirPath(Glib::ustring &path, Glib::ustring errString) { - if (safe_file_test (path, Glib::FILE_TEST_EXISTS) && safe_file_test (path, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (path, Glib::FILE_TEST_EXISTS) && Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) { return true; } else { if (!errString.empty()) { @@ -107,7 +105,7 @@ void Options::updatePaths() if (Glib::path_is_absolute(profilePath)) { // absolute path if (!checkDirPath (profilePath, "")) { - safe_g_mkdir_with_parents (profilePath, 511); + g_mkdir_with_parents (profilePath.c_str (), 511); if (!checkDirPath (profilePath, "")) { // had problems with mkdir_with_parents return value on OS X, just check dir again printf("Error: user's profiles' directory \"%s\" creation failed\n", profilePath.c_str()); @@ -140,7 +138,7 @@ void Options::updatePaths() tmpPath = Glib::build_filename(rtdir, profilePath); if (!checkDirPath (tmpPath, "")) { - safe_g_mkdir_with_parents (tmpPath, 511); + g_mkdir_with_parents (tmpPath.c_str (), 511); if (!checkDirPath (tmpPath, "")) { printf("Error: user's profiles' directory \"%s\" creation failed\n", tmpPath.c_str()); @@ -170,51 +168,51 @@ void Options::updatePaths() Glib::ustring preferredPath = getPreferredProfilePath(); // Paths are updated only if the user or global profile path is set - if (lastRgbCurvesDir.empty() || !safe_file_test (lastRgbCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastRgbCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastRgbCurvesDir.empty() || !Glib::file_test (lastRgbCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastRgbCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastRgbCurvesDir = preferredPath; } - if (lastLabCurvesDir.empty() || !safe_file_test (lastLabCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastLabCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastLabCurvesDir.empty() || !Glib::file_test (lastLabCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastLabCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastLabCurvesDir = preferredPath; } - if (lastRetinexDir.empty() || !safe_file_test (lastRetinexDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastLabCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastRetinexDir.empty() || !Glib::file_test (lastRetinexDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastLabCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastRetinexDir = preferredPath; } - if (lastDenoiseCurvesDir.empty() || !safe_file_test (lastDenoiseCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastDenoiseCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastDenoiseCurvesDir.empty() || !Glib::file_test (lastDenoiseCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastDenoiseCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastDenoiseCurvesDir = preferredPath; } - if (lastWaveletCurvesDir.empty() || !safe_file_test (lastWaveletCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastWaveletCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastWaveletCurvesDir.empty() || !Glib::file_test (lastWaveletCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastWaveletCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastWaveletCurvesDir = preferredPath; } - if (lastPFCurvesDir.empty() || !safe_file_test (lastPFCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastPFCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastPFCurvesDir.empty() || !Glib::file_test (lastPFCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastPFCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastPFCurvesDir = preferredPath; } - if (lastHsvCurvesDir.empty() || !safe_file_test (lastHsvCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastHsvCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastHsvCurvesDir.empty() || !Glib::file_test (lastHsvCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastHsvCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastHsvCurvesDir = preferredPath; } - if (lastToneCurvesDir.empty() || !safe_file_test (lastToneCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastToneCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastToneCurvesDir.empty() || !Glib::file_test (lastToneCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastToneCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastToneCurvesDir = preferredPath; } - if (lastProfilingReferenceDir.empty() || !safe_file_test (lastProfilingReferenceDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastProfilingReferenceDir, Glib::FILE_TEST_IS_DIR)) { + if (lastProfilingReferenceDir.empty() || !Glib::file_test (lastProfilingReferenceDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastProfilingReferenceDir, Glib::FILE_TEST_IS_DIR)) { lastProfilingReferenceDir = preferredPath; } - if (lastVibranceCurvesDir.empty() || !safe_file_test (lastVibranceCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastVibranceCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastVibranceCurvesDir.empty() || !Glib::file_test (lastVibranceCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastVibranceCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastVibranceCurvesDir = preferredPath; } - if (loadSaveProfilePath.empty() || !safe_file_test (loadSaveProfilePath, Glib::FILE_TEST_EXISTS) || !safe_file_test (loadSaveProfilePath, Glib::FILE_TEST_IS_DIR)) { + if (loadSaveProfilePath.empty() || !Glib::file_test (loadSaveProfilePath, Glib::FILE_TEST_EXISTS) || !Glib::file_test (loadSaveProfilePath, Glib::FILE_TEST_IS_DIR)) { loadSaveProfilePath = preferredPath; } - if (lastBWCurvesDir.empty() || !safe_file_test (lastBWCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastBWCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastBWCurvesDir.empty() || !Glib::file_test (lastBWCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastBWCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastBWCurvesDir = preferredPath; } @@ -255,7 +253,7 @@ Glib::ustring Options::findProfilePath(Glib::ustring &profName) p = getUserProfilePath(); Glib::ustring fullPath = Glib::build_filename(p, profName.substr(5) + paramFileExtension); - if (!p.empty() && safe_file_test (fullPath, Glib::FILE_TEST_EXISTS)) { + if (!p.empty() && Glib::file_test (fullPath, Glib::FILE_TEST_EXISTS)) { return Glib::path_get_dirname(fullPath); } } else if (p == "${G}") { @@ -263,7 +261,7 @@ Glib::ustring Options::findProfilePath(Glib::ustring &profName) p = getGlobalProfilePath(); Glib::ustring fullPath = Glib::build_filename(p, profName.substr(5) + paramFileExtension); - if (!p.empty() && safe_file_test (fullPath, Glib::FILE_TEST_EXISTS)) { + if (!p.empty() && Glib::file_test (fullPath, Glib::FILE_TEST_EXISTS)) { return Glib::path_get_dirname(fullPath); } } else { @@ -271,7 +269,7 @@ Glib::ustring Options::findProfilePath(Glib::ustring &profName) p = getUserProfilePath(); Glib::ustring fullPath = Glib::build_filename(p, profName + paramFileExtension); - if (!p.empty() && safe_file_test (fullPath, Glib::FILE_TEST_EXISTS)) { + if (!p.empty() && Glib::file_test (fullPath, Glib::FILE_TEST_EXISTS)) { // update the profile path profName = Glib::build_filename("${U}", profName); return Glib::path_get_dirname(fullPath); @@ -280,7 +278,7 @@ Glib::ustring Options::findProfilePath(Glib::ustring &profName) p = getGlobalProfilePath(); fullPath = Glib::build_filename(p, profName + paramFileExtension); - if (!p.empty() && safe_file_test (fullPath, Glib::FILE_TEST_EXISTS)) { + if (!p.empty() && Glib::file_test (fullPath, Glib::FILE_TEST_EXISTS)) { profName = Glib::build_filename("${G}", profName); return Glib::path_get_dirname(fullPath); } @@ -500,116 +498,114 @@ void Options::setDefaults () #endif // Reminder: 0 = SET mode, 1 = ADD mode - int babehav[] = { - 0, // ADDSET_TC_EXPCOMP - 0, // ADDSET_TC_BRIGHTNESS - 0, // ADDSET_TC_BLACKLEVEL - 0, // ADDSET_TC_CONTRAST - 0, // ADDSET_SH_HIGHLIGHTS - 0, // ADDSET_SH_SHADOWS - 0, // ADDSET_SH_LOCALCONTRAST - 0, // ADDSET_LC_BRIGHTNESS - 0, // ADDSET_LC_CONTRAST - 0, // ADDSET_SHARP_AMOUNT - 0, // ADDSET_WB_TEMPERATURE - 0, // ADDSET_WB_GREEN - 0, // ADDSET_ROTATE_DEGREE - 0, // ADDSET_DIST_AMOUNT - 0, // ADDSET_PERSPECTIVE - 0, // ADDSET_CA - 0, // ADDSET_VIGN_AMOUNT - 0, // ADDSET_VIGN_RADIUS - 0, // ADDSET_VIGN_STRENGTH - 0, // ADDSET_VIGN_CENTER - 0, // ADDSET_LC_CHROMATICITY - 0, // ADDSET_TC_SATURATION - 0, // ADDSET_TC_HLCOMPAMOUNT - 0, // ADDSET_TC_HLCOMPTHRESH - 0, // ADDSET_TC_SHCOMP - 0, // ADDSET_DIRPYREQ - 0, // ADDSET_DIRPYRDN_LUMA - 0, // ADDSET_DIRPYRDN_LUDET - 0, // ADDSET_DIRPYRDN_CHROMA - 0, // ADDSET_DIRPYRDN_CHROMARED - 0, // ADDSET_DIRPYRDN_CHROMABLUE - 0, // ADDSET_DIRPYRDN_GAMMA - 0, // ADDSET_CHMIXER - 0, // ADDSET_PREPROCESS_GREENEQUIL - 0, // ADDSET_PREPROCESS_LINEDENOISE - 0, // ADDSET_RAWCACORR - 0, // ADDSET_RAWEXPOS_LINEAR - 0, // ADDSET_RAWEXPOS_PRESER - 0, // ADDSET_RAWEXPOS_BLACKS - 0, // ADDSET_SHARPENEDGE_AMOUNT - 0, // ADDSET_SHARPENMICRO_AMOUNT - 0, // ADDSET_SHARPENEDGE_PASS - 0, // ADDSET_SHARPENMICRO_UNIFORMITY - 0, // ADDSET_VIBRANCE_PASTELS - 0, // ADDSET_VIBRANCE_SATURATED - 0, // ADDSET_FREE_OUPUT_GAMMA - 0, // ADDSET_FREE_OUTPUT_SLOPE - 0, // ADDSET_CAT_DEGREE - 0, // ADDSET_CAT_ADAPSCEN - 0, // ADDSET_CAT_ADAPLUM - 0, // ADDSET_CAT_LIGHT - 0, // ADDSET_CAT_RSTPRO - 0, // ADDSET_CAT_BADPIX - 0, // ADDSET_CAT_JLIGHT - 0, // ADDSET_CAT_CHROMA - 0, // ADDSET_CAT_CONTRAST - 0, // ADDSET_CAT_CHROMA_S - 0, // ADDSET_CAT_CHROMA_M - 0, // ADDSET_CAT_HUE - 0, // ADDSET_CAT_BADPIX - 0, // ADDSET_WB_EQUAL - 0, // ADDSET_GRADIENT_DEGREE - 0, // ADDSET_GRADIENT_FEATHER - 0, // ADDSET_GRADIENT_STRENGTH - 0, // ADDSET_GRADIENT_CENTER - 0, // ADDSET_PCVIGNETTE_STRENGTH - 0, // ADDSET_PCVIGNETTE_FEATHER - 0, // ADDSET_PCVIGNETTE_ROUNDNESS - 0, // ADDSET_BLACKWHITE_HUES - 0, // ADDSET_BLACKWHITE_GAMMA - 0, // ADDSET_DIRPYREQ_THRESHOLD - 0, // ADDSET_DIRPYREQ_SKINPROTECT - 0, // ADDSET_COLORTONING_SPLIT - 0, //ADDSET_DIRPYRDN_PASSES - 0, // ADDSET_RAWFFCLIPCONTROL - 0, // ADDSET_FILMSIMULATION_STRENGTH - 0, //ADDSET_WA - 0, //ADDSET_WA_THRESHOLD - 0, //ADDSET_WA_THRESHOLD2 - 0, //ADDSET_WA_THRES - 0, //ADDSET_WA_CHRO - 0, //ADDSET_WA_CHROMA - 0, //ADDSET_WA_CONTRAST - 0, //ADDSET_WA_SKINPROTECT - 0, //ADDSET_WA_RESCHRO - 0, //ADDSET_WA_RESCON - 0, //ADDSET_WA_RESCONH - 0, //ADDSET_WA_THRR - 0, //ADDSET_WA_THRRH - 0, //ADDSET_WA_SKYPROTECT - 0, //ADDSET_WA_EDGRAD - 0, //ADDSET_WA_EDGVAL - 0, //ADDSET_WA_STRENGTH - 0, //ADDSET_WA_EDGEDETECT - 0, //ADDSET_WA_EDGEDETECTTHR - 0, //ADDSET_WA_EDGEDETECTTHR2 - 0, //ADDSET_WA_TMRS - 0, //ADDSET_WA_GAMMA - 0, //ADDSET_RETI_STR - 0, //ADDSET_RETI_NEIGH - 0, //ADDSET_RETI_LIMD - 0, //ADDSET_RETI_GAIN - 0, //ADDSET_RETI_OFFS - 0, //ADDSET_RETI_VART - 0, //ADDSET_RETI_GAM - 0, //ADDSET_RETI_SLO - + baBehav = { + 0, // ADDSET_TC_EXPCOMP + 0, // ADDSET_TC_BRIGHTNESS + 0, // ADDSET_TC_BLACKLEVEL + 0, // ADDSET_TC_CONTRAST + 0, // ADDSET_SH_HIGHLIGHTS + 0, // ADDSET_SH_SHADOWS + 0, // ADDSET_SH_LOCALCONTRAST + 0, // ADDSET_LC_BRIGHTNESS + 0, // ADDSET_LC_CONTRAST + 0, // ADDSET_SHARP_AMOUNT + 0, // ADDSET_WB_TEMPERATURE + 0, // ADDSET_WB_GREEN + 0, // ADDSET_ROTATE_DEGREE + 0, // ADDSET_DIST_AMOUNT + 0, // ADDSET_PERSPECTIVE + 0, // ADDSET_CA + 0, // ADDSET_VIGN_AMOUNT + 0, // ADDSET_VIGN_RADIUS + 0, // ADDSET_VIGN_STRENGTH + 0, // ADDSET_VIGN_CENTER + 0, // ADDSET_LC_CHROMATICITY + 0, // ADDSET_TC_SATURATION + 0, // ADDSET_TC_HLCOMPAMOUNT + 0, // ADDSET_TC_HLCOMPTHRESH + 0, // ADDSET_TC_SHCOMP + 0, // ADDSET_DIRPYREQ + 0, // ADDSET_DIRPYRDN_LUMA + 0, // ADDSET_DIRPYRDN_LUDET + 0, // ADDSET_DIRPYRDN_CHROMA + 0, // ADDSET_DIRPYRDN_CHROMARED + 0, // ADDSET_DIRPYRDN_CHROMABLUE + 0, // ADDSET_DIRPYRDN_GAMMA + 0, // ADDSET_CHMIXER + 0, // ADDSET_PREPROCESS_GREENEQUIL + 0, // ADDSET_PREPROCESS_LINEDENOISE + 0, // ADDSET_RAWCACORR + 0, // ADDSET_RAWEXPOS_LINEAR + 0, // ADDSET_RAWEXPOS_PRESER + 0, // ADDSET_RAWEXPOS_BLACKS + 0, // ADDSET_SHARPENEDGE_AMOUNT + 0, // ADDSET_SHARPENMICRO_AMOUNT + 0, // ADDSET_SHARPENEDGE_PASS + 0, // ADDSET_SHARPENMICRO_UNIFORMITY + 0, // ADDSET_VIBRANCE_PASTELS + 0, // ADDSET_VIBRANCE_SATURATED + 0, // ADDSET_FREE_OUPUT_GAMMA + 0, // ADDSET_FREE_OUTPUT_SLOPE + 0, // ADDSET_CAT_DEGREE + 0, // ADDSET_CAT_ADAPSCEN + 0, // ADDSET_CAT_ADAPLUM + 0, // ADDSET_CAT_LIGHT + 0, // ADDSET_CAT_RSTPRO + 0, // ADDSET_CAT_BADPIX + 0, // ADDSET_CAT_JLIGHT + 0, // ADDSET_CAT_CHROMA + 0, // ADDSET_CAT_CONTRAST + 0, // ADDSET_CAT_CHROMA_S + 0, // ADDSET_CAT_CHROMA_M + 0, // ADDSET_CAT_HUE + 0, // ADDSET_CAT_BADPIX + 0, // ADDSET_WB_EQUAL + 0, // ADDSET_GRADIENT_DEGREE + 0, // ADDSET_GRADIENT_FEATHER + 0, // ADDSET_GRADIENT_STRENGTH + 0, // ADDSET_GRADIENT_CENTER + 0, // ADDSET_PCVIGNETTE_STRENGTH + 0, // ADDSET_PCVIGNETTE_FEATHER + 0, // ADDSET_PCVIGNETTE_ROUNDNESS + 0, // ADDSET_BLACKWHITE_HUES + 0, // ADDSET_BLACKWHITE_GAMMA + 0, // ADDSET_DIRPYREQ_THRESHOLD + 0, // ADDSET_DIRPYREQ_SKINPROTECT + 0, // ADDSET_COLORTONING_SPLIT + 0, // ADDSET_DIRPYRDN_PASSES + 0, // ADDSET_RAWFFCLIPCONTROL + 0, // ADDSET_FILMSIMULATION_STRENGTH + 0, // ADDSET_WA + 0, // ADDSET_WA_THRESHOLD + 0, // ADDSET_WA_THRESHOLD2 + 0, // ADDSET_WA_THRES + 0, // ADDSET_WA_CHRO + 0, // ADDSET_WA_CHROMA + 0, // ADDSET_WA_CONTRAST + 0, // ADDSET_WA_SKINPROTECT + 0, // ADDSET_WA_RESCHRO + 0, // ADDSET_WA_RESCON + 0, // ADDSET_WA_RESCONH + 0, // ADDSET_WA_THRR + 0, // ADDSET_WA_THRRH + 0, // ADDSET_WA_SKYPROTECT + 0, // ADDSET_WA_EDGRAD + 0, // ADDSET_WA_EDGVAL + 0, // ADDSET_WA_STRENGTH + 0, // ADDSET_WA_EDGEDETECT + 0, // ADDSET_WA_EDGEDETECTTHR + 0, // ADDSET_WA_EDGEDETECTTHR2 + 0, // ADDSET_WA_TMRS + 0, // ADDSET_WA_GAMMA + 0, // ADDSET_RETI_STR + 0, // ADDSET_RETI_NEIGH + 0, // ADDSET_RETI_LIMD + 0, // ADDSET_RETI_GAIN + 0, // ADDSET_RETI_OFFS + 0, // ADDSET_RETI_VART + 0, // ADDSET_RETI_GAM + 0, // ADDSET_RETI_SLO }; - baBehav = std::vector (babehav, babehav + ADDSET_PARAM_NUM); rtSettings.darkFramesPath = ""; rtSettings.flatFieldsPath = ""; @@ -648,6 +644,7 @@ void Options::setDefaults () rtSettings.bruce = "Bruce"; rtSettings.beta = "BetaRGB"; rtSettings.best = "BestRGB"; + rtSettings.rec2020 = "Rec2020"; rtSettings.verbose = false; rtSettings.gamutICC = true; rtSettings.gamutLch = true; @@ -727,9 +724,10 @@ void Options::filterOutParsedExtensions () int Options::readFromFile (Glib::ustring fname) { setlocale(LC_NUMERIC, "C"); // to set decimal point to "." - rtengine::SafeKeyFile keyFile; - if( !safe_file_test(fname, Glib::FILE_TEST_EXISTS)) { + Glib::KeyFile keyFile; + + if( !Glib::file_test(fname, Glib::FILE_TEST_EXISTS)) { return 1; } @@ -1545,6 +1543,10 @@ int Options::readFromFile (Glib::ustring fname) rtSettings.best = keyFile.get_string("Color Management", "Best"); } + if( keyFile.has_key ("Color Management", "Rec2020")) { + rtSettings.rec2020 = keyFile.get_string("Color Management", "Rec2020"); + } + if( keyFile.has_key ("Color Management", "Bruce")) { rtSettings.bruce = keyFile.get_string("Color Management", "Bruce"); } @@ -1779,23 +1781,31 @@ int Options::readFromFile (Glib::ustring fname) if (options.rtSettings.verbose) { printf("Options::readFromFile / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str()); } + + setDefaults (); } catch (...) { if (options.rtSettings.verbose) { printf("Options::readFromFile / Unknown exception while trying to load \"%s\"!\n", fname.c_str()); } + + setDefaults (); } return 1; } -bool Options::safeDirGet(const rtengine::SafeKeyFile& keyFile, const Glib::ustring& section, +bool Options::safeDirGet(const Glib::KeyFile& keyFile, const Glib::ustring& section, const Glib::ustring& entryName, Glib::ustring& destination) { - if (keyFile.has_key(section, entryName) && !keyFile.get_string(section, entryName).empty()) { - destination = keyFile.get_string(section, entryName); - return true; - } + try { + + if (keyFile.has_key (section, entryName) && !keyFile.get_string (section, entryName).empty ()) { + destination = keyFile.get_string (section, entryName); + return true; + } + + } catch(Glib::KeyFileError&) {} return false; } @@ -1803,309 +1813,322 @@ bool Options::safeDirGet(const rtengine::SafeKeyFile& keyFile, const Glib::ustri int Options::saveToFile (Glib::ustring fname) { - rtengine::SafeKeyFile keyFile; - keyFile.set_boolean ("General", "TabbedEditor", tabbedUI); + Glib::ustring keyData; - keyFile.set_boolean ("General", "StoreLastProfile", savesParamsAtExit); + try { - if (startupDir == STARTUPDIR_HOME) { - keyFile.set_string ("General", "StartupDirectory", "home"); - } else if (startupDir == STARTUPDIR_CURRENT) { - keyFile.set_string ("General", "StartupDirectory", "current"); - } else if (startupDir == STARTUPDIR_CUSTOM) { - keyFile.set_string ("General", "StartupDirectory", "custom"); - } else if (startupDir == STARTUPDIR_LAST) { - keyFile.set_string ("General", "StartupDirectory", "last"); - } + Glib::KeyFile keyFile; - keyFile.set_string ("General", "StartupPath", startupPath); - keyFile.set_string ("General", "DateFormat", dateFormat); - keyFile.set_integer ("General", "AdjusterMinDelay", adjusterMinDelay); - keyFile.set_integer ("General", "AdjusterMaxDelay", adjusterMaxDelay); - keyFile.set_boolean ("General", "MultiUser", multiUser); - keyFile.set_string ("General", "Language", language); - keyFile.set_boolean ("General", "LanguageAutoDetect", languageAutoDetect); - keyFile.set_string ("General", "Theme", theme); - keyFile.set_boolean ("General", "SlimUI", slimUI); - keyFile.set_boolean ("General", "UseSystemTheme", useSystemTheme); - keyFile.set_string ("General", "Version", VERSION); - keyFile.set_string ("General", "DarkFramesPath", rtSettings.darkFramesPath); - keyFile.set_string ("General", "FlatFieldsPath", rtSettings.flatFieldsPath); - keyFile.set_boolean ("General", "Verbose", rtSettings.verbose); - keyFile.set_double ("General", "BotLeft", rtSettings.bot_left); - keyFile.set_double ("General", "TopLeft", rtSettings.top_left); - keyFile.set_double ("General", "TopRight", rtSettings.top_right); - keyFile.set_double ("General", "BotRight", rtSettings.bot_right); - keyFile.set_double ("General", "EDdetec", rtSettings.ed_detec); - keyFile.set_double ("General", "EDdetecStr", rtSettings.ed_detecStr); - keyFile.set_double ("General", "EDLow", rtSettings.ed_low); - keyFile.set_double ("General", "EDLipinfl", rtSettings.ed_lipinfl); - keyFile.set_double ("General", "EDLipampl", rtSettings.ed_lipampl); + keyFile.set_boolean ("General", "TabbedEditor", tabbedUI); + keyFile.set_boolean ("General", "StoreLastProfile", savesParamsAtExit); - - keyFile.set_integer ("External Editor", "EditorKind", editorToSendTo); - keyFile.set_string ("External Editor", "GimpDir", gimpDir); - keyFile.set_string ("External Editor", "PhotoshopDir", psDir); - keyFile.set_string ("External Editor", "CustomEditor", customEditorProg); - - keyFile.set_boolean ("File Browser", "BrowseOnlyRaw", fbOnlyRaw); - keyFile.set_boolean ("File Browser", "BrowserShowsDate", fbShowDateTime); - keyFile.set_boolean ("File Browser", "BrowserShowsExif", fbShowBasicExif); - keyFile.set_boolean ("File Browser", "BrowserShowsExpComp", fbShowExpComp); - keyFile.set_boolean ("File Browser", "BrowserShowsHidden", fbShowHidden); - keyFile.set_integer ("File Browser", "ThumbnailSize", thumbSize); - keyFile.set_integer ("File Browser", "ThumbnailSizeTab", thumbSizeTab); - keyFile.set_integer ("File Browser", "ThumbnailSizeQueue", thumbSizeQueue); - keyFile.set_integer ("File Browser", "SameThumbSize", sameThumbSize); - keyFile.set_integer ("File Browser", "MaxPreviewHeight", maxThumbnailHeight); - keyFile.set_integer ("File Browser", "MaxCacheEntries", maxCacheEntries); - Glib::ArrayHandle pext = parseExtensions; - keyFile.set_string_list ("File Browser", "ParseExtensions", pext); - Glib::ArrayHandle pextena = parseExtensionsEnabled; - keyFile.set_integer_list ("File Browser", "ParseExtensionsEnabled", pextena); - keyFile.set_integer ("File Browser", "ThumbnailArrangement", fbArrangement); - keyFile.set_integer ("File Browser", "ThumbnailInterpolation", thumbInterp); - keyFile.set_boolean ("File Browser", "LiveThumbnails", liveThumbnails); - Glib::ArrayHandle pfav = favoriteDirs; - keyFile.set_string_list ("File Browser", "FavoriteDirs", pfav); - Glib::ArrayHandle pren = renameTemplates; - keyFile.set_string_list ("File Browser", "RenameTemplates", pren); - keyFile.set_boolean ("File Browser", "RenameUseTemplates", renameUseTemplates); - Glib::ArrayHandle ptzoom = thumbnailZoomRatios; - keyFile.set_double_list ("File Browser", "ThumbnailZoomRatios", ptzoom); - keyFile.set_boolean ("File Browser", "OverlayedFileNames", overlayedFileNames); - keyFile.set_boolean ("File Browser", "FilmStripOverlayedFileNames", filmStripOverlayedFileNames); - keyFile.set_boolean ("File Browser", "ShowFileNames", showFileNames ); - keyFile.set_boolean ("File Browser", "FilmStripShowFileNames", filmStripShowFileNames ); - keyFile.set_boolean ("File Browser", "InternalThumbIfUntouched", internalThumbIfUntouched ); - keyFile.set_boolean ("File Browser", "menuGroupRank", menuGroupRank); - keyFile.set_boolean ("File Browser", "menuGroupLabel", menuGroupLabel); - keyFile.set_boolean ("File Browser", "menuGroupFileOperations", menuGroupFileOperations); - keyFile.set_boolean ("File Browser", "menuGroupProfileOperations", menuGroupProfileOperations); - keyFile.set_boolean ("File Browser", "menuGroupExtProg", menuGroupExtProg); - keyFile.set_integer ("File Browser", "MaxRecentFolders", maxRecentFolders); - { - std::vector temp; - temp.reserve(maxRecentFolders); - - for(unsigned int i = 0; i < std::min(recentFolders.size(), maxRecentFolders); i++) { - temp.push_back(recentFolders[i]); + if (startupDir == STARTUPDIR_HOME) { + keyFile.set_string ("General", "StartupDirectory", "home"); + } else if (startupDir == STARTUPDIR_CURRENT) { + keyFile.set_string ("General", "StartupDirectory", "current"); + } else if (startupDir == STARTUPDIR_CUSTOM) { + keyFile.set_string ("General", "StartupDirectory", "custom"); + } else if (startupDir == STARTUPDIR_LAST) { + keyFile.set_string ("General", "StartupDirectory", "last"); } - keyFile.set_string_list ("File Browser", "RecentFolders", temp); - } - keyFile.set_integer ("Clipping Indication", "HighlightThreshold", highlightThreshold); - keyFile.set_integer ("Clipping Indication", "ShadowThreshold", shadowThreshold); - keyFile.set_boolean ("Clipping Indication", "BlinkClipped", blinkClipped); + keyFile.set_string ("General", "StartupPath", startupPath); + keyFile.set_string ("General", "DateFormat", dateFormat); + keyFile.set_integer ("General", "AdjusterMinDelay", adjusterMinDelay); + keyFile.set_integer ("General", "AdjusterMaxDelay", adjusterMaxDelay); + keyFile.set_boolean ("General", "MultiUser", multiUser); + keyFile.set_string ("General", "Language", language); + keyFile.set_boolean ("General", "LanguageAutoDetect", languageAutoDetect); + keyFile.set_string ("General", "Theme", theme); + keyFile.set_boolean ("General", "SlimUI", slimUI); + keyFile.set_boolean ("General", "UseSystemTheme", useSystemTheme); + keyFile.set_string ("General", "Version", VERSION); + keyFile.set_string ("General", "DarkFramesPath", rtSettings.darkFramesPath); + keyFile.set_string ("General", "FlatFieldsPath", rtSettings.flatFieldsPath); + keyFile.set_boolean ("General", "Verbose", rtSettings.verbose); + keyFile.set_double ("General", "BotLeft", rtSettings.bot_left); + keyFile.set_double ("General", "TopLeft", rtSettings.top_left); + keyFile.set_double ("General", "TopRight", rtSettings.top_right); + keyFile.set_double ("General", "BotRight", rtSettings.bot_right); + keyFile.set_double ("General", "EDdetec", rtSettings.ed_detec); + keyFile.set_double ("General", "EDdetecStr", rtSettings.ed_detecStr); + keyFile.set_double ("General", "EDLow", rtSettings.ed_low); + keyFile.set_double ("General", "EDLipinfl", rtSettings.ed_lipinfl); + keyFile.set_double ("General", "EDLipampl", rtSettings.ed_lipampl); - keyFile.set_integer ("Performance", "RgbDenoiseThreadLimit", rgbDenoiseThreadLimit); - keyFile.set_double ("Performance", "NRauto", rtSettings.nrauto); - keyFile.set_double ("Performance", "NRautomax", rtSettings.nrautomax); - keyFile.set_double ("Performance", "NRhigh", rtSettings.nrhigh); - keyFile.set_integer ("Performance", "NRWavlevel", rtSettings.nrwavlevel); - keyFile.set_integer ("Performance", "LevNR", rtSettings.leveldnv); - keyFile.set_integer ("Performance", "LevNRTI", rtSettings.leveldnti); - keyFile.set_integer ("Performance", "LevNRAUT", rtSettings.leveldnaut); - keyFile.set_integer ("Performance", "LevNRLISS", rtSettings.leveldnliss); - keyFile.set_integer ("Performance", "SIMPLNRAUT", rtSettings.leveldnautsimpl); - keyFile.set_integer ("Performance", "ClutCacheSize", clutCacheSize); - keyFile.set_integer ("Performance", "MaxInspectorBuffers", maxInspectorBuffers); - keyFile.set_integer ("Performance", "PreviewDemosaicFromSidecar", prevdemo); - keyFile.set_boolean ("Performance", "Daubechies", rtSettings.daubech); - keyFile.set_boolean ("Performance", "SerializeTiffRead", serializeTiffRead); - keyFile.set_string ("Output", "Format", saveFormat.format); - keyFile.set_integer ("Output", "JpegQuality", saveFormat.jpegQuality); - keyFile.set_integer ("Output", "JpegSubSamp", saveFormat.jpegSubSamp); - keyFile.set_integer ("Output", "PngCompression", saveFormat.pngCompression); - keyFile.set_integer ("Output", "PngBps", saveFormat.pngBits); - keyFile.set_integer ("Output", "TiffBps", saveFormat.tiffBits); - keyFile.set_boolean ("Output", "TiffUncompressed", saveFormat.tiffUncompressed); - keyFile.set_boolean ("Output", "SaveProcParams", saveFormat.saveParams); + keyFile.set_integer ("External Editor", "EditorKind", editorToSendTo); + keyFile.set_string ("External Editor", "GimpDir", gimpDir); + keyFile.set_string ("External Editor", "PhotoshopDir", psDir); + keyFile.set_string ("External Editor", "CustomEditor", customEditorProg); - keyFile.set_string ("Output", "FormatBatch", saveFormatBatch.format); - keyFile.set_integer ("Output", "JpegQualityBatch", saveFormatBatch.jpegQuality); - keyFile.set_integer ("Output", "JpegSubSampBatch", saveFormatBatch.jpegSubSamp); - keyFile.set_integer ("Output", "PngCompressionBatch", saveFormatBatch.pngCompression); - keyFile.set_integer ("Output", "PngBpsBatch", saveFormatBatch.pngBits); - keyFile.set_integer ("Output", "TiffBpsBatch", saveFormatBatch.tiffBits); - keyFile.set_boolean ("Output", "TiffUncompressedBatch", saveFormatBatch.tiffUncompressed); - keyFile.set_boolean ("Output", "SaveProcParamsBatch", saveFormatBatch.saveParams); + keyFile.set_boolean ("File Browser", "BrowseOnlyRaw", fbOnlyRaw); + keyFile.set_boolean ("File Browser", "BrowserShowsDate", fbShowDateTime); + keyFile.set_boolean ("File Browser", "BrowserShowsExif", fbShowBasicExif); + keyFile.set_boolean ("File Browser", "BrowserShowsExpComp", fbShowExpComp); + keyFile.set_boolean ("File Browser", "BrowserShowsHidden", fbShowHidden); + keyFile.set_integer ("File Browser", "ThumbnailSize", thumbSize); + keyFile.set_integer ("File Browser", "ThumbnailSizeTab", thumbSizeTab); + keyFile.set_integer ("File Browser", "ThumbnailSizeQueue", thumbSizeQueue); + keyFile.set_integer ("File Browser", "SameThumbSize", sameThumbSize); + keyFile.set_integer ("File Browser", "MaxPreviewHeight", maxThumbnailHeight); + keyFile.set_integer ("File Browser", "MaxCacheEntries", maxCacheEntries); + Glib::ArrayHandle pext = parseExtensions; + keyFile.set_string_list ("File Browser", "ParseExtensions", pext); + Glib::ArrayHandle pextena = parseExtensionsEnabled; + keyFile.set_integer_list ("File Browser", "ParseExtensionsEnabled", pextena); + keyFile.set_integer ("File Browser", "ThumbnailArrangement", fbArrangement); + keyFile.set_integer ("File Browser", "ThumbnailInterpolation", thumbInterp); + keyFile.set_boolean ("File Browser", "LiveThumbnails", liveThumbnails); + Glib::ArrayHandle pfav = favoriteDirs; + keyFile.set_string_list ("File Browser", "FavoriteDirs", pfav); + Glib::ArrayHandle pren = renameTemplates; + keyFile.set_string_list ("File Browser", "RenameTemplates", pren); + keyFile.set_boolean ("File Browser", "RenameUseTemplates", renameUseTemplates); + Glib::ArrayHandle ptzoom = thumbnailZoomRatios; + keyFile.set_double_list ("File Browser", "ThumbnailZoomRatios", ptzoom); + keyFile.set_boolean ("File Browser", "OverlayedFileNames", overlayedFileNames); + keyFile.set_boolean ("File Browser", "FilmStripOverlayedFileNames", filmStripOverlayedFileNames); + keyFile.set_boolean ("File Browser", "ShowFileNames", showFileNames ); + keyFile.set_boolean ("File Browser", "FilmStripShowFileNames", filmStripShowFileNames ); + keyFile.set_boolean ("File Browser", "InternalThumbIfUntouched", internalThumbIfUntouched ); + keyFile.set_boolean ("File Browser", "menuGroupRank", menuGroupRank); + keyFile.set_boolean ("File Browser", "menuGroupLabel", menuGroupLabel); + keyFile.set_boolean ("File Browser", "menuGroupFileOperations", menuGroupFileOperations); + keyFile.set_boolean ("File Browser", "menuGroupProfileOperations", menuGroupProfileOperations); + keyFile.set_boolean ("File Browser", "menuGroupExtProg", menuGroupExtProg); + keyFile.set_integer ("File Browser", "MaxRecentFolders", maxRecentFolders); + { + std::vector temp; + temp.reserve(maxRecentFolders); - keyFile.set_string ("Output", "PathTemplate", savePathTemplate); - keyFile.set_string ("Output", "PathFolder", savePathFolder); - keyFile.set_boolean ("Output", "AutoSuffix", autoSuffix); - keyFile.set_boolean ("Output", "ForceFormatOpts", forceFormatOpts); - keyFile.set_integer ("Output", "SaveMethodNum", saveMethodNum); - keyFile.set_boolean ("Output", "UsePathTemplate", saveUsePathTemplate); - keyFile.set_string ("Output", "LastSaveAsPath", lastSaveAsPath); - keyFile.set_boolean ("Output", "OverwriteOutputFile", overwriteOutputFile); - keyFile.set_boolean ("Output", "TunnelMetaData", tunnelMetaData); + for(unsigned int i = 0; i < std::min(recentFolders.size(), maxRecentFolders); i++) { + temp.push_back(recentFolders[i]); + } - keyFile.set_string ("Profiles", "Directory", profilePath); - keyFile.set_boolean ("Profiles", "UseBundledProfiles", useBundledProfiles); - keyFile.set_string ("Profiles", "LoadSaveProfilePath", loadSaveProfilePath); - keyFile.set_string ("Profiles", "RawDefault", defProfRaw); - keyFile.set_string ("Profiles", "ImgDefault", defProfImg); - keyFile.set_boolean ("Profiles", "FilledProfile", filledProfile); - keyFile.set_boolean ("Profiles", "SaveParamsWithFile", saveParamsFile); - keyFile.set_boolean ("Profiles", "SaveParamsToCache", saveParamsCache); - keyFile.set_integer ("Profiles", "LoadParamsFromLocation", paramsLoadLocation); - keyFile.set_string ("Profiles", "CustomProfileBuilderPath", CPBPath); - keyFile.set_integer ("Profiles", "CustomProfileBuilderKeys", CPBKeys); + keyFile.set_string_list ("File Browser", "RecentFolders", temp); + } + keyFile.set_integer ("Clipping Indication", "HighlightThreshold", highlightThreshold); + keyFile.set_integer ("Clipping Indication", "ShadowThreshold", shadowThreshold); + keyFile.set_boolean ("Clipping Indication", "BlinkClipped", blinkClipped); - keyFile.set_string ("GUI", "Font", font); - keyFile.set_integer ("GUI", "WindowWidth", windowWidth); - keyFile.set_integer ("GUI", "WindowHeight", windowHeight); - keyFile.set_integer ("GUI", "WindowX", windowX); - keyFile.set_integer ("GUI", "WindowY", windowY); - keyFile.set_boolean ("GUI", "WindowMaximized", windowMaximized); - keyFile.set_integer ("GUI", "DetailWindowWidth", detailWindowWidth); - keyFile.set_integer ("GUI", "DetailWindowHeight", detailWindowHeight); - keyFile.set_integer ("GUI", "DirBrowserWidth", dirBrowserWidth); - keyFile.set_integer ("GUI", "DirBrowserHeight", dirBrowserHeight); - keyFile.set_integer ("GUI", "SortType", dirBrowserSortType); - keyFile.set_integer ("GUI", "PreferencesWidth", preferencesWidth); - keyFile.set_integer ("GUI", "PreferencesHeight", preferencesHeight); - keyFile.set_integer ("GUI", "SaveAsDialogWidth", saveAsDialogWidth); - keyFile.set_integer ("GUI", "SaveAsDialogHeight", saveAsDialogHeight); - keyFile.set_integer ("GUI", "ToolPanelWidth", toolPanelWidth); - keyFile.set_integer ("GUI", "BrowserToolPanelWidth", browserToolPanelWidth); - keyFile.set_integer ("GUI", "BrowserToolPanelHeight", browserToolPanelHeight); - keyFile.set_boolean ("GUI", "BrowserToolPanelOpened", browserToolPanelOpened); - keyFile.set_boolean ("GUI", "EditorFilmStripOpened", editorFilmStripOpened); - keyFile.set_boolean ("GUI", "BrowserDirPanelOpened", browserDirPanelOpened); - keyFile.set_integer ("GUI", "HistoryPanelWidth", historyPanelWidth); - keyFile.set_integer ("GUI", "LastPreviewScale", lastScale); - keyFile.set_integer ("GUI", "PanAccelFactor", panAccelFactor); - keyFile.set_boolean ("GUI", "RememberZoomAndPan", rememberZoomAndPan); - keyFile.set_integer ("GUI", "LastCropSize", lastCropSize); - keyFile.set_boolean ("GUI", "ShowHistory", showHistory); - keyFile.set_integer ("GUI", "ShowFilePanelState", showFilePanelState); - keyFile.set_boolean ("GUI", "ShowInfo", showInfo); - keyFile.set_boolean ("GUI", "MainNBVertical", mainNBVertical); - keyFile.set_boolean ("GUI", "ShowClippedHighlights", showClippedHighlights); - keyFile.set_boolean ("GUI", "ShowClippedShadows", showClippedShadows); - keyFile.set_integer ("GUI", "FrameColor", bgcolor); - keyFile.set_boolean ("GUI", "ProcessingQueueEnbled", procQueueEnabled); - Glib::ArrayHandle tpopen = tpOpen; - keyFile.set_integer_list ("GUI", "ToolPanelsExpanded", tpopen); - keyFile.set_integer ("GUI", "MultiDisplayMode", multiDisplayMode); - keyFile.set_double_list ("GUI", "CutOverlayBrush", cutOverlayBrush); - keyFile.set_double_list ("GUI", "NavGuideBrush", navGuideBrush); - keyFile.set_integer ("GUI", "HistogramPosition", histogramPosition); - keyFile.set_boolean ("GUI", "HistogramBar", histogramBar); - keyFile.set_boolean ("GUI", "HistogramFullMode", histogramFullMode); - keyFile.set_boolean ("GUI", "ShowFilmStripToolBar", showFilmStripToolBar); - keyFile.set_boolean ("GUI", "FileBrowserToolbarSingleRow", FileBrowserToolbarSingleRow); - keyFile.set_boolean ("GUI", "HideTPVScrollbar", hideTPVScrollbar); - keyFile.set_boolean ("GUI", "UseIconNoText", UseIconNoText); - keyFile.set_boolean ("GUI", "HistogramWorking", rtSettings.HistogramWorking); - keyFile.set_integer ("GUI", "CurveBBoxPosition", curvebboxpos); + keyFile.set_integer ("Performance", "RgbDenoiseThreadLimit", rgbDenoiseThreadLimit); + keyFile.set_double ("Performance", "NRauto", rtSettings.nrauto); + keyFile.set_double ("Performance", "NRautomax", rtSettings.nrautomax); + keyFile.set_double ("Performance", "NRhigh", rtSettings.nrhigh); + keyFile.set_integer ("Performance", "NRWavlevel", rtSettings.nrwavlevel); + keyFile.set_integer ("Performance", "LevNR", rtSettings.leveldnv); + keyFile.set_integer ("Performance", "LevNRTI", rtSettings.leveldnti); + keyFile.set_integer ("Performance", "LevNRAUT", rtSettings.leveldnaut); + keyFile.set_integer ("Performance", "LevNRLISS", rtSettings.leveldnliss); + keyFile.set_integer ("Performance", "SIMPLNRAUT", rtSettings.leveldnautsimpl); + keyFile.set_integer ("Performance", "ClutCacheSize", clutCacheSize); + keyFile.set_integer ("Performance", "MaxInspectorBuffers", maxInspectorBuffers); + keyFile.set_integer ("Performance", "PreviewDemosaicFromSidecar", prevdemo); + keyFile.set_boolean ("Performance", "Daubechies", rtSettings.daubech); + keyFile.set_boolean ("Performance", "SerializeTiffRead", serializeTiffRead); - //Glib::ArrayHandle crvopen = crvOpen; - //keyFile.set_integer_list ("GUI", "CurvePanelsExpanded", crvopen); + keyFile.set_string ("Output", "Format", saveFormat.format); + keyFile.set_integer ("Output", "JpegQuality", saveFormat.jpegQuality); + keyFile.set_integer ("Output", "JpegSubSamp", saveFormat.jpegSubSamp); + keyFile.set_integer ("Output", "PngCompression", saveFormat.pngCompression); + keyFile.set_integer ("Output", "PngBps", saveFormat.pngBits); + keyFile.set_integer ("Output", "TiffBps", saveFormat.tiffBits); + keyFile.set_boolean ("Output", "TiffUncompressed", saveFormat.tiffUncompressed); + keyFile.set_boolean ("Output", "SaveProcParams", saveFormat.saveParams); - keyFile.set_integer ("Crop Settings", "PPI", cropPPI); + keyFile.set_string ("Output", "FormatBatch", saveFormatBatch.format); + keyFile.set_integer ("Output", "JpegQualityBatch", saveFormatBatch.jpegQuality); + keyFile.set_integer ("Output", "JpegSubSampBatch", saveFormatBatch.jpegSubSamp); + keyFile.set_integer ("Output", "PngCompressionBatch", saveFormatBatch.pngCompression); + keyFile.set_integer ("Output", "PngBpsBatch", saveFormatBatch.pngBits); + keyFile.set_integer ("Output", "TiffBpsBatch", saveFormatBatch.tiffBits); + keyFile.set_boolean ("Output", "TiffUncompressedBatch", saveFormatBatch.tiffUncompressed); + keyFile.set_boolean ("Output", "SaveProcParamsBatch", saveFormatBatch.saveParams); - keyFile.set_string ("Color Management", "ICCDirectory", rtSettings.iccDirectory); - keyFile.set_string ("Color Management", "MonitorProfile", rtSettings.monitorProfile); - keyFile.set_boolean ("Color Management", "AutoMonitorProfile", rtSettings.autoMonitorProfile); - keyFile.set_boolean ("Color Management", "Autocielab", rtSettings.autocielab); - keyFile.set_boolean ("Color Management", "RGBcurvesLumamode_Gamut", rtSettings.rgbcurveslumamode_gamut); - keyFile.set_integer ("Color Management", "Intent", rtSettings.monitorIntent); - keyFile.set_integer ("Color Management", "view", rtSettings.viewingdevice); - keyFile.set_integer ("Color Management", "grey", rtSettings.viewingdevicegrey); - keyFile.set_integer ("Color Management", "greySc", rtSettings.viewinggreySc); + keyFile.set_string ("Output", "PathTemplate", savePathTemplate); + keyFile.set_string ("Output", "PathFolder", savePathFolder); + keyFile.set_boolean ("Output", "AutoSuffix", autoSuffix); + keyFile.set_boolean ("Output", "ForceFormatOpts", forceFormatOpts); + keyFile.set_integer ("Output", "SaveMethodNum", saveMethodNum); + keyFile.set_boolean ("Output", "UsePathTemplate", saveUsePathTemplate); + keyFile.set_string ("Output", "LastSaveAsPath", lastSaveAsPath); + keyFile.set_boolean ("Output", "OverwriteOutputFile", overwriteOutputFile); + keyFile.set_boolean ("Output", "TunnelMetaData", tunnelMetaData); - keyFile.set_string ("Color Management", "AdobeRGB", rtSettings.adobe); - keyFile.set_string ("Color Management", "ProPhoto", rtSettings.prophoto); - keyFile.set_string ("Color Management", "ProPhoto10", rtSettings.prophoto10); - keyFile.set_string ("Color Management", "WideGamut", rtSettings.widegamut); - keyFile.set_string ("Color Management", "sRGB", rtSettings.srgb); - keyFile.set_string ("Color Management", "sRGB10", rtSettings.srgb10); - keyFile.set_string ("Color Management", "Beta", rtSettings.beta); - keyFile.set_string ("Color Management", "Best", rtSettings.best); - keyFile.set_string ("Color Management", "Bruce", rtSettings.bruce); - keyFile.set_integer ("Color Management", "WhiteBalanceSpotSize", whiteBalanceSpotSize); - keyFile.set_boolean ("Color Management", "GamutICC", rtSettings.gamutICC); + keyFile.set_string ("Profiles", "Directory", profilePath); + keyFile.set_boolean ("Profiles", "UseBundledProfiles", useBundledProfiles); + keyFile.set_string ("Profiles", "LoadSaveProfilePath", loadSaveProfilePath); + keyFile.set_string ("Profiles", "RawDefault", defProfRaw); + keyFile.set_string ("Profiles", "ImgDefault", defProfImg); + keyFile.set_boolean ("Profiles", "FilledProfile", filledProfile); + keyFile.set_boolean ("Profiles", "SaveParamsWithFile", saveParamsFile); + keyFile.set_boolean ("Profiles", "SaveParamsToCache", saveParamsCache); + keyFile.set_integer ("Profiles", "LoadParamsFromLocation", paramsLoadLocation); + keyFile.set_string ("Profiles", "CustomProfileBuilderPath", CPBPath); + keyFile.set_integer ("Profiles", "CustomProfileBuilderKeys", CPBKeys); + + keyFile.set_string ("GUI", "Font", font); + keyFile.set_integer ("GUI", "WindowWidth", windowWidth); + keyFile.set_integer ("GUI", "WindowHeight", windowHeight); + keyFile.set_integer ("GUI", "WindowX", windowX); + keyFile.set_integer ("GUI", "WindowY", windowY); + keyFile.set_boolean ("GUI", "WindowMaximized", windowMaximized); + keyFile.set_integer ("GUI", "DetailWindowWidth", detailWindowWidth); + keyFile.set_integer ("GUI", "DetailWindowHeight", detailWindowHeight); + keyFile.set_integer ("GUI", "DirBrowserWidth", dirBrowserWidth); + keyFile.set_integer ("GUI", "DirBrowserHeight", dirBrowserHeight); + keyFile.set_integer ("GUI", "SortType", dirBrowserSortType); + keyFile.set_integer ("GUI", "PreferencesWidth", preferencesWidth); + keyFile.set_integer ("GUI", "PreferencesHeight", preferencesHeight); + keyFile.set_integer ("GUI", "SaveAsDialogWidth", saveAsDialogWidth); + keyFile.set_integer ("GUI", "SaveAsDialogHeight", saveAsDialogHeight); + keyFile.set_integer ("GUI", "ToolPanelWidth", toolPanelWidth); + keyFile.set_integer ("GUI", "BrowserToolPanelWidth", browserToolPanelWidth); + keyFile.set_integer ("GUI", "BrowserToolPanelHeight", browserToolPanelHeight); + keyFile.set_boolean ("GUI", "BrowserToolPanelOpened", browserToolPanelOpened); + keyFile.set_boolean ("GUI", "EditorFilmStripOpened", editorFilmStripOpened); + keyFile.set_boolean ("GUI", "BrowserDirPanelOpened", browserDirPanelOpened); + keyFile.set_integer ("GUI", "HistoryPanelWidth", historyPanelWidth); + keyFile.set_integer ("GUI", "LastPreviewScale", lastScale); + keyFile.set_integer ("GUI", "PanAccelFactor", panAccelFactor); + keyFile.set_boolean ("GUI", "RememberZoomAndPan", rememberZoomAndPan); + keyFile.set_integer ("GUI", "LastCropSize", lastCropSize); + keyFile.set_boolean ("GUI", "ShowHistory", showHistory); + keyFile.set_integer ("GUI", "ShowFilePanelState", showFilePanelState); + keyFile.set_boolean ("GUI", "ShowInfo", showInfo); + keyFile.set_boolean ("GUI", "MainNBVertical", mainNBVertical); + keyFile.set_boolean ("GUI", "ShowClippedHighlights", showClippedHighlights); + keyFile.set_boolean ("GUI", "ShowClippedShadows", showClippedShadows); + keyFile.set_integer ("GUI", "FrameColor", bgcolor); + keyFile.set_boolean ("GUI", "ProcessingQueueEnbled", procQueueEnabled); + Glib::ArrayHandle tpopen = tpOpen; + keyFile.set_integer_list ("GUI", "ToolPanelsExpanded", tpopen); + keyFile.set_integer ("GUI", "MultiDisplayMode", multiDisplayMode); + keyFile.set_double_list ("GUI", "CutOverlayBrush", cutOverlayBrush); + keyFile.set_double_list ("GUI", "NavGuideBrush", navGuideBrush); + keyFile.set_integer ("GUI", "HistogramPosition", histogramPosition); + keyFile.set_boolean ("GUI", "HistogramBar", histogramBar); + keyFile.set_boolean ("GUI", "HistogramFullMode", histogramFullMode); + keyFile.set_boolean ("GUI", "ShowFilmStripToolBar", showFilmStripToolBar); + keyFile.set_boolean ("GUI", "FileBrowserToolbarSingleRow", FileBrowserToolbarSingleRow); + keyFile.set_boolean ("GUI", "HideTPVScrollbar", hideTPVScrollbar); + keyFile.set_boolean ("GUI", "UseIconNoText", UseIconNoText); + keyFile.set_boolean ("GUI", "HistogramWorking", rtSettings.HistogramWorking); + keyFile.set_integer ("GUI", "CurveBBoxPosition", curvebboxpos); + + //Glib::ArrayHandle crvopen = crvOpen; + //keyFile.set_integer_list ("GUI", "CurvePanelsExpanded", crvopen); + + keyFile.set_integer ("Crop Settings", "PPI", cropPPI); + + keyFile.set_string ("Color Management", "ICCDirectory", rtSettings.iccDirectory); + keyFile.set_string ("Color Management", "MonitorProfile", rtSettings.monitorProfile); + keyFile.set_boolean ("Color Management", "AutoMonitorProfile", rtSettings.autoMonitorProfile); + keyFile.set_boolean ("Color Management", "Autocielab", rtSettings.autocielab); + keyFile.set_boolean ("Color Management", "RGBcurvesLumamode_Gamut", rtSettings.rgbcurveslumamode_gamut); + keyFile.set_integer ("Color Management", "Intent", rtSettings.monitorIntent); + keyFile.set_integer ("Color Management", "view", rtSettings.viewingdevice); + keyFile.set_integer ("Color Management", "grey", rtSettings.viewingdevicegrey); + keyFile.set_integer ("Color Management", "greySc", rtSettings.viewinggreySc); + + keyFile.set_string ("Color Management", "AdobeRGB", rtSettings.adobe); + keyFile.set_string ("Color Management", "ProPhoto", rtSettings.prophoto); + keyFile.set_string ("Color Management", "ProPhoto10", rtSettings.prophoto10); + keyFile.set_string ("Color Management", "WideGamut", rtSettings.widegamut); + keyFile.set_string ("Color Management", "sRGB", rtSettings.srgb); + keyFile.set_string ("Color Management", "sRGB10", rtSettings.srgb10); + keyFile.set_string ("Color Management", "Beta", rtSettings.beta); + keyFile.set_string ("Color Management", "Best", rtSettings.best); + keyFile.set_string ("Color Management", "Rec2020", rtSettings.rec2020); + keyFile.set_string ("Color Management", "Bruce", rtSettings.bruce); + keyFile.set_integer ("Color Management", "WhiteBalanceSpotSize", whiteBalanceSpotSize); + keyFile.set_boolean ("Color Management", "GamutICC", rtSettings.gamutICC); // keyFile.set_boolean ("Color Management", "BWcomplement", rtSettings.bw_complementary); - keyFile.set_boolean ("Color Management", "Ciecamfloat", rtSettings.ciecamfloat); - keyFile.set_boolean ("Color Management", "GamutLch", rtSettings.gamutLch); - keyFile.set_integer ("Color Management", "ProtectRed", rtSettings.protectred); - keyFile.set_integer ("Color Management", "Amountchroma", rtSettings.amchroma); - keyFile.set_double ("Color Management", "ProtectRedH", rtSettings.protectredh); - keyFile.set_integer ("Color Management", "CRI", rtSettings.CRI_color); - keyFile.set_integer ("Color Management", "DenoiseLabgamma", rtSettings.denoiselabgamma); + keyFile.set_boolean ("Color Management", "Ciecamfloat", rtSettings.ciecamfloat); + keyFile.set_boolean ("Color Management", "GamutLch", rtSettings.gamutLch); + keyFile.set_integer ("Color Management", "ProtectRed", rtSettings.protectred); + keyFile.set_integer ("Color Management", "Amountchroma", rtSettings.amchroma); + keyFile.set_double ("Color Management", "ProtectRedH", rtSettings.protectredh); + keyFile.set_integer ("Color Management", "CRI", rtSettings.CRI_color); + keyFile.set_integer ("Color Management", "DenoiseLabgamma", rtSettings.denoiselabgamma); // keyFile.set_boolean ("Color Management", "Ciebadpixgauss", rtSettings.ciebadpixgauss); - keyFile.set_double ("Color Management", "CBDLArtif", rtSettings.artifact_cbdl); - keyFile.set_double ("Color Management", "CBDLlevel0", rtSettings.level0_cbdl); - keyFile.set_double ("Color Management", "CBDLlevel123", rtSettings.level123_cbdl); + keyFile.set_double ("Color Management", "CBDLArtif", rtSettings.artifact_cbdl); + keyFile.set_double ("Color Management", "CBDLlevel0", rtSettings.level0_cbdl); + keyFile.set_double ("Color Management", "CBDLlevel123", rtSettings.level123_cbdl); // keyFile.set_double ("Color Management", "Colortoningab", rtSettings.colortoningab); // keyFile.set_double ("Color Management", "Decaction", rtSettings.decaction); - keyFile.set_string ("Color Management", "ClutsDirectory", clutsDir); + keyFile.set_string ("Color Management", "ClutsDirectory", clutsDir); - Glib::ArrayHandle bab = baBehav; - keyFile.set_integer_list ("Batch Processing", "AdjusterBehavior", bab); + Glib::ArrayHandle bab = baBehav; + keyFile.set_integer_list ("Batch Processing", "AdjusterBehavior", bab); - keyFile.set_boolean ("Sounds", "Enable", sndEnable); - keyFile.set_string ("Sounds", "BatchQueueDone", sndBatchQueueDone); - keyFile.set_string ("Sounds", "LngEditProcDone", sndLngEditProcDone); - keyFile.set_double ("Sounds", "LngEditProcDoneSecs", sndLngEditProcDoneSecs); + keyFile.set_boolean ("Sounds", "Enable", sndEnable); + keyFile.set_string ("Sounds", "BatchQueueDone", sndBatchQueueDone); + keyFile.set_string ("Sounds", "LngEditProcDone", sndLngEditProcDone); + keyFile.set_double ("Sounds", "LngEditProcDoneSecs", sndLngEditProcDoneSecs); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpening" , fastexport_bypass_sharpening ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpenEdge" , fastexport_bypass_sharpenEdge ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpenMicro" , fastexport_bypass_sharpenMicro ); - //keyFile.set_boolean ("Fast Export", "fastexport_bypass_lumaDenoise" , fastexport_bypass_lumaDenoise ); - //keyFile.set_boolean ("Fast Export", "fastexport_bypass_colorDenoise" , fastexport_bypass_colorDenoise ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_defringe" , fastexport_bypass_defringe ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_dirpyrDenoise" , fastexport_bypass_dirpyrDenoise ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_sh_hq" , fastexport_bypass_sh_hq ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_dirpyrequalizer" , fastexport_bypass_dirpyrequalizer ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_wavelet" , fastexport_bypass_wavelet ); - keyFile.set_string ("Fast Export", "fastexport_raw_bayer_method" , fastexport_raw_bayer_method ); - //keyFile.set_boolean ("Fast Export", "fastexport_bypass_bayer_raw_all_enhance" , fastexport_bypass_raw_bayer_all_enhance ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_iterations" , fastexport_bypass_raw_bayer_dcb_iterations ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_enhance" , fastexport_bypass_raw_bayer_dcb_enhance ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_lmmse_iterations", fastexport_bypass_raw_bayer_lmmse_iterations); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_linenoise" , fastexport_bypass_raw_bayer_linenoise ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_greenthresh" , fastexport_bypass_raw_bayer_greenthresh ); - keyFile.set_string ("Fast Export", "fastexport_raw_xtrans_method" , fastexport_raw_xtrans_method ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ccSteps" , fastexport_bypass_raw_ccSteps ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ca" , fastexport_bypass_raw_ca ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_df" , fastexport_bypass_raw_df ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ff" , fastexport_bypass_raw_ff ); - keyFile.set_string ("Fast Export", "fastexport_icm_input" , fastexport_icm_input ); - keyFile.set_string ("Fast Export", "fastexport_icm_working" , fastexport_icm_working ); - keyFile.set_string ("Fast Export", "fastexport_icm_output" , fastexport_icm_output ); - keyFile.set_integer ("Fast Export", "fastexport_icm_output_intent" , fastexport_icm_outputIntent ); - keyFile.set_string ("Fast Export", "fastexport_icm_gamma" , fastexport_icm_gamma ); - keyFile.set_boolean ("Fast Export", "fastexport_resize_enabled" , fastexport_resize_enabled ); - keyFile.set_double ("Fast Export", "fastexport_resize_scale" , fastexport_resize_scale ); - keyFile.set_string ("Fast Export", "fastexport_resize_appliesTo" , fastexport_resize_appliesTo ); - keyFile.set_string ("Fast Export", "fastexport_resize_method" , fastexport_resize_method ); - keyFile.set_integer ("Fast Export", "fastexport_resize_dataspec" , fastexport_resize_dataspec ); - keyFile.set_integer ("Fast Export", "fastexport_resize_width" , fastexport_resize_width ); - keyFile.set_integer ("Fast Export", "fastexport_resize_height" , fastexport_resize_height ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpening" , fastexport_bypass_sharpening ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpenEdge" , fastexport_bypass_sharpenEdge ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpenMicro" , fastexport_bypass_sharpenMicro ); + //keyFile.set_boolean ("Fast Export", "fastexport_bypass_lumaDenoise" , fastexport_bypass_lumaDenoise ); + //keyFile.set_boolean ("Fast Export", "fastexport_bypass_colorDenoise" , fastexport_bypass_colorDenoise ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_defringe" , fastexport_bypass_defringe ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_dirpyrDenoise" , fastexport_bypass_dirpyrDenoise ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_sh_hq" , fastexport_bypass_sh_hq ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_dirpyrequalizer" , fastexport_bypass_dirpyrequalizer ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_wavelet" , fastexport_bypass_wavelet ); + keyFile.set_string ("Fast Export", "fastexport_raw_bayer_method" , fastexport_raw_bayer_method ); + //keyFile.set_boolean ("Fast Export", "fastexport_bypass_bayer_raw_all_enhance" , fastexport_bypass_raw_bayer_all_enhance ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_iterations" , fastexport_bypass_raw_bayer_dcb_iterations ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_enhance" , fastexport_bypass_raw_bayer_dcb_enhance ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_lmmse_iterations", fastexport_bypass_raw_bayer_lmmse_iterations); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_linenoise" , fastexport_bypass_raw_bayer_linenoise ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_greenthresh" , fastexport_bypass_raw_bayer_greenthresh ); + keyFile.set_string ("Fast Export", "fastexport_raw_xtrans_method" , fastexport_raw_xtrans_method ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ccSteps" , fastexport_bypass_raw_ccSteps ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ca" , fastexport_bypass_raw_ca ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_df" , fastexport_bypass_raw_df ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ff" , fastexport_bypass_raw_ff ); + keyFile.set_string ("Fast Export", "fastexport_icm_input" , fastexport_icm_input ); + keyFile.set_string ("Fast Export", "fastexport_icm_working" , fastexport_icm_working ); + keyFile.set_string ("Fast Export", "fastexport_icm_output" , fastexport_icm_output ); + keyFile.set_integer ("Fast Export", "fastexport_icm_output_intent" , fastexport_icm_outputIntent ); + keyFile.set_string ("Fast Export", "fastexport_icm_gamma" , fastexport_icm_gamma ); + keyFile.set_boolean ("Fast Export", "fastexport_resize_enabled" , fastexport_resize_enabled ); + keyFile.set_double ("Fast Export", "fastexport_resize_scale" , fastexport_resize_scale ); + keyFile.set_string ("Fast Export", "fastexport_resize_appliesTo" , fastexport_resize_appliesTo ); + keyFile.set_string ("Fast Export", "fastexport_resize_method" , fastexport_resize_method ); + keyFile.set_integer ("Fast Export", "fastexport_resize_dataspec" , fastexport_resize_dataspec ); + keyFile.set_integer ("Fast Export", "fastexport_resize_width" , fastexport_resize_width ); + keyFile.set_integer ("Fast Export", "fastexport_resize_height" , fastexport_resize_height ); - keyFile.set_string ("Dialogs", "LastIccDir", lastIccDir); - keyFile.set_string ("Dialogs", "LastDarkframeDir", lastDarkframeDir); - keyFile.set_string ("Dialogs", "LastFlatfieldDir", lastFlatfieldDir); - keyFile.set_string ("Dialogs", "LastRgbCurvesDir", lastRgbCurvesDir); - keyFile.set_string ("Dialogs", "LastLabCurvesDir", lastLabCurvesDir); - keyFile.set_string ("Dialogs", "LastRetinexDir", lastRetinexDir); - keyFile.set_string ("Dialogs", "LastDenoiseCurvesDir", lastDenoiseCurvesDir); - keyFile.set_string ("Dialogs", "LastWaveletCurvesDir", lastWaveletCurvesDir); - keyFile.set_string ("Dialogs", "LastPFCurvesDir", lastPFCurvesDir); - keyFile.set_string ("Dialogs", "LastHsvCurvesDir", lastHsvCurvesDir); - keyFile.set_string ("Dialogs", "LastBWCurvesDir", lastBWCurvesDir); - keyFile.set_string ("Dialogs", "LastToneCurvesDir", lastToneCurvesDir); - keyFile.set_string ("Dialogs", "LastVibranceCurvesDir", lastVibranceCurvesDir); - keyFile.set_string ("Dialogs", "LastProfilingReferenceDir", lastProfilingReferenceDir); + keyFile.set_string ("Dialogs", "LastIccDir", lastIccDir); + keyFile.set_string ("Dialogs", "LastDarkframeDir", lastDarkframeDir); + keyFile.set_string ("Dialogs", "LastFlatfieldDir", lastFlatfieldDir); + keyFile.set_string ("Dialogs", "LastRgbCurvesDir", lastRgbCurvesDir); + keyFile.set_string ("Dialogs", "LastLabCurvesDir", lastLabCurvesDir); + keyFile.set_string ("Dialogs", "LastRetinexDir", lastRetinexDir); + keyFile.set_string ("Dialogs", "LastDenoiseCurvesDir", lastDenoiseCurvesDir); + keyFile.set_string ("Dialogs", "LastWaveletCurvesDir", lastWaveletCurvesDir); + keyFile.set_string ("Dialogs", "LastPFCurvesDir", lastPFCurvesDir); + keyFile.set_string ("Dialogs", "LastHsvCurvesDir", lastHsvCurvesDir); + keyFile.set_string ("Dialogs", "LastBWCurvesDir", lastBWCurvesDir); + keyFile.set_string ("Dialogs", "LastToneCurvesDir", lastToneCurvesDir); + keyFile.set_string ("Dialogs", "LastVibranceCurvesDir", lastVibranceCurvesDir); + keyFile.set_string ("Dialogs", "LastProfilingReferenceDir", lastProfilingReferenceDir); - FILE *f = safe_g_fopen (fname, "wt"); + keyData = keyFile.to_data (); + + } catch (Glib::KeyFileError&) {} + + if (keyData.empty ()) { + return 1; + } + + FILE *f = g_fopen (fname.c_str (), "wt"); if (f == NULL) { if (options.rtSettings.verbose) { @@ -2114,7 +2137,7 @@ int Options::saveToFile (Glib::ustring fname) return 1; } else { - fprintf (f, "%s", keyFile.to_data().c_str()); + fprintf (f, "%s", keyData.c_str ()); fclose (f); return 0; } @@ -2187,14 +2210,14 @@ bool Options::load () int r = options.readFromFile (Glib::build_filename(rtdir, "options")); // If the local option file does not exist or is broken, and the local cache folder does not exist, recreate it - if (r && !safe_g_mkdir_with_parents (rtdir, 511)) { + if (r && !g_mkdir_with_parents (rtdir.c_str (), 511)) { // Save the option file options.saveToFile (Glib::build_filename(rtdir, "options")); } #ifdef __APPLE__ // make sure .local/share exists on OS X so we don't get problems with recently-used.xbel - safe_g_mkdir_with_parents (g_get_user_data_dir(), 511); + g_mkdir_with_parents (g_get_user_data_dir(), 511); #endif } diff --git a/rtgui/options.h b/rtgui/options.h index b896f4129..4da827f36 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -58,11 +58,6 @@ enum PPLoadLocation {PLL_Cache = 0, PLL_Input = 1}; enum CPBKeyType {CPBKT_TID = 0, CPBKT_NAME = 1, CPBKT_TID_NAME = 2}; enum prevdemo_t {PD_Sidecar = 1, PD_Fast = 0}; -namespace rtengine -{ -class SafeKeyFile; -} - class Options { @@ -87,7 +82,7 @@ private: * @param destination destination variable to store to * @return @c true if @p destination was changed */ - bool safeDirGet(const rtengine::SafeKeyFile& keyFile, const Glib::ustring& section, + bool safeDirGet(const Glib::KeyFile& keyFile, const Glib::ustring& section, const Glib::ustring& entryName, Glib::ustring& destination); public: diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 5608590ca..fba2ef059 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -376,6 +376,7 @@ void ParamsEdited::set (bool v) raw.xtranssensor.exBlackGreen = v; raw.xtranssensor.exBlackBlue = v; raw.caCorrection = v; + raw.caAutoStrength = v; raw.caBlue = v; raw.caRed = v; raw.hotPixelFilter = v; @@ -488,6 +489,8 @@ void ParamsEdited::set (bool v) dirpyrequalizer.enabled = v; dirpyrequalizer.gamutlab = v; + dirpyrequalizer.cbdlMethod = v; + for(int i = 0; i < 6; i++) { dirpyrequalizer.mult[i] = v; @@ -867,6 +870,7 @@ void ParamsEdited::initFrom (const std::vector raw.xtranssensor.exBlackGreen = raw.xtranssensor.exBlackGreen && p.raw.xtranssensor.blackgreen == other.raw.xtranssensor.blackgreen; raw.xtranssensor.exBlackBlue = raw.xtranssensor.exBlackBlue && p.raw.xtranssensor.blackblue == other.raw.xtranssensor.blackblue; raw.caCorrection = raw.caCorrection && p.raw.ca_autocorrect == other.raw.ca_autocorrect; + raw.caAutoStrength = raw.caAutoStrength && p.raw.caautostrength == other.raw.caautostrength; raw.caRed = raw.caRed && p.raw.cared == other.raw.cared; raw.caBlue = raw.caBlue && p.raw.cablue == other.raw.cablue; raw.hotPixelFilter = raw.hotPixelFilter && p.raw.hotPixelFilter == other.raw.hotPixelFilter; @@ -975,6 +979,7 @@ void ParamsEdited::initFrom (const std::vector dirpyrequalizer.enabled = dirpyrequalizer.enabled && p.dirpyrequalizer.enabled == other.dirpyrequalizer.enabled; dirpyrequalizer.gamutlab = dirpyrequalizer.gamutlab && p.dirpyrequalizer.gamutlab == other.dirpyrequalizer.gamutlab; + dirpyrequalizer.cbdlMethod = dirpyrequalizer.cbdlMethod && p.dirpyrequalizer.cbdlMethod == other.dirpyrequalizer.cbdlMethod; for(int i = 0; i < 6; i++) { dirpyrequalizer.mult[i] = dirpyrequalizer.mult[i] && p.dirpyrequalizer.mult[i] == other.dirpyrequalizer.mult[i]; @@ -2296,6 +2301,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.raw.ca_autocorrect = mods.raw.ca_autocorrect; } + if (raw.caAutoStrength) { + toEdit.raw.caautostrength = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.caautostrength + mods.raw.caautostrength : mods.raw.caautostrength; + } + if (raw.caRed) { toEdit.raw.cared = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cared + mods.raw.cared : mods.raw.cared; } @@ -2706,6 +2715,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.dirpyrequalizer.gamutlab = mods.dirpyrequalizer.gamutlab; } + if (dirpyrequalizer.cbdlMethod) { + toEdit.dirpyrequalizer.cbdlMethod = mods.dirpyrequalizer.cbdlMethod; + } + for(int i = 0; i < 6; i++) { if(dirpyrequalizer.mult[i]) { toEdit.dirpyrequalizer.mult[i] = dontforceSet && options.baBehav[ADDSET_DIRPYREQ] ? toEdit.dirpyrequalizer.mult[i] + mods.dirpyrequalizer.mult[i] : mods.dirpyrequalizer.mult[i]; @@ -2765,18 +2778,18 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten bool RAWParamsEdited::BayerSensor::isUnchanged() const { - return method && ccSteps && dcbIterations && dcbEnhance && lmmseIterations/*&& allEnhance*/ && greenEq + return method && dcbIterations && dcbEnhance && lmmseIterations/*&& allEnhance*/ && greenEq && linenoise && exBlack0 && exBlack1 && exBlack2 && exBlack3 && exTwoGreen; } bool RAWParamsEdited::XTransSensor::isUnchanged() const { - return method && ccSteps && exBlackRed && exBlackGreen && exBlackBlue; + return method && exBlackRed && exBlackGreen && exBlackBlue; } bool RAWParamsEdited::isUnchanged() const { - return bayersensor.isUnchanged() && xtranssensor.isUnchanged() && caCorrection && caRed && caBlue && hotPixelFilter && deadPixelFilter && hotDeadPixelThresh && darkFrame + return bayersensor.isUnchanged() && xtranssensor.isUnchanged() && caCorrection && caAutoStrength && caRed && caBlue && hotPixelFilter && deadPixelFilter && hotDeadPixelThresh && darkFrame && dfAuto && ff_file && ff_AutoSelect && ff_BlurRadius && ff_BlurType && exPos && exPreser && ff_AutoClipControl && ff_clipControl; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 3e2583bf2..f8d18ae57 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -648,7 +648,7 @@ public: bool enabled; bool gamutlab; bool mult[6]; - + bool cbdlMethod; bool threshold; bool skinprotect; bool hueskin; @@ -714,6 +714,7 @@ public: XTransSensor xtranssensor; bool caCorrection; + bool caAutoStrength; bool caRed; bool caBlue; bool hotPixelFilter; diff --git a/rtgui/placesbrowser.cc b/rtgui/placesbrowser.cc index bb92fab0d..acceb73e2 100644 --- a/rtgui/placesbrowser.cc +++ b/rtgui/placesbrowser.cc @@ -17,11 +17,17 @@ * along with RawTherapee. If not, see . */ #include "placesbrowser.h" -#include "options.h" -#include "toolpanel.h" -#include "../rtengine/safegtk.h" + +#ifdef WIN32 +#include +#include +#include +#endif + #include "guiutils.h" #include "rtimage.h" +#include "options.h" +#include "toolpanel.h" PlacesBrowser::PlacesBrowser () { @@ -86,17 +92,14 @@ bool compareMountByRoot (Glib::RefPtr a, Glib::RefPtr b) void PlacesBrowser::refreshPlacesList () { - placesModel->clear (); // append home directory - Glib::RefPtr hfile = Gio::File::create_for_path (safe_get_user_home_dir()); // Will send back "My documents" on Windows now, which has no restricted access + Glib::RefPtr hfile = Gio::File::create_for_path (userHomeDir()); // Will send back "My documents" on Windows now, which has no restricted access if (hfile && hfile->query_exists()) { try { - Glib::RefPtr info = safe_query_file_info (hfile); - - if (info) { + if (auto info = hfile->query_info ()) { Gtk::TreeModel::Row newrow = *(placesModel->append()); newrow[placesColumns.label] = info->get_display_name (); newrow[placesColumns.icon] = info->get_icon (); @@ -104,19 +107,15 @@ void PlacesBrowser::refreshPlacesList () newrow[placesColumns.type] = 4; newrow[placesColumns.rowSeparator] = false; } - } catch (Gio::Error&) { - /* This will be thrown if the path doesn't exist */ - } + } catch (Gio::Error&) {} } // append pictures directory - hfile = Gio::File::create_for_path (safe_get_user_picture_dir()); + hfile = Gio::File::create_for_path (userPicturesDir()); if (hfile && hfile->query_exists()) { try { - Glib::RefPtr info = safe_query_file_info (hfile); - - if (info) { + if (auto info = hfile->query_info ()) { Gtk::TreeModel::Row newrow = *(placesModel->append()); newrow[placesColumns.label] = info->get_display_name (); newrow[placesColumns.icon] = info->get_icon (); @@ -124,9 +123,7 @@ void PlacesBrowser::refreshPlacesList () newrow[placesColumns.type] = 4; newrow[placesColumns.rowSeparator] = false; } - } catch (Gio::Error&) { - /* This will be thrown if the path doesn't exist */ - } + } catch (Gio::Error&) {} } if (!placesModel->children().empty()) { @@ -225,16 +222,16 @@ void PlacesBrowser::refreshPlacesList () Glib::RefPtr hfile = Gio::File::create_for_path (options.favoriteDirs[i]); if (hfile && hfile->query_exists()) { - Glib::RefPtr info = safe_query_file_info (hfile); - - if (info) { - Gtk::TreeModel::Row newrow = *(placesModel->append()); - newrow[placesColumns.label] = info->get_display_name (); - newrow[placesColumns.icon] = info->get_icon (); - newrow[placesColumns.root] = hfile->get_parse_name (); - newrow[placesColumns.type] = 5; - newrow[placesColumns.rowSeparator] = false; - } + try { + if (auto info = hfile->query_info ()) { + Gtk::TreeModel::Row newrow = *(placesModel->append()); + newrow[placesColumns.label] = info->get_display_name (); + newrow[placesColumns.icon] = info->get_icon (); + newrow[placesColumns.root] = hfile->get_parse_name (); + newrow[placesColumns.type] = 5; + newrow[placesColumns.rowSeparator] = false; + } + } catch(Gio::Error&) {} } } } @@ -315,12 +312,12 @@ void PlacesBrowser::addPressed () Glib::RefPtr hfile = Gio::File::create_for_path (lastSelectedDir); if (hfile && hfile->query_exists()) { - Glib::RefPtr info = safe_query_file_info (hfile); - - if (info) { - options.favoriteDirs.push_back (hfile->get_parse_name ()); - refreshPlacesList (); - } + try { + if (auto info = hfile->query_info ()) { + options.favoriteDirs.push_back (hfile->get_parse_name ()); + refreshPlacesList (); + } + } catch(Gio::Error&) {} } } @@ -342,3 +339,52 @@ void PlacesBrowser::delPressed () refreshPlacesList (); } +Glib::ustring PlacesBrowser::userHomeDir () +{ +#ifdef WIN32 + + // get_home_dir crashes on some Windows configurations, + // so we rather use the safe native functions here. + WCHAR pathW[MAX_PATH]; + if (SHGetSpecialFolderPathW (NULL, pathW, CSIDL_PERSONAL, false)) { + + char pathA[MAX_PATH]; + if (WideCharToMultiByte (CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0)) { + + return Glib::ustring (pathA); + } + } + + return Glib::ustring ("C:\\"); + +#else + + return Glib::get_home_dir (); + +#endif +} + +Glib::ustring PlacesBrowser::userPicturesDir () +{ +#ifdef WIN32 + + // get_user_special_dir crashes on some Windows configurations, + // so we rather use the safe native functions here. + WCHAR pathW[MAX_PATH]; + if (SHGetSpecialFolderPathW (NULL, pathW, CSIDL_MYPICTURES, false)) { + + char pathA[MAX_PATH]; + if (WideCharToMultiByte (CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0)) { + + return Glib::ustring (pathA); + } + } + + return Glib::ustring ("C:\\"); + +#else + + return Glib::get_user_special_dir (G_USER_DIRECTORY_PICTURES); + +#endif +} diff --git a/rtgui/placesbrowser.h b/rtgui/placesbrowser.h index b9d74648b..b3bed867c 100644 --- a/rtgui/placesbrowser.h +++ b/rtgui/placesbrowser.h @@ -72,6 +72,12 @@ public: void selectionChanged (); void addPressed (); void delPressed (); + +public: + + static Glib::ustring userHomeDir (); + static Glib::ustring userPicturesDir (); + }; inline void PlacesBrowser::setDirSelector (const PlacesBrowser::DirSelectionSlot& selectDir) diff --git a/rtgui/popupcommon.cc b/rtgui/popupcommon.cc index f7e667219..24af17213 100644 --- a/rtgui/popupcommon.cc +++ b/rtgui/popupcommon.cc @@ -22,7 +22,6 @@ #include #include "multilangmgr.h" #include "popupcommon.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" PopUpCommon::PopUpCommon (Gtk::Button* thisButton, const Glib::ustring& label) diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 5f5ececee..10800d527 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -25,7 +25,6 @@ #include "../rtengine/dfmanager.h" #include "../rtengine/ffmanager.h" #include -#include "../rtengine/safegtk.h" #include "rtimage.h" #ifdef _OPENMP #include @@ -1357,7 +1356,7 @@ void Preferences::parseDir (Glib::ustring dirname, std::vector& i Glib::ustring sname = *i; // ignore directories - if (!safe_file_test (fname, Glib::FILE_TEST_IS_DIR) && sname.size() >= ext.size() && sname.substr (sname.size() - ext.size(), ext.size()).casefold() == ext) { + if (!Glib::file_test (fname, Glib::FILE_TEST_IS_DIR) && sname.size() >= ext.size() && sname.substr (sname.size() - ext.size(), ext.size()).casefold() == ext) { items.push_back (sname.substr(0, sname.size() - ext.size())); } } @@ -1647,18 +1646,18 @@ void Preferences::fillPreferences () #ifdef WIN32 edPS->set_active (moptions.editorToSendTo == 2); - if (safe_file_test (moptions.gimpDir, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (moptions.gimpDir, Glib::FILE_TEST_IS_DIR)) { gimpDir->set_current_folder (moptions.gimpDir); } - if (safe_file_test (moptions.psDir, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (moptions.psDir, Glib::FILE_TEST_IS_DIR)) { psDir->set_current_folder (moptions.psDir); } #elif defined __APPLE__ edPS->set_active (moptions.editorToSendTo == 2); - if (safe_file_test (moptions.psDir, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (moptions.psDir, Glib::FILE_TEST_IS_DIR)) { psDir->set_current_folder (moptions.psDir); } @@ -1846,7 +1845,7 @@ void Preferences::cancelPressed () void Preferences::selectStartupDir () { - Gtk::FileChooserDialog dialog(M("PREFERENCES_DIRSELECTDLG"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER); + Gtk::FileChooserDialog dialog (getToplevelWindow (this), M("PREFERENCES_DIRSELECTDLG"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER); // dialog.set_transient_for(*this); //Add response buttons the the dialog: @@ -1951,18 +1950,17 @@ void Preferences::bundledProfilesChanged () void Preferences::iccDirChanged () { - const Glib::ustring currentSelection = monProfile->get_active_text (); + const auto currentSelection = monProfile->get_active_text (); + const auto profiles = rtengine::ICCStore::getInstance ()->getProfilesFromDir (iccDir->get_filename ()); - monProfile->clear(); + monProfile->remove_all(); - monProfile->append_text (M("PREFERENCES_PROFILE_NONE")); - monProfile->set_active (0); + monProfile->append (M("PREFERENCES_PROFILE_NONE")); - const std::vector profiles = rtengine::ICCStore::getInstance ()->getProfilesFromDir (iccDir->get_filename ()); - for (std::vector::const_iterator profile = profiles.begin (); profile != profiles.end (); ++profile) - monProfile->append_text (*profile); + for (const auto& profile : profiles) + monProfile->append (profile); - monProfile->set_active_text (currentSelection); + setActiveTextOrIndex(*monProfile, currentSelection, 0); } void Preferences::storeCurrentValue() diff --git a/rtgui/preprocess.cc b/rtgui/preprocess.cc index 1bfad7cc3..44d054214 100644 --- a/rtgui/preprocess.cc +++ b/rtgui/preprocess.cc @@ -18,7 +18,6 @@ */ #include "preprocess.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include using namespace rtengine; diff --git a/rtgui/previewhandler.cc b/rtgui/previewhandler.cc index e2b635e07..9ba62230f 100644 --- a/rtgui/previewhandler.cc +++ b/rtgui/previewhandler.cc @@ -204,27 +204,14 @@ Glib::RefPtr PreviewHandler::getRoughImage (int x, int y, int w, in h = image->getHeight() * totalZoom; } - int ix = x * zoom; - int iy = y * zoom; + x *= zoom; + y *= zoom; - if (ix < 0) { - ix = 0; - } - - if (iy < 0) { - iy = 0; - } - - if ((ix + w) / totalZoom > previewImg->get_width()) { - ix = previewImg->get_width() * totalZoom - w; - } - - if ((iy + h) / totalZoom > previewImg->get_height()) { - iy = previewImg->get_height() * totalZoom - h; - } + w = rtengine::LIM(w, 0, int(previewImg->get_width() * totalZoom) - x); + h = rtengine::LIM(h, 0, int(previewImg->get_height() * totalZoom) - y); resPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, w, h); - previewImg->scale (resPixbuf, 0, 0, w, h, -ix, -iy, totalZoom, totalZoom, Gdk::INTERP_NEAREST); + previewImg->scale (resPixbuf, 0, 0, w, h, -x, -y, totalZoom, totalZoom, Gdk::INTERP_NEAREST); } return resPixbuf; diff --git a/rtgui/previewloader.cc b/rtgui/previewloader.cc index dd090a95e..02082f7a7 100644 --- a/rtgui/previewloader.cc +++ b/rtgui/previewloader.cc @@ -21,7 +21,6 @@ #include "previewloader.h" #include "guiutils.h" #include "threadutils.h" -#include "../rtengine/safegtk.h" #ifdef _OPENMP #include @@ -123,7 +122,7 @@ public: try { Thumbnail* tmb = 0; { - if (safe_file_test(j.dir_entry_, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test(j.dir_entry_, Glib::FILE_TEST_EXISTS)) { tmb = cacheMgr->getEntry(j.dir_entry_); } } diff --git a/rtgui/previewwindow.cc b/rtgui/previewwindow.cc index be932df5f..ea419427b 100644 --- a/rtgui/previewwindow.cc +++ b/rtgui/previewwindow.cc @@ -100,48 +100,50 @@ void PreviewWindow::on_resized (Gtk::Allocation& req) bool PreviewWindow::on_expose_event (GdkEventExpose* event) { - if (backBuffer) { - Glib::RefPtr window = get_window(); + if (!backBuffer) { + return true; + } - int bufferW, bufferH; - backBuffer->get_size (bufferW, bufferH); + Glib::RefPtr window = get_window(); - if (!mainCropWin && imageArea) { - mainCropWin = imageArea->getMainCropWindow (); + int bufferW, bufferH; + backBuffer->get_size (bufferW, bufferH); - if (mainCropWin) { - mainCropWin->addCropWindowListener (this); - } + if (!mainCropWin && imageArea) { + mainCropWin = imageArea->getMainCropWindow (); + + if (mainCropWin) { + mainCropWin->addCropWindowListener (this); } + } - if ((get_width() != bufferW && get_height() != bufferH) || needsUpdate) { - needsUpdate = false; - updatePreviewImage (); - } + if ((get_width() != bufferW && get_height() != bufferH) || needsUpdate) { + needsUpdate = false; + updatePreviewImage (); + } - window->draw_drawable (get_style()->get_base_gc(Gtk::STATE_NORMAL), backBuffer, 0, 0, 0, 0, -1, -1); + window->draw_drawable (get_style()->get_base_gc(Gtk::STATE_NORMAL), backBuffer, 0, 0, 0, 0, -1, -1); - if (mainCropWin && zoom > 0.0) { - if(mainCropWin->getZoom() > mainCropWin->cropHandler.getFitZoom()) { - Cairo::RefPtr cr = get_window()->create_cairo_context(); - int x, y, w, h; - getObservedFrameArea (x, y, w, h); - double rectX = x + 0.5; - double rectY = y + 0.5; - double rectW = std::min(w, (int)(imgW - (x - imgX) - 1)); - double rectH = std::min(h, (int)(imgH - (y - imgY) - 1)); + if (mainCropWin && zoom > 0.0) { + Cairo::RefPtr cr = get_window()->create_cairo_context(); + int x, y, w, h; + getObservedFrameArea (x, y, w, h); + if (x>imgX || y>imgY || w < imgW || h < imgH) { + double rectX = x + 0.5; + double rectY = y + 0.5; + double rectW = std::min(w, (int)(imgW - (x - imgX) - 1)); + double rectH = std::min(h, (int)(imgH - (y - imgY) - 1)); - // draw a black "shadow" line - cr->set_source_rgba (0.0, 0.0, 0.0, 0.65); - cr->set_line_width (1); - cr->rectangle (rectX + 1., rectY + 1, rectW, rectH); - cr->stroke (); + // draw a black "shadow" line + cr->set_source_rgba (0.0, 0.0, 0.0, 0.65); + cr->set_line_width (1); + cr->rectangle (rectX + 1., rectY + 1, rectW, rectH); + cr->stroke (); - // draw a "frame" line. Color of frame line can be set in preferences - cr->set_source_rgba(options.navGuideBrush[0], options.navGuideBrush[1], options.navGuideBrush[2], options.navGuideBrush[3]); //( 1.0, 1.0, 1.0, 1.0); - cr->rectangle (rectX, rectY, rectW, rectH); - cr->stroke (); - } + // draw a "frame" line. Color of frame line can be set in preferences + cr->set_source_rgba(options.navGuideBrush[0], options.navGuideBrush[1], options.navGuideBrush[2], options.navGuideBrush[3]); //( 1.0, 1.0, 1.0, 1.0); + cr->rectangle (rectX, rectY, rectW, rectH); + cr->stroke (); } } @@ -191,21 +193,23 @@ bool PreviewWindow::on_motion_notify_event (GdkEventMotion* event) return true; } - if(mainCropWin->getZoom() > mainCropWin->cropHandler.getFitZoom()) { - int x, y, w, h; - getObservedFrameArea (x, y, w, h); + int x, y, w, h; + getObservedFrameArea (x, y, w, h); + if (x>imgX || y>imgY || w < imgW || h < imgH) { bool inside = event->x > x - 6 && event->x < x + w - 1 + 6 && event->y > y - 6 && event->y < y + h - 1 + 6; bool moreInside = event->x > x + 6 && event->x < x + w - 1 - 6 && event->y > y + 6 && event->y < y + h - 1 - 6; if (isMoving) { mainCropWin->remoteMove ((event->x - press_x) / zoom, (event->y - press_y) / zoom); + press_x = event->x; + press_y = event->y; } else if (inside && !moreInside) { cursorManager.setCursor (get_window(), CSClosedHand); } else { cursorManager.setCursor (get_window(), CSArrow); } } - + return true; } @@ -216,9 +220,9 @@ bool PreviewWindow::on_button_press_event (GdkEventButton* event) return true; } - if(mainCropWin->getZoom() > mainCropWin->cropHandler.getFitZoom()) { - int x, y, w, h; - getObservedFrameArea (x, y, w, h); + int x, y, w, h; + getObservedFrameArea (x, y, w, h); + if (x>imgX || y>imgY || w < imgW || h < imgH) { bool inside = event->x > x - 6 && event->x < x + w - 1 + 6 && event->y > y - 6 && event->y < y + h - 1 + 6; bool moreInside = event->x > x + 6 && event->x < x + w - 1 - 6 && event->y > y + 6 && event->y < y + h - 1 - 6; diff --git a/rtgui/profilepanel.cc b/rtgui/profilepanel.cc index ca667c4d9..5974b2242 100644 --- a/rtgui/profilepanel.cc +++ b/rtgui/profilepanel.cc @@ -21,7 +21,6 @@ #include "profilestore.h" #include "clipboard.h" #include "multilangmgr.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" using namespace rtengine; @@ -288,29 +287,19 @@ void ProfilePanel::save_clicked (GdkEventButton* event) return; } - Gtk::FileChooserDialog dialog(M("PROFILEPANEL_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); + Gtk::FileChooserDialog dialog (getToplevelWindow (this), M("PROFILEPANEL_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); bindCurrentFolder (dialog, options.loadSaveProfilePath); dialog.set_current_name (lastFilename); //Add the user's default (or global if multiuser=false) profile path to the Shortcut list -#ifdef WIN32 - - // Dirty workaround, waiting for a clean solution by using exceptions! - if (!safe_is_shortcut_dir(options.getPreferredProfilePath())) -#endif - try { - dialog.add_shortcut_folder(options.getPreferredProfilePath()); - } catch (Glib::Error &err) {} + try { + dialog.add_shortcut_folder(options.getPreferredProfilePath()); + } catch (Glib::Error&) {} //Add the image's path to the Shortcut list -#ifdef WIN32 - - // Dirty workaround, waiting for a clean solution by using exceptions! - if (!safe_is_shortcut_dir(imagePath)) -#endif - try { - dialog.add_shortcut_folder(imagePath); - } catch (Glib::Error &err) {} + try { + dialog.add_shortcut_folder(imagePath); + } catch (Glib::Error&) {} //Add response buttons the the dialog: dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); @@ -464,28 +453,18 @@ void ProfilePanel::load_clicked (GdkEventButton* event) return; } - Gtk::FileChooserDialog dialog(M("PROFILEPANEL_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN); + Gtk::FileChooserDialog dialog (getToplevelWindow (this), M("PROFILEPANEL_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN); bindCurrentFolder (dialog, options.loadSaveProfilePath); //Add the user's default (or global if multiuser=false) profile path to the Shortcut list -#ifdef WIN32 - - // Dirty workaround, waiting for a clean solution by using exceptions! - if (!safe_is_shortcut_dir(options.getPreferredProfilePath())) -#endif - try { - dialog.add_shortcut_folder(options.getPreferredProfilePath()); - } catch (Glib::Error &err) {} + try { + dialog.add_shortcut_folder(options.getPreferredProfilePath()); + } catch (Glib::Error&) {} //Add the image's path to the Shortcut list -#ifdef WIN32 - - // Dirty workaround, waiting for a clean solution by using exceptions! - if (!safe_is_shortcut_dir(imagePath)) -#endif - try { - dialog.add_shortcut_folder(imagePath); - } catch (Glib::Error &err) {} + try { + dialog.add_shortcut_folder(imagePath); + } catch (Glib::Error&) {} //Add response buttons the the dialog: dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); @@ -617,6 +596,17 @@ void ProfilePanel::paste_clicked (GdkEventButton* event) } else { if (fillMode->get_active()) { custom->pparams->setDefaults(); + } else if (!isCustomSelected ()) { + if (isLastSavedSelected()) { + *custom->pparams = *lastsaved->pparams; + } else { + const ProfileStoreEntry* entry = profiles->getSelectedEntry(); + + if (entry) { + const PartialProfile* partProfile = profileStore.getProfile (entry); + *custom->pparams = *partProfile->pparams; + } + } } profiles->set_active(getCustomRow()); diff --git a/rtgui/profilestore.cc b/rtgui/profilestore.cc index fd51699bf..482f83188 100644 --- a/rtgui/profilestore.cc +++ b/rtgui/profilestore.cc @@ -20,7 +20,6 @@ #include "options.h" #include "toolpanel.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" ProfileStore profileStore; @@ -168,7 +167,7 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath unsigned int folder = 0; // folder's own Id // reload the available profiles from the profile dir - if (!realPath.empty() && safe_file_test(realPath, Glib::FILE_TEST_EXISTS) && safe_file_test (realPath, Glib::FILE_TEST_IS_DIR)) { + if (!realPath.empty() && Glib::file_test(realPath, Glib::FILE_TEST_EXISTS) && Glib::file_test (realPath, Glib::FILE_TEST_IS_DIR)) { // add this entry to the folder list folders.push_back(virtualPath); @@ -199,7 +198,7 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath Glib::ustring fname = Glib::build_filename(realPath, currDir); - if (safe_file_test (fname, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (fname, Glib::FILE_TEST_IS_DIR)) { Glib::ustring vp(Glib::build_filename(virtualPath, currDir)); Glib::ustring rp(Glib::build_filename(realPath, currDir)); fileFound = parseDir (rp, vp, currDir, folder, level + 1, 0); diff --git a/rtgui/rawcacorrection.cc b/rtgui/rawcacorrection.cc index 0e14182cf..d619ab112 100644 --- a/rtgui/rawcacorrection.cc +++ b/rtgui/rawcacorrection.cc @@ -18,7 +18,6 @@ */ #include "rawcacorrection.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include #include "rtimage.h" @@ -33,6 +32,14 @@ RAWCACorr::RAWCACorr () : FoldableToolPanel(this, "rawcacorrection", M("TP_CHROM Gtk::Image* icablueR = Gtk::manage (new RTImage ("ajd-ca-blue2.png")); caAutocorrect = Gtk::manage(new Gtk::CheckButton((M("TP_RAWCACORR_AUTO")))); + + caStrength = Gtk::manage(new Adjuster (M("TP_RAWCACORR_CASTR"), 2.0, 8.0, 0.5, 6.0)); + caStrength->setAdjusterListener (this); + if (caStrength->delay < options.adjusterMaxDelay) { + caStrength->delay = options.adjusterMaxDelay; + } + +// caStrength->show(); caRed = Gtk::manage(new Adjuster (M("TP_RAWCACORR_CARED"), -4.0, 4.0, 0.1, 0, icaredL, icaredR)); caRed->setAdjusterListener (this); @@ -51,6 +58,7 @@ RAWCACorr::RAWCACorr () : FoldableToolPanel(this, "rawcacorrection", M("TP_CHROM caBlue->show(); pack_start( *caAutocorrect, Gtk::PACK_SHRINK, 4); +// pack_start( *caStrength, Gtk::PACK_SHRINK, 4); pack_start( *caRed, Gtk::PACK_SHRINK, 4); pack_start( *caBlue, Gtk::PACK_SHRINK, 4); @@ -64,17 +72,20 @@ void RAWCACorr::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi if(pedited ) { caAutocorrect->set_inconsistent(!pedited->raw.caCorrection); + caStrength->setEditedState( pedited->raw.caAutoStrength ? Edited : UnEdited ); caRed->setEditedState( pedited->raw.caRed ? Edited : UnEdited ); caBlue->setEditedState( pedited->raw.caBlue ? Edited : UnEdited ); } lastCA = pp->raw.ca_autocorrect; + caStrength->set_sensitive(pp->raw.ca_autocorrect); // disable Red and Blue sliders when caAutocorrect is enabled caRed->set_sensitive(!pp->raw.ca_autocorrect); caBlue->set_sensitive(!pp->raw.ca_autocorrect); caAutocorrect->set_active(pp->raw.ca_autocorrect); + caStrength->setValue (pp->raw.caautostrength); caRed->setValue (pp->raw.cared); caBlue->setValue (pp->raw.cablue); @@ -85,11 +96,13 @@ void RAWCACorr::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi void RAWCACorr::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { pp->raw.ca_autocorrect = caAutocorrect->get_active(); + pp->raw.caautostrength = caStrength->getValue(); pp->raw.cared = caRed->getValue(); pp->raw.cablue = caBlue->getValue(); if (pedited) { pedited->raw.caCorrection = !caAutocorrect->get_inconsistent(); + pedited->raw.caAutoStrength = caStrength->getEditedState (); pedited->raw.caRed = caRed->getEditedState (); pedited->raw.caBlue = caBlue->getEditedState (); } @@ -106,6 +119,8 @@ void RAWCACorr::adjusterChanged (Adjuster* a, double newval) listener->panelChanged (EvPreProcessCARed, value ); } else if (a == caBlue) { listener->panelChanged (EvPreProcessCABlue, value ); +// } else if (a == caStrength) { +// listener->panelChanged (EvPreProcessCAStrength, value ); } } } @@ -113,19 +128,23 @@ void RAWCACorr::adjusterChanged (Adjuster* a, double newval) void RAWCACorr::setBatchMode(bool batchMode) { ToolPanel::setBatchMode (batchMode); + caStrength->showEditedCB (); caRed->showEditedCB (); caBlue->showEditedCB (); } void RAWCACorr::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { + caStrength->setDefault( defParams->raw.caautostrength); caRed->setDefault( defParams->raw.cared); caBlue->setDefault( defParams->raw.cablue); if (pedited) { + caStrength->setDefaultEditedState( pedited->raw.caAutoStrength ? Edited : UnEdited); caRed->setDefaultEditedState( pedited->raw.caRed ? Edited : UnEdited); caBlue->setDefaultEditedState( pedited->raw.caBlue ? Edited : UnEdited); } else { + caStrength->setDefaultEditedState( Irrelevant ); caRed->setDefaultEditedState( Irrelevant ); caBlue->setDefaultEditedState( Irrelevant ); } @@ -159,6 +178,7 @@ void RAWCACorr::caCorrectionChanged() } }*/ + caStrength->set_sensitive(caAutocorrect->get_active ()); // disable Red and Blue sliders when caAutocorrect is enabled caRed->set_sensitive(!caAutocorrect->get_active ()); caBlue->set_sensitive(!caAutocorrect->get_active ()); @@ -179,6 +199,7 @@ void RAWCACorr::caCorrectionChanged() void RAWCACorr::setAdjusterBehavior (bool caadd) { + caStrength->setAddMode(caadd); caRed->setAddMode(caadd); caBlue->setAddMode(caadd); } @@ -186,6 +207,7 @@ void RAWCACorr::setAdjusterBehavior (bool caadd) void RAWCACorr::trimValues (rtengine::procparams::ProcParams* pp) { + caStrength->trimValue(pp->raw.caautostrength); caRed->trimValue(pp->raw.cared); caBlue->trimValue(pp->raw.cablue); } diff --git a/rtgui/rawcacorrection.h b/rtgui/rawcacorrection.h index 7d41d9547..82df2c3af 100644 --- a/rtgui/rawcacorrection.h +++ b/rtgui/rawcacorrection.h @@ -29,6 +29,7 @@ class RAWCACorr : public ToolParamBlock, public AdjusterListener, public Foldabl protected: Gtk::CheckButton* caAutocorrect; + Adjuster* caStrength; Adjuster* caRed; Adjuster* caBlue; bool lastCA; diff --git a/rtgui/rawexposure.cc b/rtgui/rawexposure.cc index 746b453cf..56fcf7ec9 100644 --- a/rtgui/rawexposure.cc +++ b/rtgui/rawexposure.cc @@ -18,7 +18,6 @@ */ #include "rawexposure.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include using namespace rtengine; diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc index 167e8efeb..fead40b88 100644 --- a/rtgui/retinex.cc +++ b/rtgui/retinex.cc @@ -209,7 +209,6 @@ Retinex::Retinex () : FoldableToolPanel(this, "retinex", M("TP_RETINEX_LABEL"), mapMethod = Gtk::manage (new MyComboBoxText ()); mapMethod->append_text (M("TP_RETINEX_MAP_NONE")); -// mapMethod->append_text (M("TP_RETINEX_MAP_CURV")); mapMethod->append_text (M("TP_RETINEX_MAP_GAUS")); mapMethod->append_text (M("TP_RETINEX_MAP_MAPP")); mapMethod->append_text (M("TP_RETINEX_MAP_MAPT")); diff --git a/rtgui/rtimage.cc b/rtgui/rtimage.cc index 6472467e6..64d36e412 100644 --- a/rtgui/rtimage.cc +++ b/rtgui/rtimage.cc @@ -19,151 +19,181 @@ */ #include "rtimage.h" -#include "../rtengine/safegtk.h" -extern Glib::ustring argv0; -extern Options options; +#include -std::vector imagesPaths; -std::map > pixBufMap; // List of image buffers in order to live update them on theme switch and to avoid a lot of file accesses +#include "options.h" -/* - * RTImage is a derived class of Gtk::Image, in order to handle theme related iconsets - */ -RTImage::RTImage(Glib::ustring fileName, Glib::ustring rtlFileName) : Gtk::Image() +namespace { - Glib::ustring mapKey; - if (rtlFileName.length()) { - if (get_direction() == Gtk::TEXT_DIR_RTL) { - mapKey = rtlFileName; - } else { - mapKey = fileName; +std::vector imagePaths; +std::map> pixbufCache; + +bool loadIconSet(const Glib::ustring& iconSet) +{ + try { + + Glib::KeyFile keyFile; + keyFile.load_from_file (iconSet); + + auto iconSetDir = keyFile.get_string ("General", "Iconset"); + + if (!iconSetDir.empty ()) { + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "actions")); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir)); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "devices")); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "places")); } + + iconSetDir = keyFile.get_string ("General", "FallbackIconset"); + + if (!iconSetDir.empty ()) { + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "actions")); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir)); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "devices")); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "places")); + } + + return true; + + } catch (const Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to load icon set \"" << iconSet << "\": " << exception.what() << std::endl; + } + + return false; + + } +} + +} + +RTImage::RTImage (const Glib::ustring& fileName, const Glib::ustring& rtlFileName) : Gtk::Image() +{ + Glib::ustring imageName; + + if (!rtlFileName.empty () && get_direction () == Gtk::TEXT_DIR_RTL) { + imageName = rtlFileName; } else { - mapKey = fileName; + imageName = fileName; } - std::map >::iterator it; - it = pixBufMap.find(mapKey); + changeImage (imageName); +} - if (it != pixBufMap.end()) { - set(it->second); - } else { - Glib::RefPtr tempPixPuf = Gdk::Pixbuf::create_from_file(findIconAbsolutePath(mapKey)); - pixBufMap.insert(std::pair >(mapKey, tempPixPuf)); - set(tempPixPuf); +void RTImage::changeImage (const Glib::ustring& imageName) +{ + clear (); + + auto iterator = pixbufCache.find (imageName); + + if (iterator == pixbufCache.end ()) { + const auto imagePath = findIconAbsolutePath (imageName); + const auto pixbuf = Gdk::Pixbuf::create_from_file (imagePath); + + iterator = pixbufCache.emplace (imageName, pixbuf).first; } + + set(iterator->second); } void RTImage::updateImages() { - std::map >::iterator it; - - for (it = pixBufMap.begin(); it != pixBufMap.end(); ++it) { - Glib::ustring fullPath = findIconAbsolutePath(it->first); - it->second = Gdk::Pixbuf::create_from_file(fullPath); + for (auto& entry : pixbufCache) { + const auto imagePath = findIconAbsolutePath (entry.first); + entry.second = Gdk::Pixbuf::create_from_file (imagePath); } } -// DONE (was TODO: Maybe this could be optimized: in order to avoid looking up for an icon file in the filesystem on each popupmenu selection, maybe we could find a way to copy the image data from another RTImage) -void RTImage::changeImage(Glib::ustring &newImage) +Glib::ustring RTImage::findIconAbsolutePath (const Glib::ustring& iconName) { - clear(); - std::map >::iterator it; - it = pixBufMap.find(newImage); - - if (it != pixBufMap.end()) { - set(it->second); - } else { - Glib::ustring fullPath = findIconAbsolutePath(newImage); - Glib::RefPtr tempPixPuf = Gdk::Pixbuf::create_from_file(fullPath); - pixBufMap.insert(std::pair >(newImage, tempPixPuf)); - set(tempPixPuf); - } -} - -Glib::ustring RTImage::findIconAbsolutePath(const Glib::ustring &iconFName) -{ - Glib::ustring path; - - for (unsigned int i = 0; i < imagesPaths.size(); i++) { - path = Glib::build_filename(imagesPaths[i], iconFName); - - if (safe_file_test(path, Glib::FILE_TEST_EXISTS)) { - return path; - } - } - - printf("\"%s\" not found!\n", iconFName.c_str()); - return ""; -} - -void RTImage::setPaths(Options &opt) -{ - Glib::ustring configFilename; - rtengine::SafeKeyFile keyFile; - bool hasKeyFile = true; - - imagesPaths.clear(); - - // system theme will use the theme set in system.iconset - if (opt.useSystemTheme) { - configFilename = Glib::build_filename(argv0, Glib::build_filename("themes", "system.iconset")); - } - // Gtk theme will use the theme set in it's *.iconset fiel, if it exists - else { - configFilename = Glib::build_filename(argv0, Glib::build_filename("themes", Glib::ustring::format(opt.theme, ".iconset"))); - } - try { - if (!safe_file_test(configFilename, Glib::FILE_TEST_EXISTS) || !keyFile.load_from_file (configFilename)) { - // ...otherwise fallback to the iconset set in default.iconset - configFilename = Glib::build_filename(argv0, Glib::build_filename("themes", "Default.iconset")); - if (!keyFile.load_from_file (configFilename)) { - hasKeyFile = false; + for (const auto& imagePath : imagePaths) { + const auto iconPath = Glib::build_filename(imagePath, iconName); + + if (Glib::file_test(iconPath, Glib::FILE_TEST_IS_REGULAR)) { + return iconPath; } } - } catch (Glib::Error &err) { - if (options.rtSettings.verbose) { - printf("RTImage::setPaths / Error code %d while reading values from \"%s\":\n%s\n", err.code(), configFilename.c_str(), err.what().c_str()); - } - } catch (...) { - if (options.rtSettings.verbose) { - printf("RTImage::setPaths / Unknown exception while trying to load \"%s\"!\n", configFilename.c_str()); - } + + } catch(const Glib::Exception&) {} + + if (options.rtSettings.verbose) { + std::cerr << "Icon \"" << iconName << "\" could not be found!" << std::endl; } - if (hasKeyFile && keyFile.has_group ("General")) { - Glib::ustring iSet; - - if (keyFile.has_key ("General", "Iconset")) { - iSet = keyFile.get_string ("General", "Iconset"); - } - - if (iSet.length()) { - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename(iSet, "actions")))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", iSet))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename(iSet, "devices")))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename(iSet, "places")))); - } - - iSet.clear(); - - if (keyFile.has_key ("General", "FallbackIconset")) { - iSet = keyFile.get_string ("General", "FallbackIconset"); - } - - if (iSet.length()) { - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename(iSet, "actions")))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", iSet))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename(iSet, "devices")))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename(iSet, "places")))); - } - } - - // The images/ folder is the second fallback solution - imagesPaths.push_back (Glib::build_filename(argv0, "images")); + return Glib::ustring(); } +void RTImage::setPaths (const Options& options) +{ + Glib::ustring iconSet; + + // Either use the system icon set or the one specified in the options. + if (options.useSystemTheme) { + iconSet = Glib::build_filename (argv0, "themes", "system.iconset"); + } else { + iconSet = Glib::build_filename (argv0, "themes", options.theme + ".iconset"); + } + + imagePaths.clear (); + + if (!loadIconSet (iconSet)) { + // If the preferred icon set is unavailable, fall back to the default icon set. + loadIconSet (Glib::build_filename (argv0, "themes", "Default.iconset")); + } + + // The images folder is the second fallback solution. + imagePaths.push_back (Glib::build_filename(argv0, "images")); +} + +Glib::RefPtr RTImage::createFromFile (const Glib::ustring& fileName) +{ + Glib::RefPtr pixbuf; + + try { + + const auto filePath = findIconAbsolutePath (fileName); + + if (!filePath.empty ()) { + pixbuf = Gdk::Pixbuf::create_from_file (filePath); + } + + } catch (const Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to load image \"" << fileName << "\": " << exception.what() << std::endl; + } + + } + + return pixbuf; +} + +Cairo::RefPtr RTImage::createFromPng (const Glib::ustring& fileName) +{ + Cairo::RefPtr surface; + + try { + + const auto filePath = findIconAbsolutePath (fileName); + + if (!filePath.empty()) { + surface = Cairo::ImageSurface::create_from_png (Glib::locale_from_utf8 (filePath)); + } + + } catch (const Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to load PNG \"" << fileName << "\": " << exception.what() << std::endl; + } + + } + + return surface; +} + + diff --git a/rtgui/rtimage.h b/rtgui/rtimage.h index de5ef9334..cfc7a5fa1 100644 --- a/rtgui/rtimage.h +++ b/rtgui/rtimage.h @@ -19,17 +19,26 @@ #ifndef _RTIMAGE_ #define _RTIMAGE_ -#include -#include "options.h" +#include +class Options; + +/** + * @brief A derived class of Gtk::Image in order to handle theme-related icon sets. + */ class RTImage : public Gtk::Image { public: - RTImage(Glib::ustring fileName, Glib::ustring rtlFileName = ""); - static void setPaths(Options &opt); - static void updateImages(); - void changeImage(Glib::ustring &newImage); - static Glib::ustring findIconAbsolutePath(const Glib::ustring &iconFName); + RTImage (const Glib::ustring& fileName, const Glib::ustring& rtlFileName = Glib::ustring()); + + void changeImage (const Glib::ustring& imageName); + static void updateImages (); + + static Glib::ustring findIconAbsolutePath (const Glib::ustring& iconName); + static void setPaths (const Options& options); + + static Glib::RefPtr createFromFile (const Glib::ustring& fileName); + static Cairo::RefPtr createFromPng (const Glib::ustring& fileName); }; #endif diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index 338c5b36e..ba6c0cbd8 100644 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -341,6 +341,10 @@ void RTWindow::on_realize () fpanel->setAspect(); } + if (simpleEditor) { + epanel->setAspect(); + } + cursorManager.init (get_window()); // Check if first run of this version, then display the Release Notes text diff --git a/rtgui/saveasdlg.cc b/rtgui/saveasdlg.cc index 47957bc80..c9490f585 100644 --- a/rtgui/saveasdlg.cc +++ b/rtgui/saveasdlg.cc @@ -19,7 +19,6 @@ #include "saveasdlg.h" #include "multilangmgr.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" extern Options options; @@ -224,7 +223,7 @@ void SaveAsDialog::okPressed () // checking if the filename field is empty. The user have to click Cancel if he don't want to specify a filename // NB: There seem to be a bug in Gtkmm2.22 / FileChooserWidget : if you suppress the filename entry and // click on a folder in the list, the filename field is empty but get_filename will return the folder's path :/ - if (!fname.length() || safe_file_test (fname, Glib::FILE_TEST_IS_DIR)) { + if (!fname.length() || Glib::file_test (fname, Glib::FILE_TEST_IS_DIR)) { Glib::ustring msg_ = Glib::ustring("") + M("MAIN_MSG_EMPTYFILENAME") + ""; Gtk::MessageDialog msgd (*this, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true); msgd.run (); @@ -286,20 +285,13 @@ void SaveAsDialog::setInitialFileName (Glib::ustring fname) fchooser->set_current_name(fname); } -void SaveAsDialog::setImagePath (Glib::ustring ipath) +void SaveAsDialog::setImagePath (const Glib::ustring& imagePath) { + const auto dirName = Glib::path_get_dirname (imagePath); - Glib::ustring path = Glib::path_get_dirname(ipath); - - //Add the image's path to the Shortcut list -#ifdef WIN32 - - // Dirty workaround, waiting for a clean solution by using exceptions! - if (!safe_is_shortcut_dir(path)) -#endif - try { - fchooser->add_shortcut_folder(path); - } catch (Glib::Error &err) {} + try { + fchooser->add_shortcut_folder (dirName); + } catch (Glib::Error&) {} } diff --git a/rtgui/saveasdlg.h b/rtgui/saveasdlg.h index db307e4b8..4727b574c 100644 --- a/rtgui/saveasdlg.h +++ b/rtgui/saveasdlg.h @@ -58,7 +58,7 @@ public: int getSaveMethodNum (); void setInitialFileName (Glib::ustring iname); - void setImagePath (Glib::ustring ipath); + void setImagePath (const Glib::ustring& imagePath); void okPressed (); void cancelPressed (); diff --git a/rtgui/sharpenedge.cc b/rtgui/sharpenedge.cc index 880240f04..d21fe54aa 100644 --- a/rtgui/sharpenedge.cc +++ b/rtgui/sharpenedge.cc @@ -18,7 +18,6 @@ */ #include "sharpenedge.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include #include diff --git a/rtgui/sharpenmicro.cc b/rtgui/sharpenmicro.cc index 49c36e99f..2ca0ddf44 100644 --- a/rtgui/sharpenmicro.cc +++ b/rtgui/sharpenmicro.cc @@ -18,7 +18,6 @@ */ #include "sharpenmicro.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include #include diff --git a/rtgui/soundman.h b/rtgui/soundman.h index a778a006a..dd8e515fc 100644 --- a/rtgui/soundman.h +++ b/rtgui/soundman.h @@ -21,7 +21,10 @@ #ifndef _SOUNDMAN_ #define _SOUNDMAN_ -#include "../rtengine/safegtk.h" +namespace Glib +{ +class ustring; +} class SoundManager { diff --git a/rtgui/splash.cc b/rtgui/splash.cc index b385ca460..c936639f7 100644 --- a/rtgui/splash.cc +++ b/rtgui/splash.cc @@ -17,9 +17,11 @@ * along with RawTherapee. If not, see . */ #include "splash.h" -#include "multilangmgr.h" + #include -#include "../rtengine/safegtk.h" + +#include "multilangmgr.h" +#include "rtimage.h" extern Glib::ustring argv0; extern Glib::ustring creditsPath; @@ -29,8 +31,7 @@ extern Glib::ustring versionSuffixString; SplashImage::SplashImage () { - - pixbuf = safe_create_from_file ("splash.png"); + pixbuf = RTImage::createFromFile ("splash.png"); set_size_request (pixbuf->get_width(), pixbuf->get_height()); } @@ -106,8 +107,8 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t // Tab 2: the informations about the current version std::string buildFileName = Glib::build_filename (creditsPath, "AboutThisBuild.txt"); - if ( safe_file_test(buildFileName, (Glib::FILE_TEST_EXISTS)) ) { - FILE *f = safe_g_fopen (buildFileName, "rt"); + if ( Glib::file_test(buildFileName, (Glib::FILE_TEST_EXISTS)) ) { + FILE *f = g_fopen (buildFileName.c_str (), "rt"); if (f != NULL) { char* buffer = new char[1024]; @@ -136,8 +137,8 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t // Tab 3: the credits std::string creditsFileName = Glib::build_filename (creditsPath, "AUTHORS.txt"); - if ( safe_file_test(creditsFileName, (Glib::FILE_TEST_EXISTS)) ) { - FILE *f = safe_g_fopen (creditsFileName, "rt"); + if ( Glib::file_test(creditsFileName, (Glib::FILE_TEST_EXISTS)) ) { + FILE *f = g_fopen (creditsFileName.c_str (), "rt"); if (f != NULL) { char* buffer = new char[1024]; @@ -167,8 +168,8 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t // Tab 4: the license std::string licenseFileName = Glib::build_filename (licensePath, "LICENSE.txt"); - if ( safe_file_test(licenseFileName, (Glib::FILE_TEST_EXISTS)) ) { - FILE *f = safe_g_fopen (licenseFileName, "rt"); + if ( Glib::file_test(licenseFileName, (Glib::FILE_TEST_EXISTS)) ) { + FILE *f = g_fopen (licenseFileName.c_str (), "rt"); if (f != NULL) { char* buffer = new char[1024]; @@ -204,8 +205,8 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t // Tab 5: the Release Notes std::string releaseNotesFileName = Glib::build_filename (creditsPath, "RELEASE_NOTES.txt"); - if ( safe_file_test(releaseNotesFileName, (Glib::FILE_TEST_EXISTS)) ) { - FILE *f = safe_g_fopen (releaseNotesFileName, "rt"); + if ( Glib::file_test(releaseNotesFileName, (Glib::FILE_TEST_EXISTS)) ) { + FILE *f = g_fopen (releaseNotesFileName.c_str (), "rt"); if (f != NULL) { char* buffer = new char[1024]; diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 5e132cc14..673c49efe 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -29,7 +29,7 @@ #include "guiutils.h" #include "profilestore.h" #include "batchqueue.h" -#include "../rtengine/safegtk.h" +#include "extprog.h" using namespace rtengine::procparams; @@ -153,7 +153,7 @@ void Thumbnail::_generateThumbnailImage () cfs.supported = true; needsReProcessing = true; - cfs.save (getCacheFileName ("data") + ".txt"); + cfs.save (getCacheFileName ("data", ".txt")); generateExifDateTimeStrings (); } @@ -238,7 +238,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu if (options.paramsLoadLocation == PLL_Input) { outFName = fname + paramFileExtension; } else { - outFName = getCacheFileName("profiles") + paramFileExtension; + outFName = getCacheFileName("profiles", paramFileExtension); } exifDir->CPBDump(tmpFileName, fname, outFName, @@ -254,20 +254,16 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu printf("Custom profile builder's command line: %s\n", Glib::ustring(cmdLine).c_str()); } - bool success = safe_spawn_command_line_sync (cmdLine); + bool success = ExtProgStore::spawnCommandSync (cmdLine); // Now they SHOULD be there (and potentially "partial"), so try to load them and store it as a full procparam if (success) { loadProcParams(); } - if (safe_file_test(tmpFileName, Glib::FILE_TEST_EXISTS )) { - safe_g_remove (tmpFileName); - } + g_remove (tmpFileName.c_str ()); - if (imageMetaData) { - delete imageMetaData; - } + delete imageMetaData; } if (returnParams && hasProcParams()) { @@ -309,11 +305,11 @@ void Thumbnail::loadProcParams () // if no success, try to load the cached version of the procparams if (!pparamsValid) { - pparamsValid = !pparams.load (getCacheFileName ("profiles") + paramFileExtension); + pparamsValid = !pparams.load (getCacheFileName ("profiles", paramFileExtension)); } } else { // try to load it from cache - pparamsValid = !pparams.load (getCacheFileName ("profiles") + paramFileExtension); + pparamsValid = !pparams.load (getCacheFileName ("profiles", paramFileExtension)); // if no success, try to load it from params file next to the image file if (!pparamsValid) { @@ -364,25 +360,15 @@ void Thumbnail::clearProcParams (int whoClearedIt) updateCache(); } else { // remove param file from cache - Glib::ustring fname_ = getCacheFileName ("profiles") + paramFileExtension; - - if (safe_file_test (fname_, Glib::FILE_TEST_EXISTS)) { - safe_g_remove (fname_); - } + Glib::ustring fname_ = getCacheFileName ("profiles", paramFileExtension); + g_remove (fname_.c_str ()); // remove param file located next to the file -// fname_ = removeExtension(fname) + paramFileExtension; fname_ = fname + paramFileExtension; - - if (safe_file_test(fname_, Glib::FILE_TEST_EXISTS)) { - safe_g_remove (fname_); - } + g_remove (fname_.c_str ()); fname_ = removeExtension(fname) + paramFileExtension; - - if (safe_file_test (fname_, Glib::FILE_TEST_EXISTS)) { - safe_g_remove (fname_); - } + g_remove (fname_.c_str ()); if (cfs.format == FT_Raw && options.internalThumbIfUntouched && cfs.thumbImgType != CacheImageData::QUICK_THUMBNAIL) { // regenerate thumbnail, ie load the quick thumb again. For the rare formats not supporting quick thumbs this will @@ -464,10 +450,10 @@ void Thumbnail::imageDeveloped () { cfs.recentlySaved = true; - cfs.save (getCacheFileName ("data") + ".txt"); + cfs.save (getCacheFileName ("data", ".txt")); if (options.saveParamsCache) { - pparams.save (getCacheFileName ("profiles") + paramFileExtension); + pparams.save (getCacheFileName ("profiles", paramFileExtension)); } } @@ -778,14 +764,14 @@ void Thumbnail::_loadThumbnail(bool firstTrial) tpp->isRaw = (cfs.format == (int) FT_Raw); // load supplementary data - bool succ = tpp->readData (getCacheFileName ("data") + ".txt"); + bool succ = tpp->readData (getCacheFileName ("data", ".txt")); if (succ) { tpp->getAutoWBMultipliers(cfs.redAWBMul, cfs.greenAWBMul, cfs.blueAWBMul); } // thumbnail image - succ = succ && tpp->readImage (getCacheFileName ("images")); + succ = succ && tpp->readImage (getCacheFileName ("images", "")); if (!succ && firstTrial) { _generateThumbnailImage (); @@ -805,10 +791,10 @@ void Thumbnail::_loadThumbnail(bool firstTrial) if ( cfs.thumbImgType == CacheImageData::FULL_THUMBNAIL ) { // load aehistogram - tpp->readAEHistogram (getCacheFileName ("aehistograms")); + tpp->readAEHistogram (getCacheFileName ("aehistograms", "")); // load embedded profile - tpp->readEmbProfile (getCacheFileName ("embprofiles") + ".icc"); + tpp->readEmbProfile (getCacheFileName ("embprofiles", ".icc")); tpp->init (); } @@ -847,24 +833,24 @@ void Thumbnail::_saveThumbnail () return; } - if (safe_g_remove (getCacheFileName ("images") + ".rtti") == -1) { + if (g_remove (getCacheFileName ("images", ".rtti").c_str ()) != 0) { // No file deleted, so we try to deleted obsolete files, if any - safe_g_remove (getCacheFileName ("images") + ".cust"); - safe_g_remove (getCacheFileName ("images") + ".cust16"); - safe_g_remove (getCacheFileName ("images") + ".jpg"); + g_remove (getCacheFileName ("images", ".cust").c_str ()); + g_remove (getCacheFileName ("images", ".cust16").c_str ()); + g_remove (getCacheFileName ("images", ".jpg").c_str ()); } // save thumbnail image - tpp->writeImage (getCacheFileName ("images"), 1); + tpp->writeImage (getCacheFileName ("images", ""), 1); // save aehistogram - tpp->writeAEHistogram (getCacheFileName ("aehistograms")); + tpp->writeAEHistogram (getCacheFileName ("aehistograms", "")); // save embedded profile - tpp->writeEmbProfile (getCacheFileName ("embprofiles") + ".icc"); + tpp->writeEmbProfile (getCacheFileName ("embprofiles", ".icc")); // save supplementary data - tpp->writeData (getCacheFileName ("data") + ".txt"); + tpp->writeData (getCacheFileName ("data", ".txt")); } /* @@ -893,13 +879,13 @@ void Thumbnail::updateCache (bool updatePParams, bool updateCacheImageData) if (updatePParams && pparamsValid) { pparams.save ( options.saveParamsFile ? fname + paramFileExtension : "", - options.saveParamsCache ? getCacheFileName ("profiles") + paramFileExtension : "", + options.saveParamsCache ? getCacheFileName ("profiles", paramFileExtension) : "", true ); } if (updateCacheImageData) { - cfs.save (getCacheFileName ("data") + ".txt"); + cfs.save (getCacheFileName ("data", ".txt")); } } @@ -912,10 +898,9 @@ Thumbnail::~Thumbnail () mutex.unlock(); } -Glib::ustring Thumbnail::getCacheFileName (Glib::ustring subdir) +Glib::ustring Thumbnail::getCacheFileName (const Glib::ustring& subdir, const Glib::ustring& fext) const { - - return cachemgr->getCacheFileName (subdir, fname, Glib::ustring(), cfs.md5); + return cachemgr->getCacheFileName (subdir, fname, fext, cfs.md5); } void Thumbnail::setFileName (const Glib::ustring fn) @@ -956,7 +941,7 @@ bool Thumbnail::openDefaultViewer(int destination) if (destination == 1) { openFName = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format); - if (safe_file_test (openFName, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test (openFName, Glib::FILE_TEST_EXISTS)) { wchar_t *wfilename = (wchar_t*)g_utf8_to_utf16 (openFName.c_str(), -1, NULL, NULL, NULL); ShellExecuteW(NULL, L"open", wfilename, NULL, NULL, SW_SHOWMAXIMIZED ); g_free(wfilename); @@ -970,7 +955,7 @@ bool Thumbnail::openDefaultViewer(int destination) printf("Opening %s\n", openFName.c_str()); - if (safe_file_test (openFName, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test (openFName, Glib::FILE_TEST_EXISTS)) { // Output file exists, so open explorer and select output file wchar_t* org = (wchar_t*)g_utf8_to_utf16 (Glib::ustring::compose("/select,\"%1\"", openFName).c_str(), -1, NULL, NULL, NULL); wchar_t* par = new wchar_t[wcslen(org) + 1]; @@ -991,7 +976,7 @@ bool Thumbnail::openDefaultViewer(int destination) delete[] par; g_free(org); - } else if (safe_file_test (Glib::path_get_dirname(openFName), Glib::FILE_TEST_EXISTS)) { + } else if (Glib::file_test (Glib::path_get_dirname(openFName), Glib::FILE_TEST_EXISTS)) { // Out file does not exist, but directory wchar_t *wfilename = (wchar_t*)g_utf8_to_utf16 (Glib::path_get_dirname(openFName).c_str(), -1, NULL, NULL, NULL); ShellExecuteW(NULL, L"explore", wfilename, NULL, NULL, SW_SHOWNORMAL ); diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index df3b4549e..8656543f0 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -75,7 +75,7 @@ class Thumbnail void loadThumbnail (bool firstTrial = true); void generateExifDateTimeStrings (); - Glib::ustring getCacheFileName (Glib::ustring subdir); + Glib::ustring getCacheFileName (const Glib::ustring& subdir, const Glib::ustring& fext) const; public: Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageData* cf); diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 2c7ae9115..a9f78273e 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -28,7 +28,7 @@ using namespace rtengine::procparams; -ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) +ToolPanelCoordinator::ToolPanelCoordinator () : ipc(nullptr), editDataProvider(nullptr) { exposurePanel = Gtk::manage (new ToolVBox ()); @@ -269,8 +269,8 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) toolPanelNotebook->set_scrollable (); toolPanelNotebook->show_all (); - for (size_t i = 0; i < toolPanels.size(); i++) { - toolPanels[i]->setListener (this); + for (auto toolPanel : toolPanels) { + toolPanel->setListener (this); } whitebalance->setWBProvider (this); @@ -323,8 +323,8 @@ void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib:: ProcParams* params = ipc->beginUpdateParams (); - for (size_t i = 0; i < toolPanels.size(); i++) { - toolPanels[i]->write (params); + for (auto toolPanel : toolPanels) { + toolPanel->write (params); } // Compensate rotation on flip @@ -336,6 +336,23 @@ void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib:: } } + int tr = TR_NONE; + if (params->coarse.rotate == 90) { + tr = TR_R90; + } else if (params->coarse.rotate == 180) { + tr = TR_R180; + } else if (params->coarse.rotate == 270) { + tr = TR_R270; + } + + // Update "on preview" geometry + if (event == rtengine::EvPhotoLoaded || event == rtengine::EvProfileChanged || event == rtengine::EvHistoryBrowsed || event == rtengine::EvCTRotate) { + // updating the "on preview" geometry + int fw, fh; + ipc->getInitialImage()->getImageSource()->getFullSize (fw, fh, tr); + gradient->updateGeometry (params->gradient.centerX, params->gradient.centerY, params->gradient.feather, params->gradient.degree, fw, fh); + } + // some transformations make the crop change for convenience if (event == rtengine::EvCTHFlip) { crop->hFlipCrop (); @@ -357,8 +374,8 @@ void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib:: hasChanged = true; - for (size_t i = 0; i < paramcListeners.size(); i++) { - paramcListeners[i]->procParamsChanged (params, event, descr); + for (auto paramcListener : paramcListeners) { + paramcListener->procParamsChanged (params, event, descr); } } @@ -403,33 +420,32 @@ void ToolPanelCoordinator::profileChange (const PartialProfile *nparams, rtengi delete mergedParams; tr = TR_NONE; - if (params->coarse.rotate == 90) { - tr |= TR_R90; - } - - if (params->coarse.rotate == 180) { - tr |= TR_R180; - } - - if (params->coarse.rotate == 270) { - tr |= TR_R270; + tr = TR_R90; + } else if (params->coarse.rotate == 180) { + tr = TR_R180; + } else if (params->coarse.rotate == 270) { + tr = TR_R270; } // trimming overflowing cropped area - rtengine::ImageSource *ii = (rtengine::ImageSource*)ipc->getInitialImage(); - ii->getFullSize (fw, fh, tr); + ipc->getInitialImage()->getImageSource()->getFullSize (fw, fh, tr); crop->trim(params, fw, fh); // updating the GUI with updated values - for (unsigned int i = 0; i < toolPanels.size(); i++) { - toolPanels[i]->read (params); + for (auto toolPanel : toolPanels) { + toolPanel->read (params); if (event == rtengine::EvPhotoLoaded || event == rtengine::EvProfileChanged) { - toolPanels[i]->autoOpenCurve(); + toolPanel->autoOpenCurve(); } } + if (event == rtengine::EvPhotoLoaded || event == rtengine::EvProfileChanged || event == rtengine::EvHistoryBrowsed || event == rtengine::EvCTRotate) { + // updating the "on preview" geometry + gradient->updateGeometry (params->gradient.centerX, params->gradient.centerY, params->gradient.feather, params->gradient.degree, fw, fh); + } + // start the IPC processing if (filterRawRefresh) { ipc->endUpdateParams ( refreshmap[(int)event] & ALLNORAW ); @@ -439,8 +455,8 @@ void ToolPanelCoordinator::profileChange (const PartialProfile *nparams, rtengi hasChanged = event != rtengine::EvProfileChangeNotification; - for (size_t i = 0; i < paramcListeners.size(); i++) { - paramcListeners[i]->procParamsChanged (params, event, descr); + for (auto paramcListener : paramcListeners) { + paramcListener->procParamsChanged (params, event, descr); } } @@ -448,8 +464,8 @@ void ToolPanelCoordinator::setDefaults (ProcParams* defparams) { if (defparams) - for (size_t i = 0; i < toolPanels.size(); i++) { - toolPanels[i]->setDefaults (defparams); + for (auto toolPanel : toolPanels) { + toolPanel->setDefaults (defparams); } } @@ -746,9 +762,9 @@ void ToolPanelCoordinator::updateCurveBackgroundHistogram (LUTu & histToneCurve, void ToolPanelCoordinator::foldAllButOne (Gtk::Box* parent, FoldableToolPanel* openedSection) { - for (size_t i = 0; i < toolPanels.size(); i++) { - if (toolPanels[i]->getParent() != NULL) { - ToolPanel* currentTP = toolPanels[i]; + for (auto toolPanel : toolPanels) { + if (toolPanel->getParent() != NULL) { + ToolPanel* currentTP = toolPanel; if (currentTP->getParent() == parent) { // Section in the same tab, we unfold it if it's not the one that has been clicked diff --git a/rtgui/whitebalance.cc b/rtgui/whitebalance.cc index 914c59956..f77ce74e7 100644 --- a/rtgui/whitebalance.cc +++ b/rtgui/whitebalance.cc @@ -17,16 +17,17 @@ * along with RawTherapee. If not, see . */ #include "whitebalance.h" + #include + #include "rtimage.h" #include "options.h" -#include "../rtengine/safegtk.h" #define MINTEMP 1500 //1200 #define MAXTEMP 60000 //12000 #define CENTERTEMP 4750 #define MINGREEN 0.02 -#define MAXGREEN 5.0 +#define MAXGREEN 10.0 #define MINEQUAL 0.8 #define MAXEQUAL 1.5 @@ -42,19 +43,19 @@ Glib::RefPtr WhiteBalance::wbCameraPB, WhiteBalance::wbAutoPB, Whit void WhiteBalance::init () { - wbPixbufs[WBT_CAMERA] = safe_create_from_file("wb-camera.png"); - wbPixbufs[WBT_AUTO] = safe_create_from_file("wb-auto.png"); - wbPixbufs[WBT_DAYLIGHT] = safe_create_from_file("wb-sun.png"); - wbPixbufs[WBT_CLOUDY] = safe_create_from_file("wb-cloudy.png"); - wbPixbufs[WBT_SHADE] = safe_create_from_file("wb-shade.png"); - wbPixbufs[WBT_WATER] = safe_create_from_file("wb-water.png"); -// wbPixbufs[WBT_WATER2] = safe_create_from_file("wb-water.png"); - wbPixbufs[WBT_TUNGSTEN] = safe_create_from_file("wb-tungsten.png"); - wbPixbufs[WBT_FLUORESCENT] = safe_create_from_file("wb-fluorescent.png"); - wbPixbufs[WBT_LAMP] = safe_create_from_file("wb-lamp.png"); - wbPixbufs[WBT_FLASH] = safe_create_from_file("wb-flash.png"); - wbPixbufs[WBT_LED] = safe_create_from_file("wb-led.png"); - wbPixbufs[WBT_CUSTOM] = safe_create_from_file("wb-custom.png"); + wbPixbufs[WBT_CAMERA] = RTImage::createFromFile ("wb-camera.png"); + wbPixbufs[WBT_AUTO] = RTImage::createFromFile ("wb-auto.png"); + wbPixbufs[WBT_DAYLIGHT] = RTImage::createFromFile ("wb-sun.png"); + wbPixbufs[WBT_CLOUDY] = RTImage::createFromFile ("wb-cloudy.png"); + wbPixbufs[WBT_SHADE] = RTImage::createFromFile ("wb-shade.png"); + wbPixbufs[WBT_WATER] = RTImage::createFromFile ("wb-water.png"); +// wbPixbufs[WBT_WATER2] = RTImage::createFromFile ("wb-water.png"); + wbPixbufs[WBT_TUNGSTEN] = RTImage::createFromFile ("wb-tungsten.png"); + wbPixbufs[WBT_FLUORESCENT] = RTImage::createFromFile ("wb-fluorescent.png"); + wbPixbufs[WBT_LAMP] = RTImage::createFromFile ("wb-lamp.png"); + wbPixbufs[WBT_FLASH] = RTImage::createFromFile ("wb-flash.png"); + wbPixbufs[WBT_LED] = RTImage::createFromFile ("wb-led.png"); + wbPixbufs[WBT_CUSTOM] = RTImage::createFromFile ("wb-custom.png"); } void WhiteBalance::cleanup () diff --git a/rtgui/xtransrawexposure.cc b/rtgui/xtransrawexposure.cc index ccf1e621b..84fae9032 100644 --- a/rtgui/xtransrawexposure.cc +++ b/rtgui/xtransrawexposure.cc @@ -18,7 +18,6 @@ */ #include "xtransrawexposure.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include using namespace rtengine; diff --git a/tools/buildRT b/tools/buildRT index ca7756358..66ed43894 100755 --- a/tools/buildRT +++ b/tools/buildRT @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Written by DrSlony -# buildRT version 4.3, 2015-03-11 -# Please report bugs or enhancements to http://code.google.com/p/rawtherapee/issues/list +# buildRT version 4.4, 2016-03-03 +# Please report bugs or enhancements to https://github.com/Beep6581/RawTherapee/issues # www.rawtherapee.com # www.londonlight.org @@ -34,7 +34,7 @@ while getopts "bc:fnp:s:t:uvh?-" opt; do case "${opt}" in b) patched="yes" movetoPatched="_patched" - printf "%s\n" "Buildonly flag detected, will not hg pull or update" ;; + printf "%s\n" "Buildonly flag detected, will not git pull or checkout" ;; c) dCacheNameSuffix="$OPTARG" dCacheNameSuffix=${dCacheNameSuffix//[^\.\-_a-zA-Z0-9]/}; forceCmake="yes" @@ -55,7 +55,7 @@ while getopts "bc:fnp:s:t:uvh?-" opt; do t) titleSuffix="${OPTARG//[^\.\-\:\ \+_a-zA-Z0-9]/}" forceCmake="yes" printf "%s\n" "Titlebar version suffix: ${titleSuffix}" ;; - u) gcVer="$(curl "http://rawtherapee.googlecode.com/hg/tools/buildRT" 2>/dev/null | grep "^#.*[vV]ersion.*")" || { echo "\"curl\" program not found, please install it first."; exit 1; } + u) gcVer="$(curl "https://raw.githubusercontent.com/Beep6581/RawTherapee/master/tools/buildRT" 2>/dev/null | grep "^#.*[vV]ersion.*")" || { echo "\"curl\" program not found, please install it first."; exit 1; } gcVer="${gcVer##*[[:alpha:]] }" gcVer="${gcVer%%,*}" latestVer="$(printf "%s\n" "$version" "$gcVer" | sort -rV | head -n 1)" @@ -63,7 +63,7 @@ while getopts "bc:fnp:s:t:uvh?-" opt; do printf "%s\n" "You are using the latest version of buildRT, $version" exit 0 else - printf "%s\n" "You are using version $version but version $gcVer is available on Google Code." "You can download the Google Code version from this URL:" " https://rawtherapee.googlecode.com/hg/tools/buildRT" "Replace it with this script, and remember to run \"chmod +x buildRT\"" + printf "%s\n" "You are using version $version but version $gcVer is available on GitHub." "You can download the GitHub version from this URL:" " https://raw.githubusercontent.com/Beep6581/RawTherapee/master/tools/buildRT" "Replace it with this script, and remember to run \"chmod +x buildRT\"" exit 0 fi ;; v) verbose=yes @@ -71,7 +71,7 @@ while getopts "bc:fnp:s:t:uvh?-" opt; do h|\?|-) printf "%s\n" "Usage:" "" " $0 [-b] [-c ] [-f] [-n] [-p <1-9>] [-s ] [-t \"\"] [-v]" "" printf "%s\n" \ " -b" \ - "Build-only mode. buildRT uses \"hg update -C default\" to update your source code repository to the newest revision, however doing so might destroy any uncommitted or unpushed changes you made or any patches you applied. With the -b flag the script will not update the source code, so that you can easily compile RawTherapee with whatever patches you manually applied. buildRT should automatically detect if you modified the source code, but you can use this flag to force build-only mode." "Generally when compiling patched RT versions you want to keep the cache and config folders separate, so consider using \"-b -c _testing\"" "" \ + "Build-only mode. buildRT uses \"git checkout master\" to update your source code repository to the newest revision, however doing so might destroy any uncommitted or unpushed changes you made or any patches you applied. With the -b flag the script will not update the source code, so that you can easily compile RawTherapee with whatever patches you manually applied. buildRT should automatically detect if you modified the source code, but you can use this flag to force build-only mode." "Generally when compiling patched RT versions you want to keep the cache and config folders separate, so consider using \"-b -c _testing\"" "" \ " -c " \ "Specify a suffix to the cache and config directory names. Only alphanumerics, periods, dashes and underscores are valid. The default value is \"4\", which will result in your build of RawTherapee storing the cache in \"${HOME}/.cache/RawTherapee4\" and config in \"${HOME}/.config/RawTherapee4\". For example, use \"-c _testing\" if you want to test older or patched versions of RawTherapee without potentially damaging your \"real\" cache and config files." "" \ " -f" \ @@ -85,7 +85,7 @@ while getopts "bc:fnp:s:t:uvh?-" opt; do " -t \"\"" \ "Suffix displayed next to the RawTherapee version in the window titlebar. It is recommended that you include the changeset of the newest public commit (the one you would see if you cloned the repository anew) so it is clear which commit you applied the patches to. E.g.:" "-t \": ee72ddbcfd4e + dustremoval-1.patch + mustafa ibrahim\"" "" \ " -u" \ - "Check for an update of buildRT on Google Code." "" \ + "Check for an update of buildRT on GitHub." "" \ " -v" \ "Make compilation verbose, so you see all compiler warnings." | fold -s exit 0 ;; @@ -181,14 +181,19 @@ fi printf "%s\n" "System: ${bits}-bit" "" #--- Check script dependencies -hash hg 2>/dev/null || { echo >&2 "Mercurial not found, install Mercurial first and then re-run this script."; exit 1; } +hash git 2>/dev/null || { echo >&2 "Git not found, install Git first and then re-run this script."; exit 1; } #--- Clone and/or pull if [[ ! -d "${repo}" ]]; then - printf "%s\n" "${repo} not found, cloning from GoogleCode..." - hg clone https://rawtherapee.googlecode.com/hg/ "${repo}" + printf "%s\n" "${repo} not found, cloning from GitHub..." + git clone https://github.com/Beep6581/RawTherapee.git "${repo}" cd "${repo}" || exit 1 - hg parents --template '\nRepository state:\n Branch: {branch}\n RawTherapee-{latesttag}.{latesttagdistance}\n Changeset: {rev}:{node|short}\n Latest tag: {latesttag}\n\n' + verLatesttag="$(git describe --tags --abbrev=0)" + verLatesttagdistance="$(git describe --tags | sed -e 's/.*-\([0-9]\+\)-.*/\1/')" + currentBranch="$(git branch | grep "*" | sed -e 's/.* \+//')" + rev="$(git rev-list --all --count)" + node="$(git rev-parse --short HEAD)" + printf "\nRepository state:\n Branch: ${currentBranch}\n RawTherapee-${verLatesttag}.${verLatesttagdistance}\n Changeset: ${rev}:${node}\n Latest tag: ${verLatesttag}\n\n" alert "Repository cloned succesfully. What would you like to do next?" printf "%b" "Repository cloned succesfully.\n" "Press 'q' to quit or any other key to continue... " read -r -n 1 @@ -198,21 +203,20 @@ fi cd "${repo}" || exit 1 #--- Update or decide what to do if user edited the source code (e.g. by applying a patch) -# "hg outgoing" takes time, so skip if buildonly if [[ -z $patched ]]; then - uncommitted="$(hg status | sed "s/^/\t/")" - unpushed="$(hg outgoing -q | sed "s/^/\t/" || echo "Could not check for unpushed changes (check your internet connection), but continuing anyway.")" + uncommitted="$(git status -s | sed "s/^/\t/")" + unpushed="$(git log origin..HEAD | sed "s/^/\t/" || echo "Could not check for unpushed changes (check your internet connection), but continuing anyway.")" fi if [[ -z $uncommitted && -z $unpushed && -z $patched ]]; then - hg pull || echo "Could not \"hg pull\" (check your internet connection), but continuing anyway." - hg update -C default + git pull || echo "Could not \"git pull\" (check your internet connection), but continuing anyway." + git checkout master echo elif [[ -z $patched ]]; then printf "%s\n" "" "Warning! There are uncommitted or unpushed changes in the repository!" "Uncommitted:" "$uncommitted" "Unpushed:" "$unpushed" "" "This means that you edited the source code (e.g. applied a patch). If the script proceeds to update the repository, those changes you made to the source code might be lost. Your choices are to force the update and possibly lose the changes, not to update and to compile RT as-is, or to abort the script." | fold -s read -r -p "[f]orce update, [c]ompile as-is, or [a]bort? " fca case $fca in - f|F) hg pull || echo "Could not \"hg pull\" (check your internet connection), but continuing anyway." - hg update -C default + f|F) git pull || echo "Could not \"git pull\" (check your internet connection), but continuing anyway." + git checkout master echo ;; c|C) printf "%s\n" "Retaining edited source code and compiling RT as-is." "" patched="yes" @@ -228,16 +232,23 @@ else movetoPatched="_patched" fi fi -hg parents --template 'Repository state:\n Branch: {branch}\n RawTherapee-{latesttag}.{latesttagdistance}\n Changeset: {rev}:{node|short}\n Latest tag: {latesttag}\n\n' + +cd "${repo}" || exit 1 +verLatesttag="$(git describe --tags --abbrev=0)" +verLatesttagdistance="$(git describe --tags | sed -e 's/.*-\([0-9]\+\)-.*/\1/')" +currentBranch="$(git branch | grep "*" | sed -e 's/.* \+//')" +rev="$(git rev-list --all --count)" +node="$(git rev-parse --short HEAD)" +printf "\nRepository state:\n Branch: ${currentBranch}\n RawTherapee-${verLatesttag}.${verLatesttagdistance}\n Changeset: ${rev}:${node}\n Latest tag: ${verLatesttag}\n\n" #--- Print the menu branches=() if [[ -z $patched ]]; then while read -r branch; do branches+=("$branch") - done < <(hg branches -aq | sort -f) + done < <(git branch -a | grep origin | sed -e 's/.*\///'| sort -uf) else - branches="$(hg branch)" + branches="$(git branch | grep "*" | sed -e 's/.* \+//')" fi # Make the menu list @@ -302,11 +313,10 @@ for choiceNumber in "${choiceNumbers[@]}"; do # if [[ -z $patched && $branch != default ]]; then if [[ -z $patched ]]; then printf "%s\n" "Updating to branch $branch" - hg update -C "$branch" || exit 1 + git checkout "$branch" || exit 1 fi echo printf "%-15b %b\n" "\E[1mWill compile\E[0m:" "" "\tChoice number:" "$choiceNumber" "\tBranch:" "$branch" "\tBuild type:" "$buildType" "\tTarget:" "$procTarget" "" - rev="$(hg parents --template {rev})" [[ -d "${HOME}/rt_${branch}_${buildType}${movetoPatched}" ]] && { printf "%s\n" "Found old build directory ${HOME}/rt_${branch}_${buildType}${movetoPatched}" "To proceed you must either delete it, or choose a suffix for the destination folder for this build." @@ -327,8 +337,6 @@ for choiceNumber in "${choiceNumbers[@]}"; do cd "${repo}" || exit 1 - verLatesttag="$(hg parents --template '{latesttag}')" - verLatesttagdistance="$(hg parents --template '{latesttagdistance}')" [[ -z $dCacheNameSuffix ]] && dCacheNameSuffix="${verLatesttag%%.*}" # need to rerun cmake if buildtype changed diff --git a/tools/coordinate_system.svg b/tools/coordinate_system.svg index 73227e6ac..2c3efc42b 100644 --- a/tools/coordinate_system.svg +++ b/tools/coordinate_system.svg @@ -13,10 +13,38 @@ height="1052.3622047" id="svg2" version="1.1" - inkscape:version="0.48.4 r9939" + inkscape:version="0.91 r13725" sodipodi:docname="coordinate_system.svg"> + + + + + + + + + @@ -94,6 +135,27 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1"> + + + imgAreaW + x="393.50574" + y="1104.9916">imgAreaW imgAreaH + x="-931.88525" + y="925.78394">imgAreaH - leftBorder + style="font-size:14px">cropHandler.getCrop()->getLeftBorder() upperBorder + style="font-size:14px">cropHandler.getCrop()->getUpperBorder() imgX imgY + style="fill:#ffffff;fill-opacity:1;stroke:none" /> @@ -377,19 +434,19 @@ style="font-size:14px">xpos ypos - imgX + sodipodi:role="line">imgAreaX imgY - + sodipodi:role="line">imgAreaY CropWindow (mainCropWindow) + x="10.089189" + y="-4.9809637">CropWindow (mainCropWindow) CropWindow + sodipodi:role="line">CropWindow (detail) + Scaled full image + + Editing canvas = Full image + padding, Scaled + + cropHandler.getCrop()->getPadding() + + + + CropWindow class, geometry explained + + + imgX + + + + + imgY + imgAreaW + imgAreaH + + + + + + + + + imgW + + + + + + + + + + width + + + + height diff --git a/tools/generateSourceTarball b/tools/generateSourceTarball index eb4688037..98173c00f 100755 --- a/tools/generateSourceTarball +++ b/tools/generateSourceTarball @@ -1,16 +1,17 @@ #!/usr/bin/env bash if [[ ! "$1" ]]; then - printf "%s\n" "Usage: $0 " "Example: $0 4.0.10" + printf "%s\n" "Usage: $0 " "Example: $0 4.2" exit fi -hg update "$1" +git checkout "$1" || exit 0 tools/generateReleaseInfo mkdir rawtherapee-"$1" mv ReleaseInfo.cmake rawtherapee-"$1" -hg archive -X ".hg*" -X "rtgui/config.h" -X "rtgui/version.h" -X "rtdata/rawtherapee.desktop" rawtherapee-"$1".tar -tar -rf rawtherapee-"$1".tar rawtherapee-"$1"/ReleaseInfo.cmake +#hg archive -X ".hg*" -X "rtgui/config.h" -X "rtgui/version.h" -X "rtdata/rawtherapee.desktop" rawtherapee-"$1".tar +git archive --format=tar "$1" > rawtherapee-"$1".tar +tar --append --file=rawtherapee-"$1".tar rawtherapee-"$1"/ReleaseInfo.cmake xz -z -9e rawtherapee-"$1".tar rm -r rawtherapee-"$1" -hg update +git checkout diff --git a/rtdata/osx/Info.plist.in b/tools/osx/Info.plist.in similarity index 97% rename from rtdata/osx/Info.plist.in rename to tools/osx/Info.plist.in index 491d2ee85..5b08d63a1 100644 --- a/rtdata/osx/Info.plist.in +++ b/tools/osx/Info.plist.in @@ -111,7 +111,7 @@ CFBundleExecutable rawtherapee CFBundleGetInfoString - @version@, Copyright © 2004-2013 Gábor Horváth + @version@, Copyright © 2004-2010 Gábor Horváth, 2010-2016 RT dev team CFBundleIconFile rawtherapee.icns CFBundleIdentifier diff --git a/rtdata/osx/PkgInfo b/tools/osx/PkgInfo similarity index 100% rename from rtdata/osx/PkgInfo rename to tools/osx/PkgInfo diff --git a/rtdata/osx/executable_loader.in b/tools/osx/executable_loader.in similarity index 89% rename from rtdata/osx/executable_loader.in rename to tools/osx/executable_loader.in index d56cd1dc1..5f1911edb 100644 --- a/rtdata/osx/executable_loader.in +++ b/tools/osx/executable_loader.in @@ -4,7 +4,8 @@ cwd="$(cd "$(dirname "$0")"; pwd)" app="${cwd%/Contents/*}" etc="${cwd}"/etc -# for different os x version (issue 1795) +# for different os x versions +# see https://github.com/Beep6581/RawTherapee/issues/1779 cups_dir=/tmp/RT4 install -d ${cups_dir} cp -f /usr/lib/libcups.2.dylib ${cups_dir} diff --git a/tools/osx/libiconv_1.14_rt.patch b/tools/osx/libiconv_1.14_rt.patch new file mode 100644 index 000000000..7a01b1373 --- /dev/null +++ b/tools/osx/libiconv_1.14_rt.patch @@ -0,0 +1,30 @@ +diff --git a/lib/iconv.c b/lib/iconv.c +index 3785296..24a0f07 100644 +--- a/lib/iconv.c ++++ b/lib/iconv.c +@@ -607,4 +607,25 @@ strong_alias (libiconv, iconv) + strong_alias (libiconv_close, iconv_close) + #endif + ++#undef iconv_open ++#undef iconv ++#undef iconv_close ++ ++LIBICONV_DLL_EXPORTED iconv_t iconv_open (const char* tocode, const char* fromcode) ++{ ++ return libiconv_open(tocode, fromcode); ++} ++ ++LIBICONV_DLL_EXPORTED size_t iconv (iconv_t icd, ++ ICONV_CONST char * * inbuf, size_t *inbytesleft, ++ char * * outbuf, size_t *outbytesleft) ++{ ++ return libiconv(icd, inbuf, inbytesleft, outbuf, outbytesleft); ++} ++ ++LIBICONV_DLL_EXPORTED int iconv_close (iconv_t icd) ++{ ++ return libiconv_close(icd); ++} ++ + #endif diff --git a/rtdata/osx/macosx_bundle.sh b/tools/osx/macosx_bundle.sh similarity index 59% rename from rtdata/osx/macosx_bundle.sh rename to tools/osx/macosx_bundle.sh index 670343b08..2803396ba 100644 --- a/rtdata/osx/macosx_bundle.sh +++ b/tools/osx/macosx_bundle.sh @@ -5,40 +5,47 @@ # these are very important variables. Must be set into rtdata/CMakeLists.txt! # - PROJECT_NAME # - PROJECT_SOURCE_DIR -# - PROJECT_VERSION (if without mercurial) +# - PROJECT_VERSION (if without git) # - CMAKE_BUILD_TYPE # - PROC_BIT_DEPTH # - GTK_PREFIX function message { - printf '\e[34m-- %s\e[m\n' "$*" + printf '\e[34m-- %s\e[m\n' "$*" } + function GetDependencies { - otool -L "$1" | awk 'NR >= 2 && $1 !~ /^(\/usr\/lib|\/System|@executable_path|@rpath)\// { print $1 }' + otool -L "$1" | awk 'NR >= 2 && $1 !~ /^(\/usr\/lib|\/System|@executable_path|@rpath)\// { print $1 }' } + function CheckLink { - GetDependencies "$1" | while read; do - local dest="${LIB}/$(basename "${REPLY}")" - test -f "${dest}" || { ditto --arch ${arch} "${REPLY}" "${dest}"; CheckLink "${dest}"; } - done + GetDependencies "$1" | while read; do + local dest="${LIB}/$(basename "${REPLY}")" + test -f "${dest}" || { ditto --arch ${arch} "${REPLY}" "${dest}"; CheckLink "${dest}"; } + done } # source check if test ! -d "${CMAKE_BUILD_TYPE}"; then - printf "\e[31m${PWD}/${CMAKE_BUILD_TYPE} directory is not found. Please execute 'make install' first.\e[m\n" - exit 1 + printf "\e[31m${PWD}/${CMAKE_BUILD_TYPE} directory is not found. Please execute 'make install' first.\e[m\n" + exit 1 fi # update project version -if test -x $(which hg) -a -d "${PROJECT_SOURCE_DIR}/.hg"; then - PROJECT_VERSION=$(hg -R "${PROJECT_SOURCE_DIR}" parents --template "{latesttag}.{latesttagdistance}") +if test -x "$(which git)" -a -d "${PROJECT_SOURCE_DIR}/.git"; then + # This is what the version ought to look like to be accurate in the git universe: + PROJECT_FULL_VERSION="$(git describe --tags --always | sed 's/-g.*//')_$(git symbolic-ref --short -q HEAD)" + # outputs: 4.2-677-g904467b_master + # but Apple requirements https://goo.gl/eWDQv6 state we should use this: + PROJECT_VERSION="$(git describe --tags --always | sed -e 's/-g.*//' -e 's/-/./')" + # outputs: 4.2.677 fi # if not specify CMAKE_OSX_DEPLOYMENT_TARGET when compiling, # 'MINIMUM_VERSION' will be used host OS X version. -MINIMUM_SYSTEM_VERSION=$(otool -l "${CMAKE_BUILD_TYPE}"/rawtherapee | grep -A2 'LC_VERSION_MIN_MACOSX' | awk '$1 ~ /version/ { printf $2 }') +MINIMUM_SYSTEM_VERSION="$(otool -l "${CMAKE_BUILD_TYPE}"/rawtherapee | grep -A2 'LC_VERSION_MIN_MACOSX' | awk '$1 ~ /version/ { printf $2 }')" if test ! -n "${MINIMUM_SYSTEM_VERSION}"; then - MINIMUM_SYSTEM_VERSION=$(sw_vers -productVersion | cut -d. -f-2) + MINIMUM_SYSTEM_VERSION="$(sw_vers -productVersion | cut -d. -f-2)" fi # check for pango-querymodules. Pango 1.38.0 and above do not include it. @@ -54,8 +61,8 @@ else fi case ${PROC_BIT_DEPTH} in - 64) arch=x86_64;; - 32) arch=i386;; + 64) arch=x86_64;; + 32) arch=i386;; esac cat <<__EOS__ @@ -82,9 +89,9 @@ rm -rf "${APP}" ${PROJECT_NAME}_*.dmg message "Creating bundle container" install -d "${RESOURCES}" \ - "${MACOS}" \ - "${LIB}" \ - "${ETC}" +"${MACOS}" \ +"${LIB}" \ +"${ETC}" message "Copying release files" ditto "${CMAKE_BUILD_TYPE}" "${MACOS}" @@ -93,9 +100,9 @@ message "Copying dependencies from ${GTK_PREFIX}" CheckLink "${EXECUTABLE}" message "Copying library modules from ${GTK_PREFIX}" -ditto --arch ${arch} {"${GTK_PREFIX}"/lib,"${LIB}"}/gdk-pixbuf-2.0 -ditto --arch ${arch} {"${GTK_PREFIX}"/lib,"${LIB}"}/gtk-2.0 -ditto --arch ${arch} {"${GTK_PREFIX}"/lib,"${LIB}"}/pango +ditto --arch "${arch}" {"${GTK_PREFIX}"/lib,"${LIB}"}/gdk-pixbuf-2.0 +ditto --arch "${arch}" {"${GTK_PREFIX}"/lib,"${LIB}"}/gtk-2.0 +ditto --arch "${arch}" {"${GTK_PREFIX}"/lib,"${LIB}"}/pango message "Removing static libraries and cache files" find -E "${LIB}" -type f -regex '.*\.(a|la|cache)$' | while read; do rm "${REPLY}"; done @@ -106,7 +113,7 @@ cp "${GTK_PREFIX}"/etc/gtk-2.0/im-multipress.conf "${ETC}"/gtk-2.0 "${GTK_PREFIX}"/bin/gdk-pixbuf-query-loaders "${LIB}"/gdk-pixbuf-2.0/*/loaders/*.so > "${ETC}"/gtk-2.0/gdk-pixbuf.loaders "${GTK_PREFIX}"/bin/gtk-query-immodules-2.0 "${LIB}"/gtk-2.0/*/immodules/*.so > "${ETC}"/gtk-2.0/gtk.immodules sed -i "" -e "s|${PWD}|/tmp|" "${ETC}"/gtk-2.0/gdk-pixbuf.loaders \ - "${ETC}"/gtk-2.0/gtk.immodules +"${ETC}"/gtk-2.0/gtk.immodules if [[ "$ExistPangoQuerymodules" = "true" ]]; then "${GTK_PREFIX}"/bin/pango-querymodules "${LIB}"/pango/*/modules/*.so > "${ETC}"/pango/pango.modules sed -i "" -e "s|${PWD}|/tmp|" "${ETC}"/pango/pango.modules @@ -122,23 +129,23 @@ install -d "${MACOS}"/share/themes/Raleigh/gtk-2.0 (cd "${MACOS}"/share/themes/Raleigh/gtk-2.0 && ln -s ../../Clearlooks/gtk-2.0/gtkrc) # fontconfig files (X11 backend only) if otool -L "${EXECUTABLE}" | grep -sq 'libgtk-x11-2.0'; then - message "Installing fontconfig files (Your library is X11 backend. 'FONTCONFIG_PATH' will be set by executable loader.)" - cp -RL "${GTK_PREFIX}"/etc/fonts "${ETC}" + message "Installing fontconfig files (Your library is X11 backend. 'FONTCONFIG_PATH' will be set by executable loader.)" + cp -RL "${GTK_PREFIX}"/etc/fonts "${ETC}" fi # install names find -E "${MACOS}" -type f -regex '.*/(rawtherapee|.*\.(dylib|so))' | while read x; do - message "Modifying install names: ${x}" - { - # id + message "Modifying install names: ${x}" + { + # id case ${x} in *.dylib) echo " install_name_tool -id '@rpath/$(basename "${x}")' '${x}'";; esac # names GetDependencies "${x}" | while read y; do - echo " install_name_tool -change '${y}' '@rpath/$(basename "${y}")' '${x}'" + echo " install_name_tool -change '${y}' '@rpath/$(basename "${y}")' '${x}'" done - } | bash -v +} | bash -v done message "Registering @loader_path into the executable" @@ -147,7 +154,7 @@ echo " install_name_tool -add_rpath @loader_path/lib '${EXECUTABLE}'" | bash - message "Installing required application bundle files" -PROJECT_SOURCE_DATA_DIR="${PROJECT_SOURCE_DIR}"/rtdata/osx +PROJECT_SOURCE_DATA_DIR="${PROJECT_SOURCE_DIR}"/tools/osx # executable loader # note: executable is renamed to 'rawtherapee-bin'. mv "${MACOS}"/rawtherapee{,-bin} @@ -157,39 +164,39 @@ cp "${PROJECT_SOURCE_DATA_DIR}"/{rawtherapee,profile}.icns "${RESOURCES}" cp "${PROJECT_SOURCE_DATA_DIR}"/PkgInfo "${CONTENTS}" install -m 0644 "${PROJECT_SOURCE_DATA_DIR}"/Info.plist.in "${CONTENTS}"/Info.plist sed -i "" -e "s|@version@|${PROJECT_VERSION}| - s|@shortVersion@|$(echo ${PROJECT_VERSION} | cut -d. -f-3)| - s|@arch@|${arch}|" \ - "${CONTENTS}"/Info.plist +s|@shortVersion@|${PROJECT_VERSION}| +s|@arch@|${arch}|" \ +"${CONTENTS}"/Info.plist plutil -convert binary1 "${CONTENTS}"/Info.plist function CreateDmg { - local srcdir=$(mktemp -dt $$) - - message "Preparing disk image sources at ${srcdir}" - mv "${APP}" ${srcdir} - cp AboutThisBuild.txt ${srcdir} - ln -s /Applications ${srcdir} - - # web bookmarks - function CreateWebloc { - defaults write ${srcdir}/"$1" URL "$2" - mv ${srcdir}/"$1".{plist,webloc} - } - CreateWebloc 'RawTherapee Blog' 'http://www.rawtherapee.com' - CreateWebloc 'Online Manual' 'https://docs.google.com/document/d/1DHLb_6xNQsEInxiuU8pz1-sWNinnj09bpBUA4_Vl8w8/edit' - - # disk image name - dmg_name="${PROJECT_NAME// /_}_OSX_${MINIMUM_SYSTEM_VERSION}_${PROC_BIT_DEPTH}_${PROJECT_VERSION}" - if ! echo ${CMAKE_BUILD_TYPE} | grep -sqi "release"; then - dmg_name="${dmg_name}_$(echo ${CMAKE_BUILD_TYPE} | tr '[:upper:]' '[:lower:]')" - fi - - message "Creating disk image" - hdiutil create -format UDBZ -srcdir ${srcdir} -volname "${PROJECT_NAME}_${PROJECT_VERSION}" "${dmg_name}".dmg - - message "Removing disk image caches" - rm -rf ${srcdir} + local srcdir="$(mktemp -dt $$)" + + message "Preparing disk image sources at ${srcdir}" + mv "${APP}" "${srcdir}" + cp AboutThisBuild.txt "${srcdir}" + ln -s /Applications "${srcdir}" + + # web bookmarks + function CreateWebloc { + defaults write "${srcdir}/$1" URL "$2" + mv "${srcdir}/$1".{plist,webloc} + } + CreateWebloc 'RawTherapee Blog' 'http://www.rawtherapee.com' + CreateWebloc 'Online Manual' 'http://rawpedia.rawtherapee.com/' + + # disk image name + dmg_name="${PROJECT_NAME// /_}_OSX_${MINIMUM_SYSTEM_VERSION}_${PROC_BIT_DEPTH}_${PROJECT_FULL_VERSION}" + if ! echo "${CMAKE_BUILD_TYPE}" | grep -sqi "release"; then + dmg_name="${dmg_name}_$(echo ${CMAKE_BUILD_TYPE} | tr '[:upper:]' '[:lower:]')" + fi + + message "Creating disk image" + hdiutil create -format UDBZ -srcdir "${srcdir}" -volname "${PROJECT_NAME}_${PROJECT_FULL_VERSION}" "${dmg_name}".dmg + + message "Removing disk image caches" + rm -rf "${srcdir}" } CreateDmg diff --git a/rtdata/osx/profile.icns b/tools/osx/profile.icns similarity index 100% rename from rtdata/osx/profile.icns rename to tools/osx/profile.icns diff --git a/rtdata/osx/rawtherapee.icns b/tools/osx/rawtherapee.icns similarity index 100% rename from rtdata/osx/rawtherapee.icns rename to tools/osx/rawtherapee.icns diff --git a/rtdata/win/InnoSetup/WindowsInnoSetup.iss.in b/tools/win/InnoSetup/WindowsInnoSetup.iss.in similarity index 98% rename from rtdata/win/InnoSetup/WindowsInnoSetup.iss.in rename to tools/win/InnoSetup/WindowsInnoSetup.iss.in index 42f2a0feb..5c4a2a239 100644 --- a/rtdata/win/InnoSetup/WindowsInnoSetup.iss.in +++ b/tools/win/InnoSetup/WindowsInnoSetup.iss.in @@ -55,7 +55,7 @@ LicenseFile={#MyBuildBasePath}\LICENSE.txt OutputDir={#MyBuildBasePath}\..\ OutputBaseFilename={#MyAppName}_{#MySystemName}_{#MyBitDepth}_{#MyAppFullVersion} SetupIconFile={#MySourceBasePath}\rtgui\RT.ico -WizardImageFile={#MySourceBasePath}\rtdata\win\InnoSetup\installerStrip.bmp +WizardImageFile={#MySourceBasePath}\tools\win\InnoSetup\installerStrip.bmp WizardImageBackColor=$2A2A2A Compression=lzma SolidCompression=yes @@ -117,7 +117,7 @@ Source: "{#MyBuildBasePath}\options"; DestDir: "{app}"; Flags: ignoreversion Source: "{#MyBuildBasePath}\*.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "{#MyBuildBasePath}\gspawn-win{#MyBitDepth}-helper.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "{#MyBuildBasePath}\gspawn-win{#MyBitDepth}-helper-console.exe"; DestDir: "{app}"; Flags: ignoreversion - +;Source: "{#MyBuildBasePath}\gdb.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "{#MyBuildBasePath}\fonts\DroidSansMonoSlashed.ttf"; DestDir: "{fonts}"; FontInstall: "Droid Sans Mono Slashed"; Flags: onlyifdoesntexist uninsneveruninstall ; NOTE: Don't use "Flags: ignoreversion" on any shared system files diff --git a/rtdata/win/InnoSetup/installerStrip.bmp b/tools/win/InnoSetup/installerStrip.bmp similarity index 100% rename from rtdata/win/InnoSetup/installerStrip.bmp rename to tools/win/InnoSetup/installerStrip.bmp diff --git a/rtdata/win/InnoSetup/installerStrip.svg b/tools/win/InnoSetup/installerStrip.svg similarity index 100% rename from rtdata/win/InnoSetup/installerStrip.svg rename to tools/win/InnoSetup/installerStrip.svg diff --git a/rtdata/win/readme.txt b/tools/win/readme.txt similarity index 100% rename from rtdata/win/readme.txt rename to tools/win/readme.txt