The MATLAB Blog

Practical Advice for People on the Leading Edge

Producing animated gifs from MATLAB Flipbook Mini Hack entries

On Valentine's day, the MathWorks linkedIn channel posted this animated gif
dbc1ee461bf1d391edf5ce670d36353132993b22.gif
The obvious question was duly asked "Where's the MATLAB code for this?" Turns out, I was uniquely placed to answer this as it was one of my entries for the MATLAB Flipbook Mini Hack contest that occurred in late 2023. The full credit, however, has to go to Zhaoxu Liu / slandarer who wrote the original entry called Particle Heart 2. My version of the code was a lightly edited 'remix' that simply made the heart rotate more quickly, causing it to do a full revolution for every loop of the gif. This idea of remixing was a key feature of the contest which helped make it a lot of fun. Some of the best entries got remixed a lot!
I was at dinner at the time and wasn't able to post a full reply to the questions on LinkedIn so I just posted the link to the Minihack entry. Here's the code
function drawframe(f)
global theta1 theta2 theta3 heartHdl star1Hdl star2Hdl hpnts sx1 sx2 sy1 sy2
if f==1
% 所需匿名函数
col1Func=@(n) repmat([255,158,196]./255,[n,1])+repmat([-39,-81,-56]./255,[n,1]).*repmat(rand([n,1]),[1,3]);
col2Func=@(n) repmat([118,156,216]./255,[n,1])+repmat([137,99,39].*.1./255,[n,1]).*repmat(rand([n,1]),[1,3]);
szFunc=@(n) rand([n,1]).*15+8;
hold on
% 计算爱心点位置并绘制爱心
n=120;
x=linspace(-3,3,n);
y=linspace(-3,3,n);
z=linspace(-3,3,n);
[X,Y,Z]=ndgrid(x,y,z);
F=((-(X.^2).*(Z.^3)-(9/80).*(Y.^2).*(Z.^3))+((X.^2)+(9/4).*(Y.^2)+(Z.^2)-1).^3);
FV=isosurface(F,0);
hpnts=FV.vertices;
hpnts=(hpnts-repmat(mean(hpnts),[size(hpnts,1),1])).*repmat([.75,.7,.7],[size(hpnts,1),1]);
hpnts=hpnts+rand(size(hpnts)).*.7;
heartHdl=scatter3(hpnts(:,1),hpnts(:,2),hpnts(:,3),'.','SizeData',5,'CData',col1Func(size(hpnts,1)));
% 计算星星位置并绘制星星
sx1=rand([2e3,1]).*120-60;
sy1=rand([2e3,1]).*120-60;
sz1=ones(size(sx1)).*-30;
star1Hdl=scatter3(sx1,sy1,sz1,'.','SizeData',szFunc(length(sx1)),'CData',col2Func(size(sx1,1)),'LineWidth',1);
sx2=rand([2e3,1]).*120-60;
sy2=rand([2e3,1]).*120-60;
sz2=rand([2e3,1]).*120-20;
star2Hdl=scatter3(sx2,sy2,sz2,'.','SizeData',szFunc(length(sx2)),'CData',[1,1,1]);
% 坐标区域修饰
ax=gca;
ax.XLim=[-30,30];
ax.YLim=[-30,30];
ax.ZLim=[-40,30];
ax.Projection='perspective';
% ax.DataAspectRatio=[1,1,1];
view(-42,14);
ax.Color=[0,0,0];
ax.XColor='none';
ax.YColor='none';
ax.ZColor='none';
set(ax,'LooseInset',[0,0,0,0]);
set(ax,'Position',[-1/5,-1/5,1+2/5,1+2/5])
set(gcf,'Color',[0,0,0]);
% text(0,0,20,'slandarer','Color','w','HorizontalAlignment','center')
% 旋转爱心和星星
theta1=0;theta2=0;theta3=0;
else
theta1=theta1-pi/48;
theta2=theta2-0.003;
theta3=theta3-0.02;
set(heartHdl,'XData',hpnts(:,1).*cos(theta1)-hpnts(:,2).*sin(theta1),...
'YData',hpnts(:,1).*sin(theta1)+hpnts(:,2).*cos(theta1))
set(star1Hdl,'XData',sx1.*cos(theta2)-sy1.*sin(theta2),...
'YData',sx1.*sin(theta2)+sy1.*cos(theta2))
set(star2Hdl,'XData',sx2.*cos(theta3)-sy2.*sin(theta3),...
'YData',sx2.*sin(theta3)+sy2.*cos(theta3))
end
end
It's a function that draws a single frame. The software behind the website then called this function in a loop with the frame number going from 1 to 48 and inserted a delay such that the resulting animation would last 2 seconds before starting again. However, if you just had MATLAB then this function only produces a static frame.
drawframe(1);
How do you use this to produce the animated gif was the follow up question? I reached out to the team who built the Minihack website and asked them how they did it. How can I reproduce the exact same animated gifs using MATLAB and the drawframe() functions found on the website? They sent me the code below
function animateFrames()
animFilename = 'animation.gif'; % Output file name
firstFrame = true;
framesPerSecond = 24;
delayTime = 1/framesPerSecond;
% Create the gif
for frame = 1:48
drawframe(frame);
fig = gcf();
fig.Units = 'pixels';
fig.Position(3:4) = [300,300];
im = getframe(fig);
[A,map] = rgb2ind(im.cdata,256);
if firstFrame
firstFrame = false;
imwrite(A,map,animFilename, LoopCount=Inf, DelayTime=delayTime);
else
imwrite(A,map,animFilename, WriteMode="append", DelayTime=delayTime);
end
end
end
So, create two m-files, one called animateFrames.m and the other called drawframe.m, run animateFrames()
animateFrames()
and after a few seconds, you'll have animation.gif that contains what you are looking for. At this point, I suggest you take a look at the gallery and find something to animate yourself. These flowers, also from Zhaoxu Liu / slandarer, perhaps?
flowers.gif
or how about these lanterns by Tim?
lanterns.gif
Even though the competition only lasted 4 weeks, there are over 600 entries for you to play with. Here is a static view of a few more.
The competition had a few restrictions. For example, all animations had exactly 48 frames that would be turned into a 2 second gif. There were also computational time limits and character limits on the drawframe() function. Now you have the code, you can go crazy and produce animated gifs of whatever complexity you like!
|
  • print

Comments

To leave a comment, please click here to sign in to your MathWorks Account or create a new one.