如何使用C#代码为现有GIF图片添加底部文字与背景并保存
问题:C#实现给GIF底部添加文字并保存
我有如下原始图片:
我希望通过代码编辑该GIF,在其底部添加文字,使文字成为GIF图片的一部分。
预期效果示例如下:
我用红色标注了想要添加到第一张图的灰色背景和时间日期文字,就是示例中灰色区域加文字的效果。
我想要给第一张GIF添加底部的日期时间文字,可以仅加文字,也可以新增底部灰色像素背景区域后再写入文字,最终保存修改后的GIF。
上述第二张图只是我想要在第一张图上实现的效果示例,具体文字内容可以自定义,核心需求是可编辑GIF、在底部添加文字并保存修改后的GIF。
目前已尝试的代码
新建了如下代码的类:
using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Text; using System.Text; namespace Wpf_Download_Files { class DrawOnImage { public Image DrawText(String text, String subText, Image img) { var textColor = Color.Black; var backColor = Color.Transparent; var textFont = new Font("Arial", 15); Brush textBrush = new SolidBrush(textColor); var subTextFont = new Font("Arial", 7); Brush subTextBrush = new SolidBrush(textColor); //first, create a dummy bitmap just to get a graphics object img = new Bitmap(img); Graphics drawing = Graphics.FromImage(img); //measure the string to see how big the image needs to be SizeF textSize = drawing.MeasureString(text, textFont); SizeF subTextSize = drawing.MeasureString(subText, subTextFont); //free up the dummy image and old graphics object img.Dispose(); drawing.Dispose(); //create a new image of the right size img = new Bitmap(((int)textSize.Width + (int)subTextSize.Width) - ((int)textSize.Width / 3), (int)textSize.Height + 15); drawing = Graphics.FromImage(img); drawing.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; //paint the background drawing.Clear(backColor); //Draw Text drawing.DrawString(text, textFont, textBrush, 5, 0); //Drawing Line var linePen = new Pen(Color.Black, 3); var height = (int)textSize.Height; var width = (int)textSize.Width; drawVerticalLine(drawing, linePen, 1, 0, height + 5); drawHorizontalLine(drawing, linePen, 0, height + 5, width / 3); //Darw Subtext drawing.DrawString(subText, subTextFont, subTextBrush, width / 3, height); drawing.Save(); textBrush.Dispose(); drawing.Dispose(); return img; } private void drawHorizontalLine(Graphics graphics, Pen pen, int x, int y, int width) { graphics.DrawLine(pen, x, y, x + width, y); } private void drawVerticalLine(Graphics graphics, Pen pen, int x, int y, int height) { graphics.DrawLine(pen, x, y, x, y + height); } } }
主窗体调用代码如下:
public MainWindow() { InitializeComponent(); System.Drawing.Image img = System.Drawing.Image.FromFile(@"d:\Downloaded Images\Image0.gif"); DrawOnImage drawonimage = new DrawOnImage(); drawonimage.DrawText("Hello World", "utt 12345", img); }
运行后GIF底部没有添加任何背景和文字,需要解决该问题实现需求。
解决方案
现有代码的核心问题
- 逻辑错误:你拿到原始GIF后先创建了副本,计算完文字尺寸就直接释放了原始GIF,最后返回的是仅包含文字的全新小图,完全没有保留原始GIF的内容。
- 未处理动帧:GIF是多帧动图,默认的
System.Drawing.Image只能加载第一帧,就算修改了单帧,保存后也会丢失动效。 - 没有保存结果:你调用完
DrawText方法后没有保存返回的图片,原始GIF文件当然不会有任何变化。
正确实现方案
我们需要先拆分GIF的所有帧,给每帧底部加上灰色背景和文字,再重新编码为动图保存,以下是可直接运行的实现:
- 先安装NuGet包:
Magick.NET-Q16-AnyCPU - 替换原有实现类:
using ImageMagick; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; public class GifEditor { public void AddTextToGif(string inputGifPath, string outputGifPath, string mainText, string subText) { // 加载GIF所有帧 using var collection = new MagickImageCollection(inputGifPath); var firstFrame = collection[0]; int gifWidth = firstFrame.Width; int textAreaHeight = 40; // 底部文字区域高度 int newGifHeight = firstFrame.Height + textAreaHeight; // 预渲染文字区域,避免每帧重复计算 using var textBitmap = new Bitmap(gifWidth, textAreaHeight); using (var g = Graphics.FromImage(textBitmap)) { g.Clear(Color.LightGray); // 灰色背景 g.SmoothingMode = SmoothingMode.AntiAlias; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; var mainFont = new Font("Arial", 14, FontStyle.Bold); var subFont = new Font("Arial", 9); var blackBrush = Brushes.Black; // 文字居中绘制 var mainSize = g.MeasureString(mainText, mainFont); g.DrawString(mainText, mainFont, blackBrush, (gifWidth - mainSize.Width)/2, 3); var subSize = g.MeasureString(subText, subFont); g.DrawString(subText, subFont, blackBrush, (gifWidth - subSize.Width)/2, 22); } // 把文字区域转成MagickImage格式 using var textLayer = MagickImage.FromBitmap(textBitmap); // 遍历所有帧处理 foreach (var frame in collection) { // 扩展画布,底部留出文字区域 frame.Extent(gifWidth, newGifHeight, Gravity.North, MagickColors.Transparent); // 把文字区域合成到帧底部 frame.Composite(textLayer, 0, frame.Height - textAreaHeight, CompositeOperator.Over); } // 保存为动图 collection.Write(outputGifPath); } }
- 调用方式修改为:
public MainWindow() { InitializeComponent(); var editor = new GifEditor(); editor.AddTextToGif(@"d:\Downloaded Images\Image0.gif", @"d:\Downloaded Images\Image0_with_text.gif", "2024-05-20 14:30", "自定义备注文字"); }
注意事项
- 如果你用的是.NET Framework,不需要安装System.Drawing.Common,直接引用System.Drawing即可
- 生成的新GIF会保存在你指定的输出路径,不会修改原始文件
- 文字大小、区域高度、背景色都可以根据需求自行调整参数
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

