1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2008-08-04
7 * Description : RAW postProcessedImg widget.
8 *
9 * Copyright (C) 2008-2021 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 #include "rawpreview.h"
25
26 // Qt includes
27
28 #include <QString>
29 #include <QPainter>
30 #include <QPixmap>
31 #include <QFileInfo>
32 #include <QResizeEvent>
33 #include <QFontMetrics>
34 #include <QApplication>
35
36 // KDE includes
37
38 #include <klocalizedstring.h>
39
40 // Local includes
41
42 #include "digikam_debug.h"
43 #include "managedloadsavethread.h"
44 #include "editorcore.h"
45 #include "previewlayout.h"
46 #include "imagepreviewitem.h"
47
48 namespace DigikamRawImportNativePlugin
49 {
50
51 class Q_DECL_HIDDEN RawPreview::Private
52 {
53 public:
54
Private()55 explicit Private()
56 : currentFitWindowZoom(0.0),
57 thread (nullptr),
58 item (nullptr)
59 {
60 }
61
62 double currentFitWindowZoom;
63
64 QUrl url;
65
66 DImg demosaicedImg;
67
68 DRawDecoding settings;
69 ManagedLoadSaveThread* thread;
70 LoadingDescription loadingDesc;
71 ImagePreviewItem* item;
72 };
73
RawPreview(const QUrl & url,QWidget * const parent)74 RawPreview::RawPreview(const QUrl& url, QWidget* const parent)
75 : GraphicsDImgView(parent),
76 d (new Private)
77 {
78 d->item = new ImagePreviewItem();
79 setItem(d->item);
80
81 d->url = url;
82 d->thread = new ManagedLoadSaveThread;
83 d->thread->setLoadingPolicy(ManagedLoadSaveThread::LoadingPolicyFirstRemovePrevious);
84
85 // ------------------------------------------------------------
86
87 // set default zoom
88
89 layout()->fitToWindow();
90
91 installPanIcon();
92
93 setMinimumWidth(500);
94 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
95
96 // ------------------------------------------------------------
97
98 connect(d->thread, SIGNAL(signalImageLoaded(LoadingDescription,DImg)),
99 this, SLOT(slotImageLoaded(LoadingDescription,DImg)));
100
101 connect(d->thread, SIGNAL(signalLoadingProgress(LoadingDescription,float)),
102 this, SLOT(slotLoadingProgress(LoadingDescription,float)));
103 }
104
~RawPreview()105 RawPreview::~RawPreview()
106 {
107 delete d->item;
108 delete d;
109 }
110
setPostProcessedImage(const DImg & image)111 void RawPreview::setPostProcessedImage(const DImg& image)
112 {
113 d->item->setImage(image);
114 }
115
postProcessedImage() const116 DImg RawPreview::postProcessedImage() const
117 {
118 return d->item->image();
119 }
120
demosaicedImage() const121 DImg& RawPreview::demosaicedImage() const
122 {
123 return d->demosaicedImg;
124 }
125
setDecodingSettings(const DRawDecoding & settings)126 void RawPreview::setDecodingSettings(const DRawDecoding& settings)
127 {
128 if ((d->settings == settings) && d->thread->isRunning())
129 {
130 return;
131 }
132
133 // Save post processing settings.
134
135 d->settings = settings;
136
137 // All post processing settings will be used after demosaicing.
138
139 DRawDecoding demosaisedSettings = settings;
140 demosaisedSettings.resetPostProcessingSettings();
141
142 d->loadingDesc = LoadingDescription(d->url.toLocalFile(), demosaisedSettings);
143 d->thread->load(d->loadingDesc, ManagedLoadSaveThread::LoadingPolicyFirstRemovePrevious);
144 emit signalLoadingStarted();
145 }
146
exposureSettingsChanged()147 void RawPreview::exposureSettingsChanged()
148 {
149 viewport()->update();
150 }
151
ICCSettingsChanged()152 void RawPreview::ICCSettingsChanged()
153 {
154 viewport()->update();
155 }
156
cancelLoading()157 void RawPreview::cancelLoading()
158 {
159 d->thread->stopLoading(d->loadingDesc);
160 }
161
slotLoadingProgress(const LoadingDescription & description,float progress)162 void RawPreview::slotLoadingProgress(const LoadingDescription& description, float progress)
163 {
164 if (description.filePath != d->loadingDesc.filePath)
165 {
166 return;
167 }
168
169 emit signalLoadingProgress(progress);
170 }
171
slotImageLoaded(const LoadingDescription & description,const DImg & image)172 void RawPreview::slotImageLoaded(const LoadingDescription& description, const DImg& image)
173 {
174 if (description.filePath != d->loadingDesc.filePath)
175 {
176 return;
177 }
178
179 if (image.isNull())
180 {
181 QString msg = i18n("Cannot decode RAW image\n\"%1\"",
182 QFileInfo(d->loadingDesc.filePath).fileName());
183 QFontMetrics fontMt(font());
184 QRect fontRect = fontMt.boundingRect(0, 0, width(), height(), 0, msg);
185 QPixmap pix(fontRect.size());
186 pix.fill(qApp->palette().color(QPalette::Base));
187 QPainter p(&pix);
188 p.setPen(QPen(qApp->palette().color(QPalette::Text)));
189 p.drawText(0, 0, pix.width(), pix.height(), Qt::AlignCenter | Qt::TextWordWrap, msg);
190 p.end();
191
192 // three copies - but the image is small
193
194 setPostProcessedImage(DImg(pix.toImage()));
195 emit signalLoadingFailed();
196 }
197 else
198 {
199 d->demosaicedImg = image;
200 emit signalDemosaicedImage();
201
202 // NOTE: we will apply all Raw post processing corrections in RawImport class.
203 }
204 }
205
previewWidth() const206 int RawPreview::previewWidth() const
207 {
208 return d->item->image().width();
209 }
210
previewHeight() const211 int RawPreview::previewHeight() const
212 {
213 return d->item->image().height();
214 }
215
previewIsNull() const216 bool RawPreview::previewIsNull() const
217 {
218 return d->item->image().isNull();
219 }
220
resetPreview()221 void RawPreview::resetPreview()
222 {
223 d->item->setImage(DImg());
224 d->loadingDesc = LoadingDescription();
225 update();
226 }
227
previewToQImage() const228 QImage RawPreview::previewToQImage() const
229 {
230 return d->item->image().copyQImage();
231 }
232
233 } // namespace DigikamRawImportNativePlugin
234