引言
gif
格式的动图可以通过连续播放一系列图像或视频片段来展示动态效果,使信息更加生动形象,可以很方便的嵌入到网页或者ppt中
。上图展示了视频的前几帧转为gif动图的效果 (转了7%直接取消了)。
之前写过一个基于python的 MP4视频转GIF动图,速度略慢且不容易打包 (体积很大),故基于c++写一个小程序,方便日常使用. (这里推荐几个gif生成的小工具 - GifCam
、ScreenGif.exe
、LICEcap.exe
等等 or 直接使用ffmpeg
提供的小工具)
- 本文思路:基于
FFmpeg
进行视频的读取解码成一张张图片,调用gif.h
将图片写入gif
gif-h官方git地址:https://github.com/charlietangora/gif-h
一、设计思路
可参考之前的博客:Qt 基于FFmpeg的视频播放器 - QtFFmpegPlayer
-
- 和之前的视频播放器
play()
函数类似,实现savetoGif()
函数,将视频的一帧解码成图片后,立即写入gif文件
- 和之前的视频播放器
GifWriteFrame(&writer, image.bits(),
static_cast<uint32_t>(avcodec_context->width),
static_cast<uint32_t>(avcodec_context->height),
static_cast<uint32_t>(100/this->m_fps), // 单位是1/100秒,即10ms
8, true);
frame_id++;
qDebug()<<QString("当前转换第 %1 帧").arg(frame_id);
emit sig_SendFrameNum(frame_id);
-
- 创建新的
FFmpegVideo
类和新的处理线程,避免与播放线程冲突
- 创建新的
m_FFmpegProcessing = new FFmpegVideo();
m_ProcessingThread = new QThread(this);
m_FFmpegProcessing->moveToThread(m_ProcessingThread); // 移动到线程中
-
- 创建非模态的进度条,发送
sig_SendFrameNum
帧数信号设置进度条进度 同时判断是否点击了进度条的按钮 (稳妥起见此连接设置为Qt::BlockingQueuedConnection
- 确定同步执行对m_stopProcessing
及时赋值)
- 创建非模态的进度条,发送
// 进度条
progressDialog = new QProgressDialog();
progressDialog->setMinimumWidth(300); // 设置最小宽度
progressDialog->setWindowModality(Qt::NonModal); // 非模态,其它窗口正常交互 Qt::WindowModal 模态
progressDialog->setMinimumDuration(0); // 等待0秒后显示
progressDialog->setWindowTitle(tr("进度条框")); // 标题名
progressDialog->setLabelText(tr("正在转换")); // 标签的
progressDialog->setCancelButtonText(tr("放弃")); // 取消按钮
progressDialog->setRange(0, static_cast<int>(m_FFmpegProcessing->m_frame_num)); // 考虑是否移换种方式显示进度条进度... 不使用帧数
// 进度条绑定
connect(m_FFmpegProcessing, &FFmpegVideo