📜 ⬆️ ⬇️

Convert video file to gif

My programming experience in c ++ is 5 months, until this time I had been developing applications for mobile operating systems for about two years. At one point I got tired of it, and I decided that it was time to begin to fulfill my youthful dream - to become a game developer. And I slightly changed the direction of my career.

Somehow I sat and thought what would I write. I chose 16 programs for myself, threw a coin several times, and the lot pointed me to a program for getting gifs from a video. Who wants to see the amateur cross code - please under the cat.

The principle and structure is very simple. Two parameters enter our program: the path to our video and the name of the output gif. We create an instance of our unpretentious class and call the method of creating a gif (I forgot to say that we will use the libraries OpenCv and Magick ++).

Class Description:
')
class Video{ public: Video(const std::string& video_n, const std::string& gif_n){ video_name = video_n; output_gif_name = gif_n; }; ~Video() {}; void create_gif(); private: std::string video_name; std::string output_gif_name; std::vector<Mat> frames; std::vector<Magick::Image> Magick_frames; void extract_frames(); static inline Magick::Image mat_2_magick(cv::Mat& src); }; 

The constructor contains two parameters - our input parameters from the command line.

std :: vector frames is a property that contains frames of our video in the structure cv :: Mat, std :: vector <Magick :: Image>.
Magick_frames - this property stores the converted frames.

The extract_frames method pulls frames from the video. The algorithm is very simple and consists of the following:

1) create an instance of the class cv :: VideoCapture (class for video capture)
2) determine the frame counter and start the cycle where we will process the video
3) if our counter does not fall within the scope of our video, we exit; otherwise, set the frame to VideoCapture equal to our counter (CV_CAP_PROP_POS_FRAMES property)
4) try to read the frame and if it works out, then add it to std :: vector frames and increase the frame count by 10 (every tenth frame, which would facilitate the gif)

 void Video::extract_frames(){ try{ VideoCapture cap(this->video_name); if (!cap.isOpened()) CV_Error(CV_StsError, "Can't open video file"); double fIdx = 0; double frnb(cap.get(CV_CAP_PROP_FRAME_COUNT)); // std::cout << "frame count = " << frnb<< std::endl; for (;;){ // std::cout<<"frame : "<<fIdx<<std::endl; Mat frame; if (fIdx < 0 || fIdx >= frnb) break; cap.set(CV_CAP_PROP_POS_FRAMES, fIdx); bool success = cap.read(frame); if (success) { this->frames.push_back(frame); fIdx = fIdx + 10;} else break; } } catch(cv::Exception& e){ cerr << e.msg << std::endl; exit(1); } } 

In the main create_gif () method, we first execute the frame acquisition method, then convert these frames to the Magic :: Image structure and write the output file.

This is a method for converting cv :: Mat to Magic :: Image. This is necessary because opencv does not know how to work with gif files, I found a bunch of libraries, but decided to stop at magick ++.

* To be honest, I didn’t feel the compression and quality reduction up to 50%, the output file, with both these and without these parameters, weighed equally *

 inline Magick::Image Video::mat_2_magick(cv::Mat& src) { Magick::Image mgk(src.cols, src.rows, "BGR", Magick::CharPixel, (char *)src.data); mgk.compressType(JPEGCompression); mgk.quality(50); return mgk; } void Video::create_gif() { extract_frames();//       for(std::vector<cv::Mat>::iterator frame = this->frames.begin(); frame != this->frames.end(); ++frame){ this->Magick_frames.push_back(Video::mat_2_magick(*frame)); } Magick::writeImages(this->Magick_frames.begin(), this->Magick_frames.end(), this->output_gif_name); } 

I will tell you a little about one problem with which I was busy until 7 in the morning. I used CMake in this project and I did not specify the link and compilation flags. It was pretty disappointing that I missed it. Here is part of the Cmake file:

 find_file(MAGICK_CONFIG_EXE "Magick++-config" PATHS "/usr/bin" "/usr/local/bin" ) if (MAGICK_CONFIG_EXE) message(STATUS "Found Image Magick++ libaries -- Enabling MagickPainter.") execute_process(COMMAND Magick++-config --cppflags OUTPUT_VARIABLE Magick_CPP_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND Magick++-config --cxxflags OUTPUT_VARIABLE Magick_CXX_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND Magick++-config --ldflags OUTPUT_VARIABLE Magick_LD_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND Magick++-config --libs OUTPUT_VARIABLE Magick_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Magick_CPP_FLAGS} ${Magick_CXX_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${Magick_LIBS} ${Magick_LD_FLAGS}") # remove_definitions(-DUSE_MAGICK_PAINTER) endif (MAGICK_CONFIG_EXE) 

Everything is on the gita .

PS: the first post, I do not want to ask for mercy. On the contrary: I want you to appreciate to the fullest extent. I hope you will write that I am wrong and advise something.

Regards, Harry.

Source: https://habr.com/ru/post/269315/


All Articles