diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index aed4cce33..84f05bba5 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,11 +1,11 @@ -RAWTHERAPEE 5 DEVELOPMENT RELEASE NOTES ---------------------------------------- +RAWTHERAPEE 5.1-dev RELEASE NOTES +--------------------------------- +This is a development version of RawTherapee. We update the code almost daily. Every few months, once enough changes have accumulated and the code is stabilized, we make a new official release. Every code change between these releases is known as a "development" version, and this is one of them. + RawTherapee provides you with a selection of powerful tools with which you can practice the art of developing raw photos. Be sure to read RawPedia to understand how each tool works so that you may make the most of it. http://rawpedia.rawtherapee.com/ A great place to start is the "Getting Started" article. Click on "Main page" in the top-left corner when you have finished reading that article to see all other articles. -This is a development version of RawTherapee. We update the code almost daily. Every few months, once enough changes have accumulated and the code is stabilized, we make a new official release. Every code change between these releases is known as a "development" version, and this is one of them. - While we only commit tested and relatively stable code and so the development versions should be fairly stable, you should be aware that: - Development versions only had limited testing, so there may be bugs unknown to us. - You should report these bugs so that they get fixed for the next stable release. See @@ -15,7 +15,7 @@ While we only commit tested and relatively stable code and so the development ve News Relevant to Photographers ------------------------------ -- RawTherapee 5 supports most raw formats, including some unusual ones like those from cameras using Foveon and X-Trans sensors. If you're wondering whether it supports your camera's raw format, first download RawTherapee 5 and try for yourself. If a raw format is not supported it will either not open, or the preview in the Editor tab will appear black, white, or have a strong color cast - usually magenta. In that case, read the "Adding Support for New Raw Formats" RawPedia article. +- RawTherapee supports most raw formats, including some unusual ones like those from cameras using Foveon and X-Trans sensors. If you're wondering whether it supports your camera's raw format, first download RawTherapee and try for yourself. If a raw format is not supported it will either not open, or the preview in the Editor tab will appear black, white, or have a strong color cast - usually magenta. In that case, read the "Adding Support for New Raw Formats" RawPedia article. In order to use RawTherapee efficiently you should know that: - You can scroll all panels using the mouse scroll-wheel. @@ -24,27 +24,27 @@ In order to use RawTherapee efficiently you should know that: - All curves support the Shift and Ctrl keys while dragging a point. Shift+drag makes the point snap to meaningful axes (top, bottom, diagonal, other), while Ctrl+drag makes your mouse movement super-fine for precise point positioning. - There are many keyboard shortcuts which make working with RawTherapee much faster and give you greater control. Make sure you familiarize yourself with them on RawPedia's "Keyboard Shortcuts" page! -New features since 5.0-r1: -- +New features since 5.1: +- This section will be completed when 5.2 is released. News Relevant to Package Maintainers ------------------------------------ -- To get the latest development version, use the "dev" branch. -- All development now uses GTK3, requiring version >=3.16. There are known bugs using GTK+ versions 3.20-3.22 where scrollbars may appear stuck (issue #3545) and where the Retinex tool's "Gain and Offset" panel may appear under the "Transmission" panel (issue #3525) until the user hovers the mouse cursor over a curve button. For this reason we recommend using GTK+ 3.16-3.18 if possible. -- GTK2 is no longer supported. Use branch "gtk2" if you want to compile a GTK2 version, but remember that there will be no improvements to it after 5.0-r1. +- No significant changes since 5.1. +- Requires GTK+ version >=3.16. +- GTK2 is not supported. 5.0-r1 was the last GTK2 release. - Branches "master" and "gtk3" are dead, do not use them. - RawTherapee 5 requires GCC-4.9 or higher, or Clang. - Do not use -ffast-math, it will not make RawTherapee faster but will introduce artifacts. -- Use -o3, it will make RawTherapee faster with no known side-effects. -- For stable builds (RT5) use -DCACHE_NAME_SUFFIX="" -- For development builds use -DCACHE_NAME_SUFFIX="5-dev" -- Windows builders should compile on a drive letter which users are most unlikely to have, such as Y:, due to the "There is no disk in the drive" error (issue #3544). +- Use -O3, it will make RawTherapee faster with no known side-effects. +- For stable releases use -DCACHE_NAME_SUFFIX="" +- For development builds and release-candidates use -DCACHE_NAME_SUFFIX="5-dev" News Relevant to Developers --------------------------- -- Use C++11 +- Announce and discuss your plans in GitHub before starting work. +- Keep branches small so that completed and working features can be merged into the "dev" branch often, and so that they can be abandoned if they head in the wrong direction. +- Use C++11. - Code must be run through astyle. -- Commits automatically trigger a compilation using Travis CI. DOCUMENTATION ------------- @@ -59,8 +59,8 @@ http://rawpedia.rawtherapee.com/How_to_write_useful_bug_reports LIVE CHAT WITH USERS AND DEVELOPERS -------------------------------------- Network: freenode - Server: chat.freenode.net - Channel #rawtherapee + Server: chat.freenode.net + Channel: #rawtherapee You can use freenode webchat to communicate without installing anything: http://webchat.freenode.net/?randomnick=1&channels=rawtherapee&prompt=1 diff --git a/doc/manpage/rawtherapee.1 b/doc/manpage/rawtherapee.1 index bbd2a4f44..5e3024a99 100644 --- a/doc/manpage/rawtherapee.1 +++ b/doc/manpage/rawtherapee.1 @@ -1,4 +1,4 @@ -.TH RAWTHERAPEE 1 "July 05, 2016" +.TH RAWTHERAPEE 1 "May 10, 2017" .SH NAME RawTherapee - An advanced, cross-platform program for developing raw photos. .SH DESCRIPTION @@ -14,11 +14,14 @@ RawTherapee - An advanced, cross-platform program for developing raw photos. The pipe symbol | indicates a choice of one or the other. The dash symbol - denotes a range of possible values from one to the other. .SH SYNOPSIS + RawTherapee GUI rawtherapee Start File Browser inside folder. rawtherapee Start Image Editor with file. - rawtherapee -c | Convert files in batch with default parameters. - rawtherapee -c | Convert files in batch with your own settings. - rawtherapee [-o |-O ] [-s|-S] [-p [-p ...] ] [-d] [ -j[1-100] [-js<1-3>] | [-b<8|16>] [-t[z] | [-n]] ] [-Y] -c + + RawTherapee CLI + rawtherapee-cli -c | Convert files in batch using default parameters. + rawtherapee-cli -c | Convert files in batch using your own settings. + rawtherapee-cli [-o |-O ] [-q] [-a] [-s|-S] [-p [-p ...] ] [-d] [ -j[1-100] [-js<1-3>] | [-b<8|16>] [-t[z] | [-n]] ] [-Y] -c .SH OPTIONS -c Specify one or more input files. -c must be the last option. @@ -26,6 +29,9 @@ RawTherapee - An advanced, cross-platform program for developing raw photos. Saves output file alongside input file if -o is not specified. -O | Set output file or folder and copy pp3 file into it. Saves output file alongside input file if -O is not specified. + -q Quick-start mode. Does not load cached files to speedup start time. + -a Process all supported image file types when specifying a folder, even those + not currently selected in Preferences > File Browser > Parsed Extensions. -s Use the existing sidecar file to build the processing parameters, e.g. for photo.raw there should be a photo.raw.pp3 file in the same folder. If the sidecar file does not exist, neutral values will be used. diff --git a/rtdata/dcpprofiles/LG Mobile LG-H815.dcp b/rtdata/dcpprofiles/LG Mobile LG-H815.dcp new file mode 100644 index 000000000..d8a4539db Binary files /dev/null and b/rtdata/dcpprofiles/LG Mobile LG-H815.dcp differ diff --git a/rtdata/dcpprofiles/NIKON D5600.dcp b/rtdata/dcpprofiles/NIKON D5600.dcp new file mode 100644 index 000000000..00367d43d Binary files /dev/null and b/rtdata/dcpprofiles/NIKON D5600.dcp differ diff --git a/rtdata/images/rt_splash_5.svg b/rtdata/images/rt_splash.svg similarity index 65% rename from rtdata/images/rt_splash_5.svg rename to rtdata/images/rt_splash.svg index 8f556f37e..d860798bd 100644 --- a/rtdata/images/rt_splash_5.svg +++ b/rtdata/images/rt_splash.svg @@ -15,328 +15,15 @@ id="svg2" version="1.1" inkscape:version="0.91 r13725" - sodipodi:docname="rt_splash_5.svg" + sodipodi:docname="rt_splash.svg" style="enable-background:new" - inkscape:export-filename="/tmp/rt_splash_5.png" + inkscape:export-filename="/tmp/rt_splash_51-dev.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90"> RawTherapee Splash Screen - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 + .1 + + Development + Alt + s HISTORY_SNAPSHOT;Schnappschuss @@ -1747,6 +1749,7 @@ TP_RAW_HD_TOOLTIP;Je niedriger der Wert, umso empfindlicher reagiert\ndie “Hot TP_RAW_HPHD;HPHD TP_RAW_IGV;IGV TP_RAW_IMAGENUM;Unterbild +TP_RAW_IMAGENUM_TOOLTIP;Einige RAW-Formate enthalten mehrere Unterbilder (Pentax Pixel Shift,\nPentax 3-in-1 HDR, Canon Dual Pixel).\n\n> Auswahl des zu verwendenden Unterbildes (nicht bei Pixel Shift).\n\n> Legt das Unterbild für die Bewegungsbereiche bei Pixel Shift fest. TP_RAW_LABEL;Farbinterpolation TP_RAW_LMMSE;LMMSE TP_RAW_LMMSEITERATIONS;LMMSE-Verbesserungsstufen @@ -2182,9 +2185,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_475;PS - Equalize channel -!TP_RAW_IMAGENUM_TOOLTIP;Some raw files consist of several sub-images (Pentax Pixel Shift, Pentax 3-in-1 HDR, Canon Dual Pixel).\n\nWhen using any demosaicing method other than Pixel Shift, this selects which sub-image is used.\n\nWhen using the Pixel Shift demosaicing method on a Pixel Shift raw, all sub-images are used, and this selects which sub-image should be used for moving parts. diff --git a/rtdata/profiles/Default ISO High.pp3 b/rtdata/profiles/Default ISO High.pp3 index 691141e2c..c15085093 100644 --- a/rtdata/profiles/Default ISO High.pp3 +++ b/rtdata/profiles/Default ISO High.pp3 @@ -1,19 +1,18 @@ [Version] -AppVersion=4.2.84 -Version=322 +AppVersion=5.1 +Version=326 [Exposure] Auto=true Clip=0.02 Saturation=0 -CurveMode=Standard -CurveMode2=Standard +CurveMode=Perceptual +CurveMode2=Perceptual Curve=0; Curve2=0; -[HLRecovery] -Enabled=true -Method=Blend +[Retinex] +Enabled=false [Channel Mixer] Red=100;0;0; @@ -42,19 +41,6 @@ ClCurve=0; [Sharpening] Enabled=false -Method=usm -Radius=0.7 -Amount=250 -Threshold=20;80;2000;1200; -OnlyEdges=false -EdgedetectionRadius=1.9 -EdgeTolerance=1800 -HalocontrolEnabled=false -HalocontrolAmount=85 -DeconvRadius=0.75 -DeconvAmount=75 -DeconvDamping=20 -DeconvIterations=30 [Vibrance] Enabled=false @@ -68,6 +54,7 @@ Enabled=false [White Balance] Setting=Camera Equal=1 +TemperatureBias=0 [Color appearance] Enabled=false @@ -82,19 +69,19 @@ Enabled=false Enabled=true Enhance=false Median=true -Luma=0 -Ldetail=50 -Chroma=30 +Auto=false +Luma=40 +Ldetail=80 Method=Lab +LMethod=SLI +CMethod=MAN +C2Method=AUTO SMethod=shal -MedMethod=33 +MedMethod=soft RGBMethod=soft -MethodMed=Lab -Redchro=0 -Bluechro=0 +MethodMed=Lpab Gamma=1.7 -Passes=3 -LCurve=1;0.05;0.5;0.35;0.35;0.55;0.04;0.35;0.35; +Passes=1 [EPD] Enabled=false @@ -108,6 +95,29 @@ Enabled=false [PCVignette] Enabled=false +[Color Management] +InputProfile=(cameraICC) +ToneCurve=false +ApplyLookTable=false +ApplyBaselineExposureOffset=true +ApplyHueSatMap=true +BlendCMSMatrix=false +DCPIlluminant=0 +WorkingProfile=ProPhoto +OutputProfile=RT_sRGB +OutputProfileIntent=Relative +OutputBPC=true +Gammafree=default +Freegamma=false +GammaValue=2.2200000000000002 +GammaSlope=4.5 + +[Wavelet] +Enabled=false + +[Directional Pyramid Equalizer] +Enabled=false + [HSV Equalizer] HCurve=0; SCurve=0; @@ -116,9 +126,6 @@ VCurve=0; [Film Simulation] Enabled=false -[Wavelet] -Enabled=false - [RGB Curves] LumaMode=false rCurve=0; @@ -134,12 +141,15 @@ DarkFrameAuto=false FlatFieldFile=/szeva FlatFieldAutoSelect=false CA=true -HotPixelFilter=true +HotPixelFilter=false DeadPixelFilter=false HotDeadPixelThresh=100 +PreExposure=1 +PrePreserv=0 [RAW Bayer] Method=lmmse +ImageNum=1 CcSteps=0 PreBlack0=0 PreBlack1=0 diff --git a/rtdata/profiles/Default ISO Medium.pp3 b/rtdata/profiles/Default ISO Medium.pp3 index 889911a85..0bd94097f 100644 --- a/rtdata/profiles/Default ISO Medium.pp3 +++ b/rtdata/profiles/Default ISO Medium.pp3 @@ -1,19 +1,18 @@ [Version] -AppVersion=4.2.84 -Version=322 +AppVersion=5.1 +Version=326 [Exposure] Auto=true Clip=0.02 Saturation=0 -CurveMode=Standard -CurveMode2=Standard +CurveMode=Perceptual +CurveMode2=Perceptual Curve=0; Curve2=0; -[HLRecovery] -Enabled=true -Method=Blend +[Retinex] +Enabled=false [Channel Mixer] Red=100;0;0; @@ -43,8 +42,8 @@ ClCurve=0; [Sharpening] Enabled=true Method=usm -Radius=0.7 -Amount=250 +Radius=0.75 +Amount=200 Threshold=20;80;2000;1200; OnlyEdges=false EdgedetectionRadius=1.9 @@ -68,6 +67,7 @@ Enabled=false [White Balance] Setting=Camera Equal=1 +TemperatureBias=0 [Color appearance] Enabled=false @@ -81,20 +81,20 @@ Enabled=false [Directional Pyramid Denoising] Enabled=true Enhance=false -Median=true +Median=false +Auto=false Luma=0 -Ldetail=85 -Chroma=15 +Ldetail=80 Method=Lab +LMethod=SLI +CMethod=MAN +C2Method=AUTO SMethod=shal -MedMethod=33 +MedMethod=soft RGBMethod=soft -MethodMed=Lab -Redchro=0 -Bluechro=0 +MethodMed=Lonly Gamma=1.7 Passes=1 -LCurve=1;0.05;0.15;0.35;0.35;0.55;0.04;0.35;0.35; [EPD] Enabled=false @@ -108,6 +108,29 @@ Enabled=false [PCVignette] Enabled=false +[Color Management] +InputProfile=(cameraICC) +ToneCurve=false +ApplyLookTable=false +ApplyBaselineExposureOffset=true +ApplyHueSatMap=true +BlendCMSMatrix=false +DCPIlluminant=0 +WorkingProfile=ProPhoto +OutputProfile=RT_sRGB +OutputProfileIntent=Relative +OutputBPC=true +Gammafree=default +Freegamma=false +GammaValue=2.2200000000000002 +GammaSlope=4.5 + +[Wavelet] +Enabled=false + +[Directional Pyramid Equalizer] +Enabled=false + [HSV Equalizer] HCurve=0; SCurve=0; @@ -116,9 +139,6 @@ VCurve=0; [Film Simulation] Enabled=false -[Wavelet] -Enabled=false - [RGB Curves] LumaMode=false rCurve=0; @@ -134,12 +154,15 @@ DarkFrameAuto=false FlatFieldFile=/szeva FlatFieldAutoSelect=false CA=true -HotPixelFilter=true +HotPixelFilter=false DeadPixelFilter=false HotDeadPixelThresh=100 +PreExposure=1 +PrePreserv=0 [RAW Bayer] Method=amaze +ImageNum=1 CcSteps=0 PreBlack0=0 PreBlack1=0 diff --git a/rtdata/profiles/Default.pp3 b/rtdata/profiles/Default.pp3 index c4ea48b60..227ee2e6b 100644 --- a/rtdata/profiles/Default.pp3 +++ b/rtdata/profiles/Default.pp3 @@ -1,19 +1,18 @@ [Version] -AppVersion=4.2.84 -Version=322 +AppVersion=5.1 +Version=326 [Exposure] Auto=true Clip=0.02 Saturation=0 -CurveMode=Standard -CurveMode2=Standard +CurveMode=Perceptual +CurveMode2=Perceptual Curve=0; Curve2=0; -[HLRecovery] -Enabled=true -Method=Blend +[Retinex] +Enabled=false [Channel Mixer] Red=100;0;0; @@ -23,7 +22,6 @@ Blue=0;0;100; [Black & White] Enabled=false - [Luminance Curve] Brightness=0 Contrast=0 @@ -45,7 +43,7 @@ ClCurve=0; Enabled=true Method=usm Radius=0.5 -Amount=250 +Amount=200 Threshold=20;80;2000;1200; OnlyEdges=false EdgedetectionRadius=1.9 @@ -69,6 +67,7 @@ Enabled=false [White Balance] Setting=Camera Equal=1 +TemperatureBias=0 [Color appearance] Enabled=false @@ -81,7 +80,6 @@ Enabled=false [Directional Pyramid Denoising] Enabled=false -Method=Lab [EPD] Enabled=false @@ -95,6 +93,29 @@ Enabled=false [PCVignette] Enabled=false +[Color Management] +InputProfile=(cameraICC) +ToneCurve=false +ApplyLookTable=false +ApplyBaselineExposureOffset=true +ApplyHueSatMap=true +BlendCMSMatrix=false +DCPIlluminant=0 +WorkingProfile=ProPhoto +OutputProfile=RT_sRGB +OutputProfileIntent=Relative +OutputBPC=true +Gammafree=default +Freegamma=false +GammaValue=2.2200000000000002 +GammaSlope=4.5 + +[Wavelet] +Enabled=false + +[Directional Pyramid Equalizer] +Enabled=false + [HSV Equalizer] HCurve=0; SCurve=0; @@ -103,10 +124,6 @@ VCurve=0; [Film Simulation] Enabled=false -[Wavelet] -Enabled=false - - [RGB Curves] LumaMode=false rCurve=0; @@ -122,12 +139,15 @@ DarkFrameAuto=false FlatFieldFile=/szeva FlatFieldAutoSelect=false CA=true -HotPixelFilter=true +HotPixelFilter=false DeadPixelFilter=false HotDeadPixelThresh=100 +PreExposure=1 +PrePreserv=0 [RAW Bayer] Method=amaze +ImageNum=1 CcSteps=0 PreBlack0=0 PreBlack1=0 diff --git a/rtdata/profiles/Pentax Pixel Shift/PS ISO High.pp3 b/rtdata/profiles/Pentax Pixel Shift/PS ISO High.pp3 new file mode 100644 index 000000000..2c9927e93 --- /dev/null +++ b/rtdata/profiles/Pentax Pixel Shift/PS ISO High.pp3 @@ -0,0 +1,28 @@ +[Version] +AppVersion=5.0-r1-gtk3-503-g9e1fc78 +Version=326 + +[RAW] +CA=true + +[RAW Bayer] +Method=pixelshift +PixelShiftMotion=0 +PixelShiftMotionCorrection=5 +PixelShiftMotionCorrectionMethod=2 +pixelShiftStddevFactorGreen=5 +pixelShiftStddevFactorRed=5 +pixelShiftStddevFactorBlue=5 +PixelShiftEperIso=2.8999999999999999 +PixelShiftNreadIso=0 +PixelShiftPrnu=1 +PixelShiftSigma=10 +PixelShiftSum=3 +PixelShiftRedBlueWeight=0.69999999999999996 +pixelShiftAutomatic=true +pixelShiftHoleFill=true +pixelShiftGreen=true +pixelShiftBlur=true +pixelShiftSmoothFactor=0.69999999999999996 +pixelShiftLmmse=true +pixelShiftNonGreenCross=false diff --git a/rtdata/profiles/Pentax Pixel Shift/PS ISO Low.pp3 b/rtdata/profiles/Pentax Pixel Shift/PS ISO Low.pp3 new file mode 100644 index 000000000..cbf2e6c74 --- /dev/null +++ b/rtdata/profiles/Pentax Pixel Shift/PS ISO Low.pp3 @@ -0,0 +1,42 @@ +[Version] +AppVersion=5.0-r1-gtk3-503-g9e1fc78 +Version=326 + +[Sharpening] +Enabled=true +Method=rld +DeconvRadius=0.75 +DeconvAmount=75 +DeconvDamping=0 +DeconvIterations=30 + +[SharpenMicro] +Enabled=true +Matrix=false +Strength=20 +Uniformity=50 + +[RAW] +CA=true + +[RAW Bayer] +Method=pixelshift +PixelShiftMotion=0 +PixelShiftMotionCorrection=5 +PixelShiftMotionCorrectionMethod=1 +pixelShiftStddevFactorGreen=5 +pixelShiftStddevFactorRed=5 +pixelShiftStddevFactorBlue=5 +PixelShiftEperIso=0 +PixelShiftNreadIso=0 +PixelShiftPrnu=1 +PixelShiftSigma=1 +PixelShiftSum=3 +PixelShiftRedBlueWeight=0.69999999999999996 +pixelShiftAutomatic=true +pixelShiftHoleFill=true +pixelShiftGreen=true +pixelShiftBlur=true +pixelShiftSmoothFactor=0.69999999999999996 +pixelShiftLmmse=false +pixelShiftNonGreenCross=true diff --git a/rtdata/profiles/Pentax Pixel Shift/PS ISO Medium.pp3 b/rtdata/profiles/Pentax Pixel Shift/PS ISO Medium.pp3 new file mode 100644 index 000000000..2c83094c2 --- /dev/null +++ b/rtdata/profiles/Pentax Pixel Shift/PS ISO Medium.pp3 @@ -0,0 +1,27 @@ +[Version] +AppVersion=5.0-r1-gtk3-503-g9e1fc78 +Version=326 + +[RAW] +CA=true + +[RAW Bayer] +Method=pixelshift +PixelShiftMotion=0 +PixelShiftMotionCorrection=5 +PixelShiftMotionCorrectionMethod=2 +pixelShiftStddevFactorGreen=5 +pixelShiftStddevFactorRed=5 +pixelShiftStddevFactorBlue=5 +PixelShiftEperIso=2 +PixelShiftNreadIso=0 +PixelShiftPrnu=1 +PixelShiftSigma=5 +PixelShiftSum=3 +PixelShiftRedBlueWeight=0.69999999999999996 +pixelShiftAutomatic=true +pixelShiftHoleFill=true +pixelShiftGreen=true +pixelShiftBlur=true +pixelShiftSmoothFactor=0.69999999999999996 +pixelShiftNonGreenCross=true diff --git a/rtdata/profiles/Pentax Pixel Shift/PS No Motion.pp3 b/rtdata/profiles/Pentax Pixel Shift/PS No Motion.pp3 new file mode 100644 index 000000000..7a73881a1 --- /dev/null +++ b/rtdata/profiles/Pentax Pixel Shift/PS No Motion.pp3 @@ -0,0 +1,26 @@ +[Version] +AppVersion=5.0-r1-gtk3-503-g9e1fc78 +Version=326 + +[Sharpening] +Enabled=true +Method=rld +DeconvRadius=0.75 +DeconvAmount=75 +DeconvDamping=0 +DeconvIterations=30 + +[SharpenMicro] +Enabled=true +Matrix=false +Strength=20 +Uniformity=50 + +[RAW] +CA=true + +[RAW Bayer] +Method=pixelshift +PixelShiftMotion=0 +PixelShiftMotionCorrection=5 +PixelShiftMotionCorrectionMethod=0 diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc index 5a155e051..2449a1cd1 100644 --- a/rtengine/camconst.cc +++ b/rtengine/camconst.cc @@ -418,6 +418,18 @@ CameraConst::update_Levels(const CameraConst *other) // } } +void +CameraConst::update_Crop(CameraConst *other) +{ + if (!other) { + return; + } + + if (other->has_rawCrop()) { + other->get_rawCrop(raw_crop[0], raw_crop[1], raw_crop[2], raw_crop[3]); + } +} + bool CameraConst::get_Levels(struct camera_const_levels & lvl, int bw, int iso, float fnumber) { @@ -668,6 +680,7 @@ CameraConstantsStore::parse_camera_constants_file(Glib::ustring filename_) existingcc->update_dcrawMatrix(cc->get_dcrawMatrix()); // deleting all the existing levels, replaced by the new ones existingcc->update_Levels(cc); + existingcc->update_Crop(cc); if (settings->verbose) { printf("Merging camera constants for \"%s\"\n", make_model.c_str()); diff --git a/rtengine/camconst.h b/rtengine/camconst.h index b57c3fee9..713936bf8 100644 --- a/rtengine/camconst.h +++ b/rtengine/camconst.h @@ -43,6 +43,7 @@ public: int get_BlackLevel(int idx, int iso_speed); int get_WhiteLevel(int idx, int iso_speed, float fnumber); void update_Levels(const CameraConst *other); + void update_Crop(CameraConst *other); }; class CameraConstantsStore diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 679c7a134..527cbc632 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -1164,7 +1164,7 @@ Camera constants: { // Quality B, frame corrections "make_model": "LG mobile LG-H815", "dcraw_matrix": [ 5859,547,-1250,-6484,15547,547,-2422,5625,3906 ], // DNG D65 - "raw_crop": [ 0, 0, -8, 0 ], // full frame 5312x2988, 8 black columns at the left + "raw_crop": [ 0, 0, 0, 0 ], // full frame 5312x2988, 8 black columns at the left "ranges": { "white_max": 1023 } }, @@ -1933,6 +1933,11 @@ Camera constants: "raw_crop": [ 12, 0, -110, -62 ] // for small size all numbers/2 }, + { // Quality C, only raw crop for now - see #3858 + "make_model": "Sigma sd Quattro", + "raw_crop": [ 200, 74, 5632, 3698 ] + }, + { // Quality A, correction for color matrix from Colin Walker's d50 to dng d65 "make_model": "Sony NEX-C3", //"dcraw_matrix": [ 5130,-1055,-269,-4473,11797,3050,-701,1310,7121 ], // Colin walker's d50 kept for possible consistency issues diff --git a/rtengine/diagonalcurves.cc b/rtengine/diagonalcurves.cc index 1c75e3059..3f885782c 100644 --- a/rtengine/diagonalcurves.cc +++ b/rtengine/diagonalcurves.cc @@ -58,7 +58,9 @@ DiagonalCurve::DiagonalCurve (const std::vector& p, int poly_pn) x[i] = p[ix++]; y[i] = p[ix++]; - if (x[i] != y[i]) { + if (std::fabs(x[i] - y[i]) >= 0.000009) { + // the smallest possible difference between x and y curve point values is ~ 0.00001 + // checking against >= 0.000009 is a bit saver than checking against >= 0.00001 identity = false; } } diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 5b7daa3a1..97dc47748 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -1605,6 +1605,10 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int } } + if (alg >= 2 && la < 200.f) { + la = 200.f; + } + const float la2 = float (params->colorappearance.adaplum); // level of adaptation @@ -2362,13 +2366,13 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int hist16JCAM[posl]++; if (curveMode3 == ColorAppearanceParams::TC_MODE_CHROMA) { - chsacol = 327.f; + chsacol = 400.f;//327 colch = C; //450.0 approximative factor for s 320 for M } else if (curveMode3 == ColorAppearanceParams::TC_MODE_SATUR) { chsacol = 450.0f; colch = s; } else { /*if(curveMode3 == ColorAppearanceParams::TC_MODE_COLORF)*/ - chsacol = 327.0f; + chsacol = 400.0f;//327 colch = M; } diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index f5a1f3cff..98b279bbf 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -24,9 +24,6 @@ #include "sleef.c" #include "opthelper.h" -//#define BENCHMARK -//#include "StopWatch.h" - using namespace std; namespace rtengine @@ -35,8 +32,6 @@ namespace rtengine #undef ABS #define ABS(a) ((a)<0?-(a):(a)) -#define CLIREF(x) LIM(x,-200000.0f,200000.0f) // avoid overflow : do not act directly on image[] or pix[] - extern const Settings* settings; SSEFUNCTION void ImProcFunctions::dcdamping (float** aI, float** aO, float damping, int W, int H) @@ -488,7 +483,7 @@ void ImProcFunctions::MLsharpen (LabImage* lab) wD2 = eps2 + fabs (L[offset + width - 1] - L[offset - width + 1]) / s; s = wD1; wD1 /= wD2; - wD2 /= wD1; + wD2 /= s; // initial values int ii = offset / width; @@ -635,6 +630,7 @@ void ImProcFunctions::MLsharpen (LabImage* lab) //! MicroContrast is a sharpening method developed by Manuel Llorens and documented here: http://www.rawness.es/sharpening/?lang=en //!
The purpose is maximize clarity of the image without creating halo's. //!
Addition from JD : pyramid + pondered contrast with matrix 5x5 +//!
2017 Ingo Weyrich : reduced processing time //! \param luminance : Luminance channel of image void ImProcFunctions::MLmicrocontrast (float** luminance, int W, int H) { @@ -642,20 +638,12 @@ void ImProcFunctions::MLmicrocontrast (float** luminance, int W, int H) return; } - MyTime t1e, t2e; - t1e.set(); - - int k = params->sharpenMicro.matrix ? 1 : 2; + const int k = params->sharpenMicro.matrix ? 1 : 2; // k=2 matrix 5x5 k=1 matrix 3x3 - int offset, offset2, i, j, col, row, n; - float temp, temp2, temp3, temp4, tempL; - float *LM, v, s, contrast; - int signs[25]; - int width = W, height = H; - float uniform = params->sharpenMicro.uniformity;//between 0 to 100 - int unif; - unif = (int) (uniform / 10.0f); //put unif between 0 to 10 + const int width = W, height = H; + const float uniform = params->sharpenMicro.uniformity; //between 0 to 100 + const int unif = (int)(uniform / 10.0f); //put unif between 0 to 10 float amount = params->sharpenMicro.amount / 1500.0f; //amount 2000.0 quasi no artefacts ==> 1500 = maximum, after artefacts if (amount < 0.000001f) { @@ -668,127 +656,97 @@ void ImProcFunctions::MLmicrocontrast (float** luminance, int W, int H) if (settings->verbose) { printf ("Micro-contrast amount %f\n", amount); - } - - if (settings->verbose) { printf ("Micro-contrast uniformity %i\n", unif); } //modulation uniformity in function of luminance - float L98[11] = {0.001f, 0.0015f, 0.002f, 0.004f, 0.006f, 0.008f, 0.01f, 0.03f, 0.05f, 0.1f, 0.1f}; - float L95[11] = {0.0012f, 0.002f, 0.005f, 0.01f, 0.02f, 0.05f, 0.1f, 0.12f, 0.15f, 0.2f, 0.25f}; - float L92[11] = {0.01f, 0.015f, 0.02f, 0.06f, 0.10f, 0.13f, 0.17f, 0.25f, 0.3f, 0.32f, 0.35f}; - float L90[11] = {0.015f, 0.02f, 0.04f, 0.08f, 0.12f, 0.15f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f}; - float L87[11] = {0.025f, 0.03f, 0.05f, 0.1f, 0.15f, 0.25f, 0.3f, 0.4f, 0.5f, 0.63f, 0.75f}; - float L83[11] = {0.055f, 0.08f, 0.1f, 0.15f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.75f, 0.85f}; - float L80[11] = {0.15f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f}; - float L75[11] = {0.22f, 0.25f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.85f, 0.9f, 0.95f}; - float L70[11] = {0.35f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.97f, 1.0f, 1.0f, 1.0f, 1.0f}; - float L63[11] = {0.55f, 0.6f, 0.7f, 0.8f, 0.85f, 0.9f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; - float L58[11] = {0.75f, 0.77f, 0.8f, 0.9f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; + const float L98[11] = {0.001f, 0.0015f, 0.002f, 0.004f, 0.006f, 0.008f, 0.01f, 0.03f, 0.05f, 0.1f, 0.1f}; + const float L95[11] = {0.0012f, 0.002f, 0.005f, 0.01f, 0.02f, 0.05f, 0.1f, 0.12f, 0.15f, 0.2f, 0.25f}; + const float L92[11] = {0.01f, 0.015f, 0.02f, 0.06f, 0.10f, 0.13f, 0.17f, 0.25f, 0.3f, 0.32f, 0.35f}; + const float L90[11] = {0.015f, 0.02f, 0.04f, 0.08f, 0.12f, 0.15f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f}; + const float L87[11] = {0.025f, 0.03f, 0.05f, 0.1f, 0.15f, 0.25f, 0.3f, 0.4f, 0.5f, 0.63f, 0.75f}; + const float L83[11] = {0.055f, 0.08f, 0.1f, 0.15f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.75f, 0.85f}; + const float L80[11] = {0.15f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f}; + const float L75[11] = {0.22f, 0.25f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.85f, 0.9f, 0.95f}; + const float L70[11] = {0.35f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.97f, 1.0f, 1.0f, 1.0f, 1.0f}; + const float L63[11] = {0.55f, 0.6f, 0.7f, 0.8f, 0.85f, 0.9f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; + const float L58[11] = {0.75f, 0.77f, 0.8f, 0.9f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; //default 5 //modulation contrast - float Cont0[11] = {0.05f, 0.1f, 0.2f, 0.25f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f}; - float Cont1[11] = {0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 0.95f, 1.0f}; - float Cont2[11] = {0.2f, 0.40f, 0.6f, 0.7f, 0.8f, 0.85f, 0.90f, 0.95f, 1.0f, 1.05f, 1.10f}; - float Cont3[11] = {0.5f, 0.6f, 0.7f, 0.8f, 0.85f, 0.9f, 1.0f, 1.0f, 1.05f, 1.10f, 1.20f}; - float Cont4[11] = {0.8f, 0.85f, 0.9f, 0.95f, 1.0f, 1.05f, 1.10f, 1.150f, 1.2f, 1.25f, 1.40f}; - float Cont5[11] = {1.0f, 1.1f, 1.2f, 1.25f, 1.3f, 1.4f, 1.45f, 1.50f, 1.6f, 1.65f, 1.80f}; + const float Cont0[11] = {0.05f, 0.1f, 0.2f, 0.25f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f}; + const float Cont1[11] = {0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 0.95f, 1.0f}; + const float Cont2[11] = {0.2f, 0.40f, 0.6f, 0.7f, 0.8f, 0.85f, 0.90f, 0.95f, 1.0f, 1.05f, 1.10f}; + const float Cont3[11] = {0.5f, 0.6f, 0.7f, 0.8f, 0.85f, 0.9f, 1.0f, 1.0f, 1.05f, 1.10f, 1.20f}; + const float Cont4[11] = {0.8f, 0.85f, 0.9f, 0.95f, 1.0f, 1.05f, 1.10f, 1.150f, 1.2f, 1.25f, 1.40f}; + const float Cont5[11] = {1.0f, 1.1f, 1.2f, 1.25f, 1.3f, 1.4f, 1.45f, 1.50f, 1.6f, 1.65f, 1.80f}; + + const float s = amount; + const float sqrt2 = sqrt(2.0); + const float sqrt1d25 = sqrt(1.25); + float *LM = new float[width * height]; //allocation for Luminance - float chmax = 8.0f; - LM = new float[width * height]; //allocation for Luminance #ifdef _OPENMP - #pragma omp parallel for private(offset, i,j) shared(LM) + #pragma omp parallel +#endif +{ + +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) #endif - for (j = 0; j < height; j++) - for (i = 0, offset = j * width + i; i < width; i++, offset++) { - LM[offset] = luminance[j][i] / 327.68f; // adjust to 0.100 and to RT variables + for(int j = 0; j < height; j++) + for(int i = 0, offset = j * width + i; i < width; i++, offset++) { + LM[offset] = luminance[j][i] / 327.68f; // adjust to [0;100] and to RT variables } #ifdef _OPENMP - #pragma omp parallel for private(j,i,offset,s,signs,v,n,row,col,offset2,contrast,temp,temp2,tempL,temp4) shared(luminance,LM,amount,chmax,unif,k,L98,L95,L92,L90,L87,L83,L80,L75,L70,L63,L58,Cont0,Cont1,Cont2,Cont3,Cont4,Cont5) + #pragma omp for schedule(dynamic,16) #endif - for (j = k; j < height - k; j++) - for (i = k, offset = j * width + i; i < width - k; i++, offset++) { - s = amount; - v = LM[offset]; - n = 0; + for(int j = k; j < height - k; j++) + for(int i = k, offset = j * width + i; i < width - k; i++, offset++) { + float v = LM[offset]; - for (row = j - k; row <= j + k; row++) - for (col = i - k, offset2 = row * width + col; col <= i + k; col++, offset2++) { - signs[n] = 0; + float contrast; + if (k == 1) { + contrast = sqrtf(SQR(LM[offset + 1] - LM[offset - 1]) + SQR(LM[offset + width] - LM[offset - width])) * 0.125f; //for 3x3 + } else /* if (k==2) */ contrast = sqrtf(SQR(LM[offset + 1] - LM[offset - 1]) + SQR(LM[offset + width] - LM[offset - width]) + + SQR(LM[offset + 2] - LM[offset - 2]) + SQR(LM[offset + 2 * width] - LM[offset - 2 * width])) * 0.0625f; //for 5x5 - if (v < LM[offset2]) { - signs[n] = -1; - } - - if (v > LM[offset2]) { - signs[n] = 1; - } - - n++; - } - - if (k == 1) { - contrast = sqrt (fabs (LM[offset + 1] - LM[offset - 1]) * fabs (LM[offset + 1] - LM[offset - 1]) + fabs (LM[offset + width] - LM[offset - width]) * fabs (LM[offset + width] - LM[offset - width])) / chmax; //for 3x3 - } else /* if (k==2) */ contrast = sqrt (fabs (LM[offset + 1] - LM[offset - 1]) * fabs (LM[offset + 1] - LM[offset - 1]) + fabs (LM[offset + width] - LM[offset - width]) * fabs (LM[offset + width] - LM[offset - width]) - + fabs (LM[offset + 2] - LM[offset - 2]) * fabs (LM[offset + 2] - LM[offset - 2]) + fabs (LM[offset + 2 * width] - LM[offset - 2 * width]) * fabs (LM[offset + 2 * width] - LM[offset - 2 * width])) / (2 * chmax); //for 5x5 - - if (contrast > 1.0f) { - contrast = 1.0f; - } + contrast = std::min(contrast, 1.f); //matrix 5x5 - temp = luminance[j][i] / 327.68f; //begin 3x3 - temp += CLIREF (v - LM[offset - width - 1]) * sqrtf (2.0f) * s; - temp += CLIREF (v - LM[offset - width]) * s; - temp += CLIREF (v - LM[offset - width + 1]) * sqrtf (2.0f) * s; - temp += CLIREF (v - LM[offset - 1]) * s; - temp += CLIREF (v - LM[offset + 1]) * s; - temp += CLIREF (v - LM[offset + width - 1]) * sqrtf (2.0f) * s; - temp += CLIREF (v - LM[offset + width]) * s; - temp += CLIREF (v - LM[offset + width + 1]) * sqrtf (2.0f) * s; //end 3x3 + float temp = v + 4.f *( v * (s + sqrt2 * s)); //begin 3x3 + float temp1 = sqrt2 * s *(LM[offset - width - 1] + LM[offset - width + 1] + LM[offset + width - 1] + LM[offset + width + 1]); + temp1 += s * (LM[offset - width] + LM[offset - 1] + LM[offset + 1] + LM[offset + width]); + + temp -= temp1; // add JD continue 5x5 if (k == 2) { - temp += 2.0f * CLIREF (v - LM[offset + 2 * width]) * s; - temp += 2.0f * CLIREF (v - LM[offset - 2 * width]) * s; - temp += 2.0f * CLIREF (v - LM[offset - 2 ]) * s; - temp += 2.0f * CLIREF (v - LM[offset + 2 ]) * s; + float temp2 = -(LM[offset + 2 * width] + LM[offset - 2 * width] + LM[offset - 2] + LM[offset + 2]); - temp += 2.0f * CLIREF (v - LM[offset + 2 * width - 1]) * s * sqrtf (1.25f); // 1.25 = 1*1 + 0.5*0.5 - temp += 2.0f * CLIREF (v - LM[offset + 2 * width - 2]) * s * sqrtf (2.00f); - temp += 2.0f * CLIREF (v - LM[offset + 2 * width + 1]) * s * sqrtf (1.25f); - temp += 2.0f * CLIREF (v - LM[offset + 2 * width + 2]) * s * sqrtf (2.00f); - temp += 2.0f * CLIREF (v - LM[offset + width + 2]) * s * sqrtf (1.25f); - temp += 2.0f * CLIREF (v - LM[offset + width - 2]) * s * sqrtf (1.25f); - temp += 2.0f * CLIREF (v - LM[offset - 2 * width - 1]) * s * sqrtf (1.25f); - temp += 2.0f * CLIREF (v - LM[offset - 2 * width - 2]) * s * sqrtf (2.00f); - temp += 2.0f * CLIREF (v - LM[offset - 2 * width + 1]) * s * sqrtf (1.25f); - temp += 2.0f * CLIREF (v - LM[offset - 2 * width + 2]) * s * sqrtf (2.00f); - temp += 2.0f * CLIREF (v - LM[offset - width + 2]) * s * sqrtf (1.25f); - temp += 2.0f * CLIREF (v - LM[offset - width - 2]) * s * sqrtf (1.25f); + temp2 -= sqrt1d25 * (LM[offset + 2 * width - 1] + LM[offset + 2 * width + 1] + LM[offset + width + 2] + LM[offset + width - 2] + + LM[offset - 2 * width - 1] + LM[offset - 2 * width + 1] + LM[offset - width + 2] + LM[offset - width - 2]); + + temp2 -= sqrt2 * (LM[offset + 2 * width - 2] + LM[offset + 2 * width + 2] + LM[offset - 2 * width - 2] + LM[offset - 2 * width + 2]); + temp2 += 18.601126159f * v ; // 18.601126159 = 4 + 4 * sqrt(2) + 8 * sqrt(1.25) + temp2 *= 2.f * s; + temp += temp2; } - if (temp < 0.0f) { - temp = 0.0f; - } + temp = std::max(temp, 0.f); - v = temp; - - n = 0; - - for (row = j - k; row <= j + k; row++) { - for (col = i - k, offset2 = row * width + col; col <= i + k; col++, offset2++) { - if (((v < LM[offset2]) && (signs[n] > 0)) || ((v > LM[offset2]) && (signs[n] < 0))) { - temp = v * 0.75f + LM[offset2] * 0.25f; // 0.75 0.25 + for(int row = j + k, n = SQR(2*k+1) - 1; row >= j - k; row--) { + for(int offset2 = row * width + i + k; offset2 >= row * width + i - k; offset2--) { + if((LM[offset2] - temp) * (v - LM[offset2]) > 0.f) { + temp = intp(0.75f, temp, LM[offset2]); + goto breakout; } - - n++; + n--; } } + breakout: if (LM[offset] > 95.0f || LM[offset] < 5.0f) { contrast *= Cont0[unif]; //+ JD : luminance pyramid to adjust contrast by evaluation of LM[offset] @@ -804,184 +762,114 @@ void ImProcFunctions::MLmicrocontrast (float** luminance, int W, int H) contrast *= Cont5[unif]; //(2.0f/k)*Cont5[unif]; } - if (contrast > 1.0f) { - contrast = 1.0f; - } + contrast = std::min(contrast, 1.f); - tempL = 327.68f * (temp * (1.0f - contrast) + LM[offset] * contrast); + float tempL = intp(contrast, LM[offset], temp); // JD: modulation of microcontrast in function of original Luminance and modulation of luminance - temp2 = tempL / (327.68f * LM[offset]); //for highlights - - if (temp2 > 1.0f) { - if (temp2 > 1.70f) { - temp2 = 1.70f; //limit action - } - - if (LM[offset] > 98.0f) { - luminance[j][i] = LM[offset] * 327.68f; + if (tempL > LM[offset]) { + float temp2 = tempL / LM[offset]; //for highlights + temp2 = std::min(temp2, 1.7f); //limit action + temp2 -= 1.f; + if (LM[offset] > 98.0f) { + temp = 0.f; } else if (LM[offset] > 95.0f) { - temp = (L95[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L95[unif]; } else if (LM[offset] > 92.0f) { - temp = (L92[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L92[unif]; } else if (LM[offset] > 90.0f) { - temp = (L90[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L90[unif]; } else if (LM[offset] > 87.0f) { - temp = (L87[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L87[unif]; } else if (LM[offset] > 83.0f) { - temp = (L83[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L83[unif]; } else if (LM[offset] > 80.0f) { - temp = (L80[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L80[unif]; } else if (LM[offset] > 75.0f) { - temp = (L75[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L75[unif]; } else if (LM[offset] > 70.0f) { - temp = (L70[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L70[unif]; } else if (LM[offset] > 63.0f) { - temp = (L63[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L63[unif]; } else if (LM[offset] > 58.0f) { - temp = (L58[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L58[unif]; } else if (LM[offset] > 42.0f) { - temp = (L58[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L58[unif]; } else if (LM[offset] > 37.0f) { - temp = (L63[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L63[unif]; } else if (LM[offset] > 30.0f) { - temp = (L70[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L70[unif]; } else if (LM[offset] > 25.0f) { - temp = (L75[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L75[unif]; } else if (LM[offset] > 20.0f) { - temp = (L80[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L80[unif]; } else if (LM[offset] > 17.0f) { - temp = (L83[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L83[unif]; } else if (LM[offset] > 13.0f) { - temp = (L87[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L87[unif]; } else if (LM[offset] > 10.0f) { - temp = (L90[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; + temp = L90[unif]; } else if (LM[offset] > 5.0f) { - temp = (L95[unif] * (temp2 - 1.f)) + 1.0f; - luminance[j][i] = temp * LM[offset] * 327.68f; - } else if (LM[offset] > 0.0f) { - luminance[j][i] = LM[offset] * 327.68f; + temp = L95[unif]; + } else { + temp = 0.f; + } + luminance[j][i] *= (temp * temp2 + 1.f); + } else { + + float temp4 = LM[offset] / tempL; // + + if (temp4 > 1.0f) { + temp4 = std::min(temp4, 1.7f); //limit action + temp4 -= 1.f; + if (LM[offset] < 2.0f) { + temp = L98[unif]; + } else if (LM[offset] < 5.0f) { + temp = L95[unif]; + } else if (LM[offset] < 8.0f) { + temp = L92[unif]; + } else if (LM[offset] < 10.0f) { + temp = L90[unif]; + } else if (LM[offset] < 13.0f) { + temp = L87[unif]; + } else if (LM[offset] < 17.0f) { + temp = L83[unif]; + } else if (LM[offset] < 20.0f) { + temp = L80[unif]; + } else if (LM[offset] < 25.0f) { + temp = L75[unif]; + } else if (LM[offset] < 30.0f) { + temp = L70[unif]; + } else if (LM[offset] < 37.0f) { + temp = L63[unif]; + } else if (LM[offset] < 42.0f) { + temp = L58[unif]; + } else if (LM[offset] < 58.0f) { + temp = L58[unif]; + } else if (LM[offset] < 63.0f) { + temp = L63[unif]; + } else if (LM[offset] < 70.0f) { + temp = L70[unif]; + } else if (LM[offset] < 75.0f) { + temp = L75[unif]; + } else if (LM[offset] < 80.0f) { + temp = L80[unif]; + } else if (LM[offset] < 83.0f) { + temp = L83[unif]; + } else if (LM[offset] < 87.0f) { + temp = L87[unif]; + } else if (LM[offset] < 90.0f) { + temp = L90[unif]; + } else if (LM[offset] < 95.0f) { + temp = L95[unif]; + } else { + temp = 0.f; + } + luminance[j][i] /= (temp * temp4 + 1.f); } } - - temp4 = (327.68f * LM[offset]) / tempL; // - - if (temp4 > 1.0f) { - if (temp4 > 1.7f) { - temp4 = 1.7f; //limit action - } - - if (LM[offset] < 2.0f) { - temp3 = temp4 - 1.0f; - temp = (L98[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 5.0f) { - temp3 = temp4 - 1.0f; - temp = (L95[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 8.0f) { - temp3 = temp4 - 1.0f; - temp = (L92[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 10.0f) { - temp3 = temp4 - 1.0f; - temp = (L90[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 13.0f) { - temp3 = temp4 - 1.0f; - temp = (L87[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 17.0f) { - temp3 = temp4 - 1.0f; - temp = (L83[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 20.0f) { - temp3 = temp4 - 1.0f; - temp = (L80[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 25.0f) { - temp3 = temp4 - 1.0f; - temp = (L75[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 30.0f) { - temp3 = temp4 - 1.0f; - temp = (L70[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 37.0f) { - temp3 = temp4 - 1.0f; - temp = (L63[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 42.0f) { - temp3 = temp4 - 1.0f; - temp = (L58[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 58.0f) { - temp3 = temp4 - 1.0f; - temp = (L58[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 63.0f) { - temp3 = temp4 - 1.0f; - temp = (L63[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 70.0f) { - temp3 = temp4 - 1.0f; - temp = (L70[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 75.0f) { - temp3 = temp4 - 1.0f; - temp = (L75[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 80.0f) { - temp3 = temp4 - 1.0f; - temp = (L80[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 83.0f) { - temp3 = temp4 - 1.0f; - temp = (L83[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 87.0f) { - temp3 = temp4 - 1.0f; - temp = (L87[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 90.0f) { - temp3 = temp4 - 1.0f; - temp = (L90[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 95.0f) { - temp3 = temp4 - 1.0f; - temp = (L95[unif] * temp3) + 1.0f; - luminance[j][i] = (LM[offset] * 327.68f) / temp; - } else if (LM[offset] < 100.0f) { - luminance[j][i] = LM[offset] * 327.68f; - } - } - } - +} delete [] LM; - t2e.set(); - - if (settings->verbose) { - printf ("Micro-contrast %d usec\n", t2e.etime (t1e)); - } - } void ImProcFunctions::MLmicrocontrast (LabImage* lab) diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc index 835aa7631..e7d6b86c7 100644 --- a/rtengine/pixelshift.cc +++ b/rtengine/pixelshift.cc @@ -1,13 +1,8 @@ //////////////////////////////////////////////////////////////// // -// pentax pixelshift algorithm with motion detection +// Algorithm for Pentax Pixel Shift raw files with motion detection // -// -// If motion correction is enabled only the pixels which are not detected as motion are set -// That means for a complete image you have to demosaic one of the frames with a bayer demosaicer to fill red, green and blue -// before calling pixelshift in case motion correction is enabled. -// -// copyright (c) Ingo Weyrich 2016 +// Copyright (C) 2016 - 2017 Ingo Weyrich // // // pixelshift.cc is free software: you can redistribute it and/or modify @@ -31,73 +26,29 @@ #include "procparams.h" #include "gauss.h" #include "median.h" -#define BENCHMARK -#include "StopWatch.h" namespace { -float greenDiff(float a, float b, bool adaptive, float stddevFactor, float eperIso, float nreadIso, float prnu, bool showMotion) +float greenDiff(float a, float b, float stddevFactor, float eperIso, float nreadIso, float prnu) { // calculate the difference between two green samples -#ifdef PIXELSHIFTDEV - if(adaptive) { -#endif - float gDiff = a - b; - gDiff *= eperIso; - gDiff *= gDiff; - float avg = (a + b) * 0.5f; - avg *= eperIso; - prnu *= avg; - float stddev = stddevFactor * (avg + nreadIso + prnu * prnu); - float result = gDiff - stddev; - - if(!showMotion) { - return result; - } else if(result > 0.f) { // for the motion mask - return std::fabs(a - b) / (std::max(a, b) + 0.01f); - } else { - return 0.f; - } -#ifdef PIXELSHIFTDEV - - } else { - float gDiff = std::fabs(a - b); - // add a small epsilon to avoid division by zero - float maxVal = std::max(a, b) + 0.01f; - return gDiff / maxVal; - } -#endif -} - -#ifdef PIXELSHIFTDEV -float nonGreenDiff(float a, float b, float stddevFactor, float eperIso, float nreadIso, float prnu, bool showMotion) -{ - // calculate the difference between two nongreen samples float gDiff = a - b; gDiff *= eperIso; gDiff *= gDiff; - float avg = (a + b) / 2.f; + float avg = (a + b) * 0.5f; avg *= eperIso; prnu *= avg; float stddev = stddevFactor * (avg + nreadIso + prnu * prnu); - float result = gDiff - stddev; - - if(!showMotion) { - return result; - } else if(result > 0.f) { // for the motion mask - return std::fabs(a - b) / (std::max(a, b) + 0.01f); - } else { - return 0.f; - } + return gDiff - stddev; } -#endif -float nonGreenDiffCross(float right, float left, float top, float bottom, float centre, float clippedVal, float stddevFactor, float eperIso, float nreadIso, float prnu, bool showMotion) +float nonGreenDiffCross(float right, float left, float top, float bottom, float centre, float clippedVal, float stddevFactor, float eperIso, float nreadIso, float prnu) { if(rtengine::max(right, left, top, bottom, centre) > clippedVal) { return 0.f; } + // check non green cross float hDiff = (right + left) * 0.5f - centre; hDiff *= eperIso; @@ -109,36 +60,32 @@ float nonGreenDiffCross(float right, float left, float top, float bottom, float avg *= eperIso; prnu *= avg; float stddev = stddevFactor * (avg + nreadIso + prnu * prnu); - float result = std::min(hDiff, vDiff) - stddev; - - if(!showMotion) { - return result; - } else if(result > 0.f) { // for the motion mask - return std::sqrt((result / (stddev + result + 0.01f))); - } else { - return 0.f; - } + return std::min(hDiff, vDiff) - stddev; } -void paintMotionMask(int index, bool showMotion, float gridMax, bool showOnlyMask, float *maskDest, float *nonMaskDest0, float *nonMaskDest1) +void paintMotionMask(int index, bool showMotion, bool showOnlyMask, float *maskDest, float *nonMaskDest0, float *nonMaskDest1) { if(showMotion) { if(!showOnlyMask) { // if showMotion is enabled colourize the pixel - maskDest[index] = 1000.f + 25000.f * gridMax; + maskDest[index] = 13500.f; nonMaskDest1[index] = nonMaskDest0[index] = 0.f; } else { - maskDest[index] = nonMaskDest0[index] = nonMaskDest1[index] = 1000.f + 25000.f * gridMax; + maskDest[index] = nonMaskDest0[index] = nonMaskDest1[index] = 65535.f; } } } void invertMask(int xStart, int xEnd, int yStart, int yEnd, const array2D &maskIn, array2D &maskOut) { +#ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) +#endif for(int i = yStart; i < yEnd; ++i) { +#ifdef _OPENMP #pragma omp simd +#endif for(int j = xStart; j < xEnd; ++j) { maskOut[i][j] = ~maskIn[i][j]; @@ -148,10 +95,14 @@ void invertMask(int xStart, int xEnd, int yStart, int yEnd, const array2D &maskIn, array2D &maskOut) { +#ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) +#endif for(int i = yStart; i < yEnd; ++i) { +#ifdef _OPENMP #pragma omp simd +#endif for(int j = xStart; j < xEnd; ++j) { maskOut[i][j] ^= maskIn[i][j]; @@ -168,7 +119,7 @@ void floodFill4Impl(int y, int x, int xStart, int xEnd, int yStart, int yEnd, ar coordStack.pop(); auto x = coord.first, y = coord.second; - if (mask[y][x] == 255) { + if(mask[y][x] == 255) { auto yUp = y - 1, yDown = y + 1; bool lastXUp = false, lastXDown = false, firstXUp = false, firstXDown = false; mask[y][x] = 0; @@ -244,27 +195,37 @@ void floodFill4Impl(int y, int x, int xStart, int xEnd, int yStart, int yEnd, ar void floodFill4(int xStart, int xEnd, int yStart, int yEnd, array2D &mask) { +#ifdef _OPENMP #pragma omp parallel +#endif { std::stack, std::vector>> coordStack; +#ifdef _OPENMP #pragma omp for schedule(dynamic,128) nowait +#endif for(uint16_t i = yStart; i < yEnd; i++) { floodFill4Impl(i, xStart, xStart, xEnd, yStart, yEnd, mask, coordStack); } +#ifdef _OPENMP #pragma omp for schedule(dynamic,128) nowait +#endif for(int16_t i = yEnd - 1; i >= 0 ; i--) { floodFill4Impl(i, xEnd - 1, xStart, xEnd, yStart, yEnd, mask, coordStack); } +#ifdef _OPENMP #pragma omp sections nowait +#endif { +#ifdef _OPENMP #pragma omp section +#endif { uint16_t i = yStart; @@ -273,7 +234,9 @@ void floodFill4(int xStart, int xEnd, int yStart, int yEnd, array2D &ma floodFill4Impl(i, j, xStart, xEnd, yStart, yEnd, mask, coordStack); } } +#ifdef _OPENMP #pragma omp section +#endif { uint16_t i = yStart; @@ -282,7 +245,9 @@ void floodFill4(int xStart, int xEnd, int yStart, int yEnd, array2D &ma floodFill4Impl(i, j, xStart, xEnd, yStart, yEnd, mask, coordStack); } } +#ifdef _OPENMP #pragma omp section +#endif { uint16_t i = yEnd; @@ -291,7 +256,9 @@ void floodFill4(int xStart, int xEnd, int yStart, int yEnd, array2D &ma floodFill4Impl(i, j, xStart, xEnd, yStart, yEnd, mask, coordStack); } } +#ifdef _OPENMP #pragma omp section +#endif { uint16_t i = yEnd; @@ -307,11 +274,12 @@ void floodFill4(int xStart, int xEnd, int yStart, int yEnd, array2D &ma void calcFrameBrightnessFactor(unsigned int frame, uint32_t datalen, LUT *histo[4], float brightnessFactor[4]) { float medians[4]; + for(int i = 0; i < 4; ++i) { //find median of histogram uint32_t median = 0, count = 0; - while (count < datalen / 2) { + while(count < datalen / 2) { count += (*histo[i])[median]; ++median; } @@ -333,186 +301,95 @@ using namespace std; using namespace rtengine; void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RAWParams::BayerSensor &bayerParamsIn, unsigned int frame, const std::string &model, float rawWpCorrection) { -#ifdef PIXELSHIFTDEV - BENCHFUN -#endif if(numFrames != 4) { // fallback for non pixelshift files - amaze_demosaic_RT (0, 0, winw, winh, rawData, red, green, blue); + amaze_demosaic_RT(winx, winy, winw, winh, rawData, red, green, blue); return; } RAWParams::BayerSensor bayerParams = bayerParamsIn; -#ifndef PIXELSHIFTDEV bayerParams.pixelShiftAutomatic = true; -#endif if(bayerParams.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::Automatic) { bool pixelShiftEqualBright = bayerParams.pixelShiftEqualBright; bayerParams.setPixelShiftDefaults(); bayerParams.pixelShiftEqualBright = pixelShiftEqualBright; } else if(bayerParams.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::Off) { - bayerParams.pixelShiftMotion = 0; bayerParams.pixelShiftAutomatic = false; bayerParams.pixelShiftShowMotion = false; } - if((bayerParams.pixelShiftMotion > 0 || bayerParams.pixelShiftAutomatic)) { - if(bayerParams.pixelShiftMedian) { // We need the amaze demosaiced frames for motion correction -#ifdef PIXELSHIFTDEV - if(!bayerParams.pixelShiftMedian3) { -#endif + const bool showMotion = bayerParams.pixelShiftShowMotion; + const bool showOnlyMask = bayerParams.pixelShiftShowMotionMaskOnly && showMotion; + + if(bayerParams.pixelShiftAutomatic) { + if(!showOnlyMask) { + if(bayerParams.pixelShiftMedian) { // We need the amaze demosaiced frames for motion correction if(bayerParams.pixelShiftLmmse) { lmmse_interpolate_omp(winw, winh, *(rawDataFrames[0]), red, green, blue, bayerParams.lmmse_iterations); } else { - amaze_demosaic_RT (0, 0, winw, winh, *(rawDataFrames[0]), red, green, blue); + amaze_demosaic_RT(winx, winy, winw, winh, *(rawDataFrames[0]), red, green, blue); } - multi_array2D redTmp(W,H); - multi_array2D greenTmp(W,H); - multi_array2D blueTmp(W,H); - for(int i=0;i<3;i++) { + + multi_array2D redTmp(winw, winh); + multi_array2D greenTmp(winw, winh); + multi_array2D blueTmp(winw, winh); + + for(int i = 0; i < 3; i++) { if(bayerParams.pixelShiftLmmse) { - lmmse_interpolate_omp(winw, winh, *(rawDataFrames[i+1]), redTmp[i], greenTmp[i], blueTmp[i], bayerParams.lmmse_iterations); + lmmse_interpolate_omp(winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i], bayerParams.lmmse_iterations); } else { - amaze_demosaic_RT (0, 0, winw, winh, *(rawDataFrames[i+1]), redTmp[i], greenTmp[i], blueTmp[i]); + amaze_demosaic_RT(winx, winy, winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i]); } } + +#ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) - for(int i=border;i redTmp(W,H); - multi_array2D greenTmp(W,H); - multi_array2D blueTmp(W,H); - for(unsigned int i=0, frameIndex = 0;i<4;++i) { - if(i != currFrame) { - if(bayerParams.pixelShiftLmmse) { - lmmse_interpolate_omp(winw, winh, *(rawDataFrames[i]), redTmp[frameIndex], greenTmp[frameIndex], blueTmp[frameIndex], bayerParams.lmmse_iterations); - } else { - amaze_demosaic_RT (0, 0, winw, winh, *(rawDataFrames[i]), redTmp[frameIndex], greenTmp[frameIndex], blueTmp[frameIndex]); - } - ++frameIndex; - } - } - unsigned int offsX0 = 0, offsY0 = 0; - unsigned int offsX1 = 0, offsY1 = 0; - unsigned int offsX2 = 0, offsY2 = 0; - - // We have to adjust the offsets for the selected subframe we exclude from median - switch (currFrame) { - case 0: - offsY0 = 1; - offsX0 = 0; - offsY1 = 1; - offsX1 = 1; - offsY2 = 0; - offsX2 = 1; - break; - - case 1: - offsY0 = 0; - offsX0 = 0; - offsY1 = 1; - offsX1 = 1; - offsY2 = 0; - offsX2 = 1; - break; - - case 2: - offsY0 = 0; - offsX0 = 0; - offsY1 = 1; - offsX1 = 0; - offsY2 = 0; - offsX2 = 1; - break; - - case 3: - offsY0 = 0; - offsX0 = 0; - offsY1 = 1; - offsX1 = 0; - offsY2 = 1; - offsX2 = 1; - } - - #pragma omp parallel for schedule(dynamic,16) - for(int i=border;i 0; - float stddevFactorGreen = bayerParams.pixelShiftStddevFactorGreen; - float stddevFactorRed = bayerParams.pixelShiftStddevFactorRed; - float stddevFactorBlue = bayerParams.pixelShiftStddevFactorBlue; - float nreadIso = bayerParams.pixelShiftNreadIso; - float prnu = bayerParams.pixelShiftPrnu; - const float redBlueWeight = bayerParams.pixelShiftRedBlueWeight + 1.f; -#else - float stddevFactorGreen = 5.f; - float stddevFactorRed = 5.f; - float stddevFactorBlue = 5.f; - float nreadIso = 0.f; - float prnu = 1.f; - const float redBlueWeight = 0.7f + 1.f; -#endif + constexpr float stddevFactorGreen = 25.f; + constexpr float stddevFactorRed = 25.f; + constexpr float stddevFactorBlue = 25.f; + constexpr float prnu = 0.01f; + constexpr float redBlueWeight = 0.7f + 1.f; float eperIso = bayerParams.pixelShiftEperIso; const bool checkNonGreenCross = bayerParams.pixelShiftNonGreenCross; const bool checkGreen = bayerParams.pixelShiftGreen; - const float greenWeight = 2.f; + constexpr float greenWeight = 2.f; const bool blurMap = bayerParams.pixelShiftBlur; const float sigma = bayerParams.pixelShiftSigma; -#ifdef PIXELSHIFTDEV - const bool checkNonGreenHorizontal = bayerParams.pixelShiftNonGreenHorizontal; - const bool checkNonGreenVertical = bayerParams.pixelShiftNonGreenVertical; - const bool checkNonGreenAmaze = bayerParams.pixelShiftNonGreenAmaze; - const bool checkNonGreenCross2 = bayerParams.pixelShiftNonGreenCross2; - const float threshold = bayerParams.pixelShiftSum + 9.f; - const bool experimental0 = bayerParams.pixelShiftExp0; -#else constexpr float threshold = 3.f + 9.f; -#endif const bool holeFill = bayerParams.pixelShiftHoleFill; const bool equalBrightness = bayerParams.pixelShiftEqualBright; const bool equalChannel = bayerParams.pixelShiftEqualBrightChannel; @@ -546,8 +423,7 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA 1.5f, // ISO 25600 1.5f, // ISO 32000 1.5f, // ISO 40000 - 1.5f, // ISO 51200 - 1.5f // ISO > 51200 (we get a max ISO value of 65535 from dcraw) + 1.5f // ISO 51200 }; static const float ePerIsoK3II = 0.35f; @@ -590,6 +466,7 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA static const float ePerIsoK1 = 0.75f; + // currently nReadK70 is used for K-70 and KP static const float nReadK70[] = { 4.0f, // ISO 100 4.0f, // ISO 125 4.0f, // ISO 160 @@ -618,50 +495,28 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA 3.0f, // ISO 32000 3.0f, // ISO 40000 3.0f, // ISO 51200 - 3.0f // ISO > 51200 (we get a max ISO value of 65535 from dcraw) + 3.0f, // ISO 64000 + 3.0f, // ISO 80000 + 3.0f, // ISO 102400 + 3.0f, // ISO 128000 + 3.0f, // ISO 160000 + 3.0f, // ISO 204800 + 3.0f, // ISO 256000 + 3.0f, // ISO 320000 + 3.0f, // ISO 409600 + 3.0f, // ISO 512000 + 3.0f, // ISO 640000 + 3.0f // ISO 819200 }; static const float ePerIsoK70 = 0.5f; - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::pixelshift])); + if(plistener) { + plistener->setProgressStr(Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::pixelshift])); plistener->setProgress(0.0); } - -#ifdef PIXELSHIFTDEV - const bool skip = (gridSize_ == RAWParams::BayerSensor::ePSMotionCorrection::Grid1x2); - int gridSize = 1; - - bool nOf3x3 = false; - - switch (gridSize_) { - case RAWParams::BayerSensor::ePSMotionCorrection::Grid1x1: - case RAWParams::BayerSensor::ePSMotionCorrection::Grid1x2: - gridSize = 1; - break; - - case RAWParams::BayerSensor::ePSMotionCorrection::Grid3x3: - gridSize = 3; - break; - - case RAWParams::BayerSensor::ePSMotionCorrection::Grid5x5: - gridSize = 5; - break; - - case RAWParams::BayerSensor::ePSMotionCorrection::Grid7x7: - gridSize = 7; - break; - - case RAWParams::BayerSensor::ePSMotionCorrection::Grid3x3New: - gridSize = 1; - nOf3x3 = true; - } -#else - const bool nOf3x3 = true; -#endif - - if(adaptive && blurMap && nOf3x3 && smoothFactor == 0.f && !showMotion) { + if(adaptive && blurMap && smoothFactor == 0.f && !showMotion) { if(plistener) { plistener->setProgress(1.0); } @@ -669,20 +524,6 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA return; } -#ifdef PIXELSHIFTDEV - // Lookup table for non adaptive (slider) mode - LUTf log2Lut(32768, LUT_CLIP_BELOW | LUT_CLIP_ABOVE); - - if(detectMotion && !adaptive) { - const float lutStrength = 2.f; - log2Lut[0] = 0; - - for(int i = 2; i < 65536; i += 2) { - log2Lut[i >> 1] = lutStrength * log2(i) / 100.f; - } - } -#endif - const float scaleGreen = 1.f / scale_mul[1]; float nRead; @@ -696,27 +537,15 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA } else if(model.find("K-1") != string::npos) { nRead = nReadK1[nReadIndex]; eperIsoModel = ePerIsoK1; - } else { + } else { // as long as we don't have values for Pentax KP, we use the values from K-70 nRead = nReadK70[nReadIndex]; eperIsoModel = ePerIsoK70; } - nRead *= pow(2.f, nreadIso); eperIsoModel *= pow(2.f, eperIso); -#ifdef PIXELSHIFTDEV - if(adaptive && experimental0) { - eperIso = eperIsoModel * sqrtf(100.f / (rawWpCorrection * idata->getISOSpeed())); - } else { - eperIso = eperIsoModel * (100.f / (rawWpCorrection * idata->getISOSpeed())); - } -#else eperIso = eperIsoModel * (100.f / (rawWpCorrection * idata->getISOSpeed())); -#endif -#ifdef PIXELSHIFTDEV - std::cout << "WL: " << c_white[0] << " BL: " << c_black[0] << " ePerIso multiplicator: " << (65535.f / (c_white[0] - c_black[0])) << std::endl; -#endif const float eperIsoRed = (eperIso / scale_mul[0]) * (65535.f / (c_white[0] - c_black[0])); const float eperIsoGreen = (eperIso * scaleGreen) * (65535.f / (c_white[1] - c_black[1])); const float eperIsoBlue = (eperIso / scale_mul[2]) * (65535.f / (c_white[2] - c_black[2])); @@ -724,44 +553,8 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA const float clippedRed = 65535.f / scale_mul[0]; const float clippedBlue = 65535.f / scale_mul[2]; - prnu /= 100.f; - stddevFactorGreen *= stddevFactorGreen; - stddevFactorRed *= stddevFactorRed; - stddevFactorBlue *= stddevFactorBlue; - - nRead *= nRead; - // If the values of two corresponding green pixels differ my more then motionThreshold %, the pixel will be treated as a badGreen pixel - const float motionThreshold = 1.f - (motion / 100.f); - // For shades of green motion indicators -#ifdef PIXELSHIFTDEV - const float blendFactor = ((adaptive || motion == 0.f) ? 1.f : 1.f / (1.f - motionThreshold)); -#endif - int offsX = 0, offsY = 0; - - if(!bayerParams.pixelShiftMedian || !adaptive) { - // We have to adjust the offsets for the selected subframe we use for areas with motion - switch (frame) { - case 0: - offsX = offsY = 0; - break; - - case 1: - offsX = 0; - offsY = 1; - break; - - case 2: - offsX = offsY = 1; - break; - - case 3: - offsX = 1; - offsY = 0; - } - } - // calculate average green brightness for each frame float greenBrightness[4] = {1.f, 1.f, 1.f, 1.f}; float redBrightness[4] = {1.f, 1.f, 1.f, 1.f}; @@ -811,6 +604,7 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA for(int j = winx + 1, offset = FC(i, j) & 1; j < winw - 1; ++j, offset ^= 1) { (*histogreenThr[1 - offset])[(*rawDataFrames[1 - offset])[i - offset + 1][j]]++; (*histogreenThr[3 - offset])[(*rawDataFrames[3 - offset])[i + offset][j + 1]]++; + if(bluerow) { (*historedThr[2 - offset])[(*rawDataFrames[2 - offset])[i + 1][j - offset + 1]]++; (*histoblueThr[(offset << 1) + offset])[(*rawDataFrames[(offset << 1) + offset])[i][j + offset]]++; @@ -821,7 +615,9 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA } } +#ifdef _OPENMP #pragma omp critical +#endif { for(int i = 0; i < 4; ++i) { (*histogreen[i]) += (*histogreenThr[i]); @@ -843,556 +639,146 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA delete histoblue[i]; delete histogreen[i]; } - -#ifdef PIXELSHIFTDEV - std::cout << "blue brightness factors by median : " << blueBrightness[0] << " " << blueBrightness[1] << " " << blueBrightness[2] << " " << blueBrightness[3] << std::endl; - std::cout << "red brightness factors by median : " << redBrightness[0] << " " << redBrightness[1] << " " << redBrightness[2] << " " << redBrightness[3] << std::endl; - std::cout << "green brightness factors by median : " << greenBrightness[0] << " " << greenBrightness[1] << " " << greenBrightness[2] << " " << greenBrightness[3] << std::endl; -#endif - } - const float thresh = adaptive ? 0.f : motionThreshold; - array2D psRed(winw + 32, winh); // increase width to avoid cache conflicts - array2D psG1(winw + 32, winh); - array2D psG2(winw + 32, winh); - array2D psBlue(winw + 32, winh); - if(!equalChannel) { - for(int i = 0; i < 4; ++i ) { + for(int i = 0; i < 4; ++i) { redBrightness[i] = blueBrightness[i] = greenBrightness[i]; } } -// fill channels psRed, psG1, psG2 and psBlue -#ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) -#endif - for(int i = winy + 1; i < winh - 1; ++i) { - float *greenDest1 = psG1[i]; - float *greenDest2 = psG2[i]; - float *nonGreenDest0 = psRed[i]; - float *nonGreenDest1 = psBlue[i]; - float ngbright[2][4] = {{redBrightness[0],redBrightness[1],redBrightness[2],redBrightness[3]}, - {blueBrightness[0],blueBrightness[1],blueBrightness[2],blueBrightness[3]} - }; - int ng = 0; - int j = winx + 1; - int c = FC(i, j); - - if ((c + FC(i, j + 1)) == 3) { - // row with blue pixels => swap destination pointers for non green pixels - std::swap(nonGreenDest0, nonGreenDest1); - std::swap(greenDest1, greenDest2); - ng ^= 1; - } - - // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop - unsigned int offset = c & 1; - - for(; j < winw - 1; ++j) { - // store the values from the 4 frames into 4 different temporary planes - greenDest1[j] = (*rawDataFrames[1 - offset])[i - offset + 1][j] * greenBrightness[1 - offset]; - greenDest2[j] = (*rawDataFrames[3 - offset])[i + offset][j + 1] * greenBrightness[3 - offset]; - nonGreenDest0[j] = (*rawDataFrames[(offset << 1) + offset])[i][j + offset] * ngbright[ng][(offset << 1) + offset]; - nonGreenDest1[j] = (*rawDataFrames[2 - offset])[i + 1][j - offset + 1] * ngbright[ng^1][2 - offset]; - offset ^= 1; // 0 => 1 or 1 => 0 - } - } - -// now that the temporary planes are filled for easy access we do the motion detection -#ifdef PIXELSHIFTDEV - int sum[2] = {0}; - float pixelcount = ((winh - (border + offsY) - (winy + border - offsY)) * (winw - (border + offsX) - (winx + border - offsX))) / 2.f; -#endif - - array2D psMask(winw, winh); + if(adaptive) { + // fill channels psRed and psBlue + array2D psRed(winw + 32, winh); // increase width to avoid cache conflicts + array2D psBlue(winw + 32, winh); #ifdef _OPENMP - #pragma omp parallel -#endif - { -#ifdef PIXELSHIFTDEV - int sumThr[2] = {0}; -#endif -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) nowait -#endif - - for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) { -#ifdef PIXELSHIFTDEV - float *greenDest = green[i + offsY]; - float *redDest = red[i + offsY]; - float *blueDest = blue[i + offsY]; -#endif - int j = winx + border - offsX; - -#ifdef PIXELSHIFTDEV - float greenDifMax[gridSize]; // Here we store the maximum differences per Column - - // green channel motion detection checks the grid around the pixel for differences in green channels - - if(detectMotion || (adaptive && checkGreen)) { - if(gridSize == 3) { - // compute maximum of differences for first two columns of 3x3 grid - greenDifMax[0] = std::max({greenDiff(psG1[i - 1][j - 1], psG2[i - 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][j - 1], psG2[ i ][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][j - 1], psG2[i + 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - greenDifMax[1] = std::max({greenDiff(psG1[i - 1][ j ], psG2[i - 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][ j ], psG2[ i ][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][ j ], psG2[i + 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - } else if(gridSize == 5) { - // compute maximum of differences for first four columns of 5x5 grid - greenDifMax[0] = std::max({greenDiff(psG1[i - 2][j - 2], psG2[i - 2][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 1][j - 2], psG2[i - 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][j - 2], psG2[ i ][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][j - 2], psG2[i + 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 2][j - 2], psG2[i + 2][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - greenDifMax[1] = std::max({greenDiff(psG1[i - 2][j - 1], psG2[i - 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 1][j - 1], psG2[i - 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][j - 1], psG2[ i ][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][j - 1], psG2[i + 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 2][j - 1], psG2[i + 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - greenDifMax[2] = std::max({greenDiff(psG1[i - 2][ j ], psG2[i - 2][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 1][ j ], psG2[i - 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][ j ], psG2[ i ][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][ j ], psG2[i + 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 2][ j ], psG2[i + 2][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - greenDifMax[3] = std::max({greenDiff(psG1[i - 2][j + 1], psG2[i - 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 1][j + 1], psG2[i - 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][j + 1], psG2[ i ][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][j + 1], psG2[i + 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 2][j + 1], psG2[i + 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - } else if(gridSize == 7) { - // compute maximum of differences for first six columns of 7x7 grid - greenDifMax[0] = std::max({greenDiff(psG1[i - 3][j - 3], psG2[i - 3][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 2][j - 3], psG2[i - 2][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 1][j - 3], psG2[i - 1][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][j - 3], psG2[ i ][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][j - 3], psG2[i + 1][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 2][j - 3], psG2[i + 2][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 3][j - 3], psG2[i + 3][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - greenDifMax[1] = std::max({greenDiff(psG1[i - 3][j - 2], psG2[i - 3][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 2][j - 2], psG2[i - 2][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 1][j - 2], psG2[i - 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][j - 2], psG2[ i ][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][j - 2], psG2[i + 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 2][j - 2], psG2[i + 2][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 3][j - 2], psG2[i + 3][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - greenDifMax[2] = std::max({greenDiff(psG1[i - 3][j - 1], psG2[i - 3][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 2][j - 1], psG2[i - 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 1][j - 1], psG2[i - 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][j - 1], psG2[ i ][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][j - 1], psG2[i + 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 2][j - 1], psG2[i + 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 3][j - 1], psG2[i + 3][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - greenDifMax[3] = std::max({greenDiff(psG1[i - 3][ j ], psG2[i - 3][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 2][ j ], psG2[i - 2][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 1][ j ], psG2[i - 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][ j ], psG2[ i ][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][ j ], psG2[i + 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 2][ j ], psG2[i + 2][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 3][ j ], psG2[i + 3][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - greenDifMax[4] = std::max({greenDiff(psG1[i - 3][j + 1], psG2[i - 3][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 2][j + 1], psG2[i - 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 1][j + 1], psG2[i - 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][j + 1], psG2[ i ][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][j + 1], psG2[i + 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 2][j + 1], psG2[i + 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 3][j + 1], psG2[i + 3][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - greenDifMax[5] = std::max({greenDiff(psG1[i - 3][j + 2], psG2[i - 3][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 2][j + 2], psG2[i - 2][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 1][j + 2], psG2[i - 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][j + 2], psG2[ i ][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][j + 2], psG2[i + 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 2][j + 2], psG2[i + 2][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 3][j + 2], psG2[i + 3][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - } - - } - - // this is the index for the last column of the grid. Obviously we have to start with gridSize - 1 - int lastIndex = gridSize - 1; - float korr = 0.f; - bool blueRow = false; + #pragma omp parallel for schedule(dynamic,16) #endif + for(int i = winy + 1; i < winh - 1; ++i) { + float *nonGreenDest0 = psRed[i]; + float *nonGreenDest1 = psBlue[i]; + float ngbright[2][4] = {{redBrightness[0], redBrightness[1], redBrightness[2], redBrightness[3]}, + {blueBrightness[0], blueBrightness[1], blueBrightness[2], blueBrightness[3]} + }; + int ng = 0; + int j = winx + 1; int c = FC(i, j); -#ifdef PIXELSHIFTDEV - if (c == 2 || ((c & 1) && FC(i, j + 1) == 2)) { + if((c + FC(i, j + 1)) == 3) { // row with blue pixels => swap destination pointers for non green pixels - blueRow = true; + std::swap(nonGreenDest0, nonGreenDest1); + ng ^= 1; } -#endif + // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop unsigned int offset = c & 1; - for(; j < winw - (border + offsX); ++j) { + for(; j < winw - 1; ++j) { + // store the non green values from the 4 frames into 2 temporary planes + nonGreenDest0[j] = (*rawDataFrames[(offset << 1) + offset])[i][j + offset] * ngbright[ng][(offset << 1) + offset]; + nonGreenDest1[j] = (*rawDataFrames[2 - offset])[i + 1][j - offset + 1] * ngbright[ng ^ 1][2 - offset]; + offset ^= 1; // 0 => 1 or 1 => 0 + } + } + + // now that the temporary planes are filled for easy access we do the motion detection + array2D psMask(winw, winh); + + int offsX = 0, offsY = 0; + + if(!bayerParams.pixelShiftMedian) { + // We have to adjust the offsets for the selected subframe we use for areas with motion + switch(frame) { + case 0: + offsX = offsY = 0; + break; + + case 1: + offsX = 0; + offsY = 1; + break; + + case 2: + offsX = offsY = 1; + break; + + case 3: + offsX = 1; + offsY = 0; + } + } + + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) { + // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop + unsigned int offset = FC(i, winx + border - offsX) & 1; + + for(int j = winx + border - offsX; j < winw - (border + offsX); ++j, offset ^= 1) { psMask[i][j] = 1.f; - offset ^= 1; // 0 => 1 or 1 => 0 - -#ifdef PIXELSHIFTDEV - if(detectMotion || (adaptive && checkGreen)) { - bool skipNext = false; - float gridMax = 0.f; -#else - if(adaptive && checkGreen) { - float gridMax; -#endif - -#ifdef PIXELSHIFTDEV - - if(gridSize < 2) { - // compute difference for current pixel and skip next pixel, that's roughly the method from dcrawps -#endif - gridMax = greenDiff(psG1[i][j], psG2[i][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion); -#ifdef PIXELSHIFTDEV - - skipNext = skip; - } else if(gridSize == 3) { - // compute maximum of differences for third column of 3x3 grid and save at position lastIndex - greenDifMax[lastIndex] = std::max({greenDiff(psG1[i - 1][j + 1], psG2[i - 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][j + 1], psG2[ i ][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][j + 1], psG2[i + 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - // calculate maximum of whole grid by calculating maximum of grid column max values - gridMax = std::max({greenDifMax[0], greenDifMax[1], greenDifMax[2]}); - // adjust index for next column - lastIndex ++; - lastIndex = lastIndex == gridSize ? 0 : lastIndex; - } else if(gridSize == 5) { - // compute maximum of differences for fifth column of 5x5 grid and save at position lastIndex - greenDifMax[lastIndex] = std::max({greenDiff(psG1[i - 2][j + 2], psG2[i - 2][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 1][j + 2], psG2[i - 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][j + 2], psG2[ i ][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][j + 2], psG2[i + 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 2][j + 2], psG2[i + 2][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion) - }); - // calculate maximum of whole grid by calculating maximum of grid column max values - gridMax = std::max({greenDifMax[0], greenDifMax[1], greenDifMax[2], greenDifMax[3], greenDifMax[4]}); - // adjust index for next column - lastIndex ++; - lastIndex = lastIndex == gridSize ? 0 : lastIndex; - } else if(gridSize == 7) { - // compute maximum of differences for 7th column of 7x7 grid and save at position lastIndex - greenDifMax[lastIndex] = std::max({greenDiff(psG1[i - 3][j + 3], psG2[i - 3][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 2][j + 3], psG2[i - 2][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i - 1][j + 3], psG2[i - 1][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[ i ][j + 3], psG2[ i ][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 1][j + 3], psG2[i + 1][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 2][j + 3], psG2[i + 2][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - greenDiff(psG1[i + 3][j + 3], psG2[i + 3][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion), - }); - // calculate maximum of whole grid by calculating maximum of grid column max values - gridMax = std::max({greenDifMax[0], greenDifMax[1], greenDifMax[2], greenDifMax[3], greenDifMax[4], greenDifMax[5], greenDifMax[6]}); - // adjust index for next column - lastIndex ++; - lastIndex = lastIndex == gridSize ? 0 : lastIndex; - } - - if(!adaptive) { - // increase motion detection dependent on brightness - korr = log2Lut[((int)(psG1[i][j] * scaleGreen)) >> 1]; - } - - if (gridMax > thresh - korr) { -#else - if (gridMax > thresh) { - -#endif - -#ifdef PIXELSHIFTDEV - sumThr[offset] ++; - - if(nOf3x3) { -#endif - psMask[i][j] = greenWeight; -#ifdef PIXELSHIFTDEV - } - - else if((offset == (frame & 1)) && checkNonGreenVertical) { - if(frame > 1) { - green[i + offsY][j + offsX] = blueRow ? psG1[i][j] : psG2[i][j]; - } else { - green[i + offsY][j + offsX] = blueRow ? psG2[i][j] : psG1[i][j];; - } - - } else { - // at least one of the tested green pixels of the grid is detected as motion - paintMotionMask(j + offsX, showMotion, (gridMax - thresh + korr) * blendFactor, showOnlyMask, greenDest, redDest, blueDest); - - if(skipNext) { - // treat the horizontally next pixel also as motion - j++; - paintMotionMask(j + offsX, showMotion, (gridMax - thresh + korr) * blendFactor, showOnlyMask, greenDest, redDest, blueDest); - } - } - -#endif - // do not set the motion pixel values. They have already been set by demosaicer or showMotion + if(checkGreen) { + if(greenDiff((*rawDataFrames[1 - offset])[i - offset + 1][j] * greenBrightness[1 - offset], (*rawDataFrames[3 - offset])[i + offset][j + 1] * greenBrightness[3 - offset], stddevFactorGreen, eperIsoGreen, nRead, prnu) > 0.f) { + psMask[i][j] = greenWeight; + // do not set the motion pixel values. They have already been set by demosaicer continue; } } - if(adaptive) { - if(checkNonGreenCross) { - // check red cross - float redTop = psRed[i - 1][ j ]; - float redLeft = psRed[ i ][j - 1]; - float redCentre = psRed[ i ][ j ]; - float redRight = psRed[ i ][j + 1]; - float redBottom = psRed[i + 1][ j ]; - float redDiff = nonGreenDiffCross(redRight, redLeft, redTop, redBottom, redCentre, clippedRed, stddevFactorRed, eperIsoRed, nRead, prnu, showMotion); + if(checkNonGreenCross) { + // check red cross + float redTop = psRed[i - 1][ j ]; + float redLeft = psRed[ i ][j - 1]; + float redCentre = psRed[ i ][ j ]; + float redRight = psRed[ i ][j + 1]; + float redBottom = psRed[i + 1][ j ]; + float redDiff = nonGreenDiffCross(redRight, redLeft, redTop, redBottom, redCentre, clippedRed, stddevFactorRed, eperIsoRed, nRead, prnu); - if(redDiff > 0.f) { -#ifdef PIXELSHIFTDEV - - if(nOf3x3) { -#endif - psMask[i][j] = redBlueWeight; -#ifdef PIXELSHIFTDEV - } else { - paintMotionMask(j + offsX, showMotion, redDiff, showOnlyMask, redDest, blueDest, greenDest); - } - -#endif - continue; - } - - // check blue cross - float blueTop = psBlue[i - 1][ j ]; - float blueLeft = psBlue[ i ][j - 1]; - float blueCentre = psBlue[ i ][ j ]; - float blueRight = psBlue[ i ][j + 1]; - float blueBottom = psBlue[i + 1][ j ]; - float blueDiff = nonGreenDiffCross(blueRight, blueLeft, blueTop, blueBottom, blueCentre, clippedBlue, stddevFactorBlue, eperIsoBlue, nRead, prnu, showMotion); - - if(blueDiff > 0.f) { -#ifdef PIXELSHIFTDEV - - if(nOf3x3) { -#endif - psMask[i][j] = redBlueWeight; -#ifdef PIXELSHIFTDEV - } else { - paintMotionMask(j + offsX, showMotion, blueDiff, showOnlyMask, blueDest, redDest, greenDest); - } - -#endif - continue; - - } + if(redDiff > 0.f) { + psMask[i][j] = redBlueWeight; + continue; } -#ifdef PIXELSHIFTDEV + // check blue cross + float blueTop = psBlue[i - 1][ j ]; + float blueLeft = psBlue[ i ][j - 1]; + float blueCentre = psBlue[ i ][ j ]; + float blueRight = psBlue[ i ][j + 1]; + float blueBottom = psBlue[i + 1][ j ]; + float blueDiff = nonGreenDiffCross(blueRight, blueLeft, blueTop, blueBottom, blueCentre, clippedBlue, stddevFactorBlue, eperIsoBlue, nRead, prnu); - if(checkNonGreenHorizontal) { - float redLeft = psRed[ i ][j - 1]; - float redCentre = psRed[ i ][ j ]; - float redRight = psRed[ i ][j + 1]; - - float redDiffLeft = redLeft - redCentre; - float redDiffRight = redRight - redCentre; - - if(redDiffLeft * redDiffRight >= 0.f) { - float redAvg = (redRight + redLeft) / 2.f; - float redDiffHor = nonGreenDiff(redCentre, redAvg, stddevFactorRed, eperIsoRed, nRead, prnu, showMotion); - - if(redDiffHor > 0.f) { - if(nOf3x3) { - psMask[i][j] = redBlueWeight; - } else { - paintMotionMask(j + offsX, showMotion, redDiffHor, showOnlyMask, redDest, blueDest, greenDest); - } - - continue; - } - } - - float blueLeft = psBlue[ i ][j - 1]; - float blueCentre = psBlue[ i ][ j ]; - float blueRight = psBlue[ i ][j + 1]; - - float blueDiffLeft = blueLeft - blueCentre; - float blueDiffRight = blueRight - blueCentre; - - if(blueDiffLeft * blueDiffRight >= 0.f) { - float blueAvg = (blueRight + blueLeft) / 2.f; - float blueDiffHor = nonGreenDiff(blueCentre, blueAvg, stddevFactorBlue, eperIsoBlue, nRead, prnu, showMotion); - - if(blueDiffHor > 0.f) { - if(nOf3x3) { - psMask[i][j] = redBlueWeight; - } else { - paintMotionMask(j + offsX, showMotion, blueDiffHor, showOnlyMask, blueDest, redDest, greenDest); - } - - continue; - } - } + if(blueDiff > 0.f) { + psMask[i][j] = redBlueWeight; + continue; } - - if(checkNonGreenVertical) { - // check red vertically - float redTop = psRed[i - 1][ j ]; - float redCentre = psRed[ i ][ j ]; - float redBottom = psRed[i + 1][ j ]; - - float redDiffTop = redTop - redCentre; - float redDiffBottom = redBottom - redCentre; - - if(redDiffTop * redDiffBottom >= 0.f) { - float redAvg = (redTop + redBottom) / 2.f; - float redDiff = nonGreenDiff(redCentre, redAvg, stddevFactorRed, eperIsoRed, nRead, prnu, showMotion); - - if(redDiff > 0.f) { - if(nOf3x3) { - psMask[i][j] = redBlueWeight; - } else { - paintMotionMask(j + offsX, showMotion, redDiff, showOnlyMask, redDest, blueDest, greenDest); - } - - continue; - } - } - - // check blue vertically - float blueTop = psBlue[i - 1][ j ]; - float blueCentre = psBlue[ i ][ j ]; - float blueBottom = psBlue[i + 1][ j ]; - - float blueDiffTop = blueTop - blueCentre; - float blueDiffBottom = blueBottom - blueCentre; - - if(blueDiffTop * blueDiffBottom >= 0.f) { - float blueAvg = (blueTop + blueBottom) / 2.f; - float blueDiff = nonGreenDiff(blueCentre, blueAvg, stddevFactorBlue, eperIsoBlue, nRead, prnu, showMotion); - - if(blueDiff > 0.f) { - if(nOf3x3) { - psMask[i][j] = redBlueWeight; - } else { - paintMotionMask(j + offsX, showMotion, blueDiff, showOnlyMask, blueDest, redDest, greenDest); - } - - continue; - } - } - } - - if(checkNonGreenAmaze) { - // check current pixel against amaze - float redCentre = psRed[ i ][ j ]; - float redAmaze = red[i + offsY][j + offsX]; - - float redDiffAmaze = nonGreenDiff(redCentre, redAmaze, stddevFactorRed, eperIsoRed, nRead, prnu, showMotion); - - if(redDiffAmaze > 0.f) { - if(nOf3x3) { - psMask[i][j] = redBlueWeight; - } else { - paintMotionMask(j + offsX, showMotion, redDiffAmaze, showOnlyMask, redDest, blueDest, greenDest); - } - - continue; - } - - float blueCentre = psBlue[ i ][ j ]; - float blueAmaze = blue[i + offsY][j + offsX]; - - float blueDiffAmaze = nonGreenDiff(blueCentre, blueAmaze, stddevFactorBlue, eperIsoBlue, nRead, prnu, showMotion); - - if(blueDiffAmaze > 0.f) { - if(nOf3x3) { - psMask[i][j] = redBlueWeight; - } else { - paintMotionMask(j + offsX, showMotion, blueDiffAmaze, showOnlyMask, blueDest, redDest, greenDest); - } - - continue; - } - } - - if(checkNonGreenCross2) { // for green amaze - float greenCentre = (psG1[ i ][ j ] + psG2[ i ][ j ]) / 2.f; - float greenAmaze = green[i + offsY][j + offsX]; - float greenDiffAmaze = nonGreenDiff(greenCentre, greenAmaze, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion); - - if(greenDiffAmaze > 0.f) { - if(nOf3x3) { - psMask[i][j] = greenWeight; - } else { - paintMotionMask(j + offsX, showMotion, greenDiffAmaze, showOnlyMask, greenDest, redDest, blueDest); - } - - continue; - } - } - - if(experimental0) { // for experiments - - } - -#endif } if(showOnlyMask) { // we want only motion mask => paint areas without motion in pure black red[i + offsY][j + offsX] = green[i + offsY][j + offsX] = blue[i + offsY][j + offsX] = 0.f; - } else if(!(adaptive && nOf3x3)) { - // no motion detected, replace the a priori demosaiced values by the pixelshift combined values - red[i + offsY][j + offsX] = psRed[i][j]; - green[i + offsY][j + offsX] = (psG1[i][j] + psG2[i][j]) / 2.f; - blue[i + offsY][j + offsX] = psBlue[i][j]; } } } -#ifdef PIXELSHIFTDEV - -#ifdef _OPENMP - #pragma omp critical -#endif - { - sum[0] += sumThr[0]; - sum[1] += sumThr[1]; - } -#endif - } - - -#ifdef PIXELSHIFTDEV - float percent0 = 100.f * sum[0] / pixelcount; - float percent1 = 100.f * sum[1] / pixelcount; - - std::cout << fileName << " : Green detections at stddev " << std::setprecision( 2 ) << bayerParams.pixelShiftStddevFactorGreen << " : Frame 1/3 : " << std::setprecision( 6 ) << sum[0] << " (" << percent0 << "%)" << " Frame 2/4 : " << sum[1] << " (" << percent1 << "%)" << std::endl; -#endif - - if(adaptive && nOf3x3) { if(blurMap) { +#ifdef _OPENMP #pragma omp parallel +#endif { gaussianBlur(psMask, psMask, winw, winh, sigma); } } - array2D mask(W, H, ARRAY2D_CLEAR_DATA); + array2D mask(winw, winh, ARRAY2D_CLEAR_DATA); +#ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) +#endif for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) { int j = winx + border - offsX; @@ -1420,18 +806,20 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA } if(holeFill) { - array2D maskInv(W, H); + array2D maskInv(winw, winh); invertMask(winx + border - offsX, winw - (border + offsX), winy + border - offsY, winh - (border + offsY), mask, maskInv); floodFill4(winx + border - offsX, winw - (border + offsX), winy + border - offsY, winh - (border + offsY), maskInv); xorMasks(winx + border - offsX, winw - (border + offsX), winy + border - offsY, winh - (border + offsY), maskInv, mask); } - +#ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) +#endif for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) { #ifdef __SSE2__ + // pow() is expensive => precalculate blend factor using SSE if(smoothTransitions) { // vfloat onev = F2V(1.f); vfloat smoothv = F2V(smoothFactor); @@ -1454,29 +842,66 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA float *redDest = red[i + offsY]; float *blueDest = blue[i + offsY]; - for(int j = winx + border - offsX; j < winw - (border + offsX); ++j) { + // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop + unsigned int offset = FC(i, winx + border - offsX) & 1; + + for(int j = winx + border - offsX; j < winw - (border + offsX); ++j, offset ^= 1) { if(mask[i][j] == 255) { - paintMotionMask(j + offsX, showMotion, 0.5f, showOnlyMask, greenDest, redDest, blueDest); + paintMotionMask(j + offsX, showMotion, showOnlyMask, greenDest, redDest, blueDest); } else if(showOnlyMask) { // we want only motion mask => paint areas without motion in pure black redDest[j + offsX] = greenDest[j + offsX] = blueDest[j + offsX] = 0.f; } else { if(smoothTransitions) { #ifdef __SSE2__ + // use precalculated blend factor const float blend = psMask[i][j]; #else const float blend = smoothFactor == 0.f ? 1.f : pow_F(std::max(psMask[i][j] - 1.f, 0.f), smoothFactor); #endif redDest[j + offsX] = intp(blend, redDest[j + offsX], psRed[i][j] ); - greenDest[j + offsX] = intp(blend, greenDest[j + offsX], (psG1[i][j] + psG2[i][j]) * 0.5f); + greenDest[j + offsX] = intp(blend, greenDest[j + offsX], ((*rawDataFrames[1 - offset])[i - offset + 1][j] * greenBrightness[1 - offset] + (*rawDataFrames[3 - offset])[i + offset][j + 1] * greenBrightness[3 - offset]) * 0.5f); blueDest[j + offsX] = intp(blend, blueDest[j + offsX], psBlue[i][j]); } else { redDest[j + offsX] = psRed[i][j]; - greenDest[j + offsX] = (psG1[i][j] + psG2[i][j]) * 0.5f; + greenDest[j + offsX] = ((*rawDataFrames[1 - offset])[i - offset + 1][j] * greenBrightness[1 - offset] + (*rawDataFrames[3 - offset])[i + offset][j + 1] * greenBrightness[3 - offset]) * 0.5f; blueDest[j + offsX] = psBlue[i][j]; } } } } + } else { + // motion detection off => combine the 4 raw frames + float ngbright[2][4] = {{redBrightness[0], redBrightness[1], redBrightness[2], redBrightness[3]}, + {blueBrightness[0], blueBrightness[1], blueBrightness[2], blueBrightness[3]} + }; +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for(int i = winy + 1; i < winh - 1; ++i) { + float *nonGreenDest0 = red[i]; + float *nonGreenDest1 = blue[i]; + int ng = 0; + int j = winx + 1; + int c = FC(i, j); + + if((c + FC(i, j + 1)) == 3) { + // row with blue pixels => swap destination pointers for non green pixels + std::swap(nonGreenDest0, nonGreenDest1); + ng ^= 1; + } + + // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop + unsigned int offset = c & 1; + + for(; j < winw - 1; ++j) { + // set red, green and blue values + green[i][j] = ((*rawDataFrames[1 - offset])[i - offset + 1][j] * greenBrightness[1 - offset] + (*rawDataFrames[3 - offset])[i + offset][j + 1] * greenBrightness[3 - offset]) * 0.5f; + nonGreenDest0[j] = (*rawDataFrames[(offset << 1) + offset])[i][j + offset] * ngbright[ng][(offset << 1) + offset]; + nonGreenDest1[j] = (*rawDataFrames[2 - offset])[i + 1][j - offset + 1] * ngbright[ng ^ 1][2 - offset]; + offset ^= 1; // 0 => 1 or 1 => 0 + } + } } if(plistener) { diff --git a/rtengine/profilestore.cc b/rtengine/profilestore.cc index 984ab9423..12c1cca5c 100644 --- a/rtengine/profilestore.cc +++ b/rtengine/profilestore.cc @@ -46,7 +46,7 @@ bool ProfileStore::init (bool loadAll) this->loadAll = loadAll; - if (storeState == STORESTATE_NOTINITIALIZED && loadAll) { + if ((storeState == STORESTATE_NOTINITIALIZED || storeState == STORESTATE_DIRTY) && loadAll) { storeState = STORESTATE_BEINGINITIALIZED; _parseProfiles (); storeState = STORESTATE_INITIALIZED; @@ -85,7 +85,7 @@ ProfileStore::~ProfileStore () * This method will scan the directory tree again and update the profile list. When finished, * the listeners will be called in order to update with the new list */ -void ProfileStore::parseProfiles () +void ProfileStore::parseProfilesOnce () { for (auto listener : listeners) { @@ -100,6 +100,13 @@ void ProfileStore::parseProfiles () } } +void ProfileStore::parseProfiles () +{ + + storeState = STORESTATE_DIRTY; + parseProfilesOnce (); +} + void ProfileStore::_parseProfiles () { // clear loaded profiles @@ -272,7 +279,7 @@ const ProfileStoreEntry* ProfileStore::findEntryFromFullPathU (Glib::ustring pat } if (storeState == STORESTATE_NOTINITIALIZED) { - parseProfiles(); + parseProfilesOnce(); } if (path == DEFPROFILE_INTERNAL || path == DEFPROFILE_DYNAMIC) { @@ -340,7 +347,7 @@ const PartialProfile* ProfileStore::getProfile (Glib::ustring path) { if (storeState == STORESTATE_NOTINITIALIZED) { - parseProfiles(); + parseProfilesOnce(); } const ProfileStoreEntry *pse = findEntryFromFullPath (path); @@ -356,7 +363,7 @@ const PartialProfile* ProfileStore::getProfile (const ProfileStoreEntry* entry) { if (storeState == STORESTATE_NOTINITIALIZED) { - parseProfiles(); + parseProfilesOnce(); } MyMutex::MyLock lock (parseMutex); @@ -387,7 +394,7 @@ const std::vector* ProfileStore::getFileList () { if (storeState == STORESTATE_NOTINITIALIZED) { - parseProfiles(); + parseProfilesOnce(); } parseMutex.lock(); @@ -493,7 +500,7 @@ void ProfileStore::dumpFolderList() PartialProfile *ProfileStore::loadDynamicProfile (const ImageMetaData *im) { if (storeState == STORESTATE_NOTINITIALIZED) { - parseProfiles(); + parseProfilesOnce(); } PartialProfile *ret = new PartialProfile (true, true); diff --git a/rtengine/profilestore.h b/rtengine/profilestore.h index c6627b4c8..372dbfc3b 100644 --- a/rtengine/profilestore.h +++ b/rtengine/profilestore.h @@ -106,6 +106,7 @@ class ProfileStore : public rtengine::NonCopyable, public DynamicProfileRules STORESTATE_LIGHTWEIGHT, STORESTATE_BEINGINITIALIZED, STORESTATE_INITIALIZED, + STORESTATE_DIRTY, STORESTATE_DELETED } StoreState; @@ -153,6 +154,11 @@ private: * if false, only one root directory is expected */ bool parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath, Glib::ustring& currDir, unsigned int parentId, unsigned char level, bool displayLevel0); + /** @brief Will parse the profiles's dir only once. Subsequent call to this function will be ignored unless the profile list has been cleared + */ + void parseProfilesOnce (); + /** @brief Will scan the directory to fill the profile list + */ void _parseProfiles (); void clearFileList (); void clearProfileList (); diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index c0fd1f576..7b6ee8782 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -39,6 +39,7 @@ RawImage::~RawImage() { if(ifp) { fclose(ifp); + ifp = nullptr; } if( image ) { @@ -410,7 +411,11 @@ int RawImage::loadRaw (bool loadData, unsigned int imageNum, bool closeFile, Pro verbose = settings->verbose; oprof = nullptr; - ifp = gfopen (ifname); // Maps to either file map or direct fopen + if(!ifp) { + ifp = gfopen (ifname); // Maps to either file map or direct fopen + } else { + fseek (ifp, 0, SEEK_SET); + } if (!ifp) { return 3; @@ -547,8 +552,8 @@ int RawImage::loadRaw (bool loadData, unsigned int imageNum, bool closeFile, Pro crop_masked_pixels(); free (raw_image); raw_image = nullptr; - } else { - if (is_foveon && cc && cc->has_rawCrop()) { // foveon images + } else { + if (get_maker() == "Sigma" && cc && cc->has_rawCrop()) { // foveon images int lm, tm, w, h; cc->get_rawCrop(lm, tm, w, h); left_margin = lm; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index a84915ed3..0c15d69ec 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -4621,13 +4621,13 @@ void RawImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) } } else if (ri->get_colors() == 1) { for (int j = start; j < end; j++) { - tmphistogram[ (int) (refwb_red * rawData[i][j])]++; + tmphistogram[(int)(refwb[0] * rawData[i][j])]++; } } else { for (int j = start; j < end; j++) { - tmphistogram[CLIP ((int) (refwb_red * rawData[i][3 * j + 0]))]++; - tmphistogram[CLIP ((int) (refwb_green * rawData[i][3 * j + 1]))] += 2; - tmphistogram[CLIP ((int) (refwb_blue * rawData[i][3 * j + 2]))]++; + tmphistogram[(int)(refwb[0] * rawData[i][3 * j + 0])]++; + tmphistogram[(int)(refwb[1] * rawData[i][3 * j + 1])]++; + tmphistogram[(int)(refwb[2] * rawData[i][3 * j + 2])]++; } } } diff --git a/rtengine/rt_math.h b/rtengine/rt_math.h index 6e1138476..17a292618 100644 --- a/rtengine/rt_math.h +++ b/rtengine/rt_math.h @@ -87,6 +87,13 @@ constexpr T CLIP(const T& a) return LIM(a, static_cast(0), static_cast(MAXVAL)); } +template +constexpr T SGN(const T& a) +{ + // returns -1 for a < 0, 0 for a = 0 and +1 for a > 0 + return (T(0) < a) - (a < T(0)); +} + template constexpr T intp(T a, T b, T c) { diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 6e6177278..bf6e96549 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -544,20 +544,32 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati int left_margin = ri->get_leftmargin(); firstgreen += left_margin; int top_margin = ri->get_topmargin(); + int wmax = tmpw; + int hmax = tmph; if(ri->get_maker() == "Sigma" && ri->DNGVERSION()) { // Hack to prevent sigma dng files from crashing - tmpw = (width - 2 - left_margin) / hskip; - tmph = (height - 2 - top_margin) / vskip; + wmax = (width - 2 - left_margin) / hskip; + hmax = (height - 2 - top_margin) / vskip; } - for (int row = 1 + top_margin, y = 0; row < iheight + top_margin - 1 && y < tmph; row += vskip, y++) { + int y = 0; + for (int row = 1 + top_margin; row < iheight + top_margin - 1 && y < hmax; row += vskip, y++) { rofs = row * iwidth; - for (int col = firstgreen, x = 0; col < iwidth + left_margin - 1 && x < tmpw; col += hskip, x++) { + int x = 0; + for (int col = firstgreen; col < iwidth + left_margin - 1 && x < wmax; col += hskip, x++) { int ofs = rofs + col; tmpImg->r(y, x) = image[ofs][0]; tmpImg->g(y, x) = image[ofs][1]; tmpImg->b(y, x) = image[ofs][2]; } + for (; x < tmpw; ++x) { + tmpImg->r(y, x) = tmpImg->g(y, x) = tmpImg->b(y, x) = 0; + } + } + for (; y < tmph; ++y) { + for (int x = 0; x < tmpw; ++x) { + tmpImg->r(y, x) = tmpImg->g(y, x) = tmpImg->b(y, x) = 0; + } } } } diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index 78f1a8976..3a37996a0 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -102,7 +102,7 @@ BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) #else outdirFolder = Gtk::manage (new MyFileChooserButton (M("PREFERENCES_OUTDIRFOLDER"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER)); hb3->pack_start (*outdirFolder); - outdirFolder->signal_current_folder_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::pathFolderChanged)); + outdirFolder->signal_selection_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::pathFolderChanged)); outdirFolder->set_tooltip_markup (M("PREFERENCES_OUTDIRFOLDERHINT")); if (Glib::file_test (options.savePathFolder, Glib::FILE_TEST_IS_DIR)) { diff --git a/rtgui/colorappearance.cc b/rtgui/colorappearance.cc index cdcfb10f2..59bdb4b31 100644 --- a/rtgui/colorappearance.cc +++ b/rtgui/colorappearance.cc @@ -24,12 +24,12 @@ using namespace rtengine; using namespace rtengine::procparams; -ColorAppearance::ColorAppearance () : FoldableToolPanel(this, "colorappearance", M("TP_COLORAPP_LABEL"), false, true) +ColorAppearance::ColorAppearance () : FoldableToolPanel (this, "colorappearance", M ("TP_COLORAPP_LABEL"), false, true) { - CurveListener::setMulti(true); + CurveListener::setMulti (true); std::vector milestones; - milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + milestones.push_back ( GradientMilestone (0., 0., 0., 0.) ); + milestones.push_back ( GradientMilestone (1., 1., 1., 1.) ); // ------------------------ Process #1: Converting to CIECAM @@ -40,51 +40,51 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel(this, "colorappearance", // Vertical box container for the content of the Process 1 frame Gtk::VBox *p1VBox; - p1Frame = Gtk::manage (new Gtk::Frame(M("TP_COLORAPP_LABEL_SCENE")) ); - p1Frame->set_label_align(0.025, 0.5); + p1Frame = Gtk::manage (new Gtk::Frame (M ("TP_COLORAPP_LABEL_SCENE")) ); + p1Frame->set_label_align (0.025, 0.5); p1VBox = Gtk::manage ( new Gtk::VBox()); - p1VBox->set_spacing(2); + p1VBox->set_spacing (2); - degree = Gtk::manage (new Adjuster (M("TP_COLORAPP_CIECAT_DEGREE"), 0., 100., 1., 100.)); + degree = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CIECAT_DEGREE"), 0., 100., 1., 100.)); if (degree->delay < options.adjusterMaxDelay) { degree->delay = options.adjusterMaxDelay; } degree->throwOnButtonRelease(); - degree->addAutoButton(M("TP_COLORAPP_DEGREE_AUTO_TOOLTIP")); - degree->set_tooltip_markup (M("TP_COLORAPP_DEGREE_TOOLTIP")); + degree->addAutoButton (M ("TP_COLORAPP_DEGREE_AUTO_TOOLTIP")); + degree->set_tooltip_markup (M ("TP_COLORAPP_DEGREE_TOOLTIP")); p1VBox->pack_start (*degree); - surrsource = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_SURSOURCE"))); - surrsource->set_tooltip_markup (M("TP_COLORAPP_SURSOURCE_TOOLTIP")); + surrsource = Gtk::manage (new Gtk::CheckButton (M ("TP_COLORAPP_SURSOURCE"))); + surrsource->set_tooltip_markup (M ("TP_COLORAPP_SURSOURCE_TOOLTIP")); p1VBox->pack_start (*surrsource, Gtk::PACK_SHRINK); Gtk::HBox* wbmHBox = Gtk::manage (new Gtk::HBox ()); wbmHBox->set_spacing (2); - wbmHBox->set_tooltip_markup (M("TP_COLORAPP_MODEL_TOOLTIP")); - Gtk::Label* wbmLab = Gtk::manage (new Gtk::Label (M("TP_COLORAPP_MODEL") + ":")); + wbmHBox->set_tooltip_markup (M ("TP_COLORAPP_MODEL_TOOLTIP")); + Gtk::Label* wbmLab = Gtk::manage (new Gtk::Label (M ("TP_COLORAPP_MODEL") + ":")); wbmHBox->pack_start (*wbmLab, Gtk::PACK_SHRINK); wbmodel = Gtk::manage (new MyComboBoxText ()); - wbmodel->append (M("TP_COLORAPP_WBRT")); - wbmodel->append (M("TP_COLORAPP_WBCAM")); + wbmodel->append (M ("TP_COLORAPP_WBRT")); + wbmodel->append (M ("TP_COLORAPP_WBCAM")); wbmodel->set_active (0); wbmHBox->pack_start (*wbmodel); p1VBox->pack_start (*wbmHBox); - adapscen = Gtk::manage (new Adjuster (M("TP_COLORAPP_ADAPTSCENE"), 0.001, 16384., 0.001, 2000.));// EV -7 ==> EV 17 + adapscen = Gtk::manage (new Adjuster (M ("TP_COLORAPP_ADAPTSCENE"), 0.001, 16384., 0.001, 2000.)); // EV -7 ==> EV 17 if (adapscen->delay < options.adjusterMaxDelay) { adapscen->delay = options.adjusterMaxDelay; } adapscen->throwOnButtonRelease(); - adapscen->addAutoButton(M("TP_COLORAPP_ADAP_AUTO_TOOLTIP")); - adapscen->set_tooltip_markup (M("TP_COLORAPP_ADAPTSCENE_TOOLTIP")); + adapscen->addAutoButton (M ("TP_COLORAPP_ADAP_AUTO_TOOLTIP")); + adapscen->set_tooltip_markup (M ("TP_COLORAPP_ADAPTSCENE_TOOLTIP")); p1VBox->pack_start (*adapscen); - p1Frame->add(*p1VBox); + p1Frame->add (*p1VBox); pack_start (*p1Frame, Gtk::PACK_EXPAND_WIDGET, 4); @@ -96,123 +96,123 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel(this, "colorappearance", // Vertical box container for the content of the Process 1 frame Gtk::VBox *p2VBox; - p2Frame = Gtk::manage (new Gtk::Frame(M("TP_COLORAPP_LABEL_CAM02")) ); - p2Frame->set_label_align(0.025, 0.5); + p2Frame = Gtk::manage (new Gtk::Frame (M ("TP_COLORAPP_LABEL_CAM02")) ); + p2Frame->set_label_align (0.025, 0.5); p2VBox = Gtk::manage ( new Gtk::VBox()); - p2VBox->set_spacing(2); + p2VBox->set_spacing (2); Gtk::HBox* alHBox = Gtk::manage (new Gtk::HBox ()); alHBox->set_spacing (2); - alHBox->set_tooltip_markup (M("TP_COLORAPP_ALGO_TOOLTIP")); - Gtk::Label* alLabel = Gtk::manage (new Gtk::Label (M("TP_COLORAPP_ALGO") + ":")); + alHBox->set_tooltip_markup (M ("TP_COLORAPP_ALGO_TOOLTIP")); + Gtk::Label* alLabel = Gtk::manage (new Gtk::Label (M ("TP_COLORAPP_ALGO") + ":")); alHBox->pack_start (*alLabel, Gtk::PACK_SHRINK); algo = Gtk::manage (new MyComboBoxText ()); - algo->append (M("TP_COLORAPP_ALGO_JC")); - algo->append (M("TP_COLORAPP_ALGO_JS")); - algo->append (M("TP_COLORAPP_ALGO_QM")); - algo->append (M("TP_COLORAPP_ALGO_ALL")); + algo->append (M ("TP_COLORAPP_ALGO_JC")); + algo->append (M ("TP_COLORAPP_ALGO_JS")); + algo->append (M ("TP_COLORAPP_ALGO_QM")); + algo->append (M ("TP_COLORAPP_ALGO_ALL")); algo->set_active (0); alHBox->pack_start (*algo); p2VBox->pack_start (*alHBox); p2VBox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET, 4); - jlight = Gtk::manage (new Adjuster (M("TP_COLORAPP_LIGHT"), -100.0, 100.0, 0.1, 0.)); + jlight = Gtk::manage (new Adjuster (M ("TP_COLORAPP_LIGHT"), -100.0, 100.0, 0.1, 0.)); if (jlight->delay < options.adjusterMaxDelay) { jlight->delay = options.adjusterMaxDelay; } jlight->throwOnButtonRelease(); - jlight->set_tooltip_markup (M("TP_COLORAPP_LIGHT_TOOLTIP")); + jlight->set_tooltip_markup (M ("TP_COLORAPP_LIGHT_TOOLTIP")); p2VBox->pack_start (*jlight); - qbright = Gtk::manage (new Adjuster (M("TP_COLORAPP_BRIGHT"), -100.0, 100.0, 0.1, 0.)); + qbright = Gtk::manage (new Adjuster (M ("TP_COLORAPP_BRIGHT"), -100.0, 100.0, 0.1, 0.)); if (qbright->delay < options.adjusterMaxDelay) { qbright->delay = options.adjusterMaxDelay; } qbright->throwOnButtonRelease(); - qbright->set_tooltip_markup (M("TP_COLORAPP_BRIGHT_TOOLTIP")); + qbright->set_tooltip_markup (M ("TP_COLORAPP_BRIGHT_TOOLTIP")); p2VBox->pack_start (*qbright); - chroma = Gtk::manage (new Adjuster (M("TP_COLORAPP_CHROMA"), -100.0, 100.0, 0.1, 0.)); + chroma = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CHROMA"), -100.0, 100.0, 0.1, 0.)); if (chroma->delay < options.adjusterMaxDelay) { chroma->delay = options.adjusterMaxDelay; } chroma->throwOnButtonRelease(); - chroma->set_tooltip_markup (M("TP_COLORAPP_CHROMA_TOOLTIP")); + chroma->set_tooltip_markup (M ("TP_COLORAPP_CHROMA_TOOLTIP")); p2VBox->pack_start (*chroma); - schroma = Gtk::manage (new Adjuster (M("TP_COLORAPP_CHROMA_S"), -100.0, 100.0, 0.1, 0.)); + schroma = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CHROMA_S"), -100.0, 100.0, 0.1, 0.)); if (schroma->delay < options.adjusterMaxDelay) { schroma->delay = options.adjusterMaxDelay; } schroma->throwOnButtonRelease(); - schroma->set_tooltip_markup (M("TP_COLORAPP_CHROMA_S_TOOLTIP")); + schroma->set_tooltip_markup (M ("TP_COLORAPP_CHROMA_S_TOOLTIP")); p2VBox->pack_start (*schroma); - mchroma = Gtk::manage (new Adjuster (M("TP_COLORAPP_CHROMA_M"), -100.0, 100.0, 0.1, 0.)); + mchroma = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CHROMA_M"), -100.0, 100.0, 0.1, 0.)); if (mchroma->delay < options.adjusterMaxDelay) { mchroma->delay = options.adjusterMaxDelay; } mchroma->throwOnButtonRelease(); - mchroma->set_tooltip_markup (M("TP_COLORAPP_CHROMA_M_TOOLTIP")); + mchroma->set_tooltip_markup (M ("TP_COLORAPP_CHROMA_M_TOOLTIP")); p2VBox->pack_start (*mchroma); - rstprotection = Gtk::manage ( new Adjuster (M("TP_COLORAPP_RSTPRO"), 0., 100., 0.1, 0.) ); + rstprotection = Gtk::manage ( new Adjuster (M ("TP_COLORAPP_RSTPRO"), 0., 100., 0.1, 0.) ); if (rstprotection->delay < options.adjusterMaxDelay) { rstprotection->delay = options.adjusterMaxDelay; } rstprotection->throwOnButtonRelease(); - rstprotection->set_tooltip_markup (M("TP_COLORAPP_RSTPRO_TOOLTIP")); + rstprotection->set_tooltip_markup (M ("TP_COLORAPP_RSTPRO_TOOLTIP")); p2VBox->pack_start (*rstprotection); - contrast = Gtk::manage (new Adjuster (M("TP_COLORAPP_CONTRAST"), -100.0, 100.0, 0.1, 0.)); + contrast = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CONTRAST"), -100.0, 100.0, 0.1, 0.)); if (contrast->delay < options.adjusterMaxDelay) { contrast->delay = options.adjusterMaxDelay; } contrast->throwOnButtonRelease(); - contrast->set_tooltip_markup (M("TP_COLORAPP_CONTRAST_TOOLTIP")); + contrast->set_tooltip_markup (M ("TP_COLORAPP_CONTRAST_TOOLTIP")); p2VBox->pack_start (*contrast); - qcontrast = Gtk::manage (new Adjuster (M("TP_COLORAPP_CONTRAST_Q"), -100.0, 100.0, 0.1, 0.)); + qcontrast = Gtk::manage (new Adjuster (M ("TP_COLORAPP_CONTRAST_Q"), -100.0, 100.0, 0.1, 0.)); if (qcontrast->delay < options.adjusterMaxDelay) { qcontrast->delay = options.adjusterMaxDelay; } qcontrast->throwOnButtonRelease(); - qcontrast->set_tooltip_markup (M("TP_COLORAPP_CONTRAST_Q_TOOLTIP")); + qcontrast->set_tooltip_markup (M ("TP_COLORAPP_CONTRAST_Q_TOOLTIP")); p2VBox->pack_start (*qcontrast); - colorh = Gtk::manage (new Adjuster (M("TP_COLORAPP_HUE"), -100.0, 100.0, 0.1, 0.)); + colorh = Gtk::manage (new Adjuster (M ("TP_COLORAPP_HUE"), -100.0, 100.0, 0.1, 0.)); if (colorh->delay < options.adjusterMaxDelay) { colorh->delay = options.adjusterMaxDelay; } colorh->throwOnButtonRelease(); - colorh->set_tooltip_markup (M("TP_COLORAPP_HUE_TOOLTIP")); + colorh->set_tooltip_markup (M ("TP_COLORAPP_HUE_TOOLTIP")); p2VBox->pack_start (*colorh); - tonecie = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_TONECIE"))); - tonecie->set_tooltip_markup (M("TP_COLORAPP_TONECIE_TOOLTIP")); - tonecieconn = tonecie->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::tonecie_toggled) ); + tonecie = Gtk::manage (new Gtk::CheckButton (M ("TP_COLORAPP_TONECIE"))); + tonecie->set_tooltip_markup (M ("TP_COLORAPP_TONECIE_TOOLTIP")); + tonecieconn = tonecie->signal_toggled().connect ( sigc::mem_fun (*this, &ColorAppearance::tonecie_toggled) ); p2VBox->pack_start (*tonecie); /* sharpcie = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_SHARPCIE"))); @@ -223,52 +223,52 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel(this, "colorappearance", p2VBox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET, 4); toneCurveMode = Gtk::manage (new MyComboBoxText ()); - toneCurveMode->append (M("TP_COLORAPP_TCMODE_LIGHTNESS")); - toneCurveMode->append (M("TP_COLORAPP_TCMODE_BRIGHTNESS")); + toneCurveMode->append (M ("TP_COLORAPP_TCMODE_LIGHTNESS")); + toneCurveMode->append (M ("TP_COLORAPP_TCMODE_BRIGHTNESS")); toneCurveMode->set_active (0); - toneCurveMode->set_tooltip_text(M("TP_COLORAPP_TCMODE_LABEL1")); + toneCurveMode->set_tooltip_text (M ("TP_COLORAPP_TCMODE_LABEL1")); - curveEditorG = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_COLORAPP_CURVEEDITOR1")); + curveEditorG = new CurveEditorGroup (options.lastToneCurvesDir, M ("TP_COLORAPP_CURVEEDITOR1")); curveEditorG->setCurveListener (this); - curveEditorG->setTooltip(M("TP_COLORAPP_CURVEEDITOR1_TOOLTIP")); + curveEditorG->setTooltip (M ("TP_COLORAPP_CURVEEDITOR1_TOOLTIP")); - shape = static_cast(curveEditorG->addCurve(CT_Diagonal, "", toneCurveMode)); + shape = static_cast (curveEditorG->addCurve (CT_Diagonal, "", toneCurveMode)); - tcmodeconn = toneCurveMode->signal_changed().connect( sigc::mem_fun(*this, &ColorAppearance::curveMode1Changed), true ); + tcmodeconn = toneCurveMode->signal_changed().connect ( sigc::mem_fun (*this, &ColorAppearance::curveMode1Changed), true ); toneCurveMode2 = Gtk::manage (new MyComboBoxText ()); - toneCurveMode2->append (M("TP_COLORAPP_TCMODE_LIGHTNESS")); - toneCurveMode2->append (M("TP_COLORAPP_TCMODE_BRIGHTNESS")); + toneCurveMode2->append (M ("TP_COLORAPP_TCMODE_LIGHTNESS")); + toneCurveMode2->append (M ("TP_COLORAPP_TCMODE_BRIGHTNESS")); toneCurveMode2->set_active (0); - toneCurveMode2->set_tooltip_text(M("TP_COLORAPP_TCMODE_LABEL2")); + toneCurveMode2->set_tooltip_text (M ("TP_COLORAPP_TCMODE_LABEL2")); - curveEditorG2 = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_COLORAPP_CURVEEDITOR2")); + curveEditorG2 = new CurveEditorGroup (options.lastToneCurvesDir, M ("TP_COLORAPP_CURVEEDITOR2")); curveEditorG2->setCurveListener (this); - shape2 = static_cast(curveEditorG2->addCurve(CT_Diagonal, "", toneCurveMode2)); + shape2 = static_cast (curveEditorG2->addCurve (CT_Diagonal, "", toneCurveMode2)); - tcmode2conn = toneCurveMode2->signal_changed().connect( sigc::mem_fun(*this, &ColorAppearance::curveMode2Changed), true ); + tcmode2conn = toneCurveMode2->signal_changed().connect ( sigc::mem_fun (*this, &ColorAppearance::curveMode2Changed), true ); toneCurveMode3 = Gtk::manage (new MyComboBoxText ()); - toneCurveMode3->append (M("TP_COLORAPP_TCMODE_CHROMA")); - toneCurveMode3->append (M("TP_COLORAPP_TCMODE_SATUR")); - toneCurveMode3->append (M("TP_COLORAPP_TCMODE_COLORF")); + toneCurveMode3->append (M ("TP_COLORAPP_TCMODE_CHROMA")); + toneCurveMode3->append (M ("TP_COLORAPP_TCMODE_SATUR")); + toneCurveMode3->append (M ("TP_COLORAPP_TCMODE_COLORF")); toneCurveMode3->set_active (0); - toneCurveMode3->set_tooltip_text(M("TP_COLORAPP_TCMODE_LABEL3")); + toneCurveMode3->set_tooltip_text (M ("TP_COLORAPP_TCMODE_LABEL3")); - curveEditorG3 = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_COLORAPP_CURVEEDITOR3")); + curveEditorG3 = new CurveEditorGroup (options.lastToneCurvesDir, M ("TP_COLORAPP_CURVEEDITOR3")); curveEditorG3->setCurveListener (this); - shape3 = static_cast(curveEditorG3->addCurve(CT_Diagonal, "", toneCurveMode3)); - shape3->setRangeLabels( - M("TP_LABCURVE_CURVEEDITOR_CC_RANGE1"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE2"), - M("TP_LABCURVE_CURVEEDITOR_CC_RANGE3"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE4") + shape3 = static_cast (curveEditorG3->addCurve (CT_Diagonal, "", toneCurveMode3)); + shape3->setRangeLabels ( + M ("TP_LABCURVE_CURVEEDITOR_CC_RANGE1"), M ("TP_LABCURVE_CURVEEDITOR_CC_RANGE2"), + M ("TP_LABCURVE_CURVEEDITOR_CC_RANGE3"), M ("TP_LABCURVE_CURVEEDITOR_CC_RANGE4") ); - shape3->setBottomBarColorProvider(this, 1); - shape3->setLeftBarColorProvider(this, 1); - shape3->setRangeDefaultMilestones(0.05, 0.2, 0.58); + shape3->setBottomBarColorProvider (this, 1); + shape3->setLeftBarColorProvider (this, 1); + shape3->setRangeDefaultMilestones (0.05, 0.2, 0.58); // shape3->setBottomBarColorProvider(this, 2); @@ -278,51 +278,51 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel(this, "colorappearance", // The milestones are still the same than those define above //milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); //milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); - shape->setBottomBarBgGradient(milestones); - shape->setLeftBarBgGradient(milestones); - shape2->setBottomBarBgGradient(milestones); - shape2->setLeftBarBgGradient(milestones); + shape->setBottomBarBgGradient (milestones); + shape->setLeftBarBgGradient (milestones); + shape2->setBottomBarBgGradient (milestones); + shape2->setLeftBarBgGradient (milestones); std::vector shape3Milestones; float R, G, B; for (int i = 0; i < 7; i++) { - float x = float(i) * (1.0f / 6.0); - Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); - shape3Milestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); + float x = float (i) * (1.0f / 6.0); + Color::hsv2rgb01 (x, 0.5f, 0.5f, R, G, B); + shape3Milestones.push_back ( GradientMilestone (double (x), double (R), double (G), double (B)) ); } - shape3->setBottomBarBgGradient(shape3Milestones); - shape3->setLeftBarBgGradient(shape3Milestones); + shape3->setBottomBarBgGradient (shape3Milestones); + shape3->setLeftBarBgGradient (shape3Milestones); - shape3->setRangeDefaultMilestones(0.05, 0.2, 0.58); + shape3->setRangeDefaultMilestones (0.05, 0.2, 0.58); curveEditorG->curveListComplete(); curveEditorG2->curveListComplete(); - curveEditorG2->setTooltip(M("TP_COLORAPP_CURVEEDITOR2_TOOLTIP")); + curveEditorG2->setTooltip (M ("TP_COLORAPP_CURVEEDITOR2_TOOLTIP")); curveEditorG3->curveListComplete(); - curveEditorG3->setTooltip(M("TP_COLORAPP_CURVEEDITOR3_TOOLTIP")); - tcmode3conn = toneCurveMode3->signal_changed().connect( sigc::mem_fun(*this, &ColorAppearance::curveMode3Changed), true ); + curveEditorG3->setTooltip (M ("TP_COLORAPP_CURVEEDITOR3_TOOLTIP")); + tcmode3conn = toneCurveMode3->signal_changed().connect ( sigc::mem_fun (*this, &ColorAppearance::curveMode3Changed), true ); - p2VBox->pack_start( *curveEditorG, Gtk::PACK_SHRINK, 2); - p2VBox->pack_start( *curveEditorG2, Gtk::PACK_SHRINK, 2); - p2VBox->pack_start( *curveEditorG3, Gtk::PACK_SHRINK, 2); + p2VBox->pack_start ( *curveEditorG, Gtk::PACK_SHRINK, 2); + p2VBox->pack_start ( *curveEditorG2, Gtk::PACK_SHRINK, 2); + p2VBox->pack_start ( *curveEditorG3, Gtk::PACK_SHRINK, 2); // ------------------------ Choice CIECAM data - datacie = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_DATACIE"))); - datacie->set_tooltip_markup (M("TP_COLORAPP_DATACIE_TOOLTIP")); - datacieconn = datacie->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::datacie_toggled) ); + datacie = Gtk::manage (new Gtk::CheckButton (M ("TP_COLORAPP_DATACIE"))); + datacie->set_tooltip_markup (M ("TP_COLORAPP_DATACIE_TOOLTIP")); + datacieconn = datacie->signal_toggled().connect ( sigc::mem_fun (*this, &ColorAppearance::datacie_toggled) ); p2VBox->pack_start (*datacie); //------------------------- - p2Frame->add(*p2VBox); + p2Frame->add (*p2VBox); pack_start (*p2Frame, Gtk::PACK_EXPAND_WIDGET, 4); @@ -337,46 +337,46 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel(this, "colorappearance", // Vertical box container for the content of the Process 3 frame Gtk::VBox *p3VBox; - p3Frame = Gtk::manage (new Gtk::Frame(M("TP_COLORAPP_LABEL_VIEWING")) ); // "Editing viewing conditions" ??? - p3Frame->set_label_align(0.025, 0.5); + p3Frame = Gtk::manage (new Gtk::Frame (M ("TP_COLORAPP_LABEL_VIEWING")) ); // "Editing viewing conditions" ??? + p3Frame->set_label_align (0.025, 0.5); p3VBox = Gtk::manage ( new Gtk::VBox()); - p3VBox->set_spacing(2); + p3VBox->set_spacing (2); - adaplum = Gtk::manage (new Adjuster (M("TP_COLORAPP_ADAPTVIEWING"), 0.1, 1000., 0.1, 16.)); + adaplum = Gtk::manage (new Adjuster (M ("TP_COLORAPP_ADAPTVIEWING"), 0.1, 1000., 0.1, 16.)); if (adaplum->delay < options.adjusterMaxDelay) { adaplum->delay = options.adjusterMaxDelay; } adaplum->throwOnButtonRelease(); - adaplum->set_tooltip_markup (M("TP_COLORAPP_ADAPTVIEWING_TOOLTIP")); + adaplum->set_tooltip_markup (M ("TP_COLORAPP_ADAPTVIEWING_TOOLTIP")); p3VBox->pack_start (*adaplum); Gtk::HBox* surrHBox = Gtk::manage (new Gtk::HBox ()); surrHBox->set_spacing (2); - surrHBox->set_tooltip_markup(M("TP_COLORAPP_SURROUND_TOOLTIP")); - Gtk::Label* surrLabel = Gtk::manage (new Gtk::Label (M("TP_COLORAPP_SURROUND") + ":")); + surrHBox->set_tooltip_markup (M ("TP_COLORAPP_SURROUND_TOOLTIP")); + Gtk::Label* surrLabel = Gtk::manage (new Gtk::Label (M ("TP_COLORAPP_SURROUND") + ":")); surrHBox->pack_start (*surrLabel, Gtk::PACK_SHRINK); surround = Gtk::manage (new MyComboBoxText ()); - surround->append (M("TP_COLORAPP_SURROUND_AVER")); - surround->append (M("TP_COLORAPP_SURROUND_DIM")); - surround->append (M("TP_COLORAPP_SURROUND_DARK")); - surround->append (M("TP_COLORAPP_SURROUND_EXDARK")); + surround->append (M ("TP_COLORAPP_SURROUND_AVER")); + surround->append (M ("TP_COLORAPP_SURROUND_DIM")); + surround->append (M ("TP_COLORAPP_SURROUND_DARK")); + surround->append (M ("TP_COLORAPP_SURROUND_EXDARK")); surround->set_active (1); surrHBox->pack_start (*surround); p3VBox->pack_start (*surrHBox); - p3Frame->add(*p3VBox); + p3Frame->add (*p3VBox); pack_start (*p3Frame, Gtk::PACK_EXPAND_WIDGET, 4); // ------------------------ Lab Gamut control - gamut = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_GAMUT"))); - gamut->set_tooltip_markup (M("TP_COLORAPP_GAMUT_TOOLTIP")); - gamutconn = gamut->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::gamut_toggled) ); + gamut = Gtk::manage (new Gtk::CheckButton (M ("TP_COLORAPP_GAMUT"))); + gamut->set_tooltip_markup (M ("TP_COLORAPP_GAMUT_TOOLTIP")); + gamutconn = gamut->signal_toggled().connect ( sigc::mem_fun (*this, &ColorAppearance::gamut_toggled) ); pack_start (*gamut, Gtk::PACK_SHRINK); // ------------------------ Bad pixel control @@ -387,23 +387,23 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel(this, "colorappearance", badpixconn = badpix->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::badpix_toggled) ); pack_start (*badpix, Gtk::PACK_SHRINK); */ - badpixsl = Gtk::manage (new Adjuster (M("TP_COLORAPP_BADPIXSL"), 0, 2, 1, 0)); + badpixsl = Gtk::manage (new Adjuster (M ("TP_COLORAPP_BADPIXSL"), 0, 2, 1, 0)); if (badpixsl->delay < options.adjusterMaxDelay) { badpixsl->delay = options.adjusterMaxDelay; } badpixsl->throwOnButtonRelease(); - badpixsl->set_tooltip_markup (M("TP_COLORAPP_BADPIXSL_TOOLTIP")); + badpixsl->set_tooltip_markup (M ("TP_COLORAPP_BADPIXSL_TOOLTIP")); pack_start (*badpixsl, Gtk::PACK_SHRINK); // ------------------------ Listening events - surrconn = surrsource->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::surrsource_toggled) ); - wbmodelconn = wbmodel->signal_changed().connect ( sigc::mem_fun(*this, &ColorAppearance::wbmodelChanged) ); - algoconn = algo->signal_changed().connect ( sigc::mem_fun(*this, &ColorAppearance::algoChanged) ); - surroundconn = surround->signal_changed().connect ( sigc::mem_fun(*this, &ColorAppearance::surroundChanged) ); + surrconn = surrsource->signal_toggled().connect ( sigc::mem_fun (*this, &ColorAppearance::surrsource_toggled) ); + wbmodelconn = wbmodel->signal_changed().connect ( sigc::mem_fun (*this, &ColorAppearance::wbmodelChanged) ); + algoconn = algo->signal_changed().connect ( sigc::mem_fun (*this, &ColorAppearance::algoChanged) ); + surroundconn = surround->signal_changed().connect ( sigc::mem_fun (*this, &ColorAppearance::surroundChanged) ); degree->setAdjusterListener (this); adapscen->setAdjusterListener (this); @@ -433,12 +433,12 @@ ColorAppearance::~ColorAppearance () -bool ColorAppearance::bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) +bool ColorAppearance::bgTTipQuery (int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) { return true; } -bool ColorAppearance::srTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) +bool ColorAppearance::srTTipQuery (int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) { return true; } @@ -447,15 +447,15 @@ void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited) { disableListener (); - tcmodeconn.block(true); - tcmode2conn.block(true); - tcmode3conn.block(true); + tcmodeconn.block (true); + tcmode2conn.block (true); + tcmode3conn.block (true); shape->setCurve (pp->colorappearance.curve); shape2->setCurve (pp->colorappearance.curve2); shape3->setCurve (pp->colorappearance.curve3); - toneCurveMode->set_active(pp->colorappearance.curveMode); - toneCurveMode2->set_active(pp->colorappearance.curveMode2); - toneCurveMode3->set_active(pp->colorappearance.curveMode3); + toneCurveMode->set_active (pp->colorappearance.curveMode); + toneCurveMode2->set_active (pp->colorappearance.curveMode2); + toneCurveMode3->set_active (pp->colorappearance.curveMode3); curveMode3Changed(); // This will set the correct sensitive state of depending Adjusters if (pedited) { @@ -488,23 +488,23 @@ void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited) shape3->setUnChanged (!pedited->colorappearance.curve3); if (!pedited->colorappearance.curveMode) { - toneCurveMode->set_active(2); + toneCurveMode->set_active (2); } if (!pedited->colorappearance.curveMode2) { - toneCurveMode2->set_active(2); + toneCurveMode2->set_active (2); } if (!pedited->colorappearance.curveMode3) { - toneCurveMode3->set_active(3); + toneCurveMode3->set_active (3); } } - setEnabled(pp->colorappearance.enabled); + setEnabled (pp->colorappearance.enabled); - surroundconn.block(true); + surroundconn.block (true); if (pedited && !pedited->colorappearance.surround) { surround->set_active (4); @@ -518,11 +518,11 @@ void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited) surround->set_active (3); } - surroundconn.block(false); + surroundconn.block (false); // Have to be manually called to handle initial state update surroundChanged(); - wbmodelconn.block(true); + wbmodelconn.block (true); if (pedited && !pedited->colorappearance.wbmodel) { wbmodel->set_active (2); @@ -532,11 +532,11 @@ void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited) wbmodel->set_active (1); } - wbmodelconn.block(false); + wbmodelconn.block (false); // Have to be manually called to handle initial state update wbmodelChanged(); - algoconn.block(true); + algoconn.block (true); if (pedited && !pedited->colorappearance.algo) { algo->set_active (4); @@ -550,7 +550,7 @@ void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited) algo->set_active (3); } - algoconn.block(false); + algoconn.block (false); // Have to be manually called to handle initial state update algoChanged(); @@ -584,7 +584,7 @@ void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited) lastAutoAdapscen = pp->colorappearance.autoadapscen; degree->setValue (pp->colorappearance.degree); - degree->setAutoValue(pp->colorappearance.autodegree); + degree->setAutoValue (pp->colorappearance.autodegree); adapscen->setValue (pp->colorappearance.adapscen); adapscen->setAutoValue (pp->colorappearance.autoadapscen); @@ -600,9 +600,9 @@ void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited) qcontrast->setValue (pp->colorappearance.qcontrast); colorh->setValue (pp->colorappearance.colorh); - tcmode3conn.block(false); - tcmode2conn.block(false); - tcmodeconn.block(false); + tcmode3conn.block (false); + tcmode2conn.block (false); + tcmodeconn.block (false); enableListener (); } void ColorAppearance::autoOpenCurve () @@ -686,9 +686,9 @@ void ColorAppearance::write (ProcParams* pp, ParamsEdited* pedited) pedited->colorappearance.autodegree = !degree->getAutoInconsistent(); pedited->colorappearance.autoadapscen = !adapscen->getAutoInconsistent(); pedited->colorappearance.enabled = !get_inconsistent(); - pedited->colorappearance.surround = surround->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->colorappearance.wbmodel = wbmodel->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->colorappearance.algo = algo->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->colorappearance.surround = surround->get_active_text() != M ("GENERAL_UNCHANGED"); + pedited->colorappearance.wbmodel = wbmodel->get_active_text() != M ("GENERAL_UNCHANGED"); + pedited->colorappearance.algo = algo->get_active_text() != M ("GENERAL_UNCHANGED"); pedited->colorappearance.surrsource = !surrsource->get_inconsistent(); pedited->colorappearance.gamut = !gamut->get_inconsistent(); // pedited->colorappearance.badpix = !badpix->get_inconsistent(); @@ -735,11 +735,11 @@ void ColorAppearance::curveChanged (CurveEditor* ce) if (listener) { if (ce == shape) { - listener->panelChanged (EvCATCurve1, M("HISTORY_CUSTOMCURVE")); + listener->panelChanged (EvCATCurve1, M ("HISTORY_CUSTOMCURVE")); } else if (ce == shape2) { - listener->panelChanged (EvCATCurve2, M("HISTORY_CUSTOMCURVE")); + listener->panelChanged (EvCATCurve2, M ("HISTORY_CUSTOMCURVE")); } else if (ce == shape3) { - listener->panelChanged (EvCATCurve3, M("HISTORY_CUSTOMCURVE")); + listener->panelChanged (EvCATCurve3, M ("HISTORY_CUSTOMCURVE")); } } } @@ -747,7 +747,7 @@ void ColorAppearance::curveChanged (CurveEditor* ce) void ColorAppearance::curveMode1Changed () { if (listener) { - Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::curveMode1Changed_)); + Glib::signal_idle().connect (sigc::mem_fun (*this, &ColorAppearance::curveMode1Changed_)); } } @@ -763,7 +763,7 @@ bool ColorAppearance::curveMode1Changed_ () void ColorAppearance::curveMode2Changed () { if (listener) { - Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::curveMode2Changed_)); + Glib::signal_idle().connect (sigc::mem_fun (*this, &ColorAppearance::curveMode2Changed_)); } } @@ -781,18 +781,18 @@ void ColorAppearance::curveMode3Changed () int tcMode3 = toneCurveMode3->get_active_row_number(); if (tcMode3 == 0) { - chroma->set_sensitive(true); - schroma->set_sensitive(true); + chroma->set_sensitive (true); + schroma->set_sensitive (true); } else if (tcMode3 == 2) { - chroma->set_sensitive(false); - schroma->set_sensitive(false); + chroma->set_sensitive (false); + schroma->set_sensitive (false); } else if (tcMode3 == 1) { - chroma->set_sensitive(false); - schroma->set_sensitive(true); + chroma->set_sensitive (false); + schroma->set_sensitive (true); } if (listener) { - Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::curveMode3Changed_)); + Glib::signal_idle().connect (sigc::mem_fun (*this, &ColorAppearance::curveMode3Changed_)); } } @@ -823,9 +823,9 @@ void ColorAppearance::surrsource_toggled () if (listener) { if (surrsource->get_active ()) { - listener->panelChanged (EvCATsurr, M("GENERAL_ENABLED")); + listener->panelChanged (EvCATsurr, M ("GENERAL_ENABLED")); } else { - listener->panelChanged (EvCATsurr, M("GENERAL_DISABLED")); + listener->panelChanged (EvCATsurr, M ("GENERAL_DISABLED")); } } } @@ -848,9 +848,9 @@ void ColorAppearance::gamut_toggled () if (listener) { if (gamut->get_active ()) { - listener->panelChanged (EvCATgamut, M("GENERAL_ENABLED")); + listener->panelChanged (EvCATgamut, M ("GENERAL_ENABLED")); } else { - listener->panelChanged (EvCATgamut, M("GENERAL_DISABLED")); + listener->panelChanged (EvCATgamut, M ("GENERAL_DISABLED")); } } @@ -899,9 +899,9 @@ void ColorAppearance::datacie_toggled () if (listener) { if (datacie->get_active ()) { - listener->panelChanged (EvCATdatacie, M("GENERAL_ENABLED")); + listener->panelChanged (EvCATdatacie, M ("GENERAL_ENABLED")); } else { - listener->panelChanged (EvCATdatacie, M("GENERAL_DISABLED")); + listener->panelChanged (EvCATdatacie, M ("GENERAL_DISABLED")); } } } @@ -923,9 +923,9 @@ void ColorAppearance::tonecie_toggled () if (listener) { if (tonecie->get_active ()) { - listener->panelChanged (EvCATtonecie, M("GENERAL_ENABLED")); + listener->panelChanged (EvCATtonecie, M ("GENERAL_ENABLED")); } else { - listener->panelChanged (EvCATtonecie, M("GENERAL_DISABLED")); + listener->panelChanged (EvCATtonecie, M ("GENERAL_DISABLED")); } } @@ -1009,12 +1009,12 @@ void ColorAppearance::autoCamChanged (double ccam) { nextCcam = ccam; - const auto func = [](gpointer data) -> gboolean { - static_cast(data)->autoCamComputed_(); + const auto func = [] (gpointer data) -> gboolean { + static_cast (data)->autoCamComputed_(); return FALSE; }; - idle_register.add(func, this); + idle_register.add (func, this); } bool ColorAppearance::autoCamComputed_ () @@ -1032,12 +1032,12 @@ void ColorAppearance::adapCamChanged (double cadap) { nextCadap = cadap; - const auto func = [](gpointer data) -> gboolean { - static_cast(data)->adapCamComputed_(); + const auto func = [] (gpointer data) -> gboolean { + static_cast (data)->adapCamComputed_(); return FALSE; }; - idle_register.add(func, this); + idle_register.add (func, this); } bool ColorAppearance::adapCamComputed_ () @@ -1063,46 +1063,46 @@ void ColorAppearance::colorForValue (double valX, double valY, enum ColorCaller: if (callerId == 1) { // cc - bottom bar - float value = (1.f - 0.7f) * float(valX) + 0.7f; + float value = (1.f - 0.7f) * float (valX) + 0.7f; // whole hue range // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + Color::hsv2rgb01 (float (valY), float (valX), value, R, G, B); } - caller->ccRed = double(R); - caller->ccGreen = double(G); - caller->ccBlue = double(B); + caller->ccRed = double (R); + caller->ccGreen = double (G); + caller->ccBlue = double (B); } void ColorAppearance::adjusterChanged (Adjuster* a, double newval) { if (listener && (multiImage || getEnabled()) ) { - if(a == degree) { + if (a == degree) { listener->panelChanged (EvCATDegree, a->getTextValue()); - } else if(a == adapscen) { + } else if (a == adapscen) { listener->panelChanged (EvCATAdapscen, a->getTextValue()); - } else if(a == adaplum) { + } else if (a == adaplum) { listener->panelChanged (EvCATAdapLum, a->getTextValue()); - } else if(a == badpixsl) { + } else if (a == badpixsl) { listener->panelChanged (EvCATbadpix, a->getTextValue()); - } else if(a == jlight) { + } else if (a == jlight) { listener->panelChanged (EvCATJLight, a->getTextValue()); - } else if(a == qbright) { + } else if (a == qbright) { listener->panelChanged (EvCATQbright, a->getTextValue()); - } else if(a == chroma) { + } else if (a == chroma) { listener->panelChanged (EvCATChroma, a->getTextValue()); - } else if(a == schroma) { + } else if (a == schroma) { listener->panelChanged (EvCATSChroma, a->getTextValue()); - } else if(a == mchroma) { + } else if (a == mchroma) { listener->panelChanged (EvCATMChroma, a->getTextValue()); - } else if(a == rstprotection) { + } else if (a == rstprotection) { listener->panelChanged (EvCATRstpro, a->getTextValue()); - } else if(a == contrast) { + } else if (a == contrast) { listener->panelChanged (EvCATContrast, a->getTextValue()); - } else if(a == colorh) { + } else if (a == colorh) { listener->panelChanged (EvCAThue, a->getTextValue()); - } else if(a == qcontrast) { + } else if (a == qcontrast) { listener->panelChanged (EvCATQContrast, a->getTextValue()); } @@ -1114,19 +1114,19 @@ void ColorAppearance::adjusterAutoToggled (Adjuster* a, bool newval) if (multiImage) { if (degree->getAutoInconsistent()) { - degree->setAutoInconsistent(false); - degree->setAutoValue(false); + degree->setAutoInconsistent (false); + degree->setAutoValue (false); } else if (lastAutoDegree) { - degree->setAutoInconsistent(true); + degree->setAutoInconsistent (true); } lastAutoDegree = degree->getAutoValue(); if (adapscen->getAutoInconsistent()) { - adapscen->setAutoInconsistent(false); - adapscen->setAutoValue(false); + adapscen->setAutoInconsistent (false); + adapscen->setAutoValue (false); } else if (lastAutoAdapscen) { - adapscen->setAutoInconsistent(true); + adapscen->setAutoInconsistent (true); } lastAutoAdapscen = adapscen->getAutoValue(); @@ -1135,23 +1135,23 @@ void ColorAppearance::adjusterAutoToggled (Adjuster* a, bool newval) if (listener && (multiImage || getEnabled()) ) { - if(a == degree) { + if (a == degree) { if (degree->getAutoInconsistent()) { - listener->panelChanged (EvCATAutoDegree, M("GENERAL_UNCHANGED")); + listener->panelChanged (EvCATAutoDegree, M ("GENERAL_UNCHANGED")); } else if (degree->getAutoValue()) { - listener->panelChanged (EvCATAutoDegree, M("GENERAL_ENABLED")); + listener->panelChanged (EvCATAutoDegree, M ("GENERAL_ENABLED")); } else { - listener->panelChanged (EvCATAutoDegree, M("GENERAL_DISABLED")); + listener->panelChanged (EvCATAutoDegree, M ("GENERAL_DISABLED")); } } - if(a == adapscen) { + if (a == adapscen) { if (adapscen->getAutoInconsistent()) { - listener->panelChanged (EvCATAutoAdap, M("GENERAL_UNCHANGED")); + listener->panelChanged (EvCATAutoAdap, M ("GENERAL_UNCHANGED")); } else if (adapscen->getAutoValue()) { - listener->panelChanged (EvCATAutoAdap, M("GENERAL_ENABLED")); + listener->panelChanged (EvCATAutoAdap, M ("GENERAL_ENABLED")); } else { - listener->panelChanged (EvCATAutoAdap, M("GENERAL_DISABLED")); + listener->panelChanged (EvCATAutoAdap, M ("GENERAL_DISABLED")); } } @@ -1163,13 +1163,13 @@ void ColorAppearance::enabledChanged () if (listener) { if (get_inconsistent()) { - listener->panelChanged (EvCATEnabled, M("GENERAL_UNCHANGED")); + listener->panelChanged (EvCATEnabled, M ("GENERAL_UNCHANGED")); } else if (getEnabled()) { - listener->panelChanged (EvCATEnabled, M("GENERAL_ENABLED")); + listener->panelChanged (EvCATEnabled, M ("GENERAL_ENABLED")); curveEditorG->set_sensitive (true); toneCurveMode->set_sensitive (true); } else { - listener->panelChanged (EvCATEnabled, M("GENERAL_DISABLED")); + listener->panelChanged (EvCATEnabled, M ("GENERAL_DISABLED")); } } } @@ -1282,12 +1282,12 @@ void ColorAppearance::setBatchMode (bool batchMode) qcontrast->showEditedCB (); colorh->showEditedCB (); - surround->append (M("GENERAL_UNCHANGED")); - wbmodel->append (M("GENERAL_UNCHANGED")); - algo->append (M("GENERAL_UNCHANGED")); - toneCurveMode->append (M("GENERAL_UNCHANGED")); - toneCurveMode2->append (M("GENERAL_UNCHANGED")); - toneCurveMode3->append (M("GENERAL_UNCHANGED")); + surround->append (M ("GENERAL_UNCHANGED")); + wbmodel->append (M ("GENERAL_UNCHANGED")); + algo->append (M ("GENERAL_UNCHANGED")); + toneCurveMode->append (M ("GENERAL_UNCHANGED")); + toneCurveMode2->append (M ("GENERAL_UNCHANGED")); + toneCurveMode3->append (M ("GENERAL_UNCHANGED")); curveEditorG->setBatchMode (batchMode); curveEditorG2->setBatchMode (batchMode); @@ -1306,35 +1306,35 @@ void ColorAppearance::updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu void ColorAppearance::setAdjusterBehavior (bool degreeadd, bool adapscenadd, bool adaplumadd, bool badpixsladd, bool jlightadd, bool chromaadd, bool contrastadd, bool rstprotectionadd, bool qbrightadd, bool qcontrastadd, bool schromaadd, bool mchromaadd, bool colorhadd) { - degree->setAddMode(degreeadd); - adapscen->setAddMode(adapscenadd); - adaplum->setAddMode(adaplumadd); - badpixsl->setAddMode(badpixsladd); - jlight->setAddMode(jlightadd); - qbright->setAddMode(qbrightadd); - chroma->setAddMode(chromaadd); - schroma->setAddMode(schromaadd); - mchroma->setAddMode(mchromaadd); - rstprotection->setAddMode(rstprotectionadd); - contrast->setAddMode(contrastadd); - qcontrast->setAddMode(qcontrastadd); - colorh->setAddMode(colorhadd); + degree->setAddMode (degreeadd); + adapscen->setAddMode (adapscenadd); + adaplum->setAddMode (adaplumadd); + badpixsl->setAddMode (badpixsladd); + jlight->setAddMode (jlightadd); + qbright->setAddMode (qbrightadd); + chroma->setAddMode (chromaadd); + schroma->setAddMode (schromaadd); + mchroma->setAddMode (mchromaadd); + rstprotection->setAddMode (rstprotectionadd); + contrast->setAddMode (contrastadd); + qcontrast->setAddMode (qcontrastadd); + colorh->setAddMode (colorhadd); } void ColorAppearance::trimValues (rtengine::procparams::ProcParams* pp) { - degree->trimValue(pp->colorappearance.degree); - adapscen->trimValue(pp->colorappearance.adapscen); - adaplum->trimValue(pp->colorappearance.adaplum); - badpixsl->trimValue(pp->colorappearance.badpixsl); - jlight->trimValue(pp->colorappearance.jlight); - qbright->trimValue(pp->colorappearance.qbright); - chroma->trimValue(pp->colorappearance.chroma); - schroma->trimValue(pp->colorappearance.schroma); - mchroma->trimValue(pp->colorappearance.mchroma); - rstprotection->trimValue(pp->colorappearance.rstprotection); - contrast->trimValue(pp->colorappearance.contrast); - qcontrast->trimValue(pp->colorappearance.qcontrast); - colorh->trimValue(pp->colorappearance.colorh); + degree->trimValue (pp->colorappearance.degree); + adapscen->trimValue (pp->colorappearance.adapscen); + adaplum->trimValue (pp->colorappearance.adaplum); + badpixsl->trimValue (pp->colorappearance.badpixsl); + jlight->trimValue (pp->colorappearance.jlight); + qbright->trimValue (pp->colorappearance.qbright); + chroma->trimValue (pp->colorappearance.chroma); + schroma->trimValue (pp->colorappearance.schroma); + mchroma->trimValue (pp->colorappearance.mchroma); + rstprotection->trimValue (pp->colorappearance.rstprotection); + contrast->trimValue (pp->colorappearance.contrast); + qcontrast->trimValue (pp->colorappearance.qcontrast); + colorh->trimValue (pp->colorappearance.colorh); } diff --git a/rtgui/coloredbar.cc b/rtgui/coloredbar.cc index 9ec966d30..7d623949e 100644 --- a/rtgui/coloredbar.cc +++ b/rtgui/coloredbar.cc @@ -131,6 +131,8 @@ void ColoredBar::updateBackBuffer(Gtk::DrawingArea &drawingArea) } else { // ask the ColorProvider to provide colors :) for each pixels if (colorProvider) { + surface->flush(); + unsigned char *surfaceData = surface->get_data(); cr->set_antialias(Cairo::ANTIALIAS_NONE); @@ -202,6 +204,8 @@ void ColoredBar::updateBackBuffer(Gtk::DrawingArea &drawingArea) break; } + + surface->mark_dirty(); } } diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index 0694f68ea..25311b97b 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -444,8 +444,8 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) 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) { + needRedraw = editSubscriber->button1Pressed(bstate); if (editSubscriber->isDragging()) { state = SEditDrag1; } else if (editSubscriber->isPicking()) { @@ -2214,6 +2214,10 @@ void CropWindow::screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& c if (zoomSteps[cropZoom].zoom > 1.) { cropx = int(double(cropx) / zoomSteps[cropZoom].zoom); cropy = int(double(cropy) / zoomSteps[cropZoom].zoom); + } else { + float czoom = float((zoomSteps[cropZoom].czoom/10) * 10) / float(zoomSteps[cropZoom].czoom); + cropx = cropx / czoom; + cropy = cropy / czoom; } cropx += crop->getLeftBorder(); diff --git a/rtgui/diagonalcurveeditorsubgroup.cc b/rtgui/diagonalcurveeditorsubgroup.cc index d12cdf023..936bf0d64 100644 --- a/rtgui/diagonalcurveeditorsubgroup.cc +++ b/rtgui/diagonalcurveeditorsubgroup.cc @@ -620,7 +620,9 @@ void DiagonalCurveEditorSubGroup::switchGUI() } else { // dCurve ave a ColorProvider or a background gradient defined, so we create/update the object if (!leftBar) { - leftBar = new ColoredBar(RTO_Bottom2Top); + leftBar = new ColoredBar(RTO_Bottom2Top); + + } if (barColorProvider) { diff --git a/rtgui/extprog.cc b/rtgui/extprog.cc index bdbbb85b4..33424fac9 100644 --- a/rtgui/extprog.cc +++ b/rtgui/extprog.cc @@ -324,7 +324,7 @@ bool ExtProgStore::openInCustomEditor (const Glib::ustring& fileName) #if defined WIN32 const auto cmdLine = Glib::ustring("\"") + options.customEditorProg + Glib::ustring("\""); - auto success = ShellExecute( NULL, "open", cmdLine.c_str(), fileName.c_str(), NULL, SW_SHOWNORMAL ); + auto success = ShellExecute( NULL, "open", cmdLine.c_str(), ('"' + fileName + '"').c_str(), NULL, SW_SHOWNORMAL ); return (uintptr_t)success > 32; #elif defined __APPLE__ diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc index dc9e404fb..c39dc99fc 100644 --- a/rtgui/labcurve.cc +++ b/rtgui/labcurve.cc @@ -574,6 +574,21 @@ void LCurve::colorForValue (double valX, double valY, enum ColorCaller::ElemType // whole hue range // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + } else if (callerId == 6) { // cc - left bar + + float value = (1.f - 0.7f) * float(valX) + 0.7f; + float hue = (1.14056f - 0.92f) * float(valY) + 0.92f; + + if (hue > 1.0f) { + hue -= 1.0f; + } + + // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) + Color::hsv2rgb01(hue, float(valX), value, R, G, B); + + // whole hue range + // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) + // Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); } else if (callerId == 3) { // lc - bottom bar float value = (1.f - 0.7f) * float(valX) + 0.7f; diff --git a/rtgui/main-cli.cc b/rtgui/main-cli.cc index 91dfc9204..2a2afca63 100644 --- a/rtgui/main-cli.cc +++ b/rtgui/main-cli.cc @@ -425,7 +425,7 @@ int processLineParams( int argc, char **argv ) case 't': outputType = "tif"; - compression = ((currParam.at(2) != 'z') ? 0 : 1); + compression = ((currParam.size() < 3 || currParam.at(2) != 'z') ? 0 : 1); break; case 'n': @@ -549,9 +549,8 @@ int processLineParams( int argc, char **argv ) std::cout << std::endl; #endif std::cout << "Options:" << std::endl; - std::cout << " " << Glib::path_get_basename(argv[0]) << " [-o |-O ] [-s|-S] [-p [-p ...] ] [-d] [ -j[1-100] [-js<1-3>] | [-b<8|16>] [-t[z] | [-n]] ] [-Y] [-f] -c " << std::endl; + std::cout << " " << Glib::path_get_basename(argv[0]) << "[-o |-O ] [-q] [-a] [-s|-S] [-p [-p ...] ] [-d] [ -j[1-100] [-js<1-3>] | [-b<8|16>] [-t[z] | [-n]] ] [-Y] [-f] -c " << std::endl; std::cout << std::endl; - std::cout << " -q Quick Start mode : do not load cached files to speedup start time." << std::endl; std::cout << " -c Specify one or more input files or directory." << std::endl; std::cout << " When specifying directories, Rawtherapee will look for images files that comply with the" << std::endl; std::cout << " selected extensions (see also '-a')." << std::endl; @@ -560,8 +559,9 @@ int processLineParams( int argc, char **argv ) std::cout << " Saves output file alongside input file if -o is not specified." << std::endl; std::cout << " -O | Set output file or folder and copy " << pparamsExt << " file into it." << std::endl; std::cout << " Saves output file alongside input file if -O is not specified." << std::endl; - std::cout << " -a stand for 'all'. When specifying a directory, process all images specified in the" << std::endl; - std::cout << " extension list from the options file, even those currently not seleted" << std::endl; + std::cout << " -q Quick-start mode. Does not load cached files to speedup start time." << std::endl; + std::cout << " -a Process all supported image file types when specifying a folder, even those" << std::endl; + std::cout << " not currently selected in Preferences > File Browser > Parsed Extensions." << std::endl; std::cout << " -s Use the existing sidecar file to build the processing parameters," << std::endl; std::cout << " e.g. for photo.raw there should be a photo.raw." << pparamsExt << " file in the same folder." << std::endl; std::cout << " If the sidecar file does not exist, neutral values will be used." << std::endl; diff --git a/rtgui/multilangmgr.cc b/rtgui/multilangmgr.cc index 4c0b78fc9..d8a619292 100644 --- a/rtgui/multilangmgr.cc +++ b/rtgui/multilangmgr.cc @@ -196,7 +196,8 @@ Glib::ustring MultiLangMgr::getOSUserLanguage () #elif defined (__linux__) || defined (__APPLE__) // Query the current locale and force decimal point to dot. - if (const char* locale = setlocale (LC_CTYPE, "")) { + const char *locale = getenv("LANG"); + if (locale || (locale = setlocale (LC_CTYPE, ""))) { langName = localeToLang (locale); } diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 68de43d91..ca9953f2a 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -553,7 +553,7 @@ Gtk::Widget* Preferences::getProcParamsPanel () mvbpp->pack_start ( *fdf , Gtk::PACK_SHRINK, 4); //dfconn = darkFrameDir->signal_file_set().connect ( sigc::mem_fun(*this, &Preferences::darkFrameChanged), true); - dfconn = darkFrameDir->signal_current_folder_changed().connect ( sigc::mem_fun (*this, &Preferences::darkFrameChanged), true); + dfconn = darkFrameDir->signal_selection_changed().connect ( sigc::mem_fun(*this, &Preferences::darkFrameChanged), true); // FLATFIELD Gtk::Frame* fff = Gtk::manage (new Gtk::Frame (M ("PREFERENCES_FLATFIELD")) ); @@ -570,7 +570,7 @@ Gtk::Widget* Preferences::getProcParamsPanel () mvbpp->pack_start ( *fff , Gtk::PACK_SHRINK, 4); //ffconn = flatFieldDir->signal_file_set().connect ( sigc::mem_fun(*this, &Preferences::flatFieldChanged), true); - ffconn = flatFieldDir->signal_current_folder_changed().connect ( sigc::mem_fun (*this, &Preferences::flatFieldChanged), true); + ffconn = flatFieldDir->signal_selection_changed().connect ( sigc::mem_fun(*this, &Preferences::flatFieldChanged), true); //Cluts Dir Gtk::Frame* clutsDirFrame = Gtk::manage (new Gtk::Frame (M ("PREFERENCES_FILMSIMULATION")) ); diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index ccf0b26e2..ca1a011b9 100644 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -18,6 +18,7 @@ */ #include +#include #include "rtwindow.h" #include "options.h" #include "preferences.h" @@ -319,22 +320,38 @@ void RTWindow::on_realize () mainWindowCursorManager.init(get_window()); - // Check if first run of this version, then display the Release Notes text - if (options.version != versionString) { + // Display release notes only if new major version. + // Pattern matches "5.1" from "5.1-23-g12345678" + std::string vs[] = {versionString, options.version}; + std::regex pat("(^[0-9.]+).*"); + std::smatch sm; + std::vector vMajor; + for (const auto &v : vs) { + if (std::regex_match(v, sm, pat)) { + if (sm.size() == 2) { + std::ssub_match smsub = sm[1]; + vMajor.push_back(smsub.str()); + } + } + } - // Update the version parameter with the right value - options.version = versionString; + if (vMajor.size() == 2) { + if (vMajor[0] != vMajor[1]) { - splash = new Splash (*this); - splash->set_transient_for (*this); - splash->signal_delete_event().connect( sigc::mem_fun(*this, &RTWindow::splashClosed) ); + // Update the version parameter with the right value + options.version = versionString; - if (splash->hasReleaseNotes()) { - splash->showReleaseNotes(); - splash->show (); - } else { - delete splash; - splash = nullptr; + splash = new Splash (*this); + splash->set_transient_for (*this); + splash->signal_delete_event().connect( sigc::mem_fun(*this, &RTWindow::splashClosed) ); + + if (splash->hasReleaseNotes()) { + splash->showReleaseNotes(); + splash->show (); + } else { + delete splash; + splash = nullptr; + } } } }