Add options for render animation dialog: height, width, frames per second
AbandonedPublic

Authored by scottpetrovic on Sep 14 2017, 11:10 PM.

Details

Reviewers
dkazakov
Group Reviewers
Krita
Summary

This forwards on a few more parameters from the GUI to FFMPEG for rendering the animation. I also added a scale slider, so it is easier to scale the entire dimensions down by percentage. Blender does this and I thought it is a good idea. The aspect ratio is always locked with these actions. Making it unlocked created complications with the scale slider.

I talked with Bollebib and these were the use cases:

  1. faster to encode videos with smaller image sizes
  2. sometimes clients like to see animations slowed down (changing the FPS)

For point one, right now the only way to do this is to directly modify the image size. This has a negative effect of you forgetting you did it and potentially saving over the file.

Note: it is possible that the dimensions don't follow the aspect ratio exactly. In this case, ffmpeg will tweak the values to make sure it works. I thought this was a better solution than the render giving an error.

Test Plan
  1. make a test file for animation with a few animation frames
  2. Bring up the render animation dialog

test the following things and export to test the output:

  1. change the width. the height should change to be the same (or close) aspect ratio
  2. use the scale slider and watch the height and width inputs update
  3. change the FPS and watch the animation speed up and slow down.
  4. re-open the render dialog. The FPS, height, and width should be remembered from the last render

I tested this on my KDE Neon box.

Diff Detail

Repository
R37 Krita
Lint
Lint Skipped
Unit
Unit Tests Skipped
scottpetrovic created this revision.Sep 14 2017, 11:10 PM
rempt added a subscriber: rempt.Sep 25 2017, 8:23 AM

Aw, I'm too late... The patch no longer applies to master!

dkazakov requested changes to this revision.Sep 25 2017, 2:29 PM
dkazakov added a subscriber: dkazakov.

I'll mark the patch as Needs Changes.

After my refactoring to make rendering multithreaded the patch doesn't apply anymore :(

  1. KisAnimationExportSaver was split into two classes: KisAsyncAnimationFramesSaveDialog and KisAsyncAnimationFramesSavingRenderer
  2. As far as I can tell, now the options should be passed to KisAsyncAnimationFramesSavingRenderer
This revision now requires changes to proceed.Sep 25 2017, 2:29 PM

updated diff. I pulled latest and did a diff against it with fixes. Hopefully it will apply now.

rempt added a comment.Sep 27 2017, 7:52 AM

It does apply, but doesn't build:

[ 45%] Building CXX object libs/ui/tests/CMakeFiles/kritaui-animation_exporter_test.dir/kis_animation_exporter_test.cpp.o
/home/boud/dev/krita/libs/ui/tests/kis_animation_exporter_test.cpp: In member function ‘void KisAnimationExporterTest::testAnimationExport()’:
/home/boud/dev/krita/libs/ui/tests/kis_animation_exporter_test.cpp:71:52: error: no matching function for call to ‘KisAsyncAnimationFramesSaveDialog::KisAsyncAnimationFramesSaveDialog(KisImageWSP, KisTimeRange, const char [16], int, int)’

0, 0);
    ^

/home/boud/dev/krita/libs/ui/tests/kis_animation_exporter_test.cpp:71:52: note: candidate is:
In file included from /home/boud/dev/krita/libs/ui/tests/kis_animation_exporter_test.cpp:21:0:
/home/boud/dev/krita/libs/ui/dialogs/KisAsyncAnimationFramesSaveDialog.h:29:5: note: KisAsyncAnimationFramesSaveDialog::KisAsyncAnimationFramesSaveDialog(KisImageSP, const KisTimeRange&, const QString&, int, int, int, int, KisPropertiesConfigurationSP)

