Visual Servoing Platform  version 3.6.1 under development (2024-05-27)
vpVideoWriter.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Write image sequences.
32  */
33 
39 #include <visp3/core/vpDebug.h>
40 #include <visp3/core/vpIoTools.h>
41 #include <visp3/io/vpVideoWriter.h>
42 
43 #if defined(HAVE_OPENCV_IMGPROC)
44 #include <opencv2/imgproc/imgproc.hpp>
45 #endif
46 
51  :
52 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_VIDEOIO)
53  m_writer(), m_framerate(25.0),
54 #endif
55  m_formatType(FORMAT_UNKNOWN), m_videoName(), m_frameName(), m_initFileName(false), m_isOpen(false), m_frameCount(0),
56  m_firstFrame(0), m_width(0), m_height(0), m_frameStep(1)
57 {
58 #if defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_VIDEOIO)
59 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
60  m_fourcc = cv::VideoWriter::fourcc('P', 'I', 'M', '1');
61 #else
62  m_fourcc = CV_FOURCC('P', 'I', 'M', '1'); // default is a MPEG-1 codec
63 #endif
64 #endif
65 }
66 
71 
86 void vpVideoWriter::setFileName(const std::string &filename)
87 {
88  if (filename.empty()) {
89  throw(vpImageException(vpImageException::noFileNameError, "Filename empty in video writer"));
90  }
91 
92  m_videoName = filename;
93  m_frameName = filename;
94 
95  m_formatType = getFormat(filename);
96 
97  if (m_formatType == FORMAT_UNKNOWN) {
98  throw(vpException(vpException::badValue, "Filename extension not supported in video writer"));
99  }
100 
101  m_initFileName = true;
102 }
103 
113 {
114  if (!m_initFileName) {
115  throw(vpImageException(vpImageException::noFileNameError, "The generic filename has to be set in video writer"));
116  }
117 
119 
120  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
121  m_formatType == FORMAT_PNG) {
122  m_width = I.getWidth();
123  m_height = I.getHeight();
124  } else if (m_formatType == FORMAT_AVI || m_formatType == FORMAT_MPEG || m_formatType == FORMAT_MPEG4 ||
125  m_formatType == FORMAT_MOV) {
126 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_VIDEOIO)
127  m_writer = cv::VideoWriter(m_videoName, m_fourcc, m_framerate,
128  cv::Size(static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight())));
129 
130  if (!m_writer.isOpened()) {
131  throw(vpException(vpException::fatalError, "Could not encode the video with OpenCV"));
132  }
133 #else
134  throw(vpException(vpException::fatalError, "To encode video files ViSP should be build with OpenCV >= 2.1.0"));
135 #endif
136  }
137 
138  m_frameCount = m_firstFrame;
139 
140  m_isOpen = true;
141 }
142 
152 {
153  if (!m_initFileName) {
154  throw(vpImageException(vpImageException::noFileNameError, "The generic filename has to be set in video writer"));
155  }
156 
158 
159  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
160  m_formatType == FORMAT_PNG) {
161  m_width = I.getWidth();
162  m_height = I.getHeight();
163  } else if (m_formatType == FORMAT_AVI || m_formatType == FORMAT_MPEG || m_formatType == FORMAT_MPEG4 ||
164  m_formatType == FORMAT_MOV) {
165 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_VIDEOIO)
166  m_writer = cv::VideoWriter(m_videoName, m_fourcc, m_framerate,
167  cv::Size(static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight())));
168 
169  if (!m_writer.isOpened()) {
170  throw(vpException(vpException::fatalError, "Could not encode the video with OpenCV"));
171  }
172 #else
173  throw(vpException(vpException::fatalError, "To encode video files ViSP should be build with OpenCV >= 2.1.0"));
174 #endif
175  }
176 
177  m_frameCount = m_firstFrame;
178 
179  m_isOpen = true;
180 }
181 
192 {
193  if (!m_isOpen) {
194  throw(vpException(vpException::notInitialized, "The video has to be open first with video writer open() method"));
195  }
196 
197  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
198  m_formatType == FORMAT_PNG) {
199  char name[FILENAME_MAX];
200  snprintf(name, FILENAME_MAX, m_videoName.c_str(), m_frameCount);
201  vpImageIo::write(I, name);
202  m_frameName = std::string(name);
203  } else {
204 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_VIDEOIO)
205  cv::Mat matFrame;
206  vpImageConvert::convert(I, matFrame);
207  m_writer << matFrame;
208 #endif
209  }
210 
211  m_frameCount += m_frameStep;
212 }
213 
224 {
225  if (!m_isOpen) {
226  throw(vpException(vpException::notInitialized, "The video has to be open first with video writer open() method"));
227  }
228 
229  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
230  m_formatType == FORMAT_PNG) {
231  char name[FILENAME_MAX];
232  snprintf(name, FILENAME_MAX, m_videoName.c_str(), m_frameCount);
233  vpImageIo::write(I, name);
234  m_frameName = std::string(name);
235  } else {
236 #if defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_VIDEOIO)
237 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
238  cv::Mat matFrame, rgbMatFrame;
239  vpImageConvert::convert(I, matFrame);
240  cv::cvtColor(matFrame, rgbMatFrame, cv::COLOR_GRAY2BGR);
241  m_writer << rgbMatFrame;
242 #else
243  cv::Mat matFrame, rgbMatFrame;
244  vpImageConvert::convert(I, matFrame);
245  cv::cvtColor(matFrame, rgbMatFrame, CV_GRAY2BGR);
246  m_writer << rgbMatFrame;
247 #endif
248 #endif
249  }
250 
251  m_frameCount += m_frameStep;
252 }
253 
258 {
259  if (!m_isOpen) {
260  throw(vpException(vpException::notInitialized, "Cannot close video writer: not yet opened"));
261  }
262 }
263 
269 vpVideoWriter::vpVideoFormatType vpVideoWriter::getFormat(const std::string &filename)
270 {
271  std::string ext = vpVideoWriter::getExtension(filename);
272 
273  if (ext.compare(".PGM") == 0)
274  return FORMAT_PGM;
275  else if (ext.compare(".pgm") == 0)
276  return FORMAT_PGM;
277  else if (ext.compare(".PPM") == 0)
278  return FORMAT_PPM;
279  else if (ext.compare(".ppm") == 0)
280  return FORMAT_PPM;
281  else if (ext.compare(".JPG") == 0)
282  return FORMAT_JPEG;
283  else if (ext.compare(".jpg") == 0)
284  return FORMAT_JPEG;
285  else if (ext.compare(".JPEG") == 0)
286  return FORMAT_JPEG;
287  else if (ext.compare(".jpeg") == 0)
288  return FORMAT_JPEG;
289  else if (ext.compare(".PNG") == 0)
290  return FORMAT_PNG;
291  else if (ext.compare(".png") == 0)
292  return FORMAT_PNG;
293  else if (ext.compare(".AVI") == 0)
294  return FORMAT_AVI;
295  else if (ext.compare(".avi") == 0)
296  return FORMAT_AVI;
297  else if (ext.compare(".MPEG") == 0)
298  return FORMAT_MPEG;
299  else if (ext.compare(".mpeg") == 0)
300  return FORMAT_MPEG;
301  else if (ext.compare(".MPG") == 0)
302  return FORMAT_MPEG;
303  else if (ext.compare(".mpg") == 0)
304  return FORMAT_MPEG;
305  else if (ext.compare(".MPEG4") == 0)
306  return FORMAT_MPEG4;
307  else if (ext.compare(".mpeg4") == 0)
308  return FORMAT_MPEG4;
309  else if (ext.compare(".MP4") == 0)
310  return FORMAT_MPEG4;
311  else if (ext.compare(".mp4") == 0)
312  return FORMAT_MPEG4;
313  else if (ext.compare(".MOV") == 0)
314  return FORMAT_MOV;
315  else if (ext.compare(".mov") == 0)
316  return FORMAT_MOV;
317  else
318  return FORMAT_UNKNOWN;
319 }
320 
321 // return the extension of the file including the dot
322 std::string vpVideoWriter::getExtension(const std::string &filename)
323 {
324  // extract the extension
325  size_t dot = filename.find_last_of(".");
326  std::string ext = filename.substr(dot, filename.size() - 1);
327  return ext;
328 }
329 
336 {
337  if (first_frame < 0) {
338  throw(vpException(vpException::fatalError, "Video writer first frame index cannot be negative"));
339  }
340  m_firstFrame = first_frame;
341 }
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ badValue
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:72
@ notInitialized
Used to indicate that a parameter is not initialized.
Definition: vpException.h:73
@ fatalError
Fatal error.
Definition: vpException.h:71
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Error that can be emitted by the vpImage class and its derivatives.
@ noFileNameError
Image file name error.
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:287
unsigned int getWidth() const
Definition: vpImage.h:245
unsigned int getHeight() const
Definition: vpImage.h:184
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:983
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:2088
void saveFrame(vpImage< vpRGBa > &I)
virtual ~vpVideoWriter()
void setFileName(const std::string &filename)
void open(vpImage< vpRGBa > &I)
void setFirstFrameIndex(int first_frame)