背景

我们有很多这样的序列帧:

我这边要把这些序列帧裁切最后合并成gif,以下是我裁切后的png文件:

我一开始选用的是 SixLabors.ImageSharp

这是裁切代码:

using var image = Image.Load("input.jpg");
image.Clone(x => x.Crop(new Rectangle(10, 10, 250, 250)));
image.Save("output.jpg");

gif合成方案1(SixLabors.ImageSharp)

这里直接给出核心代码

public string FrameCombine(List<FrameConfig> frames, int fps)
{
Image firstFrame = null;
var delay = 100 / fps; //根据帧率技术延迟
GifDisposalMethod disposalMethod = GifDisposalMethod.RestoreToBackground; //背景处理方式
string outputPath = null; for (int i = 0; i < frames.Count; i++)
{
Image tempImage = Image.Load(frames[i].Path);
if (i == 0) //第一帧做底图
{
outputPath = Path.Combine(Path.GetDirectoryName(frames[i].Path), "sticker.gif");
if (File.Exists(outputPath))
{
return null;
} firstFrame = tempImage;
firstFrame.Frames.RootFrame.Metadata.GetGifMetadata().FrameDelay = delay;
firstFrame.Metadata.GetGifMetadata().RepeatCount = 0;
}
else
{
//把其他帧合到第一帧上
firstFrame.Frames.AddFrame(tempImage.Frames.RootFrame);
var meta = firstFrame.Frames[i].Metadata.GetGifMetadata();
meta.FrameDelay = delay;
meta.DisposalMethod = disposalMethod;
}
} firstFrame.SaveAsGif(outputPath); return outputPath;
}

最后合成效果(都多多少少有点问题)

大致显示正常(但锯齿和毛边严重)

还有这样的(带莫名的绿色噪点/绿底等):

这样的(莫名灰底):

试了很多方方法,想尽办法调各种属性都不行,看来用SixLabors.ImageSharp比较难解决了;

gif合成方案2(FFmpeg)--推荐

前面SixLabors.ImageSharp方案生成的gif太多问题了,最终是用FFmpeg重新合成才实现的。

步骤

首先,为所有图片生成一个统一的调色板:

ffmpeg -i %02d.png -vf "palettegen" palette.png

然后,使用这个调色板的颜色为基础来生成GIF:

ffmpeg -r 16 -i  %02d.png  -i palette.png -lavfi paletteuse sticker.gif

-r 16 :帧率
-i palette.png :是用于为GIF提供颜色调色板的图像。
-lavfi paletteuse:这是一个复杂的滤镜图描述,指示ffmpeg如何处理输入内容。paletteuse是一个特定的滤镜,它使用前面的name.png输入作为源来生成一个调色板,并使用这个调色板来处理其他输入(在本例中即img_%d.png匹配到的文件)。

将这两条命令合成一条

ffmpeg  -r 16 -i %02d.png -filter_complex "palettegen=stats_mode=single[pal],[0:v][pal]paletteuse" sticker.gif

C#写法(用了这个执行控制台命令的nuget CliWrap

var workDir = Path.GetDirectoryName(frames[0].Path);
var outputPath = Path.Combine(workDir, "sticker.gif");
var param = $" -r {fps} -i %02d.png -filter_complex \"palettegen=stats_mode=single[pal],[0:v][pal]paletteuse\" {outputPath} -y"; try
{
var result = await Cli.Wrap("ffmpeg").WithArguments(param).WithWorkingDirectory(workDir).ExecuteBufferedAsync(); if (result.ExitCode == 0)
{
return outputPath;
} return outputPath;
}
catch (Exception ex)
{
logger.LogError(ex, "FrameCombine2 failed:{0}", frames[0]?.Path);
}

最后展示效果

总结

有的时候其实是比较简单的问题,但如果思路限制在C#的话可能还是比较麻烦的,要去一个个图片处理库试了;