KisAsyncAnimationFramesSaveDialog(KisImageSP image,
^

/home/boud/dev/krita/libs/ui/dialogs/KisAsyncAnimationFramesSaveDialog.h:29:5: note: candidate expects 8 arguments, 5 provided
libs/ui/tests/CMakeFiles/kritaui-animation_exporter_test.dir/build.make:62: recipe for target 'libs/ui/tests/CMakeFiles/kritaui-animation_exporter_test.dir/kis_animation_exporter_test.cpp.o' failed
make[2]: * [libs/ui/tests/CMakeFiles/kritaui-animation_exporter_test.dir/kis_animation_exporter_test.cpp.o] Error 1
CMakeFiles/Makefile2:18240: recipe for target 'libs/ui/tests/CMakeFiles/kritaui-animation_exporter_test.dir/all' failed
make[1]:
* [libs/ui/tests/CMakeFiles/kritaui-animation_exporter_test.dir/all] Error 2
Makefile:138: recipe for target 'all' failed
make: *** [all] Error 2
boud@linux-s09k:~/dev/b-krita>

I evidently wasn't building tests before. I fixed a couple tests that needed them. It should build ok now with the new patch.

dkazakov requested changes to this revision.Oct 2 2017, 8:04 PM

Hi, @scottpetrovic!

There are four issues with the patch:

  1. The FPS setting has no effect on the saved file. As far as I can see, it has just been forgotten to connect the option to the real saving code in video_saver.cpp (see inline comment).
  2. The FPS setting is not saved into the "last used setting". Every time I click "Render Animation" the input box is reset to the default value (25fps) instead of sowing me the last used value.
  3. In the options to ffmpeg you pass "force original aspect ratio". It may cause some weird failures: e.g. you cannot export a FullHD file into 300x168, because ffmpeg tries to round it again and gets 299x168, which is odd number and is not supported by the codec. Here is a log file:
  4. When I change values in the "Width/Height" spinboxes in the dialog, the "Scale" slider is not updated automatically, which looks like a bug.
plugins/impex/video/video_saver.cpp
232

This value is not used. The patch uses animation->framerate() instead which is the image's framerate, not the one chosen in the saving dialog

This revision now requires changes to proceed.Oct 2 2017, 8:04 PM

hi @dkazakov

I made most of the updates. I was having a hard time trying to reproduce point 3 with failed renders at specific image sizes. This is what I was trying.

  1. Create image at 1920 x 1080
  2. render animation at 300 x 168. The exported render gives me --> 299 x 168
  3. render animation at 299 x 168. The exported render gives me --> 299 x 168

The main point of the force_original_aspect_ratio setting was to eliminate the errors like you got. I thought maybe that the "force_original_aspect_ratio=decrease" wasn't supported in your version of ffmpeg, but I am also using 2.8.11 (on KDE Neon)

I have seen online that can get similar results by using this other way (-vf scale="'if(gt(iw,ih),640,-1)':'if(gt(iw,ih),-1,480)'"), but I am having a hard time telling if that would make a difference. Could you test the patch out and see if you are still having issues with the export. The other points should be cleared up.

dkazakov requested changes to this revision.Oct 9 2017, 8:09 AM

Hi, @scottpetrovic!

There are three small issues. Two of them are inlined, and the third one is the following:

  1. When "Image Sequence" exporting mode is selected, it is not useful to show "Width/Height/Fps" input boxes. They are not used by anything. You can simply disable them in that case.

plugins/extensions/animationrenderer/DlgAnimationRenderer.cpp
613

As far as I can see, you have removed the percentage slider at all, so this method seems to be unused anymore...

plugins/impex/video/video_saver.cpp
242

Could you skip adding these "filter options" in case the scaled size is the same as the image size?

I'm not sure if ffmpeg is clever enough to skip the filtering at all when the the filter basically doesn't scale anything. Applying a filter one more time can decrease image quality :(

This revision now requires changes to proceed.Oct 9 2017, 8:09 AM

hi @dkazakov

Thanks for doing this review! These are the changes I made

  • The image sequence was suppose to have the ability to change the export size, so I fixed that and images appear to be getting exported at the specified size
  • The FPS area now hides if you are only exporting out the image sequence
  • I am only applying the scaling filters now if the video is being scaled.

removed a couple qDebug that I was only using for testing

Hi, @scottpetrovic!

Here is a patch that fixes the following issues:

  1. Removes unused width and height options when no rendering is activated
  2. Fixes a misprint in the default value for FPS (it fetched image height instead)
  3. Makes it not store the the properties in all the configurations. Only encoding configuration needs this info

If you are okay with my changes, just push the combined patch into master :)

1diff --git a/benchmarks/KisAnimationRenderingBenchmark.cpp b/benchmarks/KisAnimationRenderingBenchmark.cpp
2index 9c1f6fb..29e2b19 100644
3--- a/benchmarks/KisAnimationRenderingBenchmark.cpp
4+++ b/benchmarks/KisAnimationRenderingBenchmark.cpp
5@@ -54,7 +54,7 @@ void runRenderingTest(KisImageSP image, int numCores, int numClones)
6
7 const KisTimeRange range = image->animationInterface()->fullClipRange();
8
9- KisAsyncAnimationFramesSaveDialog dlg(image, range, "temp_frames.png", 0, image->height(), image->width(), 24, 0);
10+ KisAsyncAnimationFramesSaveDialog dlg(image, range, "temp_frames.png", 0, 0);
11 dlg.setBatchMode(true);
12
13 // repeat rendering twice!
14diff --git a/libs/ui/KisAsyncAnimationFramesSavingRenderer.cpp b/libs/ui/KisAsyncAnimationFramesSavingRenderer.cpp
15index 83c4d2f..5478ba8 100644
16--- a/libs/ui/KisAsyncAnimationFramesSavingRenderer.cpp
17+++ b/libs/ui/KisAsyncAnimationFramesSavingRenderer.cpp
18@@ -29,12 +29,9 @@
19
20 struct KisAsyncAnimationFramesSavingRenderer::Private
21 {
22- Private(KisImageSP image, const KisTimeRange &_range, int _height, int _width, int _framerate, int _sequenceNumberingOffset, KisPropertiesConfigurationSP _exportConfiguration)
23+ Private(KisImageSP image, const KisTimeRange &_range, int _sequenceNumberingOffset, KisPropertiesConfigurationSP _exportConfiguration)
24 : savingDoc(KisPart::instance()->createDocument()),
25 range(_range),
26- heightExport(_height),
27- widthExport(_width),
28- fps(_framerate),
29 sequenceNumberingOffset(_sequenceNumberingOffset),
30 exportConfiguration(_exportConfiguration)
31 {
32@@ -43,8 +40,8 @@ struct KisAsyncAnimationFramesSavingRenderer::Private
33 savingDoc->setFileBatchMode(true);
34
35 KisImageSP savingImage = new KisImage(savingDoc->createUndoStore(),
36- _width,
37- _height,
38+ image->bounds().width(),
39+ image->bounds().height(),
40 image->colorSpace(),
41 QString());
42
43@@ -61,9 +58,6 @@ struct KisAsyncAnimationFramesSavingRenderer::Private
44 KisPaintDeviceSP savingDevice;
45
46 KisTimeRange range;
47- int heightExport;
48- int widthExport;
49- int fps;
50 int sequenceNumberingOffset = 0;
51
52
53@@ -80,11 +74,8 @@ KisAsyncAnimationFramesSavingRenderer::KisAsyncAnimationFramesSavingRenderer(Kis
54 const QByteArray &outputMimeType,
55 const KisTimeRange &range,
56 const int sequenceNumberingOffset,
57- int height,
58- int width,
59- int framerate,
60 KisPropertiesConfigurationSP exportConfiguration)
61- : m_d(new Private(image, range, height, width, framerate, sequenceNumberingOffset, exportConfiguration))
62+ : m_d(new Private(image, range, sequenceNumberingOffset, exportConfiguration))
63 {
64 m_d->filenamePrefix = fileNamePrefix;
65 m_d->filenameSuffix = fileNameSuffix;
66diff --git a/libs/ui/KisAsyncAnimationFramesSavingRenderer.h b/libs/ui/KisAsyncAnimationFramesSavingRenderer.h
67index b275a09..6dffff6 100644
68--- a/libs/ui/KisAsyncAnimationFramesSavingRenderer.h
69+++ b/libs/ui/KisAsyncAnimationFramesSavingRenderer.h
70@@ -34,9 +34,6 @@ public:
71 const QByteArray &outputMimeType,
72 const KisTimeRange &range,
73 int sequenceNumberingOffset,
74- int height,
75- int width,
76- int framerate,
77 KisPropertiesConfigurationSP exportConfiguration);
78 ~KisAsyncAnimationFramesSavingRenderer();
79
80diff --git a/libs/ui/dialogs/KisAsyncAnimationFramesSaveDialog.cpp b/libs/ui/dialogs/KisAsyncAnimationFramesSaveDialog.cpp
81index 46f9f94..dadcea0 100644
82--- a/libs/ui/dialogs/KisAsyncAnimationFramesSaveDialog.cpp
83+++ b/libs/ui/dialogs/KisAsyncAnimationFramesSaveDialog.cpp
84@@ -35,16 +35,10 @@ struct KisAsyncAnimationFramesSaveDialog::Private {
85 const KisTimeRange &_range,
86 const QString &baseFilename,
87 int _sequenceNumberingOffset,
88- int _heightExport,
89- int _widthExport,
90- int _fps,
91 KisPropertiesConfigurationSP _exportConfiguration)
92 : originalImage(_image),
93 range(_range),
94 sequenceNumberingOffset(_sequenceNumberingOffset),
95- heightExport(_heightExport),
96- widthExport(_widthExport),
97- fps(_fps),
98 exportConfiguration(_exportConfiguration)
99 {
100 int baseLength = baseFilename.lastIndexOf(".");
101@@ -60,10 +54,6 @@ struct KisAsyncAnimationFramesSaveDialog::Private {
102
103 KisImageSP originalImage;
104 KisTimeRange range;
105- int heightExport;
106- int widthExport;
107- int fps;
108-
109
110 QString filenamePrefix;
111 QString filenameSuffix;
112@@ -77,12 +67,9 @@ KisAsyncAnimationFramesSaveDialog::KisAsyncAnimationFramesSaveDialog(KisImageSP
113 const KisTimeRange &range,
114 const QString &baseFilename,
115 int sequenceNumberingOffset,
116- int heightExport,
117- int widthExport,
118- int fps,
119 KisPropertiesConfigurationSP exportConfiguration)
120 : KisAsyncAnimationRenderDialogBase("Saving frames...", originalImage, 0),
121- m_d(new Private(originalImage, range, baseFilename, sequenceNumberingOffset, heightExport, widthExport, fps, exportConfiguration))
122+ m_d(new Private(originalImage, range, baseFilename, sequenceNumberingOffset, exportConfiguration))
123 {
124
125
126@@ -172,9 +159,6 @@ KisAsyncAnimationRendererBase *KisAsyncAnimationFramesSaveDialog::createRenderer
127 m_d->outputMimeType,
128 m_d->range,
129 m_d->sequenceNumberingOffset,
130- m_d->heightExport,
131- m_d->widthExport,
132- m_d->fps,
133 m_d->exportConfiguration);
134 }
135
136diff --git a/libs/ui/dialogs/KisAsyncAnimationFramesSaveDialog.h b/libs/ui/dialogs/KisAsyncAnimationFramesSaveDialog.h
137index 2534172..dca29ab 100644
138--- a/libs/ui/dialogs/KisAsyncAnimationFramesSaveDialog.h
139+++ b/libs/ui/dialogs/KisAsyncAnimationFramesSaveDialog.h
140@@ -30,9 +30,6 @@ public:
141 const KisTimeRange &range,
142 const QString &baseFilename,
143 int sequenceNumberingOffset,
144- int heightExport,
145- int widthExport,
146- int fps,
147 KisPropertiesConfigurationSP exportConfiguration);
148
149 ~KisAsyncAnimationFramesSaveDialog();
150diff --git a/libs/ui/tests/kis_animation_exporter_test.cpp b/libs/ui/tests/kis_animation_exporter_test.cpp
151index 30e3ccc..f44a2a3 100644
152--- a/libs/ui/tests/kis_animation_exporter_test.cpp
153+++ b/libs/ui/tests/kis_animation_exporter_test.cpp
154@@ -69,9 +69,6 @@ void KisAnimationExporterTest::testAnimationExport()
155 KisTimeRange::fromTime(0,2),
156 "export-test.png",
157 0,
158- document->image()->height(),
159- document->image()->width(),
160- 24,
161 0);
162
163
164diff --git a/plugins/extensions/animationrenderer/AnimationRenderer.cpp b/plugins/extensions/animationrenderer/AnimationRenderer.cpp
165index 9b9c40f..bb56d32 100644
166--- a/plugins/extensions/animationrenderer/AnimationRenderer.cpp
167+++ b/plugins/extensions/animationrenderer/AnimationRenderer.cpp
168@@ -106,9 +106,6 @@ void AnimaterionRenderer::slotRenderAnimation()
169 KisTimeRange::fromTime(sequenceConfig->getInt("first_frame"), sequenceConfig->getInt("last_frame")),
170 baseFileName,
171 sequenceConfig->getInt("sequence_start"),
172- sequenceConfig->getInt("height"),
173- sequenceConfig->getInt("width"),
174- sequenceConfig->getInt("framerate"),
175 dlgAnimationRenderer.getFrameExportConfiguration());
176 exporter.setBatchMode(batchMode);
177
178@@ -198,9 +195,6 @@ void AnimaterionRenderer::slotRenderSequenceAgain()
179 KisTimeRange::fromTime(sequenceConfig->getInt("first_frame"), sequenceConfig->getInt("last_frame")),
180 baseFileName,
181 sequenceConfig->getInt("sequence_start"),
182- sequenceConfig->getInt("height"),
183- sequenceConfig->getInt("width"),
184- sequenceConfig->getInt("framerate"),
185 0);
186 exporter.setBatchMode(batchMode);
187 bool success = exporter.regenerateRange(0) == KisAsyncAnimationFramesSaveDialog::RenderComplete;
188diff --git a/plugins/extensions/animationrenderer/DlgAnimationRenderer.cpp b/plugins/extensions/animationrenderer/DlgAnimationRenderer.cpp
189index 38650f8..00d070b 100644
190--- a/plugins/extensions/animationrenderer/DlgAnimationRenderer.cpp
191+++ b/plugins/extensions/animationrenderer/DlgAnimationRenderer.cpp
192@@ -251,9 +251,6 @@ KisPropertiesConfigurationSP DlgAnimationRenderer::getSequenceConfiguration() co
193 cfg->setProperty("directory", fetchRenderingDirectory());
194 cfg->setProperty("first_frame", m_page->intStart->value());
195 cfg->setProperty("last_frame", m_page->intEnd->value());
196- cfg->setProperty("framerate", m_page->intFramesPerSecond->value());
197- cfg->setProperty("height", m_page->intHeight->value());
198- cfg->setProperty("width", m_page->intWidth->value());
199 cfg->setProperty("sequence_start", m_page->sequenceStart->value());
200 cfg->setProperty("mimetype", m_page->cmbMimetype->currentData().toString());
201 return cfg;
202@@ -267,19 +264,12 @@ void DlgAnimationRenderer::setSequenceConfiguration(KisPropertiesConfigurationSP
203 cfg->removeProperty("first_frame");
204 cfg->removeProperty("last_frame");
205 cfg->removeProperty("sequence_start");
206- cfg->removeProperty("height");
207- cfg->removeProperty("width");
208- cfg->removeProperty("framerate");
209 }
210
211 m_page->dirRequester->setFileName(cfg->getString("directory", QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)));
212 m_page->intStart->setValue(cfg->getInt("first_frame", m_image->animationInterface()->playbackRange().start()));
213 m_page->intEnd->setValue(cfg->getInt("last_frame", m_image->animationInterface()->playbackRange().end()));
214 m_page->sequenceStart->setValue(cfg->getInt("sequence_start", m_image->animationInterface()->playbackRange().start()));
215- m_page->intHeight->setValue(cfg->getInt("height", int(m_image->height())));
216- m_page->intWidth->setValue(cfg->getInt("width", int(m_image->width())));
217- m_page->intFramesPerSecond->setValue(cfg->getInt("framerate", int(m_image->animationInterface()->framerate())));
218-
219
220 QString mimetype = cfg->getString("mimetype");
221 for (int i = 0; i < m_page->cmbMimetype->count(); ++i) {
222@@ -298,9 +288,6 @@ KisPropertiesConfigurationSP DlgAnimationRenderer::getFrameExportConfiguration()
223 cfg->setProperty("directory", fetchRenderingDirectory());
224 cfg->setProperty("first_frame", m_page->intStart->value());
225 cfg->setProperty("last_frame", m_page->intEnd->value());
226- cfg->setProperty("framerate", m_page->intFramesPerSecond->value());
227- cfg->setProperty("height", m_page->intHeight->value());
228- cfg->setProperty("width", m_page->intWidth->value());
229 cfg->setProperty("sequence_start", m_page->sequenceStart->value());
230 cfg->setProperty("ffmpeg_path", m_page->ffmpegLocation->fileName());
231
232@@ -321,9 +308,6 @@ KisPropertiesConfigurationSP DlgAnimationRenderer::getVideoConfiguration() const
233 cfg->setProperty("first_frame", m_page->intStart->value());
234 cfg->setProperty("last_frame", m_page->intEnd->value());
235 cfg->setProperty("sequence_start", m_page->sequenceStart->value());
236- cfg->setProperty("framerate", m_page->intFramesPerSecond->value());
237- cfg->setProperty("height", m_page->intHeight->value());
238- cfg->setProperty("width", m_page->intWidth->value());
239
240 // delete image sequence if we are only exporting out video
241 cfg->setProperty("delete_sequence", m_page->shouldExportOnlyVideo->isChecked());
242@@ -362,6 +346,10 @@ KisPropertiesConfigurationSP DlgAnimationRenderer::getEncoderConfiguration() con
243
244 void DlgAnimationRenderer::setEncoderConfiguration(KisPropertiesConfigurationSP cfg)
245 {
246+ m_page->intHeight->setValue(cfg->getInt("height", int(m_image->height())));
247+ m_page->intWidth->setValue(cfg->getInt("width", int(m_image->width())));
248+ m_page->intFramesPerSecond->setValue(cfg->getInt("framerate", int(m_image->animationInterface()->framerate())));
249+
250 if (m_encoderConfigWidget) {
251 m_encoderConfigWidget->setConfiguration(cfg);
252 }
253@@ -538,9 +526,11 @@ void DlgAnimationRenderer::slotExportTypeChanged()
254 {
255 KisConfig cfg;
256
257- // if a video format needs to be outputted
258- if (m_page->shouldExportAll->isChecked() || m_page->shouldExportOnlyVideo->isChecked()) {
259+ bool willEncodeVideo =
260+ m_page->shouldExportAll->isChecked() || m_page->shouldExportOnlyVideo->isChecked();
261
262+ // if a video format needs to be outputted
263+ if (willEncodeVideo) {
264 // videos always uses PNG for creating video, so disable the ability to change the format
265 m_page->cmbMimetype->setEnabled(false);
266 for (int i = 0; i < m_page->cmbMimetype->count(); ++i) {
267@@ -551,14 +541,19 @@ void DlgAnimationRenderer::slotExportTypeChanged()
268 }
269 }
270
271+ m_page->intWidth->setVisible(willEncodeVideo);
272+ m_page->intHeight->setVisible(willEncodeVideo);
273+ m_page->intFramesPerSecond->setVisible(willEncodeVideo);
274+ m_page->fpsLabel->setVisible(willEncodeVideo);
275+ m_page->lblWidth->setVisible(willEncodeVideo);
276+ m_page->lblHeight->setVisible(willEncodeVideo);
277+
278 // if only exporting video
279 if (m_page->shouldExportOnlyVideo->isChecked()) {
280 m_page->cmbMimetype->setEnabled(false); // allow to change image format
281 m_page->imageSequenceOptionsGroup->setVisible(false);
282 m_page->videoOptionsGroup->setVisible(false); //shrinks the horizontal space temporarily to help resize() work
283 m_page->videoOptionsGroup->setVisible(true);
284- m_page->intFramesPerSecond->setVisible(true);
285- m_page->fpsLabel->setVisible(true);
286
287 cfg.writeEntry<QString>("AnimationRenderer/export_type", "Video");
288 }
289@@ -568,9 +563,8 @@ void DlgAnimationRenderer::slotExportTypeChanged()
290 if (m_page->shouldExportOnlyImageSequence->isChecked()) {
291 m_page->cmbMimetype->setEnabled(true); // allow to change image format
292 m_page->videoOptionsGroup->setVisible(false);
293+ m_page->imageSequenceOptionsGroup->setVisible(false);
294 m_page->imageSequenceOptionsGroup->setVisible(true);
295- m_page->intFramesPerSecond->setVisible(false);
296- m_page->fpsLabel->setVisible(false);
297
298 cfg.writeEntry<QString>("AnimationRenderer/export_type", "ImageSequence");
299 }
300diff --git a/plugins/extensions/animationrenderer/wdg_animationrenderer.ui b/plugins/extensions/animationrenderer/wdg_animationrenderer.ui
301index a633dd4..a6a635b 100644
302--- a/plugins/extensions/animationrenderer/wdg_animationrenderer.ui
303+++ b/plugins/extensions/animationrenderer/wdg_animationrenderer.ui
304@@ -6,7 +6,7 @@
305 <rect>
306 <x>0</x>
307 <y>0</y>
308- <width>560</width>
309+ <width>621</width>
310 <height>381</height>
311 </rect>
312 </property>
313@@ -76,97 +76,115 @@
314 <item row="0" column="1">
315 <widget class="QSpinBox" name="intStart">
316 <property name="sizePolicy">
317- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
318- <horstretch>1</horstretch>
319+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
320+ <horstretch>0</horstretch>
321 <verstretch>0</verstretch>
322 </sizepolicy>
323 </property>
324 </widget>
325 </item>
326- <item row="1" column="2">
327- <widget class="QLabel" name="label_12">
328+ <item row="0" column="0">
329+ <widget class="QLabel" name="label_3">
330 <property name="text">
331- <string>Width:</string>
332+ <string>First frame:</string>
333 </property>
334 <property name="alignment">
335 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
336 </property>
337 </widget>
338 </item>
339- <item row="0" column="2">
340- <widget class="QLabel" name="label_4">
341+ <item row="0" column="4">
342+ <widget class="QLabel" name="fpsLabel">
343+ <property name="layoutDirection">
344+ <enum>Qt::LeftToRight</enum>
345+ </property>
346 <property name="text">
347- <string>Last frame:</string>
348+ <string>FPS:</string>
349 </property>
350 <property name="alignment">
351 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
352 </property>
353 </widget>
354 </item>
355- <item row="1" column="0">
356- <widget class="QLabel" name="label_11">
357- <property name="text">
358- <string>Height:</string>
359+ <item row="0" column="5">
360+ <widget class="QSpinBox" name="intFramesPerSecond">
361+ <property name="minimum">
362+ <number>1</number>
363 </property>
364- <property name="alignment">
365- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
366+ <property name="singleStep">
367+ <number>1</number>
368 </property>
369 </widget>
370 </item>
371- <item row="0" column="3">
372+ <item row="1" column="1">
373 <widget class="QSpinBox" name="intEnd">
374 <property name="sizePolicy">
375- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
376- <horstretch>1</horstretch>
377+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
378+ <horstretch>0</horstretch>
379 <verstretch>0</verstretch>
380 </sizepolicy>
381 </property>
382 </widget>
383 </item>
384- <item row="0" column="0">
385- <widget class="QLabel" name="label_3">
386+ <item row="1" column="0">
387+ <widget class="QLabel" name="label_4">
388 <property name="text">
389- <string>First frame:</string>
390+ <string>Last frame:</string>
391 </property>
392 <property name="alignment">
393 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
394 </property>
395 </widget>
396 </item>
397- <item row="1" column="3">
398+ <item row="0" column="3">
399 <widget class="QSpinBox" name="intWidth">
400+ <property name="sizePolicy">
401+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
402+ <horstretch>0</horstretch>
403+ <verstretch>0</verstretch>
404+ </sizepolicy>
405+ </property>
406 <property name="suffix">
407 <string> px</string>
408 </property>
409 </widget>
410 </item>
411- <item row="1" column="1">
412- <widget class="QSpinBox" name="intHeight">
413- <property name="suffix">
414- <string> px</string>
415+ <item row="0" column="2">
416+ <widget class="QLabel" name="lblWidth">
417+ <property name="sizePolicy">
418+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
419+ <horstretch>0</horstretch>
420+ <verstretch>0</verstretch>
421+ </sizepolicy>
422+ </property>
423+ <property name="text">
424+ <string>Width:</string>
425+ </property>
426+ <property name="alignment">
427+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
428 </property>
429 </widget>
430 </item>
431- <item row="0" column="4">
432- <widget class="QLabel" name="fpsLabel">
433- <property name="layoutDirection">
434- <enum>Qt::LeftToRight</enum>
435- </property>
436+ <item row="1" column="2">
437+ <widget class="QLabel" name="lblHeight">
438 <property name="text">
439- <string>FPS:</string>
440+ <string>Height:</string>
441 </property>
442 <property name="alignment">
443 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
444 </property>
445 </widget>
446 </item>
447- <item row="0" column="5">
448- <widget class="QSpinBox" name="intFramesPerSecond">
449- <property name="minimum">
450- <number>1</number>
451+ <item row="1" column="3">
452+ <widget class="QSpinBox" name="intHeight">
453+ <property name="sizePolicy">
454+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
455+ <horstretch>0</horstretch>
456+ <verstretch>0</verstretch>
457+ </sizepolicy>
458 </property>
459- <property name="singleStep">
460- <number>1</number>
461+ <property name="suffix">
462+ <string> px</string>
463 </property>
464 </widget>
465 </item>
466diff --git a/plugins/impex/video/video_saver.cpp b/plugins/impex/video/video_saver.cpp
467index b24a30d..44d4de4 100644
468--- a/plugins/impex/video/video_saver.cpp
469+++ b/plugins/impex/video/video_saver.cpp
470@@ -229,8 +229,7 @@ KisImageBuilder_Result VideoSaver::encode(const QString &filename, KisProperties
471
472 KisImageAnimationInterface *animation = m_image->animationInterface();
473 const KisTimeRange fullRange = animation->fullClipRange();
474- const int frameRate = configuration->getInt("framerate", int(m_image->height()));
475-
476+ const int frameRate = configuration->getInt("framerate", animation->framerate());
477
478 const KisTimeRange clipRange(configuration->getInt("first_frame", fullRange.start()), configuration->getInt("last_frame", fullRange.end()));
479 const bool includeAudio = configuration->getBool("include_audio", true);
480@@ -239,10 +238,8 @@ KisImageBuilder_Result VideoSaver::encode(const QString &filename, KisProperties
481 const int exportWidth = configuration->getInt("width", int(m_image->width()));
482
483 // export dimensions could be off a little bit, so the last force option tweaks the pixels for the export to work
484- QString exportDimensions = QString("scale=w=").append(QString::number(exportWidth)).append(":h=")
485- .append(QString::number(exportHeight)).append(":force_original_aspect_ratio=decrease");
486-
487-
488+ const QString exportDimensions = QString("scale=w=").append(QString::number(exportWidth)).append(":h=")
489+ .append(QString::number(exportHeight)).append(":force_original_aspect_ratio=decrease");
490
491
492 const QDir framesDir(configuration->getString("directory"));

scottpetrovic abandoned this revision.Dec 29 2017, 2:18 PM

I have combined my changes and yours. Just pushed it out to master. Closing this ticket. Thanks for you help