基于opencv和ffmpeg,生成一个转换图片格式的函数
时间: 2023-05-22 19:05:46 浏览: 183
可以使用FFmpeg库和OpenCV库来转换图片格式,具体代码可以参考以下示例:
```cpp
#include <opencv2/opencv.hpp>
extern "C"
{
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}
using namespace cv;
bool ConvertImageFormat(const std::string& input_path, const std::string& output_path)
{
// Load input image using OpenCV
cv::Mat image = cv::imread(input_path);
// Check if image was loaded successfully
if (image.empty())
{
return false;
}
// Open output file
AVFormatContext* output_format_ctx = nullptr;
avformat_alloc_output_context2(&output_format_ctx, nullptr, nullptr, output_path.c_str());
if (!output_format_ctx)
{
return false;
}
// Find encoder for desired image format
AVCodec* codec = avcodec_find_encoder(output_format_ctx->oformat->video_codec);
if (!codec)
{
avformat_free_context(output_format_ctx);
return false;
}
// Create new video stream in output file
AVStream* stream = avformat_new_stream(output_format_ctx, codec);
if (!stream)
{
avformat_free_context(output_format_ctx);
return false;
}
// Set stream parameters (codec context)
AVCodecContext* codec_ctx = stream->codec;
codec_ctx->codec_id = output_format_ctx->oformat->video_codec;
codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
codec_ctx->pix_fmt = codec->pix_fmts[0];
codec_ctx->width = image.cols;
codec_ctx->height = image.rows;
codec_ctx->time_base = { 1, 30 };
// Open codec context
if (avcodec_open2(codec_ctx, codec, nullptr) < 0)
{
avformat_free_context(output_format_ctx);
return false;
}
// Write header to output file
if (avformat_write_header(output_format_ctx, nullptr) < 0)
{
avformat_free_context(output_format_ctx);
return false;
}
// Allocate memory for video frame
AVFrame* frame = av_frame_alloc();
if (!frame)
{
avformat_free_context(output_format_ctx);
return false;
}
frame->format = codec_ctx->pix_fmt;
frame->width = codec_ctx->width;
frame->height = codec_ctx->height;
// Convert input image to format expected by encoder
cv::Mat frame_mat;
cv::cvtColor(image, frame_mat, COLOR_BGR2YUV_I420);
// Copy image data to video frame
av_image_alloc(frame->data, frame->linesize, codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt, 1);
av_image_copy(frame->data, frame->linesize, (const uint8_t**)(frame_mat.data), frame_mat.step, codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height);
// Initialize packet for storing encoded video data
AVPacket packet;
av_init_packet(&packet);
// Encode and write frames to output file
int frame_count = 0;
while (true)
{
int ret = avcodec_send_frame(codec_ctx, frame);
if (ret < 0)
{
break;
}
while (true)
{
ret = avcodec_receive_packet(codec_ctx, &packet);
if (ret < 0)
{
break;
}
av_write_frame(output_format_ctx, &packet);
av_packet_unref(&packet);
}
frame_count++;
if (ret == AVERROR_EOF)
{
break;
}
}
// Flush encoder
avcodec_send_frame(codec_ctx, nullptr);
while (true)
{
int ret = avcodec_receive_packet(codec_ctx, &packet);
if (ret == AVERROR_EOF)
{
break;
}
av_write_frame(output_format_ctx, &packet);
av_packet_unref(&packet);
}
// Write trailer to output file
av_write_trailer(output_format_ctx);
// Free allocated resources
avformat_free_context(output_format_ctx);
av_frame_free(&frame);
return true;
}
```
注意:代码中使用的是YUV I420格式,如果需要转换其它格式,请根据需要修改相关代码。
阅读全文