Krita Source Code Documentation
Loading...
Searching...
No Matches
HeifExport.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2018 Dirk Farin <farin@struktur.de>
3 * SPDX-FileCopyrightText: 2020-2021 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
4 * SPDX-FileCopyrightText: 2021 Daniel Novomesky <dnovomesky@gmail.com>
5 * SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10#include "HeifExport.h"
11#include "HeifError.h"
12
13#include <QApplication>
14#include <QBuffer>
15#include <QCheckBox>
16#include <QScopedPointer>
17#include <QSlider>
18
19#include <algorithm>
20#include <kpluginfactory.h>
21#include <libheif/heif_cxx.h>
22
23#include <KisDocument.h>
27#include <KoColorProfile.h>
31#include <KoColorProfileQuery.h>
32#include <kis_assert.h>
33#include <kis_config.h>
35#include <kis_group_layer.h>
36#include <kis_image.h>
37#include <kis_iterator_ng.h>
39#include <kis_meta_data_entry.h>
43#include <kis_meta_data_store.h>
44#include <kis_meta_data_value.h>
45#include <kis_paint_device.h>
46#include <kis_paint_layer.h>
48
49using heif::Error;
50
52
53K_PLUGIN_FACTORY_WITH_JSON(ExportFactory, "krita_heif_export.json", registerPlugin<HeifExport>();)
54
56{
57}
58
62
63KisPropertiesConfigurationSP HeifExport::defaultConfiguration(const QByteArray &/*from*/, const QByteArray &/*to*/) const
64{
66 cfg->setProperty("quality", 100);
67 cfg->setProperty("lossless", true);
68 cfg->setProperty("chroma", "444");
69 cfg->setProperty("floatingPointConversionOption", "KeepSame");
70 cfg->setProperty("monochromeToSRGB", false);
71 cfg->setProperty("HLGnominalPeak", 1000.0);
72 cfg->setProperty("HLGgamma", 1.2);
73 cfg->setProperty("removeHGLOOTF", true);
74 return cfg;
75}
76
77KisConfigWidget *HeifExport::createConfigurationWidget(QWidget *parent, const QByteArray &/*from*/, const QByteArray &/*to*/) const
78{
79 return new KisWdgOptionsHeif(parent);
80}
81
82
83
84class Writer_QIODevice : public heif::Context::Writer
85{
86public:
87 Writer_QIODevice(QIODevice* io)
88 : m_io(io)
89 {
90 }
91
92 heif_error write(const void* data, size_t size) override {
93 qint64 n = m_io->write(static_cast<const char *>(data),
94 static_cast<int>(size));
95 if (n != static_cast<qint64>(size)) {
96 QString error = m_io->errorString();
97
98 heif_error err = {
99 heif_error_Encoding_error,
100 heif_suberror_Cannot_write_output_data,
101 "Could not write output data" };
102
103 return err;
104 }
105
106 struct heif_error heif_error_ok = { heif_error_Ok, heif_suberror_Unspecified, "Success" };
107 return heif_error_ok;
108 }
109
110private:
111 QIODevice* m_io;
112};
113
114#if LIBHEIF_HAVE_VERSION(1, 13, 0)
115class Q_DECL_HIDDEN HeifLock
116{
117public:
118 HeifLock()
119 : p()
120 {
121 heif_init(&p);
122 }
123
124 ~HeifLock()
125 {
126 heif_deinit();
127 }
128
129private:
130 heif_init_params p;
131};
132#endif
133
135{
136#if LIBHEIF_HAVE_VERSION(1, 13, 0)
137 HeifLock lock;
138#endif
139
140#if LIBHEIF_HAVE_VERSION(1, 20, 2)
141 using HeifStrideType = size_t;
142 auto heifGetPlaneMethod = std::mem_fn(qNonConstOverload<heif_channel, HeifStrideType*>(&heif::Image::get_plane2));
143#elif LIBHEIF_HAVE_VERSION(1, 20, 0)
144 using HeifStrideType = size_t;
145 auto heifGetPlaneMethod = std::mem_fn(qNonConstOverload<heif_channel, HeifStrideType*>(&heif::Image::get_plane));
146#else
147 using HeifStrideType = int;
148 auto heifGetPlaneMethod = std::mem_fn(qNonConstOverload<heif_channel, HeifStrideType*>(&heif::Image::get_plane));
149#endif
150
151
152 KisImageSP image = document->savingImage();
153 const KoColorSpace *cs = image->colorSpace();
154
155
156
157 dbgFile << "Starting" << mimeType() << "encoding.";
158
159 bool convertToSRGB = (configuration->getBool("monochromeToSRGB") && cs->colorModelId() == GrayAColorModelID);
160
161 // Convert to 8 bits rgba on saving if not rgba or graya.
162 if ( (cs->colorModelId() != RGBAColorModelID && cs->colorModelId() != GrayAColorModelID) || convertToSRGB) {
164 image->convertImageColorSpace(sRgb,
167 }
168
169 if (cs->colorModelId() == GrayAColorModelID && cs->hasHighDynamicRange() && !convertToSRGB) {
171 image->convertImageColorSpace(gray,
174 }
175
177 bool convertToRec2020 = false;
178
179 if (cs->hasHighDynamicRange() && cs->colorModelId() != GrayAColorModelID) {
180 QString conversionOption =
181 (configuration->getString("floatingPointConversionOption",
182 "KeepSame"));
183 if (conversionOption == "Rec2100PQ") {
184 convertToRec2020 = true;
185 conversionPolicy = ConversionPolicy::ApplyPQ;
186 } else if (conversionOption == "Rec2100HLG") {
187 convertToRec2020 = true;
188 conversionPolicy = ConversionPolicy::ApplyHLG;
189 } else if (conversionOption == "ApplyPQ") {
190 conversionPolicy = ConversionPolicy::ApplyPQ;
191 } else if (conversionOption == "ApplyHLG") {
192 conversionPolicy = ConversionPolicy::ApplyHLG;
193 } else if (conversionOption == "ApplySMPTE428") {
194 conversionPolicy = ConversionPolicy::ApplySMPTE428;
195 }
196 }
197
198 if (cs->hasHighDynamicRange() && convertToRec2020) {
201 TRC_LINEAR));
202 const KoColorSpace *linearRec2020 = KoColorSpaceRegistry::instance()->colorSpace("RGBA", "F32", linear);
203 image->convertImageColorSpace(linearRec2020,
206 }
207
208 image->waitForDone();
209 cs = image->colorSpace();
210
211 int quality = configuration->getInt("quality", 50);
212 bool lossless = configuration->getBool("lossless", false);
213 bool hasAlpha = configuration->getBool(KisImportExportFilter::ImageContainsTransparencyTag, false);
214 float hlgGamma = configuration->getFloat("HLGgamma", 1.2f);
215 float hlgNominalPeak = configuration->getFloat("HLGnominalPeak", 1000.0f);
216 bool removeHGLOOTF = configuration->getBool("removeHGLOOTF", true);
217
218 // If we want to add information from the document to the metadata,
219 // we should do that here.
220
221 try {
222 // --- use standard HEVC encoder
223
224
225 heif::Encoder encoder(heif_compression_HEVC);
226
227
228 if (mimeType() == "image/avif") {
229 encoder = heif::Encoder(heif_compression_AV1);
230 }
231
232
233 encoder.set_lossy_quality(quality);
234 if (lossless) {
235 //https://invent.kde.org/graphics/krita/-/merge_requests/530#note_169521
236 encoder.set_lossy_quality(100);
237 }
238 encoder.set_lossless(lossless);
239 if (cs->colorModelId() != GrayAColorModelID) {
240 encoder.set_parameter("chroma", configuration->getString("chroma", "444").toStdString());
241 }
242
243
244 // --- convert KisImage to HEIF image ---
245 int width = image->width();
246 int height = image->height();
247
248 heif::Context ctx;
249
250 heif_chroma chroma = hasAlpha? heif_chroma_interleaved_RRGGBBAA_LE: heif_chroma_interleaved_RRGGBB_LE;
251 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
252 chroma = hasAlpha? heif_chroma_interleaved_RRGGBBAA_BE: heif_chroma_interleaved_RRGGBB_BE;
253 }
254
255 heif::Image img;
256
257 if (cs->colorModelId() == RGBAColorModelID) {
259 dbgFile << "saving as 8bit rgba";
260 img.create(width,height, heif_colorspace_RGB, heif_chroma_444);
261 img.add_plane(heif_channel_R, width,height, 8);
262 img.add_plane(heif_channel_G, width,height, 8);
263 img.add_plane(heif_channel_B, width,height, 8);
264
265 HeifStrideType strideR = 0;
266 HeifStrideType strideG = 0;
267 HeifStrideType strideB = 0;
268 HeifStrideType strideA = 0;
269
270 uint8_t *ptrR = heifGetPlaneMethod(img, heif_channel_R, &strideR);
271 uint8_t *ptrG = heifGetPlaneMethod(img, heif_channel_G, &strideG);
272 uint8_t *ptrB = heifGetPlaneMethod(img, heif_channel_B, &strideB);
273
274 uint8_t *ptrA = [&]() -> uint8_t * {
275 if (hasAlpha) {
276 img.add_plane(heif_channel_Alpha, width, height, 8);
277 return heifGetPlaneMethod(img, heif_channel_Alpha, &strideA);
278 } else {
279 return nullptr;
280 }
281 }();
282
283 KisPaintDeviceSP pd = image->projection();
285 pd->createHLineConstIteratorNG(0, 0, width);
286
287 Planar::writeLayer(hasAlpha,
288 width,
289 height,
290 ptrR,
291 strideR,
292 ptrG,
293 strideG,
294 ptrB,
295 strideB,
296 ptrA,
297 strideA,
298 it);
299 } else {
300 dbgFile << "Saving as 12bit rgba";
301 img.create(width, height, heif_colorspace_RGB, chroma);
302 img.add_plane(heif_channel_interleaved, width, height, 12);
303
304 HeifStrideType stride = 0;
305
306 uint8_t *ptr = heifGetPlaneMethod(img, heif_channel_interleaved, &stride);
307
308 KisPaintDeviceSP pd = image->projection();
310 pd->createHLineConstIteratorNG(0, 0, width);
311
313 HDRInt::writeInterleavedLayer(QSysInfo::ByteOrder,
314 hasAlpha,
315 width,
316 height,
317 ptr,
318 stride,
319 it);
320 } else {
322 QSysInfo::ByteOrder,
323 hasAlpha,
324 convertToRec2020,
325 cs->profile()->isLinear(),
326 conversionPolicy,
327 removeHGLOOTF,
328 width,
329 height,
330 ptr,
331 stride,
332 it,
333 hlgGamma,
334 hlgNominalPeak,
335 cs);
336 }
337 }
338 } else {
340 dbgFile << "Saving as 8 bit monochrome.";
341 img.create(width, height, heif_colorspace_monochrome, heif_chroma_monochrome);
342
343 img.add_plane(heif_channel_Y, width, height, 8);
344
345 HeifStrideType strideG = 0;
346 HeifStrideType strideA = 0;
347
348 uint8_t *ptrG = heifGetPlaneMethod(img, heif_channel_Y, &strideG);
349 uint8_t *ptrA = [&]() -> uint8_t * {
350 if (hasAlpha) {
351 img.add_plane(heif_channel_Alpha, width, height, 8);
352 return heifGetPlaneMethod(img, heif_channel_Alpha, &strideA);
353 } else {
354 return nullptr;
355 }
356 }();
357
358 KisPaintDeviceSP pd = image->projection();
360 pd->createHLineConstIteratorNG(0, 0, width);
361
362 Gray::writePlanarLayer(QSysInfo::ByteOrder,
363 8,
364 hasAlpha,
365 width,
366 height,
367 ptrG,
368 strideG,
369 ptrA,
370 strideA,
371 it);
372 } else {
373 dbgFile << "Saving as 12 bit monochrome";
374 img.create(width, height, heif_colorspace_monochrome, heif_chroma_monochrome);
375
376 img.add_plane(heif_channel_Y, width, height, 12);
377
378 HeifStrideType strideG = 0;
379 HeifStrideType strideA = 0;
380
381 uint8_t *ptrG = heifGetPlaneMethod(img, heif_channel_Y, &strideG);
382 uint8_t *ptrA = [&]() -> uint8_t * {
383 if (hasAlpha) {
384 img.add_plane(heif_channel_Alpha, width, height, 12);
385 return heifGetPlaneMethod(img, heif_channel_Alpha, &strideA);
386 } else {
387 return nullptr;
388 }
389 }();
390
391 KisPaintDeviceSP pd = image->projection();
393 pd->createHLineConstIteratorNG(0, 0, width);
394
395 Gray::writePlanarLayer(QSysInfo::ByteOrder,
396 12,
397 hasAlpha,
398 width,
399 height,
400 ptrG,
401 strideG,
402 ptrA,
403 strideA,
404 it);
405 }
406 }
407
408 // --- save the color profile.
409 if (conversionPolicy == ConversionPolicy::KeepTheSame) {
410 QByteArray rawProfileBA = image->colorSpace()->profile()->rawData();
411 std::vector<uint8_t> rawProfile(rawProfileBA.begin(), rawProfileBA.end());
412 img.set_raw_color_profile(heif_color_profile_type_prof, rawProfile);
413 } else {
414 heif::ColorProfile_nclx nclxDescription;
415 nclxDescription.set_full_range_flag(true);
416 nclxDescription.set_matrix_coefficients(heif_matrix_coefficients_RGB_GBR);
417 if (convertToRec2020) {
418#if LIBHEIF_HAVE_VERSION(1, 14, 1)
419 nclxDescription.set_color_primaries(heif_color_primaries_ITU_R_BT_2020_2_and_2100_0);
420#else
421 nclxDescription.set_color_primaties(heif_color_primaries_ITU_R_BT_2020_2_and_2100_0);
422#endif
423 } else {
424 const ColorPrimaries primaries =
425 image->colorSpace()->profile()->getColorPrimaries();
426 // PRIMARIES_ADOBE_RGB_1998 and higher are not valid for CICP.
427 // But this should have already been caught by the KeepTheSame
428 // clause...
430 errFile << "Attempt to export a file with unsupported primaries" << primaries;
432 }
433#if LIBHEIF_HAVE_VERSION(1, 14, 1)
434 nclxDescription.set_color_primaries(heif_color_primaries(primaries));
435#else
436 nclxDescription.set_color_primaties(heif_color_primaries(primaries));
437#endif
438 }
439
440 if (conversionPolicy == ConversionPolicy::ApplyPQ) {
441 nclxDescription.set_transfer_characteristics(heif_transfer_characteristic_ITU_R_BT_2100_0_PQ);
442 } else if (conversionPolicy == ConversionPolicy::ApplyHLG) {
443 nclxDescription.set_transfer_characteristics(heif_transfer_characteristic_ITU_R_BT_2100_0_HLG);
444 } else if (conversionPolicy == ConversionPolicy::ApplySMPTE428) {
445 nclxDescription.set_transfer_characteristics(heif_transfer_characteristic_SMPTE_ST_428_1);
446 }
447
448 img.set_nclx_color_profile(nclxDescription);
449 }
450
451
452 // --- encode and write image
453
454 heif::Context::EncodingOptions options;
455
456 // iOS gets confused when a heif file contains an nclx.
457 // but we absolutely need it for hdr.
458 if (conversionPolicy != ConversionPolicy::KeepTheSame && cs->hasHighDynamicRange()) {
459 options.macOS_compatibility_workaround_no_nclx_profile = false;
460 }
461
462 heif::ImageHandle handle = ctx.encode_image(img, encoder, options);
463
464
465 // --- add Exif / XMP metadata
466
467 KisExifInfoVisitor exivInfoVisitor;
468 exivInfoVisitor.visit(image->rootLayer().data());
469
470 QScopedPointer<KisMetaData::Store> metaDataStore;
471 if (exivInfoVisitor.metaDataCount() == 1) {
472 metaDataStore.reset(new KisMetaData::Store(*exivInfoVisitor.exifInfo()));
473 }
474 else {
475 metaDataStore.reset(new KisMetaData::Store());
476 }
477
478 if (!metaDataStore->empty()) {
479 {
481 QBuffer buffer;
482 exifIO->saveTo(metaDataStore.data(), &buffer, KisMetaData::IOBackend::NoHeader); // Or JpegHeader? Or something else?
483 QByteArray data = buffer.data();
484
485 // Write the data to the file
486 if (data.size() > 4) {
487 ctx.add_exif_metadata(handle, data.constData(), data.size());
488 }
489 }
490 {
492 QBuffer buffer;
493 xmpIO->saveTo(metaDataStore.data(), &buffer, KisMetaData::IOBackend::NoHeader); // Or JpegHeader? Or something else?
494 QByteArray data = buffer.data();
495
496 // Write the data to the file
497 if (data.size() > 0) {
498 ctx.add_XMP_metadata(handle, data.constData(), data.size());
499 }
500 }
501 }
502
503
504 // --- write HEIF file
505
506 Writer_QIODevice writer(io);
507
508 ctx.write(writer);
509 } catch (Error &err) {
510 return setHeifError(document, err);
511 }
512
514}
515
517{
518 // This checks before saving for what the file format supports: anything that is supported needs to be mentioned here
519
520 QList<QPair<KoID, KoID> > supportedColorModels;
522 supportedColorModels << QPair<KoID, KoID>()
523 << QPair<KoID, KoID>(RGBAColorModelID, Integer8BitsColorDepthID)
524 << QPair<KoID, KoID>(GrayAColorModelID, Integer8BitsColorDepthID)
525 << QPair<KoID, KoID>(RGBAColorModelID, Integer16BitsColorDepthID)
526 << QPair<KoID, KoID>(GrayAColorModelID, Integer16BitsColorDepthID)
527 ;
528 addSupportedColorModels(supportedColorModels, "HEIF");
529}
530
532{
533 // the export manager should have prepared some info for us!
536
537 QStringList chromaOptions;
538 chromaOptions << "420" << "422" << "444";
539 cmbChroma->addItems(chromaOptions);
540 cmbChroma->setItemData(0, i18nc("@tooltip", "The brightness of the image will be at full resolution, while the colorfulness will be halved in both dimensions."), Qt::ToolTipRole);
541 cmbChroma->setItemData(1, i18nc("@tooltip", "The brightness of the image will be at full resolution, while the colorfulness will be halved horizontally."), Qt::ToolTipRole);
542 cmbChroma->setItemData(2, i18nc("@tooltip", "Both brightness and colorfulness of the image will be at full resolution."), Qt::ToolTipRole);
543 chkLossless->setChecked(cfg->getBool("lossless", true));
544 sliderQuality->setValue(qreal(cfg->getInt("quality", 50)));
545 cmbChroma->setCurrentIndex(chromaOptions.indexOf(cfg->getString("chroma", "444")));
547
548 int cicpPrimaries = cfg->getInt(KisImportExportFilter::CICPPrimariesTag,
549 static_cast<int>(PRIMARIES_UNSPECIFIED));
550
551 // Rav1e doesn't support monochrome. To get around this, people may need to convert to sRGB first.
552 chkMonochromesRGB->setVisible(cfg->getString(KisImportExportFilter::ColorModelIDTag) == "GRAYA");
553
554 conversionSettings->setVisible(cfg->getBool(KisImportExportFilter::HDRTag, false));
555
556 QStringList conversionOptionsList = { i18nc("Color space name", "Rec 2100 PQ"), i18nc("Color space name", "Rec 2100 HLG")};
557 QStringList toolTipList = {i18nc("@tooltip", "The image will be converted to Rec 2020 linear first, and then encoded with a perceptual quantizer curve"
558 " (also known as SMPTE 2048 curve). Recommended for HDR images where the absolute brightness is important."),
559 i18nc("@tooltip", "The image will be converted to Rec 2020 linear first, and then encoded with a Hybrid Log Gamma curve."
560 " Recommended for HDR images where the display may not understand HDR.")};
561 QStringList conversionOptionName = {"Rec2100PQ", "Rec2100HLG"};
562
563 if (cfg->getString(KisImportExportFilter::ColorModelIDTag) == "RGBA") {
564 if (cicpPrimaries != PRIMARIES_UNSPECIFIED) {
565 conversionOptionsList << i18nc("Color space option plus transfer function name", "Keep colorants, encode PQ");
566 toolTipList << i18nc("@tooltip", "The image will be linearized first, and then encoded with a perceptual quantizer curve"
567 " (also known as the SMPTE 2048 curve). Recommended for images where the absolute brightness is important.");
568 conversionOptionName << "ApplyPQ";
569
570 conversionOptionsList << i18nc("Color space option plus transfer function name", "Keep colorants, encode HLG");
571 toolTipList << i18nc("@tooltip", "The image will be linearized first, and then encoded with a Hybrid Log Gamma curve."
572 " Recommended for images intended for screens which cannot understand PQ");
573 conversionOptionName << "ApplyHLG";
574
575 conversionOptionsList << i18nc("Color space option plus transfer function name", "Keep colorants, encode SMPTE ST 428");
576 toolTipList << i18nc("@tooltip", "The image will be linearized first, and then encoded with SMPTE ST 428."
577 " Krita always opens images like these as linear floating point, this option is there to reverse that");
578 conversionOptionName << "ApplySMPTE428";
579 }
580
581 conversionOptionsList << i18nc("Color space option", "No changes, clip");
582 toolTipList << i18nc("@tooltip", "The image will be converted plainly to 12bit integer, and values that are out of bounds are clipped, the icc profile will be embedded.");
583 conversionOptionName << "KeepSame";
584 }
585 cmbConversionPolicy->addItems(conversionOptionsList);
586 for (int i=0; i< toolTipList.size(); i++) {
587 cmbConversionPolicy->setItemData(i, toolTipList.at(i), Qt::ToolTipRole);
588 cmbConversionPolicy->setItemData(i, conversionOptionName.at(i), Qt::UserRole+1);
589 }
590 QString optionName =
591 cfg->getString("floatingPointConversionOption", "KeepSame");
592 if (conversionOptionName.contains(optionName)) {
593 cmbConversionPolicy->setCurrentIndex(
594 conversionOptionName.indexOf(optionName));
595 }
596 chkHLGOOTF->setChecked(cfg->getBool("removeHGLOOTF", true));
597 spnNits->setValue(cfg->getDouble("HLGnominalPeak", 1000.0));
598 spnGamma->setValue(cfg->getDouble("HLGgamma", 1.2));
599
600 lossySettings->setEnabled(!chkLossless->isChecked());
601}
602
604{
606 cfg->setProperty("lossless", chkLossless->isChecked());
607 cfg->setProperty("quality", int(sliderQuality->value()));
608 cfg->setProperty("chroma", cmbChroma->currentText());
609 cfg->setProperty("floatingPointConversionOption", cmbConversionPolicy->currentData(Qt::UserRole+1).toString());
610 cfg->setProperty("monochromeToSRGB", chkMonochromesRGB->isChecked());
611 cfg->setProperty("HLGnominalPeak", spnNits->value());
612 cfg->setProperty("HLGgamma", spnGamma->value());
613 cfg->setProperty("removeHGLOOTF", chkHLGOOTF->isChecked());
615 return cfg;
616}
617
619{
620 // Disable the quality slider if lossless is true
621 lossySettings->setEnabled(!toggle);
622}
623
625{
626 spnNits->setEnabled(toggle);
627 spnGamma->setEnabled(toggle);
628}
629
631 Q_UNUSED(index)
632 bool toggle = cmbConversionPolicy->currentData(Qt::UserRole+1).toString().contains("HLG");
633 chkHLGOOTF->setEnabled(toggle);
634 spnNits->setEnabled(toggle);
635 spnGamma->setEnabled(toggle);
636}
637#include <HeifExport.moc>
KisImportExportErrorCode setHeifError(KisDocument *document, heif::Error error)
Definition HeifError.cpp:10
const Params2D p
VertexDescriptor get(PredecessorMap const &m, VertexDescriptor v)
const KoID GrayAColorModelID("GRAYA", ki18n("Grayscale/Alpha"))
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"))
ColorPrimaries
The colorPrimaries enum Enum of colorants, follows ITU H.273 for values 0 to 255, and has extra known...
@ PRIMARIES_ITU_R_BT_2020_2_AND_2100_0
@ PRIMARIES_EBU_Tech_3213_E
@ PRIMARIES_UNSPECIFIED
void initializeCapabilities() override
~HeifExport() override
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
KisPropertiesConfigurationSP defaultConfiguration(const QByteArray &from="", const QByteArray &to="") const override
defaultConfiguration defines the default settings for the given import export filter
HeifExport(QObject *parent, const QVariantList &)
The KisExifInfoVisitor class looks for a layer with metadata.
KisMetaData::Store * exifInfo()
bool visit(KisNode *) override
static KisExportCheckRegistry * instance()
void waitForDone()
KisGroupLayerSP rootLayer() const
const KoColorSpace * colorSpace() const
void convertImageColorSpace(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
KisPaintDeviceSP projection() const
qint32 width() const
qint32 height() const
The base class for import and export filters.
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 HDRTag
void addCapability(KisExportCheckBase *capability)
@ NoHeader
Don't append any header.
virtual bool saveTo(const Store *store, QIODevice *ioDevice, HeaderType headerType=NoHeader) const =0
static KisMetadataBackendRegistry * instance()
KisHLineConstIteratorSP createHLineConstIteratorNG(qint32 x, qint32 y, qint32 w) const
KisPropertiesConfigurationSP configuration() const override
void toggleQualitySlider(bool toggle)
void toggleHLGOptions(bool toggle)
void setConfiguration(const KisPropertiesConfigurationSP cfg) override
void toggleExtraHDROptions(int index)
virtual bool hasHighDynamicRange() const =0
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
virtual const KoColorProfile * profile() const =0
const T value(const QString &id) const
Writer_QIODevice(QIODevice *io)
heif_error write(const void *data, size_t size) override
QIODevice * m_io
Encoder * encoder(Imf::OutputFile &file, const ExrPaintLayerSaveInfo &info, int width)
K_PLUGIN_FACTORY_WITH_JSON(KritaASCCDLFactory, "kritaasccdl.json", registerPlugin< KritaASCCDL >();) KritaASCCDL
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
#define errFile
Definition kis_debug.h:115
#define dbgFile
Definition kis_debug.h:53
auto writePlanarLayer(QSysInfo::Endian endian, Args &&...args)
auto writeInterleavedLayer(const KoID &id, Args &&...args)
auto writeInterleavedLayer(QSysInfo::Endian endian, Args &&...args)
auto writeLayer(bool hasAlpha, Args &&...args)
KisNodeWSP parent
Definition kis_node.cpp:86
The KoColorProfileQuery struct.
virtual QByteArray rawData() const
virtual ColorPrimaries getColorPrimaries() const
getColorPrimaries
virtual bool isLinear() const =0
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()
const KoColorProfile * profileFor(const KoColorProfileQuery &query, const bool generate=true) const
profileFor tries to find the profile that matches these characteristics, if no such profile is found,...
const KoColorSpace * graya16(const QString &profile=QString())
const KoColorSpace * rgb8(const QString &profileName=QString())