更新:
我做了更多的研究,我认为这些 ffmpeg 和 mplayer 建议值得一试:
Create Animation gif from a set of jpeg images
更新 2:
Rick van den Bosch的这段代码也非常好,因为它可以让您访问延迟时间:
.Net(至少 1.1,他们可能会将其合并到 2.0 中)无法让您通过 GDI+ 创建动画 GIF。
//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();
正如 Hans 提到的那样,它不支持,所以第三个解决方案是 RenniePet 建议从两个 Gif 中提取帧,然后将所有帧组合在一起。
添加对 System.Drawing.DLL 的引用并使用此代码获取框架:
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
}
}
我们可以像这样提取所有的帧:
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;
}
接下来我们使用NGif将所有帧组合成一个动画 gif
下载代码,打开解决方案并编译组件项目以获取 DLLGif.Components.dll
并在您的解决方案中引用该 DLL。
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;
}