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