1 /*******************************************************************************
2 **
3 ** Photivo
4 **
5 ** Copyright (C) 2008 Jos De Laender <jos.de_laender@telenet.be>
6 ** Copyright (C) 2010-2011 Michael Munzert <mail@mm-log.com>
7 ** Copyright (C) 2013 Alexander Tzyganenko <tz@fast-report.com>
8 **
9 ** This file is part of Photivo.
10 **
11 ** Photivo is free software: you can redistribute it and/or modify
12 ** it under the terms of the GNU General Public License version 3
13 ** as published by the Free Software Foundation.
14 **
15 ** Photivo is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ** GNU General Public License for more details.
19 **
20 ** You should have received a copy of the GNU General Public License
21 ** along with Photivo. If not, see <http://www.gnu.org/licenses/>.
22 **
23 *******************************************************************************/
24
25 #include "ptSettings.h"
26 #include "ptError.h"
27 #include "ptDcRaw.h"
28 #include "ptRGBTemperature.h"
29 #include "ptGuiOptions.h"
30 #include "filemgmt/ptFileMgrConstants.h"
31 #include <filters/ptFilterUids.h>
32
33 #include <cassert>
34
35 //==============================================================================
36
37 // Macro for inserting a key into the hash and checking it is a new one.
38 #define M_InsertKeyIntoHash(Key,Item) \
39 if (m_Hash.contains(Key)) { \
40 ptLogError(ptError_Argument, \
41 "Inserting an existing key (%s)", \
42 Key.toLocal8Bit().data()); \
43 assert (!m_Hash.contains(Key)); \
44 } \
45 m_Hash[Key] = Item;
46
47 ///////////////////////////////////////////////////////////////////////////////
48 //
49 // Constructor
50 //
51 ///////////////////////////////////////////////////////////////////////////////
52
ptSettings(const short InitLevel,const QString Path)53 ptSettings::ptSettings(const short InitLevel, const QString Path) {
54
55 assert(InitLevel<9); // 9 reserved for never to be remembered.
56
57 // Load in the gui input elements
58 const ptGuiInputItem GuiInputItems[] = {
59 // Attention : Default,Min,Max,Step should be consistent int or double. Double *always* in X.Y notation to indicate so.
60 // Unique Name uiElement,InitLevel,InJobFile,HasDefault Default Min Max Step Decimals Label,ToolTip
61 {"FileMgrThumbnailSize" ,ptGT_InputSlider ,1,0,1 ,100 ,50 ,500 ,25 ,0 ,tr("Thumbnail size") ,tr("Thumbnail size in pixel")},
62 {"FileMgrThumbnailPadding" ,ptGT_InputSlider ,1,0,1 ,8 ,0 ,50 ,2 ,0 ,tr("Thumbnail padding") ,tr("Thumbnail padding in pixel")},
63 {"FileMgrThumbMaxRowCol" ,ptGT_Input ,1,0,1 ,3 ,1 ,1000 ,1 ,0 ,tr("Thumbnails in a row/column") ,tr("Maximum number of thumbnails that should be placed in a row or column.")},
64 {"FileMgrThumbSaveSize" ,ptGT_InputSlider ,1,0,1 ,1000 ,50 ,8000 ,100 ,0 ,tr("Thumbnail export size") ,tr("Thumbnail export size in pixel")},
65 {"FileMgrThumbCacheSize" ,ptGT_InputSlider ,1,0,1 ,250 ,0 ,2000 ,100 ,0 ,tr("Thumbnail cache (MB)") ,tr("Maximum size of thumbnail cache in MBytes.\nRequires a restart to take effect.")},
66 {"MemoryTest" ,ptGT_InputSlider ,9,0,1 ,0 ,0 ,500 ,50 ,0 ,tr("MB") ,tr("MB to waste")},
67 {"TabStatusIndicator" ,ptGT_Input ,1,0,1 ,8 ,0 ,16 ,1 ,0 ,tr("Pixel") ,tr("Size of the LED")},
68 {"SliderWidth" ,ptGT_Input ,1,0,1 ,0 ,0 ,500 ,50 ,0 ,tr("Maximum slider width") ,tr("Maximum slider width. Enter 0 to remove restriction")},
69 {"Zoom" ,ptGT_InputSlider ,9,0,0 ,100 ,5 ,400 ,10 ,0 ,tr("Zoom") ,tr("Zoom factor")},
70 {"ColorTemperature" ,ptGT_InputSlider ,2,1,1 ,6500 ,2000 ,15000 ,50 ,0 ,tr("Temp") ,tr("Color Temperature")},
71 {"GreenIntensity" ,ptGT_Input ,2,1,1 ,1.0 ,0.001,5.0 ,0.01 ,3 ,tr("WB-G") ,tr("Green Intensity in balance")},
72 {"RMultiplier" ,ptGT_Input ,2,1,0 ,1.0 ,0.001,10.0 ,0.01 ,3 ,tr("R") ,tr("Red Multiplier in balance")},
73 {"GMultiplier" ,ptGT_Input ,2,1,0 ,1.0 ,0.001,10.0 ,0.01 ,3 ,tr("G") ,tr("Green Multiplier in balance")},
74 {"BMultiplier" ,ptGT_Input ,2,1,0 ,1.0 ,0.001,10.0 ,0.01 ,3 ,tr("B") ,tr("Blue Multiplier in balance")},
75 {"BlackPoint" ,ptGT_Input ,2,1,0 ,0 ,0 ,0xffff,1 ,0 ,tr("BP") ,tr("Black point in raw")},
76 {"WhitePoint" ,ptGT_Input ,2,1,0 ,0 ,0 ,0xffff,10 ,0 ,tr("WP") ,tr("White point in raw")},
77 {"CaRed" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-5.0 ,5.0 ,0.5 ,2 ,tr("CA red factor") ,tr("CA red factor")},
78 {"CaBlue" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-5.0 ,5.0 ,0.5 ,2 ,tr("CA blue factor") ,tr("CA blue factor")},
79 {"GreenEquil" ,ptGT_InputSlider ,2,1,1 ,0 ,0 ,100 ,1 ,0 ,tr("Green equilibration"),tr("Green equilibration")},
80 {"CfaLineDenoise" ,ptGT_InputSlider ,2,1,1 ,0 ,0 ,50 ,1 ,0 ,tr("Line denoise") ,tr("Raw line denoise threshold")},
81 {"AdjustMaximumThreshold" ,ptGT_InputSlider ,2,1,1 ,0.0 ,0.0 ,0.50 ,0.01 ,2 ,tr("Adjust maximum") ,tr("Threshold to prevent pink highlights")},
82 {"RawDenoiseThreshold" ,ptGT_InputSlider ,2,1,1 ,0 ,0 ,2000 ,100 ,0 ,tr("Wavelet denoise") ,tr("Raw wavelet denoise threshold")},
83 {"HotpixelReduction" ,ptGT_InputSlider ,2,1,1 ,0.0 ,0.0 ,1.0 ,0.05 ,3 ,tr("Badpixel reduction") ,tr("Automatic badpixel reduction")},
84 {"InterpolationPasses" ,ptGT_Input ,1,1,1 ,1 ,0 ,10 ,1 ,0 ,tr("Passes") ,tr("Nr of refinement passes")},
85 {"MedianPasses" ,ptGT_Input ,2,1,1 ,0 ,0 ,10 ,1 ,0 ,tr("Median passes") ,tr("Nr of median filter passes")},
86 {"ESMedianPasses" ,ptGT_Input ,2,1,1 ,0 ,0 ,10 ,1 ,0 ,tr("Edge sensitive median passes") ,tr("Nr of edge sensitive median filter passes")},
87 {"ClipParameter" ,ptGT_InputSlider ,1,1,1 ,0 ,0 ,100 ,1 ,0 ,tr("Parameter") ,tr("Clip function dependent parameter")},
88 {"LfunFocal" ,ptGT_Input ,2,1,1 ,50.0 ,4.0 ,1000.0,1.0 ,0 ,tr("Focal length (35mm equiv.)"), tr("Focal length (35mm equiv.)")},
89 {"LfunAperture" ,ptGT_Input ,2,1,1 ,8.0 ,0.8 ,32.0 ,1.0 ,1 ,tr("Aperture"), tr("")},
90 {"LfunDistance" ,ptGT_Input ,2,1,1 ,1.0 ,0.01 ,500.0 ,1.0 ,2 ,tr("Distance"), tr("Distance between object and camera")},
91 {"LfunScale" ,ptGT_InputSlider ,2,1,1 ,1.0 ,0.01 ,5.0 ,0.01 ,2 ,tr("Scale"),tr("Image scaling.\nUseful to avoid losing content through the distortion/geometry tools.\n0.0 means auto-scaling.")},
92 {"LfunCALinearKr" ,ptGT_InputSlider ,2,1,1 ,1.0 ,0.99 ,1.01 ,0.001,5 ,tr("kr"),tr("")},
93 {"LfunCALinearKb" ,ptGT_InputSlider ,2,1,1 ,1.0 ,0.99 ,1.01 ,0.001,5 ,tr("kb"),tr("")},
94 {"LfunCAPoly3Vr" ,ptGT_InputSlider ,2,1,1 ,1.0 ,0.99 ,1.01 ,0.001,5 ,tr("vr"),tr("")},
95 {"LfunCAPoly3Vb" ,ptGT_InputSlider ,2,1,1 ,1.0 ,0.99 ,1.01 ,0.001,5 ,tr("vb"),tr("")},
96 {"LfunCAPoly3Cr" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-0.01,0.01 ,0.001,5 ,tr("cr"),tr("")},
97 {"LfunCAPoly3Cb" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-0.01,0.01 ,0.001,5 ,tr("cb"),tr("")},
98 {"LfunCAPoly3Br" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-0.01,0.01 ,0.001,5 ,tr("br"),tr("")},
99 {"LfunCAPoly3Bb" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-0.01,0.01 ,0.001,5 ,tr("bb"),tr("")},
100 {"LfunVignettePoly6K1" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-1.0 ,2.0 ,0.01 ,3 ,tr("k1"),tr("")},
101 {"LfunVignettePoly6K2" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-1.0 ,2.0 ,0.01 ,3 ,tr("k2"),tr("")},
102 {"LfunVignettePoly6K3" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-1.0 ,2.0 ,0.01 ,3 ,tr("k3"),tr("")},
103 {"LfunDistPoly3K1" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-0.2 ,0.2 ,0.01 ,4 ,tr("k1"),tr("")},
104 {"LfunDistPoly5K1" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-0.2 ,0.2 ,0.01 ,4 ,tr("k1"),tr("")},
105 {"LfunDistPoly5K2" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-0.2 ,0.2 ,0.01 ,4 ,tr("k2"),tr("")},
106 #if LF_VERSION < (3 << 16)
107 {"LfunDistFov1Omega" ,ptGT_InputSlider ,2,1,1 ,0.0 ,0.0 ,1.4 ,0.1 ,3 ,tr("omega"),tr("")},
108 #endif
109 {"LfunDistPTLensA" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-0.2 ,0.2 ,0.01 ,4 ,tr("a"),tr("")},
110 {"LfunDistPTLensB" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-0.2 ,0.2 ,0.01 ,4 ,tr("b"),tr("")},
111 {"LfunDistPTLensC" ,ptGT_InputSlider ,2,1,1 ,0.0 ,-0.2 ,0.2 ,0.01 ,4 ,tr("c"),tr("")},
112
113 {"DefishFocalLength" ,ptGT_Input ,9,1,1 ,15.0 ,4.0 ,50.0 ,1.0 ,1 ,tr("Focal length (35mm equiv.)") ,tr("Focal length (35mm equiv.)")},
114 {"DefishScale" ,ptGT_InputSlider ,2,1,1 ,1.0 ,0.01 ,5.0 ,0.01 ,2 ,tr("Scale") ,tr("Image scaling.\n0.0 means auto-scaling.")},
115 {"Rotate" ,ptGT_InputSlider ,9,1,1 ,0.0 ,-180.0,180.0 ,0.1 ,2 ,tr("Rotate") ,tr("Rotate")},
116 {"PerspectiveFocalLength" ,ptGT_Input ,9,1,1 ,50.0 ,4.0 ,600.0 ,1.0 ,0 ,tr("Focal length (35mm equiv.)") ,tr("Focal length (35mm equiv.)")},
117 {"PerspectiveTilt" ,ptGT_InputSlider ,9,1,1 ,0.0 ,-45.0,45.0 ,0.1 ,2 ,tr("Tilt") ,tr("Tilt")},
118 {"PerspectiveTurn" ,ptGT_InputSlider ,9,1,1 ,0.0 ,-45.0,45.0 ,0.1 ,2 ,tr("Turn") ,tr("Turn")},
119 {"PerspectiveScaleX" ,ptGT_InputSlider ,9,1,1 ,1.0 ,0.2 ,5.0 ,0.05 ,2 ,tr("Horizontal scale") ,tr("Horizontal scale")},
120 {"PerspectiveScaleY" ,ptGT_InputSlider ,9,1,1 ,1.0 ,0.2 ,5.0 ,0.05 ,2 ,tr("Vertical scale") ,tr("Vertical scale")},
121 {"GridX" ,ptGT_Input ,1,0,0 ,5 ,0 ,20 ,1 ,0 ,tr("X") ,tr("Vertical lines")},
122 {"GridY" ,ptGT_Input ,1,0,0 ,5 ,0 ,20 ,1 ,0 ,tr("Y") ,tr("Horizontal lines")},
123 {"CropExposure" ,ptGT_InputSlider ,1,1,1 ,0.0 ,-5.0 ,5.0 ,0.1 ,2 ,tr("Crop exposure") ,tr("Temporary exposure in EV")},
124 {"LqrHorScale" ,ptGT_InputSlider ,2,1,1 ,1.0 ,0.2 ,2.0 ,0.02 ,3 ,tr("Horizontal scale") ,tr("Horizontal scale")},
125 {"LqrVertScale" ,ptGT_InputSlider ,2,1,1 ,1.0 ,0.2 ,2.0 ,0.02 ,3 ,tr("Vertical scale") ,tr("Vertical scale")},
126 {"LqrWidth" ,ptGT_Input ,1,1,1 ,1200 ,200 ,6000 ,100 ,0 ,tr("Width") ,tr("Width")},
127 {"LqrHeight" ,ptGT_Input ,1,1,1 ,800 ,200 ,6000 ,100 ,0 ,tr("Height") ,tr("Height")},
128 {"ResizeScale" ,ptGT_Input ,1,1,1 ,1200 ,200 ,6000 ,100 ,0 ,tr("Pixels") ,tr("Image size")},
129 {"ResizeHeight" ,ptGT_Input ,1,1,1 ,800 ,200 ,6000 ,100 ,0 ,tr("Height") ,tr("Image height")},
130 {"OutputGamma" ,ptGT_InputSlider ,1,1,1 ,0.33 ,0.1 ,1.0 ,0.01 ,3 ,tr("Gamma") ,tr("Gamma")},
131 {"OutputLinearity" ,ptGT_InputSlider ,1,1,1 ,0.06 ,0.0 ,1.0 ,0.01 ,3 ,tr("Linearity") ,tr("Linearity")},
132 {"WebResizeScale" ,ptGT_Input ,1,1,1 ,1200 ,200 ,2600 ,100 ,0 ,tr("pixels") ,tr("Image size")},
133 {"SaveQuality" ,ptGT_Input ,1,1,1 ,97 ,25 ,100 ,1 ,0 ,tr("Quality") ,tr("Quality")},
134 {"SaveResolution" ,ptGT_Input ,1,1,1 ,300 ,25 ,1200 ,100 ,0 ,tr("dpi") ,tr("Resolution in dpi")},
135 {"ImageRating" ,ptGT_Input ,2,1,1 ,0 ,0 ,5 ,1 ,0 ,tr("Rating") ,tr("Image rating")}
136 };
137
138 // Load in the gui choice (combo) elements
139 const ptGuiChoiceItem GuiChoiceItems[] = {
140 // Unique Name GuiElement,InitLevel,InJobFile,HasDefault, Default Choices (from ptGuiOptions.h), ToolTip
141 {"BatchMgrAutosaveFile" ,ptGT_Choice ,1,0,0 ,bsfStandard ,GuiOptions->BatchMgrAutosaveFile ,tr("File for autosaving batch list")},
142 {"RememberSettingLevel" ,ptGT_Choice ,1,0,0 ,2 ,GuiOptions->RememberSettingLevel ,tr("Remember setting level")},
143 {"CameraColor" ,ptGT_Choice ,1,1,1 ,ptCameraColor_Adobe_Profile ,GuiOptions->CameraColor ,tr("Transform camera RGB to working space RGB")},
144 {"CameraColorProfileIntent" ,ptGT_Choice ,1,1,1 ,INTENT_PERCEPTUAL ,GuiOptions->CameraColorProfileIntent ,tr("Intent of the profile")},
145 {"CameraColorGamma" ,ptGT_Choice ,1,1,1 ,ptCameraColorGamma_None ,GuiOptions->CameraColorGamma ,tr("Gamma that was applied before this profile")},
146 {"WorkColor" ,ptGT_Choice ,1,1,1 ,ptSpace_sRGB_D65 ,GuiOptions->WorkColor ,tr("Working colorspace")},
147 {"CMQuality" ,ptGT_Choice ,1,1,0 ,ptCMQuality_FastSRGB ,GuiOptions->CMQuality ,tr("Color management quality")},
148 {"PreviewColorProfileIntent" ,ptGT_Choice ,1,0,1 ,INTENT_PERCEPTUAL ,GuiOptions->PreviewColorProfileIntent ,tr("Intent of the profile")},
149 {"OutputColorProfileIntent" ,ptGT_Choice ,1,1,1 ,INTENT_PERCEPTUAL ,GuiOptions->OutputColorProfileIntent ,tr("Intent of the profile")},
150 {"SaveButtonMode" ,ptGT_Choice ,1,0,1 ,ptOutputMode_Pipe ,GuiOptions->OutputMode ,tr("Output mode of save button")},
151 {"ResetButtonMode" ,ptGT_Choice ,1,0,1 ,ptResetMode_User ,GuiOptions->ResetMode ,tr("Output mode of reset button")},
152 {"Style" ,ptGT_Choice ,1,0,0 ,ptStyle_DarkGrey ,GuiOptions->Style ,tr("Set the theme.")},
153 {"StyleHighLight" ,ptGT_Choice ,1,0,0 ,ptStyleHighLight_Green ,GuiOptions->StyleHighLight ,tr("Set the highlight color of the theme.")},
154 {"StartupUIMode" ,ptGT_Choice ,1,0,0 ,ptStartupUIMode_Tab ,GuiOptions->StartupUIMode ,tr("Set the start up mode for the UI.")},
155 {"PipeSize" ,ptGT_Choice ,2,0,1 ,ptPipeSize_Quarter ,GuiOptions->PipeSize ,tr("Size of image processed vs original.")},
156 {"StartupPipeSize" ,ptGT_Choice ,1,0,1 ,ptPipeSize_Quarter ,GuiOptions->PipeSize ,tr("Initial pipe size when Photivo starts.")},
157 {"SpecialPreview" ,ptGT_Choice ,2,0,1 ,ptSpecialPreview_RGB ,GuiOptions->SpecialPreview ,tr("Special preview for image analysis")},
158 {"BadPixels" ,ptGT_Choice ,1,1,0 ,0 ,GuiOptions->BadPixels ,tr("Bad pixels file")},
159 {"DarkFrame" ,ptGT_Choice ,1,1,0 ,0 ,GuiOptions->DarkFrame ,tr("Darkframe file")},
160 {"WhiteBalance" ,ptGT_Choice ,2,1,1 ,ptWhiteBalance_Camera ,GuiOptions->WhiteBalance ,tr("WhiteBalance")},
161 {"CaCorrect" ,ptGT_Choice ,2,1,1 ,ptCACorrect_Off ,GuiOptions->CACorrect ,tr("CA correction")},
162 {"Interpolation" ,ptGT_Choice ,2,1,1 ,ptInterpolation_DCB ,GuiOptions->Interpolation ,tr("Demosaicing algorithm")},
163 {"BayerDenoise" ,ptGT_Choice ,2,1,1 ,ptBayerDenoise_None ,GuiOptions->BayerDenoise ,tr("Denosie on Bayer pattern")},
164
165 {"CropGuidelines" ,ptGT_Choice ,1,0,0 ,ptGuidelines_GoldenRatio ,GuiOptions->CropGuidelines ,tr("Guide lines for crop")},
166 {"LightsOut" ,ptGT_Choice ,1,0,0 ,ptLightsOutMode_Dimmed ,GuiOptions->LightsOutMode ,tr("Dim areas outside the crop rectangle")},
167 {"ClipMode" ,ptGT_Choice ,1,1,1 ,ptClipMode_Blend ,GuiOptions->ClipMode ,tr("How to handle clipping")},
168 {"LfunCAModel" ,ptGT_Choice ,2,1,1 ,ptLfunCAModel_None ,GuiOptions->LfunCAModel ,tr("Mathematical model for CA correction")},
169 {"LfunVignetteModel" ,ptGT_Choice ,2,1,1 ,ptLfunVignetteModel_None ,GuiOptions->LfunVignetteModel ,tr("Mathematical model for vignetting correction")},
170 {"LfunSrcGeo" ,ptGT_Choice ,2,1,1 ,ptLfunGeo_Unknown ,GuiOptions->LfunGeo ,tr("Geometry of the lens the image was taken with")},
171 {"LfunTargetGeo" ,ptGT_Choice ,2,1,1 ,ptLfunGeo_Unknown ,GuiOptions->LfunGeo ,tr("Convert image to this lens geometry")},
172 {"LfunDistModel" ,ptGT_Choice ,2,1,1 ,ptLfunDistModel_None ,GuiOptions->LfunDistModel ,tr("Mathematical distortion model to apply to the image")},
173 {"LqrEnergy" ,ptGT_Choice ,2,1,1 ,ptLqr_Disabled ,GuiOptions->LqrEnergy ,tr("Energy method for liquid rescale")},
174 {"LqrScaling" ,ptGT_Choice ,1,1,1 ,ptLqr_ScaleRelative ,GuiOptions->LqrScaling ,tr("Scaling method for liquid rescale")},
175 {"ResizeFilter" ,ptGT_Choice ,1,1,1 ,ptIMFilter_Mitchell ,GuiOptions->IMResizeFilter ,tr("Filter to be used for resizing")},
176 {"ResizeDimension" ,ptGT_Choice ,2,1,1 ,ptResizeDimension_LongerEdge,GuiOptions->ResizeDimension ,tr("Image dimension the resize value applies to")},
177 {"FlipMode" ,ptGT_Choice ,2,1,1 ,ptFlipMode_None ,GuiOptions->FlipMode ,tr("Flip mode")},
178 {"AspectRatioW" ,ptGT_Choice ,2,0,0 ,3 ,GuiOptions->AspectRatio ,tr("Aspect width")},
179 {"AspectRatioH" ,ptGT_Choice ,2,0,0 ,2 ,GuiOptions->AspectRatio ,tr("Aspect height")},
180 {"WebResize" ,ptGT_Choice ,2,1,1 ,ptEnable_None ,GuiOptions->Enable ,tr("Enable web resizing")},
181 {"WebResizeDimension" ,ptGT_Choice ,2,1,1 ,ptResizeDimension_LongerEdge,GuiOptions->WebResizeDimension ,tr("Image dimension the resize value applies to")},
182 {"WebResizeFilter" ,ptGT_Choice ,1,1,1 ,ptIMFilter_Lanczos ,GuiOptions->IMResizeFilter ,tr("Filter to be used for resizing")},
183 {"SaveFormat" ,ptGT_Choice ,1,1,1 ,ptSaveFormat_JPEG ,GuiOptions->SaveFormat ,tr("Output format")},
184 {"SaveSampling" ,ptGT_Choice ,1,1,1 ,ptSaveSampling_211 ,GuiOptions->SaveSampling ,tr("JPEG color sampling")},
185 {"CropInitialZoom" ,ptGT_Choice ,1,0,1 ,ptZoomLevel_Fit ,GuiOptions->ZoomLevel ,tr("Switch to this zoom level when starting to crop.")}
186 };
187
188 // Load in the gui check elements
189 const ptGuiCheckItem GuiCheckItems[] = {
190 // Name GuiType,InitLevel,InJobFile,Default,Label,Tip
191 {"FileMgrUseThumbMaxRowCol" ,ptGT_Check ,1,0,0,tr("At most") ,tr("Maximum number of thumbnails that should be placed in a row or column.")},
192 {"FileMgrStartupOpen" ,ptGT_Check ,1,0,0,tr("Open file manager on startup"), tr("Opens the file manager when Photivo starts without an image")},
193
194 {"BatchMgrAutosave" ,ptGT_Check ,1,0,1,tr("Automatically save batch list"), tr("Automatically save current batch list")},
195 {"BatchMgrAutoload" ,ptGT_Check ,1,0,0,tr("Automatically load batch list"), tr("Automatically load previous batch list saved to standard path on startup")},
196
197 {"StartupSettings" ,ptGT_Check ,1,0,1,tr("User settings") ,tr("Load user settings on startup")},
198 {"StartupSettingsReset" ,ptGT_Check ,1,0,0,tr("Reset on new image") ,tr("Reset to user settings when new image is opened")},
199 {"StartupSwitchAR" ,ptGT_Check ,1,0,1,tr("Adjust aspect ratio") ,tr("Adjust crop aspect ratio to image aspect ratio")},
200 {"InputsAddPowerLaw" ,ptGT_Check ,1,1,1,tr("Nonlinear slider response") ,tr("Alter the slider behaviour")},
201 {"ExportToGimp" ,ptGT_Check ,1,0,1,tr("Use gimp plugin") ,tr("Use gimp plugin for export")},
202 {"ToolBoxMode" ,ptGT_Check ,1,0,0,tr("Enabled") ,tr("Show seperate toolboxes")},
203 {"PreviewTabMode" ,ptGT_Check ,1,0,0,tr("Tab mode") ,tr("Show the preview after the active tab")},
204 {"BackgroundColor" ,ptGT_Check ,1,0,0,tr("Override default"),tr("Override the default color")},
205 {"SearchBarEnable" ,ptGT_Check ,1,0,1,tr("Display search bar"),tr("Display search bar")},
206 {"WriteBackupSettings" ,ptGT_Check ,1,0,0,tr("Backup settings") ,tr("Write backup settings during processing")},
207 {"RunMode" ,ptGT_Check ,1,0,0,tr("manual") ,tr("manual or automatic pipe")},
208 {"UseThumbnail" ,ptGT_Check ,1,1,0,tr("Use thumbnail") ,tr("Use the embedded thumbnail of RAW images")},
209 {"MultiplierEnhance" ,ptGT_Check ,1,1,0,tr("Intensify") ,tr("Normalize lowest channel to 1")},
210 {"ManualBlackPoint" ,ptGT_Check ,2,1,0,tr("Manual BP") ,tr("Manual black point setting enabled")},
211 {"ManualWhitePoint" ,ptGT_Check ,2,1,0,tr("Manual WP") ,tr("Manual white point setting enabled")},
212 {"EeciRefine" ,ptGT_Check ,2,1,0,tr("Eeci refinement") ,tr("Eeci refinement")},
213 {"LfunAutoScale" ,ptGT_Check ,2,1,0,tr("Auto scale") ,tr("Auto scale to avoid black borders after distortion correction or geometry conversion.")},
214 {"Defish" ,ptGT_Check ,2,1,0,tr("Enable") ,tr("Enable defishing")},
215 {"DefishAutoScale" ,ptGT_Check ,2,1,0,tr("Auto scale") ,tr("Auto scale to avoid black borders")},
216 {"Grid" ,ptGT_Check ,9,1,0,tr("Grid") ,tr("Enable the overlay grid")},
217 {"Crop" ,ptGT_Check ,9,1,0,tr("Crop") ,tr("Enable to make a crop")},
218 {"FixedAspectRatio" ,ptGT_Check ,1,0,0,tr("Aspect Ratio") ,tr("Crop with a fixed aspect ratio")},
219 {"LqrVertFirst" ,ptGT_Check ,2,1,0,tr("Vertical first") ,tr("Resizing starts with vertical direction")},
220 {"Resize" ,ptGT_Check ,9,1,0,tr("Resize") ,tr("Enable resize")},
221 {"AutomaticPipeSize" ,ptGT_Check ,1,1,0,tr("Automatic pipe size") ,tr("Automatic pipe size")},
222 {"GeometryBlock" ,ptGT_Check ,9,0,0,tr("Block pipe") ,tr("Disable the pipe")},
223 {"WebResizeBeforeGamma" ,ptGT_Check ,1,1,0,tr("before gamma") ,tr("Webresizing before gamma compensation")},
224 {"OutputGammaCompensation" ,ptGT_Check ,1,1,0,tr("sRGB gamma compensation") ,tr("sRGB gamma compensation")},
225 {"IncludeExif" ,ptGT_Check ,2,1,1,tr("Include metadata"),tr("Include metadata (only in jpeg and tiff)")},
226 {"EraseExifThumbnail" ,ptGT_Check ,2,1,1,tr("Erase thumbnail") ,tr("Erase the exif thumbnail (only in jpeg and tiff)")},
227 {"SaveConfirmation" ,ptGT_Check ,1,0,1,tr("Save image") ,tr("Confirm any action that would discard an unsaved image")},
228 {"AutosaveSettings" ,ptGT_Check ,1,0,1,tr("Autosave settings"),tr("Autosave settings when loading another image (if save confirmation is off)")},
229 {"ResetSettingsConfirmation" ,ptGT_Check, 1,0,1,tr("Reset settings") ,tr("Confirm resetting settings or dropping a settings file onto an image")},
230 {"FullPipeConfirmation" ,ptGT_Check ,1,0,1,tr("Switch to 1:1 pipe"), tr("Confirm switch to the full sized pipe")},
231 {"EscToExit" ,ptGT_Check ,1,0,0,tr("Esc key exits Photivo"),tr("Use the Esc key not only to exit special view modes (e.g. full screen) but also to close Photivo.")},
232 {"LoadTags" ,ptGT_Check ,1,0,0,tr("Load tags from sidecar files"),tr("Load tags from sidecar XMP files when opening an image.")}
233 };
234
235 // Load in the non gui elements
236 const ptItem Items[] = {
237 // Name InitLevel Default JobFile
238 {"PipeIsRunning" ,9 ,0 ,0},
239 {"BlockTools" ,9 ,0 ,0},
240 {"InputPowerFactor" ,0 ,2.2 ,1},
241 {"PreviewMode" ,1 ,ptPreviewMode_End ,0},
242 {"ZoomMode" ,9 ,ptZoomMode_Fit ,0},
243 {"Scaled" ,9 ,0 ,0},
244 {"IsRAW" ,9 ,1 ,0},
245 {"HaveImage" ,9 ,0 ,0},
246 {"RawsDirectory" ,0 ,"" ,0},
247 {"OutputDirectory" ,0 ,"" ,1},
248 {"MainDirectory" ,0 ,"@INSTALL@/" ,0},
249 {"ShareDirectory" ,0 ,"@INSTALL@/" ,1},
250 {"UserDirectory" ,0 ,"@INSTALL@/" ,1},
251 {"UIDirectory" ,0 ,"@INSTALL@/UISettings" ,0},
252 {"TranslationsDirectory" ,0 ,"@INSTALL@/Translations" ,0},
253 {"CurvesDirectory" ,0 ,"@INSTALL@/Curves" ,1},
254 {"ChannelMixersDirectory" ,0 ,"@INSTALL@/ChannelMixers" ,1},
255 {"PresetDirectory" ,0 ,"@INSTALL@/Presets" ,0},
256 {"CameraColorProfilesDirectory" ,0 ,"@INSTALL@/Profiles/Camera" ,1},
257 {"PreviewColorProfilesDirectory" ,0 ,"@INSTALL@/Profiles/Preview" ,0},
258 {"OutputColorProfilesDirectory" ,0 ,"@INSTALL@/Profiles/Output" ,1},
259 {"StandardAdobeProfilesDirectory" ,0 ,"@INSTALL@/Profiles/Camera/Standard" ,1},
260 {"LensfunDatabaseDirectory" ,0 ,"@INSTALL@/LensfunDatabase" ,1},
261 {"PreviewColorProfile" ,1 ,"@INSTALL@/Profiles/Preview/sRGB.icc" ,1},
262 {"OutputColorProfile" ,1 ,"@INSTALL@/Profiles/Output/sRGB.icc" ,1},
263 {"GimpExecCommand" ,1 ,"gimp" ,0},
264 {"StartupSettingsFile" ,1 ,"@INSTALL@/Presets/MakeFancy.pts" ,0},
265 {"CameraMake" ,9 ,"" ,0},
266 {"CameraModel" ,9 ,"" ,0},
267 {"CameraColorProfile" ,1 ,"" ,1},
268 {"HaveBadPixels" ,1 ,0 ,1},
269 {"BadPixelsFileName" ,1 ,"" ,1},
270 {"HaveDarkFrame" ,1 ,0 ,1},
271 {"DarkFrameFileName" ,1 ,"" ,1},
272 {"Sidecar" ,1 ,"" ,1},
273 {"VisualSelectionX" ,9 ,0 ,1},
274 {"VisualSelectionY" ,9 ,0 ,1},
275 {"VisualSelectionWidth" ,9 ,0 ,1},
276 {"VisualSelectionHeight" ,9 ,0 ,1},
277 {"ImageW" ,9 ,0 ,0},
278 {"ImageH" ,9 ,0 ,0},
279 {"PipeImageW" ,9 ,0 ,0},
280 {"PipeImageH" ,9 ,0 ,0},
281 {"CropX" ,9 ,0 ,1},
282 {"CropY" ,9 ,0 ,1},
283 {"CropW" ,9 ,0 ,1},
284 {"CropH" ,9 ,0 ,1},
285 {"RotateW" ,9 ,0 ,1},
286 {"RotateH" ,9 ,0 ,1},
287 {"ExposureNormalization" ,9 ,0.0 ,0},
288 {"CurveFileNamesRGB" ,0 ,QStringList() ,1},
289 {"CurveFileNamesR" ,0 ,QStringList() ,1},
290 {"CurveFileNamesG" ,0 ,QStringList() ,1},
291 {"CurveFileNamesB" ,0 ,QStringList() ,1},
292 {"CurveFileNamesL" ,0 ,QStringList() ,1},
293 {"CurveFileNamesLa" ,0 ,QStringList() ,1},
294 {"CurveFileNamesLb" ,0 ,QStringList() ,1},
295 {"CurveFileNamesOutline" ,0 ,QStringList() ,1},
296 {"CurveFileNamesLByHue" ,0 ,QStringList() ,1},
297 {"CurveFileNamesHue" ,0 ,QStringList() ,1},
298 {"CurveFileNamesTexture" ,0 ,QStringList() ,1},
299 {"CurveFileNamesSaturation" ,0 ,QStringList() ,1},
300 {"CurveFileNamesBase" ,0 ,QStringList() ,1},
301 {"CurveFileNamesBase2" ,0 ,QStringList() ,1},
302 {"CurveFileNamesShadowsHighlights" ,0 ,QStringList() ,1},
303 {"CurveFileNamesDenoise" ,0 ,QStringList() ,1},
304 {"CurveFileNamesDenoise2" ,0 ,QStringList() ,1},
305 {"OutputFileName" ,9 ,"" ,0}, // Not in JobFile. Constructed.
306 {"JobMode" ,9 ,0 ,0}, // Not in JobFile !! Overwrites else.
307 {"InputFileNameList" ,9 ,QStringList() ,1},
308 {"DigikamTagsList" ,9 ,QStringList() ,1},
309 {"TagsList" ,9 ,QStringList() ,1},
310 {"OutputFileNameSuffix" ,9 ,"" ,1},
311 {"ImageTitle" ,9 ,"" ,1},
312 {"Copyright" ,1 ,"" ,1},
313 {"BackgroundRed" ,1 ,0 ,0},
314 {"BackgroundGreen" ,1 ,0 ,0},
315 {"BackgroundBlue" ,1 ,0 ,0},
316 {"HistogramChannel" ,1 ,ptHistogramChannel_RGB ,0},
317 {"HistogramLogX" ,1 ,0 ,0},
318 {"HistogramLogY" ,1 ,1 ,0},
319 {"HistogramMode" ,1 ,ptHistogramMode_Preview ,0},
320 {"HistogramCrop" ,9 ,0 ,0},
321 {"HistogramCropX" ,9 ,0 ,0},
322 {"HistogramCropY" ,9 ,0 ,0},
323 {"HistogramCropW" ,9 ,0 ,0},
324 {"HistogramCropH" ,9 ,0 ,0},
325 {"PixelReader" ,1 ,0 ,0},
326 {"ExposureIndicator" ,1 ,0 ,0},
327 {"ExposureIndicatorSensor" ,0 ,0 ,0},
328 {"ExposureIndicatorR" ,0 ,1 ,0},
329 {"ExposureIndicatorG" ,0 ,1 ,0},
330 {"ExposureIndicatorB" ,0 ,1 ,0},
331 {"ExposureIndicatorOver" ,0 ,1 ,0},
332 {"ExposureIndicatorUnder" ,0 ,1 ,0},
333 {"ShowExposureIndicatorSensor" ,0 ,0 ,0},
334 {"ShowBottomContainer" ,1 ,1 ,0},
335 {"ShowToolContainer" ,9 ,1 ,0},
336 {"SatCurveType" ,1 ,0 ,1},
337 {"TextureCurveType" ,1 ,0 ,1},
338 {"DenoiseCurveType" ,1 ,0 ,1},
339 {"Denoise2CurveType" ,1 ,0 ,1},
340 {"HueCurveType" ,1 ,0 ,1},
341 {"FullOutput" ,9 ,0 ,0},
342 {"HiddenTools" ,0 ,QStringList(Fuid::LumaDenoiseCurve2_LabSN)
343 ,1},
344 {"FavouriteTools" ,0 ,QStringList() ,0},
345 {"BlockedTools" ,0 ,QStringList() ,1},
346 {"DisabledTools" ,9 ,QStringList() ,0},
347 {"BlockUpdate" ,9 ,0 ,0},
348 {"FocalLengthIn35mmFilm" ,0 ,0.0 ,0},
349 {"ApertureFromExif" ,0 ,0.0 ,0}, // aperture from exif data
350 {"DetailViewActive" ,9 ,0 ,0},
351 {"DetailViewScale" ,9 ,0 ,0},
352 {"DetailViewCropX" ,9 ,0 ,0},
353 {"DetailViewCropY" ,9 ,0 ,0},
354 {"DetailViewCropW" ,9 ,0 ,0},
355 {"DetailViewCropH" ,9 ,0 ,0},
356 {"TranslationMode" ,1 ,0 ,0}, // 0 no transl (English), 1 load qm file
357 {"UiLanguage" ,1 ,"" ,0}, // Language name to load from qm file, e.g. "Deutsch"
358 {"CustomCSSFile" ,1 ,"" ,0},
359 {"FullscreenActive" ,9 ,0 ,0},
360
361 // stuff for the file manager
362 {"PreventFileMgrStartup" ,9 ,0 ,0},
363 {"FileMgrIsOpen" ,9 ,0 ,0},
364 {"LastFileMgrLocation" ,1 ,"" ,0},
365 {"FileMgrShowDirThumbs" ,1 ,1 ,0},
366 {"FileMgrShowImageView" ,1 ,1 ,0},
367 {"FileMgrShowSidebar" ,1 ,1 ,0},
368 {"FileMgrThumbLayoutType" ,1 ,tlVerticalByRow ,0},
369 {"FileMgrShowRAWs" ,1 ,1 ,0},
370 {"FileMgrShowBitmaps" ,1 ,1 ,0},
371 {"BatchIsOpen" ,9 ,0 ,0},
372 {"BatchLogIsVisible" ,1 ,0 ,0}
373 };
374
375 // Gui Numerical inputs. Copy them from the const array in ptSettingItem.
376 short NrSettings = sizeof(GuiInputItems)/sizeof(ptGuiInputItem);
377 for (short i=0; i<NrSettings; i++) {
378 ptGuiInputItem Description = GuiInputItems[i];
379 ptSettingItem* SettingItem = new ptSettingItem;
380 SettingItem->GuiType = Description.GuiType;
381 SettingItem->InitLevel = Description.InitLevel;
382 SettingItem->InJobFile = Description.InJobFile;
383 SettingItem->HasDefaultValue = Description.HasDefaultValue;
384 SettingItem->DefaultValue = Description.DefaultValue;
385 SettingItem->MinimumValue = Description.MinimumValue;
386 SettingItem->MaximumValue = Description.MaximumValue;
387 SettingItem->Step = Description.Step;
388 SettingItem->NrDecimals = Description.NrDecimals;
389 SettingItem->Label = Description.Label;
390 SettingItem->ToolTip = Description.ToolTip;
391 M_InsertKeyIntoHash(Description.KeyName,SettingItem);
392 }
393 // Gui Choice inputs. Copy them from the const array in ptSettingItem.
394 NrSettings = sizeof(GuiChoiceItems)/sizeof(ptGuiChoiceItem);
395 for (short i=0; i<NrSettings; i++) {
396 ptGuiChoiceItem Description = GuiChoiceItems[i];
397 ptSettingItem* SettingItem = new ptSettingItem;
398 SettingItem->GuiType = Description.GuiType;
399 SettingItem->InitLevel = Description.InitLevel;
400 SettingItem->InJobFile = Description.InJobFile;
401 SettingItem->HasDefaultValue = Description.HasDefaultValue;
402 SettingItem->DefaultValue = Description.DefaultValue;
403 SettingItem->Value = Description.DefaultValue;
404 SettingItem->ToolTip = Description.ToolTip;
405 SettingItem->InitialOptions = Description.InitialOptions;
406 M_InsertKeyIntoHash(Description.KeyName,SettingItem);
407 }
408 // Gui Check inputs. Copy them from the const array in ptSettingItem.
409 NrSettings = sizeof(GuiCheckItems)/sizeof(ptGuiCheckItem);
410 for (short i=0; i<NrSettings; i++) {
411 ptGuiCheckItem Description = GuiCheckItems[i];
412 ptSettingItem* SettingItem = new ptSettingItem;
413 SettingItem->GuiType = Description.GuiType;
414 SettingItem->InitLevel = Description.InitLevel;
415 SettingItem->InJobFile = Description.InJobFile;
416 SettingItem->DefaultValue = Description.DefaultValue;
417 SettingItem->Value = Description.DefaultValue;
418 SettingItem->Label = Description.Label;
419 SettingItem->ToolTip = Description.ToolTip;
420 M_InsertKeyIntoHash(Description.KeyName,SettingItem);
421 }
422 // Non gui elements
423 NrSettings = sizeof(Items)/sizeof(ptItem);
424 for (short i=0; i<NrSettings; i++) {
425 ptItem Description = Items[i];
426 ptSettingItem* SettingItem = new ptSettingItem;
427 SettingItem->GuiType = ptGT_None;
428 SettingItem->InitLevel = Description.InitLevel;
429 if (Description.DefaultValue.type() == QVariant::String) {
430 QString Tmp = Description.DefaultValue.toString();
431 Tmp.replace(QString("@INSTALL@"),QCoreApplication::applicationDirPath());
432 Description.DefaultValue = Tmp;
433 }
434 SettingItem->DefaultValue = Description.DefaultValue;
435 SettingItem->Value = Description.DefaultValue;
436 SettingItem->InJobFile = Description.InJobFile;
437 M_InsertKeyIntoHash(Description.KeyName,SettingItem);
438 }
439
440 // Now we have initialized from static values.
441 // In the second round we overwrite now with what's coming from the ini
442 // files.
443
444 // Persistent settings.
445 m_IniSettings = new QSettings(Path + "photivo.ini", QSettings::IniFormat);
446
447 QStringList Keys = m_Hash.keys();
448 for (int i=0; i<Keys.size(); i++) {
449 QString Key = Keys[i];
450 ptSettingItem* Setting = m_Hash[Key];
451
452 if (InitLevel > Setting->InitLevel) {
453 // Default needs to be overwritten by something coming from ini file.
454 Setting->Value = m_IniSettings->value(Key,Setting->DefaultValue);
455 // Correction needed as the values coming from the ini file are
456 // often interpreted as strings even if they could be int or so.
457 const QVariant::Type TargetType = Setting->DefaultValue.type();
458 if (Setting->Value.type() != TargetType) {
459 if (TargetType == QVariant::Int ||
460 TargetType == QVariant::UInt) {
461 Setting->Value = Setting->Value.toInt();
462 } else if (TargetType == QVariant::Double ||
463 (QMetaType::Type) TargetType == QMetaType::Float) {
464 Setting->Value = Setting->Value.toDouble();
465 } else if (TargetType == QVariant::StringList) {
466 Setting->Value = Setting->Value.toStringList();
467 } else {
468 ptLogError(ptError_Argument,"Unexpected type %d",TargetType);
469 assert(0);
470 }
471 }
472 // Seen above this shouldn't happen, but better safe then sorry.
473 if (Setting->Value.type() != Setting->DefaultValue.type()) {
474 ptLogError(ptError_Argument,
475 "Type conversion error from ini file. Should : %d Is : %d\n",
476 Setting->DefaultValue.type(),Setting->Value.type());
477 assert(Setting->Value.type() == Setting->DefaultValue.type());
478 }
479 } else {
480 Setting->Value = Setting->DefaultValue;
481 }
482 }
483
484 // Some ad-hoc corrections
485 QFileInfo PathInfo(GetValue("PreviewColorProfile").toString());
486 SetValue("PreviewColorProfile",PathInfo.absoluteFilePath());
487 PathInfo.setFile(GetValue("PreviewColorProfile").toString());
488 SetValue("PreviewColorProfile",PathInfo.absoluteFilePath());
489 SetValue("Scaled",GetValue("PipeSize"));
490 };
491
492 ////////////////////////////////////////////////////////////////////////////////
493 //
494 // Destructor
495 // Basically dumping the whole Settings hash to ini files.
496 //
497 ////////////////////////////////////////////////////////////////////////////////
498
~ptSettings()499 ptSettings::~ptSettings() {
500 QStringList Keys = m_Hash.keys();
501 for (int i=0; i<Keys.size(); i++) {
502 QString Key = Keys[i];
503 ptSettingItem* Setting = m_Hash[Key];
504 m_IniSettings->setValue(Key,Setting->Value);
505 }
506 // Explicit call destructor (such that synced to disk)
507 delete m_IniSettings;
508 }
509
510 ////////////////////////////////////////////////////////////////////////////////
511 //
512 // GetValue
513 // Access to the hash, but with protection on non existing key.
514 //
515 ////////////////////////////////////////////////////////////////////////////////
516
GetValue(const QString Key) const517 const QVariant ptSettings::GetValue(const QString Key) const {
518 if (!m_Hash.contains(Key)) {
519 ptLogError(ptError_Argument,
520 "(%s,%d) Could not find key '%s'\n",
521 __FILE__,__LINE__,Key.toLocal8Bit().data());
522 assert (m_Hash.contains(Key));
523 }
524 return m_Hash[Key]->Value;
525 }
526
527 ////////////////////////////////////////////////////////////////////////////////
528 //
529 // GetInt
530 //
531 ////////////////////////////////////////////////////////////////////////////////
532
GetInt(const QString Key) const533 int ptSettings::GetInt(const QString Key) const {
534 // Remark : UInt and Int are mixed here.
535 // The only settings related type where u is important is uint16_t
536 // (dimensions). uint16_t fits in an integer which is 32 bit.
537 QVariant Tmp = GetValue(Key);
538 if (Tmp.type() != QVariant::Int && Tmp.type() != QVariant::UInt) {
539 ptLogError(ptError_Argument,
540 "Expected 'QVariant::(U)Int' but got '%d' for key '%s'\n",
541 Tmp.type(),Key.toLocal8Bit().data());
542 if (Tmp.type() == QVariant::String) {
543 ptLogError(ptError_Argument,
544 "Additionally : it's a string '%s'\n",
545 Tmp.toString().toLocal8Bit().data());
546 }
547 assert(Tmp.type() == QVariant::Int);
548 }
549 return Tmp.toInt();
550 }
551
552 ////////////////////////////////////////////////////////////////////////////////
553 //
554 // GetDouble
555 //
556 ////////////////////////////////////////////////////////////////////////////////
557
GetDouble(const QString Key) const558 double ptSettings::GetDouble(const QString Key) const {
559 QVariant Tmp = GetValue(Key);
560 if (static_cast<QMetaType::Type>(Tmp.type()) == QMetaType::Float)
561 Tmp.convert(QVariant::Double);
562 if (Tmp.type() != QVariant::Double) {
563 ptLogError(ptError_Argument,
564 "Expected 'QVariant::Double' but got '%d' for key '%s'\n",
565 Tmp.type(),Key.toLocal8Bit().data());
566 assert(Tmp.type() == QVariant::Double);
567 }
568 return Tmp.toDouble();
569 }
570
571 ////////////////////////////////////////////////////////////////////////////////
572 //
573 // GetString
574 //
575 ////////////////////////////////////////////////////////////////////////////////
576
GetString(const QString Key) const577 const QString ptSettings::GetString(const QString Key) const {
578 QVariant Tmp = GetValue(Key);
579 if (Tmp.type() != QVariant::String) {
580 ptLogError(ptError_Argument,
581 "Expected 'QVariant::String' but got '%d' for key '%s'\n",
582 Tmp.type(),Key.toLocal8Bit().data());
583 assert(Tmp.type() == QVariant::String);
584 }
585 return Tmp.toString();
586 }
587
588 ////////////////////////////////////////////////////////////////////////////////
589 //
590 // GetStringList
591 //
592 ////////////////////////////////////////////////////////////////////////////////
593
GetStringList(const QString Key) const594 const QStringList ptSettings::GetStringList(const QString Key) const {
595 QVariant Tmp = GetValue(Key);
596 if (Tmp.type() != QVariant::StringList) {
597 ptLogError(ptError_Argument,
598 "Expected 'QVariant::StringList' but got '%d' for key '%s'\n",
599 Tmp.type(),Key.toLocal8Bit().data());
600 assert(Tmp.type() == QVariant::StringList);
601 }
602 return Tmp.toStringList();
603 }
604
605 ////////////////////////////////////////////////////////////////////////////////
606 //
607 // SetValue
608 // Access to the hash, but with protection on non existing key.
609 //
610 ////////////////////////////////////////////////////////////////////////////////
611
SetValue(const QString Key,const QVariant Value)612 void ptSettings::SetValue(const QString Key, const QVariant Value) {
613 if (!m_Hash.contains(Key)) {
614 ptLogError(ptError_Argument,
615 "(%s,%d) Could not find key '%s'\n",
616 __FILE__,__LINE__,Key.toLocal8Bit().data());
617 assert (m_Hash.contains(Key));
618 }
619 m_Hash[Key]->Value = Value;
620 // In job mode there are no gui elements and we have to return.
621 if (GetInt("JobMode")) return;
622 // If it's a gui element, we have to update it at once for consistency.
623 switch (m_Hash[Key]->GuiType) {
624 case ptGT_Input :
625 case ptGT_InputSlider :
626 case ptGT_InputSliderHue :
627 m_Hash[Key]->GuiInput->SetValue(Value);
628 break;
629 case ptGT_Choice :
630 m_Hash[Key]->GuiChoice->SetValue(Value);
631 break;
632 case ptGT_Check :
633 m_Hash[Key]->GuiCheck->SetValue(Value);
634 break;
635 default:
636 assert(m_Hash[Key]->GuiType == ptGT_None); // Else we missed a gui one
637 break;
638 }
639 }
640
641 ////////////////////////////////////////////////////////////////////////////////
642 //
643 // SetEnabled
644 // Enable the underlying gui element (if one)
645 //
646 ////////////////////////////////////////////////////////////////////////////////
647
SetEnabled(const QString Key,const short Enabled)648 void ptSettings::SetEnabled(const QString Key, const short Enabled) {
649 if (!m_Hash.contains(Key)) {
650 ptLogError(ptError_Argument,
651 "(%s,%d) Could not find key '%s'\n",
652 __FILE__,__LINE__,Key.toLocal8Bit().data());
653 assert (m_Hash.contains(Key));
654 }
655 switch (m_Hash[Key]->GuiType) {
656 case ptGT_Input :
657 case ptGT_InputSlider :
658 case ptGT_InputSliderHue :
659 m_Hash[Key]->GuiInput->SetEnabled(Enabled);
660 break;
661 case ptGT_Choice :
662 m_Hash[Key]->GuiChoice->SetEnabled(Enabled);
663 break;
664 case ptGT_Check :
665 m_Hash[Key]->GuiCheck->SetEnabled(Enabled);
666 break;
667 default:
668 ptLogError(ptError_Argument,
669 "%s is no (expected) gui element.",
670 Key.toLocal8Bit().data());
671 assert(m_Hash[Key]->GuiType); // Should have gui type !
672 break;
673 }
674 }
675
676 ////////////////////////////////////////////////////////////////////////////////
677 //
678 // SetMaximum
679 // Makes only sense for gui input element, which is asserted.
680 //
681 ////////////////////////////////////////////////////////////////////////////////
682
SetMaximum(const QString Key,const QVariant Maximum)683 void ptSettings::SetMaximum(const QString Key, const QVariant Maximum) {
684 if (!m_Hash.contains(Key)) {
685 ptLogError(ptError_Argument,
686 "Could not find key '%s'\n",
687 Key.toLocal8Bit().data());
688 assert (m_Hash.contains(Key));
689 }
690 if (!m_Hash[Key]->GuiInput) {
691 ptLogError(ptError_Argument,
692 "Key '%s' has no initialized GuiInput\n",
693 Key.toLocal8Bit().data());
694 assert (m_Hash[Key]->GuiChoice);
695 }
696 return m_Hash[Key]->GuiInput->SetMaximum(Maximum);
697 }
698
699 ////////////////////////////////////////////////////////////////////////////////
700 //
701 // Show (or hide)
702 // Makes only sense for gui element, which is asserted.
703 //
704 ////////////////////////////////////////////////////////////////////////////////
705
Show(const QString Key,const short Show)706 void ptSettings::Show(const QString Key, const short Show) {
707 if (!m_Hash.contains(Key)) {
708 ptLogError(ptError_Argument,
709 "(%s,%d) Could not find key '%s'\n",
710 __FILE__,__LINE__,Key.toLocal8Bit().data());
711 assert (m_Hash.contains(Key));
712 }
713 switch (m_Hash[Key]->GuiType) {
714 case ptGT_Input :
715 case ptGT_InputSlider :
716 case ptGT_InputSliderHue :
717 m_Hash[Key]->GuiInput->Show(Show);
718 break;
719 case ptGT_Choice :
720 m_Hash[Key]->GuiChoice->Show(Show);
721 break;
722 case ptGT_Check :
723 m_Hash[Key]->GuiCheck->Show(Show);
724 break;
725 default:
726 ptLogError(ptError_Argument,
727 "%s is no (expected) gui element.",
728 Key.toLocal8Bit().data());
729 assert(m_Hash[Key]->GuiType);
730 break;
731 }
732 }
733
734 ////////////////////////////////////////////////////////////////////////////////
735 //
736 // AddOrReplaceOption
737 // Makes only sense for gui choice (combo) element, which is asserted.
738 //
739 ////////////////////////////////////////////////////////////////////////////////
740
AddOrReplaceOption(const QString Key,const QString Text,const QVariant Value)741 void ptSettings::AddOrReplaceOption(const QString Key,
742 const QString Text,
743 const QVariant Value) {
744 // In job mode there are no gui elements and we have to return.
745 if (GetInt("JobMode")) return;
746 if (!m_Hash.contains(Key)) {
747 ptLogError(ptError_Argument,
748 "Could not find key '%s'\n",
749 Key.toLocal8Bit().data());
750 assert (m_Hash.contains(Key));
751 }
752 if (!m_Hash[Key]->GuiChoice) {
753 ptLogError(ptError_Argument,
754 "Key '%s' has no initialized GuiChoice\n",
755 Key.toLocal8Bit().data());
756 assert (m_Hash[Key]->GuiChoice);
757 }
758 m_Hash[Key]->GuiChoice->AddOrReplaceItem(Text,Value);
759 }
760
761 ////////////////////////////////////////////////////////////////////////////////
762 //
763 // ClearOptions
764 // Makes only sense for gui choice (combo) element, which is asserted.
765 //
766 ////////////////////////////////////////////////////////////////////////////////
767
ClearOptions(const QString Key,const short WithDefault)768 void ptSettings::ClearOptions(const QString Key, const short WithDefault) {
769 // In job mode there are no gui elements and we have to return.
770 if (GetInt("JobMode")) return;
771 if (!m_Hash.contains(Key)) {
772 ptLogError(ptError_Argument,
773 "Could not find key '%s'\n",
774 Key.toLocal8Bit().data());
775 assert (m_Hash.contains(Key));
776 }
777 if (!m_Hash[Key]->GuiChoice) {
778 ptLogError(ptError_Argument,
779 "Key '%s' has no initialized GuiChoice\n",
780 Key.toLocal8Bit().data());
781 assert (m_Hash[Key]->GuiChoice);
782 }
783 m_Hash[Key]->GuiChoice->Clear(WithDefault);
784 }
785
786 ////////////////////////////////////////////////////////////////////////////////
787 //
788 // GetNrOptions
789 // Makes only sense for gui choice (combo) element, which is asserted.
790 //
791 ////////////////////////////////////////////////////////////////////////////////
792
GetNrOptions(const QString Key)793 int ptSettings::GetNrOptions(const QString Key) {
794 if (!m_Hash.contains(Key)) {
795 ptLogError(ptError_Argument,
796 "Could not find key '%s'\n",
797 Key.toLocal8Bit().data());
798 assert (m_Hash.contains(Key));
799 }
800 if (!m_Hash[Key]->GuiChoice) {
801 ptLogError(ptError_Argument,
802 "Key '%s' has no initialized GuiChoice\n",
803 Key.toLocal8Bit().data());
804 assert (m_Hash[Key]->GuiChoice);
805 }
806 return m_Hash[Key]->GuiChoice->Count();
807 }
808
809 ////////////////////////////////////////////////////////////////////////////////
810 //
811 // GetOptionsValue (at index Index)
812 // Makes only sense for gui choice (combo) element, which is asserted.
813 //
814 ////////////////////////////////////////////////////////////////////////////////
815
GetOptionsValue(const QString Key,const int Index)816 const QVariant ptSettings::GetOptionsValue(const QString Key,const int Index){
817 if (!m_Hash.contains(Key)) {
818 ptLogError(ptError_Argument,
819 "Could not find key '%s'\n",
820 Key.toLocal8Bit().data());
821 assert (m_Hash.contains(Key));
822 }
823 if (!m_Hash[Key]->GuiChoice) {
824 ptLogError(ptError_Argument,
825 "Key '%s' has no initialized GuiChoice\n",
826 Key.toLocal8Bit().data());
827 assert (m_Hash[Key]->GuiChoice);
828 }
829 return m_Hash[Key]->GuiChoice->GetItemData(Index);
830 }
831
832 ////////////////////////////////////////////////////////////////////////////////
833 //
834 // GetCurrentText
835 // Makes only sense for gui choice (combo) element, which is asserted.
836 //
837 ////////////////////////////////////////////////////////////////////////////////
838
GetCurrentText(const QString Key)839 const QString ptSettings::GetCurrentText(const QString Key){
840 if (!m_Hash.contains(Key)) {
841 ptLogError(ptError_Argument,
842 "Could not find key '%s'\n",
843 Key.toLocal8Bit().data());
844 assert (m_Hash.contains(Key));
845 }
846 if (!m_Hash[Key]->GuiChoice) {
847 ptLogError(ptError_Argument,
848 "Key '%s' has no initialized GuiChoice\n",
849 Key.toLocal8Bit().data());
850 assert (m_Hash[Key]->GuiChoice);
851 }
852 return m_Hash[Key]->GuiChoice->CurrentText();
853 }
854
855 ////////////////////////////////////////////////////////////////////////////////
856 //
857 // SetGuiInput
858 //
859 ////////////////////////////////////////////////////////////////////////////////
860
SetGuiInput(const QString Key,ptInput * Value)861 void ptSettings::SetGuiInput(const QString Key, ptInput* Value) {
862 if (!m_Hash.contains(Key)) {
863 ptLogError(ptError_Argument,
864 "(%s,%d) Could not find key '%s'\n",
865 __FILE__,__LINE__,Key.toLocal8Bit().data());
866 assert (m_Hash.contains(Key));
867 }
868 m_Hash[Key]->GuiInput = Value;
869 m_Hash[Key]->GuiChoice = NULL;
870 m_Hash[Key]->GuiCheck = NULL;
871 }
872
873 ////////////////////////////////////////////////////////////////////////////////
874 //
875 // SetGuiChoice
876 //
877 ////////////////////////////////////////////////////////////////////////////////
878
SetGuiChoice(const QString Key,ptChoice * Value)879 void ptSettings::SetGuiChoice(const QString Key, ptChoice* Value) {
880 if (!m_Hash.contains(Key)) {
881 ptLogError(ptError_Argument,
882 "(%s,%d) Could not find key '%s'\n",
883 __FILE__,__LINE__,Key.toLocal8Bit().data());
884 assert (m_Hash.contains(Key));
885 }
886 m_Hash[Key]->GuiInput = NULL;
887 m_Hash[Key]->GuiChoice = Value;
888 m_Hash[Key]->GuiCheck = NULL;
889 }
890
891 ////////////////////////////////////////////////////////////////////////////////
892 //
893 // SetGuiCheck
894 //
895 ////////////////////////////////////////////////////////////////////////////////
896
SetGuiCheck(const QString Key,ptCheck * Value)897 void ptSettings::SetGuiCheck(const QString Key, ptCheck* Value) {
898 if (!m_Hash.contains(Key)) {
899 ptLogError(ptError_Argument,
900 "(%s,%d) Could not find key '%s'\n",
901 __FILE__,__LINE__,Key.toLocal8Bit().data());
902 assert (m_Hash.contains(Key));
903 }
904 m_Hash[Key]->GuiInput = NULL;
905 m_Hash[Key]->GuiChoice = NULL;
906 m_Hash[Key]->GuiCheck = Value;
907 }
908
909 ////////////////////////////////////////////////////////////////////////////////
910 //
911 // GetGuiWidget
912 // low level access to the underlying QWidget
913 //
914 ////////////////////////////////////////////////////////////////////////////////
915
GetGuiWidget(const QString Key)916 QWidget* ptSettings::GetGuiWidget(const QString Key) {
917 if (!m_Hash.contains(Key)) {
918 ptLogError(ptError_Argument,
919 "(%s,%d) Could not find key '%s'\n",
920 __FILE__,__LINE__,Key.toLocal8Bit().data());
921 assert (m_Hash.contains(Key));
922 }
923 if (m_Hash[Key]->GuiInput) {
924 return (QWidget*)m_Hash[Key]->GuiInput;
925 } else if (m_Hash[Key]->GuiChoice) {
926 return (QWidget*)m_Hash[Key]->GuiChoice;
927 } else if (m_Hash[Key]->GuiCheck) {
928 return (QWidget*)m_Hash[Key]->GuiCheck;
929 }
930
931 assert (!"No Gui widget");
932 return NULL;
933 }
934
935 ////////////////////////////////////////////////////////////////////////////////
936 //
937 // Transfer the settings from Settings To DcRaw UserSettings.
938 // This is sometimes not straightforward as DcRaw assumes certain
939 // combinations. That's taken care of here.
940 //
941 ////////////////////////////////////////////////////////////////////////////////
942
ToDcRaw(ptDcRaw * TheDcRaw)943 void ptSettings::ToDcRaw(ptDcRaw* TheDcRaw) {
944
945 if (!TheDcRaw) return;
946
947 // Relying on m_PipeSize being as defined in the constants ! (1<<Size)
948 TheDcRaw->m_UserSetting_HalfSize = GetInt("PipeSize");
949
950 // Input file name
951
952 QString InputFileName = GetStringList("InputFileNameList")[0];
953 FREE(TheDcRaw->m_UserSetting_InputFileName);
954 TheDcRaw->m_UserSetting_InputFileName =
955 (char*) MALLOC(1+strlen(InputFileName.toLocal8Bit().data()));
956 ptMemoryError(TheDcRaw->m_UserSetting_InputFileName,__FILE__,__LINE__);
957 strcpy(TheDcRaw->m_UserSetting_InputFileName,InputFileName.toLocal8Bit().data());
958
959 // Detail view
960 TheDcRaw->m_UserSetting_DetailView = Settings->GetInt("DetailViewActive");
961 TheDcRaw->m_UserSetting_DetailViewCropX = Settings->GetInt("DetailViewCropX");
962 TheDcRaw->m_UserSetting_DetailViewCropY = Settings->GetInt("DetailViewCropY");
963 TheDcRaw->m_UserSetting_DetailViewCropW = Settings->GetInt("DetailViewCropW");
964 TheDcRaw->m_UserSetting_DetailViewCropH = Settings->GetInt("DetailViewCropH");
965
966 // Adjust Maximum
967 TheDcRaw->m_UserSetting_AdjustMaximum = GetDouble("AdjustMaximumThreshold");
968
969 // Denoise.
970 TheDcRaw->m_UserSetting_DenoiseThreshold = GetInt("RawDenoiseThreshold");
971
972 // Hotpixel reduction
973 TheDcRaw->m_UserSetting_HotpixelReduction = GetDouble("HotpixelReduction");
974
975 // Bayer denoise
976 TheDcRaw->m_UserSetting_BayerDenoise = GetInt("BayerDenoise");
977
978 // Green equilibration
979 TheDcRaw->m_UserSetting_GreenEquil = GetInt("GreenEquil");
980
981 // CA auto correction
982 TheDcRaw->m_UserSetting_CaCorrect = GetInt("CaCorrect");
983 TheDcRaw->m_UserSetting_CaRed = GetDouble("CaRed");
984 TheDcRaw->m_UserSetting_CaBlue = GetDouble("CaBlue");
985
986 // CFA Line denoise
987 TheDcRaw->m_UserSetting_CfaLineDn = GetInt("CfaLineDenoise");
988
989 // Interpolation
990 TheDcRaw->m_UserSetting_Quality = GetInt("Interpolation");
991
992 // White balance settings.
993 switch (GetInt("WhiteBalance")) {
994 case ptWhiteBalance_Camera :
995 TheDcRaw->m_UserSetting_CameraWb = 1;
996 TheDcRaw->m_UserSetting_AutoWb = 0;
997 TheDcRaw->m_UserSetting_Multiplier[0] = 0.0;
998 TheDcRaw->m_UserSetting_Multiplier[1] = 0.0;
999 TheDcRaw->m_UserSetting_Multiplier[2] = 0.0;
1000 TheDcRaw->m_UserSetting_Multiplier[3] = 0.0;
1001 TheDcRaw->m_UserSetting_GreyBox[0] = 0;
1002 TheDcRaw->m_UserSetting_GreyBox[1] = 0;
1003 TheDcRaw->m_UserSetting_GreyBox[2] = 0xFFFF;
1004 TheDcRaw->m_UserSetting_GreyBox[3] = 0xFFFF;
1005 break;
1006 case ptWhiteBalance_Auto :
1007 TheDcRaw->m_UserSetting_CameraWb = 0;
1008 TheDcRaw->m_UserSetting_AutoWb = 1;
1009 TheDcRaw->m_UserSetting_Multiplier[0] = 0.0;
1010 TheDcRaw->m_UserSetting_Multiplier[1] = 0.0;
1011 TheDcRaw->m_UserSetting_Multiplier[2] = 0.0;
1012 TheDcRaw->m_UserSetting_Multiplier[3] = 0.0;
1013 TheDcRaw->m_UserSetting_GreyBox[0] = 0;
1014 TheDcRaw->m_UserSetting_GreyBox[1] = 0;
1015 TheDcRaw->m_UserSetting_GreyBox[2] = 0xFFFF;
1016 TheDcRaw->m_UserSetting_GreyBox[3] = 0xFFFF;
1017 break;
1018 case ptWhiteBalance_Spot :
1019 TheDcRaw->m_UserSetting_CameraWb = 0;
1020 TheDcRaw->m_UserSetting_AutoWb = 1; // GreyBox must have auto on !
1021 TheDcRaw->m_UserSetting_Multiplier[0] = 0.0;
1022 TheDcRaw->m_UserSetting_Multiplier[1] = 0.0;
1023 TheDcRaw->m_UserSetting_Multiplier[2] = 0.0;
1024 TheDcRaw->m_UserSetting_Multiplier[3] = 0.0;
1025
1026 // The selection, which is in preview coordinates, must
1027 // be transformed back to the original.
1028 // Express always in size of original image !
1029 // Also take into account TheDcRaw->m_Flip
1030
1031 { // Jump to case label issue.
1032 int TmpPipeSize = GetInt("PipeSize");
1033 uint16_t X = (1<<TmpPipeSize) * GetInt("VisualSelectionX");
1034 uint16_t Y = (1<<TmpPipeSize) * GetInt("VisualSelectionY");
1035 uint16_t W = (1<<TmpPipeSize) * GetInt("VisualSelectionWidth");
1036 uint16_t H = (1<<TmpPipeSize) * GetInt("VisualSelectionHeight");
1037
1038 uint16_t TargetW = W;
1039 uint16_t TargetH = H;
1040 if (TheDcRaw->m_Flip & 4) {
1041 SWAP(X,Y);
1042 SWAP(TargetW,TargetH);
1043 }
1044 if (TheDcRaw->m_Flip & 2) Y = GetInt("ImageH")-1-Y-TargetH;
1045 if (TheDcRaw->m_Flip & 1) X = GetInt("ImageW")-1-X-TargetW;
1046 TheDcRaw->m_UserSetting_GreyBox[0] = X;
1047 TheDcRaw->m_UserSetting_GreyBox[1] = Y;
1048 TheDcRaw->m_UserSetting_GreyBox[2] = TargetW;
1049 TheDcRaw->m_UserSetting_GreyBox[3] = TargetH;
1050 }
1051
1052 TRACEKEYVALS("GreyBox[0]","%d",TheDcRaw->m_UserSetting_GreyBox[0]);
1053 TRACEKEYVALS("GreyBox[1]","%d",TheDcRaw->m_UserSetting_GreyBox[1]);
1054 TRACEKEYVALS("GreyBox[2]","%d",TheDcRaw->m_UserSetting_GreyBox[2]);
1055 TRACEKEYVALS("GreyBox[3]","%d",TheDcRaw->m_UserSetting_GreyBox[3]);
1056
1057 break;
1058 default : // this entails as well manual as preset from ptWhiteBalances.
1059 TheDcRaw->m_UserSetting_CameraWb = 0;
1060 TheDcRaw->m_UserSetting_AutoWb = 0;
1061 TheDcRaw->m_UserSetting_Multiplier[0]= GetDouble("RMultiplier");
1062 TheDcRaw->m_UserSetting_Multiplier[1]= GetDouble("GMultiplier");
1063 TheDcRaw->m_UserSetting_Multiplier[2] =GetDouble("BMultiplier");
1064 TheDcRaw->m_UserSetting_Multiplier[3] =
1065 TheDcRaw->m_Colors == 4 ? GetDouble("GMultiplier") : 0.0;
1066 TheDcRaw->m_UserSetting_GreyBox[0] = 0;
1067 TheDcRaw->m_UserSetting_GreyBox[1] = 0;
1068 TheDcRaw->m_UserSetting_GreyBox[2] = 0xFFFF;
1069 TheDcRaw->m_UserSetting_GreyBox[3] = 0xFFFF;
1070 }
1071
1072 // Bad pixels settings.
1073 switch(GetInt("HaveBadPixels")) {
1074 case 0 : // None
1075 TheDcRaw->m_UserSetting_BadPixelsFileName = NULL;
1076 break;
1077 case 1 : // Load one : should not happen !
1078 assert(0);
1079 break;
1080 case 2 :
1081 FREE(TheDcRaw->m_UserSetting_BadPixelsFileName);
1082 TheDcRaw->m_UserSetting_BadPixelsFileName = (char *)
1083 MALLOC(1+
1084 strlen(GetString("BadPixelsFileName").toLocal8Bit().data()));
1085 ptMemoryError(TheDcRaw->m_UserSetting_BadPixelsFileName,
1086 __FILE__,__LINE__);
1087 strcpy(TheDcRaw->m_UserSetting_BadPixelsFileName,
1088 GetString("BadPixelsFileName").toLocal8Bit().data());
1089 break;
1090 default :
1091 assert(0);
1092 }
1093
1094 // Dark frame settings.
1095 switch(GetInt("HaveDarkFrame")) {
1096 case 0 : // None
1097 TheDcRaw->m_UserSetting_DarkFrameFileName = NULL;
1098 break;
1099 case 1 : // Load one : should not happen !
1100 assert(0);
1101 break;
1102 case 2 :
1103 FREE(TheDcRaw->m_UserSetting_DarkFrameFileName);
1104 TheDcRaw->m_UserSetting_DarkFrameFileName = (char *)
1105 MALLOC(1+
1106 strlen(GetString("DarkFrameFileName").toLocal8Bit().data()));
1107 ptMemoryError(TheDcRaw->m_UserSetting_DarkFrameFileName,
1108 __FILE__,__LINE__);
1109 strcpy(TheDcRaw->m_UserSetting_DarkFrameFileName,
1110 GetString("DarkFrameFileName").toLocal8Bit().data());
1111 break;
1112 default :
1113 assert(0);
1114 }
1115
1116 // Blackpoint settings.
1117 switch (GetInt("ManualBlackPoint")) {
1118 case 0 : // Automatic.
1119 TheDcRaw->m_UserSetting_BlackPoint = -1;
1120 break;
1121 default : // Manual set
1122 TheDcRaw->m_UserSetting_BlackPoint = GetInt("BlackPoint");
1123 break;
1124 }
1125
1126 // Whitepoint settings.
1127 switch (GetInt("ManualWhitePoint")) {
1128 case 0 : // Automatic.
1129 TheDcRaw->m_UserSetting_Saturation = -1;
1130 break;
1131 default : // Manual set
1132 TheDcRaw->m_UserSetting_Saturation = GetInt("WhitePoint");
1133 break;
1134 }
1135 // Normalization of Multipliers
1136 TheDcRaw->m_UserSetting_MaxMultiplier = GetInt("MultiplierEnhance");
1137
1138 // Interpolation passes.
1139 TheDcRaw->m_UserSetting_InterpolationPasses = GetInt("InterpolationPasses");
1140
1141 // Median Filter.
1142 TheDcRaw->m_UserSetting_MedianPasses = GetInt("MedianPasses");
1143 TheDcRaw->m_UserSetting_ESMedianPasses = GetInt("ESMedianPasses");
1144 TheDcRaw->m_UserSetting_EeciRefine = GetInt("EeciRefine");
1145
1146 // Clip factor
1147 TheDcRaw->m_UserSetting_photivo_ClipMode = GetInt("ClipMode");
1148 TheDcRaw->m_UserSetting_photivo_ClipParameter = GetInt("ClipParameter");
1149 }
1150
1151 ////////////////////////////////////////////////////////////////////////////////
1152 //
1153 // Transfers the settings from DcRaw back to the Gui.
1154 // In some situations , DcRaw can overwrite or calculate values.
1155 // The output of those are here fed back to the Gui settings such
1156 // that they are correctly reflected.
1157 //
1158 ////////////////////////////////////////////////////////////////////////////////
1159
FromDcRaw(ptDcRaw * TheDcRaw)1160 void ptSettings::FromDcRaw(ptDcRaw* TheDcRaw) {
1161
1162 if (!TheDcRaw) return;
1163
1164 // Copy make and model to our gui settings (f.i.
1165 // white balances rely on it)
1166 SetValue("CameraMake",TheDcRaw->m_CameraMake);
1167 SetValue("CameraModel",TheDcRaw->m_CameraModel);
1168
1169 // Reset spot white balance
1170 if (GetInt("WhiteBalance") == ptWhiteBalance_Spot)
1171 SetValue("WhiteBalance", ptWhiteBalance_Manual);
1172
1173 // Multipliers.
1174 SetValue("RMultiplier",VALUE(TheDcRaw->m_PreMultipliers[0]));
1175 SetValue("GMultiplier",VALUE(TheDcRaw->m_PreMultipliers[1]));
1176 SetValue("BMultiplier",VALUE(TheDcRaw->m_PreMultipliers[2]));
1177
1178 // (D65) Multipliers to ColorTemperature.
1179 //
1180 // m_D65Multipliers are supposed to be D65
1181 // (setting Pre to the ratio of the D65 delivers
1182 // rgbWB = (x,x,x) and 6500 temperature).
1183
1184 double RefRGB[3];
1185 if (TheDcRaw->m_RawColorPhotivo) {
1186 for (short c=0; c<3; c++) {
1187 RefRGB[c] = VALUE(TheDcRaw->m_D65Multipliers[c]) /
1188 VALUE(TheDcRaw->m_PreMultipliers[c]);
1189 }
1190 } else {
1191 // If not raw, we have to calculate back sRGB references to the cam rgb.
1192 for (short c=0; c<3; c++) {
1193 RefRGB[c] = 0;
1194 for (short cc=0; cc<TheDcRaw->m_Colors ; cc++) {
1195 RefRGB[c] += TheDcRaw->m_MatrixCamRGBToSRGB[c][cc] *
1196 VALUE(TheDcRaw->m_D65Multipliers[cc]) /
1197 VALUE(TheDcRaw->m_PreMultipliers[cc]);
1198 }
1199 }
1200 }
1201
1202 int TmpColorTemperature;
1203 double TmpGreenIntensity;
1204 RGBToTemperature(RefRGB,
1205 &TmpColorTemperature,
1206 &TmpGreenIntensity);
1207 SetValue("ColorTemperature",TmpColorTemperature);
1208 SetValue("GreenIntensity",TmpGreenIntensity);
1209
1210 // Blackpoint setting in case not manual.
1211 if (!GetInt("ManualBlackPoint")) {
1212 SetValue("BlackPoint",TheDcRaw->m_BlackLevel_AfterPhase1);
1213 }
1214
1215 // Whitepoint setting in case not manual.
1216 if (!GetInt("ManualWhitePoint")) {
1217 SetValue("WhitePoint",TheDcRaw->m_WhiteLevel_AfterPhase1);
1218 }
1219
1220 double exposureNormalization = 1.0;
1221
1222 // EOS exposure normalization might be a result of running DcRaw
1223 // (ie we have to normalize the exposure further in the flow.
1224 // TODO This is coming from ufraw. Seems fair, but no clue
1225 // what's the logic behind the calculation. Someone ?
1226 if (strcmp(TheDcRaw->m_CameraMake, "Canon")==0 &&
1227 strncmp(TheDcRaw->m_CameraModel, "EOS", 3)==0 ) {
1228 int Max = (int) VALUE(TheDcRaw->m_CameraMultipliers[0]);
1229 for (short c=1; c<TheDcRaw->m_Colors; c++) {
1230 if (VALUE(TheDcRaw->m_CameraMultipliers[c]) > Max) {
1231 Max = (int) VALUE(TheDcRaw->m_CameraMultipliers[c]);
1232 }
1233 }
1234 // The 100 is a pretty random value that makes sure above
1235 // was a 'right' number calculated and it's not bogus
1236 // due to for instance not being able reading CamMultipliers
1237 if ( Max > 100 ) {
1238 exposureNormalization =
1239 (4096.0-TheDcRaw->m_BlackLevel_AfterPhase1)/Max;
1240 }
1241 }
1242
1243 TRACEKEYVALS("EOSExposureNorm","%f",exposureNormalization);
1244
1245 SetValue("ExposureNormalization",
1246 // EV conversion !
1247 log(exposureNormalization/TheDcRaw->m_MinPreMulti)/log(2));
1248
1249 TRACEKEYVALS("ExposureNorm(EV)","%f", GetDouble("ExposureNormalization"));
1250 }
1251
1252 //==============================================================================
1253
useRAWHandling() const1254 bool ptSettings::useRAWHandling() const
1255 {
1256 return (GetInt("IsRAW") == 1) && (GetInt("UseThumbnail") == 0);
1257 }
1258
1259 ////////////////////////////////////////////////////////////////////////////////
1260 //
1261 // Tool Info
1262 // IsActive contains, if the filter will be processed!
1263 //
1264 ////////////////////////////////////////////////////////////////////////////////
1265
1266 struct sToolInfo {
1267 QString Name;
1268 short IsActive;
1269 short IsHidden;
1270 short IsBlocked;
1271 short IsDisabled;
1272 };
1273
ToolInfo(const QString GuiName)1274 sToolInfo ToolInfo (const QString GuiName) {
1275 sToolInfo Info = {"N.N.",0,0,0,0};
1276
1277 // Tab Geometry
1278 if (GuiName == "TabLensfunCA") {
1279 Info.Name = "Chromatic Aberration (Lensfun)";
1280 Info.IsActive = Settings->GetInt("LfunCAModel") != 0;
1281 } else if (GuiName == "TabLensfunVignette") {
1282 Info.Name = "Vignetting (Lensfun)";
1283 Info.IsActive = Settings->GetInt("LfunVignetteModel") != 0;
1284 } else if (GuiName == "TabLensfunDistortion") {
1285 Info.Name = "Lens Distortion (Lensfun)";
1286 Info.IsActive = Settings->GetInt("LfunDistModel") != 0;
1287 } else if (GuiName == "TabLensfunGeometry") {
1288 Info.Name = "Geometry Conversion (Lensfun)";
1289 Info.IsActive = Settings->GetInt("LfunSrcGeo") != Settings->GetInt("LfunTargetGeo");
1290 } else if (GuiName == "TabDefish") {
1291 Info.Name = "Defish";
1292 Info.IsActive = Settings->GetInt("Defish");
1293 } else if (GuiName == "TabRotation") {
1294 Info.Name = "Rotation";
1295 Info.IsActive = (Settings->GetDouble("Rotate")!=0.0f ||
1296 Settings->GetDouble("PerspectiveTilt")!=0.0f ||
1297 Settings->GetDouble("PerspectiveTurn")!=0.0f ||
1298 Settings->GetDouble("PerspectiveScaleX")!=1.0f ||
1299 Settings->GetDouble("PerspectiveScaleY")!=1.0f)?1:0;
1300 } else if (GuiName == "TabLiquidRescale") {
1301 Info.Name = "Seam carving";
1302 Info.IsActive = Settings->GetInt("LqrEnergy");
1303 } else if (GuiName == "TabCrop") {
1304 Info.Name = "Crop";
1305 Info.IsActive = Settings->GetInt("Crop");
1306 } else if (GuiName == "TabResize") {
1307 Info.Name = "Resize";
1308 Info.IsActive = Settings->GetInt("Resize");
1309 } else if (GuiName == "TabFlip") {
1310 Info.Name = "Flip";
1311 Info.IsActive = Settings->GetInt("FlipMode");
1312 } else if (GuiName == "TabBlock") {
1313 Info.Name = "Block";
1314 Info.IsActive = !Settings->GetInt("JobMode") &&
1315 Settings->GetInt("GeometryBlock");
1316 }
1317 // Tab Output
1318 else if (GuiName == "TabGammaCompensation") {
1319 Info.Name = "Output gamma compensation";
1320 Info.IsActive = Settings->GetInt("OutputGammaCompensation")!=0?1:0;
1321 } else if (GuiName == "TabWebResize") {
1322 Info.Name = "Output web resize";
1323 Info.IsActive = (Settings->GetInt("WebResize")==2 ||
1324 (Settings->GetInt("FullOutput") &&
1325 Settings->GetInt("WebResize")==1))!=0?1:0;
1326 }
1327
1328 // tool blocked?
1329 Info.IsBlocked = (Settings->GetStringList("BlockedTools")).contains(GuiName)?1:0;
1330
1331 // tool hidden?
1332 Info.IsHidden = (Settings->GetStringList("HiddenTools")).contains(GuiName)?1:0;
1333
1334 // tool disabled?
1335 Info.IsDisabled = (Settings->GetStringList("DisabledTools")).contains(GuiName)?1:0;
1336 return Info;
1337 }
1338
ToolAlwaysVisible(const QString GuiName) const1339 int ptSettings::ToolAlwaysVisible(const QString GuiName) const {
1340 QStringList VisibleTools =
1341 (QStringList()
1342 // Settings tab
1343 << "TabWorkColorSpace"
1344 << "TabPreviewColorSpace"
1345 << "TabUISettings"
1346 << "TabGimpCommand"
1347 << "TabRememberSettings"
1348 << "TabStartupSettings"
1349 << "TabCropSettings"
1350 << "TabInputControl"
1351 << "TabToolBoxControl"
1352 << "TabTabStatusIndicator"
1353 << "TabPreviewControl"
1354 << "TabTheming"
1355 << "TabConfigSaveMode"
1356 << "TabSearchBar"
1357 << "TabConfirmDialogs"
1358 << "TabBackupSettings"
1359 << "TabTranslation"
1360 << "TabMemoryTest"
1361 << "TabVisibleTools"
1362 << "TabFileMgrSettings"
1363 // Info tab
1364 << "TabInfoPhotivo"
1365 << "TabInfoFile"
1366 << "TabInfoExif"
1367 << "TabInfoSizes"
1368 // Input tab
1369 << "TabInput"
1370 << "TabCameraColorSpace"
1371 << "TabGenCorrections"
1372 << "TabWhiteBalance"
1373 << "TabDemosaicing"
1374 << "TabHighlightRecovery"
1375 // Output Tab
1376 << "TabOutputColorSpace"
1377 << "TabOutParameters"
1378 << "TabOutput");
1379 if (VisibleTools.contains(GuiName)) return 1;
1380 return 0;
1381 }
1382
ToolGetName(const QString GuiName) const1383 QString ptSettings::ToolGetName (const QString GuiName) const {
1384 sToolInfo Info = ToolInfo(GuiName);
1385 return Info.Name;
1386 }
1387
ToolIsActive(const QString GuiName) const1388 int ptSettings::ToolIsActive (const QString GuiName) const {
1389 sToolInfo Info = ToolInfo(GuiName);
1390 return (Info.IsHidden || Info.IsBlocked || Info.IsDisabled)?0:Info.IsActive;
1391 }
1392
ToolIsBlocked(const QString GuiName) const1393 int ptSettings::ToolIsBlocked (const QString GuiName) const {
1394 sToolInfo Info = ToolInfo(GuiName);
1395 return Info.IsBlocked;
1396 }
1397
ToolIsHidden(const QString GuiName) const1398 int ptSettings::ToolIsHidden (const QString GuiName) const {
1399 sToolInfo Info = ToolInfo(GuiName);
1400 return Info.IsHidden;
1401 }
1402 ///////////////////////////////////////////////////////////////////////////////
1403