digiKam
editorcore_p.h
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date : 2003-01-15
7  * Description : DImg interface for image editor
8  *
9  * Copyright (C) 2004-2022 by Gilles Caulier <caulier dot gilles at gmail dot com>
10  *
11  * This program is free software; you can redistribute it
12  * and/or modify it under the terms of the GNU General
13  * Public License as published by the Free Software Foundation;
14  * either version 2, or (at your option)
15  * any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * ============================================================ */
23 
24 #ifndef DIGIKAM_IMAGE_EDITOR_CORE_PRIVATE_H
25 #define DIGIKAM_IMAGE_EDITOR_CORE_PRIVATE_H
26 
27 // Local includes
28 
29 #include "digikam_config.h"
30 #include "digikam_debug.h"
31 #include "dimgbuiltinfilter.h"
32 #include "undomanager.h"
33 #include "undoaction.h"
34 #include "undostate.h"
35 #include "iccmanager.h"
36 #include "iccsettingscontainer.h"
37 #include "icctransform.h"
38 #include "exposurecontainer.h"
39 #include "iofilesettings.h"
40 #include "sharedloadsavethread.h"
41 #include "dmetadata.h"
42 #include "editortooliface.h"
43 #include "dimg.h"
44 #include "dimgfiltergenerator.h"
45 #include "bcgfilter.h"
46 #include "equalizefilter.h"
47 #include "dimgfiltermanager.h"
48 #include "versionmanager.h"
49 #include "colorcorrectiondlg.h"
50 #include "dpluginloader.h"
51 #include "dpluginrawimport.h"
52 #include "editortool.h"
53 
54 namespace Digikam
55 {
56 
57 class UndoManager;
58 
59 class Q_DECL_HIDDEN EditorCore::Private
60 {
61 
62 public:
63 
64  class Q_DECL_HIDDEN FileToSave
65  {
66  public:
67 
70 
71  QString fileName;
72  QString filePath;
74  QString mimeType;
75  QMap<QString, QVariant> ioAttributes;
77  };
78 
79 public:
80 
82  : valid (false),
83  rotatedOrFlipped (false),
84  exifOrient (false),
85  doSoftProofing (false),
86  width (0),
87  height (0),
88  origWidth (0),
89  origHeight (0),
90  selX (0),
91  selY (0),
92  selW (0),
93  selH (0),
94  zoom (1.0),
95  displayingWidget (nullptr),
96  currentFileToSave(0),
97  undoMan (nullptr),
98  expoSettings (nullptr),
99  thread (nullptr),
100  rawPlugin (nullptr)
101  {
102  }
103 
104  QMap<QString, QVariant> ioAttributes(IOFileSettings* const iofileSettings, const QString& givenMimeType) const;
105 
106  void applyBuiltinFilter(const DImgBuiltinFilter& filter, UndoAction* const action);
107  void applyReversibleBuiltinFilter(const DImgBuiltinFilter& filter);
108  void putImageData(uchar* const data, int w, int h, bool sixteenBit);
109  void resetValues();
110  void saveNext();
111  void loadCurrent();
112  void load(const LoadingDescription& description);
113  void saveAs(const QString& file, IOFileSettings* const iofileSettings,
114  bool setExifOrientationTag, const QString& givenMimeType,
115  const VersionFileOperation& operation, const QString& intendedFilePath);
116 
117 public:
118 
119  bool valid;
123 
124  int width;
125  int height;
128  int selX;
129  int selY;
130  int selW;
131  int selH;
132 
133  double zoom;
134 
136 
139 
143 
145 
147 
149 
151 
153 };
154 
155 void EditorCore::Private::putImageData(uchar* const data, int w, int h, bool sixteenBit)
156 {
157  if (image.isNull())
158  {
159  qCWarning(DIGIKAM_GENERAL_LOG) << "d->image is NULL";
160  return;
161  }
162 
163  if (!data)
164  {
165  qCWarning(DIGIKAM_GENERAL_LOG) << "New image is NULL";
166  return;
167  }
168 
169  if ((w == -1) && (h == -1))
170  {
171  // New image size
172 
173  w = origWidth;
174  h = origHeight;
175  }
176  else
177  {
178  // New image size == original size
179 
180  origWidth = w;
181  origHeight = h;
182  }
183 
184  image.putImageData(w, h, sixteenBit, image.hasAlpha(), data);
185  image.setAttribute(QLatin1String("originalSize"), image.size());
186 }
187 
189 {
190  valid = false;
191  currentDescription = LoadingDescription();
192  width = 0;
193  height = 0;
194  origWidth = 0;
195  origHeight = 0;
196  selX = 0;
197  selY = 0;
198  selW = 0;
199  selH = 0;
200  resolvedInitialHistory = DImageHistory();
201  undoMan->clear();
202 }
203 
205 {
206  if (filesToSave.isEmpty() || (currentFileToSave >= filesToSave.size()))
207  {
208  return;
209  }
210 
211  FileToSave& file = filesToSave[currentFileToSave];
212  qCDebug(DIGIKAM_GENERAL_LOG) << "Saving file" << file.filePath << "at" << file.historyStep;
213 
214  if (file.historyStep != -1)
215  {
216  // intermediate. Need to get data from undo manager
217 
218  int currentStep = EditorCore::defaultInstance()->getItemHistory().size() - 1;
219 
220  //qCDebug(DIGIKAM_GENERAL_LOG) << "Requesting from undo manager data" << currentStep - file.historyStep << "steps back";
221 
222  undoMan->putImageDataAndHistory(&file.image, currentStep - file.historyStep);
223  }
224 
225  QMap<QString, QVariant>::const_iterator it;
226 
227  for (it = file.ioAttributes.constBegin() ; it != file.ioAttributes.constEnd() ; ++it)
228  {
229  file.image.setAttribute(it.key(), it.value());
230  }
231 
233 
234  //qCDebug(DIGIKAM_GENERAL_LOG) << "Adjusting image" << file.mimeType << file.fileName << file.setExifOrientationTag << file.ioAttributes
235  // << "image:" << file.image.size() << file.image.isNull();
236 
237  thread->save(file.image, file.filePath, file.mimeType);
238 }
239 
241 {
242  applyBuiltinFilter(filter, new UndoActionReversible(EditorCore::defaultInstance(), filter));
243 }
244 
246 {
247  undoMan->addAction(action);
248 
249  filter.apply(image);
250  image.addFilterAction(filter.filterAction());
251 
252  // many operations change the image size
253 
254  origWidth = image.width();
255  origHeight = image.height();
256  width = origWidth;
257  height = origHeight;
258 
259  image.setAttribute(QLatin1String("originalSize"), image.size());
261 }
262 
263 QMap<QString, QVariant> EditorCore::Private::ioAttributes(IOFileSettings* const iofileSettings,
264  const QString& mimeType) const
265 {
266  QMap<QString, QVariant> attributes;
267 
268  // JPEG file format.
269 
270  if ((mimeType.toUpper() == QLatin1String("JPG")) ||
271  (mimeType.toUpper() == QLatin1String("JPEG")) ||
272  (mimeType.toUpper() == QLatin1String("JPE")))
273  {
274  attributes.insert(QLatin1String("quality"), iofileSettings->JPEGCompression);
275  attributes.insert(QLatin1String("subsampling"), iofileSettings->JPEGSubSampling);
276  }
277 
278  // PNG file format.
279 
280  if (mimeType.toUpper() == QLatin1String("PNG"))
281  {
282  attributes.insert(QLatin1String("quality"), iofileSettings->PNGCompression);
283  }
284 
285  // TIFF file format.
286 
287  if ((mimeType.toUpper() == QLatin1String("TIFF")) ||
288  (mimeType.toUpper() == QLatin1String("TIF")))
289  {
290  attributes.insert(QLatin1String("compress"), iofileSettings->TIFFCompression);
291  }
292 
293  // JPEG 2000 file format.
294 
295 #ifdef HAVE_JASPER
296 
297  if ((mimeType.toUpper() == QLatin1String("JP2")) ||
298  (mimeType.toUpper() == QLatin1String("JPX")) ||
299  (mimeType.toUpper() == QLatin1String("JPC")) ||
300  (mimeType.toUpper() == QLatin1String("PGX")) ||
301  (mimeType.toUpper() == QLatin1String("J2K")))
302  {
303  if (iofileSettings->JPEG2000LossLess)
304  {
305  attributes.insert(QLatin1String("quality"), 100); // LossLess compression
306  }
307  else
308  {
309  attributes.insert(QLatin1String("quality"), iofileSettings->JPEG2000Compression);
310  }
311  }
312 
313 #endif // HAVE_JASPER
314 
315  // HEIF file format.
316 
317 #ifdef HAVE_X265
318 
319  if ((mimeType.toUpper() == QLatin1String("HEIC")) ||
320  (mimeType.toUpper() == QLatin1String("HEIF")))
321  {
322  if (iofileSettings->HEIFLossLess)
323  {
324  attributes.insert(QLatin1String("quality"), 0); // LossLess compression
325  }
326  else
327  {
328  attributes.insert(QLatin1String("quality"), iofileSettings->HEIFCompression);
329  }
330  }
331 
332 #endif // HAVE_X265
333 
334  // PGF file format.
335 
336  if (mimeType.toUpper() == QLatin1String("PGF"))
337  {
338  if (iofileSettings->PGFLossLess)
339  {
340  attributes.insert(QLatin1String("quality"), 0); // LossLess compression
341  }
342  else
343  {
344  attributes.insert(QLatin1String("quality"), iofileSettings->PGFCompression);
345  }
346  }
347 
348  return attributes;
349 }
350 
351 void EditorCore::Private::saveAs(const QString& filePath, IOFileSettings* const iofileSettings,
352  bool setExifOrientationTag, const QString& givenMimeType,
353  const VersionFileOperation& op, const QString& intendedFilePath)
354 {
355  // No need to toggle off undo, redo or save action during saving using
356  // signalUndoStateChanged(), this is will done by GUI implementation directly.
357 
359 
360  filesToSave.clear();
361  currentFileToSave = 0;
362 
363  QString mimeType = givenMimeType;
364 
365  // This is possibly empty
366 
367  if (mimeType.isEmpty())
368  {
370  }
371 
374  {
375  // The current file will stored away at a different name. Adjust history.
376 
377  image.getItemHistory().moveCurrentReferredImage(op.intermediateForLoadedFile.path,
379  }
380 
382  {
383  // The current file will be replaced. Remove hint at file path (file path will be a different image)
384 
385  image.getItemHistory().purgePathFromReferredImages(op.saveFile.path, op.saveFile.fileName);
386  }
387 
388  QMap<int, VersionFileInfo>::const_iterator it;
389 
390  for (it = op.intermediates.begin() ; it != op.intermediates.end() ; ++it)
391  {
392  FileToSave file;
393  file.fileName = it.value().fileName;
394  file.filePath = it.value().filePath();
395  file.intendedFilePath = file.filePath;
396  file.mimeType = it.value().format;
397  file.ioAttributes = ioAttributes(iofileSettings, it.value().format);
398  file.historyStep = it.key();
399  file.setExifOrientationTag = setExifOrientationTag;
400  file.image = image.copyMetaData();
401  filesToSave << file;
402  qCDebug(DIGIKAM_GENERAL_LOG) << "Saving intermediate at history step" << file.historyStep
403  << "to" << file.filePath << "(" << file.mimeType << ")";
404  }
405 
406  // This shall be the last in the list. If not, adjust slotImageSaved
407 
408  FileToSave primary;
409  primary.fileName = op.saveFile.fileName;
410  primary.filePath = filePath; // can be temporary file path
411  primary.intendedFilePath = intendedFilePath;
412  primary.mimeType = mimeType;
413  primary.ioAttributes = ioAttributes(iofileSettings, mimeType);
414  primary.historyStep = -1; // special value
415  primary.setExifOrientationTag = setExifOrientationTag;
416  primary.image = image;
417  filesToSave << primary;
418 
419  qCDebug(DIGIKAM_GENERAL_LOG) << "Saving to :" << primary.filePath << "(" << primary.mimeType << ")";
420 
421  saveNext();
422 }
423 
425 {
426  thread->load(currentDescription,
429 
430  emit EditorCore::defaultInstance()->signalLoadingStarted(currentDescription.filePath);
431 }
432 
434 {
436  {
438  }
439 
440  if (description != currentDescription)
441  {
442  resetValues();
443  currentDescription = description;
444  loadCurrent();
445  }
446  else
447  {
448  emit EditorCore::defaultInstance()->signalLoadingStarted(currentDescription.filePath);
449  emit EditorCore::defaultInstance()->signalImageLoaded(currentDescription.filePath, true);
450  }
451 }
452 
453 } // namespace Digikam
454 
455 #endif // DIGIKAM_IMAGE_EDITOR_CORE_PRIVATE_H
Definition: dimagehistory.h:49
int size() const
Returns the number of entries.
Definition: dimagehistory.cpp:134
Definition: dimgbuiltinfilter.h:44
FilterAction filterAction() const
Definition: dimgbuiltinfilter.cpp:235
void apply(DImg &image) const
Definition: dimgbuiltinfilter.cpp:169
Definition: dimg.h:62
bool isNull() const
Definition: dimg_props.cpp:31
QSize size() const
Definition: dimg_props.cpp:46
void setAttribute(const QString &key, const QVariant &value)
Definition: dimg_props.cpp:223
void putImageData(uint width, uint height, bool sixteenBit, bool alpha, uchar *const data, bool copyData=true)
Definition: dimg_data.cpp:70
void prepareMetadataToSave(const QString &intendedDestPath, const QString &destMimeType, const QString &originalFileName=QString(), PrepareMetadataFlags flags=PrepareMetadataFlagsAll)
Definition: dimg_metadata.cpp:126
bool hasAlpha() const
Definition: dimg_props.cpp:76
DImg copyMetaData() const
Definition: dimg_copy.cpp:46
Definition: dpluginrawimport.h:39
Definition: editorcore_p.h:65
QString filePath
Definition: editorcore_p.h:72
QString mimeType
Definition: editorcore_p.h:74
int historyStep
Definition: editorcore_p.h:69
QString intendedFilePath
Definition: editorcore_p.h:73
QString fileName
Definition: editorcore_p.h:71
bool setExifOrientationTag
Definition: editorcore_p.h:68
QMap< QString, QVariant > ioAttributes
Definition: editorcore_p.h:75
DImg image
Definition: editorcore_p.h:76
Definition: editorcore_p.h:60
LoadingDescription currentDescription
Definition: editorcore_p.h:152
void resetValues()
Definition: editorcore_p.h:188
bool valid
Definition: editorcore_p.h:119
QMap< QString, QVariant > ioAttributes(IOFileSettings *const iofileSettings, const QString &givenMimeType) const
Definition: editorcore_p.h:263
UndoManager * undoMan
Definition: editorcore_p.h:142
int currentFileToSave
Definition: editorcore_p.h:138
void applyBuiltinFilter(const DImgBuiltinFilter &filter, UndoAction *const action)
Definition: editorcore_p.h:245
SharedLoadSaveThread * thread
Definition: editorcore_p.h:148
int selH
Definition: editorcore_p.h:131
double zoom
Definition: editorcore_p.h:133
int selY
Definition: editorcore_p.h:129
int height
Definition: editorcore_p.h:125
ExposureSettingsContainer * expoSettings
Definition: editorcore_p.h:146
int width
Definition: editorcore_p.h:124
bool exifOrient
Definition: editorcore_p.h:121
ICCSettingsContainer cmSettings
Definition: editorcore_p.h:144
DImageHistory resolvedInitialHistory
Definition: editorcore_p.h:141
void loadCurrent()
Definition: editorcore_p.h:424
DPluginRawImport * rawPlugin
Definition: editorcore_p.h:150
int selX
Definition: editorcore_p.h:128
void saveAs(const QString &file, IOFileSettings *const iofileSettings, bool setExifOrientationTag, const QString &givenMimeType, const VersionFileOperation &operation, const QString &intendedFilePath)
Definition: editorcore_p.h:351
QWidget * displayingWidget
Definition: editorcore_p.h:135
void putImageData(uchar *const data, int w, int h, bool sixteenBit)
Definition: editorcore_p.h:155
int selW
Definition: editorcore_p.h:130
Private()
Definition: editorcore_p.h:81
bool doSoftProofing
Definition: editorcore_p.h:122
void applyReversibleBuiltinFilter(const DImgBuiltinFilter &filter)
Definition: editorcore_p.h:240
int origHeight
Definition: editorcore_p.h:127
int origWidth
Definition: editorcore_p.h:126
bool rotatedOrFlipped
Definition: editorcore_p.h:120
void saveNext()
Definition: editorcore_p.h:204
DImg image
Definition: editorcore_p.h:140
QList< FileToSave > filesToSave
Definition: editorcore_p.h:137
void load(const LoadingDescription &description)
Definition: editorcore_p.h:433
Definition: editorcore.h:58
int origWidth() const
Definition: editorcore.cpp:575
void setModified()
Definition: editorcore.cpp:520
int height() const
Definition: editorcore.cpp:570
void signalImageLoaded(const QString &filePath, bool success)
void signalSavingStarted(const QString &filename)
bool sixteenBit() const
Definition: editorcore.cpp:590
QString getImageFormat() const
Definition: editorcore.cpp:824
int origHeight() const
Definition: editorcore.cpp:580
static EditorCore * defaultInstance()
Definition: editorcore.cpp:53
void signalLoadingStarted(const QString &filename)
int width() const
Definition: editorcore.cpp:565
DImageHistory getItemHistory() const
Definition: editorcore.cpp:681
void unLoadTool()
Definition: editortooliface.cpp:190
static EditorToolIface * editorToolIface()
Definition: editortooliface.cpp:75
Definition: exposurecontainer.h:39
Definition: iccsettingscontainer.h:44
Definition: iofilesettings.h:36
int PGFCompression
PGF quality value.
Definition: iofilesettings.h:81
bool JPEG2000LossLess
JPEG2000 lossless compression.
Definition: iofilesettings.h:78
bool TIFFCompression
TIFF deflate compression.
Definition: iofilesettings.h:72
bool PGFLossLess
PGF lossless compression.
Definition: iofilesettings.h:84
int HEIFCompression
HEIF quality value.
Definition: iofilesettings.h:87
int JPEGCompression
JPEG quality value.
Definition: iofilesettings.h:58
int PNGCompression
PNG compression value.
Definition: iofilesettings.h:69
int JPEGSubSampling
JPEG chroma sub-sampling value.
Definition: iofilesettings.h:66
int JPEG2000Compression
JPEG2000 quality value.
Definition: iofilesettings.h:75
bool HEIFLossLess
HEIF lossless compression.
Definition: iofilesettings.h:90
@ AccessModeReadWrite
Definition: loadsavethread.h:135
Definition: loadingdescription.h:45
@ LoadingPolicyFirstRemovePrevious
Definition: managedloadsavethread.h:49
Definition: sharedloadsavethread.h:35
Definition: undoaction.h:100
Definition: undoaction.h:66
Definition: undomanager.h:47
QString path
Definition: versionfileoperation.h:64
QString fileName
Definition: versionfileoperation.h:65
Definition: versionfileoperation.h:72
VersionFileInfo saveFile
Definition: versionfileoperation.h:113
QMap< int, VersionFileInfo > intermediates
Definition: versionfileoperation.h:117
VersionFileInfo intermediateForLoadedFile
Definition: versionfileoperation.h:115
@ SaveAndDelete
Similar to Replace, but the new file name differs from the old one, which should be removed.
Definition: versionfileoperation.h:99
@ MoveToIntermediate
Move loadedFile to loadedFileToIntermediate.
Definition: versionfileoperation.h:101
@ Replace
loadedFile and saveFile are the same - replace. Excludes NewFile.
Definition: versionfileoperation.h:97
Tasks tasks
Definition: versionfileoperation.h:109
Definition: piwigotalker.h:48
Definition: datefolderview.cpp:43