Update:
I did more research and I think these ffmpeg and mplayer recommendations are worth trying:
Create animated gif from a set of jpeg images
Update 2:
This code from Rick van den Bosch is very good too, as it gives you access to the delay times:
.Net (at least 1.1, they might incorporate it in 2.0) does not give
you possibilities to create animated GIFs through GDI+.
//Variable declaration
StringCollection stringCollection;
MemoryStream memoryStream;
BinaryWriter binaryWriter;
Image image;
Byte[] buf1;
Byte[] buf2;
Byte[] buf3;
//Variable declaration
stringCollection = a_StringCollection_containing_images;
Response.ContentType = "Image/gif";
memoryStream = new MemoryStream();
buf2 = new Byte[19];
buf3 = new Byte[8];
buf2[0] = 33; //extension introducer
buf2[1] = 255; //application extension
buf2[2] = 11; //size of block
buf2[3] = 78; //N
buf2[4] = 69; //E
buf2[5] = 84; //T
buf2[6] = 83; //S
buf2[7] = 67; //C
buf2[8] = 65; //A
buf2[9] = 80; //P
buf2[10] = 69; //E
buf2[11] = 50; //2
buf2[12] = 46; //.
buf2[13] = 48; //0
buf2[14] = 3; //Size of block
buf2[15] = 1; //
buf2[16] = 0; //
buf2[17] = 0; //
buf2[18] = 0; //Block terminator
buf3[0] = 33; //Extension introducer
buf3[1] = 249; //Graphic control extension
buf3[2] = 4; //Size of block
buf3[3] = 9; //Flags: reserved, disposal method, user input, transparent color
buf3[4] = 10; //Delay time low byte
buf3[5] = 3; //Delay time high byte
buf3[6] = 255; //Transparent color index
buf3[7] = 0; //Block terminator
binaryWriter = new BinaryWriter(Response.OutputStream);
for (int picCount = 0; picCount < stringCollection.Count; picCount++)
{
image = Bitmap.FromFile(stringCollection[picCount]);
image.Save(memoryStream, ImageFormat.Gif);
buf1 = memoryStream.ToArray();
if (picCount == 0)
{
//only write these the first time....
binaryWriter.Write(buf1, 0, 781); //Header & global color table
binaryWriter.Write(buf2, 0, 19); //Application extension
}
binaryWriter.Write(buf3, 0, 8); //Graphic extension
binaryWriter.Write(buf1, 789, buf1.Length - 790); //Image data
if (picCount == stringCollection.Count - 1)
{
//only write this one the last time....
binaryWriter.Write(";"); //Image terminator
}
memoryStream.SetLength(0);
}
binaryWriter.Close();
Response.End();
As Hans mentioned its not supported, so this third solution is RenniePet's suggestion to extract the frames from both Gif's and then combine all the frames together.
Add a reference to System.Drawing.DLL and use this code to get the frames:
using System.Drawing;
using System.Drawing.Imaging;
public class GifImage
{
private Image gifImage;
private FrameDimension dimension;
private int frameCount;
private int currentFrame = -1;
private bool reverse;
private int step = 1;
public GifImage(string path)
{
gifImage = Image.FromFile(path);
//initialize
dimension = new FrameDimension(gifImage.FrameDimensionsList[0]);
//gets the GUID
//total frames in the animation
frameCount = gifImage.GetFrameCount(dimension);
}
public int GetFrameCount()
{
return frameCount;
}
public bool ReverseAtEnd
{
//whether the gif should play backwards when it reaches the end
get { return reverse; }
set { reverse = value; }
}
public Image GetNextFrame()
{
currentFrame += step;
//if the animation reaches a boundary...
if (currentFrame >= frameCount || currentFrame < 1)
{
if (reverse)
{
step *= -1;
//...reverse the count
//apply it
currentFrame += step;
}
else
{
currentFrame = 0;
//...or start over
}
}
return GetFrame(currentFrame);
}
public Image GetFrame(int index)
{
gifImage.SelectActiveFrame(dimension, index);
//find the frame
return (Image)gifImage.Clone();
//return a copy of it
}
}
We can extract all the Frames like this:
private static readonly string tempFolder = @"C:\temp\";
static void Main(string[] args)
{
CombineGifs(@"c:\temp\a.gif", @"c:\temp\b.gif");
}
public static void CombineGifs(string firstImageFilePath, string secondImageFilePath)
{
int frameCounter = ExtractGifFramesAndGetCount(firstImageFilePath, 0);
int secondframeCounter = ExtractGifFramesAndGetCount(secondImageFilePath, frameCounter);
string filePathOfCombinedGif = CombineFramesIntoGif(0, secondframeCounter);
}
private static int ExtractGifFramesAndGetCount(string filePath, int imageNameStartNumber)
{
////NGif had an error when I tried it
//GifDecoder gifDecoder = new GifDecoder();
//gifDecoder.Read(filePath);
//int frameCounter = imageNameStartNumber + gifDecoder.GetFrameCount();
//for (int i = imageNameStartNumber; i < frameCounter; i++)
//{
// Image frame = gifDecoder.GetFrame(i); // frame i
// frame.Save(tempFolder + i.ToString() + ".png", ImageFormat.Png);
//}
//So we'll use the Gifimage implementation
GifImage gifImage = new GifImage(filePath);
gifImage.ReverseAtEnd = false;
int frameCounter = imageNameStartNumber + gifImage.GetFrameCount();
for (int i = imageNameStartNumber; i < frameCounter; i++)
{
Image img = gifImage.GetNextFrame();
img.Save(tempFolder + i.ToString() + ".png");
}
return frameCounter;
}
Next we combine all the frames into a single animated gif using NGif
Download the code, open the Solution and compile the Components project to get the DLL Gif.Components.dll
and reference that DLL in your solution.
private static string CombineFramesIntoGif(int startFrameCount, int endFrameCount)
{
List<string> imageFilePaths = new List<string>();
for (int i = startFrameCount; i < endFrameCount; i++)
{
imageFilePaths.Add(tempFolder + i.ToString() + ".png");
}
string outputFilePath = tempFolder + "test.gif";
AnimatedGifEncoder e = new AnimatedGifEncoder();
e.Start(outputFilePath);
e.SetDelay(500);
//-1:no repeat,0:always repeat
e.SetRepeat(0);
for (int i = 0; i < imageFilePaths.Count; i++)
{
e.AddFrame(Image.FromFile(imageFilePaths[i]));
}
e.Finish();
return outputFilePath;
}