Krita Source Code Documentation
Loading...
Searching...
No Matches
KisDlgAnimationRenderer Class Reference

#include <KisDlgAnimationRenderer.h>

+ Inheritance diagram for KisDlgAnimationRenderer:

Public Member Functions

KisAnimationRenderingOptions getEncoderOptions () const
 
 KisDlgAnimationRenderer (KisDocument *doc, QWidget *parent=0)
 
 ~KisDlgAnimationRenderer () override
 
- Public Member Functions inherited from KoDialog
QPushButton * button (ButtonCode id) const
 
QIcon buttonIcon (ButtonCode id) const
 
QString buttonText (ButtonCode id) const
 
QString buttonToolTip (ButtonCode id) const
 
QString buttonWhatsThis (ButtonCode id) const
 
ButtonCode defaultButton () const
 
QString helpLinkText () const
 
void incrementInitialSize (const QSize &size)
 
bool isButtonEnabled (ButtonCode id) const
 
 KoDialog (QWidget *parent=0, Qt::WindowFlags f=Qt::WindowFlags())
 
QWidget * mainWidget ()
 
QSize minimumSizeHint () const override
 
void setButtonFocus (ButtonCode id)
 
void setButtonGuiItem (ButtonCode id, const KGuiItem &item)
 
void setButtonIcon (ButtonCode id, const QIcon &icon)
 
void setButtons (ButtonCodes buttonMask)
 
void setButtonsOrientation (Qt::Orientation orientation)
 
void setButtonText (ButtonCode id, const QString &text)
 
void setButtonToolTip (ButtonCode id, const QString &text)
 
void setButtonWhatsThis (ButtonCode id, const QString &text)
 
void setDefaultButton (ButtonCode id)
 
void setEscapeButton (ButtonCode id)
 
void setInitialSize (const QSize &size)
 
void setMainWidget (QWidget *widget)
 
void showButton (ButtonCode id, bool state)
 
void showButtonSeparator (bool state)
 
QSize sizeHint () const override
 
 ~KoDialog () override
 

Protected Slots

void slotButtonClicked (int button) override
 
void slotDialogAccepted ()
 
- Protected Slots inherited from KoDialog
virtual void slotButtonClicked (int button)
 

Private Types

enum  FFmpegValidationResult { VALID = 1 , INVALID = 0 , NOT_A_BINARY = -1 , COMPRESSED_FORMAT = -2 }
 

Private Slots

void frameRateChanged (int framerate)
 
void selectRenderOptions ()
 
void selectRenderType (int i)
 
void sequenceMimeTypeOptionsClicked ()
 sequenceMimeTypeSelected calls the dialog for the export widget.
 
void setFFmpegPath (const QString &path)
 
void slotExportTypeChanged ()
 
void slotLockAspectRatioDimensionsHeight (int height)
 
void slotLockAspectRatioDimensionsWidth (int width)
 

Private Member Functions

void ffmpegWarningCheck ()
 
QStringList filterMimeTypeListByAvailableEncoders (const QStringList &mimeTypes)
 
void initializeRenderSettings (const KisDocument &doc, const KisAnimationRenderingOptions &lastUsedOptions)
 
FFmpegValidationResult validateFFmpeg (const QString &ffmpegPath)
 

Static Private Member Functions

static QString defaultVideoFileName (KisDocument *doc, const QString &mimeType)
 
static void filterSequenceMimeTypes (QStringList &mimeTypes)
 
static void getDefaultVideoEncoderOptions (const QString &mimeType, KisPropertiesConfigurationSP cfg, const QStringList &availableEncoders, QString *customFFMpegOptionsString, bool *forceHDRVideo)
 
static bool imageMimeSupportsHDR (QString &hdr)
 
static KisPropertiesConfigurationSP loadLastConfiguration (QString configurationID)
 
static QStringList makeVideoMimeTypesList ()
 
static void saveLastUsedConfiguration (QString configurationID, KisPropertiesConfigurationSP config)
 

Private Attributes

QStringList ffmpegCodecs = QStringList()
 
QMap< QString, QStringListffmpegEncoderTypes
 
QString ffmpegVersion = "None"
 
QString m_customFFMpegOptionsString
 
KisDocumentm_doc
 
KisImageSP m_image
 
WdgAnimationRendererm_page {0}
 
bool m_wantsRenderWithHDR = false
 

Static Private Attributes

static constexpr bool PLATFORM_SUPPORTS_FFMPEG = true
 

Additional Inherited Members

- Public Types inherited from KoDialog
enum  ButtonCode {
  None = 0x00000000 , Help = 0x00000001 , Default = 0x00000002 , Ok = 0x00000004 ,
  Apply = 0x00000008 , Try = 0x00000010 , Cancel = 0x00000020 , Close = 0x00000040 ,
  No = 0x00000080 , Yes = 0x00000100 , Reset = 0x00000200 , Details = 0x00000400 ,
  User1 = 0x00001000 , User2 = 0x00002000 , User3 = 0x00004000 , NoDefault = 0x00008000
}
 
enum  ButtonPopupMode { InstantPopup = 0 , DelayedPopup = 1 }
 
enum  CaptionFlag { NoCaptionFlags = 0 , AppNameCaption = 1 , ModifiedCaption = 2 , HIGCompliantCaption = AppNameCaption }
 
- Public Slots inherited from KoDialog
void delayedDestruct ()
 
void enableButton (ButtonCode id, bool state)
 
void enableButtonApply (bool state)
 
void enableButtonCancel (bool state)
 
void enableButtonOk (bool state)
 
void enableLinkedHelp (bool state)
 
bool isDetailsWidgetVisible () const
 
virtual void setCaption (const QString &caption)
 
virtual void setCaption (const QString &caption, bool modified)
 
void setDetailsWidget (QWidget *detailsWidget)
 
void setDetailsWidgetVisible (bool visible)
 
void setHelp (const QString &anchor, const QString &appname=QString())
 
void setHelpLinkText (const QString &text)
 
virtual void setPlainCaption (const QString &caption)
 
- Signals inherited from KoDialog
void aboutToShowDetails ()
 
void applyClicked ()
 
void buttonClicked (KoDialog::ButtonCode button)
 
void cancelClicked ()
 
void closeClicked ()
 
void defaultClicked ()
 
void finished ()
 
void helpClicked ()
 
void hidden ()
 
void layoutHintChanged ()
 
void noClicked ()
 
void okClicked ()
 
void resetClicked ()
 
void tryClicked ()
 
void user1Clicked ()
 
void user2Clicked ()
 
void user3Clicked ()
 
void yesClicked ()
 
- Static Public Member Functions inherited from KoDialog
static int groupSpacingHint ()
 
static QString makeStandardCaption (const QString &userCaption, QWidget *window=0, CaptionFlags flags=HIGCompliantCaption)
 
static int marginHint ()
 
static void resizeLayout (QLayout *lay, int margin, int spacing)
 
static void resizeLayout (QWidget *widget, int margin, int spacing)
 
static int spacingHint ()
 
- Protected Member Functions inherited from KoDialog
void closeEvent (QCloseEvent *e) override
 
void hideEvent (QHideEvent *) override
 
void keyPressEvent (QKeyEvent *) override
 
void showEvent (QShowEvent *e) override
 

Detailed Description

Definition at line 38 of file KisDlgAnimationRenderer.h.

