一帧的属性复制到了新的对象中,大家如果需要可以直接修改这些属性,比如设置间隔时间可以通过
res.GetPropertyItem(0x5100)这个方法可以得到间隔时间,然后设置得到的属性即可,每一帧有很多属性,具体大家可以去http://msdn.microsoft.com/zh-cn/library/system.drawing.imaging.propertyitem.id.aspx这里去找需要的值。
在设置EncoderParameter的时候第一帧需要设置为MultiFrame这样表明这个图像对象是个多帧的图片,之后如果是GIF则要设置为FrameDimensionTime,TIFF为FrameDimensionPage。
之后还必须给每一帧设置属性,我这里就使用原来的属性保持不变,所以直接将原文件的属性复制进去就好。
我的代码里没有做压缩处理,如果大家的图片需要压缩,则直接可以在取道每一帧后对“图像操作对象”来压缩后再saveadd进去。
C#
/// <summary>
/// 设置GIF大小
/// </summary>
/// <param name="path">图片路径</param>
/// <param name="width">宽</param>
/// <param name="height">高</param>
private void setGifSize(string path, int width, int height)
{
Image gif = new Bitmap(width, height);
Image frame = new Bitmap(width, height);
Image res = Image.FromFile(path);
Graphics g = Graphics.FromImage(gif);
Rectangle rg = new Rectangle(0, 0, width, height);
Graphics gFrame = Graphics.FromImage(frame);
foreach (Guid gd in res.FrameDimensionsList)
{
FrameDimension fd = new FrameDimension(gd);
//因为是缩小GIF文件所以这里要设置为Time,如果是TIFF这里要设置为PAGE,因为GIF以时间分割,TIFF为页分割
FrameDimension f = FrameDimension.Time;
int count = res.GetFrameCount(fd);
ImageCodecInfo codecInfo = GetEncoder(ImageFormat.Gif);
System.Drawing.Imaging.Encoder encoder = System.Drawing.Imaging.Encoder.SaveFlag;
EncoderParameters eps = null;
for (int i = 0; i < count; i++)
{
res.SelectActiveFrame(f, i);
if (0 == i)
{
g.DrawImage(res, rg);
eps = new EncoderParameters(1);
//第一帧需要设置为MultiFrame
eps.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.MultiFrame);
bindProperty(res, gif);
gif.Save(@"C:\tmp\test\aaa.gif", codecInfo, eps);
}
else
{
gFrame.DrawImage(res, rg);
eps = new EncoderParameters(1);
//如果是GIF这里设置为FrameDimensionTime,如果为TIFF则设置为FrameDimensionPage
eps.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.FrameDimensionTime);
bindProperty(res, frame);
gif.SaveAdd(frame, eps);
}
}
eps = new EncoderParameters(1);
eps.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.Flush);
gif.SaveAdd(eps);
}
}
/// <summary>
/// 将源图片文件里每一帧的属性设置到新的图片对象里
/// </summary>
/// <param name="a">源图片帧</param>
/// <param name="b">新的图片帧</param>
private void bindProperty(Image a,Image b)
{
//这个东西就是每一帧所拥有的属性,可以用GetPropertyItem方法取得这里用为完全复制原有属性所以直接赋值了
//顺便说一下这个属性里包含每帧间隔的秒数和透明背景调色板等设置,这里具体那个值对应那个属性大家自己在msdn搜索GetPropertyItem方法说明就有了
for (int i = 0; i < a.PropertyItems.Length; i++)
{
b.SetPropertyItem(a.PropertyItems[i]);
}
}
private ImageCodecInfo GetEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}