1 /**
2 * This file is a part of LuminanceHDR package.
3 * ----------------------------------------------------------------------
4 * Copyright (C) 2006,2007 Giuseppe Rota
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * ----------------------------------------------------------------------
20 *
21 * Original Work
22 * @author Giuseppe Rota <grota@users.sourceforge.net>
23 * Improvements, bugfixing
24 * @author Franco Comida <fcomida@users.sourceforge.net>
25 *
26 */
27
28 #include <QByteArray>
29 #include <QDebug>
30 #include <QFile>
31 #include <QMessageBox>
32 #include <QScopedPointer>
33 #include <QString>
34
35 #include "Common/LuminanceOptions.h"
36 #include "Core/TonemappingOptions.h"
37 #include "Fileformat/pfsoutldrimage.h"
38 #include "Viewers/IGraphicsPixmapItem.h"
39 #include "Viewers/LdrViewer.h"
40
41 #include <Libpfs/frame.h>
42 #include <Libpfs/utils/resourcehandlerlcms.h>
43
44 using namespace pfs;
45
46 namespace {
parseOptions(TonemappingOptions * opts,QString & caption)47 void parseOptions(TonemappingOptions *opts, QString &caption) {
48 if (opts == NULL) {
49 caption.clear();
50 } else {
51 TMOptionsOperations tmopts(opts);
52 // postfix = opts->getPostfix();
53 caption = opts->getCaption();
54 // exif_comment = tmopts.getExifComment();
55 }
56 }
57
doCMSTransform(QImage & qImage,bool doProof,bool doGamutCheck)58 bool doCMSTransform(QImage &qImage, bool doProof, bool doGamutCheck) {
59 LuminanceOptions luminance_opts;
60 QString monitor_fname = luminance_opts.getMonitorProfileFileName();
61 qDebug() << "Monitor profile: " << monitor_fname;
62 QString printer_fname = luminance_opts.getPrinterProfileFileName();
63 qDebug() << "Printer profile: " << printer_fname;
64
65 // Check Monitor Profile
66 if (monitor_fname.isEmpty()) {
67 return false;
68 }
69
70 utils::ScopedCmsProfile hsRGB(cmsCreate_sRGBProfile());
71 utils::ScopedCmsProfile hOut(cmsOpenProfileFromFile(
72 QFile::encodeName(monitor_fname).constData(), "r"));
73
74 utils::ScopedCmsProfile hProof;
75 utils::ScopedCmsTransform xform;
76
77 // Check whether the output profile is open
78 if (!hOut) {
79 QMessageBox::warning(0, QObject::tr("Warning"),
80 QObject::tr("I cannot open monitor profile. "
81 "Please select a different one."),
82 QMessageBox::Ok, QMessageBox::NoButton);
83
84 return false;
85 }
86
87 //
88 if (doProof && !printer_fname.isEmpty()) {
89 hProof.reset(cmsOpenProfileFromFile(
90 QFile::encodeName(printer_fname).constData(), "r"));
91 if (!hProof) {
92 QMessageBox::warning(0, QObject::tr("Warning"),
93 QObject::tr("I cannot open printer profile. "
94 "Please select a different one."),
95 QMessageBox::Ok, QMessageBox::NoButton);
96 doProof = false;
97 }
98 } else if (doProof) {
99 QMessageBox::warning(0, QObject::tr("Warning"),
100 QObject::tr("Please select a printer profile ."),
101 QMessageBox::Ok, QMessageBox::NoButton);
102 doProof = false;
103 }
104
105 if (doProof) {
106 cmsUInt32Number dwFlags =
107 doGamutCheck ? cmsFLAGS_SOFTPROOFING | cmsFLAGS_GAMUTCHECK
108 : cmsFLAGS_SOFTPROOFING;
109 cmsUInt16Number alarmCodes[cmsMAXCHANNELS] = {0};
110 alarmCodes[1] = 0xFFFF;
111 cmsSetAlarmCodes(alarmCodes);
112 xform.reset(cmsCreateProofingTransform(
113 hsRGB.data(), TYPE_BGRA_8, // TYPE_RGBA_8,
114 hOut.data(), TYPE_BGRA_8, // TYPE_RGBA_8,
115 hProof.data(), INTENT_PERCEPTUAL, INTENT_ABSOLUTE_COLORIMETRIC,
116 dwFlags));
117 } else {
118 xform.reset(cmsCreateTransform(hsRGB.data(),
119 TYPE_BGRA_8, // TYPE_RGBA_8,
120 hOut.data(),
121 TYPE_BGRA_8, // TYPE_RGBA_8,
122 INTENT_PERCEPTUAL, 0));
123 }
124
125 if (!xform) {
126 QMessageBox::warning(
127 0, QObject::tr("Warning"),
128 QObject::tr("I cannot perform the color transform. Please select a "
129 "different monitor profile."),
130 QMessageBox::Ok, QMessageBox::NoButton);
131
132 return false;
133 }
134
135 cmsDoTransform(xform.data(), qImage.bits(), qImage.bits(),
136 qImage.width() * qImage.height());
137
138 return true;
139 }
140 }
141
142 // This constructor is a bit of a mess!
LdrViewer(pfs::Frame * frame,TonemappingOptions * opts,QWidget * parent,bool ns,const float devicePixelRatio)143 LdrViewer::LdrViewer(pfs::Frame *frame, TonemappingOptions *opts,
144 QWidget *parent, bool ns, const float devicePixelRatio)
145 : GenericViewer(frame, parent, ns),
146 informativeLabel(new QLabel(mToolBar)),
147 mTonemappingOptions(opts) {
148 informativeLabel->setSizePolicy(QSizePolicy::Preferred,
149 QSizePolicy::Preferred);
150 informativeLabel->setMinimumSize(QSize(200, 36));
151 mToolBar->addWidget(informativeLabel);
152
153 setDevicePixelRatio(devicePixelRatio);
154
155 mPixmap->disableSelectionTool(); // disable by default crop functionalities
156
157 // I shouldn't call a virtual function straight from the constructor,
158 // but specifing correctly which version of this virtual function I want to
159 // call,
160 // I am safe
161 LdrViewer::setTonemappingOptions(opts);
162
163 QScopedPointer<QImage> temp_qimage(fromLDRPFStoQImage(getFrame()));
164 doCMSTransform(*temp_qimage, false, false);
165 setQImage(*temp_qimage);
166
167 updateView();
168 retranslateUi();
169 }
170
~LdrViewer()171 LdrViewer::~LdrViewer() {
172 #ifdef QT_DEBUG
173 qDebug() << "LdrViewer::~LdrViewer()";
174 #endif
175 }
176
retranslateUi()177 void LdrViewer::retranslateUi() {
178 parseOptions(mTonemappingOptions, caption);
179 informativeLabel->setText(tr("LDR image [%1 x %2]: %3")
180 .arg(getWidth())
181 .arg(getHeight())
182 .arg(caption));
183
184 GenericViewer::retranslateUi();
185 }
186
getFileNamePostFix()187 QString LdrViewer::getFileNamePostFix() {
188 return mTonemappingOptions ? mTonemappingOptions->getPostfix() : QString();
189 }
190
getExifComment()191 QString LdrViewer::getExifComment() {
192 if (mTonemappingOptions) {
193 TMOptionsOperations tm_ops(mTonemappingOptions);
194 return tm_ops.getExifComment();
195 } else {
196 return QString();
197 }
198 }
199
updatePixmap()200 void LdrViewer::updatePixmap() {
201 #ifdef QT_DEBUG
202 qDebug() << "void LdrViewer::updatePixmap()";
203 #endif
204
205 QScopedPointer<QImage> temp_qimage(fromLDRPFStoQImage(getFrame()));
206
207 doCMSTransform(*temp_qimage, false, false);
208 mPixmap->setPixmap(QPixmap::fromImage(*temp_qimage));
209
210 parseOptions(mTonemappingOptions, caption);
211 informativeLabel->setText(tr("LDR image [%1 x %2]: %3")
212 .arg(getWidth())
213 .arg(getHeight())
214 .arg(caption));
215 }
216
setTonemappingOptions(TonemappingOptions * tmopts)217 void LdrViewer::setTonemappingOptions(TonemappingOptions *tmopts) {
218 mTonemappingOptions = tmopts;
219
220 parseOptions(tmopts, caption);
221 setWindowTitle(caption);
222 // setToolTip(caption);
223 informativeLabel->setText(tr("LDR image [%1 x %2]: %3")
224 .arg(getWidth())
225 .arg(getHeight())
226 .arg(caption));
227 }
228
getTonemappingOptions()229 TonemappingOptions *LdrViewer::getTonemappingOptions() {
230 return mTonemappingOptions;
231 }
232
233 //! \brief returns max value of the handled frame
getMaxLuminanceValue()234 float LdrViewer::getMaxLuminanceValue() { return 1.0f; }
235
236 //! \brief returns min value of the handled frame
getMinLuminanceValue()237 float LdrViewer::getMinLuminanceValue() { return 0.0f; }
238
doSoftProofing(bool doGamutCheck)239 void LdrViewer::doSoftProofing(bool doGamutCheck) {
240 QScopedPointer<QImage> src_image(fromLDRPFStoQImage(getFrame()));
241 if (doCMSTransform(*src_image, true, doGamutCheck)) {
242 mPixmap->setPixmap(QPixmap::fromImage(*src_image));
243 }
244 }
245
undoSoftProofing()246 void LdrViewer::undoSoftProofing() {
247 QScopedPointer<QImage> src_image(fromLDRPFStoQImage(getFrame()));
248 if (doCMSTransform(*src_image, false, false)) {
249 mPixmap->setPixmap(QPixmap::fromImage(*src_image));
250 }
251 }
252