Member Enumeration Documentation

◆ FFmpegValidationResult

Enumerator
VALID 
INVALID 
NOT_A_BINARY 
COMPRESSED_FORMAT 

Definition at line 80 of file KisDlgAnimationRenderer.h.

Constructor & Destructor Documentation

◆ KisDlgAnimationRenderer()

KisDlgAnimationRenderer::KisDlgAnimationRenderer ( KisDocument * doc,
QWidget * parent = 0 )

Definition at line 47 of file KisDlgAnimationRenderer.cpp.

48 : KoDialog(parent)
49 , m_image(doc->image())
50 , m_doc(doc)
51{
52 KisConfig cfg(true);
53
54 setCaption(i18n("Render Animation"));
57
58 m_page = new WdgAnimationRenderer(this);
59 m_page->layout()->setContentsMargins(0, 0, 0, 0);
60
61 m_page->dirRequester->setMode(KoFileDialog::OpenDirectory);
62
63 m_page->intStart->setMinimum(0);
64 m_page->intStart->setMaximum(doc->image()->animationInterface()->documentPlaybackRange().end());
65 m_page->intEnd->setMinimum(doc->image()->animationInterface()->documentPlaybackRange().start());
66
67 m_page->intHeight->setMinimum(1);
68 m_page->intHeight->setMaximum(100000);
69
70 m_page->intWidth->setMinimum(1);
71 m_page->intWidth->setMaximum(100000);
72
73 // Setup audio...
74 QVector<QFileInfo> audioFiles = doc->getAudioTracks();
75 const bool hasAudio = audioFiles.count() > 0;
76 m_page->chkIncludeAudio->setEnabled(hasAudio);
77
78 // Setup image mimeTypes...
80 mimes.sort();
82 Q_FOREACH(const QString &mime, mimes) {
83 QString description = KisMimeDatabase::descriptionForMimeType(mime);
84 if (description.isEmpty()) {
85 description = mime;
86 }
87
88 m_page->cmbMimetype->addItem(description, mime);
89
90 if (mime == "image/png") {
91 m_page->cmbMimetype->setCurrentIndex(m_page->cmbMimetype->count() - 1);
92 }
93 }
94
95 m_page->cmbScaleFilter->addItem(i18nc("bicubic filtering", "bicubic"), "bicubic");
96 m_page->cmbScaleFilter->addItem(i18nc("bilinear filtering", "bilinear"), "bilinear");
97 m_page->cmbScaleFilter->addItem(i18nc("lanczos3 filtering", "lanczos3"), "lanczos");
98 m_page->cmbScaleFilter->addItem(i18nc("nearest neighbor filtering", "neighbor"), "neighbor");
99 m_page->cmbScaleFilter->addItem(i18nc("spline filtering", "spline"), "spline");
100
101 m_page->videoFilename->setMode(KoFileDialog::SaveFile);
102
103 m_page->ffmpegLocation->setMode(KoFileDialog::OpenFile);
104
105 m_page->cmbRenderType->setPlaceholderText(i18nc("Not applicable. No render types without valid ffmpeg path.", "N/A"));
106
107 { // Establish connections...
108 connect(m_page->bnExportOptions, SIGNAL(clicked()), this, SLOT(sequenceMimeTypeOptionsClicked()));
109 connect(m_page->bnRenderOptions, SIGNAL(clicked()), this, SLOT(selectRenderOptions()));
110
111 connect(m_page->shouldExportOnlyImageSequence, SIGNAL(toggled(bool)), this, SLOT(slotExportTypeChanged()));
112 connect(m_page->shouldExportOnlyVideo, SIGNAL(toggled(bool)), this, SLOT(slotExportTypeChanged()));
113
114 connect(m_page->intFramesPerSecond, SIGNAL(valueChanged(int)), SLOT(frameRateChanged(int)));
115
116 connect(m_page->ffmpegLocation, SIGNAL(fileSelected(QString)), SLOT(setFFmpegPath(QString)));
117
118 connect(this, SIGNAL(accepted()), SLOT(slotDialogAccepted()));
119 }
120
121
122 // try to lock the width and height being updated
123 KisAcyclicSignalConnector *constrainsConnector = new KisAcyclicSignalConnector(this);
124 constrainsConnector->createCoordinatedConnector()->connectBackwardInt(m_page->intWidth, SIGNAL(valueChanged(int)), this, SLOT(slotLockAspectRatioDimensionsWidth(int)));
125 constrainsConnector->createCoordinatedConnector()->connectForwardInt(m_page->intHeight, SIGNAL(valueChanged(int)), this, SLOT(slotLockAspectRatioDimensionsHeight(int)));
126
127 { // Initialize settings from last configuration...
128 KisPropertiesConfigurationSP animProperties = loadLastConfiguration("ANIMATION_EXPORT");
130 options.fromProperties(animProperties);
131
132 initializeRenderSettings(*doc, options);
133 }
134
136}
KisAcyclicSignalConnector * createCoordinatedConnector()
create a coordinated connector that can be used for extending the number of self-locking connection.
void connectBackwardInt(QObject *sender, const char *signal, QObject *receiver, const char *method)
void connectForwardInt(QObject *sender, const char *signal, QObject *receiver, const char *method)
void fromProperties(KisPropertiesConfigurationSP config)
void initializeRenderSettings(const KisDocument &doc, const KisAnimationRenderingOptions &lastUsedOptions)
void sequenceMimeTypeOptionsClicked()
sequenceMimeTypeSelected calls the dialog for the export widget.
void setFFmpegPath(const QString &path)
void slotLockAspectRatioDimensionsHeight(int height)
void slotLockAspectRatioDimensionsWidth(int width)
static KisPropertiesConfigurationSP loadLastConfiguration(QString configurationID)
WdgAnimationRenderer * m_page
static void filterSequenceMimeTypes(QStringList &mimeTypes)
KisImageSP image
QVector< QFileInfo > getAudioTracks() const
const KisTimeSpan & documentPlaybackRange() const
documentPlaybackRange
KisImageAnimationInterface * animationInterface() const
static QStringList supportedMimeTypes(Direction direction)
static QString descriptionForMimeType(const QString &mimeType)
Find the user-readable description for the given mimetype.
int start() const
int end() const
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
KoDialog(QWidget *parent=0, Qt::WindowFlags f=Qt::WindowFlags())
Definition KoDialog.cpp:176

References KisImage::animationInterface(), KoDialog::Cancel, KisAcyclicSignalConnector::connectBackwardInt(), KisAcyclicSignalConnector::connectForwardInt(), KisAcyclicSignalConnector::createCoordinatedConnector(), KisMimeDatabase::descriptionForMimeType(), KisImageAnimationInterface::documentPlaybackRange(), KisTimeSpan::end(), KisImportExportManager::Export, filterSequenceMimeTypes(), frameRateChanged(), KisAnimationRenderingOptions::fromProperties(), KisDocument::getAudioTracks(), KisDocument::image, initializeRenderSettings(), loadLastConfiguration(), m_page, KoDialog::Ok, KoFileDialog::OpenDirectory, KoFileDialog::OpenFile, KoFileDialog::SaveFile, selectRenderOptions(), sequenceMimeTypeOptionsClicked(), KoDialog::setButtons(), KoDialog::setCaption(), KoDialog::setDefaultButton(), setFFmpegPath(), KoDialog::setMainWidget(), slotDialogAccepted(), slotExportTypeChanged(), slotLockAspectRatioDimensionsHeight(), slotLockAspectRatioDimensionsWidth(), KisTimeSpan::start(), and KisImportExportManager::supportedMimeTypes().

