[graphics/krita/krita/6.0] libs/ui/animation: Warn about crazy animation export parameters

Carsten Hartenfels <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 17a0faeb9ba56b91e2aa1175217176e6a7d6f799 by Carsten Hartenfels.
Committed on 27/07/2026 at 17:19.
Pushed by hartenfels into branch 'krita/6.0'.

Warn about crazy animation export parameters

FPS above 30 and dimensions beyond 1920 in either direction, since those
can cause some exporters to fail and some devices to refuse to play back
the resulting file. This is analogous to the timelapse export dialog.

This also fixes the flicker of the warning dialog a bit by disabling
updates during its refresh and doesn't show the warnings about video
issues when the user isn't exporting video.

M  +43   -20   libs/ui/animation/KisDlgAnimationRenderer.cpp
M  +1    -2    libs/ui/animation/KisDlgAnimationRenderer.h

https://invent.kde.org/graphics/krita/-/commit/17a0faeb9ba56b91e2aa1175217176e6a7d6f799

diff --git a/libs/ui/animation/KisDlgAnimationRenderer.cpp b/libs/ui/animation/KisDlgAnimationRenderer.cpp
index f226b16d8a2..b113ec203b3 100644
--- a/libs/ui/animation/KisDlgAnimationRenderer.cpp
+++ b/libs/ui/animation/KisDlgAnimationRenderer.cpp
@@ -145,7 +145,9 @@ KisDlgAnimationRenderer::KisDlgAnimationRenderer(KisDocument *doc, QWidget *pare
         connect(m_page->shouldExportOnlyImageSequence, SIGNAL(toggled(bool)), this, SLOT(slotExportTypeChanged()));
         connect(m_page->shouldExportOnlyVideo, SIGNAL(toggled(bool)), this, SLOT(slotExportTypeChanged()));
 
-        connect(m_page->intFramesPerSecond, SIGNAL(valueChanged(int)), SLOT(frameRateChanged(int)));
+        connect(m_page->intFramesPerSecond, SIGNAL(valueChanged(int)), SLOT(slotCheckWarnings()));
+        connect(m_page->intWidth, SIGNAL(valueChanged(int)), SLOT(slotCheckWarnings()));
+        connect(m_page->intHeight, SIGNAL(valueChanged(int)), SLOT(slotCheckWarnings()));
 
 #ifndef Q_OS_ANDROID
         connect(m_page->ffmpegLocation, SIGNAL(fileSelected(QString)), SLOT(setFFmpegPath(QString)));
@@ -169,6 +171,7 @@ KisDlgAnimationRenderer::KisDlgAnimationRenderer(KisDocument *doc, QWidget *pare
     }
 
     setMainWidget(m_page);
+    slotCheckWarnings();
 }
 
 KisDlgAnimationRenderer::~KisDlgAnimationRenderer()
@@ -573,31 +576,47 @@ void KisDlgAnimationRenderer::setFFmpegPath(const QString& path) {
         // Store configuration..
         cfg.setFFMpegLocation(ffmpegJsonObj["path"].toString());
 
-        checkWarnings();
+        slotCheckWarnings();
     }
 }
 #endif
 
