1 /*******************************************************************************
2 **
3 ** Photivo
4 **
5 ** Copyright (C) 2008,2009 Jos De Laender <jos.de_laender@telenet.be>
6 ** Copyright (C) 2009-2012 Michael Munzert <mail@mm-log.com>
7 ** Copyright (C) 2010-2012 Bernd Schoeler <brjohn@brother-john.net>
8 ** Copyright (C) 2013 Alexander Tzyganenko <tz@fast-report.com>
9 **
10 ** This file is part of Photivo.
11 **
12 ** Photivo is free software: you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License version 3
14 ** as published by the Free Software Foundation.
15 **
16 ** Photivo is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ** GNU General Public License for more details.
20 **
21 ** You should have received a copy of the GNU General Public License
22 ** along with Photivo. If not, see <http://www.gnu.org/licenses/>.
23 **
24 *******************************************************************************/
25 #include "ptDefines.h"
26 #include "ptInfo.h"
27 #include "ptCalloc.h"
28 #include "ptConfirmRequest.h"
29 #include "ptConstants.h"
30 #include "ptMessageBox.h"
31 #include "ptDcRaw.h"
32 #include "ptProcessor.h"
33 #include "ptMainWindow.h"
34 #include "ptViewWindow.h"
35 #include "ptHistogramWindow.h"
36 #include "ptGuiOptions.h"
37 #include "ptSettings.h"
38 #include "ptError.h"
39 #include "ptRGBTemperature.h"
40 #include "ptWhiteBalances.h"
41 #include "ptCurve.h"
42 #include "ptTheme.h"
43 #include "ptWiener.h"
44 #include "ptParseCli.h"
45 #include "ptImageHelper.h"
46 #include "filters/imagespot/ptTuningSpot.h"
47 #include "qtsingleapplication/qtsingleapplication.h"
48 #include "filemgmt/ptFileMgrWindow.h"
49 #include "batch/ptBatchWindow.h"
50 #include "filters/ptFilterDM.h"
51 #include "filters/ptFilterBase.h"
52 #include "ptToolBox.h"
53 #include "filters/ptFilterUids.h"
54
55 #ifdef Q_OS_WIN
56 #include "ptEcWin7.h"
57 #include "ptWinApi.h"
58 #endif
59
60 #include <wand/magick_wand.h>
61
62 #define QT_CLEAN_NAMESPACE
63
64 #include <QFileInfo>
65 #include <QtGui>
66 #include <QtCore>
67 #include <QFileDialog>
68 #include <QColorDialog>
69 #include <QInputDialog>
70 #include <QTextCodec>
71 #include <QDesktopWidget>
72 #ifdef Q_OS_MAC
73 #include <QFileOpenEvent>
74 #endif
75
76 #include <string>
77 #include <csignal>
78 #include <exception>
79
80 using namespace std;
81
82 ////////////////////////////////////////////////////////////////////////////////
83 //
84 // This is the file where everything is started.
85 // It starts not only the gui but it is *also* the starting point
86 // for guiless jobmode. The design is such that the pipe runs
87 // independent whether or not gui thingies are attached to it.
88 //
89 ////////////////////////////////////////////////////////////////////////////////
90
91 ptDcRaw* TheDcRaw = NULL;
92 ptProcessor* TheProcessor = NULL;
93
94 QStringList FileExtsRaw;
95 QStringList FileExtsBitmap;
96 QString UserDirectory;
97 QString ShareDirectory;
98 // Sidecar related
99 Exiv2::IptcData IptcData;
100 Exiv2::XmpData XmpData;
101
102 cmsHPROFILE PreviewColorProfile = NULL;
103 cmsCIExyY D65;
104 cmsCIExyY D50;
105 // precalculated color transform
106 cmsHTRANSFORM ToPreviewTransform = NULL;
107 void ReadSidecar(const QString& Sidecar);
108 void SetRatingFromXmp();
109 void SetTagsFromXmp();
110
111 //
112 // The 'tee' towards the display.
113 // Visualization :
114 //
115 // Raw->Image_AfterDcRaw->Image_AfterLensfun->Image_AfterRGB->Image_AfterLab->
116 // Image_AfterGREYC->Image_AfterEyeCandy
117 // -------------------------------------------------------------------------
118 // |
119 // Somewhere a tee to the preview
120 // |
121 // PreviewImage
122 //
123 // The pipe changed, Lab and Greyc became LabCC and LabSN
124
125
126 ptImage* PreviewImage = NULL;
127 ptImage* HistogramImage = NULL;
128
129 // The main windows of the application.
130 ptMainWindow* MainWindow = NULL;
131 ptViewWindow* ViewWindow = NULL;
132 ptHistogramWindow* HistogramWindow = NULL;
133 ptFileMgrWindow* FileMgrWindow = NULL;
134 ptBatchWindow* BatchWindow = NULL;
135
136 // Error dialog for segfaults
137 ptMessageBox* SegfaultErrorBox;
138
139 // Theming
140 ptTheme* Theme = NULL;
141
142 QTranslator appTranslator;
143
144 // Gui options and settings.
145 ptGuiOptions *GuiOptions = NULL;
146 ptSettings *Settings = NULL;
147
148 // Lensfun database.
149 //ptLensfun* LensfunData = NULL; // TODO BJ: implement lensfun DB
150
151 // Run mode
152 short NextPhase;
153 short NextSubPhase;
154 short ImageSaved;
155 short ImageCleanUp;
156
157 // uint16_t (0,0xffff) to float (0.0, 1.0)
158 float ToFloatTable[0x10000];
159 float ToFloatABNeutral[0x10000];
160 uint16_t ToInvertTable[0x10000];
161 uint16_t ToSRGBTable[0x10000];
162
163 // Filter patterns for the filechooser.
164 QString ChannelMixerFilePattern;
165 QString CurveFilePattern;
166 QString JobFilePattern;
167 QString SettingsFilePattern;
168 QString ProfilePattern;
169 QString RawPattern;
170 QString BitmapPattern;
171 QString SaveBitmapPattern;
172
InitStrings()173 void InitStrings() {
174 ChannelMixerFilePattern =
175 QCoreApplication::translate("Global Strings","Photivo channelmixer file (*.ptm);;All files (*.*)");
176 CurveFilePattern =
177 QCoreApplication::translate("Global Strings","Photivo curve file (*.ptc);;All files (*.*)");
178 JobFilePattern =
179 QCoreApplication::translate("Global Strings","Photivo job file (*.ptj);;All files (*.*)");
180 SettingsFilePattern =
181 QCoreApplication::translate("Global Strings","Photivo settings file (*.pts);;All files (*.*)");
182 ProfilePattern =
183 QCoreApplication::translate("Global Strings","ICC colour profiles (*.icc *.icm);;All files (*.*)");
184
185 // QFileDialog has no case insensitive option ...
186 RawPattern =
187 QCoreApplication::translate("Global Strings","Raw files ("
188 "*.arw *.ARW *.Arw "
189 "*.bay *.BAY *.Bay "
190 "*.bmq *.BMQ *.Bmq "
191 "*.cr2 *.CR2 *.Cr2 "
192 "*.crw *.CRW *.Crw "
193 "*.cs1 *.CS1 *.Cs1 "
194 "*.dc2 *.DC2 *.Dc2 "
195 "*.dcr *.DCR *.Dcr "
196 "*.dng *.DNG *.Dng "
197 "*.erf *.ERF *.Erf "
198 "*.fff *.FFF *.Fff "
199 "*.hdr *.HDR *.Hdr "
200 "*.ia *.IA *.Ia "
201 "*.k25 *.K25 "
202 "*.kc2 *.KC2 *.Kc2 "
203 "*.kdc *.KDC *.Kdc "
204 "*.mdc *.MDC *.Mdc "
205 "*.mef *.MEF *.Mef "
206 "*.mos *.MOS *.Mos "
207 "*.mrw *.MRW *.Mrw "
208 "*.nef *.NEF *.Nef "
209 "*.nrw *.NRW *.Nrw "
210 "*.orf *.ORF *.Orf "
211 "*.pef *.PEF *.Pef "
212 "*.pxn *.PXN *.Pxn "
213 "*.qtk *.QTK *.Qtk "
214 "*.raf *.RAF *.Raf "
215 "*.raw *.RAW *.Raw "
216 "*.rdc *.RDC *.Rdc "
217 "*.rw2 *.RW2 *.Rw2 "
218 "*.sr2 *.SR2 *.Sr2 "
219 "*.srf *.SRF *.Srf "
220 "*.srw *.SRW *.Srw "
221 "*.sti *.STI *.Sti "
222 "*.tif *.TIF *.Tif "
223 "*.x3f *.X3F *.X3f)"
224 ";;Bitmaps ("
225 "*.jpeg *.JPEG *.Jpeg "
226 "*.jpg *.JPG *.Jpg "
227 "*.tiff *.TIFF *.Tiff "
228 "*.tif *.TIF *.Tif "
229 "*.bmp *.BMP *.Bmp "
230 "*.png *.PNG *.Png "
231 "*.ppm *.PPm *.Ppm)"
232 ";;All files (*.*)");
233
234 BitmapPattern =
235 QCoreApplication::translate("Global Strings","Bitmaps ("
236 "*.jpeg *.JPEG *.Jpeg "
237 "*.jpg *.JPG *.Jpg "
238 "*.tiff *.TIFF *.Tiff "
239 "*.tif *.TIF *.Tif "
240 "*.bmp *.BMP *.Bmp "
241 "*.png *.PNG *.Png "
242 "*.ppm *.PPm *.Ppm "
243 ";;All files (*.*)");
244
245 SaveBitmapPattern =
246 QCoreApplication::translate("Global Strings","Jpeg (*.jpg);;"
247 "Tiff (*.tiff);;"
248 "Png (*.png);;"
249 "All files (*.*)");
250 }
251
252 ////////////////////////////////////////////////////////////////////////////////
253 //
254 // Some function prototypes.
255 //
256 ////////////////////////////////////////////////////////////////////////////////
257
258 ptImageType CheckImageType(QString filename,
259 uint16_t* width, uint16_t* height,
260 ptDcRaw* dcRaw = NULL);
261 void RunJob(const QString FileName);
262 short ReadJobFile(const QString FileName);
263 void WriteOut();
264 void UpdatePreviewImage(const ptImage* ForcedImage = NULL,
265 const short OnlyHistogram = 0);
266 void UpdateCropToolUI();
267 void PreCalcTransforms();
268 void CB_ZoomFitButton();
269 void CB_MenuFileOpen(const short HaveFile);
270 void CB_MenuFileExit(const short);
271 void ExtFileOpen(const QString file);
272 void CB_WritePipeButton();
273 void CB_OpenPresetFileButton();
274 void CB_OpenSettingsFileButton();
275 void CB_CropOrientationButton();
276 //short WriteSettingsFile(const QString FileName, const short IsJobFile = 0);
277 void SetBackgroundColor(int SetIt);
278 void CB_StyleChoice(const QVariant Choice);
279 void CB_SliderWidthInput(const QVariant Value);
280 void Export(const short mode);
281 void Update(short Phase,
282 short SubPhase = -1,
283 short WithIdentify = 1,
284 short ProcessorMode = ptProcessorMode_Preview);
285 int CalculatePipeSize(const bool NewImage = false);
286 void CB_OpenSettingsFile(QString SettingsFileName);
287 void SaveButtonToolTip(const short mode);
288
289 int photivoMain(int Argc, char *Argv[]);
290 void CleanupResources();
291 void copyFolder(QString sourceFolder, QString destFolder);
292 void CB_PixelReader(const QPointF Point, const ptPixelReading PixelReading);
293 bool GBusy = false;
294
295 // undo-redo & clipboard support
296 QByteArray ptSettingsToQByteArray();
297 void ptQByteArrayToSettings(const QByteArray &arr);
298 void ptAddUndo();
299 void ptMakeUndo();
300 void ptMakeRedo();
301 void ptClearUndoRedo();
302 void ptMakeFullUndo();
303 void ptResetSettingsToDefault();
304 void ptCopySettingsToClipboard();
305 void ptPasteSettingsFromClipboard();
306
307 //==============================================================================
308
CreateAllFilters()309 void CreateAllFilters() {
310 // Filter ID unique name caption postfix
311 // Local Edit tab
312 GFilterDM->NewFilter("SpotTuning", Fuid::SpotTuning_Local);
313 // RGB tab
314 GFilterDM->NewFilter("ChannelMixer", Fuid::ChannelMixer_RGB);
315 GFilterDM->NewFilter("Highlights", Fuid::Highlights_RGB);
316 GFilterDM->NewFilter("ColorIntensity", Fuid::ColorIntensity_RGB);
317 GFilterDM->NewFilter("Brightness", Fuid::Brightness_RGB);
318 GFilterDM->NewFilter("ExposureCorrection", Fuid::Exposure_RGB);
319 GFilterDM->NewFilter("ReinhardBrighten", Fuid::ReinhardBrighten_RGB);
320 GFilterDM->NewFilter("GammaTool", Fuid::GammaTool_RGB);
321 GFilterDM->NewFilter("Normalization", Fuid::Normalization_RGB);
322 GFilterDM->NewFilter("ColorEnhancement", Fuid::ColorEnhancement_RGB);
323 GFilterDM->NewFilter("LMHRecoveryRgb", Fuid::LMHRecovery_RGB);
324 GFilterDM->NewFilter("TextureContrastRgb", Fuid::TextureContrast_RGB);
325 GFilterDM->NewFilter("LocalContrastRgb", Fuid::LocalContrast1_RGB, " I");
326 GFilterDM->NewFilter("LocalContrastRgb", Fuid::LocalContrast2_RGB, " II");
327 GFilterDM->NewFilter("SigContrastRgb", Fuid::SigContrastRgb_RGB);
328 GFilterDM->NewFilter("LevelsRgb", Fuid::Levels_RGB);
329 GFilterDM->NewFilter("RgbCurve", Fuid::RgbCurve_RGB);
330 // Lab Color/contrast tab
331 GFilterDM->NewFilter("LabTransform", Fuid::LabTransform_LabCC);
332 GFilterDM->NewFilter("ShadowsHighlights", Fuid::ShadowsHighlights_LabCC);
333 GFilterDM->NewFilter("LMHRecoveryLab", Fuid::LMHRecovery_LabCC);
334 GFilterDM->NewFilter("Drc", Fuid::Drc_LabCC);
335 GFilterDM->NewFilter("SigContrastLab", Fuid::SigContrastLab_LabCC);
336 GFilterDM->NewFilter("TextureCurve", Fuid::TextureCurve_LabCC);
337 GFilterDM->NewFilter("TextureContrastLab", Fuid::TextureContrast1_LabCC, " I");
338 GFilterDM->NewFilter("TextureContrastLab", Fuid::TextureContrast2_LabCC, " II");
339 GFilterDM->NewFilter("LocalContrastLab", Fuid::LocalContrast1_LabCC, " I");
340 GFilterDM->NewFilter("LocalContrastLab", Fuid::LocalContrast2_LabCC, " II");
341 GFilterDM->NewFilter("LocalContrastStretch", Fuid::LocalContrastStretch1_LabCC, " I");
342 GFilterDM->NewFilter("LocalContrastStretch", Fuid::LocalContrastStretch2_LabCC, " II");
343 GFilterDM->NewFilter("Saturation", Fuid::Saturation_LabCC);
344 GFilterDM->NewFilter("ColorBoost", Fuid::ColorBoost_LabCC);
345 GFilterDM->NewFilter("LevelsLab", Fuid::Levels_LabCC);
346 // Lab sharpen/noise tab
347 GFilterDM->NewFilter("ImpulseNR", Fuid::ImpulseNR_LabSN);
348 GFilterDM->NewFilter("EAWavelets", Fuid::EAWavelets_LabSN);
349 GFilterDM->NewFilter("GreyCStoration", Fuid::GreyCStoration_LabSN);
350 GFilterDM->NewFilter("Defringe", Fuid::Defringe_LabSN);
351 GFilterDM->NewFilter("WaveletDenoise", Fuid::WaveletDenoise_LabSN);
352 GFilterDM->NewFilter("LumaDenoise", Fuid::LumaDenoise_LabSN);
353 GFilterDM->NewFilter("LumaDenoiseCurve", Fuid::LumaDenoiseCurve_LabSN);
354 GFilterDM->NewFilter("LumaDenoiseCurve", Fuid::LumaDenoiseCurve2_LabSN, " II");
355 GFilterDM->NewFilter("PyramidDenoise", Fuid::PyramidDenoise_LabSN);
356 GFilterDM->NewFilter("ColorDenoise", Fuid::ColorDenoise_LabSN);
357 GFilterDM->NewFilter("GradientSharpen", Fuid::GradientSharpen_LabSN);
358 GFilterDM->NewFilter("DetailCurve", Fuid::DetailCurve_LabSN);
359 GFilterDM->NewFilter("Wiener", Fuid::Wiener_LabSN);
360 GFilterDM->NewFilter("InvDiffSharpen", Fuid::InvDiffSharpen_LabSN);
361 GFilterDM->NewFilter("UnsharpMask", Fuid::Usm_LabSN);
362 GFilterDM->NewFilter("HighpassSharpen", Fuid::HighpassSharpen_LabSN);
363 GFilterDM->NewFilter("FilmGrain", Fuid::FilmGrain_LabSN);
364 GFilterDM->NewFilter("LabChannelView", Fuid::ViewLab_LabSN);
365 // Lab Eyecandy tab
366 GFilterDM->NewFilter("Outline", Fuid::Outline_LabEyeCandy);
367 GFilterDM->NewFilter("LumaByHueCurve", Fuid::LumaByHueCurve_LabEyeCandy);
368 GFilterDM->NewFilter("SatCurve", Fuid::SatCurve_LabEyeCandy);
369 GFilterDM->NewFilter("HueCurve", Fuid::HueCurve_LabEyeCandy);
370 GFilterDM->NewFilter("LCurve", Fuid::LCurve_LabEyeCandy);
371 GFilterDM->NewFilter("ABCurves", Fuid::ABCurves_LabEyeCandy);
372 GFilterDM->NewFilter("ColorContrast", Fuid::ColorContrast_LabEyeCandy);
373 GFilterDM->NewFilter("ToneAdjust", Fuid::ToneAdjust1_LabEyeCandy, " I");
374 GFilterDM->NewFilter("ToneAdjust", Fuid::ToneAdjust2_LabEyeCandy, " II");
375 GFilterDM->NewFilter("LumaAdjust", Fuid::LumaAdjust_LabEyeCandy);
376 GFilterDM->NewFilter("SatAdjust", Fuid::SatAdjust_LabEyeCandy);
377 GFilterDM->NewFilter("Tone", Fuid::Tone_LabEyeCandy);
378 GFilterDM->NewFilter("VignetteLab", Fuid::Vignette_LabEyeCandy);
379 // Eyecandy tab
380 GFilterDM->NewFilter("BlackWhite", Fuid::BlackWhite_EyeCandy);
381 GFilterDM->NewFilter("CrossProcessing", Fuid::CrossProcessing_EyeCandy);
382 GFilterDM->NewFilter("SimpleTone", Fuid::SimpleTone_EyeCandy);
383 GFilterDM->NewFilter("ColorTone", Fuid::ColorTone1_EyeCandy, " I");
384 GFilterDM->NewFilter("ColorTone", Fuid::ColorTone2_EyeCandy, " II");
385 GFilterDM->NewFilter("SigContrastRgb", Fuid::SigContrastRgb_EyeCandy);
386 GFilterDM->NewFilter("TextureOverlay", Fuid::TextureOverlay1_EyeCandy, " I");
387 GFilterDM->NewFilter("TextureOverlay", Fuid::TextureOverlay2_EyeCandy, " II");
388 GFilterDM->NewFilter("GradualOverlay", Fuid::GradualOverlay1_EyeCandy, " I");
389 GFilterDM->NewFilter("GradualOverlay", Fuid::GradualOverlay2_EyeCandy, " II");
390 GFilterDM->NewFilter("VignetteRgb", Fuid::Vignette_EyeCandy);
391 GFilterDM->NewFilter("GradualBlur", Fuid::GradualBlur1_EyeCandy, " I");
392 GFilterDM->NewFilter("GradualBlur", Fuid::GradualBlur2_EyeCandy, " II");
393 GFilterDM->NewFilter("SoftglowOrton", Fuid::SoftglowOrton_EyeCandy);
394 GFilterDM->NewFilter("ColorIntensity", Fuid::ColorIntensity_EyeCandy);
395 GFilterDM->NewFilter("RToneCurve", Fuid::RTone_EyeCandy);
396 GFilterDM->NewFilter("GToneCurve", Fuid::GTone_EyeCandy);
397 GFilterDM->NewFilter("BToneCurve", Fuid::BTone_EyeCandy);
398 // Output tab
399 GFilterDM->NewFilter("RgbCurve", Fuid::RgbCurve_Out);
400 GFilterDM->NewFilter("AfterGammaCurve", Fuid::AfterGammaCurve_Out);
401 GFilterDM->NewFilter("SigContrastRgb", Fuid::SigContrastRgb_Out);
402 GFilterDM->NewFilter("Wiener", Fuid::Wiener_Out);
403 }
404
405
406 //==============================================================================
407
408
409 ////////////////////////////////////////////////////////////////////////////////
410 //
411 // Progress function in the GUI.
412 // Can later also in job.
413 //
414 ////////////////////////////////////////////////////////////////////////////////
415
ReportProgress(const QString Message)416 void ReportProgress(const QString Message) {
417 printf("Progress : %s\n",Message.toLocal8Bit().data());
418 if (!MainWindow) return;
419 MainWindow->StatusLabel->setText(Message);
420 MainWindow->StatusLabel->repaint();
421 // Workaround to keep the GUI responsive
422 // during pipe processing...
423 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
424 }
425
426 ////////////////////////////////////////////////////////////////////////////////
427 //
428 // Main : instantiating toplevel windows, settings and options ..
429 //
430 ////////////////////////////////////////////////////////////////////////////////
431
432 short InStartup = 1;
433
434 short JobMode = 0;
435 QString JobFileName = "";
436 QString ImageFileToOpen = "";
437 QString PtsFileToOpen = "";
438 QString Sidecar = "";
439 #ifdef Q_OS_MAC
440 bool MacGotFileEvent=false;
441 #endif
442 QRect DetailViewRect;
443
444
445 #ifndef DLRAW_GIMP_PLUGIN
SegfaultAbort(int)446 void SegfaultAbort(int) {
447 // prevent infinite recursion if SegfaultAbort() causes another segfault
448 std::signal(SIGSEGV, SIG_DFL);
449 std::signal(SIGABRT, SIG_DFL);
450 SegfaultErrorBox->exec();
451 // std::abort();
452 // Batch manager needs Photivo to return a value to determine a crash
453 exit(EXIT_FAILURE);
454 }
455
main(int Argc,char * Argv[])456 int main(int Argc, char *Argv[]) {
457 #ifdef Q_OS_WIN
458 WinApi::AttachToParentConsole();
459 #endif
460
461 int RV = photivoMain(Argc,Argv);
462 DestroyMagick();
463 DelAndNull(SegfaultErrorBox);
464 CleanupResources(); // Not necessary , for debug.
465
466 #ifdef Q_OS_WIN
467 // Close output channels to a possibly attached console and detach from it.
468 // Not sure if this is strictly necessary, but it does not hurt either.
469 fclose(stdout);
470 fclose(stderr);
471 FreeConsole();
472 #endif
473
474 return RV;
475 }
476 #endif
477
478
479 //class QtSingleApplication with redefined event to handle QFileOpenEvent
480 #ifdef Q_OS_MAC
481 class MyQApplication : public QtSingleApplication {
482 protected:
483 virtual bool event(QEvent *event);
484 public:
485 bool initialized;
486 void macinit();
487 MyQApplication(const QString &appId, int & argc, char ** arg);
488 };
489
event(QEvent * event)490 bool MyQApplication::event(QEvent *event)
491 {
492 switch (event->type()) {
493 case QEvent::FileOpen:
494 ImageFileToOpen=static_cast<QFileOpenEvent *>(event)->file();
495 MacGotFileEvent=true;
496 if(initialized){
497 //skip on first Event
498 ExtFileOpen(ImageFileToOpen);
499 }
500 return true;
501 default:
502 MacGotFileEvent=false;
503 break;
504 }
505 return QtSingleApplication::event(event);
506 }
MyQApplication(const QString & appId,int & argc,char ** argv)507 MyQApplication::MyQApplication(const QString &appId,int & argc, char ** argv) : QtSingleApplication(appId,argc, argv){
508 initialized=false;
509 };
macinit()510 void MyQApplication::macinit(){
511 initialized=true;
512 };
513 #endif
514
515
516 #ifdef Q_OS_MAC
517 MyQApplication* TheApplication;
518 #else
519 QtSingleApplication* TheApplication;
520 #endif
521
photivoMain(int Argc,char * Argv[])522 int photivoMain(int Argc, char *Argv[]) {
523 QString VerTemp(TOSTRING(APPVERSION)); //also used for the cli syntax error msg below!
524 printf("Photivo version %s\n", VerTemp.toLocal8Bit().data());
525
526 InitializeMagick(*Argv);
527
528 //QApplication TheApplication(Argc,Argv);
529 QStringList environment = QProcess::systemEnvironment();
530 QString user=environment.filter(QRegExp("^USERNAME=|^USER=",Qt::CaseInsensitive)).first();
531 if(!user.isEmpty()){
532 int l=user.indexOf("=",0);
533 user="_"+user.right(user.length()-l-1);
534 }
535 user="photivo"+user;
536
537 #ifdef Q_OS_MAC
538 TheApplication = new MyQApplication(user, Argc,Argv);
539 #else
540 TheApplication = new QtSingleApplication(user, Argc,Argv);
541 #endif
542 //close on last window closed, seems to be unneeded
543 TheApplication->connect(TheApplication, SIGNAL(lastWindowClosed()), TheApplication, SLOT(quit()));
544
545 // Error handling for segfaults (to prevent silent crashes)
546 SegfaultErrorBox = new ptMessageBox(QMessageBox::Critical,
547 QObject::tr("Photivo crashed"),
548 QObject::tr("Photivo crashed. You can get help on our flickr forum at\n"
549 "<a href=\"http://www.flickr.com/groups/photivo/discuss/\">http://www.flickr.com/groups/photivo/discuss/</a>"
550 "\nWhen you post there make sure to describe your last actions before the crash occurred."),
551 QMessageBox::Ok);
552 SegfaultErrorBox->setTextFormat(Qt::RichText);
553 std::signal(SIGSEGV, SegfaultAbort);
554 std::signal(SIGABRT, SegfaultAbort);
555
556 // Check for wrong GM quantum depth. We need the 16bit GraphicsMagick.
557 ulong QDepth = 0;
558 const ulong MinQD = 16;
559 MagickGetQuantumDepth(&QDepth);
560 if (QDepth < MinQD) {
561 QString WrongQDepthMsg = QObject::tr(
562 "Fatal error: Wrong GraphicsMagick quantum depth!\n"
563 "Found quantum depth %1. Photivo needs at least %2.\n")
564 .arg(QDepth).arg(MinQD);
565 fprintf(stderr,"%s", WrongQDepthMsg.toLocal8Bit().data());
566 ptMessageBox::critical(0, QObject::tr("Photivo: Fatal Error"), WrongQDepthMsg);
567 exit(EXIT_FAILURE);
568 }
569
570
571 // Handle cli arguments
572 QString PhotivoCliUsageMsg = "<pre>" + QObject::tr(
573 "Syntax: photivo [inputfile | -i imagefile | -j jobfile |\n"
574 " --load-and-delete imagefile]\n"
575 " [--pts ptsfile] [--sidecar sidecarfile] [-h] [--new-instance]\n"
576 "Options:\n"
577 "inputfile\n"
578 " Specify the image or settings file to load. Works like -i for image files\n"
579 " and like --pts for settings files.\n"
580 "-i imagefile\n"
581 " Specify image file to load.\n"
582 "-j jobfile\n"
583 " Specify jobfile for batch processing. Job files are created\n in Photivo\n"
584 " and then executed with this option.\n"
585 "--load-and-delete imagefile\n"
586 " Specify temporary file used for Gimp-to-Photivo export. Internal option,\n"
587 " not intended for general use. BEWARE! This option deletes imagefile!\n"
588 "--pts ptsfile\n"
589 " Specify settings file to load with the image. Must be used together\n"
590 " with -i.\n"
591 "--sidecar sidecarfile\n"
592 " Specify sidecar file to load with the image.\n"
593 "--new-instance\n"
594 " Allow opening another Photivo instance instead of using a currently\n"
595 " running Photivo. Job files are always opened in a new instance.\n"
596 "--no-fmgr or -p\n"
597 " Prevent auto-open file manager when Photivo starts.\n"
598 "--help or -h\n"
599 " Display this usage information.\n\n"
600 "For more documentation visit the wiki: http://photivo.org/photivo/start\n"
601 ) + "</pre>";
602
603 ptCliCommands cli = { cliNoAction, "", "", "", false, false };
604
605 #ifdef Q_OS_MAC
606 //Just Skip if engaged by QFileOpenEvent
607 if(!MacGotFileEvent) {
608 #endif
609
610 cli = ParseCli(Argc, Argv);
611
612 // Show help message and exit Photivo
613 if (cli.Mode == cliShowHelp) {
614 #ifdef Q_OS_WIN
615 ptMessageBox::critical(0, QObject::tr("Photivo"), PhotivoCliUsageMsg);
616 #else
617 fprintf(stderr,"%s",PhotivoCliUsageMsg.toLocal8Bit().data());
618 #endif
619 exit(EXIT_FAILURE);
620 }
621
622 ImageCleanUp = cli.Mode == cliLoadAndDelImage;
623 JobMode = cli.Mode == cliProcessJob;
624 PtsFileToOpen = cli.PtsFilename;
625
626 if (JobMode) {
627 JobFileName = cli.Filename;
628 } else {
629 ImageFileToOpen = cli.Filename;
630 }
631
632
633 if (cli.Sidecar != "" ) {
634 Sidecar = cli.Sidecar;
635 }
636
637 // QtSingleInstance, add CLI-Switch to skip and allow multiple instances
638 // JobMode is always run in a new instance
639 // Sent messages are handled by ptMainWindow::OtherInstanceMessage
640 if (!JobMode) {
641 if (TheApplication->isRunning() && !cli.NewInstance) {
642 if (PtsFileToOpen != "") {
643 TheApplication->sendMessage("::pts::" + PtsFileToOpen);
644 }
645 if (ImageFileToOpen != "") {
646 if (ImageCleanUp > 0) {
647 TheApplication->sendMessage("::tmp::" + ImageFileToOpen);
648 } else {
649 TheApplication->sendMessage("::img::" + ImageFileToOpen);
650 }
651 }
652 if (Sidecar != ""){
653 TheApplication->sendMessage("::sidecar::" + Sidecar);
654 }
655 TheApplication->activateWindow();
656 exit(0);
657 }
658 }
659
660
661 #ifdef Q_OS_MAC
662 } // !MacGotFileEvent
663 QDir dir(QApplication::applicationDirPath());
664 QApplication::setLibraryPaths(QStringList(dir.absolutePath()));
665 #endif
666
667
668
669 FileExtsRaw << "*.arw" << "*.ARW" << " *.Arw"
670 << "*.bay" << "*.BAY" << "*.Bay"
671 << "*.bmq" << "*.BMQ" << "*.Bmq"
672 << "*.cr2" << "*.CR2" << "*.Cr2"
673 << "*.crw" << "*.CRW" << "*.Crw"
674 << "*.cs1" << "*.CS1" << "*.Cs1"
675 << "*.dc2" << "*.DC2" << "*.Dc2"
676 << "*.dcr" << "*.DCR" << "*.Dcr"
677 << "*.dng" << "*.DNG" << "*.Dng"
678 << "*.erf" << "*.ERF" << "*.Erf"
679 << "*.fff" << "*.FFF" << "*.Fff"
680 << "*.hdr" << "*.HDR" << "*.Hdr"
681 << "*.ia " << "*.IA" << "*.Ia"
682 << "*.k25" << "*.K25"
683 << "*.kc2" << "*.KC2" << "*.Kc2"
684 << "*.kdc" << "*.KDC" << "*.Kdc"
685 << "*.mdc" << "*.MDC" << "*.Mdc"
686 << "*.mef" << "*.MEF" << "*.Mef"
687 << "*.mos" << "*.MOS" << "*.Mos"
688 << "*.mrw" << "*.MRW" << "*.Mrw"
689 << "*.nef" << "*.NEF" << "*.Nef"
690 << "*.nrw" << "*.NRW" << "*.Nrw"
691 << "*.orf" << "*.ORF" << "*.Orf"
692 << "*.pef" << "*.PEF" << "*.Pef"
693 << "*.pxn" << "*.PXN" << "*.Pxn"
694 << "*.qtk" << "*.QTK" << "*.Qtk"
695 << "*.raf" << "*.RAF" << "*.Raf"
696 << "*.raw" << "*.RAW" << "*.Raw"
697 << "*.rdc" << "*.RDC" << "*.Rdc"
698 << "*.rw2" << "*.RW2" << "*.Rw2"
699 << "*.sr2" << "*.SR2" << "*.Sr2"
700 << "*.srf" << "*.SRF" << "*.Srf"
701 << "*.srw" << "*.SRW" << "*.Srw"
702 << "*.sti" << "*.STI" << "*.Sti"
703 << "*.tif" << "*.TIF" << "*.Tif"
704 << "*.x3f" << "*.X3F" << "*.X3f";
705
706 FileExtsBitmap << "*.jpeg" << "*.JPEG" << "*.Jpeg"
707 << "*.jpg" << "*.JPG" << "*.Jpg"
708 << "*.png" << "*.PNG" << "*.Png"
709 << "*.tiff" << "*.TIFF" << "*.Tiff"
710 << "*.tif" << "*.TIF" << "*.Tif"
711 << "*.bmp" << "*.BMP" << "*.Bmp"
712 << "*.png" << "*.PNG" << "*.Png"
713 << "*.ppm" << "*.PPm" << "*.Ppm";
714
715
716 // User home folder, where Photivo stores its ini and all Presets, Curves etc
717 // %appdata%\Photivo on Windows, ~/.photivo on Linux or the program folder for the
718 // portable Windows version.
719 short IsPortableProfile = 0;
720 QString AppDataFolder = "";
721 QString Folder = "";
722 #ifdef Q_OS_WIN
723 IsPortableProfile = QFile::exists("use-portable-profile");
724 if (IsPortableProfile != 0) {
725 printf("Photivo running in portable mode.\n");
726 AppDataFolder = QCoreApplication::applicationDirPath();
727 Folder = "";
728 } else {
729 // WinAPI returns path with native separators "\". We need to change this to "/" for Qt.
730 AppDataFolder = WinApi::AppdataFolder();
731 // Keeping the leading "/" separate here is important or mkdir will fail.
732 Folder = "Photivo/";
733 }
734 #else
735 Folder = ".photivo/";
736 AppDataFolder = QDir::homePath();
737 #endif
738
739 UserDirectory = AppDataFolder + "/" + Folder;
740
741 if (IsPortableProfile == 0) {
742 QDir home(AppDataFolder);
743 if (!home.exists(Folder))
744 home.mkdir(Folder);
745 }
746
747 QString SettingsFileName = UserDirectory + "photivo.ini";
748 // this has to be changed when we move to a different tree structure!
749 #ifdef __unix__
750 QString NewShareDirectory(TOSTRING(PREFIX));
751 if (NewShareDirectory.endsWith("/")) NewShareDirectory.chop(1);
752 NewShareDirectory.append("/share/photivo/");
753 #else
754 QString NewShareDirectory = QCoreApplication::applicationDirPath().append("/");
755 #endif
756 ShareDirectory = NewShareDirectory;
757
758 QFileInfo SettingsFileInfo(SettingsFileName);
759 // short NeedInitialization = 1;
760 short FirstStart = 1;
761 if (SettingsFileInfo.exists() &&
762 SettingsFileInfo.isFile() &&
763 SettingsFileInfo.isReadable()) {
764 // photivo was initialized
765 // NeedInitialization = 0;
766 FirstStart = 0;
767 printf("Existing settingsfile '%s'\n",SettingsFileName.toLocal8Bit().data());
768 } else {
769 printf("New settingsfile '%s'\n",SettingsFileName.toLocal8Bit().data());
770 }
771
772 printf("User directory: '%s'; \n",UserDirectory.toLocal8Bit().data());
773 printf("Share directory: '%s'; \n",NewShareDirectory.toLocal8Bit().data());
774
775 // We need to load the translation before the ptSettings
776 QSettings* TempSettings = new QSettings(SettingsFileName, QSettings::IniFormat);
777
778 // if (TempSettings->value("SettingsVersion",0).toInt() < PhotivoSettingsVersion)
779 // NeedInitialization = 1;
780
781 // Initialize the user folder if needed
782 /* TODO: for testing. Enable the other line below once profile versions are final. */
783 if (IsPortableProfile == 0) {
784 //if (NeedInitialization == 1 && IsPortableProfile == 0) {
785 printf("Initializing/Updating user profile...\n");
786 QFile::remove(UserDirectory + "photivo.png");
787 QFile::copy(NewShareDirectory + "photivo.png",
788 UserDirectory + "photivo.png");
789 // QFile::remove(UserDirectory + "photivoLogo.png");
790 // QFile::copy(NewShareDirectory + "photivoLogo.png",
791 // UserDirectory + "photivoLogo.png");
792 QFile::remove(UserDirectory + "photivoPreview.jpg");
793 QFile::copy(NewShareDirectory + "photivoPreview.jpg",
794 UserDirectory + "photivoPreview.jpg");
795 QStringList SourceFolders;
796 SourceFolders << NewShareDirectory + "Translations"
797 << NewShareDirectory + "Curves"
798 << NewShareDirectory + "ChannelMixers"
799 << NewShareDirectory + "Presets"
800 << NewShareDirectory + "Profiles"
801 << NewShareDirectory + "LensfunDatabase"
802 << NewShareDirectory + "UISettings";
803 QStringList DestFolders;
804 DestFolders << UserDirectory + "Translations"
805 << UserDirectory + "Curves"
806 << UserDirectory + "ChannelMixers"
807 << UserDirectory + "Presets"
808 << UserDirectory + "Profiles"
809 << UserDirectory + "LensfunDatabase"
810 << UserDirectory + "UISettings";
811
812 for (int i = 0; i < SourceFolders.size(); i++) {
813 copyFolder(SourceFolders.at(i), DestFolders.at(i));
814 }
815 }
816
817
818 // Load Translation
819 int TranslMode = TempSettings->value("TranslationMode",0).toInt();
820 QDir TranslDir(UserDirectory + "Translations");
821 QStringList UiLanguages = TranslDir.entryList(QStringList("photivo_*.qm"), QDir::Files|QDir::Readable, QDir::Name).replaceInStrings(".qm", "", Qt::CaseInsensitive);
822 UiLanguages.replaceInStrings("photivo_", "", Qt::CaseInsensitive);
823 int LangIdx = -1;
824
825 if (TranslMode == 1) {
826 LangIdx = UiLanguages.indexOf(TempSettings->value("UiLanguage","").toString());
827 if (LangIdx >= 0) {
828 QTranslator qtTranslator;
829 appTranslator.load("photivo_" + UiLanguages[LangIdx], UserDirectory + "Translations");
830 TheApplication->installTranslator(&appTranslator);
831 qtTranslator.load("qt_" + UiLanguages[LangIdx], UserDirectory + "Translations");
832 TheApplication->installTranslator(&qtTranslator);
833 printf("Enabled translation: \"%s\".\n", UiLanguages[LangIdx].toLocal8Bit().data());
834 }
835 }
836
837 delete TempSettings;
838
839 // Persistent settings.
840 // fixed the remember level to 2, since we have settings files now
841 short RememberSettingLevel = 2;
842
843 // Load the Settings (are also partly used in JobMode)
844 Settings = new ptSettings(RememberSettingLevel, UserDirectory);
845
846 // Set directories for needed files
847 Settings->SetValue("UserDirectory", UserDirectory);
848 Settings->SetValue("ShareDirectory",NewShareDirectory);
849 Settings->SetValue("MainDirectory",QCoreApplication::applicationDirPath().append("/"));
850 Settings->SetValue("Sidecar", Sidecar);
851
852 // Set paths once with first start
853 if (FirstStart == 1) {
854 Settings->SetValue("RawsDirectory", UserDirectory);
855 Settings->SetValue("OutputDirectory", UserDirectory);
856 Settings->SetValue("UIDirectory", UserDirectory + "UISettings");
857 Settings->SetValue("PresetDirectory", UserDirectory + "Presets");
858 Settings->SetValue("CurvesDirectory", UserDirectory + "Curves");
859 Settings->SetValue("ChannelMixersDirectory", UserDirectory + "ChannelMixers");
860 Settings->SetValue("TranslationsDirectory", UserDirectory + "Translations");
861 Settings->SetValue("CameraColorProfilesDirectory", UserDirectory + "Profiles/Camera");
862 Settings->SetValue("PreviewColorProfilesDirectory", UserDirectory + "Profiles/Preview");
863 Settings->SetValue("OutputColorProfilesDirectory", UserDirectory + "Profiles/Output");
864 Settings->SetValue("StandardAdobeProfilesDirectory", UserDirectory + "Profiles/Camera/Standard");
865 Settings->SetValue("LensfunDatabaseDirectory", UserDirectory + "LensfunDatabase");
866 Settings->SetValue("PreviewColorProfile", UserDirectory + "Profiles/Preview/sRGB.icc");
867 Settings->SetValue("OutputColorProfile", UserDirectory + "Profiles/Output/sRGB.icc");
868 Settings->SetValue("StartupSettingsFile", UserDirectory + "Presets/MakeFancy.pts");
869 }
870
871 // Initialize patterns (after translation)
872 InitStrings();
873
874 // Init filter data module
875 ptFilterDM::CreateInstance();
876 CreateAllFilters();
877
878 // Load also the LensfunDatabase.
879 printf("Lensfun database: '%s'; \n",Settings->GetString("LensfunDatabaseDirectory").toLocal8Bit().data());
880 // LensfunData = new ptLensfun; // TODO BJ: implement lensfun DB
881
882 // Instantiate the processor. Spot models are not set here because we
883 // do not yet know if we are in GUI or batch mode.
884 TheProcessor = new ptProcessor(ReportProgress);
885
886 // First check if we are maybe started as a command line with options.
887 // (And thus have to run a batch job)
888
889 if (JobMode) {
890 RunJob(JobFileName);
891 exit(EXIT_SUCCESS);
892 }
893
894 // If falling through to here we are in an interactive non-job mode.
895 // Start op the Gui stuff.
896
897 // Start the theme class
898 Theme = new ptTheme(TheApplication,
899 (ptTheme::Theme)Settings->GetInt("Style"),
900 (ptTheme::Highlight)Settings->GetInt("StyleHighLight"));
901 Theme->setCustomCSS(Settings->GetString("CustomCSSFile"));
902
903 GuiOptions = new ptGuiOptions();
904
905 // Open and keep open the profile for previewing.
906 PreviewColorProfile = cmsOpenProfileFromFile(
907 Settings->GetString("PreviewColorProfile").toLocal8Bit().data(),
908 "r");
909 if (!PreviewColorProfile) {
910 ptLogError(ptError_FileOpen,
911 Settings->GetString("PreviewColorProfile").toLocal8Bit().data());
912 return ptError_FileOpen;
913 }
914
915 // When loading a file via cli, set file manager directory to that path.
916 // Chances are good the user want to work with other files from that dir as well
917 if (!JobMode && !ImageCleanUp && (ImageFileToOpen != "")) {
918 Settings->SetValue("LastFileMgrLocation", QFileInfo(ImageFileToOpen).absolutePath());
919 }
920
921 #ifndef PT_WITHOUT_FILEMGR
922 Settings->SetValue("PreventFileMgrStartup", int(cli.NoOpenFileMgr));
923 #endif
924
925 // Construct windows
926 MainWindow = new ptMainWindow(QObject::tr("Photivo"));
927 QObject::connect(TheApplication, SIGNAL(messageReceived(const QString &)),
928 MainWindow, SLOT(OtherInstanceMessage(const QString &)));
929 TheApplication->setActivationWindow(MainWindow);
930
931 ViewWindow =
932 new ptViewWindow(MainWindow->ViewFrameCentralWidget, MainWindow);
933
934 ViewWindow->SetPixelReader(CB_PixelReader);
935
936 HistogramWindow =
937 new ptHistogramWindow(NULL,MainWindow->HistogramFrameCentralWidget);
938
939 #ifndef PT_WITHOUT_FILEMGR
940 FileMgrWindow = new ptFileMgrWindow(MainWindow->FileManagerPage);
941 MainWindow->FileManagerLayout->addWidget(FileMgrWindow);
942 QObject::connect(FileMgrWindow, SIGNAL(fileMgrWindowClosed()),
943 MainWindow, SLOT(CloseFileMgrWindow()));
944 QObject::connect(ViewWindow, SIGNAL(openFileMgr()), MainWindow, SLOT(OpenFileMgrWindow()));
945 #endif
946 QObject::connect(ViewWindow, SIGNAL(openBatch()), MainWindow, SLOT(OpenBatchWindow()));
947
948 BatchWindow = new ptBatchWindow(MainWindow->BatchPage);
949 MainWindow->BatchLayout->addWidget(BatchWindow);
950 QObject::connect(BatchWindow, SIGNAL(BatchWindowClosed()), MainWindow, SLOT(CloseBatchWindow()));
951
952 // Populate Translations combobox
953 MainWindow->PopulateTranslationsCombobox(UiLanguages, LangIdx);
954
955 // Theming
956 CB_StyleChoice(Settings->GetInt("Style"));
957
958 SetBackgroundColor(Settings->GetInt("BackgroundColor"));
959
960 MainWindow->UpdateToolBoxes();
961
962
963 //-------------------------------------
964 // Initialize main window geometry and position
965 // If the screen is not longer present, we move the window to the standard screen
966
967 int Screen = Settings->m_IniSettings->value("MainWindowScreen", -1).toInt();
968 if (Screen >= qApp->desktop()->screenCount()) {
969 Screen = -1;
970 }
971 QRect DesktopRect = qApp->desktop()->screenGeometry(Screen);
972 QPoint UpperLeft = DesktopRect.topLeft() + QPoint(30, 30);
973 QPoint MainWindowPos = Settings->m_IniSettings->value("MainWindowPos", UpperLeft).toPoint();
974 QVariant WinSize = Settings->m_IniSettings->value("MainWindowSize");
975 QSize MainWindowSize;
976
977 if (!DesktopRect.contains(MainWindowPos)) {
978 MainWindowPos = UpperLeft;
979 }
980
981 if(!WinSize.isValid() ||
982 !(WinSize.toSize().width() < DesktopRect.width() + 50 &&
983 WinSize.toSize().height() < DesktopRect.height() + 50 )) {
984 // ensure a reasonable size if we don’t get one from Settings
985 MainWindowSize = QSize(qMin(1200, (int)(DesktopRect.width() * 0.8)),
986 qMin( 900, (int)(DesktopRect.height() * 0.8)) );
987 } else {
988 MainWindowSize = WinSize.toSize();
989 }
990
991 MainWindow->resize(MainWindowSize);
992 MainWindow->move( MainWindowPos);
993
994 // MainSplitter is the one between tool pane and image pane.
995 // ControlSplitter is the one between histogram and tools tabwidget.
996 QVariant splitterState = Settings->m_IniSettings->value("MainSplitter");
997 if (splitterState.isValid()) {
998 MainWindow->MainSplitter->restoreState(splitterState.toByteArray());
999 } else {
1000 // 10000 width for image pane to ensure the 300 for tool pane
1001 MainWindow->MainSplitter->setSizes(QList<int>() << 300 << 10000);
1002 }
1003
1004 splitterState = Settings->m_IniSettings->value("ControlSplitter");
1005 if (splitterState.isValid()) {
1006 MainWindow->ControlSplitter->restoreState(splitterState.toByteArray());
1007 } else {
1008 MainWindow->ControlSplitter->setSizes(QList<int>() << 100 << 10000);
1009 }
1010
1011 if (Settings->m_IniSettings->value("IsMaximized",0).toBool()) {
1012 MainWindow->showMaximized();
1013 } else {
1014 MainWindow->show();
1015 }
1016 //-------------------------------------
1017
1018
1019 // Update the preview image will result in displaying the splash.
1020 Update(ptProcessorPhase_Preview);
1021
1022 // Open and keep open the profile for previewing.
1023 PreviewColorProfile = cmsOpenProfileFromFile(
1024 Settings->GetString("PreviewColorProfile").toLocal8Bit().data(),
1025 "r");
1026 if (!PreviewColorProfile) {
1027 ptLogError(ptError_FileOpen,
1028 Settings->GetString("PreviewColorProfile").toLocal8Bit().data());
1029 assert(PreviewColorProfile);
1030 }
1031
1032 try {
1033 // Start event loops.
1034 return TheApplication->exec();
1035 } catch (const exception& E) {
1036 GInfo->Raise(E.what(), AT);
1037 } catch (...) {
1038 GInfo->Raise("Unknown error.", AT);
1039 }
1040 return 1;
1041 }
1042
1043 ////////////////////////////////////////////////////////////////////////////////
1044 //
1045 // This is only needed for the gimp integration.
1046 // Calling over and over photivoMain would otherwise leak like hell
1047 // (or any comparable place).
1048 //
1049 ////////////////////////////////////////////////////////////////////////////////
1050
CleanupResources()1051 void CleanupResources() {
1052 //printf("(%s,%d) qApp:%p\n",__FILE__,__LINE__,qApp);
1053 // Not : is done at CB for the exit.
1054 // delete Settings; // Don't, is done at CB_MenuFileExit
1055 // Also : do not delete items which are handled by MainWindow, such as
1056 // ViewWindow or HistogramWindow or CurveWindows
1057 // delete LensfunData; // TODO BJ: implement lensfun DB
1058 delete TheProcessor;
1059 delete GuiOptions;
1060 delete MainWindow; // Cleans up HistogramWindow and ViewWindow also !
1061 ViewWindow = NULL; // needs to be NULL to properly construct MainWindow
1062 delete PreviewImage;
1063 delete TheDcRaw;
1064 }
ExtFileOpen(const QString file)1065 void ExtFileOpen(const QString file){
1066 ImageFileToOpen = file;
1067 CB_MenuFileOpen(1);
1068 }
1069
1070 ////////////////////////////////////////////////////////////////////////////////
1071
ptRemoveFile(const QString FileName)1072 void ptRemoveFile( const QString FileName) {
1073 if (QMessageBox::Yes == ptMessageBox::question(
1074 MainWindow,
1075 QObject::tr("Clean up input file"),
1076 "As requested, Photivo will delete the input file " + FileName + ". Proceed?",
1077 QMessageBox::No|QMessageBox::Yes)) {
1078 QFile::remove(FileName);
1079 }
1080 }
1081
1082 ////////////////////////////////////////////////////////////////////////////////
1083 //
1084 // Hack : called at t=0 after the event loop started.
1085 //
1086 ////////////////////////////////////////////////////////////////////////////////
1087
CB_Event0()1088 void CB_Event0() {
1089 // Init Curves : supposed to be in event loop indeed.
1090 // (f.i. for progress reporting)
1091 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1092 if (Settings->GetInt("JobMode") == 0)
1093 SaveButtonToolTip(Settings->GetInt("SaveButtonMode"));
1094
1095 // Fill some look up tables
1096 #pragma omp parallel for
1097 for (uint32_t i=0; i<0x10000; i++) {
1098 // uint16_t (0,0xffff) to float (0.0, 1.0)
1099 ToFloatTable[i] = (float)i*ptInvWP;
1100 ToFloatABNeutral[i] = (float)i-ptWPHLab;
1101 ToInvertTable[i] = ptWP - i;
1102 // linear RGB to sRGB table
1103 if (ToFloatTable[i] <= 0.0031308)
1104 ToSRGBTable[i] = CLIP((int32_t)(12.92*i));
1105 else
1106 ToSRGBTable[i] = CLIP((int32_t)((1.055*pow(ToFloatTable[i],1.0/2.4)-0.055)*ptWPf));
1107 }
1108
1109 // Init run mode
1110 NextPhase = ptProcessorPhase_Raw;
1111 NextSubPhase = ptProcessorPhase_Load;
1112 ImageSaved = 0;
1113
1114 PreCalcTransforms();
1115
1116 if (Settings->GetInt("JobMode") == 0) { // not job mode!
1117 MainWindow->Settings_2_Form();
1118
1119 // Load user settings
1120 if (Settings->GetInt("StartupSettings")) {
1121 if (ImageCleanUp == 0) {
1122 CB_OpenSettingsFile(Settings->GetString("StartupSettingsFile"));
1123 } else { // we got an image from gimp -> neutral display
1124 CB_OpenSettingsFile(Settings->GetString("PresetDirectory") + "/Neutral_absolute.pts");
1125 }
1126 // clean up
1127 QStringList Temp;
1128 Temp << "CropX" << "CropY" << "CropW" << "CropH";
1129 Temp << "RotateW" << "RotateH";
1130 for (int i = 0; i < Temp.size(); i++) Settings->SetValue(Temp.at(i),0);
1131 }
1132
1133 if (PtsFileToOpen != "") {
1134 CB_OpenSettingsFile(PtsFileToOpen);
1135 }
1136
1137 if (Sidecar != "") {
1138 ReadSidecar(Sidecar);
1139 }
1140
1141 if (ImageFileToOpen != "") {
1142 CB_MenuFileOpen(1);
1143 }
1144 MainWindow->UpdateSettings();
1145 ViewWindow->setFocus();
1146 HistogramWindow->Init();
1147 }
1148
1149 if (Settings->GetStringList("FavouriteTools").isEmpty()) {
1150 Settings->SetValue(
1151 "FavouriteTools",
1152 QStringList({
1153 "TabWhiteBalance",
1154 "TabRotation",
1155 "TabCrop",
1156 Fuid::ReinhardBrighten_RGB,
1157 Fuid::TextureContrast2_LabCC,
1158 Fuid::DetailCurve_LabSN,
1159 Fuid::Vignette_LabEyeCandy,
1160 Fuid::SigContrastRgb_Out
1161 })
1162 );
1163 }
1164
1165 #ifndef PT_WITHOUT_FILEMGR
1166 if (Settings->GetInt("FileMgrIsOpen")) {
1167 FileMgrWindow->displayThumbnails();
1168 FileMgrWindow->setFocus(Qt::OtherFocusReason);
1169 }
1170 #endif
1171
1172 //prepare for further QFileOpenEvent(s)
1173 #ifdef Q_OS_MAC
1174 TheApplication->macinit();
1175 #endif
1176
1177 InStartup = 0;
1178 }
1179
1180 ////////////////////////////////////////////////////////////////////////////////
1181 //
1182 // Precalculation of color transforms
1183 //
1184 ////////////////////////////////////////////////////////////////////////////////
1185
PreCalcTransforms()1186 void PreCalcTransforms() {
1187 cmsToneCurve* Gamma = cmsBuildGamma(NULL, 1.0);
1188 cmsToneCurve* Gamma3[3];
1189 Gamma3[0] = Gamma3[1] = Gamma3[2] = Gamma;
1190
1191 cmsHPROFILE InProfile = 0;
1192
1193 cmsCIExyY DFromReference;
1194
1195 switch (Settings->GetInt("WorkColor")) {
1196 case ptSpace_sRGB_D65 :
1197 case ptSpace_AdobeRGB_D65 :
1198 DFromReference = D65;
1199 break;
1200 case ptSpace_WideGamutRGB_D50 :
1201 case ptSpace_ProPhotoRGB_D50 :
1202 DFromReference = D50;
1203 break;
1204 default:
1205 assert(0);
1206 }
1207
1208 ptImage::setCurrentRGB(Settings->GetInt("WorkColor"));
1209
1210 InProfile = cmsCreateRGBProfile(&DFromReference,
1211 (cmsCIExyYTRIPLE*)&RGBPrimaries[Settings->GetInt("WorkColor")],
1212 Gamma3);
1213
1214 if (!InProfile) {
1215 ptLogError(ptError_Profile,"Could not open InProfile profile.");
1216 return;
1217 }
1218
1219 cmsFreeToneCurve(Gamma);
1220
1221 if (Settings->GetInt("CMQuality") == ptCMQuality_HighResPreCalc) {
1222 ToPreviewTransform =
1223 cmsCreateTransform(InProfile,
1224 TYPE_RGB_16,
1225 PreviewColorProfile,
1226 TYPE_RGB_16,
1227 Settings->GetInt("PreviewColorProfileIntent"),
1228 cmsFLAGS_HIGHRESPRECALC | cmsFLAGS_BLACKPOINTCOMPENSATION);
1229 } else { // fast sRGB preview also uses the not optimized profile for output
1230 ToPreviewTransform =
1231 cmsCreateTransform(InProfile,
1232 TYPE_RGB_16,
1233 PreviewColorProfile,
1234 TYPE_RGB_16,
1235 Settings->GetInt("PreviewColorProfileIntent"),
1236 cmsFLAGS_NOOPTIMIZE | cmsFLAGS_BLACKPOINTCOMPENSATION);
1237 }
1238
1239 cmsCloseProfile(InProfile);
1240 }
1241
1242 ////////////////////////////////////////////////////////////////////////////////
1243 //
1244 // Copy folder
1245 //
1246 ////////////////////////////////////////////////////////////////////////////////
1247
copyFolder(QString sourceFolder,QString destFolder)1248 void copyFolder(QString sourceFolder, QString destFolder)
1249 {
1250 QDir sourceDir(sourceFolder);
1251 if(!sourceDir.exists())
1252 return;
1253 QDir destDir(destFolder);
1254 if(!destDir.exists())
1255 {
1256 destDir.mkdir(destFolder);
1257 }
1258 QStringList files = sourceDir.entryList(QDir::Files);
1259 for(int i = 0; i< files.count(); i++)
1260 {
1261 QString srcName = sourceFolder + "/" + files[i];
1262 QString destName = destFolder + "/" + files[i];
1263 QFile::remove(destName);
1264 QFile::copy(srcName, destName);
1265 }
1266 files.clear();
1267 files = sourceDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
1268 for(int i = 0; i< files.count(); i++)
1269 {
1270 QString srcName = sourceFolder + "/" + files[i];
1271 QString destName = destFolder + "/" + files[i];
1272 copyFolder(srcName, destName);
1273 }
1274 }
1275
1276 ////////////////////////////////////////////////////////////////////////////////
1277 //
1278 // Update
1279 //
1280 ////////////////////////////////////////////////////////////////////////////////
1281
Update(short Phase,short SubPhase,short WithIdentify,short ProcessorMode)1282 void Update(short Phase,
1283 short SubPhase /* = -1 */,
1284 short WithIdentify /* = 1 */,
1285 short ProcessorMode /* = ptProcessorMode_Preview */)
1286 {
1287 #ifdef Q_OS_WIN
1288 ptEcWin7* Win7Taskbar = NULL;
1289 if (!JobMode) {
1290 Win7Taskbar = ptEcWin7::GetInstance();
1291 Win7Taskbar->setProgressState(ptEcWin7::Indeterminate);
1292 }
1293 #endif
1294
1295 if (Settings->GetInt("BlockUpdate") == 1) return; // hard block
1296 if (Settings->GetInt("PipeIsRunning") == 1) {
1297 // record that we got here with the new settings
1298 // and make sure the pipe is run after the current
1299 // pass automatically -> timer
1300 return;
1301 } else Settings->SetValue("PipeIsRunning",1);
1302
1303 if (Phase < ptProcessorPhase_Preview) {
1304 // main processing
1305 if (Phase < NextPhase) NextPhase = Phase;
1306 if (SubPhase > 0 && SubPhase < NextSubPhase) NextSubPhase = SubPhase;
1307 if (Settings->GetInt("RunMode") == 1) {
1308 // we're in manual mode!
1309 MainWindow->UpdateSettings();
1310 } else {
1311 try {
1312 // run processor!
1313 ImageSaved = 0;
1314 MainWindow->UpdateSettings();
1315 if(Settings->GetInt("HaveImage")==1) {
1316 if (NextPhase < ptProcessorPhase_Output)
1317 TheProcessor->Run(NextPhase, NextSubPhase, WithIdentify, ProcessorMode);
1318 UpdatePreviewImage();
1319 }
1320 NextPhase = ptProcessorPhase_Output;
1321 NextSubPhase = ptProcessorPhase_Highlights;
1322 } catch (std::bad_alloc) {
1323 // make sure we image gets processed again
1324 NextPhase = ptProcessorPhase_Raw;
1325 NextSubPhase = ptProcessorPhase_Load;
1326 ViewWindow->ShowStatus(ptStatus_Done);
1327 ReportProgress(QObject::tr("Ready"));
1328 if (Settings->GetInt("PipeSize") == 0) {
1329 ptMessageBox::critical(NULL, "Memory error", "Processing aborted, memory error.\nReverting to 1:2 pipe. Reprocess with F5.");
1330
1331 Settings->SetValue("PipeSize",1);
1332 } else {
1333 ptMessageBox::critical(NULL, "Memory error", "Processing aborted, memory error.");
1334 }
1335 }
1336 }
1337 } else if (Phase == ptProcessorPhase_OnlyHistogram) {
1338 // only histogram update, don't care about manual mode
1339 UpdatePreviewImage(NULL,1);
1340 } else if (Phase == ptProcessorPhase_Preview) {
1341 // only preview update, don't care about manual mode
1342 UpdatePreviewImage(NULL,0);
1343 } else if (Phase == ptProcessorPhase_WriteOut) {
1344 // write output
1345 WriteOut();
1346 } else if (Phase == ptProcessorPhase_ToGimp) {
1347 // export
1348 Export(ptExportMode_GimpPipe);
1349 } else {
1350 // should not happen!
1351 assert(0);
1352 }
1353 Settings->SetValue("PipeIsRunning",0);
1354
1355 #ifdef Q_OS_WIN
1356 if (!JobMode) {
1357 Win7Taskbar->setProgressState(ptEcWin7::NoProgress);
1358 }
1359 #endif
1360 }
1361
1362 ////////////////////////////////////////////////////////////////////////////////
1363 //
1364 // Update
1365 // Overloaded function, expects toolname and will call Update
1366 //
1367 ////////////////////////////////////////////////////////////////////////////////
1368
GetProcessorPhase(const QString GuiName)1369 int GetProcessorPhase(const QString GuiName) {
1370 int Phase = 0;
1371 QString Tab = MainWindow->ProcessingTabBook->widget(
1372 MainWindow->m_GroupBox->value(GuiName)->parentTabIdx() )->objectName();
1373 if (Tab == "LocalTab") Phase = ptProcessorPhase_LocalEdit;
1374 else if (Tab == "GeometryTab") Phase = ptProcessorPhase_Geometry;
1375 else if (Tab == "RGBTab") Phase = ptProcessorPhase_RGB;
1376 else if (Tab == "LabCCTab") Phase = ptProcessorPhase_LabCC;
1377 else if (Tab == "LabSNTab") Phase = ptProcessorPhase_LabSN;
1378 else if (Tab == "LabEyeCandyTab") Phase = ptProcessorPhase_LabEyeCandy;
1379 else if (Tab == "EyeCandyTab") Phase = ptProcessorPhase_EyeCandy;
1380 else if (Tab == "OutTab") Phase = ptProcessorPhase_Output;
1381 else Phase = ptProcessorPhase_Raw;
1382 return Phase;
1383 }
1384
1385 //==============================================================================
1386
Update(const QString GuiName)1387 void Update(const QString GuiName) {
1388 int Phase = GetProcessorPhase(GuiName);
1389 // It is assumed that no tool before white balance will use this.
1390 if (Phase < 2) {
1391 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
1392 } else {
1393 Update(Phase);
1394 }
1395 }
1396
1397
1398 ////////////////////////////////////////////////////////////////////////////////
1399 //
1400 // Block tools
1401 //
1402 ////////////////////////////////////////////////////////////////////////////////
1403
BlockTools(const ptBlockToolsMode ANewState,QStringList AExcludeIds=QStringList ())1404 void BlockTools(const ptBlockToolsMode ANewState, QStringList AExcludeIds = QStringList()) {
1405 // Set the object name of the widget that is excluded from blocking.
1406 switch (ANewState) {
1407 case btmBlockForCrop:
1408 AExcludeIds << "TabCrop";
1409 break;
1410 case btmBlockForSpotRepair:
1411 AExcludeIds << "TabSpotRepair";
1412 break;
1413 default:
1414 // nothing to do
1415 break;
1416 }
1417
1418 bool EnabledStatus = ANewState == btmUnblock;
1419
1420 // Handle all necessary widgets outside the processing tabbook
1421 MainWindow->HistogramFrameCentralWidget->setEnabled(EnabledStatus);
1422 MainWindow->SearchWidget->setEnabled(EnabledStatus);
1423 MainWindow->PipeControlWidget->setEnabled(EnabledStatus);
1424 MainWindow->StatusWidget->setEnabled(EnabledStatus);
1425
1426 if (MainWindow->m_MovedTools->size() > 0) {
1427 /* Process moved tools list when UI is not in tab mode (e.g. showing favourites)
1428 We just cycle through the list of currently visible tools and en/disable them.
1429 */
1430 for (QWidget *hToolBox: *MainWindow->m_MovedTools) {
1431 if (!AExcludeIds.contains(hToolBox->objectName())) {
1432 if (hToolBox->objectName().contains("-")) //new-style
1433 hToolBox->setEnabled(EnabledStatus);
1434 else // old-style
1435 ((ptGroupBox*)hToolBox)->SetEnabled(EnabledStatus);
1436 }
1437 }
1438
1439 } else {
1440 /* Process processing tabbook
1441 To avoid cycling through all ptGroupBox objects on every tab every time we use the following
1442 approach: We assume that the tabbook is switched to the appropriate tab when BlockTools() is
1443 called, i.e. the tab containing the filter that should not be blocked (if there is such a one).
1444 We en/disable all tabs except the current one completely. Now we only need to cycle through the
1445 remaining ptGroupBoxes on the current tab.
1446 */
1447 int CurrentTab = MainWindow->ProcessingTabBook->currentIndex();
1448
1449 for (int i = 0; i < MainWindow->ProcessingTabBook->count(); i++) {
1450 if (i != CurrentTab)
1451 MainWindow->ProcessingTabBook->setTabEnabled(i, EnabledStatus);
1452 }
1453
1454 QList<ptToolBox*> NewToolList =
1455 MainWindow->ProcessingTabBook->widget(CurrentTab)->findChildren<ptToolBox*>();
1456 foreach (ptToolBox* Tool, NewToolList) {
1457 if (!AExcludeIds.contains(Tool->objectName()))
1458 Tool->setEnabled(EnabledStatus);
1459 }
1460 QList<ptGroupBox*> ToolList =
1461 MainWindow->ProcessingTabBook->widget(CurrentTab)->findChildren<ptGroupBox*>();
1462 foreach (ptGroupBox* Tool, ToolList) {
1463 if (!AExcludeIds.contains(Tool->objectName()))
1464 Tool->SetEnabled(EnabledStatus);
1465 }
1466 }
1467
1468 Settings->SetValue("BlockTools", ANewState);
1469 }
1470
1471 ////////////////////////////////////////////////////////////////////////////////
1472 //
1473 // Histogram
1474 //
1475 ////////////////////////////////////////////////////////////////////////////////
1476 void HistogramCropDone(const ptStatus ExitStatus, QRect SelectionRect);
1477
HistogramGetCrop()1478 void HistogramGetCrop() {
1479 // Get the crop for the histogram
1480 if (Settings->GetInt("HistogramCrop")) {
1481 // Allow to be selected in the view window. And deactivate main.
1482 BlockTools(btmBlockAll);
1483 ViewWindow->ShowStatus(QObject::tr("Selection"));
1484 ViewWindow->StartSimpleRect(HistogramCropDone);
1485 ViewWindow->setFocus();
1486 } else {
1487 ReportProgress(QObject::tr("Updating histogram"));
1488 Update(ptProcessorPhase_Preview);
1489 ReportProgress(QObject::tr("Ready"));
1490 }
1491 }
1492
HistogramCropDone(const ptStatus ExitStatus,QRect SelectionRect)1493 void HistogramCropDone(const ptStatus ExitStatus, QRect SelectionRect) {
1494 // Selection is done at this point. Disallow it further and activate main.
1495 BlockTools(btmUnblock);
1496 if (ExitStatus == stFailure) {
1497 Settings->SetValue("HistogramCropX",0);
1498 Settings->SetValue("HistogramCropY",0);
1499 Settings->SetValue("HistogramCropW",0);
1500 Settings->SetValue("HistogramCropH",0);
1501 Settings->SetValue("HistogramCrop",0);
1502 return;
1503 }
1504
1505 short XScale = 1<<Settings->GetInt("PipeSize");
1506 short YScale = 1<<Settings->GetInt("PipeSize");
1507
1508 Settings->SetValue("HistogramCropX", SelectionRect.left() * XScale);
1509 Settings->SetValue("HistogramCropY", SelectionRect.top() * YScale);
1510 Settings->SetValue("HistogramCropW", SelectionRect.width() * XScale);
1511 Settings->SetValue("HistogramCropH", SelectionRect.height() * YScale);
1512
1513 // Check if the chosen area is large enough
1514 if (Settings->GetInt("HistogramCropW") < 50 || Settings->GetInt("HistogramCropH") < 50) {
1515 ptMessageBox::information(0,
1516 QObject::tr("Selection too small"),
1517 QObject::tr("Selection rectangle needs to be at least 50x50 pixels in size.\nNo crop, try again."));
1518 Settings->SetValue("HistogramCropX",0);
1519 Settings->SetValue("HistogramCropY",0);
1520 Settings->SetValue("HistogramCropW",0);
1521 Settings->SetValue("HistogramCropH",0);
1522 Settings->SetValue("HistogramCrop",0);
1523 }
1524
1525 ReportProgress(QObject::tr("Updating histogram"));
1526 Update(ptProcessorPhase_Preview);
1527 ReportProgress(QObject::tr("Ready"));
1528 }
1529
1530
1531 ////////////////////////////////////////////////////////////////////////////////
1532 //
1533 // Status report in Viewwindow
1534 //
1535 ////////////////////////////////////////////////////////////////////////////////
1536
ViewWindowShowStatus(short State)1537 void ViewWindowShowStatus(short State) {
1538 if (ViewWindow) {
1539 ViewWindow->ShowStatus(State);
1540 }
1541 }
1542
1543 ////////////////////////////////////////////////////////////////////////////////
1544 //
1545 // Operations done right before gamma and profile for whatever reason
1546 // Finalrun to allow filters only on the final run
1547 // Resize to forbid resizing (-> histogram only on crop)
1548 //
1549 ////////////////////////////////////////////////////////////////////////////////
1550
BeforeGamma(ptImage * Image,const short FinalRun=0,const short Resize=1)1551 void BeforeGamma(ptImage* Image, const short FinalRun = 0, const short Resize = 1) {
1552
1553 if (Settings->GetInt("WebResizeBeforeGamma")==1 && Resize) {
1554 if (FinalRun == 1) Settings->SetValue("FullOutput",1);
1555 if (Settings->ToolIsActive("TabWebResize")) {
1556 ReportProgress(QObject::tr("WebResizing"));
1557 Image->ptGMResize(Settings->GetInt("WebResizeScale"),
1558 0,
1559 Settings->GetInt("WebResizeFilter"),
1560 Settings->GetInt("WebResizeDimension"));
1561 }
1562 if (FinalRun == 1) Settings->SetValue("FullOutput",0);
1563 }
1564
1565 // TODO put these curves together as devicelink into lcms
1566
1567 // BaseCurve.
1568 auto hFilter = GFilterDM->GetFilterFromName(Fuid::RgbCurve_Out);
1569 if (hFilter->isActive()) {
1570 ReportProgress(QObject::tr("Applying base curve"));
1571 hFilter->runFilter(Image);
1572 }
1573
1574 //GammaCompensation
1575 if (Settings->ToolIsActive("TabGammaCompensation")) {
1576 ReportProgress(QObject::tr("Applying gamma compensation"));
1577 ptCurve* CompensationCurve = new ptCurve();
1578 CompensationCurve->setFromFunc(ptCurve::DeltaGammaTool,Settings->GetDouble("OutputGamma"),
1579 Settings->GetDouble("OutputLinearity"));
1580 Image->ApplyCurve(CompensationCurve,7);
1581 delete CompensationCurve;
1582 }
1583 }
1584
1585 ////////////////////////////////////////////////////////////////////////////////
1586 //
1587 // Operations done after gamma and profile for whatever reason
1588 // Finalrun to allow filters only on the final run
1589 // Resize to forbid resizing (-> histogram only on crop)
1590 //
1591 ////////////////////////////////////////////////////////////////////////////////
1592
AfterAll(ptImage * Image,const short FinalRun=0,const short Resize=1)1593 void AfterAll(ptImage* Image, const short FinalRun = 0, const short Resize = 1) {
1594 // Sigmoidal contrast
1595 auto hFilter = GFilterDM->GetFilterFromName(Fuid::SigContrastRgb_Out);
1596 if (hFilter->isActive()) {
1597 ReportProgress(QObject::tr("Applying RGB Contrast"));
1598 hFilter->runFilter(Image);
1599 }
1600
1601 // After gamma curve
1602 hFilter = GFilterDM->GetFilterFromName(Fuid::AfterGammaCurve_Out);
1603 if (hFilter->isActive()) {
1604 ReportProgress(QObject::tr("Applying after gamma curve"));
1605 hFilter->runFilter(Image);
1606 }
1607
1608 // WebResize for quality reasons done after output profile
1609 if (Settings->GetInt("WebResizeBeforeGamma")==0 && Resize) {
1610 if (FinalRun == 1) Settings->SetValue("FullOutput",1);
1611 if (Settings->ToolIsActive("TabWebResize")) {
1612 ReportProgress(QObject::tr("WebResizing"));
1613 Image->ptGMResize(Settings->GetInt("WebResizeScale"),
1614 0,
1615 Settings->GetInt("WebResizeFilter"),
1616 Settings->GetInt("WebResizeDimension"));
1617 }
1618 if (FinalRun == 1) Settings->SetValue("FullOutput",0);
1619 }
1620 }
1621
EndSharpen(ptImage * Image,cmsHPROFILE Profile,const int Intent)1622 void EndSharpen(ptImage* Image, cmsHPROFILE Profile, const int Intent) {
1623 ReportProgress(QObject::tr("Wiener Filter"));
1624 int InColorSpace = Image->m_ColorSpace;
1625 cmsHPROFILE InternalProfile = 0;
1626 if (Profile == NULL || InColorSpace != ptSpace_Profiled) {
1627 // linear case
1628 cmsToneCurve* Gamma = cmsBuildGamma(NULL, 1.0);
1629 cmsToneCurve* Gamma3[3];
1630 Gamma3[0] = Gamma3[1] = Gamma3[2] = Gamma;
1631
1632 cmsCIExyY DFromReference;
1633
1634 switch (Image->m_ColorSpace) {
1635 case ptSpace_sRGB_D65 :
1636 case ptSpace_AdobeRGB_D65 :
1637 DFromReference = D65;
1638 break;
1639 case ptSpace_WideGamutRGB_D50 :
1640 case ptSpace_ProPhotoRGB_D50 :
1641 DFromReference = D50;
1642 break;
1643 default:
1644 assert(0);
1645 }
1646
1647 InternalProfile = cmsCreateRGBProfile(&DFromReference,
1648 (cmsCIExyYTRIPLE*)&RGBPrimaries[Image->m_ColorSpace],
1649 Gamma3);
1650
1651 if (!InternalProfile) {
1652 ptLogError(ptError_Profile,"Could not open InternalProfile profile.");
1653 return;
1654 }
1655
1656 cmsFreeToneCurve(Gamma);
1657 } else {
1658 // profiled case
1659 InternalProfile = Profile;
1660 }
1661
1662 cmsHPROFILE LabProfile = 0;
1663 LabProfile = cmsCreateLab4Profile(NULL);
1664 // to Lab
1665 cmsHTRANSFORM Transform;
1666 Transform = cmsCreateTransform(InternalProfile,
1667 TYPE_RGB_16,
1668 LabProfile,
1669 TYPE_Lab_16,
1670 Intent,
1671 cmsFLAGS_NOOPTIMIZE | cmsFLAGS_BLACKPOINTCOMPENSATION);
1672
1673 int32_t Size = Image->m_Width*Image->m_Height;
1674 int32_t Step = 100000;
1675 #pragma omp parallel for schedule(static)
1676 for (int32_t i = 0; i < Size; i+=Step) {
1677 int32_t Length = (i+Step)<Size ? Step : Size - i;
1678 uint16_t* Tile = &(Image->m_Image[i][0]);
1679 cmsDoTransform(Transform,Tile,Tile,Length);
1680 }
1681 Image->m_ColorSpace = ptSpace_Lab;
1682 // Wiener Filter
1683 GFilterDM->GetFilterFromName(Fuid::Wiener_Out)->runFilter(Image);
1684
1685 // to RGB
1686 Transform = cmsCreateTransform(LabProfile,
1687 TYPE_Lab_16,
1688 InternalProfile,
1689 TYPE_RGB_16,
1690 Intent,
1691 cmsFLAGS_NOOPTIMIZE | cmsFLAGS_BLACKPOINTCOMPENSATION);
1692
1693 #pragma omp parallel for schedule(static)
1694 for (int32_t i = 0; i < Size; i+=Step) {
1695 int32_t Length = (i+Step)<Size ? Step : Size - i;
1696 uint16_t* Tile = &(Image->m_Image[i][0]);
1697 cmsDoTransform(Transform,Tile,Tile,Length);
1698 }
1699
1700 cmsDeleteTransform(Transform);
1701 cmsCloseProfile(LabProfile);
1702 if (Profile == NULL || InColorSpace != ptSpace_Profiled)
1703 cmsCloseProfile(InternalProfile);
1704 Image->m_ColorSpace = InColorSpace;
1705 }
1706
1707 ////////////////////////////////////////////////////////////////////////////////
1708 //
1709 // Determine and update the preview image.
1710 //
1711 // ForcedImage claims that this image should be previewed.
1712 // (somehow of a hack : it is used for the Crop function where
1713 // we want the user to present fast a new image to be cropped without
1714 // having to calculate through the whole pipe).
1715 //
1716 // OnlyHistogram : hack to sync up the histogram when it was inactive.
1717 //
1718 ////////////////////////////////////////////////////////////////////////////////
1719
UpdatePreviewImage(const ptImage * ForcedImage,const short OnlyHistogram)1720 void UpdatePreviewImage(const ptImage* ForcedImage /* = NULL */,
1721 const short OnlyHistogram /* = false */) {
1722
1723 if (!PreviewImage) PreviewImage = new (ptImage);
1724
1725 // If we don't have yet a m_Image_AfterGeometry we are in
1726 // startup condition and show the start screen
1727 if (!TheProcessor->m_Image_AfterGeometry) {
1728 MainWindow->ViewFrameStackedWidget->setCurrentWidget(MainWindow->ViewStartPage);
1729 return;
1730 }
1731
1732 MainWindow->ViewFrameStackedWidget->setCurrentWidget(MainWindow->ViewFrameCentralWidget);
1733
1734 // Fast display of an image, e.g. for cropping
1735 // -> no histogram
1736 // -> only exposure for better display
1737 // -> transfer to preview color space
1738 if (ForcedImage) {
1739 PreviewImage->Set(ForcedImage);
1740 if (Settings->GetDouble("CropExposure") != 0.0) {
1741 PreviewImage->Expose(pow(2,Settings->GetDouble("CropExposure")), TExposureClipMode::Ratio);
1742 }
1743 BeforeGamma(PreviewImage,0,0);
1744
1745 // Convert from working space to screen space.
1746 // Using lcms and a standard sRGB or custom profile.
1747 ptImage* ReturnValue = PreviewImage->lcmsRGBToPreviewRGB(Settings->GetInt("CMQuality") == ptCMQuality_FastSRGB);
1748 if (!ReturnValue) {
1749 ptLogError(ptError_lcms,"lcmsRGBToPreviewRGB");
1750 assert(ReturnValue);
1751 }
1752 AfterAll(PreviewImage,0,0);
1753
1754 ViewWindow->UpdateImage(PreviewImage);
1755 ReportProgress(QObject::tr("Ready"));
1756 return;
1757 }
1758
1759 ViewWindow->ShowStatus(ptStatus_Updating);
1760 ReportProgress(QObject::tr("Updating preview image"));
1761
1762 if (!HistogramImage) HistogramImage = new (ptImage);
1763
1764 short ActiveTab = MainWindow->GetCurrentTab();
1765
1766 Settings->SetValue("ShowExposureIndicatorSensor",0);
1767
1768 // Determine first what is the current image.
1769 if (ForcedImage) {
1770 PreviewImage->Set(ForcedImage);
1771 } else if (Settings->GetInt("PreviewMode") == ptPreviewMode_End) {
1772 PreviewImage->Set(TheProcessor->m_Image_AfterEyeCandy);
1773 } else {
1774 if (!Settings->useRAWHandling()) ActiveTab = MAX(ptLocalTab, ActiveTab);
1775 switch (ActiveTab) {
1776 case ptCameraTab:
1777 Settings->SetValue("ShowExposureIndicatorSensor",1);
1778 if (Settings->GetInt("ExposureIndicatorSensor")) {
1779 PreviewImage->Set(TheDcRaw,
1780 Settings->GetInt("WorkColor"));
1781 } else {
1782 PreviewImage->Set(TheProcessor->m_Image_AfterDcRaw);
1783 }
1784 break;
1785 case ptLocalTab:
1786 PreviewImage->Set(TheProcessor->m_Image_AfterLocalEdit);
1787 break;
1788 case ptGeometryTab:
1789 PreviewImage->Set(TheProcessor->m_Image_AfterGeometry);
1790 break;
1791 case ptRGBTab:
1792 PreviewImage->Set(TheProcessor->m_Image_AfterRGB);
1793 break;
1794 case ptLabCCTab:
1795 PreviewImage->Set(TheProcessor->m_Image_AfterLabCC);
1796 break;
1797 case ptLabSNTab:
1798 PreviewImage->Set(TheProcessor->m_Image_AfterLabSN);
1799 break;
1800 case ptLabEyeCandyTab:
1801 PreviewImage->Set(TheProcessor->m_Image_AfterLabEyeCandy);
1802 break;
1803 case ptEyeCandyTab:
1804 case ptOutTab:
1805 PreviewImage->Set(TheProcessor->m_Image_AfterEyeCandy);
1806 break;
1807 default:
1808 // Should not happen.
1809 assert(0);
1810 }
1811 }
1812
1813 if (Settings->GetInt("HistogramMode")==ptHistogramMode_Linear) {
1814 HistogramImage->Set(PreviewImage);
1815 // If we are in a Tab preview mode and in the lab mode
1816 // we do the conversion to Lab in case it would not have been
1817 // done yet (due to suppressed for speed in absense of USM or L Curve).
1818 // This way the histogram is an L Histogram at this point.
1819 if ( (Settings->GetInt("PreviewMode") == ptPreviewMode_Tab) &&
1820 (ActiveTab == ptLabCCTab || ActiveTab == ptLabSNTab || ActiveTab == ptLabEyeCandyTab) &&
1821 (HistogramImage->m_ColorSpace != ptSpace_Lab) ) {
1822 HistogramImage->RGBToLab();
1823 }
1824 } else if (Settings->GetInt("HistogramMode")==ptHistogramMode_Output &&
1825 !(Settings->GetInt("HistogramCrop") && !Settings->GetInt("WebResize"))) {
1826 HistogramImage->Set(PreviewImage);
1827
1828
1829 } else if (Settings->GetInt("HistogramCrop")) {
1830 HistogramImage->Set(PreviewImage);
1831 }
1832
1833 if (PreviewImage->m_ColorSpace == ptSpace_Lab)
1834 PreviewImage->LabToRGB(Settings->GetInt("WorkColor"));
1835
1836 uint16_t Width = 0;
1837 uint16_t Height = 0;
1838 uint16_t TempCropX = 0;
1839 uint16_t TempCropY = 0;
1840 uint16_t TempCropW = 0;
1841 uint16_t TempCropH = 0;
1842
1843 if (Settings->GetInt("HistogramMode")==ptHistogramMode_Linear) {
1844 ReportProgress(QObject::tr("Updating histogram"));
1845
1846 if (Settings->GetInt("HistogramCrop")) {
1847 float TmpScaled = TheProcessor->m_ScaleFactor;
1848 Width = HistogramImage->m_Width;
1849 Height = HistogramImage->m_Height;
1850 TempCropX = Settings->GetInt("HistogramCropX")*TmpScaled;
1851 TempCropY = Settings->GetInt("HistogramCropY")*TmpScaled;
1852 TempCropW = Settings->GetInt("HistogramCropW")*TmpScaled;
1853 TempCropH = Settings->GetInt("HistogramCropH")*TmpScaled;
1854 if ((((TempCropX) + (TempCropW)) > Width) ||
1855 (((TempCropY) + (TempCropH)) > Height)) {
1856 ptMessageBox::information(MainWindow,
1857 QObject::tr("Histogram selection outside the image"),
1858 QObject::tr("Histogram selection rectangle too large.\nNo crop, try again."));
1859 Settings->SetValue("HistogramCropX",0);
1860 Settings->SetValue("HistogramCropY",0);
1861 Settings->SetValue("HistogramCropW",0);
1862 Settings->SetValue("HistogramCropH",0);
1863 Settings->SetValue("HistogramCrop",0);
1864 } else {
1865 HistogramImage->Crop(TempCropX, TempCropY, TempCropW, TempCropH);
1866 }
1867 }
1868
1869 // In case of histogram update only, we're done.
1870 if (OnlyHistogram) {
1871 HistogramWindow->UpdateView(HistogramImage);
1872 ViewWindow->ShowStatus(ptStatus_Done);
1873 return;
1874 }
1875 }
1876
1877 uint8_t ExposureChannelMask = 0;
1878 uint16_t OverExposureLevel[3];
1879 uint16_t UnderExposureLevel[3];
1880 if (Settings->GetInt("ExposureIndicator")) {
1881 ReportProgress(QObject::tr("Indicating exposure"));
1882
1883 if (Settings->GetInt("ExposureIndicatorR")) ExposureChannelMask |= 1;
1884 if (Settings->GetInt("ExposureIndicatorG")) ExposureChannelMask |= 2;
1885 if (Settings->GetInt("ExposureIndicatorB")) ExposureChannelMask |= 4;
1886
1887 if (ActiveTab == ptCameraTab && Settings->GetInt("ExposureIndicatorSensor")){
1888 OverExposureLevel[0] = CLIP((int32_t)
1889 ((TheDcRaw->m_WhiteLevel_AfterPhase1-TheDcRaw->m_BlackLevel_AfterPhase1)
1890 *TheDcRaw->m_Multipliers[0]));
1891 OverExposureLevel[1] = CLIP((int32_t)
1892 ((TheDcRaw->m_WhiteLevel_AfterPhase1-TheDcRaw->m_BlackLevel_AfterPhase1)
1893 *TheDcRaw->m_Multipliers[1]));
1894 OverExposureLevel[2] = CLIP((int32_t)
1895 ((TheDcRaw->m_WhiteLevel_AfterPhase1-TheDcRaw->m_BlackLevel_AfterPhase1)
1896 *TheDcRaw->m_Multipliers[2]));
1897 UnderExposureLevel[0] = 0x0000;
1898 UnderExposureLevel[1] = 0x0000;
1899 UnderExposureLevel[2] = 0x0000;
1900 } else {
1901 OverExposureLevel[0] = 0xfff0;
1902 OverExposureLevel[1] = 0xfff0;
1903 OverExposureLevel[2] = 0xfff0;
1904 UnderExposureLevel[0] = 0x000f;
1905 UnderExposureLevel[1] = 0x000f;
1906 UnderExposureLevel[2] = 0x000f;
1907 }
1908 }
1909
1910 if (!ForcedImage) {
1911 BeforeGamma(PreviewImage);
1912 }
1913
1914 if (Settings->GetInt("HistogramMode")==ptHistogramMode_Output) {
1915
1916 ReportProgress(QObject::tr("Updating histogram"));
1917 if (Settings->GetInt("HistogramCrop") && !Settings->GetInt("WebResize")) {
1918 HistogramImage->Set(PreviewImage);
1919 } else {
1920 BeforeGamma(HistogramImage,0,0);
1921 }
1922
1923 ReportProgress(QObject::tr("Converting to output space"));
1924
1925 cmsHPROFILE OutputColorProfile = NULL;
1926 OutputColorProfile = cmsOpenProfileFromFile(
1927 Settings->GetString("OutputColorProfile").toLocal8Bit().data(), "r");
1928 if (!OutputColorProfile) {
1929 ptLogError(ptError_FileOpen,
1930 Settings->GetString("OutputColorProfile").toLocal8Bit().data());
1931 assert(OutputColorProfile);
1932 }
1933
1934 // Convert from working space to screen space.
1935 // Using lcms and a standard sRGB or custom profile.
1936
1937 ptImage* ReturnValue = HistogramImage->lcmsRGBToRGB(
1938 OutputColorProfile,
1939 Settings->GetInt("OutputColorProfileIntent"),
1940 Settings->GetInt("CMQuality"));
1941 if (!ReturnValue) {
1942 ptLogError(ptError_lcms,"lcmsRGBToRGB(OutputColorProfile)");
1943 assert(ReturnValue);
1944 }
1945
1946 if (Settings->GetInt("HistogramCrop") && !Settings->GetInt("WebResize")) {
1947 AfterAll(HistogramImage);
1948 if (GFilterDM->GetFilterFromName(Fuid::Wiener_Out)->isActive() &&
1949 Settings->GetInt("PreviewMode") == ptPreviewMode_End)
1950 {
1951 EndSharpen(HistogramImage, OutputColorProfile, Settings->GetInt("OutputColorProfileIntent"));
1952 }
1953 } else {
1954 AfterAll(HistogramImage,0,0);
1955 if (GFilterDM->GetFilterFromName(Fuid::Wiener_Out)->isActive() &&
1956 Settings->GetInt("PreviewMode") == ptPreviewMode_End)
1957 {
1958 EndSharpen(HistogramImage, OutputColorProfile, Settings->GetInt("OutputColorProfileIntent"));
1959 }
1960 }
1961
1962 // Close the output profile.
1963 cmsCloseProfile(OutputColorProfile);
1964
1965 if (Settings->GetInt("HistogramCrop")) {
1966 float TmpScaled = TheProcessor->m_ScaleFactor;
1967 Width = HistogramImage->m_Width;
1968 Height = HistogramImage->m_Height;
1969 TempCropX = Settings->GetInt("HistogramCropX")*TmpScaled;
1970 TempCropY = Settings->GetInt("HistogramCropY")*TmpScaled;
1971 TempCropW = Settings->GetInt("HistogramCropW")*TmpScaled;
1972 TempCropH = Settings->GetInt("HistogramCropH")*TmpScaled;
1973 if ((((TempCropX) + (TempCropW)) > Width) ||
1974 (((TempCropY) + (TempCropH)) > Height)) {
1975 ptMessageBox::information(MainWindow,
1976 QObject::tr("Histogram selection outside the image"),
1977 QObject::tr("Histogram selection rectangle too large.\nNo crop, try again."));
1978 Settings->SetValue("HistogramCropX",0);
1979 Settings->SetValue("HistogramCropY",0);
1980 Settings->SetValue("HistogramCropW",0);
1981 Settings->SetValue("HistogramCropH",0);
1982 Settings->SetValue("HistogramCrop",0);
1983 } else {
1984 HistogramImage->Crop(TempCropX, TempCropY, TempCropW, TempCropH);
1985 }
1986 }
1987 if (OnlyHistogram) {
1988 HistogramWindow->UpdateView(HistogramImage);
1989 ViewWindow->ShowStatus(ptStatus_Done);
1990 return;
1991 }
1992 }
1993
1994 ReportProgress(QObject::tr("Converting to screen space"));
1995
1996 // Convert from working space to screen space.
1997 // Using lcms and a standard sRGB or custom profile.
1998 PreviewImage->lcmsRGBToPreviewRGB(Settings->GetInt("CMQuality") == ptCMQuality_FastSRGB);
1999
2000 if (!ForcedImage) {
2001 AfterAll(PreviewImage);
2002 if (GFilterDM->GetFilterFromName(Fuid::Wiener_Out)->isActive() &&
2003 Settings->GetInt("PreviewMode") == ptPreviewMode_End)
2004 {
2005 EndSharpen(PreviewImage, PreviewColorProfile, Settings->GetInt("PreviewColorProfileIntent"));
2006 }
2007 }
2008
2009 if (Settings->GetInt("HistogramMode")==ptHistogramMode_Preview) {
2010 if (!Settings->GetInt("HistogramCrop") ||
2011 (Settings->GetInt("HistogramCrop") && !Settings->GetInt("WebResize"))) {
2012 HistogramImage->Set(PreviewImage);
2013 } else if (Settings->GetInt("HistogramCrop")) {
2014 BeforeGamma(HistogramImage,0,0);
2015
2016 ptImage* ReturnValue = HistogramImage->lcmsRGBToPreviewRGB(Settings->GetInt("CMQuality") == ptCMQuality_FastSRGB);
2017 if (!ReturnValue) {
2018 ptLogError(ptError_lcms,"lcmsRGBToPreviewRGB");
2019 assert(ReturnValue);
2020 }
2021
2022 AfterAll(HistogramImage,0,0);
2023 if (GFilterDM->GetFilterFromName(Fuid::Wiener_Out)->isActive() &&
2024 Settings->GetInt("PreviewMode") == ptPreviewMode_End)
2025 {
2026 EndSharpen(HistogramImage, PreviewColorProfile, Settings->GetInt("PreviewColorProfileIntent"));
2027 }
2028 }
2029
2030 if (Settings->GetInt("HistogramCrop")) {
2031 float TmpScaled = TheProcessor->m_ScaleFactor;
2032 Width = HistogramImage->m_Width;
2033 Height = HistogramImage->m_Height;
2034 TempCropX = Settings->GetInt("HistogramCropX")*TmpScaled;
2035 TempCropY = Settings->GetInt("HistogramCropY")*TmpScaled;
2036 TempCropW = Settings->GetInt("HistogramCropW")*TmpScaled;
2037 TempCropH = Settings->GetInt("HistogramCropH")*TmpScaled;
2038 if ((((TempCropX) + (TempCropW)) > Width) ||
2039 (((TempCropY) + (TempCropH)) > Height)) {
2040 ptMessageBox::information(MainWindow,
2041 QObject::tr("Histogram selection outside the image"),
2042 QObject::tr("Histogram selection rectangle too large.\nNo crop, try again."));
2043 Settings->SetValue("HistogramCropX",0);
2044 Settings->SetValue("HistogramCropY",0);
2045 Settings->SetValue("HistogramCropW",0);
2046 Settings->SetValue("HistogramCropH",0);
2047 Settings->SetValue("HistogramCrop",0);
2048 } else {
2049 HistogramImage->Crop(TempCropX, TempCropY, TempCropW, TempCropH);
2050 }
2051 }
2052 }
2053
2054 if (!OnlyHistogram) {
2055 if (Settings->GetInt("HistogramMode")==ptHistogramMode_Output) {
2056 if (Settings->GetInt("ExposureIndicator"))
2057 PreviewImage->IndicateExposure(HistogramImage,
2058 Settings->GetInt("ExposureIndicatorOver"),
2059 Settings->GetInt("ExposureIndicatorUnder"),
2060 ExposureChannelMask,
2061 OverExposureLevel,
2062 UnderExposureLevel);
2063 } else {
2064 if (Settings->GetInt("ExposureIndicator"))
2065 PreviewImage->IndicateExposure(Settings->GetInt("ExposureIndicatorOver"),
2066 Settings->GetInt("ExposureIndicatorUnder"),
2067 ExposureChannelMask,
2068 OverExposureLevel,
2069 UnderExposureLevel);
2070 }
2071
2072 // Get a special preview
2073 if (Settings->GetInt("SpecialPreview"))
2074 PreviewImage->SpecialPreview(Settings->GetInt("SpecialPreview"),
2075 Settings->GetInt("PreviewColorProfileIntent"));
2076
2077 // Update the ViewWindow and show if needed.
2078 ViewWindow->UpdateImage(PreviewImage);
2079 }
2080
2081 HistogramWindow->UpdateView(HistogramImage);
2082 ViewWindow->ShowStatus(ptStatus_Done);
2083
2084 ReportProgress(QObject::tr("Ready"));
2085
2086 if (!OnlyHistogram) {
2087 if (Settings->GetInt("WriteBackupSettings")) {
2088 GFilterDM->WritePresetFile(Settings->GetString("UserDirectory")+"backup.pts");
2089 }
2090 }
2091 } // UpdatePreviewImage
2092
2093
2094 ////////////////////////////////////////////////////////////////////////////////
2095 //
2096 // RunJob (the non-interactive 'batch' run).
2097 //
2098 ////////////////////////////////////////////////////////////////////////////////
2099
RunJob(const QString JobFileName)2100 void RunJob(const QString JobFileName) {
2101 Settings->SetValue("JobMode",1);
2102 // Init
2103 CB_Event0();
2104
2105 // Read the gui settings from a file.
2106 short NextPhase = 1;
2107 short ReturnValue = GFilterDM->ReadPresetFile(JobFileName, NextPhase);
2108 // TODO: BJ Implement spot processing
2109 if (ReturnValue) {
2110 printf("\nNo valid job file!\n\n");
2111 return;
2112 }
2113
2114 QStringList InputFileNameList = Settings->GetStringList("InputFileNameList");
2115 assert(InputFileNameList.size());
2116
2117 do {
2118 try {
2119 // Test if we can handle the file
2120 ptDcRaw* TestDcRaw = new(ptDcRaw);
2121 Settings->ToDcRaw(TestDcRaw);
2122 uint16_t InputWidth = 0;
2123 uint16_t InputHeight = 0;
2124 ptImageType InputType = CheckImageType(InputFileNameList[0],
2125 &InputWidth, &InputHeight,
2126 TestDcRaw);
2127
2128 if (InputType <= itUndetermined) {
2129 // not a supported image type or error reading the file
2130 QString ErrorMessage = QObject::tr("Cannot decode")
2131 + " '"
2132 + InputFileNameList[0]
2133 + "'" ;
2134 printf("%s\n",ErrorMessage.toLocal8Bit().data());
2135 delete TestDcRaw;
2136
2137
2138 } else {
2139 // process the image
2140 if (InputType == itRaw) {
2141 Settings->SetValue("IsRAW",1);
2142 } else {
2143 Settings->SetValue("IsRAW",0);
2144 }
2145
2146 if (!Settings->useRAWHandling()) {
2147 Settings->SetValue("ExposureNormalization", 0.0);
2148 }
2149
2150 QFileInfo PathInfo(InputFileNameList[0]);
2151 if (!Settings->GetString("OutputDirectory").isEmpty()) {
2152 Settings->SetValue("OutputFileName",
2153 Settings->GetString("OutputDirectory") + "/" + PathInfo.completeBaseName());
2154 } else {
2155 Settings->SetValue("OutputFileName",
2156 PathInfo.dir().path() + "/" + PathInfo.completeBaseName());
2157 }
2158 if (!Settings->GetString("OutputFileNameSuffix").isEmpty()) {
2159 Settings->SetValue("OutputFileName",
2160 Settings->GetString("OutputFileName") +
2161 Settings->GetString("OutputFileNameSuffix"));
2162 }
2163 else {
2164 if (!Settings->GetInt("IsRAW")) {
2165 Settings->SetValue("OutputFileName",
2166 Settings->GetString("OutputFileName") + "-new");
2167 }
2168 }
2169
2170 // Here we have the OutputFileName, but extension still to add.
2171 switch(Settings->GetInt("SaveFormat")) {
2172 case ptSaveFormat_JPEG :
2173 Settings->SetValue("OutputFileName",
2174 Settings->GetString("OutputFileName") + ".jpg");
2175 break;
2176 case ptSaveFormat_PNG :
2177 case ptSaveFormat_PNG16 :
2178 Settings->SetValue("OutputFileName",
2179 Settings->GetString("OutputFileName") + ".png");
2180 break;
2181 case ptSaveFormat_TIFF8 :
2182 case ptSaveFormat_TIFF16 :
2183 Settings->SetValue("OutputFileName",
2184 Settings->GetString("OutputFileName") + ".tif");
2185 break;
2186 default :
2187 Settings->SetValue("OutputFileName",
2188 Settings->GetString("OutputFileName") + ".ppm");
2189 break;
2190 }
2191
2192 // Processing the job.
2193 delete TheDcRaw;
2194 delete TheProcessor;
2195 TheProcessor = new ptProcessor(ReportProgress);
2196 TheDcRaw = TestDcRaw;
2197 Settings->SetValue("ImageW",InputWidth);
2198 Settings->SetValue("ImageH",InputHeight);
2199
2200 TheProcessor->m_DcRaw = TheDcRaw;
2201
2202 Settings->SetValue("RunMode",0);
2203 Settings->SetValue("FullOutput",1);
2204 TheProcessor->Run(ptProcessorPhase_Raw,ptProcessorPhase_Load,0,1);
2205 Settings->SetValue("FullOutput",0);
2206 // And write result.
2207 Update(ptProcessorPhase_WriteOut);
2208 }
2209 } catch (std::bad_alloc) {
2210 QString ErrorMessage = QObject::tr("Memory error, no conversion for file:")
2211 + " '"
2212 + InputFileNameList[0]
2213 + "'" ;
2214 printf("%s\n",ErrorMessage.toLocal8Bit().data());
2215 }
2216
2217 // Loop over the inputfiles by shifting the next one to index 0
2218 if (InputFileNameList.size()) {
2219 InputFileNameList.removeAt(0);
2220 }
2221
2222 // Write the changed InputFileNameList back to the settings.
2223 Settings->SetValue("InputFileNameList",InputFileNameList);
2224
2225 } while (InputFileNameList.size());
2226 } // RunJob
2227
2228 //==============================================================================
2229 // Prepares the tags list and sets TagsList and DigikamTagsList
PrepareTags(const QString TagsInput)2230 void PrepareTags(const QString TagsInput) {
2231
2232 QString WorkString = TagsInput;
2233 WorkString.replace("\n",",");
2234 while (WorkString.contains(" "))
2235 WorkString.replace(" "," ");
2236 if (WorkString.startsWith(" ")) WorkString.remove(0,1);
2237 if (WorkString.endsWith(" ")) WorkString.remove(WorkString.size()-1,1);
2238 while (WorkString.contains("//"))
2239 WorkString.replace("//","/");
2240 while (WorkString.contains("/ /"))
2241 WorkString.replace("/ /","/");
2242 if (WorkString.endsWith("/")) WorkString.remove(WorkString.size()-1,1);
2243 WorkString.replace(" ,",",");
2244 WorkString.replace("/,",",");
2245 WorkString.replace(" ,",","); // We need this again!
2246 WorkString.replace(" /","/");
2247 WorkString.replace("/ ","/");
2248 WorkString.replace(",/",",");
2249 WorkString.replace(", ",",");
2250 if (WorkString.startsWith("/")) WorkString.remove(0,1);
2251
2252 QStringList DigikamTags = WorkString.split(",", QString::SkipEmptyParts);
2253
2254 QStringList Tags;
2255 QString TempString;
2256 for (int i = 0; i < DigikamTags.size(); i++) {
2257 TempString = DigikamTags.at(i);
2258 TempString.remove(0,TempString.lastIndexOf("/")+1);
2259 if (TempString.startsWith(" ")) TempString.remove(0,1);
2260 Tags << TempString;
2261 }
2262
2263 Settings->SetValue("DigikamTagsList", DigikamTags);
2264 Settings->SetValue("TagsList", Tags);
2265 }
2266
2267 //==============================================================================
2268
2269 /*! Write out in one of the output formats (after applying output profile). */
WriteOut()2270 void WriteOut() {
2271 ptImage* OutImage = NULL;
2272
2273 if (Settings->GetInt("JobMode") == 1) {
2274 OutImage = TheProcessor->m_Image_AfterEyeCandy; // Job mode -> no cache
2275 } else {
2276 if (!OutImage) OutImage = new(ptImage);
2277 OutImage->Set(TheProcessor->m_Image_AfterEyeCandy);
2278 }
2279
2280 BeforeGamma(OutImage, 1);
2281
2282 cmsHPROFILE OutputColorProfile = NULL;
2283
2284 ReportProgress(QObject::tr("Converting to output space"));
2285
2286 // Prepare and open an output profile.
2287 OutputColorProfile = cmsOpenProfileFromFile(
2288 Settings->GetString("OutputColorProfile").toLocal8Bit().data(),
2289 "r");
2290 if (!OutputColorProfile) {
2291 ptLogError(ptError_FileOpen,
2292 Settings->GetString("OutputColorProfile").toLocal8Bit().data());
2293 assert(OutputColorProfile);
2294 }
2295
2296 // Color space conversion
2297 ptImage* ReturnValue = OutImage->lcmsRGBToRGB(
2298 OutputColorProfile,
2299 Settings->GetInt("OutputColorProfileIntent"),
2300 Settings->GetInt("CMQuality"));
2301 if (!ReturnValue) {
2302 ptLogError(ptError_lcms,"lcmsRGBToRGB(OutputColorProfile)");
2303 assert(ReturnValue);
2304 }
2305
2306 AfterAll(OutImage, 1);
2307 if (GFilterDM->GetFilterFromName(Fuid::Wiener_Out)->isActive())
2308 EndSharpen(OutImage, OutputColorProfile, Settings->GetInt("OutputColorProfileIntent"));
2309 // Close the output profile.
2310 cmsCloseProfile(OutputColorProfile);
2311
2312 ReportProgress(QObject::tr("Writing output"));
2313
2314 bool FileWritten = OutImage->ptGMCWriteImage(
2315 Settings->GetString("OutputFileName").toLocal8Bit().data(),
2316 Settings->GetInt("SaveFormat"),
2317 Settings->GetInt("SaveQuality"),
2318 Settings->GetInt("SaveSampling"),
2319 Settings->GetInt("SaveResolution"),
2320 Settings->GetString("OutputColorProfile").toLocal8Bit().data(),
2321 Settings->GetInt("OutputColorProfileIntent"));
2322
2323 if (!FileWritten) {
2324 ptMessageBox::warning(MainWindow, QObject::tr("GraphicsMagick Error"), QObject::tr("No output file written."));
2325 } else {
2326 ReportProgress(QObject::tr("Writing output (exif)"));
2327
2328 if (Settings->GetInt("IncludeExif")) {
2329 if (!ptImageHelper::WriteExif(Settings->GetString("OutputFileName"),
2330 TheProcessor->m_ExifBuffer,
2331 IptcData,
2332 XmpData))
2333 ptMessageBox::warning(MainWindow, QObject::tr("Exif Error"), QObject::tr("No exif data written."));
2334 }
2335 }
2336
2337 if (Settings->GetInt("JobMode") == 0) delete OutImage;
2338
2339 if (JobMode == 0) {
2340 // This variable carries only JobMode, the "JobMode" settings
2341 // is also used for full image output.
2342 ReportProgress(QObject::tr("Writing output (settings)"));
2343
2344 QFileInfo PathInfo(Settings->GetString("OutputFileName"));
2345 QString SettingsFileName = PathInfo.dir().path() + "/" + PathInfo.completeBaseName() + ".pts";
2346
2347 GFilterDM->WritePresetFile(SettingsFileName);
2348 }
2349
2350 if (FileWritten) {
2351 QFileInfo hInfo = QFileInfo(Settings->GetString("OutputFileName"));
2352 ReportProgress(
2353 QString(QObject::tr("Written %L1 bytes (%L2 MByte)"))
2354 .arg(hInfo.size())
2355 .arg((float)hInfo.size()/1024/1024, 0, 'f', 2)
2356 );
2357 } else {
2358 ReportProgress(QObject::tr("Ready"));
2359 }
2360 }
2361
2362 //==============================================================================
2363
WritePipe(QString OutputName="")2364 void WritePipe(QString OutputName = "") {
2365
2366 if (Settings->GetInt("HaveImage")==0) return;
2367
2368 QStringList InputFileNameList = Settings->GetStringList("InputFileNameList");
2369 QFileInfo PathInfo(InputFileNameList[0]);
2370 QString SuggestedFileName = PathInfo.dir().path() + "/" + PathInfo.completeBaseName();
2371 if (!Settings->GetString("OutputFileNameSuffix").isEmpty())
2372 SuggestedFileName += Settings->GetString("OutputFileNameSuffix");
2373 else
2374 if (!Settings->GetInt("IsRAW")) SuggestedFileName += "-new";
2375 QString Pattern;
2376
2377 switch(Settings->GetInt("SaveFormat")) {
2378 case ptSaveFormat_JPEG :
2379 SuggestedFileName += ".jpg";
2380 Pattern = QObject::tr("Jpg images (*.jpg *.jpeg);;All files (*.*)");
2381 break;
2382 case ptSaveFormat_PNG :
2383 case ptSaveFormat_PNG16 :
2384 SuggestedFileName += ".png";
2385 Pattern = QObject::tr("PNG images(*.png);;All files (*.*)");
2386 break;
2387 case ptSaveFormat_TIFF8 :
2388 case ptSaveFormat_TIFF16 :
2389 SuggestedFileName += ".tif";
2390 Pattern = QObject::tr("Tiff images (*.tif *.tiff);;All files (*.*)");
2391 break;
2392 default :
2393 SuggestedFileName += ".ppm";
2394 Pattern = QObject::tr("Ppm images (*.ppm);;All files (*.*)");
2395 break;
2396 }
2397
2398 QString FileName = OutputName;
2399 if (FileName == "")
2400 FileName = QFileDialog::getSaveFileName(NULL,
2401 QObject::tr("Save File"),
2402 SuggestedFileName,
2403 Pattern);
2404
2405 if (0 == FileName.size()) return; // Operation cancelled.
2406
2407 Settings->SetValue("OutputFileName",FileName);
2408
2409 // Write out (maybe after applying gamma).
2410 Update(ptProcessorPhase_WriteOut);
2411 ImageSaved = 1;
2412 }
2413
2414 ////////////////////////////////////////////////////////////////////////////////
2415 //
2416 // Utility : Update GuiSettings->m_?Multiplier according
2417 // to the ColorTemperature/GreenIntensity in the GuiSettings.
2418 //
2419 ////////////////////////////////////////////////////////////////////////////////
2420
CalculateMultipliersFromTemperature()2421 void CalculateMultipliersFromTemperature() {
2422
2423 // m_D65Multipliers are supposed to be D65
2424 // (setting Pre to the ratio of the D65 delivers
2425 // rgbWB = (x,x,x) and 6500 temperature).
2426
2427 double RefRGB[3];
2428 TemperatureToRGB(Settings->GetInt("ColorTemperature"),RefRGB);
2429 RefRGB[1] /= Settings->GetDouble("GreenIntensity");
2430 if (TheDcRaw->m_RawColorPhotivo) {
2431 Settings->SetValue("RMultiplier",
2432 VALUE(TheDcRaw->m_D65Multipliers[0])/RefRGB[0]);
2433 Settings->SetValue("GMultiplier",
2434 VALUE(TheDcRaw->m_D65Multipliers[1])/RefRGB[1]);
2435 Settings->SetValue("BMultiplier",
2436 VALUE(TheDcRaw->m_D65Multipliers[2])/RefRGB[2]);
2437 } else {
2438 // If not raw color, calculate RefRGB in sRGB back to the camera RGB
2439 for (short c=0; c<TheDcRaw->m_Colors; c++) {
2440 double InverseMultiplier = 0;
2441 for (short cc=0; cc<3; cc++) {
2442 InverseMultiplier += 1/VALUE(TheDcRaw->m_D65Multipliers[c])
2443 * TheDcRaw->m_MatrixSRGBToCamRGB[c][cc]
2444 * RefRGB[cc];
2445 }
2446 switch (c) {
2447 case 0 :
2448 Settings->SetValue("RMultiplier",1/InverseMultiplier);
2449 break;
2450 case 1 :
2451 Settings->SetValue("GMultiplier",1/InverseMultiplier);
2452 break;
2453 case 2 :
2454 Settings->SetValue("BMultiplier",1/InverseMultiplier);
2455 break;
2456 default :
2457 assert(0);
2458 }
2459 }
2460 }
2461 }
2462
2463 ////////////////////////////////////////////////////////////////////////////////
2464 //
2465 // Utility function : Normalize the Multipliers to largest 1.0
2466 // If Max is set, normalize to lowest 1.0
2467 //
2468 ////////////////////////////////////////////////////////////////////////////////
2469
NormalizeMultipliers(const short Max=0)2470 void NormalizeMultipliers(const short Max = 0) {
2471 if (Max == 0) {
2472 double Maximum = Settings->GetDouble("RMultiplier");
2473 if (Settings->GetDouble("GMultiplier") > Maximum)
2474 Maximum = Settings->GetDouble("GMultiplier");
2475 if (Settings->GetDouble("BMultiplier") > Maximum)
2476 Maximum = Settings->GetDouble("BMultiplier");
2477 assert (Maximum > 0.0);
2478 Settings->SetValue("RMultiplier",Settings->GetDouble("RMultiplier")/Maximum);
2479 Settings->SetValue("GMultiplier",Settings->GetDouble("GMultiplier")/Maximum);
2480 Settings->SetValue("BMultiplier",Settings->GetDouble("BMultiplier")/Maximum);
2481 } else {
2482 double Minimum = Settings->GetDouble("RMultiplier");
2483 if (Settings->GetDouble("GMultiplier") < Minimum)
2484 Minimum = Settings->GetDouble("GMultiplier");
2485 if (Settings->GetDouble("BMultiplier") < Minimum)
2486 Minimum = Settings->GetDouble("BMultiplier");
2487 assert (Minimum > 0.0);
2488 Settings->SetValue("RMultiplier",Settings->GetDouble("RMultiplier")/Minimum);
2489 Settings->SetValue("GMultiplier",Settings->GetDouble("GMultiplier")/Minimum);
2490 Settings->SetValue("BMultiplier",Settings->GetDouble("BMultiplier")/Minimum);
2491 }
2492 }
2493
2494 //==============================================================================
2495 // Handles the display of the pixel values
CB_PixelReader(const QPointF Point,const ptPixelReading PixelReading)2496 void CB_PixelReader(const QPointF Point, const ptPixelReading PixelReading) {
2497 // No display while pipe is running
2498 if (Settings->GetInt("PipeIsRunning") || Settings->GetInt("HaveImage")==0) {
2499 HistogramWindow->PixelInfoHide();
2500 return;
2501 }
2502
2503 RGBValue RGB;
2504
2505 // reset the display
2506 if (PixelReading == prNone) {
2507 HistogramWindow->PixelInfoHide();
2508 return;
2509 } else if (PixelReading == prLinear) {
2510 // we use the AfterEyeCandy image as source
2511 RGB = TheProcessor->m_Image_AfterEyeCandy->GetRGB(Point.x(), Point.y());
2512 } else {
2513 // we use the PreviewImage as source
2514 RGB = PreviewImage->GetRGB(Point.x(), Point.y());
2515 }
2516
2517 // We normalize the values to 0..100
2518 HistogramWindow->PixelInfo(QString::number(RGB.R/655.35, 'f', 2),
2519 QString::number(RGB.G/655.35, 'f', 2),
2520 QString::number(RGB.B/655.35, 'f', 2));
2521 }
2522
2523 ////////////////////////////////////////////////////////////////////////////////
2524 //
2525 // For convenience...
2526 //
2527 ////////////////////////////////////////////////////////////////////////////////
2528
UpdateSettings()2529 void UpdateSettings() {
2530 MainWindow->UpdateSettings();
2531 }
2532
2533 ////////////////////////////////////////////////////////////////////////////////
2534 //
2535 // Callback pertaining to the Tabs structure (switching page)
2536 //
2537 ////////////////////////////////////////////////////////////////////////////////
2538
CB_Tabs(const short)2539 void CB_Tabs(const short) {
2540 // If we are previewing according to Tab, we now have to update.
2541 if (Settings->GetInt("PreviewMode") == ptPreviewMode_Tab) {
2542 Update(ptProcessorPhase_Preview);
2543 }
2544 }
2545
2546
2547 ////////////////////////////////////////////////////////////////////////////////
2548 //
2549 // Callbacks pertaining to the Menu structure.
2550 // (inclusive 'X' pressing).
2551 //
2552 ////////////////////////////////////////////////////////////////////////////////
2553
CB_MenuFileOpen(const short HaveFile)2554 void CB_MenuFileOpen(const short HaveFile) {
2555 QStringList OldInputFileNameList = Settings->GetStringList("InputFileNameList");
2556 QString InputFileName = "";
2557 if (HaveFile) {
2558 InputFileName = ImageFileToOpen;
2559 }
2560
2561 // Ask user confirmation
2562 if (Settings->GetInt("HaveImage") == 1) {
2563 if (!ptConfirmRequest::saveImage(InputFileName)) {
2564 return;
2565 }
2566 }
2567
2568 // open file dialog
2569 if (!HaveFile) {
2570 InputFileName =
2571 QFileDialog::getOpenFileName(NULL,
2572 QObject::tr("Open Raw"),
2573 Settings->GetString("RawsDirectory"),
2574 RawPattern);
2575 }
2576
2577 // no new image file: abort
2578 if (InputFileName == "") {
2579 return;
2580 } else {
2581 if (!QFile::exists(InputFileName)) {
2582 ptMessageBox::warning(NULL,
2583 QObject::tr("File not found"),
2584 QObject::tr("Input file does not exist.") + "\n\n" + InputFileName);
2585 return;
2586 }
2587 }
2588
2589 QFileInfo PathInfo(InputFileName);
2590 Settings->SetValue("RawsDirectory",PathInfo.absolutePath());
2591 QStringList InputFileNameList;
2592 InputFileNameList << PathInfo.absoluteFilePath();
2593
2594 Settings->SetValue("InputFileNameList",InputFileNameList);
2595
2596 // Feedback to the user
2597 ReportProgress(QObject::tr("Reading file"));
2598
2599 // Test if we can handle the file
2600 ptDcRaw* TestDcRaw = new(ptDcRaw);
2601 Settings->ToDcRaw(TestDcRaw);
2602 uint16_t InputWidth = 0;
2603 uint16_t InputHeight = 0;
2604 ptImageType InputType = CheckImageType(InputFileNameList[0],
2605 &InputWidth, &InputHeight,
2606 TestDcRaw);
2607
2608 if (InputType <= itUndetermined) {
2609 // not a supported image type or error reading the file
2610 QString ErrorMessage = QObject::tr("Cannot decode")
2611 + " '"
2612 + InputFileNameList[0]
2613 + "'" ;
2614 ptMessageBox::warning(MainWindow, "Decode error", ErrorMessage);
2615 Settings->SetValue("InputFileNameList", OldInputFileNameList);
2616 delete TestDcRaw;
2617 return;
2618 }
2619
2620 // Image type is supported: process the image
2621 if (InputType == itRaw) {
2622 Settings->SetValue("IsRAW", 1);
2623 } else {
2624 Settings->SetValue("IsRAW", 0);
2625 }
2626
2627 Settings->SetEnabled("UseThumbnail", Settings->GetInt("IsRAW") == 1);
2628
2629 if (!Settings->useRAWHandling()) {
2630 Settings->SetValue("ExposureNormalization", 0.0);
2631 }
2632
2633 if (Settings->GetInt("HaveImage") == 1) {
2634 // Catch 1:1 pipe size when opening
2635 if (Settings->GetInt("PipeSize") == 0)
2636 Settings->SetValue("PipeSize", 1);
2637 }
2638
2639 // TODO mike: need to delete the processor here?
2640 delete TheDcRaw;
2641 delete TheProcessor;
2642 // Load user settings
2643 if (Settings->GetInt("StartupSettings") == 1 &&
2644 Settings->GetInt("StartupSettingsReset") == 1 &&
2645 Settings->GetInt("HaveImage") == 1) {
2646 Settings->SetValue("HaveImage", 0);
2647 CB_OpenSettingsFile(Settings->GetString("StartupSettingsFile"));
2648 // clean up
2649 QStringList Temp;
2650 Temp << "CropX" << "CropY" << "CropW" << "CropH";
2651 Temp << "RotateW" << "RotateH";
2652 for (int i = 0; i < Temp.size(); i++) Settings->SetValue(Temp.at(i), 0);
2653 }
2654
2655 if (Settings->GetString("Sidecar") != "") {
2656 ReadSidecar(Settings->GetString("Sidecar"));
2657 }
2658
2659 // load settings file automatically
2660 QString SettingsFileName = PathInfo.dir().path() + "/" + PathInfo.completeBaseName() + ".pts";
2661 if (QFile::exists(SettingsFileName)) {
2662 Settings->SetValue("HaveImage", 0);
2663 CB_OpenSettingsFile(SettingsFileName);
2664 }
2665
2666 // clean up possible detail view cache
2667 if (Settings->GetInt("DetailViewActive") == 1) {
2668 Settings->SetValue("DetailViewActive", 0);
2669 Settings->SetValue("DetailViewCropX", 0);
2670 Settings->SetValue("DetailViewCropY", 0);
2671 Settings->SetValue("DetailViewCropW", 0);
2672 Settings->SetValue("DetailViewCropH", 0);
2673 Settings->ToDcRaw(TestDcRaw);
2674 }
2675
2676 TheDcRaw = TestDcRaw;
2677 Settings->SetValue("ImageW", InputWidth);
2678 Settings->SetValue("ImageH", InputHeight);
2679
2680 if (Settings->GetInt("StartupSwitchAR")) {
2681 // portrait image
2682 if ((!Settings->useRAWHandling() &&
2683 Settings->GetInt("ImageW") < Settings->GetInt("ImageH")) ||
2684 TheDcRaw->m_Flip & 4) {
2685 if (Settings->GetInt("AspectRatioW") > Settings->GetInt("AspectRatioH"))
2686 CB_CropOrientationButton();
2687 } else { // landscape
2688 if (Settings->GetInt("AspectRatioW") < Settings->GetInt("AspectRatioH"))
2689 CB_CropOrientationButton();
2690 }
2691 }
2692 SetRatingFromXmp();
2693 if (Settings->GetInt("LoadTags"))
2694 SetTagsFromXmp();
2695
2696 // reflect RAW or bitmap in GUI
2697 MainWindow->UpdateToolBoxes();
2698
2699 TheProcessor = new ptProcessor(ReportProgress);
2700 TheProcessor->m_DcRaw = TheDcRaw;
2701
2702 Settings->SetValue("HaveImage", 1);
2703 short OldRunMode = Settings->GetInt("RunMode");
2704 Settings->SetValue("RunMode", 0);
2705
2706 if (Settings->GetInt("AutomaticPipeSize") && Settings->ToolIsActive("TabResize")) {
2707 CalculatePipeSize(true);
2708 }
2709
2710 Update(ptProcessorPhase_Raw, ptProcessorPhase_Load, 0);
2711
2712 MainWindow->UpdateExifInfo(TheProcessor->m_ExifData);
2713 Settings->SetValue("PerspectiveFocalLength", Settings->GetDouble("FocalLengthIn35mmFilm"));
2714 Settings->SetValue("DefishFocalLength", Settings->GetDouble("FocalLengthIn35mmFilm"));
2715 Settings->SetValue("LfunFocal", Settings->GetDouble("FocalLengthIn35mmFilm"));
2716 double TmpAprt = Settings->GetDouble("ApertureFromExif");
2717 Settings->SetValue("LfunAperture", (TmpAprt == 0.0) ? 8.0 : TmpAprt);
2718 MainWindow->UpdateFilenameInfo(Settings->GetStringList("InputFileNameList"));
2719
2720 QFileInfo finfo = QFileInfo((Settings->GetStringList("InputFileNameList"))[0]);
2721 MainWindow->setWindowTitle(
2722 QString("%1 - %2 - Photivo").arg(finfo.fileName())
2723 .arg(QDir::toNativeSeparators(finfo.absolutePath())) );
2724
2725 Settings->SetValue("RunMode",OldRunMode);
2726
2727 ptClearUndoRedo();
2728 }
2729
2730 //==============================================================================
2731
CB_MenuFileSaveOutput(QString OutputName="")2732 void CB_MenuFileSaveOutput(QString OutputName = "") {
2733 try {
2734 if (Settings->GetInt("HaveImage")==0) return;
2735
2736 QStringList InputFileNameList = Settings->GetStringList("InputFileNameList");
2737 QFileInfo PathInfo(InputFileNameList[0]);
2738 QString SuggestedFileName = PathInfo.dir().path() + "/" + PathInfo.completeBaseName();
2739 if (!Settings->GetString("OutputFileNameSuffix").isEmpty())
2740 SuggestedFileName += Settings->GetString("OutputFileNameSuffix");
2741 else
2742 if (!Settings->GetInt("IsRAW")) SuggestedFileName += "-new";
2743 QString Pattern;
2744
2745 switch(Settings->GetInt("SaveFormat")) {
2746 case ptSaveFormat_JPEG :
2747 SuggestedFileName += ".jpg";
2748 Pattern = QObject::tr("Jpg images (*.jpg *.jpeg);;All files (*.*)");
2749 break;
2750 case ptSaveFormat_PNG :
2751 case ptSaveFormat_PNG16 :
2752 SuggestedFileName += ".png";
2753 Pattern = QObject::tr("PNG images(*.png);;All files (*.*)");
2754 break;
2755 case ptSaveFormat_TIFF8 :
2756 case ptSaveFormat_TIFF16 :
2757 SuggestedFileName += ".tif";
2758 Pattern = QObject::tr("Tiff images (*.tif *.tiff);;All files (*.*)");
2759 break;
2760 default :
2761 SuggestedFileName += ".ppm";
2762 Pattern = QObject::tr("Ppm images (*.ppm);;All files (*.*)");
2763 break;
2764 }
2765
2766 QString FileName = OutputName;
2767 if (FileName == "")
2768 FileName = QFileDialog::getSaveFileName(NULL,
2769 QObject::tr("Save File"),
2770 SuggestedFileName,
2771 Pattern);
2772
2773 if (0 == FileName.size()) return; // Operation cancelled.
2774
2775 Settings->SetValue("OutputFileName",FileName);
2776
2777 short OldRunMode = Settings->GetInt("RunMode");
2778 Settings->SetValue("RunMode",0);
2779
2780 // Processing the job.
2781 delete TheDcRaw;
2782 delete TheProcessor;
2783 TheDcRaw = new(ptDcRaw);
2784 TheProcessor = new ptProcessor(ReportProgress);
2785 Settings->SetValue("JobMode",1); // Disable caching to save memory
2786 TheProcessor->m_DcRaw = TheDcRaw;
2787 Settings->ToDcRaw(TheDcRaw);
2788 // Run the graphical pipe in full format mode to recreate the image.
2789 Settings->SetValue("FullOutput",1);
2790 TheProcessor->Run(ptProcessorPhase_Raw,ptProcessorPhase_Load,1,1);
2791 Settings->SetValue("FullOutput",0);
2792
2793 // Write out (maybe after applying gamma).
2794 Update(ptProcessorPhase_WriteOut);
2795
2796 delete TheDcRaw;
2797 delete TheProcessor;
2798 TheDcRaw = new(ptDcRaw);
2799 TheProcessor = new ptProcessor(ReportProgress);
2800 Settings->SetValue("JobMode",0);
2801 TheProcessor->m_DcRaw = TheDcRaw;
2802 Settings->ToDcRaw(TheDcRaw);
2803 Update(ptProcessorPhase_Raw,ptProcessorPhase_Load,0);
2804 MainWindow->UpdateExifInfo(TheProcessor->m_ExifData);
2805 Settings->SetValue("RunMode",OldRunMode);
2806 ImageSaved = 1;
2807 } catch (std::bad_alloc) {
2808 ptMessageBox::critical(NULL, "Memory error", "No file written, memory error.");
2809 }
2810 } // CB_MenuFileSaveOutput
2811
2812 //==============================================================================
2813
CB_MenuFileExit(const short)2814 void CB_MenuFileExit(const short) {
2815 if (Settings->GetInt("HaveImage")==1 && ImageSaved == 0) {
2816 if (!ptConfirmRequest::saveImage()) {
2817 return;
2818 }
2819 }
2820
2821 // Save current filter config
2822 if (Settings->GetString("StartupSettingsFile").endsWith("Presets/Latest.pts"))
2823 GFilterDM->WritePresetFile(Settings->GetString("UserDirectory") + "/Presets/Latest.pts");
2824
2825 // clean up the input file if we got just a temp file
2826 if (Settings->GetInt("HaveImage")==1 && ImageCleanUp == 1) {
2827 QString OldInputFileName = Settings->GetStringList("InputFileNameList")[0];
2828 ptRemoveFile(OldInputFileName);
2829 ImageCleanUp--;
2830 }
2831
2832 // Delete backup settingsfile
2833 if (Settings->GetInt("WriteBackupSettings") == 1)
2834 QFile::remove(Settings->GetString("UserDirectory")+"/backup.pts");
2835
2836 MainWindow->Form_2_Settings();
2837
2838 printf("Saving settings ...\n");
2839
2840 #ifndef PT_WITHOUT_FILEMGR
2841 // this also writes settings.
2842 delete FileMgrWindow;
2843 #endif
2844
2845 delete BatchWindow;
2846
2847 // Store the position of the splitter and main window
2848 Settings->m_IniSettings->
2849 setValue("MainSplitter",MainWindow->MainSplitter->saveState());
2850 Settings->m_IniSettings->
2851 setValue("ControlSplitter",MainWindow->ControlSplitter->saveState());
2852 Settings->m_IniSettings->setValue("MainWindowPos", MainWindow->pos());
2853 Settings->m_IniSettings->setValue("MainWindowSize", MainWindow->size());
2854 Settings->m_IniSettings->setValue("IsMaximized", MainWindow->windowState() == Qt::WindowMaximized);
2855 Settings->m_IniSettings->setValue("MainWindowScreen", qApp->desktop()->screenNumber(MainWindow));
2856
2857 // Store the version of the settings and files
2858 Settings->m_IniSettings->setValue("SettingsVersion",PhotivoSettingsVersion);
2859
2860 // Explicitly. The destructor of it cares for persistent settings.
2861 delete Settings;
2862 #ifdef Q_OS_WIN
2863 if (!JobMode)
2864 ptEcWin7::DestroyInstance();
2865 #endif
2866
2867 ALLOCATED(10000000);
2868 printf("Exiting Photivo.\n");
2869 QCoreApplication::exit(EXIT_SUCCESS);
2870 }
2871
2872 ////////////////////////////////////////////////////////////////////////////////
2873 //
2874 // Callbacks pertaining to the gimp
2875 //
2876 ////////////////////////////////////////////////////////////////////////////////
2877
CB_ExportToGimpCheck(const QVariant Check)2878 void CB_ExportToGimpCheck(const QVariant Check) {
2879 Settings->SetValue("ExportToGimp",Check);
2880 }
2881
GimpExport(const short UsePipe)2882 void GimpExport(const short UsePipe) {
2883 try {
2884 if (Settings->GetInt("HaveImage")==0) return;
2885
2886 ReportProgress(QObject::tr("Writing tmp image for gimp"));
2887
2888 short OldRunMode = Settings->GetInt("RunMode");
2889
2890 ptImage* ImageForGimp = new ptImage;
2891
2892 if (UsePipe == 1)
2893 ImageForGimp->Set(TheProcessor->m_Image_AfterEyeCandy);
2894 else {
2895 Settings->SetValue("RunMode",0);
2896
2897 // Processing the job.
2898 delete TheDcRaw;
2899 delete TheProcessor;
2900 TheDcRaw = new(ptDcRaw);
2901 TheProcessor = new ptProcessor(ReportProgress);
2902 Settings->SetValue("JobMode",1); // Disable caching to save memory
2903
2904 TheProcessor->m_DcRaw = TheDcRaw;
2905 Settings->ToDcRaw(TheDcRaw);
2906 // Run the graphical pipe in full format mode to recreate the image.
2907 Settings->SetValue("FullOutput",1);
2908 TheProcessor->Run(ptProcessorPhase_Raw,ptProcessorPhase_Load,1,1);
2909 Settings->SetValue("FullOutput",0);
2910
2911 ImageForGimp = TheProcessor->m_Image_AfterEyeCandy; // no cache
2912 }
2913
2914 BeforeGamma(ImageForGimp);
2915
2916 cmsHPROFILE OutputColorProfile = NULL;
2917
2918 ReportProgress(QObject::tr("Converting to output space"));
2919
2920 // Prepare and open an output profile.
2921 OutputColorProfile = cmsOpenProfileFromFile(
2922 Settings->GetString("OutputColorProfile").toLocal8Bit().data(),
2923 "r");
2924 if (!OutputColorProfile) {
2925 ptLogError(ptError_FileOpen,
2926 Settings->GetString("OutputColorProfile").toLocal8Bit().data());
2927 assert(OutputColorProfile);
2928 }
2929
2930 // Color space conversion
2931 ptImage* ReturnValue = ImageForGimp->lcmsRGBToRGB(
2932 OutputColorProfile,
2933 Settings->GetInt("OutputColorProfileIntent"),
2934 Settings->GetInt("CMQuality"));
2935 if (!ReturnValue) {
2936 ptLogError(ptError_lcms,"lcmsRGBToRGB(OutputColorProfile)");
2937 assert(ReturnValue);
2938 }
2939
2940 AfterAll(ImageForGimp);
2941
2942 if (GFilterDM->GetFilterFromName(Fuid::Wiener_Out)->isActive())
2943 EndSharpen(ImageForGimp, OutputColorProfile, Settings->GetInt("OutputColorProfileIntent"));
2944 // Close the output profile.
2945 cmsCloseProfile(OutputColorProfile);
2946
2947 QTemporaryFile ImageFile;
2948 ImageFile.setFileTemplate(QDir::tempPath()+"/XXXXXX.ppm");
2949 bool result = ImageFile.open();
2950 assert (result);
2951 QString ImageFileName = ImageFile.fileName();
2952 ImageFile.setAutoRemove(false);
2953 ImageFile.close();
2954 printf("(%s,%d) '%s'\n",
2955 __FILE__,__LINE__,ImageFileName.toLocal8Bit().data());
2956 ImageForGimp->WriteAsPpm(ImageFileName.toLocal8Bit().data(),16);
2957
2958 ReportProgress(QObject::tr("Writing tmp exif for gimp"));
2959
2960 QTemporaryFile ExifFile;
2961 result = ExifFile.open();
2962 assert (result);
2963 QString ExifFileName = ExifFile.fileName();
2964 ExifFile.setAutoRemove(false);
2965 printf("(%s,%d) '%s'\n",
2966 __FILE__,__LINE__,ExifFileName.toLocal8Bit().data());
2967 QDataStream ExifOut(&ExifFile);
2968 ExifOut.writeRawData((char *) TheProcessor->m_ExifBuffer.data(),
2969 TheProcessor->m_ExifBuffer.size());
2970 ExifFile.close();
2971
2972 ReportProgress(QObject::tr("Writing tmp icc for gimp"));
2973
2974 QTemporaryFile ICCFile;
2975 result = ICCFile.open();
2976 assert (result);
2977 QString ICCFileName = ICCFile.fileName();
2978 ICCFile.setAutoRemove(false);
2979 printf("(%s,%d) '%s'\n",
2980 __FILE__,__LINE__,ICCFileName.toLocal8Bit().data());
2981 QDataStream ICCOut(&ICCFile);
2982 FILE* pFile = fopen ( Settings->GetString("OutputColorProfile").toLocal8Bit().data(), "rb" );
2983 if (pFile==NULL) {
2984 ptLogError(ptError_FileOpen,Settings->GetString("OutputColorProfile").toLocal8Bit().data());
2985 exit(EXIT_FAILURE);
2986 }
2987 fseek (pFile , 0 , SEEK_END);
2988 long lSize = ftell (pFile);
2989 rewind (pFile);
2990
2991 char* pchBuffer = (char*) CALLOC2(lSize,sizeof(uint8_t));
2992 ptMemoryError(pchBuffer,__FILE__,__LINE__);
2993
2994 size_t RV = fread (pchBuffer, 1, lSize, pFile);
2995 if (RV != (size_t) lSize) {
2996 ptLogError(ptError_FileOpen,Settings->GetString("OutputColorProfile").toLocal8Bit().data());
2997 exit(EXIT_FAILURE);
2998 }
2999 ICCOut.writeRawData(pchBuffer, lSize);
3000
3001 FCLOSE (pFile);
3002 FREE2 (pchBuffer);
3003 ICCFile.close();
3004
3005 ReportProgress(QObject::tr("Writing gimp interface file"));
3006
3007 QTemporaryFile GimpFile;
3008 GimpFile.setFileTemplate(QDir::tempPath()+"/XXXXXX.ptg");
3009 result = GimpFile.open();
3010 assert (result);
3011 QString GimpFileName = GimpFile.fileName();
3012 GimpFile.setAutoRemove(false);
3013 printf("(%s,%d) '%s'\n",
3014 __FILE__,__LINE__,GimpFileName.toLocal8Bit().data());
3015 QTextStream Out(&GimpFile);
3016 Out << ImageFileName << "\n";
3017 Out << ExifFileName << "\n";
3018 Out << ICCFileName << "\n";
3019 GimpFile.close();
3020
3021 QString GimpExeCommand = Settings->GetString("GimpExecCommand");
3022 QStringList GimpArguments;
3023 GimpArguments << GimpFileName;
3024 QProcess* GimpProcess = new QProcess();
3025 GimpProcess->startDetached(GimpExeCommand,GimpArguments);
3026
3027 // clean up
3028 if (UsePipe == 1) {
3029 delete ImageForGimp;
3030 } else {
3031 delete TheDcRaw;
3032 delete TheProcessor;
3033 TheDcRaw = new(ptDcRaw);
3034 TheProcessor = new ptProcessor(ReportProgress);
3035 Settings->SetValue("JobMode",0);
3036 TheProcessor->m_DcRaw = TheDcRaw;
3037 Settings->ToDcRaw(TheDcRaw);
3038 Update(ptProcessorPhase_Raw,ptProcessorPhase_Load,0);
3039 MainWindow->UpdateExifInfo(TheProcessor->m_ExifData);
3040 Settings->SetValue("RunMode",OldRunMode);
3041 }
3042 ReportProgress(QObject::tr("Ready"));
3043 } catch (std::bad_alloc) {
3044 ptMessageBox::critical(NULL, "Memory error", "No export, memory error.");
3045 }
3046 }
3047
3048 ////////////////////////////////////////////////////////////////////////////////
3049 //
3050 // Callbacks pertaining to the Zoom function
3051 //
3052 ////////////////////////////////////////////////////////////////////////////////
3053
CB_ZoomInput(const QVariant Value)3054 void CB_ZoomInput(const QVariant Value) {
3055 ViewWindow->ZoomTo(Value.toFloat() / 100.0);
3056 // TODO SR: updatesettings doesnt seem to be necessary
3057 // MainWindow->UpdateSettings(); // To reflect maybe new zoom
3058 }
3059
CB_ZoomFitButton()3060 void CB_ZoomFitButton() {
3061 ViewWindow->ZoomToFit();
3062 //MainWindow->UpdateSettings(); // To reflect maybe new zoom
3063 }
3064
CB_ZoomFullButton()3065 void CB_ZoomFullButton() {
3066 CB_ZoomInput(100);
3067 }
3068
CB_ZoomStep(int direction)3069 void CB_ZoomStep(int direction) {
3070 ViewWindow->ZoomStep(direction);
3071 }
3072
CB_BatchButton()3073 void CB_BatchButton() {
3074 MainWindow->OpenBatchWindow();
3075 }
3076
CB_FileMgrButton()3077 void CB_FileMgrButton() {
3078 #ifndef PT_WITHOUT_FILEMGR
3079 MainWindow->OpenFileMgrWindow();
3080 #endif
3081 }
3082
CB_FullScreenButton(const int State)3083 void CB_FullScreenButton(const int State) {
3084 if (State == 1) {
3085 MainWindow->raise();
3086 MainWindow->showFullScreen();
3087 Settings->SetValue("FullscreenActive", 1);
3088 } else {
3089 MainWindow->showNormal();
3090 Settings->SetValue("FullscreenActive", 0);
3091 }
3092 MainWindow->FullScreenButton->setChecked(State);
3093 }
3094
3095 ////////////////////////////////////////////////////////////////////////////////
3096 //
3097 // Callbacks pertaining to the prev/next image buttons
3098 //
3099 ////////////////////////////////////////////////////////////////////////////////
3100
ptGetFilesInTheImageFolder()3101 QFileInfoList ptGetFilesInTheImageFolder() {
3102 QStringList InputFileNameList = Settings->GetStringList("InputFileNameList");
3103 QFileInfo PathInfo(InputFileNameList[0]);
3104 QString fileName = PathInfo.fileName();
3105 QDir fileDir = PathInfo.dir();
3106 fileDir.setFilter(QDir::Files);
3107 fileDir.setSorting(QDir::Name);
3108
3109 QStringList fileExts;
3110 if (Settings->GetInt("FileMgrShowRAWs")) {
3111 fileExts << FileExtsRaw;
3112 }
3113 if (Settings->GetInt("FileMgrShowBitmaps")) {
3114 fileExts << FileExtsBitmap;
3115 }
3116 return fileDir.entryInfoList(fileExts);
3117 }
3118
ptGetImageFileName()3119 QString ptGetImageFileName() {
3120 QStringList InputFileNameList = Settings->GetStringList("InputFileNameList");
3121 QFileInfo PathInfo(InputFileNameList[0]);
3122 return PathInfo.fileName();
3123 }
3124
CB_PreviousImageButton()3125 void CB_PreviousImageButton() {
3126 if (Settings->GetInt("HaveImage")==0) return;
3127
3128 QString fileName = ptGetImageFileName();
3129 QFileInfoList files = ptGetFilesInTheImageFolder();
3130
3131 for (int i = 1; i < files.count(); i++) {
3132 if (files[i].fileName() == fileName) {
3133 ImageFileToOpen = files[i - 1].absoluteFilePath();
3134 CB_MenuFileOpen(1);
3135 break;
3136 }
3137 }
3138 }
3139
CB_NextImageButton()3140 void CB_NextImageButton() {
3141 if (Settings->GetInt("HaveImage")==0) return;
3142
3143 QString fileName = ptGetImageFileName();
3144 QFileInfoList files = ptGetFilesInTheImageFolder();
3145
3146 for (int i = 0; i < files.count() - 1; i++) {
3147 if (files[i].fileName() == fileName) {
3148 ImageFileToOpen = files[i + 1].absoluteFilePath();
3149 CB_MenuFileOpen(1);
3150 break;
3151 }
3152 }
3153 }
3154
3155 ////////////////////////////////////////////////////////////////////////////////
3156 //
3157 // Callbacks pertaining to the Generic Tab
3158 //
3159 ////////////////////////////////////////////////////////////////////////////////
3160
CB_CameraColorChoice(const QVariant Choice)3161 void CB_CameraColorChoice(const QVariant Choice) {
3162 int PreviousChoice = Settings->GetInt("CameraColor");
3163 Settings->SetValue("CameraColor",Choice);
3164 if (Choice.toInt() == ptCameraColor_Profile) {
3165 if (!Settings->GetString("CameraColorProfile").size()) {
3166 ptMessageBox::warning(MainWindow,
3167 QObject::tr("Please load a profile first"),
3168 QObject::tr("Please load a profile first"));
3169 Settings->SetValue("CameraColor",PreviousChoice);
3170 }
3171 }
3172
3173 if (Settings->GetInt("CameraColor") == ptCameraColor_Embedded) {
3174 // TODO
3175 ptMessageBox::warning(MainWindow,
3176 QObject::tr("Not yet implemented"),
3177 QObject::tr("Not yet implemented. Reverting to Adobe."));
3178 Settings->SetValue("CameraColor",ptCameraColor_Adobe_Matrix);
3179 }
3180
3181 Update(ptProcessorPhase_Raw,ptProcessorPhase_Highlights);
3182 }
3183
CB_CameraColorProfileButton()3184 void CB_CameraColorProfileButton() {
3185 QString ProfileFileName = QFileDialog::getOpenFileName(
3186 NULL,
3187 QObject::tr("Open Profile"),
3188 Settings->GetString("CameraColorProfilesDirectory"),
3189 ProfilePattern);
3190
3191 if (0 == ProfileFileName.size() ) {
3192 // Canceled just return
3193 return;
3194 } else {
3195 QFileInfo PathInfo(ProfileFileName);
3196 Settings->SetValue("CameraColorProfilesDirectory",PathInfo.absolutePath());
3197 Settings->SetValue("CameraColorProfile",PathInfo.absoluteFilePath());
3198 Settings->SetValue("CameraColor",ptCameraColor_Profile);
3199 }
3200
3201 Update(ptProcessorPhase_Raw,ptProcessorPhase_Highlights);
3202 }
3203
CB_CameraColorProfileIntentChoice(const QVariant Choice)3204 void CB_CameraColorProfileIntentChoice(const QVariant Choice) {
3205 Settings->SetValue("CameraColorProfileIntent",Choice);
3206 Update(ptProcessorPhase_Raw,ptProcessorPhase_Highlights);
3207 }
3208
CB_CameraColorGammaChoice(const QVariant Choice)3209 void CB_CameraColorGammaChoice(const QVariant Choice) {
3210 Settings->SetValue("CameraColorGamma",Choice);
3211 Update(ptProcessorPhase_Raw,ptProcessorPhase_Highlights);
3212 }
3213
CB_WorkColorChoice(const QVariant Choice)3214 void CB_WorkColorChoice(const QVariant Choice) {
3215 Settings->SetValue("WorkColor",Choice);
3216 PreCalcTransforms();
3217 Update(ptProcessorPhase_Raw,ptProcessorPhase_Highlights);
3218 }
3219
CB_CMQualityChoice(const QVariant Choice)3220 void CB_CMQualityChoice(const QVariant Choice) {
3221 Settings->SetValue("CMQuality",Choice);
3222 MainWindow->UpdateSettings();
3223 PreCalcTransforms();
3224 Update(ptProcessorPhase_Preview);
3225 }
3226
CB_PreviewColorProfileButton()3227 void CB_PreviewColorProfileButton() {
3228 QString ProfileFileName = QFileDialog::getOpenFileName(
3229 NULL,
3230 QObject::tr("Open Profile"),
3231 Settings->GetString("PreviewColorProfilesDirectory"),
3232 ProfilePattern);
3233
3234 if (0 == ProfileFileName.size() ) {
3235 // Canceled just return
3236 return;
3237 } else {
3238 QFileInfo PathInfo(ProfileFileName);
3239 Settings->SetValue("PreviewColorProfilesDirectory",PathInfo.absolutePath());
3240 Settings->SetValue("PreviewColorProfile",PathInfo.absoluteFilePath());
3241 }
3242
3243 // Reflect in gui.
3244 MainWindow->UpdateSettings();
3245
3246 // Close old profile and open new one.
3247 cmsCloseProfile(PreviewColorProfile);
3248 PreviewColorProfile = cmsOpenProfileFromFile(
3249 Settings->GetString("PreviewColorProfile").toLocal8Bit().data(),
3250 "r");
3251 if (!PreviewColorProfile) {
3252 ptLogError(ptError_FileOpen,
3253 Settings->GetString("PreviewColorProfile").toLocal8Bit().data());
3254 assert(PreviewColorProfile);
3255 }
3256 PreCalcTransforms();
3257 // And update the preview.
3258 Update(ptProcessorPhase_Preview);
3259 }
3260
CB_PreviewColorProfileIntentChoice(const QVariant Choice)3261 void CB_PreviewColorProfileIntentChoice(const QVariant Choice) {
3262 Settings->SetValue("PreviewColorProfileIntent",Choice);
3263 PreCalcTransforms();
3264 Update(ptProcessorPhase_Preview);
3265 }
3266
CB_OutputColorProfileButton()3267 void CB_OutputColorProfileButton() {
3268 QString ProfileFileName = QFileDialog::getOpenFileName(
3269 NULL,
3270 QObject::tr("Open Profile"),
3271 Settings->GetString("OutputColorProfilesDirectory"),
3272 ProfilePattern);
3273
3274 if (0 == ProfileFileName.size() ) {
3275 // Canceled just return
3276 return;
3277 } else {
3278 QFileInfo PathInfo(ProfileFileName);
3279 Settings->SetValue("OutputColorProfilesDirectory",PathInfo.absolutePath());
3280 Settings->SetValue("OutputColorProfile",PathInfo.absoluteFilePath());
3281 }
3282
3283 // Reflect in gui.
3284 if (Settings->GetInt("HistogramMode")==ptHistogramMode_Output) {
3285 if (Settings->GetInt("ExposureIndicator")==1) {
3286 Update(ptProcessorPhase_Preview);
3287 } else {
3288 Update(ptProcessorPhase_OnlyHistogram);
3289 }
3290 }
3291 MainWindow->UpdateSettings();
3292 }
3293
CB_OutputColorProfileResetButton()3294 void CB_OutputColorProfileResetButton() {
3295 Settings->SetValue("OutputColorProfile",
3296 (Settings->GetString("UserDirectory") + "Profiles/Output/sRGB.icc").toLocal8Bit().data());
3297 if (Settings->GetInt("HistogramMode")==ptHistogramMode_Output) {
3298 if (Settings->GetInt("ExposureIndicator")==1) {
3299 Update(ptProcessorPhase_Preview);
3300 } else {
3301 Update(ptProcessorPhase_OnlyHistogram);
3302 }
3303 }
3304 MainWindow->UpdateSettings();
3305 }
3306
CB_OutputColorProfileIntentChoice(const QVariant Choice)3307 void CB_OutputColorProfileIntentChoice(const QVariant Choice) {
3308 Settings->SetValue("OutputColorProfileIntent",Choice);
3309 if (Settings->GetInt("HistogramMode")==ptHistogramMode_Output) {
3310 if (Settings->GetInt("ExposureIndicator")==1) {
3311 Update(ptProcessorPhase_Preview);
3312 } else {
3313 Update(ptProcessorPhase_OnlyHistogram);
3314 }
3315 }
3316 MainWindow->UpdateSettings();
3317 }
3318
CB_StyleChoice(const QVariant Choice)3319 void CB_StyleChoice(const QVariant Choice) {
3320 Settings->SetValue("Style", Choice);
3321 ptTheme::Theme newTheme = (ptTheme::Theme)Choice.toInt();
3322
3323 if (newTheme == ptTheme::thNone) {
3324 Settings->SetValue("CustomCSSFile","");
3325 Theme->setCustomCSS("");
3326 }
3327
3328 Theme->SwitchTo(newTheme, (ptTheme::Highlight)Settings->GetInt("StyleHighLight"));
3329
3330 #ifdef Q_OS_MAC
3331 //dirty hack to make theming work
3332 MainWindow->MainSplitter->setStyleSheet("");
3333 #endif
3334
3335 MainWindow->MainTabBook->setStyle(Theme->style());
3336 MainWindow->ProcessingTabBook->setStyle(Theme->style());
3337 MainWindow->BottomContainer->setStyle(Theme->style());
3338 MainWindow->PipeControlWidget->setStyle(Theme->style());
3339 MainWindow->MainSplitter->setStyle(Theme->style());
3340 MainWindow->ControlSplitter->setStyle(Theme->style());
3341 MainWindow->ViewSplitter->setStyle(Theme->style());
3342 MainWindow->ViewStartPage->setStyle(Theme->style());
3343
3344 TheApplication->setPalette(Theme->palette());
3345
3346 MainWindow->MainTabBook->setStyleSheet(Theme->stylesheet());
3347 MainWindow->BottomContainer->setStyleSheet(Theme->stylesheet());
3348 MainWindow->PipeControlWidget->setStyleSheet(Theme->stylesheet());
3349 MainWindow->StatusWidget->setStyleSheet(Theme->stylesheet());
3350 MainWindow->SearchWidget->setStyleSheet(Theme->stylesheet());
3351 MainWindow->ViewStartPageFrame->setStyleSheet(Theme->stylesheet());
3352 #ifdef Q_OS_MAC
3353 //dirty hack to make theming work
3354 if(Theme->MacStyleFlag){
3355 MainWindow->MainSplitter->setStyleSheet("background-color:"+Theme->MacBackGround+";");
3356 }
3357 #endif
3358 MainWindow->UpdateToolBoxes();
3359 SetBackgroundColor(Settings->GetInt("BackgroundColor"));
3360 CB_SliderWidthInput(Settings->GetInt("SliderWidth"));
3361 #ifndef PT_WITHOUT_FILEMGR
3362 FileMgrWindow->updateTheme();
3363 #endif
3364 BatchWindow->UpdateTheme();
3365 }
3366
CB_StyleHighLightChoice(const QVariant Choice)3367 void CB_StyleHighLightChoice(const QVariant Choice) {
3368 Settings->SetValue("StyleHighLight",Choice);
3369 CB_StyleChoice(Settings->GetInt("Style"));
3370 }
3371
CB_LoadStyleButton()3372 void CB_LoadStyleButton() {
3373 QString FileName;
3374
3375 FileName = QFileDialog::getOpenFileName(NULL,
3376 QObject::tr("Open Image"),
3377 Settings->GetString("UserDirectory"),
3378 QObject::tr("CSS files (*.css *.qss);;All files(*.*)")
3379 );
3380
3381 if (FileName.size() == 0) {
3382 return;
3383 } else {
3384 Settings->SetValue("CustomCSSFile", FileName);
3385 Theme->setCustomCSS(FileName);
3386 CB_StyleChoice(Settings->GetInt("Style"));
3387 }
3388 }
3389
3390
CB_SaveConfirmationCheck(const QVariant Check)3391 void CB_SaveConfirmationCheck(const QVariant Check) {
3392 Settings->SetValue("SaveConfirmation",Check);
3393 MainWindow->AutosaveSettingsWidget->setDisabled(Settings->GetInt("SaveConfirmation"));
3394 }
3395
CB_AutosaveSettingsCheck(const QVariant Check)3396 void CB_AutosaveSettingsCheck(const QVariant Check) {
3397 Settings->SetValue("AutosaveSettings",Check);
3398 }
3399
CB_ResetSettingsConfirmationCheck(const QVariant Check)3400 void CB_ResetSettingsConfirmationCheck(const QVariant Check) {
3401 Settings->SetValue("ResetSettingsConfirmation",Check);
3402 }
3403
CB_FullPipeConfirmationCheck(const QVariant Check)3404 void CB_FullPipeConfirmationCheck(const QVariant Check) {
3405 Settings->SetValue("FullPipeConfirmation",Check);
3406 }
3407
3408
CB_WriteBackupSettingsCheck(const QVariant Check)3409 void CB_WriteBackupSettingsCheck(const QVariant Check) {
3410 Settings->SetValue("WriteBackupSettings",Check);
3411 }
3412
CB_MemoryTestInput(const QVariant Value)3413 void CB_MemoryTestInput(const QVariant Value) {
3414 Settings->SetValue("MemoryTest",0);
3415 if (Value.toInt()>0)
3416 if (ptMessageBox::question(MainWindow,
3417 QObject::tr("Are you sure?"),
3418 QObject::tr("If you don't stop me, I will waste %1 MB of memory.").arg(Value.toInt()),
3419 QMessageBox::Ok,QMessageBox::Cancel)==QMessageBox::Ok){
3420 // allocate orphaned memory for testing
3421 char (*Test) = (char (*)) CALLOC2(Value.toInt()*1024*1024,1);
3422 memset(Test, '\0', Value.toInt()*1024*1024);
3423 ptMessageBox::critical(0,"Feedback","Memory wasted ;-)");
3424 }
3425 }
3426
SetDetailViewRect(const ptStatus,QRect rect)3427 void SetDetailViewRect(const ptStatus, QRect rect) {
3428 DetailViewRect = rect;
3429 }
CB_PipeSizeChoice(const QVariant Choice)3430 void CB_PipeSizeChoice(const QVariant Choice) {
3431
3432 short PreviousPipeSize = Settings->GetInt("PipeSize");
3433
3434 if (Choice == ptPipeSize_Full &&
3435 Settings->GetInt("FullPipeConfirmation")==1 &&
3436 (Settings->GetInt("ImageH") > 2000 ||
3437 Settings->GetInt("ImageW") > 2000)) {
3438 ptMessageBox msgBox;
3439 msgBox.setWindowTitle(QObject::tr("Really switch to 1:1 pipe?"));
3440 msgBox.setText(QObject::tr("Switching to 1:1 pipe will increase memory usage and processing time greatly.\nAre you sure?"));
3441
3442 QPushButton *DetailButton = msgBox.addButton(QObject::tr("Detail view"), QMessageBox::ActionRole);
3443 QPushButton *CancelButton = msgBox.addButton(QMessageBox::Cancel);
3444 msgBox.addButton(QMessageBox::Ok);
3445
3446 msgBox.exec();
3447
3448 if (msgBox.clickedButton() == CancelButton ||
3449 (msgBox.clickedButton() == DetailButton &&
3450 Settings->GetInt("HaveImage")==0)) {
3451 Settings->SetValue("PipeSize", PreviousPipeSize);
3452 return;
3453 } else if (msgBox.clickedButton() == DetailButton &&
3454 Settings->GetInt("HaveImage") == 1) {
3455 short OldZoomMode = 0;
3456 if (Settings->GetInt("DetailViewActive") == 0) {
3457 Settings->SetValue("DetailViewScale", PreviousPipeSize);
3458 if (TheProcessor->m_Image_DetailPreview == NULL)
3459 TheProcessor->m_Image_DetailPreview = new ptImage();
3460 // save a full image if we have several detail views without full view
3461 if (!Settings->useRAWHandling()) {
3462 TheProcessor->m_Image_DetailPreview->SetScaled(TheProcessor->m_Image_AfterDcRaw,
3463 Settings->GetInt("Scaled"));
3464 } else {
3465 TheProcessor->m_Image_DetailPreview->Set(TheProcessor->m_Image_AfterDcRaw);
3466 }
3467 }
3468 // display the cache image and start crop mode
3469
3470 // First : make sure we have Image_AfterDcRaw in the view window.
3471 // Anything else might have undergone geometric transformations that are
3472 // impossible to calculate reverse to a spot in dcraw.
3473 OldZoomMode = Settings->GetInt("ZoomMode");
3474 ViewWindow->ZoomToFit();
3475 UpdatePreviewImage(TheProcessor->m_Image_DetailPreview);
3476
3477 // Allow to be selected in the view window. And deactivate main.
3478 BlockTools(btmBlockAll);
3479 ViewWindow->ShowStatus(QObject::tr("Detail view"));
3480 ViewWindow->StartSimpleRect(SetDetailViewRect);
3481 while (ViewWindow->interaction() == iaSelectRect) {
3482 QApplication::processEvents();
3483 }
3484
3485 // Selection is done at this point. Disallow it further and activate main.
3486 BlockTools(btmUnblock);
3487
3488 if (DetailViewRect.width() >>4 <<4 > 19 &&
3489 DetailViewRect.height() >>4 <<4 > 19) {
3490 Settings->SetValue("DetailViewActive",1);
3491 short CachedPipeSize = Settings->GetInt("DetailViewScale");
3492 Settings->SetValue("DetailViewCropX", ((DetailViewRect.left() >>4) <<4) << CachedPipeSize);
3493 Settings->SetValue("DetailViewCropY", ((DetailViewRect.top() >>4) <<4) << CachedPipeSize);
3494 Settings->SetValue("DetailViewCropW", ((DetailViewRect.width() >>4) <<4) << CachedPipeSize);
3495 Settings->SetValue("DetailViewCropH", ((DetailViewRect.height() >>4) <<4) << CachedPipeSize);
3496 Settings->ToDcRaw(TheDcRaw);
3497 } else {
3498 ptMessageBox::information(NULL,"No crop","Too small. Please try again!");
3499 //ViewWindow->Zoom(OldZoom,0); // TODOSR: re-enable
3500 Settings->SetValue("ZoomMode",OldZoomMode);
3501 Update(ptProcessorPhase_Preview);
3502 if (Settings->GetInt("DetailViewActive")==0) {
3503 delete TheProcessor->m_Image_DetailPreview;
3504 TheProcessor->m_Image_DetailPreview = NULL;
3505 }
3506 Settings->SetValue("PipeSize",PreviousPipeSize);
3507 return;
3508 }
3509
3510 //ViewWindow->Zoom(OldZoom,0); // TODOSR: re-enable
3511 Settings->SetValue("ZoomMode",OldZoomMode);
3512
3513 } else { // 1:1 full mode
3514 // clean up possible detail view cache
3515 if (TheProcessor->m_Image_DetailPreview != NULL) {
3516 delete TheProcessor->m_Image_DetailPreview;
3517 TheProcessor->m_Image_DetailPreview = NULL;
3518 Settings->SetValue("DetailViewActive",0);
3519 Settings->SetValue("DetailViewCropX", 0);
3520 Settings->SetValue("DetailViewCropY", 0);
3521 Settings->SetValue("DetailViewCropW", 0);
3522 Settings->SetValue("DetailViewCropH", 0);
3523 Settings->ToDcRaw(TheDcRaw);
3524 }
3525 }
3526 } else {
3527 // clean up possible detail view cache
3528 if (TheProcessor->m_Image_DetailPreview != NULL) {
3529 delete TheProcessor->m_Image_DetailPreview;
3530 TheProcessor->m_Image_DetailPreview = NULL;
3531 Settings->SetValue("DetailViewActive",0);
3532 Settings->SetValue("DetailViewCropX", 0);
3533 Settings->SetValue("DetailViewCropY", 0);
3534 Settings->SetValue("DetailViewCropW", 0);
3535 Settings->SetValue("DetailViewCropH", 0);
3536 Settings->ToDcRaw(TheDcRaw);
3537 }
3538 }
3539
3540 MainWindow->UpdateToolBoxes();
3541
3542 Settings->SetValue("PipeSize",Choice);
3543 short PipeSize = Settings->GetInt("PipeSize");
3544 short Expansion = PreviousPipeSize-PipeSize;
3545
3546 if (Settings->GetInt("DetailViewActive")==0) {
3547 // Following adaptation is needed for the case spot WB is in place.
3548 if (Expansion > 0) {
3549 Settings->SetValue("VisualSelectionX",
3550 Settings->GetInt("VisualSelectionX")<<Expansion);
3551 Settings->SetValue("VisualSelectionY",
3552 Settings->GetInt("VisualSelectionY")<<Expansion);
3553 Settings->SetValue("VisualSelectionWidth",
3554 Settings->GetInt("VisualSelectionWidth")<<Expansion);
3555 Settings->SetValue("VisualSelectionHeight",
3556 Settings->GetInt("VisualSelectionHeight")<<Expansion);
3557 } else {
3558 Expansion = -Expansion;
3559 Settings->SetValue("VisualSelectionX",
3560 Settings->GetInt("VisualSelectionX")>>Expansion);
3561 Settings->SetValue("VisualSelectionY",
3562 Settings->GetInt("VisualSelectionY")>>Expansion);
3563 Settings->SetValue("VisualSelectionWidth",
3564 Settings->GetInt("VisualSelectionWidth")>>Expansion);
3565 Settings->SetValue("VisualSelectionHeight",
3566 Settings->GetInt("VisualSelectionHeight")>>Expansion);
3567 }
3568 }
3569
3570 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
3571 MainWindow->UpdateExifInfo(TheProcessor->m_ExifData);
3572
3573 ALLOCATED(10000000);
3574 }
3575
3576
CB_RunModeCheck(const QVariant Check)3577 void CB_RunModeCheck(const QVariant Check) {
3578 Settings->SetValue("RunMode",Check);
3579 MainWindow->UpdateSettings();
3580 if (Settings->GetInt("RunMode")==0) {
3581 Update(ptProcessorPhase_Output);
3582 }
3583 }
3584
CB_PreviewModeButton(const QVariant State)3585 void CB_PreviewModeButton(const QVariant State) {
3586 Settings->SetValue("PreviewTabMode",State);
3587 if (Settings->GetInt("PreviewTabMode")) {
3588 Settings->SetValue("PreviewMode",ptPreviewMode_Tab);
3589 MainWindow->PreviewModeButton->setChecked(1);
3590 } else {
3591 Settings->SetValue("PreviewMode",ptPreviewMode_End);
3592 MainWindow->PreviewModeButton->setChecked(0);
3593 }
3594 Update(ptProcessorPhase_Preview);
3595 }
3596
CB_RunButton()3597 void CB_RunButton() {
3598 short OldRunMode = Settings->GetInt("RunMode");
3599 Settings->SetValue("RunMode",0);
3600 Update(ptProcessorPhase_Output);
3601 Settings->SetValue("RunMode",OldRunMode);
3602 MainWindow->UpdateSettings();
3603 }
3604
ResetButtonHandler(const short mode)3605 void ResetButtonHandler(const short mode) {
3606 int DoOpen = 1;
3607 if (mode == ptResetMode_Full) { // full reset
3608 if ( Settings->GetInt("ResetSettingsConfirmation")==1 ) {
3609 ptMessageBox msgBox;
3610 msgBox.setIcon(QMessageBox::Question);
3611 msgBox.setWindowTitle(QObject::tr("Reset?"));
3612 msgBox.setText(QObject::tr("Reset to neutral values?\n"));
3613 msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
3614 msgBox.setDefaultButton(QMessageBox::Ok);
3615 if ( msgBox.exec()==QMessageBox::Cancel ) {
3616 DoOpen = 0;
3617 }
3618 }
3619 if ( DoOpen==1 ) {
3620 CB_OpenSettingsFile(Settings->GetString("PresetDirectory") + "/Neutral_absolute.pts");
3621 }
3622 } else if (mode == ptResetMode_User) { // reset to startup settings
3623 if ( Settings->GetInt("ResetSettingsConfirmation")==1 ) {
3624 ptMessageBox msgBox;
3625 msgBox.setIcon(QMessageBox::Question);
3626 msgBox.setWindowTitle(QObject::tr("Reset?"));
3627 msgBox.setText(QObject::tr("Reset to start up settings?\n"));
3628 msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
3629 msgBox.setDefaultButton(QMessageBox::Ok);
3630 if ( msgBox.exec()==QMessageBox::Cancel ) {
3631 DoOpen = 0;
3632 }
3633 }
3634 if ( DoOpen==1 ) {
3635 CB_OpenSettingsFile(Settings->GetString("StartupSettingsFile"));
3636 }
3637 } else if (mode == ptResetMode_OpenPreset) { // open preset file
3638 CB_OpenPresetFileButton();
3639 } else { // open settings file
3640 CB_OpenSettingsFileButton();
3641 }
3642 }
3643
CB_ResetButton()3644 void CB_ResetButton() {
3645 ResetButtonHandler(Settings->GetInt("ResetButtonMode"));
3646 }
3647
CB_SpecialPreviewChoice(const QVariant Choice)3648 void CB_SpecialPreviewChoice(const QVariant Choice) {
3649 Settings->SetValue("SpecialPreview",Choice);
3650 Update(ptProcessorPhase_Preview);
3651 }
3652
CB_GimpExecCommandButton()3653 void CB_GimpExecCommandButton() {
3654
3655 QString GimpExecCommandString = QFileDialog::getOpenFileName(NULL,
3656 QObject::tr("Get Gimp command"),
3657 Settings->GetString("UserDirectory"),
3658 "All files (*.*)");
3659
3660 if (0 == GimpExecCommandString.size() ) {
3661 // Canceled just return
3662 return;
3663 } else {
3664 QFileInfo PathInfo(GimpExecCommandString);
3665 Settings->SetValue("GimpExecCommand",PathInfo.absoluteFilePath());
3666 }
3667
3668 // Reflect in gui.
3669 MainWindow->UpdateSettings();
3670 }
3671
CB_RememberSettingLevelChoice(const QVariant Choice)3672 void CB_RememberSettingLevelChoice(const QVariant Choice) {
3673 Settings->SetValue("RememberSettingLevel",Choice);
3674 MainWindow->UpdateSettings();
3675 }
3676
CB_StartupSettingsCheck(const QVariant State)3677 void CB_StartupSettingsCheck(const QVariant State) {
3678 Settings->SetValue("StartupSettings",State);
3679 }
3680
CB_StartupSettingsResetCheck(const QVariant State)3681 void CB_StartupSettingsResetCheck(const QVariant State) {
3682 Settings->SetValue("StartupSettingsReset",State);
3683 }
3684
CB_StartupSettingsButton()3685 void CB_StartupSettingsButton() {
3686 QString StartupSettingsString = QFileDialog::getOpenFileName(NULL,
3687 QObject::tr("Get preset file"),
3688 Settings->GetString("PresetDirectory"),
3689 SettingsFilePattern);
3690
3691 if (0 == StartupSettingsString.size() ) {
3692 // Canceled just return
3693 return;
3694 } else {
3695 QFileInfo PathInfo(StartupSettingsString);
3696 Settings->SetValue("PresetDirectory",PathInfo.absolutePath());
3697 Settings->SetValue("StartupSettingsFile",PathInfo.absoluteFilePath());
3698 }
3699
3700 // Reflect in gui.
3701 MainWindow->UpdateSettings();
3702 }
3703
CB_StartupUIModeChoice(const QVariant Choice)3704 void CB_StartupUIModeChoice(const QVariant Choice) {
3705 Settings->SetValue("StartupUIMode",Choice);
3706 }
3707
CB_StartupPipeSizeChoice(const QVariant Choice)3708 void CB_StartupPipeSizeChoice(const QVariant Choice) {
3709 Settings->SetValue("StartupPipeSize", Choice);
3710 }
3711
CB_CropInitialZoomChoice(const QVariant Choice)3712 void CB_CropInitialZoomChoice(const QVariant Choice) {
3713 Settings->SetValue("CropInitialZoom",Choice);
3714 }
3715
CB_InputsAddPowerLawCheck(const QVariant State)3716 void CB_InputsAddPowerLawCheck(const QVariant State) {
3717 Settings->SetValue("InputsAddPowerLaw",State);
3718 if (Settings->GetInt("InputsAddPowerLaw")) {
3719 Settings->SetValue("InputPowerFactor",2.2);
3720 } else {
3721 Settings->SetValue("InputPowerFactor",1.0);
3722 }
3723 Update(ptProcessorPhase_RGB);
3724 }
3725
CB_ToolBoxModeCheck(const QVariant State)3726 void CB_ToolBoxModeCheck(const QVariant State) {
3727 Settings->SetValue("ToolBoxMode",State);
3728 MainWindow->OnToolBoxesEnabledTriggered(Settings->GetInt("ToolBoxMode"));
3729 }
3730
CB_TabStatusIndicatorInput(const QVariant Value)3731 void CB_TabStatusIndicatorInput(const QVariant Value) {
3732 Settings->SetValue("TabStatusIndicator",Value);
3733 MainWindow->UpdateSettings();
3734 }
3735
CB_PreviewTabModeCheck(const QVariant State)3736 void CB_PreviewTabModeCheck(const QVariant State) {
3737 Settings->SetValue("PreviewTabMode",State);
3738 if (Settings->GetInt("PreviewTabMode")) {
3739 Settings->SetValue("PreviewMode",ptPreviewMode_Tab);
3740 } else {
3741 Settings->SetValue("PreviewMode",ptPreviewMode_End);
3742 }
3743 Update(ptProcessorPhase_Preview);
3744 }
3745
CB_BackgroundColorCheck(const QVariant State)3746 void CB_BackgroundColorCheck(const QVariant State) {
3747 Settings->SetValue("BackgroundColor",State);
3748 SetBackgroundColor(Settings->GetInt("BackgroundColor"));
3749 }
3750
CB_BackgroundColorButton()3751 void CB_BackgroundColorButton() {
3752 QPixmap Pix(80, 14);
3753 QColor Color;
3754 Color.setRed(Settings->GetInt("BackgroundRed"));
3755 Color.setGreen(Settings->GetInt("BackgroundGreen"));
3756 Color.setBlue(Settings->GetInt("BackgroundBlue"));
3757 QColorDialog Dialog(Color,NULL);
3758 Dialog.setStyle(Theme->systemStyle());
3759 Dialog.setPalette(Theme->systemPalette());
3760 Dialog.exec();
3761 QColor TestColor = Dialog.selectedColor();
3762 if (TestColor.isValid()) {
3763 Color = TestColor;
3764 Settings->SetValue("BackgroundRed",Color.red());
3765 Settings->SetValue("BackgroundGreen",Color.green());
3766 Settings->SetValue("BackgroundBlue",Color.blue());
3767 Pix.fill(Color);
3768 MainWindow->BackgroundColorButton->setIcon(Pix);
3769 if (Settings->GetInt("BackgroundColor")){
3770 SetBackgroundColor(1);
3771 }
3772 }
3773 }
3774
SetBackgroundColor(int SetIt)3775 void SetBackgroundColor(int SetIt) {
3776 if (SetIt) {
3777 QPalette BGPal;
3778 BGPal.setColor(QPalette::Background, QColor(Settings->GetInt("BackgroundRed"),
3779 Settings->GetInt("BackgroundGreen"),
3780 Settings->GetInt("BackgroundBlue")));
3781 ViewWindow->setPalette(BGPal);
3782 MainWindow->ViewStartPage->setPalette(BGPal);
3783 } else {
3784 ViewWindow->setPalette(Theme->palette());
3785 MainWindow->ViewStartPage->setPalette(Theme->palette());
3786 }
3787 }
3788
CB_SliderWidthInput(const QVariant Value)3789 void CB_SliderWidthInput(const QVariant Value) {
3790 Settings->SetValue("SliderWidth",Value);
3791 if (Settings->GetInt("SliderWidth") == 0)
3792 // maximum slider width is equal to the toolbar width
3793 MainWindow->setStyleSheet("ptSlider { max-width: " + QString("%1").arg(10000) + "px; }");
3794 else
3795 // maximum slider width is equal to "SliderWidth"
3796 MainWindow->setStyleSheet("ptSlider { max-width: " + QString("%1").arg(Settings->GetInt("SliderWidth")) + "px; }");
3797 }
3798
CB_SaveButtonModeChoice(const QVariant Choice)3799 void CB_SaveButtonModeChoice(const QVariant Choice) {
3800 Settings->SetValue("SaveButtonMode",Choice);
3801 SaveButtonToolTip(Settings->GetInt("SaveButtonMode"));
3802 }
3803
CB_ResetButtonModeChoice(const QVariant Value)3804 void CB_ResetButtonModeChoice(const QVariant Value) {
3805 Settings->SetValue("ResetButtonMode",Value);
3806 }
3807
CB_SearchBarEnableCheck(const QVariant State)3808 void CB_SearchBarEnableCheck(const QVariant State) {
3809 Settings->SetValue("SearchBarEnable",State);
3810 MainWindow->SearchWidget->setVisible(Settings->GetInt("SearchBarEnable"));
3811 }
3812
SaveButtonToolTip(const short mode)3813 void SaveButtonToolTip(const short mode) {
3814 if (mode==ptOutputMode_Full) {
3815 MainWindow->WritePipeButton->setToolTip(QObject::tr("Save full size image"));
3816 } else if (mode==ptOutputMode_Pipe) {
3817 MainWindow->WritePipeButton->setToolTip(QObject::tr("Save current pipe"));
3818 } else if (mode==ptOutputMode_Jobfile) {
3819 MainWindow->WritePipeButton->setToolTip(QObject::tr("Save job file"));
3820 } else if (mode==ptOutputMode_Settingsfile) {
3821 MainWindow->WritePipeButton->setToolTip(QObject::tr("Save settings file"));
3822 } else if (mode==ptOutputMode_Batch) {
3823 MainWindow->WritePipeButton->setToolTip(QObject::tr("Save and send to batch manager"));
3824 }
3825 }
3826
3827 ////////////////////////////////////////////////////////////////////////////////
3828 //
3829 // Callbacks pertaining to the Camera Tab
3830 // Partim Generic Corrections.
3831 //
3832 ////////////////////////////////////////////////////////////////////////////////
3833
CB_OpenFileButton()3834 void CB_OpenFileButton() {
3835 CB_MenuFileOpen(0);
3836 }
3837
CB_OpenSettingsFile(QString SettingsFileName)3838 void CB_OpenSettingsFile(QString SettingsFileName) {
3839 if (0 == SettingsFileName.size()) return;
3840 short NextPhase = 1;
3841 short ReturnValue = GFilterDM->ReadPresetFile(SettingsFileName, NextPhase);
3842 if (ReturnValue) {
3843 ptMessageBox::critical(0,"Error","No valid settings file!\n" + SettingsFileName);
3844 return;
3845 }
3846 if (NextPhase == 1) {
3847 if (Settings->GetInt("HaveImage")==1) {
3848 CalculateMultipliersFromTemperature();
3849 NormalizeMultipliers(Settings->GetInt("MultiplierEnhance"));
3850 }
3851 if (Settings->GetInt("AutomaticPipeSize") && Settings->ToolIsActive("TabResize")) {
3852 if (!CalculatePipeSize())
3853 Update(ptProcessorPhase_Raw,ptProcessorPhase_Load);
3854 } else {
3855 Update(ptProcessorPhase_Raw,ptProcessorPhase_Load);
3856 }
3857 } else {
3858 //TODO: check Nextphase against automatic pipesize
3859 Update(NextPhase);
3860 }
3861 SetRatingFromXmp();
3862 if (Settings->GetInt("LoadTags"))
3863 SetTagsFromXmp();
3864 }
3865
CB_OpenSettingsFileButton()3866 void CB_OpenSettingsFileButton() {
3867 if (!ptConfirmRequest::loadConfig(lcmGeneralCfg)) {
3868 return;
3869 }
3870
3871 ptAddUndo();
3872
3873 QString SettingsFilePattern =
3874 QObject::tr("All supported files (*.pts *ptj);;Settings files (*.pts);;Job files (*.ptj);;All files (*.*)");
3875 QString SettingsFileName =
3876 QFileDialog::getOpenFileName(NULL,
3877 QObject::tr("Open setting file"),
3878 Settings->GetString("RawsDirectory"),
3879 SettingsFilePattern);
3880 if (0 == SettingsFileName.size()) return;
3881 CB_OpenSettingsFile(SettingsFileName);
3882 }
3883
CB_OpenPresetFileButton()3884 void CB_OpenPresetFileButton() {
3885 ptAddUndo();
3886
3887 QString SettingsFilePattern =
3888 QObject::tr("All supported files (*.pts *ptj);;Settings files (*.pts);;Job files (*.ptj);;All files (*.*)");
3889 QString SettingsFileName =
3890 QFileDialog::getOpenFileName(NULL,
3891 QObject::tr("Open preset"),
3892 Settings->GetString("PresetDirectory"),
3893 SettingsFilePattern);
3894 if (0 == SettingsFileName.size()) return;
3895 CB_OpenSettingsFile(SettingsFileName);
3896 }
3897
CB_UseThumbnailCheck(const QVariant Check)3898 void CB_UseThumbnailCheck(const QVariant Check) {
3899 Settings->SetValue("UseThumbnail", Check);
3900
3901 if (Settings->GetInt("IsRAW")) {
3902 Update(ptProcessorPhase_Raw, ptProcessorPhase_Load);
3903 }
3904 }
3905
3906
CB_BadPixelsChoice(const QVariant Choice)3907 void CB_BadPixelsChoice(const QVariant Choice) {
3908 Settings->SetValue("HaveBadPixels", Choice);
3909 short Cancelled = 0;
3910 if (Choice.toInt() == 1) {
3911 // Request to load one.
3912 QString BadPixelsFileName =
3913 QFileDialog::getOpenFileName(NULL,
3914 QObject::tr("Open 'bad pixels' file"),
3915 NULL);
3916 if (0 == Settings->GetString("BadPixelsFileName").size() ) {
3917 // A cancel we'll interprate as no bad pixel
3918 Settings->SetValue("HaveBadPixels",0);
3919 Cancelled = 1;
3920 } else {
3921 Settings->SetValue("HaveBadPixels",2);
3922 Settings->SetValue("BadPixelsFileName",BadPixelsFileName);
3923 }
3924 }
3925 if (!Cancelled) {
3926 Update(ptProcessorPhase_Raw,ptProcessorPhase_Load);
3927 MainWindow->UpdateExifInfo(TheProcessor->m_ExifData);
3928 }
3929 }
3930
CB_DarkFrameChoice(const QVariant Choice)3931 void CB_DarkFrameChoice(const QVariant Choice) {
3932 Settings->SetValue("HaveDarkFrame",Choice);
3933 short Cancelled = 0;
3934 if (Choice.toInt() == 1) {
3935 // Request to load one.
3936 QString DarkFrameFileName =
3937 QFileDialog::getOpenFileName(NULL,
3938 QObject::tr("Open 'dark frame' file"),
3939 NULL);
3940 if (0 == Settings->GetString("DarkFrameFileName").size() ) {
3941 // A cancel we'll interprate as no bad pixel
3942 Settings->SetValue("HaveDarkFrame",0);
3943 Cancelled = 1;
3944 } else {
3945 Settings->SetValue("HaveDarkFrame",2);
3946 Settings->SetValue("DarkFrameFileName",DarkFrameFileName);
3947 }
3948 }
3949 if (!Cancelled) {
3950 Update(ptProcessorPhase_Raw,ptProcessorPhase_Load);
3951 MainWindow->UpdateExifInfo(TheProcessor->m_ExifData);
3952 }
3953 }
3954
3955 ////////////////////////////////////////////////////////////////////////////////
3956 //
3957 // Callbacks pertaining to the Camera Tab
3958 // Partim White Balance.
3959 //
3960 ////////////////////////////////////////////////////////////////////////////////
3961 void SelectSpotWBDone(const ptStatus ExitStatus, const QRect SelectionRect);
3962
CB_WhiteBalanceChoice(const QVariant Choice)3963 void CB_WhiteBalanceChoice(const QVariant Choice) {
3964 Settings->SetValue("WhiteBalance",Choice);
3965 if (Settings->GetInt("HaveImage") == 0 || (!Settings->useRAWHandling())) return;
3966
3967 switch (Choice.toInt()) {
3968 case ptWhiteBalance_Camera :
3969 case ptWhiteBalance_Auto :
3970 case ptWhiteBalance_Manual :
3971 // In fact all of above just translates to settings into
3972 // DcRaw handled via GuiSettingsToDcRaw. Nothing more to do.
3973 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
3974 break;
3975
3976 case ptWhiteBalance_Spot: {
3977 // First : make sure we have Image_AfterDcRaw in the view window.
3978 // Anything else might have undergone geometric transformations that are
3979 // impossible to calculate reverse to a spot in dcraw.
3980 ViewWindow->SaveZoom();
3981 ViewWindow->ZoomToFit();
3982 UpdatePreviewImage(TheProcessor->m_Image_AfterDcRaw);
3983
3984 // Allow to be selected in the view window. And deactivate main.
3985 BlockTools(btmBlockAll);
3986 ViewWindow->ShowStatus(QObject::tr("Spot WB"));
3987 ReportProgress(QObject::tr("Spot WB"));
3988 ViewWindow->StartSimpleRect(SelectSpotWBDone);
3989 ViewWindow->setFocus();
3990 break;
3991 }
3992
3993 default :
3994 // Here we have presets selected from ptWhiteBalances.
3995 // GuiSettings->m_WhiteBalance should point
3996 // to the right index into the array.
3997 Settings->SetValue("RMultiplier",
3998 ptWhiteBalances[Choice.toInt()].m_Multipliers[0]);
3999 Settings->SetValue("GMultiplier",
4000 ptWhiteBalances[Choice.toInt()].m_Multipliers[1]);
4001 Settings->SetValue("BMultiplier",
4002 ptWhiteBalances[Choice.toInt()].m_Multipliers[2]);
4003 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4004 }
4005 }
4006
SelectSpotWBDone(const ptStatus ExitStatus,const QRect SelectionRect)4007 void SelectSpotWBDone(const ptStatus ExitStatus, const QRect SelectionRect) {
4008 // Selection is done at this point. Disallow it further and activate main.
4009 BlockTools(btmUnblock);
4010
4011 if (ExitStatus == stSuccess) {
4012 Settings->SetValue("VisualSelectionX", SelectionRect.left());
4013 Settings->SetValue("VisualSelectionY", SelectionRect.top());
4014 Settings->SetValue("VisualSelectionWidth", SelectionRect.width());
4015 Settings->SetValue("VisualSelectionHeight", SelectionRect.height());
4016
4017 TRACEKEYVALS("Selection X","%d",
4018 Settings->GetInt("VisualSelectionX"));
4019 TRACEKEYVALS("Selection Y","%d",
4020 Settings->GetInt("VisualSelectionY"));
4021 TRACEKEYVALS("Selection W","%d",
4022 Settings->GetInt("VisualSelectionWidth"));
4023 TRACEKEYVALS("Selection H","%d",
4024 Settings->GetInt("VisualSelectionHeight"));
4025 }
4026
4027 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4028 ViewWindow->RestoreZoom();
4029 }
4030
CB_SpotWBButton()4031 void CB_SpotWBButton() {
4032 CB_WhiteBalanceChoice(ptWhiteBalance_Spot);
4033 }
4034
CB_ColorTemperatureInput(const QVariant Value)4035 void CB_ColorTemperatureInput(const QVariant Value) {
4036 Settings->SetValue("ColorTemperature",Value);
4037 Settings->SetValue("WhiteBalance",ptWhiteBalance_Manual);
4038 if (!TheDcRaw) return;
4039 CalculateMultipliersFromTemperature();
4040 NormalizeMultipliers(Settings->GetInt("MultiplierEnhance"));
4041 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4042 }
4043
CB_GreenIntensityInput(const QVariant Value)4044 void CB_GreenIntensityInput(const QVariant Value) {
4045 Settings->SetValue("GreenIntensity",Value);
4046 Settings->SetValue("WhiteBalance",ptWhiteBalance_Manual);
4047 if (!TheDcRaw) return;
4048 CalculateMultipliersFromTemperature();
4049 NormalizeMultipliers(Settings->GetInt("MultiplierEnhance"));
4050 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4051 }
4052
CB_MultiplierEnhanceCheck(const QVariant State)4053 void CB_MultiplierEnhanceCheck(const QVariant State) {
4054 Settings->SetValue("MultiplierEnhance",State);
4055 if (!TheDcRaw) return;
4056 TheDcRaw->m_UserSetting_MaxMultiplier = Settings->GetInt("MultiplierEnhance");
4057 NormalizeMultipliers(Settings->GetInt("MultiplierEnhance"));
4058 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4059 }
4060
CB_RMultiplierInput(const QVariant Value)4061 void CB_RMultiplierInput(const QVariant Value) {
4062 Settings->SetValue("RMultiplier",Value);
4063 Settings->SetValue("WhiteBalance",ptWhiteBalance_Manual);
4064 NormalizeMultipliers(Settings->GetInt("MultiplierEnhance"));
4065 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4066 }
4067
CB_GMultiplierInput(const QVariant Value)4068 void CB_GMultiplierInput(const QVariant Value) {
4069 Settings->SetValue("GMultiplier",Value);
4070 Settings->SetValue("WhiteBalance",ptWhiteBalance_Manual);
4071 NormalizeMultipliers(Settings->GetInt("MultiplierEnhance"));
4072 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4073 }
4074
CB_BMultiplierInput(const QVariant Value)4075 void CB_BMultiplierInput(const QVariant Value) {
4076 Settings->SetValue("BMultiplier",Value);
4077 Settings->SetValue("WhiteBalance",ptWhiteBalance_Manual);
4078 NormalizeMultipliers(Settings->GetInt("MultiplierEnhance"));
4079 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4080 }
4081
CB_ManualBlackPointCheck(const QVariant State)4082 void CB_ManualBlackPointCheck(const QVariant State) {
4083 short OldState = Settings->GetInt("ManualBlackPoint");
4084 Settings->SetValue("ManualBlackPoint",State);
4085 if (OldState) {
4086 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4087 } else {
4088 MainWindow->UpdateSettings();
4089 }
4090 }
4091
CB_BlackPointInput(const QVariant Value)4092 void CB_BlackPointInput(const QVariant Value) {
4093 Settings->SetValue("BlackPoint",Value);
4094 if (Settings->GetInt("ManualBlackPoint")) {
4095 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4096 }
4097 }
4098
CB_ManualWhitePointCheck(const QVariant State)4099 void CB_ManualWhitePointCheck(const QVariant State) {
4100 short OldState = Settings->GetInt("ManualWhitePoint");
4101 Settings->SetValue("ManualWhitePoint",State);
4102 if (OldState) {
4103 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4104 } else {
4105 MainWindow->UpdateSettings();
4106 }
4107 }
4108
CB_WhitePointInput(const QVariant Value)4109 void CB_WhitePointInput(const QVariant Value) {
4110 Settings->SetValue("WhitePoint",Value);
4111 if (Settings->GetInt("ManualWhitePoint")) {
4112 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4113 }
4114 }
4115
4116 ////////////////////////////////////////////////////////////////////////////////
4117 //
4118 // Callbacks pertaining to the Camera Tab
4119 // Partim Demosaicing.
4120 //
4121 ////////////////////////////////////////////////////////////////////////////////
4122
CB_CaCorrectChoice(const QVariant Choice)4123 void CB_CaCorrectChoice(const QVariant Choice) {
4124 Settings->SetValue("CaCorrect",Choice);
4125 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4126 }
4127
CB_CaRedInput(const QVariant Value)4128 void CB_CaRedInput(const QVariant Value) {
4129 Settings->SetValue("CaRed",Value);
4130 if (Settings->GetInt("CaCorrect")==ptCACorrect_Manual)
4131 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4132 }
4133
CB_CaBlueInput(const QVariant Value)4134 void CB_CaBlueInput(const QVariant Value) {
4135 Settings->SetValue("CaBlue",Value);
4136 if (Settings->GetInt("CaCorrect")==ptCACorrect_Manual)
4137 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4138 }
4139
CB_GreenEquilInput(const QVariant Value)4140 void CB_GreenEquilInput(const QVariant Value) {
4141 Settings->SetValue("GreenEquil",Value);
4142 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4143 }
4144
CB_CfaLineDenoiseInput(const QVariant Value)4145 void CB_CfaLineDenoiseInput(const QVariant Value) {
4146 Settings->SetValue("CfaLineDenoise",Value);
4147 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4148 }
4149
CB_AdjustMaximumThresholdInput(const QVariant Value)4150 void CB_AdjustMaximumThresholdInput(const QVariant Value) {
4151 Settings->SetValue("AdjustMaximumThreshold",Value);
4152 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4153 }
4154
CB_RawDenoiseThresholdInput(const QVariant Value)4155 void CB_RawDenoiseThresholdInput(const QVariant Value) {
4156 Settings->SetValue("RawDenoiseThreshold",Value);
4157 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4158 }
4159
CB_HotpixelReductionInput(const QVariant Value)4160 void CB_HotpixelReductionInput(const QVariant Value) {
4161 Settings->SetValue("HotpixelReduction",Value);
4162 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4163 }
4164
CB_BayerDenoiseChoice(const QVariant Choice)4165 void CB_BayerDenoiseChoice(const QVariant Choice) {
4166 Settings->SetValue("BayerDenoise",Choice);
4167 if (!Settings->GetInt("PipeSize")) {
4168 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4169 }
4170 }
4171
CB_InterpolationChoice(const QVariant Choice)4172 void CB_InterpolationChoice(const QVariant Choice) {
4173 Settings->SetValue("Interpolation",Choice);
4174 MainWindow->UpdateSettings();
4175 if (!Settings->GetInt("PipeSize")) {
4176 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4177 }
4178 }
4179
CB_InterpolationPassesInput(const QVariant Value)4180 void CB_InterpolationPassesInput(const QVariant Value) {
4181 Settings->SetValue("InterpolationPasses",Value);
4182 if (!Settings->GetInt("PipeSize") &&
4183 (Settings->GetInt("Interpolation")==ptInterpolation_DCB ||
4184 Settings->GetInt("Interpolation")==ptInterpolation_DCBSoft ||
4185 Settings->GetInt("Interpolation")==ptInterpolation_DCBSharp)) {
4186 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4187 }
4188 }
4189
CB_MedianPassesInput(const QVariant Value)4190 void CB_MedianPassesInput(const QVariant Value) {
4191 Settings->SetValue("MedianPasses",Value);
4192 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4193 }
4194
CB_ESMedianPassesInput(const QVariant Value)4195 void CB_ESMedianPassesInput(const QVariant Value) {
4196 Settings->SetValue("ESMedianPasses",Value);
4197 if (!Settings->GetInt("PipeSize")) {
4198 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4199 }
4200 }
4201
CB_EeciRefineCheck(const QVariant State)4202 void CB_EeciRefineCheck(const QVariant State) {
4203 Settings->SetValue("EeciRefine",State);
4204 Update(ptProcessorPhase_Raw,ptProcessorPhase_Demosaic);
4205 }
4206
4207 ////////////////////////////////////////////////////////////////////////////////
4208 //
4209 // Callbacks pertaining to the Camera Tab
4210 // Partim Highlight.
4211 //
4212 ////////////////////////////////////////////////////////////////////////////////
4213
CB_ClipModeChoice(const QVariant Choice)4214 void CB_ClipModeChoice(const QVariant Choice) {
4215 Settings->SetValue("ClipMode",Choice);
4216 Update(ptProcessorPhase_Raw,ptProcessorPhase_Highlights);
4217 }
4218
CB_ClipParameterInput(const QVariant Value)4219 void CB_ClipParameterInput(const QVariant Value) {
4220 Settings->SetValue("ClipParameter",Value);
4221 Update(ptProcessorPhase_Raw,ptProcessorPhase_Highlights);
4222 }
4223
4224
4225 ////////////////////////////////////////////////////////////////////////////////
4226 //
4227 // Callbacks pertaining to Lensfun (Geometry tab)
4228 //
4229 ////////////////////////////////////////////////////////////////////////////////
4230
4231 // General tab
4232
CB_LfunFocalInput(const QVariant Value)4233 void CB_LfunFocalInput(const QVariant Value) {
4234 Settings->SetValue("LfunFocal", Value);
4235 Update(ptProcessorPhase_Geometry);
4236 }
4237
CB_LfunApertureInput(const QVariant Value)4238 void CB_LfunApertureInput(const QVariant Value) {
4239 Settings->SetValue("LfunAperture", Value);
4240 Update(ptProcessorPhase_Geometry);
4241 }
4242
CB_LfunDistanceInput(const QVariant Value)4243 void CB_LfunDistanceInput(const QVariant Value) {
4244 Settings->SetValue("LfunDistance", Value);
4245 Update(ptProcessorPhase_Geometry);
4246 }
4247
CB_LfunScaleInput(const QVariant Value)4248 void CB_LfunScaleInput(const QVariant Value) {
4249 Settings->SetValue("LfunScale", Value);
4250 Update(ptProcessorPhase_Geometry);
4251 }
4252
CB_LfunAutoScaleCheck(const QVariant State)4253 void CB_LfunAutoScaleCheck(const QVariant State) {
4254 Settings->SetValue("LfunAutoScale",State);
4255 MainWindow->LfunScaleWidget->setEnabled(!State.toBool());
4256 Update(ptProcessorPhase_Geometry);
4257 }
4258
4259
4260 // CA and Vignette tab
4261
CB_LfunCAModelChoice(const QVariant Choice)4262 void CB_LfunCAModelChoice(const QVariant Choice) {
4263 Settings->SetValue("LfunCAModel", Choice);
4264 MainWindow->UpdateLfunCAUI();
4265 Update(ptProcessorPhase_Geometry);
4266 }
4267
CB_LfunCALinearKrInput(const QVariant Value)4268 void CB_LfunCALinearKrInput(const QVariant Value) {
4269 Settings->SetValue("LfunCALinearKr", Value);
4270 Update(ptProcessorPhase_Geometry);
4271 }
4272
CB_LfunCALinearKbInput(const QVariant Value)4273 void CB_LfunCALinearKbInput(const QVariant Value) {
4274 Settings->SetValue("LfunCALinearKb", Value);
4275 Update(ptProcessorPhase_Geometry);
4276 }
4277
CB_LfunCAPoly3VrInput(const QVariant Value)4278 void CB_LfunCAPoly3VrInput(const QVariant Value) {
4279 Settings->SetValue("LfunCAPoly3Vr", Value);
4280 Update(ptProcessorPhase_Geometry);
4281 }
4282
CB_LfunCAPoly3VbInput(const QVariant Value)4283 void CB_LfunCAPoly3VbInput(const QVariant Value) {
4284 Settings->SetValue("LfunCAPoly3Vb", Value);
4285 Update(ptProcessorPhase_Geometry);
4286 }
4287
CB_LfunCAPoly3CrInput(const QVariant Value)4288 void CB_LfunCAPoly3CrInput(const QVariant Value) {
4289 Settings->SetValue("LfunCAPoly3Cr", Value);
4290 Update(ptProcessorPhase_Geometry);
4291 }
4292
CB_LfunCAPoly3CbInput(const QVariant Value)4293 void CB_LfunCAPoly3CbInput(const QVariant Value) {
4294 Settings->SetValue("LfunCAPoly3Cb", Value);
4295 Update(ptProcessorPhase_Geometry);
4296 }
4297
CB_LfunCAPoly3BrInput(const QVariant Value)4298 void CB_LfunCAPoly3BrInput(const QVariant Value) {
4299 Settings->SetValue("LfunCAPoly3Br", Value);
4300 Update(ptProcessorPhase_Geometry);
4301 }
4302
CB_LfunCAPoly3BbInput(const QVariant Value)4303 void CB_LfunCAPoly3BbInput(const QVariant Value) {
4304 Settings->SetValue("LfunCAPoly3Bb", Value);
4305 Update(ptProcessorPhase_Geometry);
4306 }
4307
CB_LfunVignetteModelChoice(const QVariant Choice)4308 void CB_LfunVignetteModelChoice(const QVariant Choice) {
4309 Settings->SetValue("LfunVignetteModel", Choice);
4310 MainWindow->UpdateLfunVignetteUI();
4311 Update(ptProcessorPhase_Geometry);
4312 }
4313
CB_LfunVignettePoly6K1Input(const QVariant Value)4314 void CB_LfunVignettePoly6K1Input(const QVariant Value) {
4315 Settings->SetValue("LfunVignettePoly6K1", Value);
4316 Update(ptProcessorPhase_Geometry);
4317 }
4318
CB_LfunVignettePoly6K2Input(const QVariant Value)4319 void CB_LfunVignettePoly6K2Input(const QVariant Value) {
4320 Settings->SetValue("LfunVignettePoly6K2", Value);
4321 Update(ptProcessorPhase_Geometry);
4322 }
4323
CB_LfunVignettePoly6K3Input(const QVariant Value)4324 void CB_LfunVignettePoly6K3Input(const QVariant Value) {
4325 Settings->SetValue("LfunVignettePoly6K3", Value);
4326 Update(ptProcessorPhase_Geometry);
4327 }
4328
4329
4330 // Lens correction tab
4331
CB_LfunSrcGeoChoice(const QVariant Choice)4332 void CB_LfunSrcGeoChoice(const QVariant Choice) {
4333 Settings->SetValue("LfunSrcGeo", Choice);
4334 Update(ptProcessorPhase_Geometry);
4335 }
4336
CB_LfunTargetGeoChoice(const QVariant Choice)4337 void CB_LfunTargetGeoChoice(const QVariant Choice) {
4338 Settings->SetValue("LfunTargetGeo", Choice);
4339 Update(ptProcessorPhase_Geometry);
4340 }
4341
CB_LfunDistModelChoice(const QVariant Choice)4342 void CB_LfunDistModelChoice(const QVariant Choice) {
4343 Settings->SetValue("LfunDistModel", Choice);
4344 MainWindow->UpdateLfunDistUI();
4345 Update(ptProcessorPhase_Geometry);
4346 }
4347
CB_LfunDistPoly3K1Input(const QVariant Value)4348 void CB_LfunDistPoly3K1Input(const QVariant Value) {
4349 Settings->SetValue("LfunDistPoly3K1", Value);
4350 Update(ptProcessorPhase_Geometry);
4351 }
4352
CB_LfunDistPoly5K1Input(const QVariant Value)4353 void CB_LfunDistPoly5K1Input(const QVariant Value) {
4354 Settings->SetValue("LfunDistPoly5K1", Value);
4355 Update(ptProcessorPhase_Geometry);
4356 }
4357
CB_LfunDistPoly5K2Input(const QVariant Value)4358 void CB_LfunDistPoly5K2Input(const QVariant Value) {
4359 Settings->SetValue("LfunDistPoly5K2", Value);
4360 Update(ptProcessorPhase_Geometry);
4361 }
4362
CB_LfunDistFov1OmegaInput(const QVariant Value)4363 void CB_LfunDistFov1OmegaInput(const QVariant Value) {
4364 Settings->SetValue("LfunDistFov1Omega", Value);
4365 Update(ptProcessorPhase_Geometry);
4366 }
4367
CB_LfunDistPTLensAInput(const QVariant Value)4368 void CB_LfunDistPTLensAInput(const QVariant Value) {
4369 Settings->SetValue("LfunDistPTLensA", Value);
4370 Update(ptProcessorPhase_Geometry);
4371 }
4372
CB_LfunDistPTLensBInput(const QVariant Value)4373 void CB_LfunDistPTLensBInput(const QVariant Value) {
4374 Settings->SetValue("LfunDistPTLensB", Value);
4375 Update(ptProcessorPhase_Geometry);
4376 }
4377
CB_LfunDistPTLensCInput(const QVariant Value)4378 void CB_LfunDistPTLensCInput(const QVariant Value) {
4379 Settings->SetValue("LfunDistPTLensC", Value);
4380 Update(ptProcessorPhase_Geometry);
4381 }
4382
4383 ////////////////////////////////////////////////////////////////////////////////
4384 //
4385 // Callbacks pertaining to the Geometry Tab
4386 // Partim Defish
4387 //
4388 ////////////////////////////////////////////////////////////////////////////////
4389
CB_DefishCheck(const QVariant State)4390 void CB_DefishCheck(const QVariant State) {
4391 Settings->SetValue("Defish",State);
4392 Update(ptProcessorPhase_Geometry);
4393 }
4394
CB_DefishFocalLengthInput(const QVariant Value)4395 void CB_DefishFocalLengthInput(const QVariant Value) {
4396 Settings->SetValue("DefishFocalLength", Value);
4397 if (Settings->GetInt("Defish"))
4398 Update(ptProcessorPhase_Geometry);
4399 }
4400
CB_DefishScaleInput(const QVariant Value)4401 void CB_DefishScaleInput(const QVariant Value) {
4402 Settings->SetValue("DefishScale", Value);
4403 if (Settings->GetInt("Defish"))
4404 Update(ptProcessorPhase_Geometry);
4405 }
4406
CB_DefishAutoScaleCheck(const QVariant State)4407 void CB_DefishAutoScaleCheck(const QVariant State) {
4408 Settings->SetValue("DefishAutoScale",State);
4409 MainWindow->DefishScaleWidget->setEnabled(!State.toBool());
4410 Update(ptProcessorPhase_Geometry);
4411 }
4412
4413 ////////////////////////////////////////////////////////////////////////////////
4414 //
4415 // Callbacks pertaining to the Geometry Tab
4416 // Partim Rotate
4417 //
4418 ////////////////////////////////////////////////////////////////////////////////
4419
CB_RotateLeftButton()4420 void CB_RotateLeftButton() {
4421 double Value = Settings->GetDouble("Rotate");
4422 Value -= 90.0;
4423 if (Value < -180.0) Value += 360.0;
4424 Settings->SetValue("Rotate",Value);
4425 Update(ptProcessorPhase_Geometry);
4426 }
4427
CB_RotateRightButton()4428 void CB_RotateRightButton() {
4429 double Value = Settings->GetDouble("Rotate");
4430 Value += 90.0;
4431 if (Value > 180.0) Value -= 360.0;
4432 Settings->SetValue("Rotate",Value);
4433 Update(ptProcessorPhase_Geometry);
4434 }
4435
CB_RotateAngleButton()4436 void CB_RotateAngleButton() {
4437 if (Settings->GetInt("HaveImage")==0) {
4438 ptMessageBox::information(MainWindow,
4439 QObject::tr("No selection"),
4440 QObject::tr("Open an image first."));
4441 return;
4442 }
4443
4444 // Rerun the part of geometry stage before rotate to get correct preview
4445 // image in TheProcessor->m_Image_AfterGeometry
4446 TheProcessor->RunGeometry(ptProcessorStopBefore::Rotate);
4447 ViewWindow->SaveZoom();
4448 ViewWindow->ZoomToFit();
4449 UpdatePreviewImage(TheProcessor->m_Image_AfterGeometry); // Calculate in any case.
4450
4451 // Allow to be selected in the view window. And deactivate main.
4452 ViewWindow->ShowStatus(QObject::tr("Get angle"));
4453 ReportProgress(QObject::tr("Get angle"));
4454
4455 BlockTools(btmBlockAll);
4456 ViewWindow->StartLine();
4457 ViewWindow->setFocus();
4458 }
4459
RotateAngleDetermined(const ptStatus ExitStatus,double RotateAngle)4460 void RotateAngleDetermined(const ptStatus ExitStatus, double RotateAngle) {
4461 // Selection is done at this point. Disallow it further and activate main.
4462 BlockTools(btmUnblock);
4463
4464 if (ExitStatus == stSuccess) {
4465 if (RotateAngle < -45.0) {
4466 RotateAngle += 180.0;
4467 }
4468 if (fabs(fabs(RotateAngle) - 90.0) < 45.0) {
4469 RotateAngle -= 90.0;
4470 }
4471 Settings->SetValue("Rotate",RotateAngle);
4472 }
4473
4474 ViewWindow->RestoreZoom();
4475 Update(ptProcessorPhase_Geometry);
4476 }
4477
CB_RotateInput(const QVariant Value)4478 void CB_RotateInput(const QVariant Value) {
4479 Settings->SetValue("Rotate",Value);
4480 Update(ptProcessorPhase_Geometry);
4481 }
4482
CB_PerspectiveFocalLengthInput(const QVariant Value)4483 void CB_PerspectiveFocalLengthInput(const QVariant Value) {
4484 Settings->SetValue("PerspectiveFocalLength",Value);
4485 Update(ptProcessorPhase_Geometry);
4486 }
4487
CB_PerspectiveTiltInput(const QVariant Value)4488 void CB_PerspectiveTiltInput(const QVariant Value) {
4489 Settings->SetValue("PerspectiveTilt",Value);
4490 Update(ptProcessorPhase_Geometry);
4491 }
4492
CB_PerspectiveTurnInput(const QVariant Value)4493 void CB_PerspectiveTurnInput(const QVariant Value) {
4494 Settings->SetValue("PerspectiveTurn",Value);
4495 Update(ptProcessorPhase_Geometry);
4496 }
4497
CB_PerspectiveScaleXInput(const QVariant Value)4498 void CB_PerspectiveScaleXInput(const QVariant Value) {
4499 Settings->SetValue("PerspectiveScaleX",Value);
4500 Update(ptProcessorPhase_Geometry);
4501 }
4502
CB_PerspectiveScaleYInput(const QVariant Value)4503 void CB_PerspectiveScaleYInput(const QVariant Value) {
4504 Settings->SetValue("PerspectiveScaleY",Value);
4505 Update(ptProcessorPhase_Geometry);
4506 }
4507
CB_GridCheck(const QVariant State)4508 void CB_GridCheck(const QVariant State) {
4509 Settings->SetValue("Grid",State);
4510 ViewWindow->setGrid(Settings->GetInt("Grid"), Settings->GetInt("GridX"), Settings->GetInt("GridY"));
4511 Update(ptProcessorPhase_Preview);
4512 }
4513
CB_GridXInput(const QVariant Value)4514 void CB_GridXInput(const QVariant Value) {
4515 Settings->SetValue("GridX",Value);
4516 if (Settings->GetInt("Grid")) {
4517 ViewWindow->setGrid(Settings->GetInt("Grid"), Settings->GetInt("GridX"), Settings->GetInt("GridY"));
4518 Update(ptProcessorPhase_Preview);
4519 }
4520 }
4521
CB_GridYInput(const QVariant Value)4522 void CB_GridYInput(const QVariant Value) {
4523 Settings->SetValue("GridY",Value);
4524 if (Settings->GetInt("Grid")) {
4525 ViewWindow->setGrid(Settings->GetInt("Grid"), Settings->GetInt("GridX"), Settings->GetInt("GridY"));
4526 Update(ptProcessorPhase_Preview);
4527 }
4528 }
4529
CB_FlipModeChoice(const QVariant Value)4530 void CB_FlipModeChoice(const QVariant Value) {
4531 Settings->SetValue("FlipMode",Value);
4532 Update(ptProcessorPhase_Geometry);
4533 }
4534
CB_GeometryBlockCheck(const QVariant State)4535 void CB_GeometryBlockCheck(const QVariant State) {
4536 Settings->SetValue("GeometryBlock",State);
4537 Update(ptProcessorPhase_RGB);
4538 }
4539
4540 ////////////////////////////////////////////////////////////////////////////////
4541 //
4542 // Callbacks pertaining to the Geometry Tab
4543 // Partim Crop
4544 //
4545 ////////////////////////////////////////////////////////////////////////////////
4546
CB_FixedAspectRatioCheck(const QVariant Check)4547 void CB_FixedAspectRatioCheck(const QVariant Check) {
4548 Settings->SetValue("FixedAspectRatio", Check);
4549 MainWindow->UpdateCropToolUI();
4550 if (ViewWindow->interaction() == iaCrop) {
4551 ViewWindow->crop()->setAspectRatio(Settings->GetInt("FixedAspectRatio"),
4552 Settings->GetInt("AspectRatioW"),
4553 Settings->GetInt("AspectRatioH"));
4554 ViewWindow->setFocus();
4555 }
4556 }
4557
CB_AspectRatioWChoice(const QVariant Value)4558 void CB_AspectRatioWChoice(const QVariant Value) {
4559 Settings->SetValue("AspectRatioW",Value);
4560 if (ViewWindow->interaction() == iaCrop) {
4561 ViewWindow->crop()->setAspectRatio(Settings->GetInt("FixedAspectRatio"),
4562 Settings->GetInt("AspectRatioW"),
4563 Settings->GetInt("AspectRatioH"));
4564 ViewWindow->setFocus();
4565 }
4566 }
4567
CB_AspectRatioHChoice(const QVariant Value)4568 void CB_AspectRatioHChoice(const QVariant Value) {
4569 Settings->SetValue("AspectRatioH",Value);
4570 if (ViewWindow->interaction() == iaCrop) {
4571 ViewWindow->crop()->setAspectRatio(Settings->GetInt("FixedAspectRatio"),
4572 Settings->GetInt("AspectRatioW"),
4573 Settings->GetInt("AspectRatioH"));
4574 ViewWindow->setFocus();
4575 }
4576 }
4577
CB_CropExposureInput(const QVariant Value)4578 void CB_CropExposureInput(const QVariant Value) {
4579 Settings->SetValue("CropExposure", Value);
4580
4581 if (ViewWindow->interaction() == iaCrop) {
4582 if (GBusy) return;
4583 else GBusy = true;
4584 UpdatePreviewImage(TheProcessor->m_Image_AfterGeometry); // Calculate in any case.
4585 GBusy = false;
4586 }
4587 }
4588
CB_CropOrientationButton()4589 void CB_CropOrientationButton() {
4590 int w = Settings->GetInt("AspectRatioW");
4591 int h = Settings->GetInt("AspectRatioH");
4592
4593 if (w != h) {
4594 Settings->SetValue("AspectRatioW", h);
4595 Settings->SetValue("AspectRatioH", w);
4596 if (ViewWindow->interaction() == iaCrop) {
4597 ViewWindow->crop()->flipAspectRatio();
4598 ViewWindow->setFocus();
4599 }
4600 }
4601 }
4602
CB_CropCenterHorButton()4603 void CB_CropCenterHorButton() {
4604 if (ViewWindow->interaction() == iaCrop) {
4605 ViewWindow->crop()->moveToCenter(1, 0);
4606 ViewWindow->setFocus();
4607 }
4608 }
4609
CB_CropCenterVertButton()4610 void CB_CropCenterVertButton() {
4611 if (ViewWindow->interaction() == iaCrop) {
4612 ViewWindow->crop()->moveToCenter(0, 1);
4613 ViewWindow->setFocus();
4614 }
4615 }
4616
CB_CropGuidelinesChoice(const QVariant Choice)4617 void CB_CropGuidelinesChoice(const QVariant Choice) {
4618 Settings->SetValue("CropGuidelines",Choice);
4619 if (ViewWindow->interaction() == iaCrop) {
4620 ViewWindow->crop()->setGuidelines(Choice.toInt());
4621 ViewWindow->setFocus();
4622 }
4623 }
4624
CB_LightsOutChoice(const QVariant Choice)4625 void CB_LightsOutChoice(const QVariant Choice) {
4626 // View window takes care of Settings
4627 if (ViewWindow->interaction() == iaCrop) {
4628 ViewWindow->crop()->setLightsOut(Choice.toInt());
4629 ViewWindow->setFocus();
4630 }
4631 }
4632
4633
4634 // Prepare and start image crop interaction
CB_MakeCropButton()4635 void CB_MakeCropButton() {
4636 if (Settings->GetInt("HaveImage")==0) {
4637 ptMessageBox::information(MainWindow,
4638 QObject::tr("No crop possible"),
4639 QObject::tr("Open an image first."));
4640 return;
4641 }
4642
4643 ViewWindow->ShowStatus(QObject::tr("Prepare"));
4644 ReportProgress(QObject::tr("Prepare for cropping"));
4645
4646 // Rerun the part of geometry stage before crop to get correct preview
4647 // image in TheProcessor->m_Image_AfterGeometry
4648 TheProcessor->RunGeometry(ptProcessorStopBefore::Crop);
4649 UpdatePreviewImage(TheProcessor->m_Image_AfterGeometry); // Calculate in any case.
4650
4651 // Allow to be selected in the view window. And deactivate main.
4652 ViewWindow->ShowStatus(QObject::tr("Crop"));
4653 ReportProgress(QObject::tr("Crop"));
4654 BlockTools(btmBlockForCrop);
4655
4656 switch (Settings->GetInt("CropInitialZoom")) {
4657 case ptZoomLevel_Current:
4658 // nothing to do
4659 break;
4660
4661 case ptZoomLevel_Fit:
4662 ViewWindow->ZoomToFit(0);
4663 break;
4664
4665 default:
4666 ViewWindow->ZoomTo((float)Settings->GetInt("CropInitialZoom") / 100);
4667 break;
4668 }
4669
4670 ViewWindow->StartCrop(); // always start the interaction first,
4671 MainWindow->UpdateCropToolUI(); // *then* update main window
4672 ViewWindow->setFocus();
4673 }
4674
4675
4676 // After-crop processing and cleanup.
CleanupAfterCrop(const ptStatus CropStatus,const QRect CropRect)4677 void CleanupAfterCrop(const ptStatus CropStatus, const QRect CropRect) {
4678 BlockTools(btmUnblock);
4679
4680 if (CropStatus == stSuccess) {
4681 // Account for the pipesize factor.
4682 int XScale = 1<<Settings->GetInt("PipeSize");
4683 int YScale = 1<<Settings->GetInt("PipeSize");
4684
4685 if ((CropRect.width() * XScale < 4) || (CropRect.height() * YScale < 4)) {
4686 ptMessageBox::information(MainWindow,
4687 QObject::tr("Crop too small"),
4688 QObject::tr("Crop rectangle needs to be at least 4x4 pixels in size.\nNo crop, try again."));
4689
4690 if ((Settings->GetInt("CropW") < 4) || (Settings->GetInt("CropH") < 4)) {
4691 Settings->SetValue("Crop", 0);
4692 QCheckBox(MainWindow->CropWidget).setCheckState(Qt::Unchecked);
4693 }
4694
4695 if(Settings->GetInt("RunMode")==1) {
4696 // we're in manual mode!
4697 Update(ptProcessorPhase_Preview);
4698 }
4699 } else {
4700 Settings->SetValue("Crop",1);
4701 Settings->SetValue("CropX",CropRect.left() * XScale);
4702 Settings->SetValue("CropY",CropRect.top() * YScale);
4703 Settings->SetValue("CropW",CropRect.width() * XScale);
4704 Settings->SetValue("CropH",CropRect.height() * YScale);
4705 }
4706
4707 TRACEKEYVALS("PreviewImageW","%d",PreviewImage->m_Width);
4708 TRACEKEYVALS("PreviewImageH","%d",PreviewImage->m_Height);
4709 TRACEKEYVALS("XScale","%d",XScale);
4710 TRACEKEYVALS("YScale","%d",YScale);
4711 TRACEKEYVALS("CropX","%d",Settings->GetInt("CropX"));
4712 TRACEKEYVALS("CropY","%d",Settings->GetInt("CropY"));
4713 TRACEKEYVALS("CropW","%d",Settings->GetInt("CropW"));
4714 TRACEKEYVALS("CropH","%d",Settings->GetInt("CropH"));
4715
4716
4717 // Crop aborted, disable crop checkbox when no previous crop present
4718 } else {
4719 if ((Settings->GetInt("CropW") < 4) || (Settings->GetInt("CropH") < 4)) {
4720 Settings->SetValue("Crop", 0);
4721 }
4722 }
4723
4724 Update(ptProcessorPhase_Geometry);
4725 MainWindow->UpdateCropToolUI();
4726 }
4727
4728
CB_ConfirmCropButton()4729 void CB_ConfirmCropButton() {
4730 ViewWindow->crop()->stop(stSuccess); // user confirmed crop
4731 }
4732
CB_CancelCropButton()4733 void CB_CancelCropButton() {
4734 ViewWindow->crop()->stop(stFailure); // user cancelled crop
4735 }
4736
4737
4738 // En/disable an existing crop in the pipe
CB_CropCheck(const QVariant State)4739 void CB_CropCheck(const QVariant State) {
4740 Settings->SetValue("Crop",State);
4741
4742 if (State.toInt() != 0 &&
4743 (Settings->GetInt("CropW") <= 4 || Settings->GetInt("CropH") <= 4))
4744 {
4745 ptMessageBox::information(MainWindow,
4746 QObject::tr("No previous crop found"),
4747 QObject::tr("Set a crop rectangle now."));
4748
4749 CB_MakeCropButton();
4750 return;
4751 }
4752
4753 Update(ptProcessorPhase_Geometry);
4754 }
4755
4756
4757 ////////////////////////////////////////////////////////////////////////////////
4758 //
4759 // Callbacks pertaining to the Geometry Tab
4760 // Partim Liquid rescale
4761 //
4762 ////////////////////////////////////////////////////////////////////////////////
4763
CB_LqrEnergyChoice(const QVariant Choice)4764 void CB_LqrEnergyChoice(const QVariant Choice) {
4765 Settings->SetValue("LqrEnergy",Choice);
4766 Update(ptProcessorPhase_Geometry);
4767 }
4768
CB_LqrScalingChoice(const QVariant Choice)4769 void CB_LqrScalingChoice(const QVariant Choice) {
4770 Settings->SetValue("LqrScaling",Choice);
4771 MainWindow->UpdateLiquidRescaleUI();
4772 if (Settings->ToolIsActive("TabLiquidRescale"))
4773 Update(ptProcessorPhase_Geometry);
4774 }
4775
CB_LqrHorScaleInput(const QVariant Value)4776 void CB_LqrHorScaleInput(const QVariant Value) {
4777 Settings->SetValue("LqrHorScale",Value);
4778 if (Settings->ToolIsActive("TabLiquidRescale"))
4779 Update(ptProcessorPhase_Geometry);
4780 }
4781
CB_LqrVertScaleInput(const QVariant Value)4782 void CB_LqrVertScaleInput(const QVariant Value) {
4783 Settings->SetValue("LqrVertScale",Value);
4784 if (Settings->ToolIsActive("TabLiquidRescale"))
4785 Update(ptProcessorPhase_Geometry);
4786 }
4787
CB_LqrWidthInput(const QVariant Value)4788 void CB_LqrWidthInput(const QVariant Value) {
4789 Settings->SetValue("LqrWidth",Value);
4790 if (Settings->ToolIsActive("TabLiquidRescale"))
4791 Update(ptProcessorPhase_Geometry);
4792 }
4793
CB_LqrHeightInput(const QVariant Value)4794 void CB_LqrHeightInput(const QVariant Value) {
4795 Settings->SetValue("LqrHeight",Value);
4796 if (Settings->ToolIsActive("TabLiquidRescale"))
4797 Update(ptProcessorPhase_Geometry);
4798 }
4799
CB_LqrVertFirstCheck(const QVariant Check)4800 void CB_LqrVertFirstCheck(const QVariant Check) {
4801 Settings->SetValue("LqrVertFirst",Check);
4802 if (Settings->ToolIsActive("TabLiquidRescale"))
4803 Update(ptProcessorPhase_Geometry);
4804 }
4805
4806
4807 ////////////////////////////////////////////////////////////////////////////////
4808 //
4809 // Callbacks pertaining to the Geometry Tab
4810 // Partim Resize
4811 //
4812 ////////////////////////////////////////////////////////////////////////////////
4813
CalculatePipeSizeHelper(const short Size,const bool NewImage)4814 void CalculatePipeSizeHelper(const short Size, const bool NewImage) {
4815 if (NewImage) {
4816 Settings->SetValue("PipeSize",Size);
4817 } else {
4818 CB_PipeSizeChoice(Size);
4819 }
4820 }
4821
4822 // returns 1 if pipe was updated
CalculatePipeSize(const bool NewImage)4823 int CalculatePipeSize(const bool NewImage /* = False */) {
4824 uint16_t InSize = 0;
4825 if (Settings->GetInt("HaveImage")==0) return 0;
4826 if (Settings->GetInt("Crop")==0) {
4827 InSize = MAX(Settings->GetInt("ImageW"),Settings->GetInt("ImageH"));
4828 } else {
4829 InSize = MAX(Settings->GetInt("CropW"),Settings->GetInt("CropH"));
4830 }
4831 int s = MAX(0,((int)floor(logf((float)InSize*0.9/(float)Settings->GetInt("ResizeScale"))/logf(2))));
4832 if (s < Settings->GetInt("PipeSize")) {
4833 if (Settings->GetInt("RunMode") != 1) {// not manual mode
4834 ImageSaved = 1; // bad hack to check what happens in the next step
4835 CalculatePipeSizeHelper(s, NewImage);
4836 if (ImageSaved == 1 && !NewImage) {
4837 if (Settings->GetInt("PipeSize")==1) {
4838 ptMessageBox::information(NULL,"Failure!","Could not run on full size!\nWill stay on half size instead!");
4839 ImageSaved = 0;
4840 return 0;
4841 } else {
4842 ptMessageBox::information(NULL,"Failure!","Could not run on full size!\nWill run on half size instead!");
4843 CalculatePipeSizeHelper(1, NewImage);
4844 }
4845 }
4846 } else {
4847 CalculatePipeSizeHelper(s, NewImage);
4848 }
4849 return 1;
4850 }
4851 return 0;
4852 }
4853
CB_ResizeCheck(const QVariant Check)4854 void CB_ResizeCheck(const QVariant Check) {
4855 Settings->SetValue("Resize",Check);
4856 if (Settings->GetInt("AutomaticPipeSize") && Settings->GetInt("Resize")) {
4857 if (!CalculatePipeSize())
4858 Update(ptProcessorPhase_Geometry);
4859 } else {
4860 Update(ptProcessorPhase_Geometry);
4861 }
4862 MainWindow->UpdateExifInfo(TheProcessor->m_ExifData);
4863 }
4864
CB_ResizeDimensionChoice(const QVariant Choice)4865 void CB_ResizeDimensionChoice(const QVariant Choice) {
4866 Settings->SetValue("ResizeDimension",Choice);
4867 if (Settings->GetInt("Resize")) {
4868 if (Settings->GetInt("AutomaticPipeSize")) {
4869 if (!CalculatePipeSize())
4870 Update(ptProcessorPhase_Geometry);
4871 } else {
4872 Update(ptProcessorPhase_Geometry);
4873 }
4874 MainWindow->UpdateExifInfo(TheProcessor->m_ExifData);
4875 } else {
4876 MainWindow->UpdateSettings();
4877 }
4878 }
4879
CB_ResizeScaleInput(const QVariant Value)4880 void CB_ResizeScaleInput(const QVariant Value) {
4881 Settings->SetValue("ResizeScale",Value);
4882 if (Settings->GetInt("Resize")) {
4883 if (Settings->GetInt("AutomaticPipeSize")) {
4884 if (!CalculatePipeSize())
4885 Update(ptProcessorPhase_Geometry);
4886 } else {
4887 Update(ptProcessorPhase_Geometry);
4888 }
4889 MainWindow->UpdateExifInfo(TheProcessor->m_ExifData);
4890 }
4891 }
4892
CB_ResizeHeightInput(const QVariant Value)4893 void CB_ResizeHeightInput(const QVariant Value) {
4894 Settings->SetValue("ResizeHeight",Value);
4895 if (Settings->GetInt("Resize") &&
4896 Settings->GetInt("ResizeDimension") == ptResizeDimension_WidthHeight) {
4897 if (Settings->GetInt("AutomaticPipeSize")) {
4898 if (!CalculatePipeSize())
4899 Update(ptProcessorPhase_Geometry);
4900 } else {
4901 Update(ptProcessorPhase_Geometry);
4902 }
4903 MainWindow->UpdateExifInfo(TheProcessor->m_ExifData);
4904 }
4905 }
4906
CB_ResizeFilterChoice(const QVariant Choice)4907 void CB_ResizeFilterChoice(const QVariant Choice) {
4908 Settings->SetValue("ResizeFilter",Choice);
4909 if (Settings->GetInt("Resize")) {
4910 if (Settings->GetInt("AutomaticPipeSize")) {
4911 if (!CalculatePipeSize())
4912 Update(ptProcessorPhase_Geometry);
4913 } else {
4914 Update(ptProcessorPhase_Geometry);
4915 }
4916 MainWindow->UpdateExifInfo(TheProcessor->m_ExifData);
4917 }
4918 }
4919
CB_AutomaticPipeSizeCheck(const QVariant Check)4920 void CB_AutomaticPipeSizeCheck(const QVariant Check) {
4921 Settings->SetValue("AutomaticPipeSize",Check);
4922 if (Settings->GetInt("Resize")) {
4923 if (Settings->GetInt("AutomaticPipeSize")) {
4924 if (!CalculatePipeSize())
4925 Update(ptProcessorPhase_Geometry);
4926 } else {
4927 Update(ptProcessorPhase_Geometry);
4928 }
4929 MainWindow->UpdateExifInfo(TheProcessor->m_ExifData);
4930 }
4931 }
4932
4933 ////////////////////////////////////////////////////////////////////////////////
4934 //
4935 // Callbacks pertaining to Out Tab
4936 //
4937 ////////////////////////////////////////////////////////////////////////////////
4938
CB_SaveFormatChoice(const QVariant Choice)4939 void CB_SaveFormatChoice(const QVariant Choice) {
4940 Settings->SetValue("SaveFormat",Choice);
4941 MainWindow->UpdateSettings();
4942 }
4943
CB_EraseExifThumbnailCheck(const QVariant State)4944 void CB_EraseExifThumbnailCheck(const QVariant State) {
4945 Settings->SetValue("EraseExifThumbnail",State);
4946 TheProcessor->ReadExifBuffer();
4947 }
4948
BlockExport(bool Block)4949 inline void BlockExport(bool Block) {
4950 if (!Block) QApplication::processEvents();
4951 MainWindow->ToGimpButton->setEnabled(!Block);
4952 QApplication::processEvents();
4953 }
4954
BlockSave(bool Block)4955 inline void BlockSave(bool Block) {
4956 if (!Block) QApplication::processEvents();
4957 MainWindow->WritePipeButton->setEnabled(!Block);
4958 QApplication::processEvents();
4959 }
4960
4961 //==============================================================================
4962
GetCurrentImageBaseName()4963 QString GetCurrentImageBaseName() {
4964 if (Settings->GetInt("HaveImage")==0) return "";
4965
4966 QStringList InputFileNameList = Settings->GetStringList("InputFileNameList");
4967 QFileInfo PathInfo(InputFileNameList[0]);
4968 return PathInfo.dir().absolutePath() + QDir::separator() + PathInfo.baseName() +
4969 Settings->GetString("OutputFileNameSuffix") + ".";
4970 }
4971
4972 //==============================================================================
4973
SaveOutput(const short mode)4974 void SaveOutput(const short mode) {
4975 BlockSave(true);
4976
4977 if (mode==ptOutputMode_Full) {
4978 CB_MenuFileSaveOutput();
4979
4980 } else if (mode==ptOutputMode_Pipe) {
4981 WritePipe();
4982
4983 } else if (mode==ptOutputMode_Jobfile) {
4984 GFilterDM->WriteJobFile();
4985
4986 } else if (mode==ptOutputMode_Settingsfile) {
4987 GFilterDM->WritePresetFile(GetCurrentImageBaseName());
4988
4989 } else if (mode==ptOutputMode_Batch) {
4990 GFilterDM->SendToBatch(GetCurrentImageBaseName());
4991 }
4992
4993 BlockSave(false);
4994 }
4995
4996 //==============================================================================
4997
Export(const short mode)4998 void Export(const short mode) {
4999 BlockExport(true);
5000 if (mode==ptExportMode_GimpPipe && Settings->GetInt("ExportToGimp")) {
5001 GimpExport(1);
5002 BlockExport(false);
5003 return;
5004 } else if (mode==ptExportMode_GimpFull && Settings->GetInt("ExportToGimp")) {
5005 GimpExport(0);
5006 BlockExport(false);
5007 return;
5008 }
5009
5010 // regular export without plugin
5011 // We generate a temporary name.
5012 QString ImageFileName = QDir::tempPath() + QDir::separator() +
5013 "ptTemp" + QString::number(QDateTime::currentMSecsSinceEpoch()) + ".tif";
5014
5015 short Temp = Settings->GetInt("SaveFormat");
5016 Settings->SetValue("SaveFormat", ptSaveFormat_TIFF16);
5017
5018 if (mode==ptExportMode_GimpPipe && !Settings->GetInt("ExportToGimp")) {
5019 WritePipe(ImageFileName);
5020 } else if (mode==ptExportMode_GimpFull && !Settings->GetInt("ExportToGimp")) {
5021 CB_MenuFileSaveOutput(ImageFileName);
5022 }
5023
5024 Settings->SetValue("SaveFormat", Temp);
5025
5026 QString ExportCommand = Settings->GetString("GimpExecCommand");
5027 QStringList ExportArguments;
5028 ExportArguments << ImageFileName;
5029 QProcess* ExportProcess = new QProcess();
5030 ExportProcess->startDetached(ExportCommand,ExportArguments);
5031 BlockExport(false);
5032 }
5033
CB_WritePipeButton()5034 void CB_WritePipeButton() {
5035 SaveOutput(Settings->GetInt("SaveButtonMode"));
5036 }
5037
CB_FileMgrUseThumbMaxRowColCheck(const QVariant checked)5038 void CB_FileMgrUseThumbMaxRowColCheck(const QVariant checked) {
5039 Settings->SetValue("FileMgrUseThumbMaxRowCol", checked);
5040 MainWindow->FileMgrThumbMaxRowColWidget->setEnabled(checked.toBool());
5041 }
5042
5043
5044 ////////////////////////////////////////////////////////////////////////////////
5045 //
5046 // Callback dispatcher
5047 //
5048 // For refactoring:
5049 // The control switching the active state of the tool needs always to trigger
5050 // a pipe run (also if it just disabled the tool!) The only exception is the
5051 // external blocked state (blocked or hidden tools!).
5052 //
5053 ////////////////////////////////////////////////////////////////////////////////
5054
5055 // For simple switches, just get the value to the settings
Standard_CB_JustSet(const QString ObjectName,const QVariant Value)5056 void Standard_CB_JustSet (const QString ObjectName, const QVariant Value) {
5057 QString Temp = ObjectName;
5058 if (Temp.endsWith("Input") || Temp.endsWith("Check")) Temp.chop(5);
5059 if (Temp.endsWith("Choice")) Temp.chop(6);
5060 Settings->SetValue(Temp,Value);
5061 }
5062
5063 // Standard form of call backs, value to settings and pipe run if needed
Standard_CB_SetAndRun(const QString ObjectName,const QVariant Value)5064 void Standard_CB_SetAndRun (const QString ObjectName, const QVariant Value) {
5065 QString Key = ObjectName;
5066 if (Key.endsWith("Input") || Key.endsWith("Check")) Key.chop(5);
5067 if (Key.endsWith("Choice")) Key.chop(6);
5068
5069 QWidget* CurrentControl = Settings->GetGuiWidget(Key);
5070 if (CurrentControl == NULL) assert(!"Widget not found");
5071 ptGroupBox* CurrentTool = dynamic_cast<ptGroupBox*>(CurrentControl);
5072
5073 while (CurrentTool == NULL) {
5074 CurrentControl = CurrentControl->parentWidget();
5075 CurrentTool = dynamic_cast<ptGroupBox*>(CurrentControl);
5076 }
5077 QString ToolName = CurrentTool->objectName();
5078
5079 // Save previous state for rerun when disabling a filter
5080 short PreviousActiveState = Settings->ToolIsActive(ToolName);
5081
5082 Settings->SetValue(Key,Value);
5083
5084 short NewActiveState = Settings->ToolIsActive(ToolName);
5085 CurrentTool->SetActive(NewActiveState);
5086
5087 if (NewActiveState || PreviousActiveState) {
5088 Update(ToolName);
5089 } else {
5090 MainWindow->UpdateSettings();
5091 }
5092 }
5093
CB_InputChanged(const QString ObjectName,const QVariant Value)5094 void CB_InputChanged(const QString ObjectName, const QVariant Value) {
5095 // No CB processing while in startup phase. Too much
5096 // noise events otherwise.
5097 if (InStartup) return;
5098
5099 if (ObjectName != "ZoomInput" &&
5100 ObjectName != "PipeSizeChoice" &&
5101 ObjectName != "RunModeCheck" &&
5102 ObjectName != "SpecialPreviewChoice" &&
5103 ObjectName != "UseThumbnailCheck")
5104 {
5105 ptAddUndo();
5106 }
5107
5108 if (ObjectName == "ZoomInput") {
5109 CB_ZoomInput(Value);
5110
5111 #define M_Dispatch(Name)\
5112 } else if (ObjectName == #Name) { CB_ ## Name (Value);
5113
5114 #define M_JustSetDispatch(Name)\
5115 } else if (ObjectName == #Name) { Standard_CB_JustSet(#Name,Value);
5116
5117 #define M_SetAndRunDispatch(Name)\
5118 } else if (ObjectName == #Name) { Standard_CB_SetAndRun(#Name,Value);
5119
5120 M_Dispatch(CameraColorChoice)
5121 M_Dispatch(CameraColorProfileIntentChoice)
5122 M_Dispatch(CameraColorGammaChoice)
5123
5124 M_Dispatch(WorkColorChoice)
5125 M_Dispatch(CMQualityChoice)
5126
5127 M_Dispatch(PreviewColorProfileIntentChoice)
5128
5129 M_Dispatch(StyleChoice)
5130 M_Dispatch(StyleHighLightChoice)
5131
5132 M_Dispatch(SaveConfirmationCheck)
5133 M_Dispatch(AutosaveSettingsCheck)
5134 M_Dispatch(ResetSettingsConfirmationCheck)
5135 M_Dispatch(FullPipeConfirmationCheck)
5136
5137 M_Dispatch(WriteBackupSettingsCheck)
5138
5139 M_JustSetDispatch(FileMgrThumbnailSizeInput)
5140 M_JustSetDispatch(FileMgrThumbnailPaddingInput)
5141 M_Dispatch(FileMgrUseThumbMaxRowColCheck)
5142 M_JustSetDispatch(FileMgrThumbMaxRowColInput)
5143 M_JustSetDispatch(FileMgrThumbSaveSizeInput)
5144 M_JustSetDispatch(FileMgrStartupOpenCheck)
5145 M_JustSetDispatch(FileMgrThumbCacheSizeInput)
5146
5147 M_JustSetDispatch(BatchMgrAutosaveCheck)
5148 M_JustSetDispatch(BatchMgrAutosaveFileChoice)
5149 M_JustSetDispatch(BatchMgrAutoloadCheck)
5150
5151 M_Dispatch(MemoryTestInput)
5152
5153 M_Dispatch(ExportToGimpCheck)
5154
5155 M_Dispatch(StartupSettingsCheck)
5156 M_Dispatch(StartupSettingsResetCheck)
5157 M_Dispatch(StartupUIModeChoice)
5158 M_Dispatch(StartupPipeSizeChoice)
5159 M_JustSetDispatch(EscToExitCheck)
5160 M_JustSetDispatch(LoadTagsCheck)
5161
5162 M_JustSetDispatch(StartupSwitchARCheck)
5163
5164 M_Dispatch(CropInitialZoomChoice)
5165
5166 M_Dispatch(RememberSettingLevelChoice)
5167 M_Dispatch(InputsAddPowerLawCheck)
5168 M_Dispatch(ToolBoxModeCheck)
5169 M_Dispatch(TabStatusIndicatorInput)
5170 M_Dispatch(PreviewTabModeCheck)
5171 M_Dispatch(BackgroundColorCheck)
5172 M_Dispatch(SliderWidthInput)
5173 M_Dispatch(SaveButtonModeChoice)
5174 M_Dispatch(ResetButtonModeChoice)
5175 M_Dispatch(SearchBarEnableCheck)
5176
5177 M_Dispatch(PipeSizeChoice)
5178 M_Dispatch(RunModeCheck)
5179 M_Dispatch(SpecialPreviewChoice)
5180
5181 M_Dispatch(UseThumbnailCheck)
5182
5183 M_Dispatch(BadPixelsChoice)
5184 M_Dispatch(DarkFrameChoice)
5185
5186 M_Dispatch(WhiteBalanceChoice)
5187 M_Dispatch(ColorTemperatureInput)
5188 M_Dispatch(GreenIntensityInput)
5189 M_Dispatch(MultiplierEnhanceCheck)
5190 M_Dispatch(RMultiplierInput)
5191 M_Dispatch(GMultiplierInput)
5192 M_Dispatch(BMultiplierInput)
5193 M_Dispatch(ManualBlackPointCheck)
5194 M_Dispatch(BlackPointInput)
5195 M_Dispatch(ManualWhitePointCheck)
5196 M_Dispatch(WhitePointInput)
5197 M_Dispatch(CaCorrectChoice)
5198 M_Dispatch(CaRedInput)
5199 M_Dispatch(CaBlueInput)
5200 M_Dispatch(GreenEquilInput)
5201 M_Dispatch(CfaLineDenoiseInput)
5202 M_Dispatch(AdjustMaximumThresholdInput)
5203 M_Dispatch(RawDenoiseThresholdInput)
5204 M_Dispatch(HotpixelReductionInput)
5205 M_Dispatch(BayerDenoiseChoice)
5206 M_Dispatch(InterpolationChoice)
5207 M_Dispatch(InterpolationPassesInput)
5208 M_Dispatch(MedianPassesInput)
5209 M_Dispatch(ESMedianPassesInput)
5210 M_Dispatch(EeciRefineCheck)
5211 M_Dispatch(ClipModeChoice)
5212 M_Dispatch(ClipParameterInput)
5213
5214 M_Dispatch(LfunFocalInput)
5215 M_Dispatch(LfunApertureInput)
5216 M_Dispatch(LfunDistanceInput)
5217 M_Dispatch(LfunScaleInput)
5218 M_Dispatch(LfunAutoScaleCheck)
5219 M_Dispatch(LfunCAModelChoice)
5220 M_Dispatch(LfunCALinearKbInput)
5221 M_Dispatch(LfunCALinearKrInput)
5222 M_Dispatch(LfunCAPoly3VrInput)
5223 M_Dispatch(LfunCAPoly3VbInput)
5224 M_Dispatch(LfunCAPoly3CrInput)
5225 M_Dispatch(LfunCAPoly3CbInput)
5226 M_Dispatch(LfunCAPoly3BrInput)
5227 M_Dispatch(LfunCAPoly3BbInput)
5228 M_Dispatch(LfunVignetteModelChoice)
5229 M_Dispatch(LfunVignettePoly6K1Input)
5230 M_Dispatch(LfunVignettePoly6K2Input)
5231 M_Dispatch(LfunVignettePoly6K3Input)
5232 M_Dispatch(LfunSrcGeoChoice)
5233 M_Dispatch(LfunTargetGeoChoice)
5234 M_Dispatch(LfunDistModelChoice)
5235 M_Dispatch(LfunDistPoly3K1Input)
5236 M_Dispatch(LfunDistPoly5K1Input)
5237 M_Dispatch(LfunDistPoly5K2Input)
5238 #if LF_VERSION < (3 << 16)
5239 M_Dispatch(LfunDistFov1OmegaInput)
5240 #endif
5241 M_Dispatch(LfunDistPTLensAInput)
5242 M_Dispatch(LfunDistPTLensBInput)
5243 M_Dispatch(LfunDistPTLensCInput)
5244
5245 M_Dispatch(DefishCheck)
5246 M_Dispatch(DefishFocalLengthInput)
5247 M_Dispatch(DefishScaleInput)
5248 M_Dispatch(DefishAutoScaleCheck)
5249
5250 M_Dispatch(RotateInput)
5251 M_Dispatch(PerspectiveFocalLengthInput)
5252 M_Dispatch(PerspectiveTiltInput)
5253 M_Dispatch(PerspectiveTurnInput)
5254 M_Dispatch(PerspectiveScaleXInput)
5255 M_Dispatch(PerspectiveScaleYInput)
5256 M_Dispatch(GridCheck)
5257 M_Dispatch(GridXInput)
5258 M_Dispatch(GridYInput)
5259
5260 M_Dispatch(CropCheck)
5261 M_Dispatch(CropGuidelinesChoice)
5262 M_Dispatch(LightsOutChoice)
5263 M_Dispatch(FixedAspectRatioCheck)
5264 M_Dispatch(AspectRatioWChoice)
5265 M_Dispatch(AspectRatioHChoice)
5266 M_Dispatch(CropExposureInput)
5267
5268 M_Dispatch(LqrEnergyChoice)
5269 M_Dispatch(LqrScalingChoice)
5270 M_Dispatch(LqrHorScaleInput)
5271 M_Dispatch(LqrVertScaleInput)
5272 M_Dispatch(LqrWidthInput)
5273 M_Dispatch(LqrHeightInput)
5274 M_Dispatch(LqrVertFirstCheck)
5275
5276 M_Dispatch(ResizeCheck)
5277 M_Dispatch(ResizeDimensionChoice)
5278 M_Dispatch(ResizeScaleInput)
5279 M_Dispatch(ResizeHeightInput)
5280 M_Dispatch(ResizeFilterChoice)
5281 M_Dispatch(AutomaticPipeSizeCheck)
5282
5283 M_Dispatch(FlipModeChoice)
5284
5285 M_Dispatch(GeometryBlockCheck)
5286
5287 M_SetAndRunDispatch(OutputGammaCompensationCheck)
5288 M_SetAndRunDispatch(OutputGammaInput)
5289 M_SetAndRunDispatch(OutputLinearityInput)
5290
5291 M_SetAndRunDispatch(WebResizeChoice)
5292 M_SetAndRunDispatch(WebResizeDimensionChoice)
5293 M_SetAndRunDispatch(WebResizeBeforeGammaCheck)
5294 M_SetAndRunDispatch(WebResizeScaleInput)
5295 M_SetAndRunDispatch(WebResizeFilterChoice)
5296
5297 M_Dispatch(OutputColorProfileIntentChoice)
5298
5299 M_JustSetDispatch(SaveQualityInput)
5300 M_JustSetDispatch(SaveResolutionInput)
5301 M_Dispatch(SaveFormatChoice)
5302 M_JustSetDispatch(SaveSamplingChoice)
5303 M_JustSetDispatch(IncludeExifCheck)
5304 M_Dispatch(EraseExifThumbnailCheck)
5305 M_JustSetDispatch(ImageRatingInput)
5306
5307 } else {
5308 fprintf(stderr,"(%s,%d) Unexpected ObjectName '%s'\n",
5309 __FILE__,__LINE__,ObjectName.toLocal8Bit().data());
5310 assert(0);
5311 }
5312 }
5313
5314 //==============================================================================
5315
5316 /*!
5317 * Reads Sidecar file
5318 * Places data into \var IptcData and \var XmpData
5319 */
ReadSidecar(const QString & Sidecar)5320 void ReadSidecar(const QString& Sidecar)
5321 {
5322 if (Sidecar.size() == 0) return;
5323
5324 if (Exiv2::ImageFactory::getType(Sidecar.toLocal8Bit().data()) == Exiv2::ImageType::none) {
5325 return;
5326 }
5327
5328 Exiv2::Image::AutoPtr hImage = Exiv2::ImageFactory::open(Sidecar.toLocal8Bit().data());
5329
5330 if (!hImage.get()) {
5331 return;
5332 }
5333 hImage->readMetadata();
5334 IptcData = hImage->iptcData();
5335 XmpData = hImage->xmpData();
5336 }
5337
5338 //==============================================================================
5339
5340 /*!
5341 * Sets ImageRating value, which is taken from Xmp.xmp.Rating
5342 * Places data into IptcData and XmpData
5343 */
SetRatingFromXmp()5344 void SetRatingFromXmp()
5345 {
5346 Exiv2::XmpData::const_iterator Pos;
5347 if ((Pos = XmpData.findKey(Exiv2::XmpKey("Xmp.xmp.Rating"))) != XmpData.end()) {
5348 std::stringstream str;
5349 str << *Pos;
5350 int Rating;
5351 sscanf(str.str().c_str(),"%d",&Rating);
5352 Settings->SetValue("ImageRating", Rating);
5353 }
5354 }
5355
5356 //==============================================================================
5357
5358 /*!
5359 * Sets Tags value, which is taken from Xmp.digiKam.TagsList
5360 * Places data into IptcData and XmpData
5361 */
SetTagsFromXmp()5362 void SetTagsFromXmp()
5363 {
5364 Exiv2::XmpData::const_iterator Pos;
5365 if ((Pos = XmpData.findKey(Exiv2::XmpKey("Xmp.digiKam.TagsList"))) != XmpData.end()) {
5366 std::stringstream str;
5367 str << *Pos;
5368 QString tags = str.str().c_str();
5369 MainWindow->TagsEditWidget->setPlainText(tags);
5370 }
5371 }
5372
5373 //==============================================================================
5374
5375 /*! Returns the type of an image file.
5376 \param filename
5377 path/filename of the image. An empty string is interpreted as the current global
5378 input file, i.e. InputFileNameList[0]. Note that \c CheckImageType never changes
5379 the value of InputFileNameList[0].
5380 \param width
5381 A pointer to a variable that holds the width of the image. Pass NULL if you
5382 do not need to know the width. If the width of the file cannot be determined,
5383 \c CheckImageType sets this variable to \c 0.
5384 \param height
5385 Same as \c width, but for the image height.
5386 \param dcRaw
5387 An optional pointer to an existing and properly initialized ptDcRaw object that the
5388 function should use. Note that the file associated with that dcraw gets changed to
5389 \c filename.
5390 */
CheckImageType(QString filename,uint16_t * width,uint16_t * height,ptDcRaw * dcRaw)5391 ptImageType CheckImageType(QString filename,
5392 uint16_t* width, uint16_t* height,
5393 ptDcRaw* dcRaw /*= NULL*/)
5394 {
5395 ptImageType result = itUndetermined;
5396 ptDcRaw* LocalDcRaw = NULL;
5397 bool UseLocalDcRaw = dcRaw == NULL;
5398
5399 // Setup dcraw
5400 if (UseLocalDcRaw) {
5401 LocalDcRaw = new ptDcRaw;
5402 Settings->ToDcRaw(LocalDcRaw);
5403 } else {
5404 LocalDcRaw = dcRaw;
5405 }
5406
5407 // Setup file name
5408 QStringList InputFileNameList = Settings->GetStringList("InputFileNameList");
5409 if (filename.isEmpty())
5410 filename = InputFileNameList[0];
5411
5412 if (filename != InputFileNameList[0]) {
5413 FREE(LocalDcRaw->m_UserSetting_InputFileName);
5414 LocalDcRaw->m_UserSetting_InputFileName =
5415 (char*) MALLOC(1+strlen(filename.toLocal8Bit().data()));
5416 ptMemoryError(LocalDcRaw->m_UserSetting_InputFileName,__FILE__,__LINE__);
5417 strcpy(LocalDcRaw->m_UserSetting_InputFileName,filename.toLocal8Bit().data());
5418 }
5419
5420 if (LocalDcRaw->Identify() == 0) {
5421 // we have a raw file
5422 result = itRaw;
5423 if (Settings->GetInt("UseThumbnail") == 0) {
5424 if (width != NULL) *width = LocalDcRaw->m_Width;
5425 if (height != NULL) *height = LocalDcRaw->m_Height;
5426 } else {
5427 if (width != NULL) *width = LocalDcRaw->m_ThumbWidth;
5428 if (height != NULL) *height = LocalDcRaw->m_ThumbHeight;
5429 }
5430
5431 } else {
5432 // Not a raw image. We use GraphicsMagick to check for valid Bitmaps.
5433 MagickWand* image = NewMagickWand();
5434 MagickPingImage(image, filename.toLocal8Bit().data());
5435
5436 ExceptionType MagickExcept;
5437 const char* MagickErrorMsg = MagickGetException(image, &MagickExcept);
5438
5439 if (MagickExcept == UndefinedException) {
5440 // image could be pinged without problems: we have a bitmap
5441 result = itBitmap;
5442 if (width != NULL) *width = MagickGetImageWidth(image);
5443 if (height != NULL) *height = MagickGetImageHeight(image);
5444
5445 } else {
5446 // not a supported image format
5447 printf("%s", MagickErrorMsg);
5448 result = itNotSupported;
5449 if (width != NULL) *width = 0;
5450 if (height != NULL) *height = 0;
5451 }
5452
5453 DestroyMagickWand(image);
5454 }
5455
5456 if (UseLocalDcRaw)
5457 DelAndNull(LocalDcRaw);
5458
5459 return result;
5460 }
5461
5462 //==============================================================================
5463 QList<QByteArray> ptUndoBuffer;
5464 QList<QByteArray> ptRedoBuffer;
5465 QByteArray ptClipboard;
5466
5467 ////////////////////////////////////////////////////////////////////////////////
5468 //
5469 // ptSettingsToQByteArray
5470 //
5471 // Copies Settings to a byte array
5472 //
5473 ////////////////////////////////////////////////////////////////////////////////
5474
ptSettingsToQByteArray()5475 QByteArray ptSettingsToQByteArray() {
5476 ptTempFile* tempFile = new ptTempFile();
5477 GFilterDM->WritePresetFile(tempFile->fileName());
5478 QFile file(tempFile->fileName());
5479 file.open(QIODevice::ReadOnly);
5480 QByteArray arr = file.readAll();
5481 file.close();
5482 delete tempFile;
5483 return arr;
5484 }
5485
5486
5487 ////////////////////////////////////////////////////////////////////////////////
5488 //
5489 // ptQByteArrayToSettings
5490 //
5491 // Loads Settings from a byte array
5492 //
5493 ////////////////////////////////////////////////////////////////////////////////
5494
ptQByteArrayToSettings(const QByteArray & arr)5495 void ptQByteArrayToSettings(const QByteArray &arr) {
5496 ptTempFile* tempFile = new ptTempFile();
5497 QFile file(tempFile->fileName());
5498 file.open(QIODevice::WriteOnly);
5499 file.write(arr);
5500 file.close();
5501 CB_OpenSettingsFile(tempFile->fileName());
5502 delete tempFile;
5503 }
5504
5505
5506 ////////////////////////////////////////////////////////////////////////////////
5507 //
5508 // ptAddUndo
5509 //
5510 // Adds current Settings to undo buffer
5511 //
5512 ////////////////////////////////////////////////////////////////////////////////
5513
ptAddUndo()5514 void ptAddUndo() {
5515 QByteArray arr = ptSettingsToQByteArray();
5516 ptUndoBuffer << arr;
5517 ptRedoBuffer.clear();
5518 }
5519
5520 ////////////////////////////////////////////////////////////////////////////////
5521 //
5522 // ptMakeUndo
5523 //
5524 // Loads Settings from undo buffer
5525 //
5526 ////////////////////////////////////////////////////////////////////////////////
5527
ptMakeUndo()5528 void ptMakeUndo() {
5529 if (ptUndoBuffer.isEmpty())
5530 return;
5531
5532 QByteArray arr = ptSettingsToQByteArray();
5533 ptRedoBuffer << arr;
5534 arr = ptUndoBuffer.last();
5535 ptUndoBuffer.removeLast();
5536
5537 ptQByteArrayToSettings(arr);
5538 }
5539
5540 ////////////////////////////////////////////////////////////////////////////////
5541 //
5542 // ptMakeRedo
5543 //
5544 // Loads Settings from redo buffer
5545 //
5546 ////////////////////////////////////////////////////////////////////////////////
5547
ptMakeRedo()5548 void ptMakeRedo() {
5549 if (ptRedoBuffer.isEmpty())
5550 return;
5551
5552 QByteArray arr = ptSettingsToQByteArray();
5553 ptUndoBuffer << arr;
5554 arr = ptRedoBuffer.last();
5555 ptRedoBuffer.removeLast();
5556
5557 ptQByteArrayToSettings(arr);
5558 }
5559
5560 ////////////////////////////////////////////////////////////////////////////////
5561 //
5562 // ptClearUndoRedo
5563 //
5564 // Clears undo-redo buffers
5565 //
5566 ////////////////////////////////////////////////////////////////////////////////
5567
ptClearUndoRedo()5568 void ptClearUndoRedo() {
5569 ptUndoBuffer.clear();
5570 ptRedoBuffer.clear();
5571 }
5572
5573 ////////////////////////////////////////////////////////////////////////////////
5574 //
5575 // ptMakeFullUndo
5576 //
5577 // Loads Settings from the first slot of undobuffer
5578 //
5579 ////////////////////////////////////////////////////////////////////////////////
5580
ptMakeFullUndo()5581 void ptMakeFullUndo() {
5582 if (ptUndoBuffer.isEmpty())
5583 return;
5584
5585 QByteArray arr = ptUndoBuffer.first();
5586 ptQByteArrayToSettings(arr);
5587 ptClearUndoRedo();
5588 }
5589
5590 ////////////////////////////////////////////////////////////////////////////////
5591 //
5592 // ptResetSettingsToDefault
5593 //
5594 // Loads initial Settings
5595 //
5596 ////////////////////////////////////////////////////////////////////////////////
5597
ptResetSettingsToDefault()5598 void ptResetSettingsToDefault() {
5599 ptAddUndo();
5600 CB_OpenSettingsFile(Settings->GetString("StartupSettingsFile"));
5601 }
5602
5603 ////////////////////////////////////////////////////////////////////////////////
5604 //
5605 // ptCopySettingsToClipboard
5606 //
5607 // Copies Settings to a "clipboard"
5608 //
5609 ////////////////////////////////////////////////////////////////////////////////
5610
ptCopySettingsToClipboard()5611 void ptCopySettingsToClipboard() {
5612 ptClipboard = ptSettingsToQByteArray();
5613 }
5614
5615 ////////////////////////////////////////////////////////////////////////////////
5616 //
5617 // ptPasteSettingsFromClipboard
5618 //
5619 // Pastes Settings from a "clipboard"
5620 //
5621 ////////////////////////////////////////////////////////////////////////////////
5622
ptPasteSettingsFromClipboard()5623 void ptPasteSettingsFromClipboard() {
5624 if (ptClipboard.isEmpty())
5625 return;
5626
5627 ptAddUndo();
5628 ptQByteArrayToSettings(ptClipboard);
5629 }
5630