◆ ~KisDlgAnimationRenderer()

KisDlgAnimationRenderer::~KisDlgAnimationRenderer ( )
override

Definition at line 138 of file KisDlgAnimationRenderer.cpp.

139{
140 delete m_page;
141}

References m_page.

Member Function Documentation

◆ defaultVideoFileName()

QString KisDlgAnimationRenderer::defaultVideoFileName ( KisDocument * doc,
const QString & mimeType )
staticprivate

Definition at line 540 of file KisDlgAnimationRenderer.cpp.

541{
542 const QString docFileName = !doc->localFilePath().isEmpty() ? doc->localFilePath() : i18n("Untitled");
543
544 if (!mimeType.isEmpty()) {
545 return QString("%1.%2").arg(QFileInfo(docFileName).completeBaseName(),
546 KisMimeDatabase::suffixesForMimeType(mimeType).first());
547 } else {
548 return docFileName;
549 }
550}
QString localFilePath() const
static QStringList suffixesForMimeType(const QString &mimeType)

References KisDocument::localFilePath(), and KisMimeDatabase::suffixesForMimeType().

◆ ffmpegWarningCheck()

void KisDlgAnimationRenderer::ffmpegWarningCheck ( )
private

Definition at line 500 of file KisDlgAnimationRenderer.cpp.

500 {
501 const QString mimeType = m_page->cmbRenderType->itemData(m_page->cmbRenderType->currentIndex()).toString();
502
503 const QRegularExpression minVerFFMpegRX(R"(^n{0,1}(?:[0-3]|4\.[01])[\.\-])");
504 const QRegularExpressionMatch minVerFFMpegMatch = minVerFFMpegRX.match(ffmpegVersion);
505
506 QStringList warnings;
507
508 if (mimeType == "image/gif" && minVerFFMpegMatch.hasMatch()) {
509 warnings << i18nc("ffmpeg warning checks", "FFmpeg must be at least version 4.2+ for GIF transparency to work");
510 }
511
512 // m_page->bnRenderOptions->setEnabled(mimeType != "image/gif" && mimeType != "image/webp" && mimeType !=
513 // "image/png" );
514 if (mimeType == "image/gif" && m_page->intFramesPerSecond->value() > 50) {
515 warnings << i18nc("ffmpeg warning checks",
516 "Animated GIF images cannot have a framerate higher than 50. The framerate will be reduced "
517 "to 50 frames per second");
518 }
519
520 m_page->lblWarnings->setVisible(!warnings.isEmpty());
521
522 if (!warnings.isEmpty()) {
523 QString text = QString("<p><b>%1</b>").arg(i18n("Warning(s):"));
524 text.append("<ul>");
525 Q_FOREACH (const QString &warning, warnings) {
526 text.append("<li>");
527 text.append(warning.toHtmlEscaped());
528 text.append("</li>");
529 }
530 text.append("</ul></p>");
531 m_page->lblWarnings->setText(text);
532
533 m_page->lblWarnings->setPixmap(
534 m_page->lblWarnings->style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(QSize(32, 32)));
535 }
536
537 m_page->adjustSize();
538}

References ffmpegVersion, and m_page.

◆ filterMimeTypeListByAvailableEncoders()

QStringList KisDlgAnimationRenderer::filterMimeTypeListByAvailableEncoders ( const QStringList & mimeTypes)
private

Definition at line 350 of file KisDlgAnimationRenderer.cpp.

351{
352 QStringList retValue;
353
354 Q_FOREACH(const QString& mime, input) {
355 if ( mime == "video/x-matroska" ) {
356 if ( ffmpegCodecs.contains("h264") || ffmpegCodecs.contains("vp9") ) {
357 QList<QString> encodersPresent;
358 encodersPresent << ffmpegEncoderTypes["h264"] << ffmpegEncoderTypes["vp9"];
360 retValue << mime;
361 }
362 } else if (mime == "video/mp4") {
363 if ( ffmpegCodecs.contains("h264") || ffmpegCodecs.contains("vp9") ) {
364 QList<QString> encodersPresent;
365 encodersPresent << ffmpegEncoderTypes["h264"] << ffmpegEncoderTypes["vp9"];
367 retValue << mime;
368 }
369 } else if (mime == "video/webm") {
370 if ( ffmpegCodecs.contains("vp9") ) {
371 QList<QString> encodersPresent;
372 encodersPresent << ffmpegEncoderTypes["vp9"];
374 retValue << mime;
375 }
376 } else if (mime == "image/gif") {
377 if ( ffmpegCodecs.contains("gif") ) {
378 retValue << mime;
379 }
380 } else if (mime == "image/apng") {
381 if ( ffmpegCodecs.contains("apng") ) {
382 retValue << mime;
383 }
384 } else if (mime == "image/webp") {
385 if ( ffmpegCodecs.contains("webp") ) {
386 retValue << mime;
387 }
388 } else if (mime == "video/ogg") {
389 if ( ffmpegCodecs.contains("theora") ) {
390 retValue << mime;
391 }
392 }
393 }
394
395 return retValue;
396}
bool meetsEncoderRequirementsForContainer(KisVideoExportOptionsDialog::ContainerType encoderType, const QStringList &encodersPresent)
QMap< QString, QStringList > ffmpegEncoderTypes

References ffmpegCodecs, ffmpegEncoderTypes, meetsEncoderRequirementsForContainer(), KisVideoExportOptionsDialog::MKV, KisVideoExportOptionsDialog::MP4, and KisVideoExportOptionsDialog::WEBM.

◆ filterSequenceMimeTypes()

void KisDlgAnimationRenderer::filterSequenceMimeTypes ( QStringList & mimeTypes)
staticprivate

Definition at line 315 of file KisDlgAnimationRenderer.cpp.

316{
317 KritaUtils::filterContainer(mimeTypes, [](QString type) {
318 return (type.startsWith("image/")
319 || (type.startsWith("application/") &&
320 !type.startsWith("application/x-spriter")));
321 });
322}
auto filterContainer(C &container, KeepIfFunction keepIf) -> decltype(bool(keepIf(container[0])), void())

References KritaUtils::filterContainer().

◆ frameRateChanged

void KisDlgAnimationRenderer::frameRateChanged ( int framerate)
privateslot

Definition at line 816 of file KisDlgAnimationRenderer.cpp.

817{
818 Q_UNUSED(framerate);
820}

References ffmpegWarningCheck().

◆ getDefaultVideoEncoderOptions()

void KisDlgAnimationRenderer::getDefaultVideoEncoderOptions ( const QString & mimeType,
KisPropertiesConfigurationSP cfg,
const QStringList & availableEncoders,
QString * customFFMpegOptionsString,
bool * forceHDRVideo )
staticprivate

Definition at line 296 of file KisDlgAnimationRenderer.cpp.

