/// <summary> /// 将Gif图片进行旋转或者翻转 /// </summary> /// <param name="gifFilePath">原图像路径</param> /// <param name="rotateType">翻转或者旋转方式</param> /// <param name="outputPath">输出路径</param> public static void Rotate(string gifFilePath, RotateFlipType rotateType, string outputPath) { if (!File.Exists(gifFilePath)) { throw new IOException(string.Format("文件{0}不存在!", gifFilePath)); } using (Bitmap ora_Img = new Bitmap(gifFilePath)) { if (ora_Img.RawFormat.Guid != ImageFormat.Gif.Guid) { throw new IOException(string.Format("文件{0}!", gifFilePath)); } } GifImage gifImage = GifDecoder.Decode(gifFilePath); ThinkDisposalMethod(gifImage); int index = 0; foreach (GifFrame f in gifImage.Frames) { f.Image.RotateFlip(rotateType); f.ImageDescriptor.Width = (short)f.Image.Width; f.ImageDescriptor.Height = (short)f.Image.Height; if (index++ == 0) { gifImage.LogicalScreenDescriptor.Width = (short)f.Image.Width; gifImage.LogicalScreenDescriptor.Height = (short)f.Image.Height; } } GifEncoder.Encode(gifImage, outputPath); }
/// <summary> /// 对Gif图片进行剪裁 /// </summary> /// <param name="gifFilePath">原图像</param> /// <param name="rect">剪裁区域</param> /// <param name="outFilePath">输出路径</param> public static void Crop(string gifFilePath, Rectangle rect, string outFilePath) { if (!File.Exists(gifFilePath)) { throw new IOException(string.Format("文件{0}不存在!", gifFilePath)); } using (Bitmap ora_Img = new Bitmap(gifFilePath)) { if (ora_Img.RawFormat.Guid != ImageFormat.Gif.Guid) { throw new IOException(string.Format("文件{0}!", gifFilePath)); } } GifImage gifImage = GifDecoder.Decode(gifFilePath); ThinkDisposalMethod(gifImage); int index = 0; foreach (GifFrame f in gifImage.Frames) { f.Image = f.Image.Clone(rect, f.Image.PixelFormat); f.ImageDescriptor.Width = (short)rect.Width; f.ImageDescriptor.Height = (short)rect.Height; if (index++ == 0) { gifImage.LogicalScreenDescriptor.Width = (short)rect.Width; gifImage.LogicalScreenDescriptor.Height = (short)rect.Height; } } GifEncoder.Encode(gifImage, outFilePath); }
/// <summary> /// 对gif动画添加水印 /// </summary> /// <param name="gifFilePath">原gif动画的路径</param> /// <param name="text">水印文字</param> /// <param name="textForceColor">水印文字的颜色,因为gif不是真彩色图片,所以在显示的时候,该颜色可能有所误差,但基本上可以确定颜色范围</param> /// <param name="font">字体</param> /// <param name="x">水印位置横坐标</param> /// <param name="y">水印位置纵坐标</param> /// <param name="outputPath">输出路径</param> public static void SmartWaterMark(string gifFilePath, string text, Color textForceColor, Font font, float x, float y, string outputPath) { if (!File.Exists(gifFilePath)) { throw new IOException(string.Format("文件{0}不存在!", gifFilePath)); } using (Bitmap ora_Img = new Bitmap(gifFilePath)) { if (ora_Img.RawFormat.Guid != ImageFormat.Gif.Guid) { throw new IOException(string.Format("文件{0}!", gifFilePath)); } } GifImage gifImage = GifDecoder.Decode(gifFilePath); ThinkDisposalMethod(gifImage); Color textColor = textForceColor;// Color.FromArgb(closestC); foreach (GifFrame f in gifImage.Frames) { Graphics g = Graphics.FromImage(f.Image); g.DrawString(text, font, new SolidBrush(textColor), new PointF(x, y)); g.Dispose(); } GifEncoder.Encode(gifImage, outputPath); }
/// <summary> /// 获取gif动画的缩略图 /// </summary> /// <param name="gifFilePath">原gif图片路径</param> /// <param name="rate">缩放大小</param> /// <param name="outputPath">缩略图大小</param> public static void GetThumbnail(string gifFilePath, double rate, string outputPath) { if (!File.Exists(gifFilePath)) { throw new IOException(string.Format("文件{0}不存在!", gifFilePath)); } using (Bitmap ora_Img = new Bitmap(gifFilePath)) { if (ora_Img.RawFormat.Guid != ImageFormat.Gif.Guid) { throw new IOException(string.Format("文件{0}!", gifFilePath)); } } GifImage gifImage = GifDecoder.Decode(gifFilePath); if (rate != 1.0) { gifImage.LogicalScreenDescriptor.Width = (short)(gifImage.LogicalScreenDescriptor.Width * rate); gifImage.LogicalScreenDescriptor.Height = (short)(gifImage.LogicalScreenDescriptor.Height * rate); int index = 0; foreach (GifFrame f in gifImage.Frames) { f.ImageDescriptor.XOffSet = (short)(f.ImageDescriptor.XOffSet * rate); f.ImageDescriptor.YOffSet = (short)(f.ImageDescriptor.YOffSet * rate); f.ImageDescriptor.Width = (short)(f.ImageDescriptor.Width * rate); f.ImageDescriptor.Height = (short)(f.ImageDescriptor.Height * rate); if (f.ImageDescriptor.Width == 0) { f.ImageDescriptor.Width = 1; } if (f.ImageDescriptor.Height == 0) { f.ImageDescriptor.Height = 1; } Bitmap bmp = new Bitmap(f.ImageDescriptor.Width, f.ImageDescriptor.Height); Graphics g = Graphics.FromImage(bmp); g.DrawImage(f.Image, new Rectangle(0, 0, f.ImageDescriptor.Width, f.ImageDescriptor.Height)); g.Dispose(); Quantizer(bmp, f.Palette); f.Image.Dispose(); f.Image = bmp; index++; } GifEncoder.Encode(gifImage, outputPath); } }
/// <summary> /// 对gif动画添加图片水印 /// </summary> /// <param name="gifFilePath">原图片路径</param> /// <param name="waterImg">水印图片</param> /// <param name="x">横坐标</param> /// <param name="y">纵坐标</param> /// <param name="outputPath">输出路径</param> public static void WaterMark(string gifFilePath, Bitmap waterImg, float x, float y, string outputPath) { if (!File.Exists(gifFilePath)) { throw new IOException(string.Format("文件{0}不存在!", gifFilePath)); } using (Bitmap ora_Img = new Bitmap(gifFilePath)) { if (ora_Img.RawFormat.Guid != ImageFormat.Gif.Guid) { throw new IOException(string.Format("文件{0}!", gifFilePath)); } } GifImage gifImage = GifDecoder.Decode(gifFilePath); ThinkDisposalMethod(gifImage); foreach (GifFrame f in gifImage.Frames) { Graphics g = Graphics.FromImage(f.Image); g.DrawImage(waterImg, new PointF(x, y)); g.Dispose(); OcTreeQuantizer q = new OcTreeQuantizer(8); Color32[] cs = q.Quantizer(f.Image); byte[] lct = new byte[cs.Length * 3]; int index = 0; int colorCount = 0; foreach (Color32 c in cs) { lct[index++] = c.Red; lct[index++] = c.Green; lct[index++] = c.Blue; if (c.ARGB == f.BgColor.ARGB) { f.GraphicExtension.TranIndex = (byte)colorCount; } colorCount++; } Quantizer(f.Image, cs); f.LocalColorTable = lct; f.ImageDescriptor.LctFlag = true; f.ImageDescriptor.LctSize = 256; f.ColorDepth = 8; } GifEncoder.Encode(gifImage, outputPath); }
/// <summary> /// 合并多个gif动画,在空间坐标上 /// </summary> /// <param name="sourceGifs">原图像</param> /// <param name="outPath">合并后图像</param> public static void Merge(List <string> sourceGifs, string outPath) { List <List <GifFrame> > frames = new List <List <GifFrame> >(); foreach (string source in sourceGifs) { if (!File.Exists(source)) { throw new IOException(string.Format("文件{0}不存在!", source)); } using (Bitmap ora_Img = new Bitmap(source)) { if (ora_Img.RawFormat.Guid != ImageFormat.Gif.Guid) { throw new IOException(string.Format("文件{0}!", source)); } } GifImage gifImage = GifDecoder.Decode(source); ThinkDisposalMethod(gifImage); int index = 0; foreach (GifFrame f in gifImage.Frames) { if (frames.Count <= index) { List <GifFrame> list = new List <GifFrame>(); frames.Add(list); } List <GifFrame> frameList = frames[index]; frameList.Add(f); index++; } } List <GifFrame> frameCol = new List <GifFrame>(); int frameIndex = 0; foreach (List <GifFrame> fs in frames) { GifFrame frame = Merge(fs); frameCol.Add(frame); if (frame.Image.Width != frameCol[0].Image.Width || frame.Image.Height != frameCol[0].Image.Height) { frame.ImageDescriptor.XOffSet = frames[frameIndex][0].ImageDescriptor.XOffSet; frame.ImageDescriptor.YOffSet = frames[frameIndex][0].ImageDescriptor.YOffSet; frame.GraphicExtension.DisposalMethod = frames[frameIndex][0].GraphicExtension.DisposalMethod; } frame.GraphicExtension.Delay = frame.Delay = frames[frameIndex][0].Delay; frameIndex++; } GifImage gifImg = new GifImage(); gifImg.Header = "GIF89a"; LogicalScreenDescriptor lcd = new LogicalScreenDescriptor(); lcd.Width = (short)frameCol[0].Image.Width; lcd.Height = (short)frameCol[0].Image.Height; gifImg.LogicalScreenDescriptor = lcd; ApplicationEx ape = new ApplicationEx(); List <ApplicationEx> apps = new List <ApplicationEx>(); apps.Add(ape); gifImg.ApplictionExtensions = apps; gifImg.Frames = frameCol; GifEncoder.Encode(gifImg, outPath); }
/// <summary> /// 对gif动画添加水印 /// </summary> /// <param name="gifFilePath">原gif动画的路径</param> /// <param name="text">水印文字</param> /// <param name="textForceColor">水印文字的颜色,因为gif不是真彩色图片,所以在显示的时候,该颜色可能有所误差,但基本上可以确定颜色范围</param> /// <param name="font">字体</param> /// <param name="x">水印位置横坐标</param> /// <param name="y">水印位置纵坐标</param> /// <param name="outputPath">输出路径</param> public static void WaterMark(string gifFilePath, SizeMode sizeMode, string text, Color textForceColor, Font font, float x, float y, string outputPath) { if (!File.Exists(gifFilePath)) { throw new IOException(string.Format("文件{0}不存在!", gifFilePath)); } using (Bitmap ora_Img = new Bitmap(gifFilePath)) { if (ora_Img.RawFormat.Guid != ImageFormat.Gif.Guid) { throw new IOException(string.Format("文件{0}!", gifFilePath)); } } GifImage gifImage = GifDecoder.Decode(gifFilePath); if (sizeMode == SizeMode.Large) { ThinkDisposalMethod(gifImage); } Color textColor = textForceColor; int frameCount = 0; foreach (GifFrame f in gifImage.Frames) { if ((sizeMode == SizeMode.Normal && frameCount++ == 0) || sizeMode == SizeMode.Large) { Graphics g = Graphics.FromImage(f.Image); g.DrawString(text, font, new SolidBrush(textColor), new PointF(x, y)); g.Dispose(); bool hasTextColor = false; Color32[] colors = PaletteHelper.GetColor32s(f.LocalColorTable); foreach (Color32 c in colors) { if (c.ARGB == textColor.ToArgb()) { hasTextColor = true; break; } } if (!hasTextColor) { if (f.Palette.Length < 256) { int newSize = f.Palette.Length * 2; Color32[] newColors = new Color32[newSize]; newColors[f.Palette.Length] = new Color32(textColor.ToArgb()); Array.Copy(colors, newColors, colors.Length); byte[] lct = new byte[newColors.Length * 3]; int index = 0; foreach (Color32 c in newColors) { lct[index++] = c.Red; lct[index++] = c.Green; lct[index++] = c.Blue; } f.LocalColorTable = lct; f.ImageDescriptor.LctFlag = true; f.ImageDescriptor.LctSize = newSize; f.ColorDepth = f.ColorDepth + 1; } else { OcTreeQuantizer q = new OcTreeQuantizer(8); Color32[] cs = q.Quantizer(f.Image); byte[] lct = new byte[cs.Length * 3]; int index = 0; int colorCount = 0; foreach (Color32 c in cs) { lct[index++] = c.Red; lct[index++] = c.Green; lct[index++] = c.Blue; if (c.ARGB == f.BgColor.ARGB) { f.GraphicExtension.TranIndex = (byte)colorCount; } colorCount++; } Quantizer(f.Image, cs); f.LocalColorTable = lct; f.ImageDescriptor.LctFlag = true; f.ImageDescriptor.LctSize = 256; f.ColorDepth = 8; } } } } GifEncoder.Encode(gifImage, outputPath); }
/// <summary> /// 合并多个gif文件 /// </summary> /// <param name="sourceGifs">原图像路径集合</param> /// <param name="outGif">合并后图像路径</param> /// <param name="delay">间隔时间</param> /// <param name="repeat">是否重复播放</param> public static void Merge(List <string> sourceGifs, string outGif, short delay, bool repeat) { GifImage gifImage = null; int index = 0; short lastDelay = delay; foreach (string source in sourceGifs) { if (!File.Exists(source)) { throw new IOException(string.Format("文件{0}不存在!", source)); } using (Bitmap ora_Img = new Bitmap(source)) { if (ora_Img.RawFormat.Guid != ImageFormat.Gif.Guid) { throw new IOException(string.Format("文件{0}!", source)); } } GifImage gif = GifDecoder.Decode(source); if (index == 0) { gifImage = gif; } int frameCount = 0; foreach (GifFrame f in gif.Frames) { if (frameCount == 0 && f.GraphicExtension.DisposalMethod == 0) { f.GraphicExtension.DisposalMethod = 2; } if (!f.ImageDescriptor.LctFlag) { f.ImageDescriptor.LctSize = f.LocalColorTable.Length / 3; f.ImageDescriptor.LctFlag = true; f.GraphicExtension.TranIndex = gif.LogicalScreenDescriptor.BgColorIndex; f.LocalColorTable = gif.GlobalColorTable; } if (frameCount == 0) { f.Delay = f.GraphicExtension.Delay = lastDelay; } if (f.Delay == 0) { f.Delay = f.GraphicExtension.Delay = lastDelay; } f.ColorDepth = (byte)(Math.Log(f.ImageDescriptor.LctSize, 2)); lastDelay = f.GraphicExtension.Delay; frameCount++; } gifImage.Frames.AddRange(gif.Frames); index++; } if (repeat && gifImage.ApplictionExtensions.Count == 0) { ApplicationEx ae = new ApplicationEx(); gifImage.ApplictionExtensions.Add(ae); } gifImage.LogicalScreenDescriptor.PixcelAspect = 0; Size maxSize = FindMaxSize(sourceGifs); gifImage.LogicalScreenDescriptor.Width = (short)maxSize.Width; gifImage.LogicalScreenDescriptor.Height = (short)maxSize.Height; GifEncoder.Encode(gifImage, outGif); }
/// <summary> /// Gif动画单色化 /// </summary> /// <param name="gifFilePath">原动画路径</param> /// <param name="outputPath">单色后动画路径</param> public static void Monochrome(string gifFilePath, string outputPath) { if (!File.Exists(gifFilePath)) { throw new IOException(string.Format("文件{0}不存在!", gifFilePath)); } using (Bitmap ora_Img = new Bitmap(gifFilePath)) { if (ora_Img.RawFormat.Guid != ImageFormat.Gif.Guid) { throw new IOException(string.Format("文件{0}!", gifFilePath)); } } GifImage gifImage = GifDecoder.Decode(gifFilePath); int transIndex = gifImage.LogicalScreenDescriptor.BgColorIndex; int c1 = (255 << 24) | (158 << 16) | (128 << 8) | 128; int c2 = (255 << 24) | (0 << 16) | (0 << 8) | 0; int c3 = (255 << 24) | (255 << 16) | (255 << 8) | 255; int c4 = (255 << 24) | (0 << 16) | (0 << 8) | 0; int[] palette = new int[] { c1, c2, c3, c4 }; byte[] buffer = new byte[12] { 128, 128, 128, 0, 0, 0, 255, 255, 255, 0, 0, 0 }; gifImage.GlobalColorTable = buffer; gifImage.LogicalScreenDescriptor.BgColorIndex = 0; gifImage.LogicalScreenDescriptor.GlobalColorTableSize = 4; gifImage.LogicalScreenDescriptor.GlobalColorTableFlag = true; int index = 0; foreach (GifFrame f in gifImage.Frames) { Color32[] act = PaletteHelper.GetColor32s(f.LocalColorTable); f.LocalColorTable = buffer; Color bgC = act[(transIndex / 3)].Color; byte bgGray = (byte)(bgC.R * 0.3 + bgC.G * 0.59 + bgC.B * 0.11); BitmapData bmpData = f.Image.LockBits(new Rectangle(0, 0, f.Image.Width, f.Image.Height), ImageLockMode.ReadWrite, f.Image.PixelFormat); unsafe { int *p = (int *)bmpData.Scan0.ToPointer(); for (int i = 0; i < f.Image.Width * f.Image.Height; i++) { if (p[i] == 0) { p[i] = c1; } else { Color c = Color.FromArgb(p[i]); int gray = (byte)(c.R * 0.3 + c.G * 0.59 + c.B * 0.11); if (gray > bgGray) { if (bgGray > 128) { p[i] = c2; } else { p[i] = c3; } } else if (gray < bgGray) { if (bgGray > 128) { p[i] = c3; } else { p[i] = c2; } } else { p[i] = c1; } } } } f.Image.UnlockBits(bmpData); f.GraphicExtension.TranIndex = 0; f.ColorDepth = 2; f.ImageDescriptor.LctFlag = false; index++; } GifEncoder.Encode(gifImage, outputPath); }