很多时候下载了gif动画,但只想截取其中的的一部分(包括画面的一部分或者部分帧),于是做了个软件完成这部分功能。
1.软件布局
点击“截取”按钮则跳出保持对话框,“调整”按钮可进行GIF速度与分辨率调整,点选1:1会限制截取框的比例,开始与结束为需要保存的帧范围。
2.代码
需要引入Gif.Components.dll,网上可以下载这个dll
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.IO;
using Gif.Components;
namespace GIF截取
{
public partial class FormGIF : Form
{
private Point startPoint = new Point();
private Rectangle cutRect ;
private bool startDraw = false;
private Image srcImg;
FrameDimension fd = null;
int FrameCount=0, nowFrameCount=0;
String FilePath;
public FormGIF()
{
InitializeComponent();
}
private bool picbox_loadpic(Image img)
{
cutRect.Width = 0; cutRect.Height = 0;
fd = new FrameDimension(img.FrameDimensionsList[0]);
FrameCount = img.GetFrameCount(fd);
num_start.Maximum = FrameCount;
num_end.Maximum = FrameCount ;
num_start.Value = num_start.Minimum;
num_end.Value = num_end.Maximum;
label_cnt.Text = "帧数:"+FrameCount.ToString();
pictureBox_Main.Cursor = Cursors.Cross;
pictureBox_Main.Size = new System.Drawing.Size(img.Width, img.Height);
this.ClientSize = new System.Drawing.Size(pictureBox_Main.Right + 8, pictureBox_Main.Bottom+8);
Bitmap g_tempMainbmp = new Bitmap(img ); //清空缓存
//Graphics g = Graphics.FromImage(g_tempMainbmp);
//g.DrawImage(img, new Rectangle(0, 0, pictureBox_Main.Width, pictureBox_Main.Height), new Rectangle(0, 0, pictureBox_Main.Width, pictureBox_Main.Height), GraphicsUnit.Pixel);
pictureBox_Main.Image = g_tempMainbmp; //加载图片
//g.Dispose();
return true;
}
private void btn_open_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();//实例化文件打开对话框
ofd.Filter = "GIF|*.gif"; //设置对话框打开文件的括展名
if ( ofd.ShowDialog() == DialogResult.OK )
{
try
{
srcImg = Image.FromStream(new MemoryStream(File.ReadAllBytes(ofd.FileName)));
picbox_loadpic(srcImg);
FilePath = ofd.FileName;
}
catch
{
MessageBox.Show("文件不能识别","tip");
}
}
}
private void btn_cut_Click(object sender, EventArgs e)
{
if (fd != null && cutRect.Width!=0 )
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "GIF|*.gif";
sfd.DefaultExt = ".gif";
if ( sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK )
{
label_cnt.Text = "转换...";
label_cnt.Refresh();
AnimatedGifEncoder en = new AnimatedGifEncoder();
string ph = //Path.GetFullPath(FilePath) + "x.GIF";
sfd.FileName;
try
{
PropertyItem invtime = srcImg.GetPropertyItem(0x5100);
int delay = invtime.Value[0] + invtime.Value[1] * 256 + invtime.Value[2] * 256 * 256 + invtime.Value[3] * 256 * 256 * 256;
en.Start(ph);
en.SetRepeat(0); //-1:不循环,0:总是循环 播放
en.SetDelay(delay); // 延迟间隔
int start = 0, end = FrameCount-1;
if (checkBox_enbleframe.Checked)
{
int swap=0;
start = (int)num_start.Value - 1;
end = (int)num_end.Value - 1;
if (start > end) { swap = start; start = end; end = swap; }
}
for (int i = start; i <= end; i++)
{
srcImg.SelectActiveFrame(fd, i);
Bitmap bmp = new System.Drawing.Bitmap(srcImg);
Bitmap tbmp = new Bitmap(cutRect.Width, cutRect.Height);
Graphics g = Graphics.FromImage(tbmp);
g.DrawImage(bmp, new Rectangle(0, 0, cutRect.Width, cutRect.Height), cutRect, GraphicsUnit.Pixel);
//Image img = tbmp;
en.AddFrame(tbmp);
g.Dispose();
}
}
catch
{
MessageBox.Show("不是GIF");
}
en.Finish();
label_cnt.Text = "OK";
}
}
}
//将点限制在S内
void limitPoint(ref Point p , Size s)
{
if (p.X < 0) p.X = 0; if (p.Y < 0) p.Y = 0;
if (p.X >= s.Width) p.X = s.Width - 1; if (p.Y >= s.Height) p.Y = s.Height - 1;
}
private void pictureBox_Main_MouseDown(object sender, MouseEventArgs e)
{
startDraw = true;
startPoint = e.Location;
}
private void pictureBox_Main_MouseMove(object sender, MouseEventArgs e)
{
if (startDraw && pictureBox_Main.Image !=null)
{
Bitmap scratchImg = new Bitmap(pictureBox_Main.Width, pictureBox_Main.Height);
Graphics gg = Graphics.FromImage(scratchImg);
int width = 0;
int heigth = 0;
Point rectStartPoint = startPoint;
Point nowPointX = e.Location;
limitPoint(ref nowPointX, pictureBox_Main.Size );
{//画矩形
width = Math.Abs(nowPointX.X - startPoint.X); //确定矩形的宽
heigth = Math.Abs(nowPointX.Y - startPoint.Y);//确定矩形的高
if (checkBox_ratio.Checked) // 1:1限制
{
if (width > heigth) width = heigth;
if (nowPointX.X < rectStartPoint.X)
{
if (nowPointX.Y < rectStartPoint.Y)
{
cutRect = new Rectangle(rectStartPoint.X - width, rectStartPoint.Y - width, width, width);
}
else
{
cutRect = new Rectangle(rectStartPoint.X - width, rectStartPoint.Y, width, width);
}
}
else
{
if (nowPointX.Y < rectStartPoint.Y)
{
cutRect = new Rectangle(rectStartPoint.X, rectStartPoint.Y - width, width, width);
}
else
{
cutRect = new Rectangle(rectStartPoint.X, rectStartPoint.Y , width, width);
}
}
}
else
{
if (nowPointX.X < startPoint.X)
{
rectStartPoint.X = nowPointX.X;
}
if (nowPointX.Y < startPoint.Y)
{
rectStartPoint.Y = nowPointX.Y;
}
cutRect = new Rectangle(rectStartPoint.X, rectStartPoint.Y, width, heigth);
}
Pen dpen = new Pen(Color.Blue,1);
dpen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
dpen.DashPattern = new float[] {5,5};
gg.DrawRectangle(Pens.Red, cutRect);
gg.DrawRectangle(dpen, cutRect);
}
gg.Dispose();
pictureBox_Main.Refresh(); // 这个位置很关键,不能放在最后
Graphics gp = pictureBox_Main.CreateGraphics();
gp.DrawImage(scratchImg, 0, 0);
gp.Dispose();
}
}
private void pictureBox_Main_MouseUp(object sender, MouseEventArgs e)
{
if (startDraw)
{
startDraw = false;
}
}
private void btn_next_Click(object sender, EventArgs e)
{
if (fd != null)
{
nowFrameCount++;
if (nowFrameCount >= FrameCount) nowFrameCount = 0;
srcImg.SelectActiveFrame(fd, nowFrameCount);
btn_next.Text = "下一帧:" + ( (nowFrameCount+1) % (FrameCount+1) ).ToString();
Bitmap bmp = new System.Drawing.Bitmap(srcImg);
pictureBox_Main.Image = bmp;
}
}
private void btn_run_Click(object sender, EventArgs e)
{
if (srcImg != null)
{
if (btn_run.Text == "播放")
{
btn_run.Text = "停止";
btn_cut.Enabled = false;
pictureBox_Main.Image = srcImg;
}
else
{
btn_run.Text = "播放";
btn_cut.Enabled = true;
Bitmap bmp = new System.Drawing.Bitmap(srcImg);
pictureBox_Main.Image = bmp;
}
}
}
private void gifSet(int w, int h, int v)
{
if ( w * h > 0)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "GIF|*.gif";
sfd.DefaultExt = ".gif";
if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
label_cnt.Text = "压缩...";
label_cnt.Refresh();
AnimatedGifEncoder en = new AnimatedGifEncoder();
string ph = //Path.GetFullPath(FilePath) + "x.GIF";
sfd.FileName;
try
{
PropertyItem invtime = srcImg.GetPropertyItem(0x5100);
int delay = invtime.Value[0] + invtime.Value[1] * 256 + invtime.Value[2] * 256 * 256 + invtime.Value[3] * 256 * 256 * 256;
en.Start(ph);
en.SetRepeat(0); //-1:不循环,0:总是循环 播放
if (v == 5)
{ }
else {
double x = v / 5.0;
delay = delay * (int)x;
}
en.SetDelay(delay*10); // 延迟间隔
int start = 0, end = FrameCount - 1;
if (checkBox_enbleframe.Checked)
{
int swap = 0;
start = (int)num_start.Value - 1;
end = (int)num_end.Value - 1;
if (start > end) { swap = start; start = end; end = swap; }
}
for (int i = start; i <= end; i++)
{
srcImg.SelectActiveFrame(fd, i);
Bitmap bmp = new System.Drawing.Bitmap(srcImg);
Bitmap tbmp = new Bitmap(w, h);
Graphics g = Graphics.FromImage(tbmp);
g.DrawImage(bmp,0,0 ,w , h );
en.AddFrame(tbmp);
g.Dispose();
}
}
catch
{
MessageBox.Show("不是GIF");
}
en.Finish();
label_cnt.Text = "OK";
}
}
}
private void btn_rar_Click(object sender, EventArgs e)
{
if (fd != null)
{
FormResolution fr = new FormResolution();
if (fr.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
int v = fr.time;
int w = fr.w;
int h = fr.h;
fr.Dispose();
gifSet(w, h, v);
}
}
}
private void pictureBox_Main_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (fd != null)
{
PropertyItem invtime = srcImg.GetPropertyItem(0x5100);
MessageBox.Show("ID:"+invtime.Id.ToString() + "\r\ntime:" + invtime.Value[0].ToString() + "," + invtime.Value[1].ToString() + "," + invtime.Value[2].ToString() + "," + invtime.Value[3].ToString());
}
}
}
}
3.效果
选择一幅GIF,鼠标选取需要的部分,点击截取按钮,就可以保存下来了。
可设置分辨率,速度