301{
304
305 QScopedPointer<KisVideoExportOptionsDialog> encoderConfigWidget(
306 new KisVideoExportOptionsDialog(containerType, availableEncoders, 0));
307
308 // we always enable HDR, letting the user to force it
309 encoderConfigWidget->setSupportsHDR(true);
310 encoderConfigWidget->setConfiguration(cfg);
311 *customFFMpegOptionsString = encoderConfigWidget->customUserOptionsString();
312 *renderHDR = encoderConfigWidget->videoConfiguredForHDR();
313}
static ContainerType mimeToContainer(const QString &mimeType)

References KisVideoExportOptionsDialog::mimeToContainer().

◆ getEncoderOptions()

KisAnimationRenderingOptions KisDlgAnimationRenderer::getEncoderOptions ( ) const

Definition at line 679 of file KisDlgAnimationRenderer.cpp.

680{
682
684 options.videoMimeType = m_page->cmbRenderType->currentData().toString();
685 options.frameMimeType = m_page->cmbMimetype->currentData().toString();
686 options.scaleFilter = m_page->cmbScaleFilter->currentData().toString();
687
688 options.basename = m_page->txtBasename->text();
689 options.directory = m_page->dirRequester->fileName();
690 options.firstFrame = m_page->intStart->value();
691 options.lastFrame = m_page->intEnd->value();
692 options.sequenceStart = m_page->sequenceStart->value();
693
694 if constexpr (PLATFORM_SUPPORTS_FFMPEG) {
695 options.shouldEncodeVideo = m_page->shouldExportOnlyVideo->isChecked();
696 options.shouldDeleteSequence = !m_page->shouldExportOnlyImageSequence->isChecked();
697 } else {
698 options.shouldEncodeVideo = false;
699 options.shouldDeleteSequence = false;
700 }
701 options.includeAudio = m_page->chkIncludeAudio->isChecked();
702 options.wantsOnlyUniqueFrameSequence = m_page->chkOnlyUniqueFrames->isChecked();
703
704 options.ffmpegPath = m_page->ffmpegLocation->fileName();
705 options.frameRate = m_page->intFramesPerSecond->value();
706
707 if (options.frameRate > 50 && options.videoMimeType == "image/gif") {
708 options.frameRate = 50;
709 }
710
711 options.width = m_page->intWidth->value();
712 options.height = m_page->intHeight->value();
713 options.videoFileName = m_page->videoFilename->fileName();
714
716
717 {
719 if (cfg) {
721 }
722
723 const bool forceNecessaryHDRSettings = m_wantsRenderWithHDR && imageMimeSupportsHDR(options.frameMimeType);
724 if (forceNecessaryHDRSettings) {
725 KIS_SAFE_ASSERT_RECOVER_NOOP(options.frameMimeType == "image/png");
726 cfg->setProperty("forceSRGB", false);
727 cfg->setProperty("saveAsHDR", true);
728 }
729
730 options.frameExportConfig = cfg;
731 }
732
733 return options;
734}
KisPropertiesConfigurationSP frameExportConfig
static constexpr bool PLATFORM_SUPPORTS_FFMPEG
static bool imageMimeSupportsHDR(QString &hdr)
static void fillStaticExportConfigurationProperties(KisPropertiesConfigurationSP exportConfiguration, KisImageSP image)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130

References KisAnimationRenderingOptions::basename, KisAnimationRenderingOptions::customFFMpegOptions, KisAnimationRenderingOptions::directory, KisAnimationRenderingOptions::ffmpegPath, KisImportExportManager::fillStaticExportConfigurationProperties(), KisAnimationRenderingOptions::firstFrame, KisAnimationRenderingOptions::frameExportConfig, KisAnimationRenderingOptions::frameMimeType, KisAnimationRenderingOptions::frameRate, KisAnimationRenderingOptions::height, imageMimeSupportsHDR(), KisAnimationRenderingOptions::includeAudio, KIS_SAFE_ASSERT_RECOVER_NOOP, KisAnimationRenderingOptions::lastDocumentPath, KisAnimationRenderingOptions::lastFrame, loadLastConfiguration(), KisDocument::localFilePath(), m_customFFMpegOptionsString, m_doc, m_image, m_page, m_wantsRenderWithHDR, PLATFORM_SUPPORTS_FFMPEG, KisAnimationRenderingOptions::scaleFilter, KisAnimationRenderingOptions::sequenceStart, KisAnimationRenderingOptions::shouldDeleteSequence, KisAnimationRenderingOptions::shouldEncodeVideo, KisAnimationRenderingOptions::videoFileName, KisAnimationRenderingOptions::videoMimeType, KisAnimationRenderingOptions::wantsOnlyUniqueFrameSequence, and KisAnimationRenderingOptions::width.

◆ imageMimeSupportsHDR()

bool KisDlgAnimationRenderer::imageMimeSupportsHDR ( QString & hdr)
staticprivate

Definition at line 398 of file KisDlgAnimationRenderer.cpp.

399{
400 return (mime == "image/png");
401}

◆ initializeRenderSettings()

void KisDlgAnimationRenderer::initializeRenderSettings ( const KisDocument & doc,
const KisAnimationRenderingOptions & lastUsedOptions )
private

Definition at line 143 of file KisDlgAnimationRenderer.cpp.

