~ubuntu-branches/ubuntu/trusty/digikam/trusty

« back to all changes in this revision

Viewing changes to core/utilities/imageeditor/core/editorcore_p.h

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2012-09-27 21:41:30 UTC
  • mfrom: (1.2.43)
  • mto: This revision was merged to the branch mainline in revision 86.
  • Revision ID: package-import@ubuntu.com-20120927214130-i8v3ufr21nesp29i
Tags: 4:3.0.0~beta1a-1
* New upstream release

* Fix "wrongly conflicts phonon-backend-vlc" dropped (Closes: #688142)
* debian/watch include download.kde.org

* digikam 3.0.0 uses features from unreleased kdegraphics >=4.10 & ships 
a private version of the kdegraphics libs - this is not the Debian way :-(
* Unsatisfactory Conflicts: libkipi8, libkexiv2-10, libkdcraw20, libksane0
* Suspend digikam-dbg >130Mb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ============================================================
 
2
 *
 
3
 * This file is a part of digiKam project
 
4
 * http://www.digikam.org
 
5
 *
 
6
 * Date        : 2003-01-15
 
7
 * Description : DImg interface for image editor
 
8
 *
 
9
 * Copyright (C) 2004-2012 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
#define OPACITY  0.7
 
25
#define RCOL     0xAA
 
26
#define GCOL     0xAA
 
27
#define BCOL     0xAA
 
28
 
 
29
namespace Digikam
 
30
{
 
31
 
 
32
class UndoManager;
 
33
 
 
34
class EditorCore::Private
 
35
{
 
36
 
 
37
public:
 
38
 
 
39
    class FileToSave
 
40
    {
 
41
    public:
 
42
 
 
43
        bool                    setExifOrientationTag;
 
44
        int                     historyStep;
 
45
 
 
46
        QString                 fileName;
 
47
        QString                 filePath;
 
48
        QString                 intendedFilePath;
 
49
        QString                 mimeType;
 
50
        QMap<QString, QVariant> ioAttributes;
 
51
        DImg                    image;
 
52
    };
 
53
 
 
54
public:
 
55
 
 
56
    Private() :
 
57
        valid(false),
 
58
        rotatedOrFlipped(false),
 
59
        exifOrient(false),
 
60
        doSoftProofing(false),
 
61
        width(0),
 
62
        height(0),
 
63
        origWidth(0),
 
64
        origHeight(0),
 
65
        selX(0),
 
66
        selY(0),
 
67
        selW(0),
 
68
        selH(0),
 
69
        gamma(0.0),
 
70
        brightness(0.0),
 
71
        contrast(0.0),
 
72
        zoom(1.0),
 
73
        displayingWidget(0),
 
74
        currentFileToSave(0),
 
75
        undoMan(0),
 
76
        expoSettings(0),
 
77
        thread(0)
 
78
    {
 
79
    }
 
80
 
 
81
    QMap<QString, QVariant> ioAttributes(IOFileSettings* const iofileSettings, const QString& givenMimeType) const;
 
82
 
 
83
    void applyBuiltinFilter(const DImgBuiltinFilter& filter, UndoAction* const action);
 
84
    void applyReversibleBuiltinFilter(const DImgBuiltinFilter& filter);
 
85
    void putImageData(uchar* const data, int w, int h, bool sixteenBit);
 
86
    void resetValues();
 
87
    void saveNext();
 
88
    void loadCurrent();
 
89
    void load(const LoadingDescription& description);
 
90
    void saveAs(const QString& file, IOFileSettings* const iofileSettings,
 
91
                bool setExifOrientationTag, const QString& givenMimeType,
 
92
                const VersionFileOperation& operation, const QString& intendedFilePath);
 
93
 
 
94
public:
 
95
 
 
96
    bool                       valid;
 
97
    bool                       rotatedOrFlipped;
 
98
    bool                       exifOrient;
 
99
    bool                       doSoftProofing;
 
100
 
 
101
    int                        width;
 
102
    int                        height;
 
103
    int                        origWidth;
 
104
    int                        origHeight;
 
105
    int                        selX;
 
106
    int                        selY;
 
107
    int                        selW;
 
108
    int                        selH;
 
109
 
 
110
    float                      gamma;
 
111
    float                      brightness;
 
112
    float                      contrast;
 
113
 
 
114
    double                     zoom;
 
115
 
 
116
    QWidget*                   displayingWidget;
 
117
 
 
118
    QList<FileToSave>          filesToSave;
 
119
    int                        currentFileToSave;
 
120
 
 
121
    DImg                       image;
 
122
    DImageHistory              resolvedInitialHistory;
 
123
    UndoManager*               undoMan;
 
124
 
 
125
    ICCSettingsContainer       cmSettings;
 
126
 
 
127
    ExposureSettingsContainer* expoSettings;
 
128
 
 
129
    SharedLoadSaveThread*      thread;
 
130
    LoadingDescription         currentDescription;
 
131
    LoadingDescription         nextRawDescription;
 
132
 
 
133
    IccTransform               monitorICCtrans;
 
134
};
 
135
 
 
136
void EditorCore::Private::putImageData(uchar* const data, int w, int h, bool sixteenBit)
 
137
{
 
138
    if (image.isNull())
 
139
    {
 
140
        kWarning() << "d->image is NULL";
 
141
        return;
 
142
    }
 
143
 
 
144
    if (!data)
 
145
    {
 
146
        kWarning() << "New image is NULL";
 
147
        return;
 
148
    }
 
149
 
 
150
    if (w == -1 && h == -1)
 
151
    {
 
152
        // New image size
 
153
        w = origWidth;
 
154
        h = origHeight;
 
155
    }
 
156
    else
 
157
    {
 
158
        // New image size == original size
 
159
        origWidth  = w;
 
160
        origHeight = h;
 
161
    }
 
162
 
 
163
    image.putImageData(w, h, sixteenBit, image.hasAlpha(), data);
 
164
}
 
165
 
 
166
void EditorCore::Private::resetValues()
 
167
{
 
168
    valid                  = false;
 
169
    currentDescription     = LoadingDescription();
 
170
    width                  = 0;
 
171
    height                 = 0;
 
172
    origWidth              = 0;
 
173
    origHeight             = 0;
 
174
    selX                   = 0;
 
175
    selY                   = 0;
 
176
    selW                   = 0;
 
177
    selH                   = 0;
 
178
    gamma                  = 1.0f;
 
179
    contrast               = 1.0f;
 
180
    brightness             = 0.0f;
 
181
    resolvedInitialHistory = DImageHistory();
 
182
    undoMan->clear();
 
183
}
 
184
 
 
185
void EditorCore::Private::saveNext()
 
186
{
 
187
    if (filesToSave.isEmpty() || currentFileToSave >= filesToSave.size())
 
188
    {
 
189
        return;
 
190
    }
 
191
 
 
192
    FileToSave& file = filesToSave[currentFileToSave];
 
193
    kDebug() << "Saving file" << file.filePath << "at" << file.historyStep;
 
194
 
 
195
    if (file.historyStep != -1)
 
196
    {
 
197
        // intermediate. Need to get data from undo manager
 
198
        int currentStep = EditorCore::defaultInstance()->getImageHistory().size() - 1;
 
199
        //kDebug() << "Requesting from undo manager data" << currentStep - file.historyStep << "steps back";
 
200
        undoMan->putImageDataAndHistory(&file.image, currentStep - file.historyStep);
 
201
    }
 
202
 
 
203
    QMap<QString, QVariant>::const_iterator it;
 
204
 
 
205
    for (it = file.ioAttributes.constBegin(); it != file.ioAttributes.constEnd(); ++it)
 
206
    {
 
207
        file.image.setAttribute(it.key(), it.value());
 
208
    }
 
209
 
 
210
    file.image.prepareMetadataToSave(file.intendedFilePath, file.mimeType, file.setExifOrientationTag);
 
211
    //kDebug() << "Adjusting image" << file.mimeType << file.fileName << file.setExifOrientationTag << file.ioAttributes
 
212
    //       << "image:" << file.image.size() << file.image.isNull();
 
213
 
 
214
    thread->save(file.image, file.filePath, file.mimeType);
 
215
}
 
216
 
 
217
void EditorCore::Private::applyReversibleBuiltinFilter(const DImgBuiltinFilter& filter)
 
218
{
 
219
    applyBuiltinFilter(filter, new UndoActionReversible(EditorCore::defaultInstance(), filter));
 
220
}
 
221
 
 
222
void EditorCore::Private::applyBuiltinFilter(const DImgBuiltinFilter& filter, UndoAction* const action)
 
223
{
 
224
    undoMan->addAction(action);
 
225
 
 
226
    filter.apply(image);
 
227
    image.addFilterAction(filter.filterAction());
 
228
 
 
229
    // many operations change the image size
 
230
    origWidth  = image.width();
 
231
    origHeight = image.height();
 
232
 
 
233
    EditorCore::defaultInstance()->setModified();
 
234
}
 
235
 
 
236
QMap<QString, QVariant> EditorCore::Private::ioAttributes(IOFileSettings* const iofileSettings,
 
237
                                                          const QString& mimeType) const
 
238
{
 
239
    QMap<QString, QVariant> attributes;
 
240
 
 
241
    // JPEG file format.
 
242
    if (mimeType.toUpper() == QString("JPG") || mimeType.toUpper() == QString("JPEG") ||
 
243
        mimeType.toUpper() == QString("JPE"))
 
244
    {
 
245
        attributes.insert("quality",     iofileSettings->JPEGCompression);
 
246
        attributes.insert("subsampling", iofileSettings->JPEGSubSampling);
 
247
    }
 
248
 
 
249
    // PNG file format.
 
250
    if (mimeType.toUpper() == QString("PNG"))
 
251
    {
 
252
        attributes.insert("quality", iofileSettings->PNGCompression);
 
253
    }
 
254
 
 
255
    // TIFF file format.
 
256
    if (mimeType.toUpper() == QString("TIFF") || mimeType.toUpper() == QString("TIF"))
 
257
    {
 
258
        attributes.insert("compress", iofileSettings->TIFFCompression);
 
259
    }
 
260
 
 
261
    // JPEG 2000 file format.
 
262
    if (mimeType.toUpper() == QString("JP2") || mimeType.toUpper() == QString("JPX") ||
 
263
        mimeType.toUpper() == QString("JPC") || mimeType.toUpper() == QString("PGX") ||
 
264
        mimeType.toUpper() == QString("J2K"))
 
265
    {
 
266
        if (iofileSettings->JPEG2000LossLess)
 
267
        {
 
268
            attributes.insert("quality", 100);    // LossLess compression
 
269
        }
 
270
        else
 
271
        {
 
272
            attributes.insert("quality", iofileSettings->JPEG2000Compression);
 
273
        }
 
274
    }
 
275
 
 
276
    // PGF file format.
 
277
    if (mimeType.toUpper() == QString("PGF"))
 
278
    {
 
279
        if (iofileSettings->PGFLossLess)
 
280
        {
 
281
            attributes.insert("quality", 0);    // LossLess compression
 
282
        }
 
283
        else
 
284
        {
 
285
            attributes.insert("quality", iofileSettings->PGFCompression);
 
286
        }
 
287
    }
 
288
 
 
289
    return attributes;
 
290
}
 
291
 
 
292
void EditorCore::Private::saveAs(const QString& filePath, IOFileSettings* const iofileSettings,
 
293
                                 bool setExifOrientationTag, const QString& givenMimeType,
 
294
                                 const VersionFileOperation& op, const QString& intendedFilePath)
 
295
{
 
296
    // No need to toggle off undo, redo or save action during saving using
 
297
    // signalUndoStateChanged(), this is will done by GUI implementation directly.
 
298
 
 
299
    EditorCore::defaultInstance()->emit signalSavingStarted(filePath);
 
300
 
 
301
    filesToSave.clear();
 
302
    currentFileToSave = 0;
 
303
 
 
304
    QString mimeType = givenMimeType;
 
305
 
 
306
    // This is possibly empty
 
307
    if (mimeType.isEmpty())
 
308
    {
 
309
        mimeType = EditorCore::defaultInstance()->getImageFormat();
 
310
    }
 
311
 
 
312
    if (op.tasks & VersionFileOperation::MoveToIntermediate ||
 
313
        op.tasks & VersionFileOperation::SaveAndDelete)
 
314
    {
 
315
        // The current file will stored away at a different name. Adjust history.
 
316
        image.getImageHistory().moveCurrentReferredImage(op.intermediateForLoadedFile.path,
 
317
                                                         op.intermediateForLoadedFile.fileName);
 
318
    }
 
319
 
 
320
    if (op.tasks & VersionFileOperation::Replace)
 
321
    {
 
322
        // The current file will be replaced. Remove hint at file path (file path will be a different image)
 
323
        image.getImageHistory().purgePathFromReferredImages(op.saveFile.path, op.saveFile.fileName);
 
324
    }
 
325
 
 
326
    QMap<int, VersionFileInfo>::const_iterator it;
 
327
 
 
328
    for (it = op.intermediates.begin(); it != op.intermediates.end(); ++it)
 
329
    {
 
330
        FileToSave file;
 
331
        file.fileName              = it.value().fileName;
 
332
        file.filePath              = it.value().filePath();
 
333
        file.intendedFilePath      = file.filePath;
 
334
        file.mimeType              = it.value().format;
 
335
        file.ioAttributes          = ioAttributes(iofileSettings, it.value().format);
 
336
        file.historyStep           = it.key();
 
337
        file.setExifOrientationTag = setExifOrientationTag;
 
338
        file.image                 = image.copyMetaData();
 
339
        filesToSave << file;
 
340
        kDebug() << "Saving intermediate at history step" << file.historyStep
 
341
                 << "to" << file.filePath << "(" << file.mimeType << ")";
 
342
    }
 
343
 
 
344
    // This shall be the last in the list. If not, adjust slotImageSaved
 
345
    FileToSave primary;
 
346
    primary.fileName              = op.saveFile.fileName;
 
347
    primary.filePath              = filePath; // can be temporary file path
 
348
    primary.intendedFilePath      = intendedFilePath;
 
349
    primary.mimeType              = mimeType;
 
350
    primary.ioAttributes          = ioAttributes(iofileSettings, mimeType);
 
351
    primary.historyStep           = -1; // special value
 
352
    primary.setExifOrientationTag = setExifOrientationTag;
 
353
    primary.image                 = image;
 
354
    filesToSave << primary;
 
355
 
 
356
    kDebug() << "Saving to :" << primary.filePath << "(" << primary.mimeType << ")";
 
357
 
 
358
    saveNext();
 
359
}
 
360
 
 
361
void EditorCore::Private::loadCurrent()
 
362
{
 
363
    thread->load(currentDescription,
 
364
                 SharedLoadSaveThread::AccessModeReadWrite,
 
365
                 SharedLoadSaveThread::LoadingPolicyFirstRemovePrevious);
 
366
 
 
367
    EditorCore::defaultInstance()->emit signalLoadingStarted(currentDescription.filePath);
 
368
}
 
369
 
 
370
void EditorCore::Private::load(const LoadingDescription& description)
 
371
{
 
372
    if (EditorToolIface::editorToolIface())
 
373
    {
 
374
        EditorToolIface::editorToolIface()->unLoadTool();
 
375
    }
 
376
 
 
377
    if (description != currentDescription)
 
378
    {
 
379
        resetValues();
 
380
        currentDescription = description;
 
381
        loadCurrent();
 
382
    }
 
383
    else
 
384
    {
 
385
        EditorCore::defaultInstance()->emit signalLoadingStarted(currentDescription.filePath);
 
386
        EditorCore::defaultInstance()->emit signalImageLoaded(currentDescription.filePath, true);
 
387
    }
 
388
}
 
389
 
 
390
}  // namespace Digikam