隐藏

C#去除gif图片水印的操作方法

发布:2022/12/27 11:05:45作者:管理员 来源:本站 浏览次数:611

背景:


从网上下了几十个gif图片,准备用来做学习用,但是这图片里面水印比较多,就想到了能不能通过代码处理一下这个水印。

方案:


首先想到的是将gif的每一帧的图片都解出来,单个单个处理图片,单个图片水印处理完成之后再重新生成回gif图片。


到此,方案有了,相当于需求分析已经做完,就差编码了,废话不多说,进入主题。


第一步:


先把所有的gif的每一帧解出来


   Image gif = Image.FromFile(@"c:\users\server\desktop\91c9.gif");

   FrameDimension fd = new FrameDimension(gif.FrameDimensionsList[0]);

   

   //获取帧数(gif图片可能包含多帧,其它格式图片一般仅一帧)

   int count = gif.GetFrameCount(fd);

   

   //以jpeg格式保存各帧

   for (int i = 0; i < count; i++)

   {

       gif.SelectActiveFrame(fd, i);

       var savePath = @"C:\Users\Server\Desktop\gif\frame_" + i + ".jpg";

       gif.Save(savePath , ImageFormat.Jpeg);

   }


至此,图片已经完全解出来了,打开图片看,好在这个图片的水印都在四个角的位置(一般也不至于将水印写在中间部分,那样极大印象了gif图片的整体效果),利用截图工具先计算需要去掉水印框的矩形框大小,然后利用FillRectangle方法将该处填充为与图片同背景色的颜色区块。


第二步:填充选择区块


   FrameDimension fd = new FrameDimension(gif.FrameDimensionsList[0]);

   

   //获取帧数(gif图片可能包含多帧,其它格式图片一般仅一帧)

   int count = gif.GetFrameCount(fd);

   

   //以jpeg格式保存各帧

   for (int i = 0; i < count; i++)

   {

    gif.SelectActiveFrame(fd, i);

    System.IO.MemoryStream stream = new System.IO.MemoryStream();

    gif.Save(stream, ImageFormat.Jpeg);

       //由于导出的帧图片较多,直接存入到流,避免频繁的IO

    Bitmap bg_bitmap = new Bitmap(stream);

    using (Graphics g = Graphics.FromImage(bg_bitmap))

    {

    var bitmapW = bg_bitmap.Width;

    var bitmapH = bg_bitmap.Height;

   

    g.CompositingQuality = CompositingQuality.HighQuality;

    g.SmoothingMode = SmoothingMode.HighQuality;

    g.InterpolationMode = InterpolationMode.HighQualityBicubic;

   

    //左上角的某个位置

    var point = new System.Drawing.Point(0, 0);//位置

    var brush = new SolidBrush(Color.FromArgb(232, 232, 232));

    var size = new System.Drawing.Size(33, 46);//大小

    var racent = new Rectangle(point, size);

    g.FillRectangle(brush, racent);

   

    //右下角的位置

    point = new System.Drawing.Point(bitmapW - 69, bitmapH - 22);//位置

    size = new System.Drawing.Size(69, 22);//大小

    racent = new Rectangle(point, size);

    g.FillRectangle(brush, racent);

   

   

    EncoderParameter p;

    EncoderParameters ps;

    ps = new EncoderParameters(1);

   

    p = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);

    ps.Param[0] = p;

   

    ImageCodecInfo ii = GetCodecInfo("image/jpeg");

   

    var savePath = @"C:\Users\Server\Desktop\gif\frame_" + i + "_b.jpg";

   

    bg_bitmap.Save(savePath, ii, ps);//保存图片

    }

   }


补充获取图片格式的方法:


   ImageCodecInfo GetCodecInfo(string mimeType)

   {

    ImageCodecInfo[] CodecInfo = ImageCodecInfo.GetImageEncoders();

    foreach (ImageCodecInfo ici in CodecInfo)

    {

    if (ici.MimeType == mimeType) return ici;

    }

    return null;

   }


第三步:将去掉水印的图片重新组合成gif


   GifBitmapEncoder gEnc = new GifBitmapEncoder();

   for (int i = 0; i < count; i++)

   {

    var frameFilePath = @"C:\Users\Server\Desktop\gif\frame_" + i + "_b.jpg";

    var img = System.Drawing.Image.FromFile(frameFilePath);

    System.Drawing.Bitmap bmpImage = (Bitmap)img;

    var bmp = bmpImage.GetHbitmap();

    var src = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

    gEnc.Frames.Add(BitmapFrame.Create(src));

   }

   using (FileStream fs = new FileStream(@"C:\Users\Server\Desktop\test.gif", FileMode.Create))

   {

    gEnc.Save(fs);

   }


注意:此处需要引入

using System.Windows;

using System.Windows.Media.Imaging;


这两个命名空间,到这里,已经处理完成了。