144{
145 // Initialize FFmpeg location... (!)
146 KisConfig cfg(false);
147 QString cfgFFmpegPath = cfg.ffmpegLocation();
148#ifdef Q_OS_MACOS
149 if (cfgFFmpegPath.isEmpty()) {
150 QJsonObject ffmpegInfo = KisFFMpegWrapper::findFFMpeg(cfgFFmpegPath);
151 cfgFFmpegPath = (ffmpegInfo["enabled"].toBool()) ? ffmpegInfo["path"].toString() : "";
152 }
153#endif
154
155 // Check known ffmpeg locations..
156 QString likelyFFmpegPath = [&]() {
157 // Check last used
158 if (!lastUsedOptions.ffmpegPath.isEmpty() && QFileInfo(lastUsedOptions.ffmpegPath).isExecutable()) {
159 return lastUsedOptions.ffmpegPath;
160 }
161
162 // Check krita config
163 if (!cfgFFmpegPath.isEmpty() && QFileInfo(cfgFFmpegPath).isExecutable()) {
164 return cfgFFmpegPath;
165 }
166
167 // Check standard paths
168 QString systemFFmpeg = QStandardPaths::findExecutable("ffmpeg");
169 if (!systemFFmpeg.isEmpty() && QFileInfo(systemFFmpeg).isExecutable()) {
170 return systemFFmpeg;
171 }
172
173 // Find ffmpeg elsewhere...
174 QJsonObject ffmpegJsonObj = KisFFMpegWrapper::findFFMpeg("");
175 return (ffmpegJsonObj["enabled"].toBool()) ? ffmpegJsonObj["path"].toString() : "";
176 }();
177
178 if (!likelyFFmpegPath.isEmpty() && QFileInfo(likelyFFmpegPath).isExecutable()) {
179 setFFmpegPath(likelyFFmpegPath);
180 }
181
182 const QString documentPath = m_doc->localFilePath();
183
184 // Initialize these settings based on last used configuration when possible..
185 if (!lastUsedOptions.lastDocumentPath.isEmpty() &&
186 lastUsedOptions.lastDocumentPath == documentPath) {
187
188 // If the file is the same as last time, we use the last used basename.
189 m_page->txtBasename->setText(lastUsedOptions.basename);
190
191 m_page->sequenceStart->setValue(lastUsedOptions.sequenceStart);
192 m_page->intWidth->setValue(lastUsedOptions.width);
193 m_page->intHeight->setValue(lastUsedOptions.height);
194
195 m_page->videoFilename->setStartDir(lastUsedOptions.resolveAbsoluteDocumentFilePath(documentPath));
196 m_page->videoFilename->setFileName(lastUsedOptions.videoFileName);
197
198 m_page->dirRequester->setStartDir(lastUsedOptions.resolveAbsoluteDocumentFilePath(documentPath));
199 m_page->dirRequester->setFileName(lastUsedOptions.directory);
200 } else {
201 m_page->sequenceStart->setValue(m_image->animationInterface()->activePlaybackRange().start());
202 m_page->intWidth->setValue(m_image->width());
203 m_page->intHeight->setValue(m_image->height());
204
205 m_page->videoFilename->setStartDir(lastUsedOptions.resolveAbsoluteDocumentFilePath(documentPath));
206 m_page->videoFilename->setFileName(defaultVideoFileName(m_doc, lastUsedOptions.videoMimeType));
207
208 m_page->dirRequester->setStartDir(lastUsedOptions.resolveAbsoluteDocumentFilePath(documentPath));
209 m_page->dirRequester->setFileName(lastUsedOptions.directory);
210 }
211
212 // Initialize FRAME render format...
213 for (int i = 0; i < m_page->cmbMimetype->count(); ++i) {
214 if (m_page->cmbMimetype->itemData(i).toString() == lastUsedOptions.frameMimeType) {
215 m_page->cmbMimetype->setCurrentIndex(i);
216 break;
217 }
218 }
219
220 for (int i = 0; i < m_page->cmbScaleFilter->count(); ++i) {
221 if (m_page->cmbScaleFilter->itemData(i).toString() == lastUsedOptions.scaleFilter) {
222 m_page->cmbScaleFilter->setCurrentIndex(i);
223 break;
224 }
225 }
226
227 // Initialize VIDEO render format...
228 for (int i = 0; i < m_page->cmbRenderType->count(); ++i) {
229 if (m_page->cmbRenderType->itemData(i).toString() == lastUsedOptions.videoMimeType) {
230 m_page->cmbRenderType->setCurrentIndex(i);
231 break;
232 }
233 }
234
235 m_page->chkOnlyUniqueFrames->setChecked(lastUsedOptions.wantsOnlyUniqueFrameSequence);
236
237 if constexpr (PLATFORM_SUPPORTS_FFMPEG) {
238 m_page->shouldExportOnlyVideo->setChecked(lastUsedOptions.shouldEncodeVideo);
239 m_page->shouldExportOnlyImageSequence->setChecked(!lastUsedOptions.shouldDeleteSequence);
240 } else {
241 m_page->shouldExportOnlyVideo->setChecked(false);
242 m_page->shouldExportOnlyVideo->setEnabled(false);
243 m_page->shouldExportOnlyVideo->setVisible(false);
244 m_page->shouldExportOnlyImageSequence->setChecked(true);
245 m_page->shouldExportOnlyImageSequence->setCheckable(false);
246 }
247
249
250 {
251 KisPropertiesConfigurationSP settings = loadLastConfiguration("VIDEO_ENCODER");
252
253 QStringList encodersPresent;
254 Q_FOREACH(const QString& key, ffmpegEncoderTypes.keys()) {
255 encodersPresent << ffmpegEncoderTypes[key];
256 }
257
258 getDefaultVideoEncoderOptions(lastUsedOptions.videoMimeType, settings,
259 encodersPresent,
262 }
263
264 {
265 KisPropertiesConfigurationSP settings = loadLastConfiguration("img_sequence/" + lastUsedOptions.frameMimeType);
266 m_wantsRenderWithHDR = settings->getPropertyLazy("saveAsHDR", m_wantsRenderWithHDR);
267 }
268
269 m_page->ffmpegLocation->setFileName(likelyFFmpegPath);
270 m_page->ffmpegLocation->setStartDir(QFileInfo(m_doc->localFilePath()).path());
271 m_page->ffmpegLocation->setReadOnlyText(true);
272
273 // Initialize these settings based on the current document context..
274 m_page->intStart->setValue(doc.image()->animationInterface()->activePlaybackRange().start());
275 m_page->intEnd->setValue(doc.image()->animationInterface()->activePlaybackRange().end());
276 m_page->intFramesPerSecond->setValue(doc.image()->animationInterface()->framerate());
277
278 if (!doc.image()->animationInterface()->exportSequenceFilePath().isEmpty()
279 && QDir(doc.image()->animationInterface()->exportSequenceFilePath()).exists() ) {
280 m_page->dirRequester->setStartDir(doc.image()->animationInterface()->exportSequenceFilePath());
281 m_page->dirRequester->setFileName(doc.image()->animationInterface()->exportSequenceFilePath());
282 }
283
284 if (!doc.image()->animationInterface()->exportSequenceBaseName().isEmpty()) {
285 m_page->txtBasename->setText(doc.image()->animationInterface()->exportSequenceBaseName());
286 }
287
288 if (doc.image()->animationInterface()->exportInitialFrameNumber() != -1) {
289 m_page->sequenceStart->setValue(doc.image()->animationInterface()->exportInitialFrameNumber());
290 }
291
292 bool hasAudioLoaded = doc.getAudioTracks().count() > 0;
293 m_page->chkIncludeAudio->setChecked(hasAudioLoaded);
294}
QString resolveAbsoluteDocumentFilePath(const QString &documentPath) const
static void getDefaultVideoEncoderOptions(const QString &mimeType, KisPropertiesConfigurationSP cfg, const QStringList &availableEncoders, QString *customFFMpegOptionsString, bool *forceHDRVideo)
static QString defaultVideoFileName(KisDocument *doc, const QString &mimeType)
static QJsonObject findFFMpeg(const QString &customLocation)
const KisTimeSpan & activePlaybackRange() const
activePlaybackRange
qint32 width() const
qint32 height() const
QString toString(const QString &value)

References KisImageAnimationInterface::activePlaybackRange(), KisImage::animationInterface(), KisAnimationRenderingOptions::basename, defaultVideoFileName(), KisAnimationRenderingOptions::directory, KisTimeSpan::end(), KisImageAnimationInterface::exportInitialFrameNumber(), KisImageAnimationInterface::exportSequenceBaseName(), KisImageAnimationInterface::exportSequenceFilePath(), ffmpegEncoderTypes, KisConfig::ffmpegLocation(), KisAnimationRenderingOptions::ffmpegPath, KisFFMpegWrapper::findFFMpeg(), KisAnimationRenderingOptions::frameMimeType, KisImageAnimationInterface::framerate(), KisDocument::getAudioTracks(), getDefaultVideoEncoderOptions(), KisImage::height(), KisAnimationRenderingOptions::height, KisDocument::image, KisAnimationRenderingOptions::lastDocumentPath, loadLastConfiguration(), KisDocument::localFilePath(), m_customFFMpegOptionsString, m_doc, m_image, m_page, m_wantsRenderWithHDR, PLATFORM_SUPPORTS_FFMPEG, KisAnimationRenderingOptions::resolveAbsoluteDocumentFilePath(), KisAnimationRenderingOptions::scaleFilter, KisAnimationRenderingOptions::sequenceStart, setFFmpegPath(), KisAnimationRenderingOptions::shouldDeleteSequence, KisAnimationRenderingOptions::shouldEncodeVideo, slotExportTypeChanged(), KisTimeSpan::start(), KisAnimationRenderingOptions::videoFileName, KisAnimationRenderingOptions::videoMimeType, KisAnimationRenderingOptions::wantsOnlyUniqueFrameSequence, KisImage::width(), and KisAnimationRenderingOptions::width.

◆ loadLastConfiguration()

KisPropertiesConfigurationSP KisDlgAnimationRenderer::loadLastConfiguration ( QString configurationID)
staticprivate

Definition at line 403 of file KisDlgAnimationRenderer.cpp.

403 {
404 KisConfig globalConfig(true);
405 return globalConfig.exportConfiguration(configurationID);
406}

References KisConfig::exportConfiguration().

◆ makeVideoMimeTypesList()

QStringList KisDlgAnimationRenderer::makeVideoMimeTypesList ( )
staticprivate

Definition at line 324 of file KisDlgAnimationRenderer.cpp.

325{
326 QStringList supportedMimeTypes = QStringList();
327 supportedMimeTypes << "video/x-matroska";
328 supportedMimeTypes << "video/mp4";
329 supportedMimeTypes << "video/webm";
330 supportedMimeTypes << "image/gif";
331 supportedMimeTypes << "image/apng";
332 supportedMimeTypes << "image/webp";
333 supportedMimeTypes << "video/ogg";
334
335 return supportedMimeTypes;
336}
QList< QString > QStringList

◆ saveLastUsedConfiguration()

void KisDlgAnimationRenderer::saveLastUsedConfiguration ( QString configurationID,
KisPropertiesConfigurationSP config )
staticprivate

Definition at line 408 of file KisDlgAnimationRenderer.cpp.

409{
410 KisConfig globalConfig(false);
411 globalConfig.setExportConfiguration(configurationID, config);
412}

References KisConfig::setExportConfiguration().

◆ selectRenderOptions

void KisDlgAnimationRenderer::selectRenderOptions ( )
privateslot

Definition at line 596 of file KisDlgAnimationRenderer.cpp.

597{
598 const int index = m_page->cmbRenderType->currentIndex();
599 const QString mimetype = m_page->cmbRenderType->itemData(index).toString();
600
603
604 QStringList encodersPresent;
605 Q_FOREACH(const QString& key, ffmpegEncoderTypes.keys()) {
606 encodersPresent << ffmpegEncoderTypes[key];
607 }
608
609 KisVideoExportOptionsDialog *encoderConfigWidget =
610 new KisVideoExportOptionsDialog(containerType, encodersPresent, this);
611
612 // we always enable HDR, letting the user to force it
613 encoderConfigWidget->setSupportsHDR(true);
614
615 {
616 KisPropertiesConfigurationSP settings = loadLastConfiguration("VIDEO_ENCODER");
617 encoderConfigWidget->setConfiguration(settings);
618 encoderConfigWidget->setHDRConfiguration(m_wantsRenderWithHDR);
619 }
620
621 KoDialog dlg(this);
622 dlg.setMainWidget(encoderConfigWidget);
623 dlg.setButtons(KoDialog::Ok | KoDialog::Cancel);
624 if (dlg.exec() == QDialog::Accepted) {
625 saveLastUsedConfiguration("VIDEO_ENCODER", encoderConfigWidget->configuration());
627 m_wantsRenderWithHDR = encoderConfigWidget->videoConfiguredForHDR();
628 }
629
630 dlg.setMainWidget(0);
631 encoderConfigWidget->deleteLater();
632}
static void saveLastUsedConfiguration(QString configurationID, KisPropertiesConfigurationSP config)
KisPropertiesConfigurationSP configuration() const override
void setConfiguration(const KisPropertiesConfigurationSP config) override
A dialog base class with standard buttons and predefined layouts.
Definition KoDialog.h:116

References KoDialog::Cancel, KisVideoExportOptionsDialog::configuration(), KisVideoExportOptionsDialog::customUserOptionsString(), ffmpegEncoderTypes, loadLastConfiguration(), m_customFFMpegOptionsString, m_page, m_wantsRenderWithHDR, KisVideoExportOptionsDialog::mimeToContainer(), KoDialog::Ok, saveLastUsedConfiguration(), KoDialog::setButtons(), KisVideoExportOptionsDialog::setConfiguration(), KisVideoExportOptionsDialog::setHDRConfiguration(), KoDialog::setMainWidget(), KisVideoExportOptionsDialog::setSupportsHDR(), and KisVideoExportOptionsDialog::videoConfiguredForHDR().

◆ selectRenderType

void KisDlgAnimationRenderer::selectRenderType ( int i)
privateslot

Definition at line 552 of file KisDlgAnimationRenderer.cpp.

553{
554 if (m_page->cmbRenderType->count() == 0) return;
555
556 const QString mimeType = m_page->cmbRenderType->itemData(index).toString();
557
558 /*
559 m_page->bnRenderOptions->setEnabled(mimeType != "image/gif" && mimeType != "image/webp" && mimeType != "image/png");
560 */
561
563
564 QString videoFileName = defaultVideoFileName(m_doc, mimeType);
565
566 if (!m_page->videoFilename->fileName().isEmpty()) {
567 const QFileInfo info = QFileInfo(m_page->videoFilename->fileName());
568 const QString baseName = info.completeBaseName();
569 const QString path = info.path();
570
571 videoFileName = QString("%1%2%3.%4")
572 .arg(path, "/", baseName, KisMimeDatabase::suffixesForMimeType(mimeType).first());
573 }
574 m_page->videoFilename->setMimeTypeFilters(QStringList() << mimeType, mimeType);
575 m_page->videoFilename->setFileName(videoFileName);
576
577 m_wantsRenderWithHDR = (mimeType == "video/mp4") ? m_wantsRenderWithHDR : false;
578
579 { // We've got to reload the render settings to account for the user changing render type without configuration.
580 // If this is removed from the configuration, ogg vorbis can fail to render on first attempt. BUG:421658
581 // This should be revisited at some point, too much configuration juggling in this class makes it error-prone...
582
583 QStringList encodersPresent;
584 Q_FOREACH(const QString& key, ffmpegEncoderTypes.keys()) {
585 encodersPresent << ffmpegEncoderTypes[key];
586 }
587
588 KisPropertiesConfigurationSP settings = loadLastConfiguration("VIDEO_ENCODER");
589 getDefaultVideoEncoderOptions(mimeType, settings,
590 encodersPresent,
593 }
594}

References defaultVideoFileName(), ffmpegEncoderTypes, ffmpegWarningCheck(), getDefaultVideoEncoderOptions(), loadLastConfiguration(), m_customFFMpegOptionsString, m_doc, m_page, m_wantsRenderWithHDR, and KisMimeDatabase::suffixesForMimeType().

◆ sequenceMimeTypeOptionsClicked

void KisDlgAnimationRenderer::sequenceMimeTypeOptionsClicked ( )
privateslot

sequenceMimeTypeSelected calls the dialog for the export widget.

Definition at line 634 of file KisDlgAnimationRenderer.cpp.

635{
636 int index = m_page->cmbMimetype->currentIndex();
637
638 KisConfigWidget *frameExportConfigWidget = 0;
639
640 QString mimetype = m_page->cmbMimetype->itemData(index).toString();
642 if (filter) {
643 frameExportConfigWidget = filter->createConfigurationWidget(0, KisDocument::nativeFormatMimeType(), mimetype.toLatin1());
644
645 if (frameExportConfigWidget) {
646
647 KisPropertiesConfigurationSP exportConfig = loadLastConfiguration("img_sequence/" + mimetype);
648 if (exportConfig) {
650 }
651
652 //Important -- m_useHDR allows the synchronization of both the video and image render settings.
653 if(imageMimeSupportsHDR(mimetype)) {
654 exportConfig->setProperty("saveAsHDR", m_wantsRenderWithHDR);
656 exportConfig->setProperty("forceSRGB", false);
657 }
658 }
659
660 frameExportConfigWidget->setConfiguration(exportConfig);
661 KoDialog dlg(this);
662 dlg.setMainWidget(frameExportConfigWidget);
663 dlg.setButtons(KoDialog::Ok | KoDialog::Cancel);
664 if (dlg.exec() == QDialog::Accepted) {
665 m_wantsRenderWithHDR = frameExportConfigWidget->configuration()->getPropertyLazy("saveAsHDR", false);
666 saveLastUsedConfiguration("img_sequence/" + mimetype, frameExportConfigWidget->configuration());
667 }
668
669 frameExportConfigWidget->hide();
670 dlg.setMainWidget(0);
671 frameExportConfigWidget->setParent(0);
672 frameExportConfigWidget->deleteLater();
673
674 }
675 }
676}
virtual KisPropertiesConfigurationSP configuration() const =0
virtual void setConfiguration(const KisPropertiesConfigurationSP config)=0
static QByteArray nativeFormatMimeType()
static KisImportExportFilter * filterForMimeType(const QString &mimetype, Direction direction)
filterForMimeType loads the relevant import/export plugin and returns it. The caller is responsible f...

References KoDialog::Cancel, KisConfigWidget::configuration(), KisImportExportManager::Export, KisImportExportManager::fillStaticExportConfigurationProperties(), KisImportExportManager::filterForMimeType(), imageMimeSupportsHDR(), loadLastConfiguration(), m_image, m_page, m_wantsRenderWithHDR, KisDocument::nativeFormatMimeType(), KoDialog::Ok, saveLastUsedConfiguration(), KoDialog::setButtons(), KisConfigWidget::setConfiguration(), and KoDialog::setMainWidget().

◆ setFFmpegPath

void KisDlgAnimationRenderer::setFFmpegPath ( const QString & path)
privateslot

Definition at line 414 of file KisDlgAnimationRenderer.cpp.

414 {
415 // Let's START with the assumption that user-specified ffmpeg path is invalid
416 // and clear out all of the ffmpeg-specific fields to fill post-validation...
417 m_page->cmbRenderType->setDisabled(true);
418 m_page->bnRenderOptions->setDisabled(true);
419
420 QString previousMimeType = m_page->cmbRenderType->currentData().toString();
421
422 m_page->cmbRenderType->clear();
423 ffmpegEncoderTypes.clear();
424
425 // Validate FFmpeg binary and setup FFMpeg...
426 if (validateFFmpeg(path)) {
427 QJsonObject ffmpegJsonObj = KisFFMpegWrapper::findFFMpeg(path);
428 ffmpegVersion = ffmpegJsonObj["enabled"].toBool() ? ffmpegJsonObj["version"].toString() : i18n("No valid FFmpeg binary supplied...");
430
431 // Build map of encoding types to their specific encoder support (e.g. h264 => libopenh264, h264, h264_vaapi or whatever)
432 Q_FOREACH(const QString& codec, ffmpegCodecs) {
433 QJsonObject codecjson = ffmpegJsonObj["codecs"].toObject()[codec].toObject();
434 if ( codecjson["encoding"].toBool() ) {
435 QJsonArray codecEncoders = codecjson["encoders"].toArray();
436
437 // In the case where no specific codec "library" is specified but we do support
438 // encoding, we simply push the type onto the list regardless. This basically
439 // means that there's no "specific" requirements that we need to meet and
440 // encoding should be possible.
441 if (codecEncoders.size() == 0) {
442 codecEncoders.push_back(QJsonValue(codec));
443 }
444
445 Q_FOREACH(const QJsonValue& value, codecEncoders) {
446 if (ffmpegEncoderTypes.contains(codec)) {
447 ffmpegEncoderTypes[codec].push_back(value.toString());
448 } else {
449 ffmpegEncoderTypes.insert(codec, {value.toString()} );
450 }
451 }
452 }
453 }
454
455 KisConfig cfg(false);
456
457 { // Build list of supported container types and repopulate cmbRenderType.
458 KisSignalsBlocker(m_page->cmbRenderType);
459
460 QStringList supportedMimeTypes = makeVideoMimeTypesList();
461 supportedMimeTypes = filterMimeTypeListByAvailableEncoders(supportedMimeTypes);
462
463 int previousMimeTypeIndex = -1;
464 Q_FOREACH (const QString &mime, supportedMimeTypes) {
465 QString description = KisMimeDatabase::descriptionForMimeType(mime);
466 if (description.isEmpty()) {
467 description = mime;
468 }
469
470 m_page->cmbRenderType->addItem(description, mime);
471 if (mime == previousMimeType) {
472 previousMimeTypeIndex = m_page->cmbRenderType->count() - 1;
473 }
474 }
475
476 const int indexCount = m_page->cmbRenderType->count();
477 if (indexCount > 0) {
478 if (previousMimeTypeIndex >= 0) {
479 m_page->cmbRenderType->setCurrentIndex(previousMimeTypeIndex % indexCount);
480 } else {
481 m_page->cmbRenderType->setCurrentIndex(0);
482 }
483
484 selectRenderType(m_page->cmbRenderType->currentIndex());
485 m_page->cmbRenderType->setDisabled(false);
486 m_page->bnRenderOptions->setDisabled(false);
487 connect(m_page->cmbRenderType, SIGNAL(currentIndexChanged(int)), this, SLOT(selectRenderType(int)));
488 }
489 }
490
491 m_page->lblFFMpegVersion->setText(ffmpegVersion);
492
493 // Store configuration..
494 cfg.setFFMpegLocation(ffmpegJsonObj["path"].toString());
495
497 }
498}
float value(const T *src, size_t ch)
QStringList filterMimeTypeListByAvailableEncoders(const QStringList &mimeTypes)
FFmpegValidationResult validateFFmpeg(const QString &ffmpegPath)
static QStringList makeVideoMimeTypesList()
static QStringList getSupportedCodecs(const QJsonObject &ffmpegJsonProcessInput)

References KisMimeDatabase::descriptionForMimeType(), ffmpegCodecs, ffmpegEncoderTypes, ffmpegVersion, ffmpegWarningCheck(), filterMimeTypeListByAvailableEncoders(), KisFFMpegWrapper::findFFMpeg(), KisFFMpegWrapper::getSupportedCodecs(), m_page, makeVideoMimeTypesList(), selectRenderType(), KisConfig::setFFMpegLocation(), validateFFmpeg(), and value().

◆ slotButtonClicked

void KisDlgAnimationRenderer::slotButtonClicked ( int button)
overrideprotectedslot

Definition at line 755 of file KisDlgAnimationRenderer.cpp.

756{
757 if (button == KoDialog::Ok && (PLATFORM_SUPPORTS_FFMPEG && !m_page->shouldExportOnlyImageSequence->isChecked())) {
758 QString fileName = m_page->videoFilename->fileName();
759
760 if (fileName.isEmpty()) {
761 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("Please enter a file name to render to."));
762 return;
763 }
764 else {
765 switch (validateFFmpeg(m_page->ffmpegLocation->fileName())) {
767 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("The FFmpeg that you've given us appears to be compressed. Please try to extract FFmpeg from the archive first."));
768 return;
770 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("The FFmpeg that you've given us appears to be invalid. Please select the correct location of an FFmpeg executable on your system."));
771 return;
772 default:
773 break;
774 }
775 }
776 }
778}
virtual void slotButtonClicked(int button)
Definition KoDialog.cpp:811
QPushButton * button(ButtonCode id) const
Definition KoDialog.cpp:582

