【相关类库】 链接: http://pan.baidu.com/s/1gd9XfBt 密码: h27c
参考链接:
http://www.codeproject.com/Articles/11505/NGif-Animated-GIF-Encoder-for-NET
http://cnn237111.blog.51cto.com/2359144/1261422
折腾了一些时间,NGIF不可以直接使用,会有各种各样的问题,合成的图片有黑线条等等不如意的问题。留言下面有很多网友的留言国内国外都有,还有针对上面做出修改的版本。经过一番研究再加上相关资源整合了一下,终于可以满足我的基本需求了。其他不做赘述了,该说的其他人都说了.
具体实现原理,先把gif 图片一帧一帧拆分成jpg图片,然后针对每个图片进行裁剪,局部裁剪还是等比裁剪等等可以自己实现网上有很多针对jpge图片的处理类,我这里也提供了一个Thumbnail.cs类可下载.
实现部分
private static Size gifSize;
private static int delay;
/// <summary>
/// 裁剪GIF图片
/// </summary>
/// <param name="gifFilePath">源文件地址</param>
/// <param name="maxWidth">最大宽度</param>
/// <param name="maxHeight">最大高度</param>
/// <param name="outputPath">输出文件地址</param>
public static void GetThumbnail(string gifFilePath, int maxWidth, int maxHeight, string outputPath)
{
List<Image> gifList = GetFrames(gifFilePath);
AnimatedGifEncoder ae = new AnimatedGifEncoder();
ae.Start();
ae.SetDelay(delay); // 延迟间隔
ae.SetRepeat(0); //-1:不循环,0:总是循环 播放
//我这里是等比缩小(如果原图长大于宽以长为基准缩放,反之以宽为基准缩放)
Size _newSize = Thumbnail.ResizeImage(gifSize.Width, gifSize.Height, maxWidth, maxHeight);
ae.SetSize(_newSize.Width,_newSize.Height);
for (int i = 0, count = gifList.Count; i < count; i++)
{
//Image frame = Image.FromFile(gifList[i]);
ae.AddFrame(gifList[i]);
}
ae.Finish();
ae.Output(outputPath);
}
//解码gif图片
public static List<Image> GetFrames(string pPath)
{
Image gif = Image.FromFile(pPath);
gifSize = new Size(gif.Width, gif.Height);
FrameDimension fd = new FrameDimension(gif.FrameDimensionsList[0]);
//获取帧数(gif图片可能包含多帧,其它格式图片一般仅一帧)
int count = gif.GetFrameCount(fd);
// List<string> gifList = new List<string>();
List<Image> gifList = new List<Image>();
//以Jpeg格式保存各帧
for (int i = 0; i < count; i++)
{
gif.SelectActiveFrame(fd, i);
//获取第一帧 的延时时间。/*-----说明一下,按道理应该每一帧的延时时间都应该获取,在合并的时候再设置delay,但是我测试很多图片的每一帧之间的延时时间都是一样的------*/
if (i == 0)
{
for (int j = 0; j < gif.PropertyIdList.Length; j++)//遍历帧属性
{
if ((int)gif.PropertyIdList.GetValue(j) == 0x5100)//.如果是延迟时间
{
PropertyItem pItem = (PropertyItem)gif.PropertyItems.GetValue(j);//获取延迟时间属性
byte[] delayByte = new byte[4];//延迟时间,以1/100秒为单位
delayByte[0] = pItem.Value[i * 4];
delayByte[1] = pItem.Value[1 + i * 4];
delayByte[2] = pItem.Value[2 + i * 4];
delayByte[3] = pItem.Value[3 + i * 4];
delay = BitConverter.ToInt32(delayByte, 0) * 10; //乘以10,获取到毫秒
break;
}
}
}
gifList.Add( new Bitmap(gif));//这里可以将每帧图片保存成文件gif.save(,);根据需求
}
gif.Dispose();
return gifList;
}
说明:
AnimatedGifEncoder.cs -> GetImagePixels()
protected void GetImagePixels()
{
int w = image.Width;
int h = image.Height;
// int type = image.GetType().;
if ((w != width)
|| (h != height)
)
{
// create new image with right size/format
Image temp = new Bitmap(width, height );
Graphics g = Graphics.FromImage(temp);
// 设置画布的描绘质量,说明:这里是等比缩放,可以根据需求从Thumbnail.cs中找到符合自己的缩放方法进行修改。
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(image, new Rectangle(0, 0, width, height), 0, 0, w, h, GraphicsUnit.Pixel);
image = temp;
g.Dispose();
}
/*
ToDo:
improve performance: use unsafe code
*/
pixels = new Byte [ 3 * image.Width * image.Height ];
int count = 0;
Bitmap tempBitmap = new Bitmap( image );
for (int th = 0; th < image.Height; th++)
{
for (int tw = 0; tw < image.Width; tw++)
{
Color color = tempBitmap.GetPixel(tw, th);
pixels[count] = color.R;
count++;
pixels[count] = color.G;
count++;
pixels[count] = color.B;
count++;
}
}
tempBitmap.Dispose();
image.Dispose();
// pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
}