C# .net core中如何将多张png图片合并成一个gif的更多相关文章

  1. ros中同时订阅两个topic(2张图像)合并成一个topic(1张图像)

    2019-12-06 15:42:39 先暂时做个资料保存 要同时用两个红外相机,但是没有做硬件上的 时间戳同步,就是笔记本上同时插着两个相机. 两个topic发布各自相机的图像,然后要有个节点同时订 ...

  2. mysql中的多行查询结果合并成一个

    SELECT GROUP_CONCAT(md.data1) FROM DATA md,contacts cc WHERE md.conskey=cc.id AND md.mimetype_id= 5 ...

  3. gulp-css-spriter 将css代码中的切片图片合并成雪碧图

    NPM地址:https://www.npmjs.com/package/gulp-css-spriter/ 配置gulpfile.js: var gulp = require('gulp'),     ...

  4. MATLAB读取一张RGB图片转成YUV格式

    1.读入照片 控制输出的标志定义 clc;close all;clear YES = 1; NO = 0; %YES表示输出该文件,请用户配置 yuv444_out_txt = 1; yuv444_o ...

  5. php将两张身份证图片合并到一张图

    /** * @desc 合并身份证的正反面到同一张图片 * @author Jimmy * @date 2016-12-33 * @param $imageSrc0 身份证正面 * @param $i ...

  6. python中如何将两个list合并成一个list,不用for语句

    1, add 2, 用list的extend方法,L1.extend(L2),该方法将参数L2的全部元素添加到L1的尾部,例如: 3, 用切片(slice)操作,L1[len(L1):len(L1)] ...

  7. .NET Core 中的日志与分布式链路追踪

    目录 .NET Core 中的日志与分布式链路追踪 .NET Core 中的日志 控制台输出 非侵入式日志 Microsoft.Extensions.Logging ILoggerFactory IL ...

  8. .NET Core中的数据保护组件

    原文地址: PREVENTING INSECURE OBJECT REFERENCES IN ASP.NET CORE 2.0 作者: Tahir Naushad 背景介绍 在 OWASP(开放式 W ...

  9. .net core中的对象池

    asp.net core中通过扩展库的方式提供给了一个标准的对象池ObjectPool,定义在Microsoft.Extensions.ObjectPool.dll 程序集中.它本身是个纯虚的抽象类, ...

  10. 在asp.net core中使用托管服务实现后台任务

    在业务场景中经常需要后台服务不停的或定时处理一些任务,这些任务是不需要及时响应请求的. 在 asp.net中会使用windows服务来处理. 在 asp.net core中,可以使用托管服务来实现,托 ...

随机推荐

  1. [FAQ] puppeteer 清空输入框的值 并 重新输入

    一种方式是,清空输入框可以通过如下注入代码实现,但是可能存在 和页面本身的操作 存在优先级问题. await page.evaluate( () => document.getElementBy ...

  2. 不只有 Spring,这四款 Java 基础开发框架同样值得关注! 审核中

    Java 开发不只有 Spring ,今天给大家推荐几个同样优秀的 Java 基础开发框架,为日常项目开发提供更多的选择.答应我,请不要再叫我 Spring 小子了,​好吗? 项目概览: Guice: ...

  3. C语言程序设计-笔记9-函数与程序结构

    C语言程序设计-笔记9-函数与程序结构 例10-1    有序表的增删查操作.首先输入一个无重复元素的.从小到大排列的有序表,并在屏幕上显示以下菜单(编号和选项),用户可以反复对该有序表进行插入.删除 ...

  4. 移动端、微信小程序兼容性问题汇总(持续更新……

    1. safari浏览器字体不能自动随网页缩放调整大小 -webkit-text-size-adjust:100% 2. 点击<button><input>有灰色透明背景 -w ...

  5. IDEA 2020 Maven编译问题:Error:(3, 32) java: 程序包org.springframework.boot不存在。

    今天在编译Maven项目时,包已经加载好了,也进行了打包,途中均没有报错.package -- Install -- test 都没用问题,但是,一致性run,就会一直报错,如图 检查打包位置,包也在 ...

  6. npm包离线安装

    npm包离线安装 npm包的安装,在Internet联网机器上通过npm install轻松搞定的事情,在离线或者纯内网环境下就变得异常艰难,本文就来讲一讲离线安装npm包的方法. 通过 npm in ...

  7. smtplib详解,发送邮件

    创建邮箱账号 1.官网登录邮箱. 2.在邮箱的主界面找到"设置",新版的主界面与旧版稍有不同,一般位于上方,齿轮状的即是. 3.点击齿轮状的设置标志,会弹出一个下拉菜单,在最后有我 ...

  8. win11如何调解屏幕亮度【win10刚刚升级win11】?

    打开电脑后鼠标右键,点击个性化 点击系统 点击屏幕亮度 滑动按钮,调解屏幕亮度即可

  9. ModelScope初体验

    使用环境:windows 11 前置条件:已安装 anaconda 参考文档:环境安装 step1:新建一个 conda 环境,命名为 modelscope conda create -n model ...

  10. exe应用程序安装为windows服务

    1.使用instsrv.exe和srvany.exe 当你获取到srvany后并决定将某程序作为服务启动后,请先将srvany安装为系统服务,具体的安装方法有很多,这里使用instsrv,语法如下:安 ...