References KoDialog::button(), COMPRESSED_FORMAT, m_page, NOT_A_BINARY, KoDialog::Ok, PLATFORM_SUPPORTS_FFMPEG, KoDialog::slotButtonClicked(), and validateFFmpeg().

◆ slotDialogAccepted

void KisDlgAnimationRenderer::slotDialogAccepted ( )
protectedslot

Definition at line 780 of file KisDlgAnimationRenderer.cpp.

781{
782 KisConfig cfg(false);
784 saveLastUsedConfiguration("ANIMATION_EXPORT", options.toProperties());
785
789}
KisPropertiesConfigurationSP toProperties() const
KisAnimationRenderingOptions getEncoderOptions() const
void setExportSequenceBaseName(const QString &baseName)
void setExportInitialFrameNumber(const int frameNum)
void setExportSequenceFilePath(const QString &filePath)

References KisImage::animationInterface(), KisAnimationRenderingOptions::basename, KisAnimationRenderingOptions::directory, getEncoderOptions(), m_image, saveLastUsedConfiguration(), KisAnimationRenderingOptions::sequenceStart, KisImageAnimationInterface::setExportInitialFrameNumber(), KisImageAnimationInterface::setExportSequenceBaseName(), KisImageAnimationInterface::setExportSequenceFilePath(), and KisAnimationRenderingOptions::toProperties().

