使用ffmpeg 的 filter 給圖片添加水印

使用ffmpeg 的 filter 給圖片添加水印。
main.c

#include <stdio.h>#include <libavfilter/avfilter.h>
#include <libavfilter/buffersrc.h>
#include <libavfilter/buffersink.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>AVFilterContext* mainsrc_ctx = NULL;
AVFilterContext* logosrc_ctx = NULL;
AVFilterContext* resultsink_ctx = NULL;
AVFilterGraph* filter_graph = NULL;//初始化過濾器處理
static int init_filters(const AVFrame* main_frame, const AVFrame* logo_frame, int x, int y)
{int ret = 0;AVFilterInOut* inputs = NULL;AVFilterInOut* outputs = NULL;char filter_args[1024] = {0};//初始化用于整個過濾處理的封裝filter_graph = avfilter_graph_alloc();if(!filter_graph){printf("%d : avfilter_graph_alloc() failed!\n", __LINE__);return -1;}//所有使用到過濾器處理的命令snprintf(filter_args, sizeof(filter_args),"buffer=video_size=%dx%d:pix_fmt=%d:time_base=1/25:pixel_aspect=%d/%d[main];" // Parsed_buffer_0"buffer=video_size=%dx%d:pix_fmt=%d:time_base=1/25:pixel_aspect=%d/%d[logo];" // Parsed_bufer_1"[main][logo]overlay=%d:%d[result];" // Parsed_overlay_2"[result]buffersink", // Parsed_buffer_sink_3main_frame->width, main_frame->height, main_frame->format, main_frame->sample_aspect_ratio.num, main_frame->sample_aspect_ratio.den,logo_frame->width, logo_frame->height, logo_frame->format, logo_frame->sample_aspect_ratio.num, logo_frame->sample_aspect_ratio.den,x, y);//添加過濾器處理到AVFilterGraphret = avfilter_graph_parse2(filter_graph, filter_args, &inputs, &outputs);if(ret < 0){printf("%d : avfilter_graph_parse2() failed!\n", __LINE__);return ret;}//配置AVFilterGraph的過濾器處理ret = avfilter_graph_config(filter_graph, NULL);if(ret < 0){printf("%d : avfilter_graph_config() failed!\n", __LINE__);return ret;}//獲取AVFilterGraph內的過濾器mainsrc_ctx = avfilter_graph_get_filter(filter_graph, "Parsed_buffer_0");logosrc_ctx = avfilter_graph_get_filter(filter_graph, "Parsed_buffer_1");resultsink_ctx = avfilter_graph_get_filter(filter_graph, "Parsed_buffersink_3");avfilter_inout_free(&inputs);avfilter_inout_free(&outputs);return 0;
}//添加水印
static int main_mix_logo(AVFrame* main_frame, AVFrame* logo_frame, AVFrame *result_frame)
{int ret = 0;//添加主圖ret = av_buffersrc_add_frame(mainsrc_ctx, main_frame);if(ret < 0)return ret;//添加logoret = av_buffersrc_add_frame(logosrc_ctx, logo_frame);if(ret < 0)return ret;//獲取合成圖ret = av_buffersink_get_frame(resultsink_ctx, result_frame);return ret;}static AVFrame* get_jpeg(const char* filename)
{int ret = 0;AVFormatContext* format_ctx = NULL;//打開文件if((ret = avformat_open_input(&format_ctx, filename, NULL, NULL)) != 0){printf("%d : avformat_open_input() failed!\n");return NULL;}//獲取媒體文件信息avformat_find_stream_info(format_ctx, NULL);AVCodec* codec = NULL;AVCodecContext* codec_ctx = NULL;int video_stream_index = -1;//獲取流video_stream_index = av_find_best_stream(format_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0);if(video_stream_index < 0)goto cleanup;codec_ctx = avcodec_alloc_context3(codec);//關聯解碼器上下文ret = avcodec_open2(codec_ctx, codec, NULL);if(ret < 0)goto cleanup;AVPacket pkt;av_init_packet(&pkt);pkt.data = NULL;pkt.size = 0;//從文件中讀一幀ret = av_read_frame(format_ctx, &pkt);if(ret < 0)goto cleanup;//進行解碼ret = avcodec_send_packet(codec_ctx, &pkt);if(ret < 0)goto cleanup;//AVFrame* frame = av_frame_alloc();ret = avcodec_receive_frame(codec_ctx, frame);if(ret < 0)av_frame_free(&frame);cleanup:if(format_ctx)avformat_close_input(&format_ctx);if(codec_ctx)avcodec_free_context(&codec_ctx);return frame;
}static int savejpeg(const char* filename, const AVFrame* frame)
{//查找相應編碼器AVCodec* jpeg_codec = avcodec_find_encoder(AV_CODEC_ID_MJPEG);if(!jpeg_codec)return -1;AVCodecContext* jpeg_codec_ctx = avcodec_alloc_context3(jpeg_codec);if(!jpeg_codec_ctx)return -2;//設置jpeg相關參數jpeg_codec_ctx->pix_fmt = AV_PIX_FMT_YUVJ420P;jpeg_codec_ctx->width = frame->width;jpeg_codec_ctx->height = frame->height;jpeg_codec_ctx->time_base.num = 1;jpeg_codec_ctx->time_base.den = 25;jpeg_codec_ctx->framerate.num = 25;jpeg_codec_ctx->framerate.den = 1;AVDictionary* encoder_opts = NULL;//encoder_opts 為空就會分配內存的av_dict_set(&encoder_opts, "flags", "+qscale", 0);av_dict_set(&encoder_opts, "qmax", "2", 0);av_dict_set(&encoder_opts, "qmin", "2", 0);int ret = avcodec_open2(jpeg_codec_ctx, jpeg_codec, &encoder_opts);if(ret < 0){avcodec_free_context(&jpeg_codec_ctx);printf("%d : avcodec_open2() failed!\n");return -3;}av_dict_free(&encoder_opts);AVPacket pkt;av_init_packet(&pkt);pkt.data = NULL;pkt.size = 0;//編碼ret = avcodec_send_frame(jpeg_codec_ctx, frame);if(ret < 0){avcodec_free_context(&jpeg_codec_ctx);printf("%d : avcodec_send_frame() failed!\n");return -4;}ret = 0;while(ret >= 0){//得到編碼數據ret = avcodec_receive_packet(jpeg_codec_ctx, &pkt);if(ret == AVERROR(EAGAIN))continue;if(ret == AVERROR_EOF){ret = 0;break;}FILE* outfile = fopen(filename, "wb");if(!outfile){printf("%d : fopen() failed!\n");ret = -1;break;}//寫入文件if(fwrite((char*)pkt.data, 1, pkt.size, outfile) == pkt.size){ret = 0;}else{printf("%d : fwrite failed!\n");ret = -1;}fclose(outfile);ret = 0;break;}avcodec_free_context(&jpeg_codec_ctx);return ret;
}int main()
{printf("Hello watermarkmix!\n");AVFrame *main_frame = get_jpeg("main.jpg");AVFrame *logo_frame = get_jpeg("logo.jpg");AVFrame* result_frame = av_frame_alloc();int ret = 0;if(ret = init_filters(main_frame, logo_frame, 100, 200) < 0) {printf("%d : init_filters failed\n", __LINE__);goto end;}if(main_mix_logo(main_frame, logo_frame, result_frame) < 0) {printf("%d : main_picture_mix_logo failed\n", __LINE__);goto end;}savejpeg("output.jpg", result_frame);
end:if(main_frame)av_frame_free(&main_frame);if(logo_frame)av_frame_free(&logo_frame);if(result_frame)av_frame_free(&result_frame);if(filter_graph)avfilter_graph_free(&filter_graph);printf("finish\n");printf("End watermarkmix!\n");return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379074.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379074.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379074.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

程序崩潰 分析工具_程序分析工具| 軟件工程

程序崩潰 分析工具A program analysis tool implies an automatic tool that takes the source code or the executable code of a program as information and produces reports with respect to a few significant attributes of the program, for example, its size, multif…

28335接兩個spi設備_IIC和SPI如此流行,誰才是嵌入式工程師的必備工具?

IICvs SPI現今&#xff0c;在低端數字通信應用領域&#xff0c;我們隨處可見 IIC (Inter-Integrated Circuit) 和 SPI (Serial Peripheral Interface)的身影。原因是這兩種通信協議非常適合近距離低速芯片間通信。Philips(for IIC)和 Motorola(for SPI) 出于不同背景和市場需求…

線性表15|魔術師發牌問題和拉丁方陣 - 數據結構和算法20

線性表15 : 魔術師發牌問題和拉丁方陣 讓編程改變世界 Change the world by program 題外話 今天小甲魚看到到微博有朋友在問&#xff0c;這個《數據結構和算法》系列課程有木有JAVA版本的&#xff1f; 因為這個問題之前也有一些朋友問過&#xff0c;所以咱在這里統一說下哈…

[ZT]Three ways to tell if a .NET Assembly is Strongly Named (or has Strong Name)

Here are several convenient ways to tell whether a .NET assembly is strongly named. (English language note: I assume the form “strongly named” is preferred over “strong named” since that’s the form used in the output of the sn.exe tool shown immediat…

最佳頁面置換算法

在一個請求分頁系統中&#xff0c;采用最佳頁面置換算法時&#xff0c;假如一個作業的頁面走向為4、3、2、1、4、3、5、4、3、2、1、5&#xff0c;當分配給該作業的物理塊數M分別為3和4時&#xff0c;試計算在訪問過程中所發生的缺頁次數和缺頁率。請給出分析過程。 解析&…

網絡名稱 轉換 網絡地址_網絡地址轉換| 計算機網絡

網絡名稱 轉換 網絡地址At the time of classful addressing, the number of household users and small businesses that want to use the Internet kept increasing. In the beginning, a user was connected to the Internet with a dial-up line, for a specific period of…

rstudio 修改代碼間距_第一章 R和RStudio

R與RStudioR是一種統計學編程語言&#xff0c;在科學計算領域非常流行。它是由Ross Ihaka和Robert Gentleman開發的&#xff0c;是 "S "編程語言的開源實現。R也是使用這種語言進行統計計算的軟件的名字。它有一個龐大的在線支持社區和專門的軟件包&#xff0c;可以為…

ubuntu下最穩定的QQ

一、安裝好 Wine 1.2&#xff08;1.2 版安裝好就支持中文界面的了&#xff09; 當然得有WINE 了 當然我的有 如果沒有可以如下方法得到&#xff1a; 第一種方法&#xff1a;如果你已經安裝過 Wine 的老版本&#xff0c;那么只要添加 Wine 1.2 的軟件源&#xff0c;然后去新立得…

字體Times New Roman

Windows系統中的字體是Monotype公司為微軟公司制作的Times New Roman PS&#xff08;TrueType字體&#xff09;&#xff0c;視窗系統從3.1版本開始就一直附帶這個字體。而在蘋果電腦公司的麥金塔系統中使用的是Linotype公司的 Times Roman (在Macintosh系統中直接簡稱為‘Times…

最近最久未使用頁面置換算法

在一個請求分頁系統中&#xff0c;采用最近最久未使用頁面置換算法時&#xff0c;假如一個作業的頁面走向為4、3、2、1、4、3、5、4、3、2、1、5&#xff0c;當分配給該作業的物理塊數M分別為3和4時&#xff0c;試計算在訪問過程中所發生的缺頁次數和缺頁率。請給出分析過程。 …

ffplay的數據結構分析

《ffplay分析&#xff08;從啟動到讀取線程的操作&#xff09;》 《ffplay分析&#xff08;視頻解碼線程的操作&#xff09;》 《ffplay分析&#xff08;音頻解碼線程的操作&#xff09;》 《ffplay 分析&#xff08;音頻從Frame(解碼后)隊列取數據到SDL輸出&#xff09;》 《f…

tolowercase_Java String toLowerCase()方法與示例

tolowercase字符串toLowerCase()方法 (String toLowerCase() Method) toLowerCase() method is a String class method, it is used to convert given string into the lowercase. toLowerCase()方法是String類方法&#xff0c;用于將給定的字符串轉換為小寫。 Syntax: 句法&a…

python web 服務器實時監控 websocket_python websocket網頁實時顯示遠程服務器日志信息...

功能&#xff1a;用websocket技術&#xff0c;在運維工具的瀏覽器上實時顯示遠程服務器上的日志信息一般我們在運維工具部署環境的時候&#xff0c;需要實時展現部署過程中的信息&#xff0c;或者在瀏覽器中實時顯示程序日志給開發人員看。你還在用ajax每隔段時間去獲取服務器日…

磁盤調度算法

1&#xff0c;假設磁頭當前位于第105道&#xff0c;正在向磁道序號增加的方向移動&#xff0c;現有一個磁道訪問請求序列為&#xff1a;35&#xff0c;45&#xff0c;12&#xff0c;68&#xff0c;100&#xff0c;180&#xff0c;170&#xff0c;195&#xff0c;試用先來先服務…

C# Using用法三則

&#xff08;1&#xff09;引用命名空間 using作為引入命名空間指令的用法準則為&#xff1a; using Namespace; 在.NET程序中&#xff0c;最多見的代碼莫過于在程序文件的開頭引入System命名空間&#xff0c;其原由在于System命名空間中封裝了許多最基本最常用的操作&#xff…

iOS開發 工程

一直沒正兒八經的寫過技術文章。今日開個小窗&#xff0c;準備寫點東西。。。完了 1、傳統的MVC結構需要至少M、V、C三個模塊&#xff0c;在實際開發中往往需要添加額外的模塊&#xff0c;添加的模塊當然也大體上屬于這三個模塊之內。以下為較為常用的子模塊。 &#xff08;1&a…

C++11 std::shared_ptr的std::move()移動語義底層分析

std::shared_ptr的std::move()移動語義底層分析 執行std::move()之前&#xff1a; 執行std::move()之后&#xff1a; 結論&#xff1a;一個淺拷貝 sizeof(std::shared_ptr) 8字節 pss1 : 0x0028fea8 pss2 : 0x0028fea0 &#xff08;棧是逆增長的&#xff09; 觀察執行std::m…

一個使用numpy.ones()的矩陣| 使用Python的線性代數

Ones Matrix - When all the entries of a matrix are one, then it is called as ones matrix. It may be of any dimension (MxN). 一個矩陣 -當矩陣的所有條目均為1時&#xff0c;則稱為一個矩陣。 它可以是任何尺寸( MxN )。 Properties: 特性&#xff1a; The determina…

python去掉字符串最外側的引號_瘋狂Python講義第二章讀書筆記

本章講解變量和簡單類型2.1 從注釋講起單行注釋使用#&#xff0c;#后面的代碼被注釋掉不會運行&#xff0c;如&#xff1a;# print(123) 注釋掉后123不會輸出。多行注釋使用""" """&#xff0c;三個雙引號&#xff0c;雙引號中的內容注釋掉&…