Question

I have searched stackoverflow for a similar question and I found question "movie2avi-frame-size-error-and-keeping-frame-size-constant". Unfortunately the answer given there did not solve my problem (it has been suggested the use of xlim, ylim and zlim).

In what follows I send a lightly modified version of a well-known example given elsewhere.

%# figure
figure, set(gcf, 'Color','white')
Z = peaks; surf(Z);  axis tight
set(gca, 'nextplot','replacechildren', 'Visible','off');
[az,el]=view;
xl=xlim;
yl=ylim;
zl=zlim;

%# preallocate
nFrames = 20;
mov(1:nFrames) = struct('cdata',[], 'colormap',[]);

%# create movie
for k=1:nFrames
   view([(az-k*10) el]);
   xlim(xl);ylim(yl);zlim(zl);
   drawnow;pause(0.1);
   mov(k) = getframe(gca);
end
close(gcf)

%# save as AVI file, and open it using system video player
movie2avi(mov, 'myPeaks1.avi', 'compression','None', 'fps',10);

The idea is to rotate the figure and create a movie. Everything works fine except for the last command, that is, movie2avi. The error msg is

Error using avifile/addframe>ValidateFrame (line 290)
Frame must be 435 by 344.

Error in avifile/addframe (line 158)
ValidateFrame(aviobj,width, height,dims);

Error in movie2avi (line 67)
avimov = addframe(avimov,mov);

Error in more_video_test (line 24)
movie2avi(mov, 'myPeaks1.avi', 'compression','None', 'fps',10); 

I have looked at approaches-to-create-a-video-in-matlab here in stackoverflow and found that:

a) Solution ffmpeg works but I would like to avoid it.
b) All other solutions failed even QTWriter. How can I fix the frame size so that all these other solutions work?

Many thanks.

Ed

Was it helpful?

Solution

The problem is that due to the rotation of the graph the size of the axis changes, so you end up with a sequence of frames of different sizes. You can see this if you insert the lines

s = size(mov(k).cdata);
fprintf('%d %d\n', s(2), s(1))

within the loop, directly after you grabbed the frame by

mov(k) = getframe(gca);

The result is

435 344
435 343
435 343
436 342
435 343
435 343
435 343
435 343
435 343
435 343
435 343
435 343
435 343
435 343
435 343
435 343
435 343
435 343
435 343
435 343

Because the first frame has the size 435 x 344, movie2avi expects the following frames to be of the same size – but they're not.

In order to fix this, you might want to set the axis size (& position) explicitly using set(gca, 'Position', [...]). An easier workaround though is to grab the frame not from the axis, but from the figure. That is, instead of mov(k) = getframe(gca); use

mov(k) = getframe(gcf);

The frames then have a uniform size of 560 x 420.

On my machine, the resulting avi has frames upside down. In order to fix this, too, you can additionally insert a line

mov(k).cdata = mov(k).cdata(end :-1: 1, :, :);

after grabbing the frame.

OTHER TIPS

I found an alternative solution to my question.

%# figure
figure, set(gcf, 'Color','white')
Z = peaks; surf(Z);  axis tight
set(gca, 'nextplot','replacechildren', 'Visible','off');
axis vis3d

% With VideoWriter

writerObj = VideoWriter('myPeaks3.avi');
open(writerObj);

%# preallocate
nFrames = 90;
mov(1:nFrames) = struct('cdata',[], 'colormap',[]);

%# create movie
for k=1:nFrames
   camorbit(360/nFrames,0,'data','z');
   drawnow;
   mov(k) = getframe(gcf);
   writeVideo(writerObj,mov(k));
end;

% Close file

close(writerObj);

I habe the same problem, the frame size is changing during making a video. After searching a long while in internet I didn't find a good solution. But when I tried adding drawnow after getframe calling and before writeVideo calling. The problem is solved and didn't appear any more.

I'm using matlab 2017b.

e.g.

mov(k) = getframe(gcf);
drawnow;
writeVideo(writerObj,mov(k));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top