◆ slotExportTypeChanged

void KisDlgAnimationRenderer::slotExportTypeChanged ( )
privateslot

A fallback fix for a case when both checkboxes are unchecked

Definition at line 791 of file KisDlgAnimationRenderer.cpp.

792{
793 if constexpr (PLATFORM_SUPPORTS_FFMPEG) {
794 // if a video format needs to be outputted
795 if (m_page->shouldExportOnlyVideo->isChecked()) {
796 // videos always uses PNG for creating video, so disable the ability to change the format
797 m_page->cmbMimetype->setEnabled(false);
798 m_page->cmbMimetype->setCurrentIndex(m_page->cmbMimetype->findData("image/png"));
799 }
800
804 if (!m_page->shouldExportOnlyVideo->isChecked() &&
805 !m_page->shouldExportOnlyImageSequence->isChecked()) {
806
807 KisSignalsBlocker b(m_page->shouldExportOnlyImageSequence);
808 m_page->shouldExportOnlyImageSequence->setChecked(true);
809 }
810 } else {
811 KisSignalsBlocker b(m_page->shouldExportOnlyImageSequence);
812 m_page->shouldExportOnlyImageSequence->setChecked(true);
813 }
814}

References m_page, and PLATFORM_SUPPORTS_FFMPEG.

