Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_png_export.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2005 Cyrille Berger <cberger@cberger.net>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "kis_png_export.h"
8
9#include <QCheckBox>
10#include <QSlider>
11#include <QApplication>
12
13#include <kpluginfactory.h>
14
15#include <KoColorSpace.h>
18#include <KoColorProfile.h>
21
23
25#include <kis_paint_device.h>
26#include <KisDocument.h>
27#include <kis_image.h>
28#include <kis_paint_layer.h>
29#include <kis_group_layer.h>
30#include <kis_config.h>
31#include <kis_meta_data_store.h>
34#include "kis_png_converter.h"
35#include <kis_iterator_ng.h>
36
37K_PLUGIN_FACTORY_WITH_JSON(KisPNGExportFactory, "krita_png_export.json", registerPlugin<KisPNGExport>();)
38
39KisPNGExport::KisPNGExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent)
40{
41}
42
46
48{
49 KisImageSP image = document->savingImage();
50
51 KisPNGOptions options;
52
53 options.alpha = configuration->getBool("alpha", true);
54 options.interlace = configuration->getBool("interlaced", false);
55 options.compression = configuration->getInt("compression", 3);
56 options.tryToSaveAsIndexed = configuration->getBool("indexed", false);
58 c.fromQColor(Qt::white);
59 options.transparencyFillColor = configuration->getColor("transparencyFillcolor", c).toQColor();
60 options.forceSRGB = configuration->getBool("forceSRGB", true);
61 options.storeAuthor = configuration->getBool("storeAuthor", false);
62 options.storeMetaData = configuration->getBool("storeMetaData", false);
63 options.downsample = configuration->getBool("downsample", false);
64 options.storeColorSpaceInfo = configuration->getBool("storeColorSpaceInfo", true);
65 options.writeCicpIfPossible = configuration->getBool("writeCicpIfPossible", false);
66 options.storeExtraColorChunks = configuration->getBool("storeExtraColorChunks", false);
67
68 const QString conversionOption = configuration->getString("floatingPointConversionOption", "KeepSame");
69 options.convertFloatToRec2020 = false;
70 if (conversionOption == "Rec2100PQ") {
71 options.convertFloatToRec2020 = true;
73 } else if (conversionOption == "Rec2100HLG") {
74 options.convertFloatToRec2020 = true;
76 } else if (conversionOption == "ApplyPQ") {
78 } else if (conversionOption == "ApplyHLG") {
80 } else if (conversionOption == "ApplySMPTE428") {
82 }
83
84 vKisAnnotationSP_it beginIt = image->beginAnnotations();
85 vKisAnnotationSP_it endIt = image->endAnnotations();
86
88 eIV.visit(image->rootLayer().data());
89 KisMetaData::Store *eI = 0;
90 if (eIV.metaDataCount() == 1) {
91 eI = eIV.exifInfo();
92 }
93 if (eI) {
95 eI = copy;
96 }
97
98 KisPNGConverter pngConverter(document);
99
100 KisImportExportErrorCode res = pngConverter.buildFile(io, image->bounds(), image->xRes(), image->yRes(), image->projection(), beginIt, endIt, options, eI);
101 delete eI;
102 dbgFile << " Result =" << res;
103 return res;
104}
105
106KisPropertiesConfigurationSP KisPNGExport::defaultConfiguration(const QByteArray &, const QByteArray &) const
107{
109 cfg->setProperty("alpha", true);
110 cfg->setProperty("indexed", false);
111 cfg->setProperty("compression", 3);
112 cfg->setProperty("interlaced", false);
113
114 KoColor fill_color(KoColorSpaceRegistry::instance()->rgb8());
115 fill_color = KoColor();
116 fill_color.fromQColor(Qt::white);
117 QVariant v;
118 v.setValue(fill_color);
119
120 cfg->setProperty("transparencyFillcolor", v);
121 cfg->setProperty("forceSRGB", true);
122 cfg->setProperty("storeMetaData", false);
123 cfg->setProperty("storeAuthor", false);
124 cfg->setProperty("downsample", false);
125 cfg->setProperty("storeColorSpaceInfo", true);
126 cfg->setProperty("writeCicpIfPossible", false);
127 cfg->setProperty("storeExtraColorChunks", false);
128 cfg->setProperty("floatingPointConversionOption", "KeepSame");
129 return cfg;
130}
131
132KisConfigWidget *KisPNGExport::createConfigurationWidget(QWidget *parent, const QByteArray &, const QByteArray &) const
133{
134 return new KisWdgOptionsPNG(parent);
135}
136
138{
140 QList<QPair<KoID, KoID> > supportedColorModels;
141 supportedColorModels << QPair<KoID, KoID>()
142 << QPair<KoID, KoID>(RGBAColorModelID, Integer8BitsColorDepthID)
143 << QPair<KoID, KoID>(RGBAColorModelID, Integer16BitsColorDepthID)
144 << QPair<KoID, KoID>(GrayAColorModelID, Integer8BitsColorDepthID)
145 << QPair<KoID, KoID>(GrayAColorModelID, Integer16BitsColorDepthID);
146 addSupportedColorModels(supportedColorModels, "PNG");
147}
148
150 : KisConfigWidget(parent)
151{
152 setupUi(this);
153
154 connect(cmbFloatingConversion, SIGNAL(activated(int)), this, SLOT(onConversionPolicyChanged()));
155 connect(chkCICP, SIGNAL(toggled(bool)), this, SLOT(onConversionPolicyChanged()));
156 connect(gbSaveColorInfo, SIGNAL(toggled(bool)), this, SLOT(onConversionPolicyChanged()));
157}
158
160{
161 // the export manager should have prepared some info for us!
165
166 // Setup the floating point conversion options.
167 QStringList conversionOptionsList = { i18nc("Color space name", "Rec 2100 PQ"), i18nc("Color space name", "Rec 2100 HLG")};
168 QStringList toolTipList = {i18nc("@tooltip", "The image will be converted to Rec 2020 linear first, and then encoded with a perceptual quantizer curve"
169 " (also known as SMPTE 2048 curve). Recommended for HDR images where the absolute brightness is important."),
170 i18nc("@tooltip", "The image will be converted to Rec 2020 linear first, and then encoded with a Hybrid Log Gamma curve."
171 " Recommended for HDR images where the display may not understand HDR.")};
172 QStringList conversionOptionName = {"Rec2100PQ", "Rec2100HLG"};
173 int cicpPrimaries = cfg->getInt(KisImportExportFilter::CICPPrimariesTag,
174 static_cast<int>(PRIMARIES_UNSPECIFIED));
175 if (cicpPrimaries != PRIMARIES_UNSPECIFIED) {
176 conversionOptionsList << i18nc("Color space option plus transfer function name", "Keep colorants, encode PQ");
177 toolTipList << i18nc("@tooltip", "The image will be linearized first, and then encoded with a perceptual quantizer curve"
178 " (also known as the SMPTE 2048 curve). Recommended for images where the absolute brightness is important.");
179 conversionOptionName << "ApplyPQ";
180
181 conversionOptionsList << i18nc("Color space option plus transfer function name", "Keep colorants, encode HLG");
182 toolTipList << i18nc("@tooltip", "The image will be linearized first, and then encoded with a Hybrid Log Gamma curve."
183 " Recommended for images intended for screens which cannot understand PQ");
184 conversionOptionName << "ApplyHLG";
185
186 conversionOptionsList << i18nc("Color space option plus transfer function name", "Keep colorants, encode SMPTE ST 428");
187 toolTipList << i18nc("@tooltip", "The image will be linearized first, and then encoded with SMPTE ST 428."
188 " Krita always opens images like these as linear floating point, this option is there to reverse that");
189 conversionOptionName << "ApplySMPTE428";
190 }
191
192 conversionOptionsList << i18nc("Color space option", "No changes, clip");
193 toolTipList << i18nc("@tooltip", "The image will be converted plainly to 16bit integer, and values that are out of bounds are clipped, the icc profile will be embedded.");
194 conversionOptionName << "KeepSame";
195
196
197 cmbFloatingConversion->clear();
198 cmbFloatingConversion->addItems(conversionOptionsList);
199 for (int i=0; i< toolTipList.size(); i++) {
200 cmbFloatingConversion->setItemData(i, toolTipList.at(i), Qt::ToolTipRole);
201 cmbFloatingConversion->setItemData(i, conversionOptionName.at(i), Qt::UserRole+1);
202 }
203 QString optionName =
204 cfg->getString("floatingPointConversionOption", "KeepSame");
205 if (conversionOptionName.contains(optionName)) {
206 cmbFloatingConversion->setCurrentIndex(
207 conversionOptionName.indexOf(optionName));
208 }
209 const QString colorDepthId =
211 if ((colorDepthId == Float16BitsColorDepthID.id()
212 || colorDepthId == Float32BitsColorDepthID.id()
213 || colorDepthId == Float64BitsColorDepthID.id())
214 && cfg->getString(KisImportExportFilter::ColorModelIDTag) == "RGBA") {
215 m_floatingPoint = true;
216 } else {
217 m_floatingPoint = false;
218 }
219
220 gbSaveColorInfo->setChecked(cfg->getBool("storeColorSpaceInfo", true));
221 chkCICP->setChecked(cfg->getBool("writeCicpIfPossible", true));
222 chkExtraColorChunks->setChecked(cfg->getBool("storeExtraColorChunks", true));
223
224
225 const bool isThereAlpha = cfg->getBool(KisImportExportFilter::ImageContainsTransparencyTag);
226
227 alpha->setChecked(cfg->getBool("alpha", isThereAlpha));
228
229 bnTransparencyFillColor->setEnabled(!alpha->isChecked());
230
232 tryToSaveAsIndexed->setVisible(true);
233 if (alpha->isChecked()) {
234 tryToSaveAsIndexed->setChecked(false);
235 }
236 else {
237 tryToSaveAsIndexed->setChecked(cfg->getBool("indexed", false));
238 }
239 }
240 else {
241 tryToSaveAsIndexed->setVisible(false);
242 }
243 interlacing->setChecked(cfg->getBool("interlaced", false));
244 compressionLevel->setValue(cfg->getInt("compression", 3));
245 compressionLevel->setRange(1, 9, 0);
246
247 tryToSaveAsIndexed->setVisible(!isThereAlpha);
248
249 chkForceSRGB->setChecked(cfg->getBool("forceSRGB", false));
250
251 chkAuthor->setChecked(cfg->getBool("storeAuthor", false));
252 chkMetaData->setChecked(cfg->getBool("storeMetaData", false));
253
254 KoColor background(KoColorSpaceRegistry::instance()->rgb8());
255 background.fromQColor(Qt::white);
256 bnTransparencyFillColor->setDefaultColor(background);
257 bnTransparencyFillColor->setColor(cfg->getColor("transparencyFillcolor", background));
258
259 chkDownsample->setChecked(cfg->getBool("downsample", false));
260
262}
263
265{
266
268
269 bool alpha = this->alpha->isChecked();
270 bool interlace = interlacing->isChecked();
271 int compression = (int)compressionLevel->value();
272 bool tryToSaveAsIndexed = this->tryToSaveAsIndexed->isChecked();
273 bool forceSRGB = chkForceSRGB->isEnabled()? chkForceSRGB->isChecked(): false;
274 bool storeAuthor = chkAuthor->isChecked();
275 bool storeMetaData = chkMetaData->isChecked();
276 bool downsample = chkDownsample->isChecked();
277
278 bool saveColorInfo = gbSaveColorInfo->isChecked();
279 bool saveCICP = chkCICP->isChecked();
280 bool extraColor = chkExtraColorChunks->isChecked();
281
282 QString conversionMode = cmbFloatingConversion->currentData(Qt::UserRole+1).toString();
283
284 QVariant transparencyFillcolor;
285 transparencyFillcolor.setValue(bnTransparencyFillColor->color());
286
287 cfg->setProperty("alpha", alpha);
288 cfg->setProperty("indexed", tryToSaveAsIndexed);
289 cfg->setProperty("compression", compression);
290 cfg->setProperty("interlaced", interlace);
291 cfg->setProperty("transparencyFillcolor", transparencyFillcolor);
292 cfg->setProperty("forceSRGB", forceSRGB);
293 cfg->setProperty("storeAuthor", storeAuthor);
294 cfg->setProperty("storeMetaData", storeMetaData);
295 cfg->setProperty("downsample", downsample);
296 cfg->setProperty("storeColorSpaceInfo", saveColorInfo);
297 cfg->setProperty("writeCicpIfPossible", saveCICP);
298 cfg->setProperty("storeExtraColorChunks", extraColor);
299 cfg->setProperty("floatingPointConversionOption", conversionMode);
300 return cfg;
301}
302
304{
305 bnTransparencyFillColor->setEnabled(!checked);
306}
307
309{
310 cmbFloatingConversion->setEnabled(m_floatingPoint && (chkCICP->isChecked() && chkCICP->isEnabled()));
311 const QString conversionMode = cmbFloatingConversion->currentData(Qt::UserRole+1).toString();
312 if (cmbFloatingConversion->isEnabled()) {
313 chkForceSRGB->setEnabled(conversionMode == "KeepSame");
314 } else {
315 chkForceSRGB->setEnabled(true);
316 }
317}
318
319#include "kis_png_export.moc"
320
qreal v
VertexDescriptor get(PredecessorMap const &m, VertexDescriptor v)
const KoID Float32BitsColorDepthID("F32", ki18n("32-bit float/channel"))
const KoID Float64BitsColorDepthID("F64", ki18n("64-bit float/channel"))
const KoID GrayAColorModelID("GRAYA", ki18n("Grayscale/Alpha"))
const KoID Float16BitsColorDepthID("F16", ki18n("16-bit float/channel"))
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
@ PRIMARIES_UNSPECIFIED
The KisExifInfoVisitor class looks for a layer with metadata.
KisMetaData::Store * exifInfo()
bool visit(KisNode *) override
static KisExportCheckRegistry * instance()
vKisAnnotationSP_it endAnnotations()
KisGroupLayerSP rootLayer() const
KisPaintDeviceSP projection() const
double xRes() const
double yRes() const
QRect bounds() const override
vKisAnnotationSP_it beginAnnotations()
The base class for import and export filters.
static const QString ColorDepthIDTag
static const QString ColorModelIDTag
static const QString CICPPrimariesTag
void addSupportedColorModels(QList< QPair< KoID, KoID > > supportedColorModels, const QString &name, KisExportCheckBase::Level level=KisExportCheckBase::PARTIALLY)
static const QString ImageContainsTransparencyTag
static const QString sRGBTag
void addCapability(KisExportCheckBase *capability)
KisImportExportErrorCode buildFile(const QString &filename, const QRect &imageRect, const qreal xRes, const qreal yRes, KisPaintDeviceSP device, vKisAnnotationSP_it annotationsStart, vKisAnnotationSP_it annotationsEnd, KisPNGOptions options, KisMetaData::Store *metaData)
KisPropertiesConfigurationSP defaultConfiguration(const QByteArray &from="", const QByteArray &to="") const override
defaultConfiguration defines the default settings for the given import export filter
KisConfigWidget * createConfigurationWidget(QWidget *parent, const QByteArray &from="", const QByteArray &to="") const override
createConfigurationWidget creates a widget that can be used to define the settings for a given import...
KisImportExportErrorCode convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration=0) override
~KisPNGExport() override
void initializeCapabilities() override
KisPNGExport(QObject *parent, const QVariantList &)
KisWdgOptionsPNG(QWidget *parent)
void on_alpha_toggled(bool checked)
KisPropertiesConfigurationSP configuration() const override
void onConversionPolicyChanged()
void setConfiguration(const KisPropertiesConfigurationSP config) override
void fromQColor(const QColor &c)
Convenient function for converting from a QColor.
Definition KoColor.cpp:213
QString id() const
Definition KoID.cpp:63
K_PLUGIN_FACTORY_WITH_JSON(KritaASCCDLFactory, "kritaasccdl.json", registerPlugin< KritaASCCDL >();) KritaASCCDL
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
#define dbgFile
Definition kis_debug.h:56
vKisAnnotationSP::iterator vKisAnnotationSP_it
Definition kis_types.h:181
ConversionPolicy floatingPointConversion
QColor transparencyFillColor
static KoColorSpaceRegistry * instance()