-void KisDlgAnimationRenderer::checkWarnings()
+void KisDlgAnimationRenderer::slotCheckWarnings()
 {
+    setUpdatesEnabled(false);
     QStringList warnings;
+    bool exportMayFail = false;
 
-    QString videoType = m_page->cmbRenderType->itemData(m_page->cmbRenderType->currentIndex()).toString();
-    bool gif = looksLikeGif(videoType);
+    if (m_page->shouldExportOnlyVideo->isChecked()) {
+        QString videoType = m_page->cmbRenderType->itemData(m_page->cmbRenderType->currentIndex()).toString();
+        bool gif = looksLikeGif(videoType);
 
 #ifndef Q_OS_ANDROID
-    const QRegularExpression minVerFFMpegRX(R"(^n{0,1}(?:[0-3]|4\.[01])[\.\-])");
-    const QRegularExpressionMatch minVerFFMpegMatch = minVerFFMpegRX.match(ffmpegVersion);
+        const QRegularExpression minVerFFMpegRX(R"(^n{0,1}(?:[0-3]|4\.[01])[\.\-])");
+        const QRegularExpressionMatch minVerFFMpegMatch = minVerFFMpegRX.match(ffmpegVersion);
 
-    if (gif && minVerFFMpegMatch.hasMatch()) {
-        warnings << i18nc("ffmpeg warning checks", "FFmpeg must be at least version 4.2+ for GIF transparency to work");
-    }
+        if (gif && minVerFFMpegMatch.hasMatch()) {
+            warnings << i18nc("ffmpeg warning checks",
+                              "FFmpeg must be at least version 4.2+ for GIF transparency to work");
+        }
 #endif
 
-    if (gif && m_page->intFramesPerSecond->value() > 50) {
-        warnings << i18nc("ffmpeg warning checks",
-                          "Animated GIF images cannot have a framerate higher than 50. The framerate will be reduced "
-                          "to 50 frames per second");
+        int fps = m_page->intFramesPerSecond->value();
+        if (gif && fps > 50) {
+            warnings << i18nc("ffmpeg warning checks",
+                              "Animated GIF images cannot have a framerate higher than 50. The framerate will be "
+                              "reduced to 50 frames per second");
+        }
+
+        if (fps > 30) {
+            exportMayFail = true;
+            warnings << i18nc("ffmpeg warning checks", "FPS beyond 30 are not widely supported.");
+        }
+
+        if (m_page->intWidth->value() > 1920 || m_page->intHeight->value() > 1920) {
+            exportMayFail = true;
+            warnings << i18nc("ffmpeg warnings checks", "Dimensions larger than 1920 pixels are not widely supported.");
+        }
     }
 
     m_page->lblWarnings->setVisible(!warnings.isEmpty());
@@ -611,6 +630,13 @@ void KisDlgAnimationRenderer::checkWarnings()
             text.append("</li>");
         }
         text.append("</ul></p>");
+        if (exportMayFail) {
+            text.append(QStringLiteral("<p>"));
+            text.append(
+                i18nc("ffmpeg warning checks", "The export may fail and some devices may not be able to play it.")
+                    .toHtmlEscaped());
+            text.append(QStringLiteral("</p>"));
+        }
         m_page->lblWarnings->setText(text);
 
         m_page->lblWarnings->setPixmap(
@@ -618,6 +644,7 @@ void KisDlgAnimationRenderer::checkWarnings()
     }
 
     m_page->adjustSize();
+    setUpdatesEnabled(true);
 }
 
 #ifndef Q_OS_ANDROID
@@ -639,7 +666,7 @@ void KisDlgAnimationRenderer::selectRenderType(int index)
 
     const QString mimeType = m_page->cmbRenderType->itemData(index).toString();
 
-    checkWarnings();
+    slotCheckWarnings();
 
     QString videoFileName = defaultVideoFileName(m_doc, mimeType);
 
@@ -931,12 +958,8 @@ void KisDlgAnimationRenderer::slotExportTypeChanged()
          KisSignalsBlocker b(m_page->shouldExportOnlyImageSequence);
          m_page->shouldExportOnlyImageSequence->setChecked(true);
     }
-}
 
-void KisDlgAnimationRenderer::frameRateChanged(int framerate)
-{
-    Q_UNUSED(framerate);
-    checkWarnings();
+    slotCheckWarnings();
 }
 
 void KisDlgAnimationRenderer::slotLockAspectRatioDimensionsWidth(int width)
diff --git a/libs/ui/animation/KisDlgAnimationRenderer.h b/libs/ui/animation/KisDlgAnimationRenderer.h
index be295b2e248..85e2e9e2275 100644
--- a/libs/ui/animation/KisDlgAnimationRenderer.h
+++ b/libs/ui/animation/KisDlgAnimationRenderer.h
@@ -69,7 +69,7 @@ private Q_SLOTS:
     void setFFmpegPath(const QString& path);
 #endif
 
-    void frameRateChanged(int framerate);
+    void slotCheckWarnings();
 
 protected Q_SLOTS:
 #ifndef Q_OS_ANDROID
@@ -90,7 +90,6 @@ private:
 
     void initializeRenderSettings(const KisDocument &doc, const KisAnimationRenderingOptions &lastUsedOptions);
 
-    void checkWarnings();
 #ifndef Q_OS_ANDROID
     FFmpegValidationResult validateFFmpeg(const QString &ffmpegPath);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.