◆ slotLockAspectRatioDimensionsHeight

void KisDlgAnimationRenderer::slotLockAspectRatioDimensionsHeight ( int height)
privateslot

Definition at line 835 of file KisDlgAnimationRenderer.cpp.

836{
837 Q_UNUSED(height);
838
839 float aspectRatio = (float)m_image->width() / (float)m_image->height();
840
841 // update width here
842 float newWidth = aspectRatio * m_page->intHeight->value();
843
844 m_page->intWidth->setValue(newWidth);
845}

References KisImage::height(), m_image, m_page, and KisImage::width().

◆ slotLockAspectRatioDimensionsWidth

void KisDlgAnimationRenderer::slotLockAspectRatioDimensionsWidth ( int width)
privateslot

Definition at line 822 of file KisDlgAnimationRenderer.cpp.

823{
824 Q_UNUSED(width);
825
826 float aspectRatio = (float)m_image->width() / (float)m_image->height();
827
828 // update height here
829 float newHeight = m_page->intWidth->value() / aspectRatio ;
830
831 m_page->intHeight->setValue(newHeight);
832
833}

References KisImage::height(), m_image, m_page, and KisImage::width().

◆ validateFFmpeg()

KisDlgAnimationRenderer::FFmpegValidationResult KisDlgAnimationRenderer::validateFFmpeg ( const QString & ffmpegPath)
private

Definition at line 736 of file KisDlgAnimationRenderer.cpp.

737{
738 if (!ffmpegPath.isEmpty()) {
739 QFileInfo ffmpegBinary(ffmpegPath);
740 if (ffmpegBinary.exists() && ffmpegBinary.isExecutable()) {
741 QStringList commpressedFormats{"zip", "7z", "tar.bz2"};
742 Q_FOREACH(const QString& compressedFormat, commpressedFormats) {
743 if (ffmpegBinary.fileName().endsWith(compressedFormat)) {
745 }
746 }
748 } else if (ffmpegBinary.exists()) {
750 }
751 }
753}

References COMPRESSED_FORMAT, INVALID, NOT_A_BINARY, and VALID.

Member Data Documentation

◆ ffmpegCodecs

QStringList KisDlgAnimationRenderer::ffmpegCodecs = QStringList()
private

Definition at line 114 of file KisDlgAnimationRenderer.h.

◆ ffmpegEncoderTypes

QMap<QString, QStringList> KisDlgAnimationRenderer::ffmpegEncoderTypes
private

Definition at line 115 of file KisDlgAnimationRenderer.h.

◆ ffmpegVersion

QString KisDlgAnimationRenderer::ffmpegVersion = "None"
private

Definition at line 112 of file KisDlgAnimationRenderer.h.

◆ m_customFFMpegOptionsString

QString KisDlgAnimationRenderer::m_customFFMpegOptionsString
private

Definition at line 111 of file KisDlgAnimationRenderer.h.

◆ m_doc

KisDocument* KisDlgAnimationRenderer::m_doc
private

Definition at line 109 of file KisDlgAnimationRenderer.h.

◆ m_image

KisImageSP KisDlgAnimationRenderer::m_image
private

Definition at line 108 of file KisDlgAnimationRenderer.h.

◆ m_page

WdgAnimationRenderer* KisDlgAnimationRenderer::m_page {0}
private

Definition at line 119 of file KisDlgAnimationRenderer.h.

119{0};

◆ m_wantsRenderWithHDR

bool KisDlgAnimationRenderer::m_wantsRenderWithHDR = false
private

Definition at line 117 of file KisDlgAnimationRenderer.h.

◆ PLATFORM_SUPPORTS_FFMPEG

constexpr bool KisDlgAnimationRenderer::PLATFORM_SUPPORTS_FFMPEG = true
staticconstexprprivate

Definition at line 77 of file KisDlgAnimationRenderer.h.


The documentation for this class was generated from the following files: