Convert video file to gif

My programming experience in C ++ is 5 months, until that time I have been developing applications for mobile operating systems for about two years. At one moment I was tired of it, and I decided that it was time to start fulfilling my youthful dream - to become a game developer. And I slightly changed the direction of my career.

So somehow I sat and thought what would I write. I chose 16 programs for myself, tossed a coin several times, and the lot pointed me to the program to get GIFs from the video. Who wants to see the amateurish cross code - please, under cat.

The principle and structure are very simple. Two parameters are input to our program: the path to our video and the name of the output GIF. We create an instance of our simple class and call the GIF creation method (I forgot to say that we will use the OpenCv and Magick ++ libraries).

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 frames;
  std::vector 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 - a property that contains frames of our video in the structure cv :: Mat, std :: vector.
Magick_frames - This property stores converted frames.

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

1) create an instance of the cv :: VideoCapture class (class for video capture)
2) define a frame counter and start a loop where we will process the video
3) if our counter does not fall into the scope of our video, exit, otherwise, set the VideoCapture frame equal to our counter (CV_CAP_PROP_POS_FRAMES property)
4) try to read the frame and if it does, add it to std :: vector frames and increase the frame counter by 10 (every tenth frame to make the gif easier)

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 : "<= 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 the method to convert 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 stay on magick ++.

* To be honest, I did not feel compression and quality reduction to 50%, the output file, with both these and without these parameters, weighed the same *

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::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’ll talk a little about one problem with which I was transported until 7 in the morning. I used CMake in this project and I did not specify the link and compilation flags. It was rather a shame that I missed it. Here is the 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 .

Regards, Max.

Also popular now: