Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_dlg_image_properties.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <QLabel>
10#include <QPushButton>
11
12#include <klocalizedstring.h>
13
14#include <KoColorSpace.h>
15#include <KoColorProfile.h>
17#include <KoColor.h>
18#include <kis_image.h>
19#include <kis_annotation.h>
20#include <kis_config.h>
22#include <kis_image_config.h>
23#include "kis_hdr_metadata.h"
25#include "kis_layer_utils.h"
28
31#include <kis_undo_adapter.h>
32#include <kis_types.h>
33#include <kis_group_layer.h>
34
36
38
40
42
59
60KisDlgImageProperties::KisDlgImageProperties(KisImageWSP image, KisDisplayColorConverter *colorConverter, QWidget *parent, const char *name)
61 : KoDialog(parent)
62 , d(new Private(colorConverter))
63{
66 setObjectName(name);
67 setCaption(i18n("Image Properties"));
68 m_page = new WdgImageProperties(this);
69
70 d->image = image;
71
73 resize(m_page->sizeHint());
74
75 m_page->lblWidthValue->setText(QString::number(image->width()));
76 m_page->lblHeightValue->setText(QString::number(image->height()));
77 m_page->lblLayerCount->setText(QString::number(image->nChildLayers()));
78
79 m_page->lblResolutionValue->setText(QLocale().toString(image->xRes()*72, 2)); // XXX: separate values for x & y?
80
81 //Set the canvas projection color: backgroundColor
82 KoColor background = d->image->defaultProjectionColor();
83 background.setOpacity(1.0);
84 m_page->bnBackgroundColor->setColor(background);
85 m_page->sldBackgroundColor->setRange(0.0,1.0,2);
86 m_page->sldBackgroundColor->setSingleStep(0.05);
87 m_page->sldBackgroundColor->setValue(d->image->defaultProjectionColor().opacityF());
88
89 connect(m_page->bnBackgroundColor, SIGNAL(changed(KoColor)), &d->compressor, SLOT(start()));
90 connect(m_page->sldBackgroundColor, SIGNAL(valueChanged(qreal)), &d->compressor, SLOT(start()));
91 connect(&d->compressor, SIGNAL(timeout()), this, SLOT(setCurrentColor()));
92
93 //Set the color space
94 m_page->colorSpaceSelector->setCurrentColorSpace(image->colorSpace());
95 m_page->chkConvertLayers->setChecked(KisConfig(true).convertLayerColorSpaceInProperties());
96
97 // fetch the proofing space
98 KisProofingConfigurationSP config = d->image->proofingConfiguration();
99 const bool hasImageLocalConfig = bool(config);
100
101 if (config) {
102 // create a copy of the original config
103 d->originalProofingConfig.reset(new KisProofingConfiguration(*config));
104 } else {
106 }
107
108 // enable proofing config widgets only when the image has its
109 // own config
110 m_page->chkSaveProofing->setChecked(hasImageLocalConfig);
111 connect(m_page->chkSaveProofing, &QCheckBox::toggled,
112 m_page->wdgProofingOptions, &KisProofingOptionsWidget::setEnabled);
113 m_page->wdgProofingOptions->setEnabled(m_page->chkSaveProofing->isChecked());
114
115 // we should reset to the global settings when when the checkbox
116 // is toggled
117 connect(m_page->chkSaveProofing, &QCheckBox::toggled,
119
120 // initialize the proofing configuration widget
121 m_page->wdgProofingOptions->setProofingConfig(config);
122 connect(d->colorConverter, SIGNAL(displayConfigurationChanged()), this, SLOT(updateDisplayConfigInfo()));
124
125 connect(m_page->wdgProofingOptions,
127 this,
129
130 d->hdrMetadataModel.setImageProfileHdrReferenceWhite(d->image->colorSpace()->profile()->hdrReferenceWhite());
131 d->hdrMetadataModel.setImageHdrReferenceWhiteMetadata(d->image->hdrReferenceWhiteLightLevel());
132 d->hdrMetadataModel.setClli(d->image->relativeContentLightLevelInformation());
133 d->hdrMetadataModel.setCvi(d->image->colorVolumeInformation());
134 connect(m_page->btnCalculateClli, &QPushButton::clicked, this, &KisDlgImageProperties::slotCalculateLightLevels);
135
136 KisWidgetConnectionUtils::connectControlState( m_page->cmbHdrReferenceWhite, &d->hdrMetadataModel, "referenceWhiteState", "referenceWhiteIndex");
137
138 KisWidgetConnectionUtils::connectControlState( m_page->gbxHdrReferenceWhite, &d->hdrMetadataModel, "referenceWhitePresentState", "referenceWhitePresent");
139
140 KisWidgetConnectionUtils::connectControlState( m_page->gbxContentLightLevel, &d->hdrMetadataModel, "clliPresentState", "clliPresent");
141 KisWidgetConnectionUtils::connectControl( m_page->spnMaxCll, &d->hdrMetadataModel, "maxContentLightLevel");
142 KisWidgetConnectionUtils::connectControl( m_page->spnMaxFall, &d->hdrMetadataModel, "maxFrameAverageLightLevel");
143 KisWidgetConnectionUtils::connectControlState( m_page->cmbLumiCalcType, &d->hdrMetadataModel, "clliCalculationTypeState", "clliCalculationType");
144
145 KisWidgetConnectionUtils::connectControl( m_page->gbxColorVolume, &d->hdrMetadataModel, "cviPresent");
146
147 KisWidgetConnectionUtils::connectControl( m_page->spnWhiteX, &d->hdrMetadataModel, "cviWhiteX");
148 KisWidgetConnectionUtils::connectControl( m_page->spnWhiteY, &d->hdrMetadataModel, "cviWhiteY");
149 KisWidgetConnectionUtils::connectControl( m_page->spnRedX, &d->hdrMetadataModel, "cviRedX");
150 KisWidgetConnectionUtils::connectControl( m_page->spnRedY, &d->hdrMetadataModel, "cviRedY");
151 KisWidgetConnectionUtils::connectControl( m_page->spnGreenX, &d->hdrMetadataModel, "cviGreenX");
152 KisWidgetConnectionUtils::connectControl( m_page->spnGreenY, &d->hdrMetadataModel, "cviGreenY");
153 KisWidgetConnectionUtils::connectControl( m_page->spnBlueX, &d->hdrMetadataModel, "cviBlueX");
154 KisWidgetConnectionUtils::connectControl( m_page->spnBlueY, &d->hdrMetadataModel, "cviBlueY");
155 KisWidgetConnectionUtils::connectControl( m_page->spnMinLuminance, &d->hdrMetadataModel, "cviMinLuminance");
156 KisWidgetConnectionUtils::connectControl( m_page->spnMaxLuminance, &d->hdrMetadataModel, "cviMaxLuminance");
157
158 KisWidgetConnectionUtils::connectControlState( m_page->cmbColorVolumePresets, &d->hdrMetadataModel, "cviEffectivePresetIndexState", "cviEffectivePresetIndex");
159
160 const bool hdr = d->image->colorSpace()->hasHighDynamicRange() ||
161 d->image->colorSpace()->profile()->getTransferCharacteristics() == TRC_ITU_R_BT_2100_0_PQ;
162 m_page->grpHdrMeta->setEnabled(hdr);
163
164 //annotations
165 vKisAnnotationSP_it beginIt = image->beginAnnotations();
166 vKisAnnotationSP_it endIt = image->endAnnotations();
167
168 vKisAnnotationSP_it it = beginIt;
169 while (it != endIt) {
170
171 if (!(*it) || (*it)->type().isEmpty()) {
172 dbgFile << "Warning: empty annotation";
173 it++;
174 continue;
175 }
176
177 m_page->cmbAnnotations->addItem((*it)->type());
178 it++;
179 }
180 connect(m_page->cmbAnnotations, SIGNAL(textActivated(QString)), SLOT(setAnnotation(QString)));
181 setAnnotation(m_page->cmbAnnotations->currentText());
182
183 connect(m_page->colorSpaceSelector,
184 SIGNAL(colorSpaceChanged(const KoColorSpace*)),
185 SLOT(slotColorSpaceChanged(const KoColorSpace*)));
186 slotColorSpaceChanged(d->image->colorSpace());
187}
188
190{
191 if (d->compressor.isActive()) {
192 d->compressor.stop();
194 }
195
196 delete m_page;
197}
198
200{
201 int resultCode = KoDialog::exec();
202
203 m_page->wdgProofingOptions->stopPendingUpdates();
204
205 if (resultCode == QDialog::Accepted) {
206 if (m_page->chkSaveProofing->isChecked()) {
207 d->image->setProofingConfiguration(m_page->wdgProofingOptions->currentProofingConfig());
208 } else {
209 d->image->setProofingConfiguration(nullptr);
210 }
211
212 std::optional<double> effectiveHdrReferenceWhite = d->hdrMetadataModel.effectiveReferenceWhite();
213 std::optional<KisRelativeContentLightLevelInformation> effectiveClli;
214 std::optional<KisColorVolumeInformation> effectiveCvi;
215
216 if (d->hdrMetadataModel.effectiveClliPresent()) {
217 effectiveClli = d->hdrMetadataModel.clliData.get();
218 }
219
220 if (d->hdrMetadataModel.cviPresent()) {
221 effectiveCvi = d->hdrMetadataModel.cviData.get();
222 }
223
224 if (effectiveHdrReferenceWhite != d->image->hdrReferenceWhiteLightLevel() ||
225 effectiveClli != d->image->relativeContentLightLevelInformation() ||
226 effectiveCvi != d->image->colorVolumeInformation()) {
227
228 KUndo2Command *cmd = new KisChangeImageHdrMetadataCommand(d->image, effectiveHdrReferenceWhite, effectiveClli, effectiveCvi);
230 }
231 } else {
232 d->image->setProofingConfiguration(d->originalProofingConfig);
233 }
234
235 KisConfig cfg(false);
236 cfg.setConvertLayerColorSpaceInProperties(m_page->chkConvertLayers->isChecked());
237
238 return resultCode;
239}
240
242{
243 return m_page->chkConvertLayers->isChecked();
244}
245
247{
248 return m_page->colorSpaceSelector->currentColorSpace();
249}
250
252{
253 KoColor background = m_page->bnBackgroundColor->color();
254 background.setOpacity(m_page->sldBackgroundColor->value());
256}
257
259{
260 if (m_page->chkSaveProofing->isChecked()) {
261 d->image->setProofingConfiguration(m_page->wdgProofingOptions->currentProofingConfig());
262 } else {
263 d->image->setProofingConfiguration(nullptr);
264 }
265}
266
268{
269 m_page->wdgProofingOptions->setDisplayConfigOptions(d->colorConverter->conversionOptions());
270}
271
273{
274 KisRelativeContentLightLevelInformation::CalculationType type = d->hdrMetadataModel.clliCalculationType();
276 new KisContentLightLevelProcessingVistor(type, d->image->bounds());
277
278 KisProcessingApplicator::ProcessingFlags flags =
280 KisProcessingApplicator applicator(d->image, d->image->rootLayer(), flags);
281
282 applicator.applyVisitorAllFrames(visitor);
283
284 // a poor-man implementation of a QFuture (which is Qt6-only),
285 // the proxy object will notify us manually when the visitor
286 // has completed its execution
288 connect(completionSignalProxy.get(), &FunctionToSignalProxy::timeout, this,
289 [visitor, model = &d->hdrMetadataModel, image = d->image]() {
290 auto info = visitor->contentLightLevelInformation();
291
292 model->setClli(info);
293 });
294
295 // add the command **after** the signal has been set up; this
296 // is not a QFuture, so it cannot store the actual "finished"
297 // state
298 applicator.applyCommand(new KisCommandUtils::LambdaCommand([completionSignalProxy]() {
299 completionSignalProxy->start();
300 return nullptr;
301 }));
302
303 applicator.end();
304}
305
307{
308 if (*d->image->profile() != *cs->profile() &&
310
311 m_page->wdgWarningNotice->setVisible(true);
312 m_page->wdgWarningNotice->setText(
313 m_page->wdgWarningNotice->changeImageProfileWarningText());
314 } else {
315 m_page->wdgWarningNotice->setVisible(false);
316 }
317}
318
320{
321 KisAnnotationSP annotation = d->image->annotation(type);
322 if (annotation) {
323 m_page->lblDescription->clear();
324 m_page->txtAnnotation->clear();
325 m_page->lblDescription->setText(annotation->description());
326 m_page->txtAnnotation->appendPlainText(annotation->displayText());
327 }
328 else {
329 m_page->lblDescription->clear();
330 m_page->txtAnnotation->clear();
331 }
332}
333
@ TRC_ITU_R_BT_2100_0_PQ
void setConvertLayerColorSpaceInProperties(bool value)
The KisContentLightLevelProcessingVistor class This processing visitor checks the projection of the r...
void slotColorSpaceChanged(const KoColorSpace *)
void setAnnotation(const QString &type)
KisDlgImageProperties(KisImageWSP image, KisDisplayColorConverter *colorConverter, QWidget *parent=0, const char *name=0)
QScopedPointer< Private > d
const KoColorSpace * colorSpace() const
KisProofingConfigurationSP defaultProofingconfiguration(bool requestDefault=false)
vKisAnnotationSP_it endAnnotations()
qint32 nChildLayers() const
const KoColorSpace * colorSpace() const
qint32 width() const
double xRes() const
qint32 height() const
vKisAnnotationSP_it beginAnnotations()
@ RECURSIVE_FRAME_TIMES
you might want to have the frame times be recursive, useful for group layers.
static void runSingleCommandStroke(KisImageSP image, KUndo2Command *cmd, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
runSingleCommandStroke creates a stroke and runs cmd in it. The text() field of cmd is used as a titl...
void applyCommand(KUndo2Command *command, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
void applyVisitorAllFrames(KisProcessingVisitorSP visitor, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
The KisProofingConfiguration struct Little struct that stores the proofing configuration for a given ...
void sigProofingConfigChanged(KisProofingConfigurationSP config)
virtual const KoColorProfile * profile() const =0
void setOpacity(quint8 alpha)
Definition KoColor.cpp:333
A dialog base class with standard buttons and predefined layouts.
Definition KoDialog.h:116
void setMainWidget(QWidget *widget)
Definition KoDialog.cpp:345
virtual void setCaption(const QString &caption)
Definition KoDialog.cpp:489
void setButtons(ButtonCodes buttonMask)
Definition KoDialog.cpp:195
void setDefaultButton(ButtonCode id)
Definition KoDialog.cpp:293
@ Ok
Show Ok button. (this button accept()s the dialog; result set to QDialog::Accepted)
Definition KoDialog.h:127
@ Cancel
Show Cancel-button. (this button reject()s the dialog; result set to QDialog::Rejected)
Definition KoDialog.h:130
This file is part of the Krita application in calligra.
#define dbgFile
Definition kis_debug.h:56
vKisAnnotationSP::iterator vKisAnnotationSP_it
Definition kis_types.h:181
void changeImageDefaultProjectionColor(KisImageSP image, const KoColor &color)
bool canChangeImageProfileInvisibly(KisImageSP image)
void connectControl(KisCompositeOpListWidget *widget, QObject *source, const char *property)
void connectControlState(QSpinBox *spinBox, QObject *source, const char *readStateProperty, const char *writeProperty)
The LambdaCommand struct is a shorthand for creation of AggregateCommand commands using C++ lambda fe...
Private(KisDisplayColorConverter *colorConverter)
KisProofingConfigurationSP originalProofingConfig
KisDisplayColorConverter * colorConverter