基于C++写一个具有视频和图像压缩功能的程序
时间: 2024-06-07 18:11:57 浏览: 162
要实现视频和图像压缩功能,你可以使用一些开源库和算法,例如OpenCV和FFmpeg。以下是一个基本的C++程序框架,它可以使用OpenCV和FFmpeg库进行视频和图像压缩。
首先,你需要包含所需的头文件:
```c++
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
```
接下来,你可以定义视频和图像的压缩参数,例如压缩格式、编码器、帧率和分辨率等:
```c++
const char* filename = "input.mp4";
int codec_id = AV_CODEC_ID_H264;
int width = 640;
int height = 360;
int fps = 25;
```
然后,你可以使用OpenCV库加载图像或视频:
```c++
cv::Mat image = cv::imread("input.jpg");
cv::VideoCapture cap(filename);
```
接下来,你可以使用FFmpeg库创建输出视频文件并设置编码器和压缩参数:
```c++
AVFormatContext* format_ctx = NULL;
avformat_alloc_output_context2(&format_ctx, NULL, NULL, "output.mp4");
AVCodec* codec = avcodec_find_encoder(codec_id);
AVStream* stream = avformat_new_stream(format_ctx, codec);
AVCodecContext* codec_ctx = stream->codec;
codec_ctx->codec_id = codec_id;
codec_ctx->width = width;
codec_ctx->height = height;
codec_ctx->time_base = { 1, fps };
codec_ctx->gop_size = 10;
codec_ctx->max_b_frames = 1;
if (format_ctx->oformat->flags & AVFMT_GLOBALHEADER) {
codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
avcodec_open2(codec_ctx, codec, NULL);
avformat_write_header(format_ctx, NULL);
```
接下来,你可以使用OpenCV库读取图像或视频的帧,并使用FFmpeg库将它们压缩和编码:
```c++
cv::Mat frame;
AVFrame* av_frame = av_frame_alloc();
av_frame->format = codec_ctx->pix_fmt;
av_frame->width = codec_ctx->width;
av_frame->height = codec_ctx->height;
av_frame->pts = 0;
av_frame->pkt_dts = 0;
av_frame->pkt_duration = av_rescale_q(1, codec_ctx->time_base, stream->time_base);
while (cap.read(frame)) {
cv::resize(frame, frame, cv::Size(codec_ctx->width, codec_ctx->height));
cv::cvtColor(frame, frame, cv::COLOR_BGR2YUV);
av_frame->data[0] = frame.data;
av_frame->data[1] = av_frame->data[0] + codec_ctx->width * codec_ctx->height;
av_frame->data[2] = av_frame->data[1] + codec_ctx->width * codec_ctx->height / 4;
av_frame->linesize[0] = codec_ctx->width;
av_frame->linesize[1] = codec_ctx->width / 2;
av_frame->linesize[2] = codec_ctx->width / 2;
AVPacket pkt = { 0 };
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
int ret = avcodec_send_frame(codec_ctx, av_frame);
if (ret < 0) {
std::cerr << "Error sending a frame for encoding" << std::endl;
continue;
}
while (ret >= 0) {
ret = avcodec_receive_packet(codec_ctx, &pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
std::cerr << "Error during encoding" << std::endl;
break;
}
av_packet_rescale_ts(&pkt, codec_ctx->time_base, stream->time_base);
pkt.stream_index = stream->index;
av_write_frame(format_ctx, &pkt);
av_packet_unref(&pkt);
}
av_frame_unref(av_frame);
}
av_write_trailer(format_ctx);
avcodec_close(codec_ctx);
avformat_free_context(format_ctx);
```
最后,你可以使用OpenCV库显示压缩后的图像或播放压缩后的视频:
```c++
cv::Mat decoded_frame;
AVFrame* decoded_av_frame = av_frame_alloc();
AVCodec* decoder = avcodec_find_decoder(codec_id);
AVCodecContext* decoder_ctx = avcodec_alloc_context3(decoder);
avcodec_open2(decoder_ctx, decoder, NULL);
while (true) {
AVPacket pkt = { 0 };
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
if (av_read_frame(format_ctx, &pkt) < 0) {
break;
}
if (pkt.stream_index == stream->index) {
avcodec_send_packet(decoder_ctx, &pkt);
while (avcodec_receive_frame(decoder_ctx, decoded_av_frame) == 0) {
cv::Mat(decoded_av_frame->height, decoded_av_frame->width, CV_8UC3,
decoded_av_frame->data[0], decoded_av_frame->linesize[0]).copyTo(decoded_frame);
cv::cvtColor(decoded_frame, decoded_frame, cv::COLOR_YUV2BGR);
cv::imshow("Decoded Frame", decoded_frame);
cv::waitKey(1);
av_frame_unref(decoded_av_frame);
}
}
av_packet_unref(&pkt);
}
avcodec_free_context(&decoder_ctx);
av_frame_free(&decoded_av_frame);
cv::destroyAllWindows();
```
这就是一个基本的C++程序框架,它可以使用OpenCV和FFmpeg库进行视频和图像压缩。当然,你可以根据需要进行修改和扩展。
阅读全文