Пример 1: пошаговое построение анимированной картинки
1. Нарисуем картинку
x = 0:0.01:1;
y = x;
plot(x,y)
2. Захватим кадр
f = getframe;
3. Преобразуем полноцветное изображение в палитровое
Полноцветное изображение хранится в f.cdata
. Оно имеет размер NxMx3
. Вместо него получаем палитровое изображение im
размера NxM
, цвет каждого пиксела которого определяется цветовой картой (палитрой) map
. 256 — ограничение на количество цветов в палитре (больше нам не нужно).
[im,map] = rgb2ind(f.cdata,256);
4. Задаем массив, в котором будем хранить кадры анимации
im(1,1,1,10) = 0;
Результатом работы rgb2ind
может быть двумерный или четырехмерный массив. Так что введение дополнительного (третьего) измерения — дело вынужденное. Значение индекса четвертого измерения (10
) — количество кадров будущей анимации. Таким образом мы заранее резервируем место под массив im
.
5. Цикл рисования и запоминания кадров
Рисуем очередной кадр, захватываем его (getframe
) и добавляем в массив im
.
for k = 1:10
y = x.^k;
plot(x,y)
f = getframe;
im(:,:,1,k) = rgb2ind(f.cdata,map);
end
6. Записываем полученную анимацию в файл
(:source lang=scilab:) imwrite(im,map,'test.gif','DelayTime',0,'LoopCount',inf)
`DelayTime` — определяет время задержки между кадрами анимации, `LoopCount` задает число повторений. Один раз анимация воспроизводится всегда, так что `LoopCount=0` означает, что анимация будет воспроизведена один раз, при `LoopCount=1` анимация выполняется дважды и т.д. `LoopCount=inf` зацикливает анимацию (повторяет ее бесконечное число раз).
**Теперь все вместе:**
```matlab
x = 0:0.01:1;
y = x;
plot(x,y)
f = getframe;
[im,map] = rgb2ind(f.cdata,256);
im(1,1,1,10) = 0;
for k = 1:10
y = x.^k;
plot(x,y)
f = getframe;
im(:,:,1,k) = rgb2ind(f.cdata,map);
end
imwrite(im,map,'test.gif','DelayTime',0,'LoopCount',inf)
Получаем:
Пример 2: еще один способ создания анимации
Если нам понадобится дробные показатели степени, нужно будет ввести еще один индекс для элементов массива im
, вместо k
. Другой вариант — создать первый кадр изображения и постепенно добавлять к нему новые кадры.
x = 0:0.01:1;
y = x;
plot(x,y)
f = getframe;
[im,map] = rgb2ind(f.cdata,256);
filename = 'test.gif';
imwrite(im,map,filename,'DelayTime',0,'Loopcount',inf);
for k = 1:0.5:5
y = x.^k;
plot(x,y)
drawnow
f = getframe;
[im,map] = rgb2ind(f.cdata,256);
imwrite(im,map,filename,'DelayTime',0,'WriteMode','Append');
end
Можно поместить оба imwrite
в цикл, проверяя номер итерации: для первой итерации создается графический файл, для остальных в него добавляются кадры:
outfile = 'out.gif';
for i = 1:50
plot;
...
frame = getframe(1);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
% На первой итерации создается файл, на остальных добавляются кадры.
if i == 1
imwrite(imind,cm,outfile,'gif','DelayTime',0,'LoopCount',inf);
else
imwrite(imind,cm,outfile,'gif','DelayTime',0,'WriteMode','append');
end
end
С помощью такого подхода реализована анимация простых методов сортировки.
Пример 3: анимация поверхности
Основная идея — та же, что и в примере 1.
Z = peaks;
surf(Z)
axis tight
set(gca,'nextplot','replacechildren')
f = getframe;
[im,map] = rgb2ind(f.cdata,256);
im(:,:,1,20) = im;
for k = 1:20
surf(cos(2*pi*k/20)*Z,Z)
f = getframe;
im(:,:,1,k) = rgb2ind(f.cdata,map);
end
imwrite(im,map,'test.gif','DelayTime',0,'LoopCount',inf)
Самое интересное в этом примере находится в строках:
axis tight
set(gca,'nextplot','replacechildren')
Первая не позволяет изменится размеру кадра. Вторая — стирает изображение в текущих координатных осях, не изменяя при этом остальных свойств осей (принятое по умолчанию для nextplot
значение replace
"сбрасывает" все свойства осей в их значения по умолчанию).
Пример 4: анимация нескольких графиков в разных координатных осях
x=0:pi/10:4*pi; % х-координата
y1=sin(x); % функция для одной анимации
y2=cos(x); % функция для другой анимации
fig = figure();
% создание первого пустого кадра
set(fig,'Position',[350,200,700,300]);
frame = getframe(fig);
[im,map] = rgb2ind(frame.cdata,4);
imwrite(im,map,'animation1.gif','DelayTime',0,'Loopcount',0);
% цикл анимации
for i=1:length(x)
subplot(2,1,1);
plot(x(i),y1(i),'.');
xlim([0, 4*pi]);
ylim([-1, 1]);
hold on;
subplot(2,1,2);
plot(x(i),y2(i),'.');
xlim([0, 4*pi]);
ylim([-1, 1]);
hold on;
frame = getframe(fig);
[im,map] = rgb2ind(frame.cdata,4);
imwrite(im,map,'animation1.gif','DelayTime',0.1,'WriteMode','Append');
end;
Пример 5: анимация нескольких графиков в общих координатных осях
x=0:pi/10:4*pi; % х-координата
y1=sin(x); % функция для одной анимации
y2=cos(x); % функция для другой анимации
fig = figure();
% создание первого пустого кадра
set(fig,'Position',[350,200,700,300]);
axes('xlim',[0 4*pi],'ylim',[-1 1],'NextPlot','add','Parent',fig);
frame = getframe(fig);
[im,map] = rgb2ind(frame.cdata,4);
imwrite(im,map,'animation2.gif','DelayTime',0,'Loopcount',0);
% цикл анимации
for i=1:length(x)
plot(x(i),y1(i),'.');
plot(x(i),y2(i),'r.');
frame = getframe(fig);
[im,map] = rgb2ind(frame.cdata,4);
imwrite(im,map,'animation2.gif','DelayTime',0.1,'WriteMode','Append');
end;
Пример 6: анимация нескольких поверхностей
Объединим результаты примеров 3 и 4.
fig = figure();
% создание первого пустого кадра
set(fig,'Position',[350,200,700,700]);
frame = getframe(fig);
[im,map] = rgb2ind(frame.cdata,4);
imwrite(im,map,'animation3.gif','DelayTime',0,'Loopcount',0);
% создание тестовой поверхности
Z = peaks;
% цикл анимации
for i=1:100
subplot(2,1,1);
surf(cos(pi*i/20)*Z,Z)
xlim([0, 50]);
ylim([0, 50]);
zlim([-10, 10]);
hold on;
subplot(2,1,2);
surf((sin(pi*i/20)-cos(pi*i))*Z,Z)
xlim([0, 50]);
ylim([0, 50]);
zlim([-20, 20]);
hold on;
frame = getframe(fig);
[im,map] = rgb2ind(frame.cdata,4);
imwrite(im,map,'animation3.gif','DelayTime',0.1,'WriteMode','Append');
end;
Обратите внимание, что здесь Loopcount=0
, так что анимация будет выполняться один раз.
Здесь может возникнуть следующая проблема: некоторое программы просмотра графических файлов, например, IrfanView, сами по умолчанию зацикливают анимацию. Так что если в результате выполнения этого примера вы получите зацикленную анимацию, то просто смените программу просмотра, например, на браузер.*
Комментарии
comments powered by Disqus