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