How can I create animated GIF images in MATLAB?

I would like to know if there is MATLAB functionality to create an animated GIF in MATLAB.

 Accepted Answer

In MATLAB 2022a, export to GIF format is supported by the exportgraphics function using the ‘Append’ option.  For example:
x = 0:0.01:1;
p = plot(nan,nan);
p.XData = x;
for n = 1:0.5:5
      p.YData = x.^n;
exportgraphics(gcf,'testAnimated.gif','Append',true);
end
For releases prior to R2022a, follow the example "Write Animated GIF" on the imwrite reference page.

7 Comments

Could you add support for APNG? It is much superior to GIF.
Royi has a good point!
That's a good suggestion, thanks for commenting! I have submitted an enhancement request for this functionality, so it may be considered for a future release of MATLAB.
@Peter Beringer, "Can the GIF then be converted into a *.AVI or *.MOV file within MATLAB?"
You can use gif2avi() from the file exchange to convert from GIF to AVI or MP4 format.
Why does it return a picture of a kid when evaluated on its own?
What did you pass into rgb2ind when you called it? Did you call image with no inputs, capture the result using getframe and frame2im, and then call rgb2ind on the result? If so the picture of a kid is not coming from rgb2ind but from image. Steve Eddins explains what's going on in this post on his blog.
As for what the rgb2ind line is doing: getframe returns a struct array. imwrite doesn't know how to accept that struct array as its first (or first two) inputs. frame2im turns that struct array into an image that imwrite could accept, but the image may have more colors in it than the image file format supports so rgb2ind modifies the image to use a colormap with at most 256 colors. It is that image and colormap pair that imwrite writes to the file.
If the bounding box for your surface plot was the same each time you plotted, I would expect this to work. But if the surface plot was rotated or enlarged (so that the area on the screen taken up by each frame would be different) that would be a problem. It would be like printing a report where the first page was on a sheet of letter paper, the second was a 3x5 index card, and the third was a sheet of legal sized paper. That wouldn't make for a very stable stack of reports.
prefix = 'abc_20190304'
dinfo = dir( [prefix '*.png']);
filenames = {dinfo.name};
for K = 1 : length(filenames)
work with file name in filenames{K}
end
exportgraphics does not currently have an option to control frame rate of GIFs.
The documentation for exportgraphics > Append argument suggests to use imwrite for more elaborate graphics. Also see Write Animated GIF.

Sign in to comment.

More Answers (2)

Chad Greene
Chad Greene on 4 Jun 2017
Edited: MathWorks Support Team on 25 Sep 2022
Or, for a much simpler option, use the gif function on File Exchange.
So it appears that `imwrite` now supports writing animated grayscale GIFs "When writing multiframe GIF images, X should be an 4-dimensional M-by-N-by-1-by-P array, where P is the number of frames to write."
But if I try to pass it an M-by-N-by-3-by-P it seems to treat each RGB color channel as a separate grayscale frame. Is there now way to write an animated color GIF without a for loop over the frames?

1 Comment

MIMT gifwrite() works to write I/IA/RGB/RGBA and indexed color images from 4D arrays. MIMT gifread() can read the image with minimal hassle.
Pay attention to the synopsis if you intend to read GIF files in versions newer than R2018a -- regardless of what tools you're using. If you're using a newer version, you will not be able to correctly read most multiframe color GIF files unless you make that effort.
Stitching the frames together to generate a colormap is a bad idea, since it means that no frame can have a unique optimized local color table. The more dynamic the color content is over the sequence, the worse the entire image will look.
EDIT: I think my claim should be obvious, but let's demonstrate it anyway. I'm going to use MIMT tools here, because why would I make things harder for myself?
Let's start with a short imageset where the colors vary a lot.
% read six colored images and stack into a 4D array
inpict = mimread('wide*.png');
inpict = imstacker(inpict,'padding',0);
% write the RGB images as (mostly) usual
% each frame gets its own optimized local color table (LCT)
% in this example, gifwrite() is internally modified to call
% rgb2ind(...,'nodither') for purposes of making the artifacts clear
gifwrite(inpict,'uniqueCT.gif',0.5)
% instead of converting each frame independently,
% tile the frames, convert, and then detile
% again, i'm using 'nodither' so that the effects are clearly visible
inpict = imtile(inpict,[3 2]);
[inpict,map] = rgb2ind(inpict,256,'nodither');
inpict = imdetile(inpict,[3,2]);
% write the indexed images to create a garbage GIF
% in this image, all the LCTs are identical copies of the same 256 colors
gifwrite(inpict,map,'pseudoglobalCT.gif',0.5)
These are the two GIFs produced. Note that they are significantly different.
But you might notice that we're trying to span all of RGB with this GIF. Surely this little error won't cause any issues if the interframe variation were small. Let's try the same thing, only using a much narrower color swing.
While pageload will pretty much ensure that the two GIFs aren't synchronized here, you may notice that they don't appear to even have the same number of frames. Let's look into that.
% read the images back
G1 = gifread('uniqueCT.gif');
G2 = gifread('pseudoglobalCT.gif');
% calculate the MSE between adjacent frames
mse1 = zeros(1,5);
mse2 = zeros(1,5);
for f = 1:5
mse1(f) = immse(G1(:,:,:,f),G1(:,:,:,f+1));
mse2(f) = immse(G2(:,:,:,f),G2(:,:,:,f+1));
end
% note that for two cases, the effect is large enough that adjacent frames
% which were once unique are now identical.
mse1
mse1 =
56.3333 48.0000 56.3333 48.0000 56.3333
mse2
mse2 =
120.3333 0 208.3333 0 120.3333
So yes, we actually lost two frames of information. This is a bad idea even when interframe variation is small.
Again, this example uses MIMT tools, specifically gifread() and gifwrite(), though the lessons here are not unique to those tools. Before you decide to test these examples yourself, understand that MIMT gifread() and all other tools require significant workarounds to correctly read multiframe GIFs in current versions. If you do not make your own effort to fix that, the results you get from gifread()/imread() will be either subtly or wildly wrong, leaving you with a misunderstanding of the file's actual content. See the link.

Sign in to comment.

Categories

Find more on Graphics Performance in Help Center and File Exchange

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!