Visual Servoing Platform  version 3.6.1 under development (2024-12-17)
vpVideoWriter.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 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/vpIoTools.h>
40 #include <visp3/io/vpVideoWriter.h>
41 
42 #if defined(HAVE_OPENCV_IMGPROC)
43 #include <opencv2/imgproc/imgproc.hpp>
44 #endif
45 
46 BEGIN_VISP_NAMESPACE
47 
52  :
53 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_VIDEOIO)
54  m_writer(), m_framerate(25.0),
55 #endif
56  m_formatType(FORMAT_UNKNOWN), m_videoName(), m_frameName(), m_initFileName(false), m_isOpen(false), m_frameCount(0),
57  m_firstFrame(0), m_width(0), m_height(0), m_frameStep(1)
58 {
59 #if defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_VIDEOIO)
60 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
61  m_fourcc = cv::VideoWriter::fourcc('P', 'I', 'M', '1');
62 #else
63  m_fourcc = CV_FOURCC('P', 'I', 'M', '1'); // default is a MPEG-1 codec
64 #endif
65 #endif
66 }
67 
72 
87 void vpVideoWriter::setFileName(const std::string &filename)
88 {
89  if (filename.empty()) {
90  throw(vpImageException(vpImageException::noFileNameError, "Filename empty in video writer"));
91  }
92 
93  m_videoName = filename;
94  m_frameName = filename;
95 
96  m_formatType = getFormat(filename);
97 
98  if (m_formatType == FORMAT_UNKNOWN) {
99  throw(vpException(vpException::badValue, "Filename extension not supported in video writer"));
100  }
101 
102  m_initFileName = true;
103 }
104 
114 {
115  if (!m_initFileName) {
116  throw(vpImageException(vpImageException::noFileNameError, "The generic filename has to be set in video writer"));
117  }
118 
120 
121  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
122  m_formatType == FORMAT_PNG) {
123  m_width = I.getWidth();
124  m_height = I.getHeight();
125  }
126  else if (m_formatType == FORMAT_AVI || m_formatType == FORMAT_MPEG || m_formatType == FORMAT_MPEG4 ||
127  m_formatType == FORMAT_MOV) {
128 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_VIDEOIO)
129  m_writer = cv::VideoWriter(m_videoName, m_fourcc, m_framerate,
130  cv::Size(static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight())));
131 
132  if (!m_writer.isOpened()) {
133  throw(vpException(vpException::fatalError, "Could not encode the video with OpenCV"));
134  }
135 #else
136  throw(vpException(vpException::fatalError, "To encode video files ViSP should be build with OpenCV >= 2.1.0"));
137 #endif
138  }
139 
140  m_frameCount = m_firstFrame;
141 
142  m_isOpen = true;
143 }
144 
154 {
155  if (!m_initFileName) {
156  throw(vpImageException(vpImageException::noFileNameError, "The generic filename has to be set in video writer"));
157  }
158 
160 
161  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
162  m_formatType == FORMAT_PNG) {
163  m_width = I.getWidth();
164  m_height = I.getHeight();
165  }
166  else if (m_formatType == FORMAT_AVI || m_formatType == FORMAT_MPEG || m_formatType == FORMAT_MPEG4 ||
167  m_formatType == FORMAT_MOV) {
168 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_VIDEOIO)
169  m_writer = cv::VideoWriter(m_videoName, m_fourcc, m_framerate,
170  cv::Size(static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight())));
171 
172  if (!m_writer.isOpened()) {
173  throw(vpException(vpException::fatalError, "Could not encode the video with OpenCV"));
174  }
175 #else
176  throw(vpException(vpException::fatalError, "To encode video files ViSP should be build with OpenCV >= 2.1.0"));
177 #endif
178  }
179 
180  m_frameCount = m_firstFrame;
181 
182  m_isOpen = true;
183 }
184 
195 {
196  if (!m_isOpen) {
197  throw(vpException(vpException::notInitialized, "The video has to be open first with video writer open() method"));
198  }
199 
200  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
201  m_formatType == FORMAT_PNG) {
202  char name[FILENAME_MAX];
203  snprintf(name, FILENAME_MAX, m_videoName.c_str(), m_frameCount);
204  vpImageIo::write(I, name);
205  m_frameName = std::string(name);
206  }
207  else {
208 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_VIDEOIO)
209  cv::Mat matFrame;
210  vpImageConvert::convert(I, matFrame);
211  m_writer << matFrame;
212 #endif
213  }
214 
215  m_frameCount += m_frameStep;
216 }
217 
228 {
229  if (!m_isOpen) {
230  throw(vpException(vpException::notInitialized, "The video has to be open first with video writer open() method"));
231  }
232 
233  if (m_formatType == FORMAT_PGM || m_formatType == FORMAT_PPM || m_formatType == FORMAT_JPEG ||
234  m_formatType == FORMAT_PNG) {
235  char name[FILENAME_MAX];
236  snprintf(name, FILENAME_MAX, m_videoName.c_str(), m_frameCount);
237  vpImageIo::write(I, name);
238  m_frameName = std::string(name);
239  }
240  else {
241 #if defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_VIDEOIO)
242 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
243  cv::Mat matFrame, rgbMatFrame;
244  vpImageConvert::convert(I, matFrame);
245  cv::cvtColor(matFrame, rgbMatFrame, cv::COLOR_GRAY2BGR);
246  m_writer << rgbMatFrame;
247 #else
248  cv::Mat matFrame, rgbMatFrame;
249  vpImageConvert::convert(I, matFrame);
250  cv::cvtColor(matFrame, rgbMatFrame, CV_GRAY2BGR);
251  m_writer << rgbMatFrame;
252 #endif
253 #endif
254  }
255 
256  m_frameCount += m_frameStep;
257 }
258 
263 {
264  if (!m_isOpen) {
265  throw(vpException(vpException::notInitialized, "Cannot close video writer: not yet opened"));
266  }
267 }
268 
274 vpVideoWriter::vpVideoFormatType vpVideoWriter::getFormat(const std::string &filename)
275 {
276  std::string ext = vpVideoWriter::getExtension(filename);
277 
278  if (ext.compare(".PGM") == 0)
279  return FORMAT_PGM;
280  else if (ext.compare(".pgm") == 0)
281  return FORMAT_PGM;
282  else if (ext.compare(".PPM") == 0)
283  return FORMAT_PPM;
284  else if (ext.compare(".ppm") == 0)
285  return FORMAT_PPM;
286  else if (ext.compare(".JPG") == 0)
287  return FORMAT_JPEG;
288  else if (ext.compare(".jpg") == 0)
289  return FORMAT_JPEG;
290  else if (ext.compare(".JPEG") == 0)
291  return FORMAT_JPEG;
292  else if (ext.compare(".jpeg") == 0)
293  return FORMAT_JPEG;
294  else if (ext.compare(".PNG") == 0)
295  return FORMAT_PNG;
296  else if (ext.compare(".png") == 0)
297  return FORMAT_PNG;
298  else if (ext.compare(".AVI") == 0)
299  return FORMAT_AVI;
300  else if (ext.compare(".avi") == 0)
301  return FORMAT_AVI;
302  else if (ext.compare(".MPEG") == 0)
303  return FORMAT_MPEG;
304  else if (ext.compare(".mpeg") == 0)
305  return FORMAT_MPEG;
306  else if (ext.compare(".MPG") == 0)
307  return FORMAT_MPEG;
308  else if (ext.compare(".mpg") == 0)
309  return FORMAT_MPEG;
310  else if (ext.compare(".MPEG4") == 0)
311  return FORMAT_MPEG4;
312  else if (ext.compare(".mpeg4") == 0)
313  return FORMAT_MPEG4;
314  else if (ext.compare(".MP4") == 0)
315  return FORMAT_MPEG4;
316  else if (ext.compare(".mp4") == 0)
317  return FORMAT_MPEG4;
318  else if (ext.compare(".MOV") == 0)
319  return FORMAT_MOV;
320  else if (ext.compare(".mov") == 0)
321  return FORMAT_MOV;
322  else
323  return FORMAT_UNKNOWN;
324 }
325 
326 // return the extension of the file including the dot
327 std::string vpVideoWriter::getExtension(const std::string &filename)
328 {
329  // extract the extension
330  size_t dot = filename.find_last_of(".");
331  std::string ext = filename.substr(dot, filename.size() - 1);
332  return ext;
333 }
334 
341 {
342  if (first_frame < 0) {
343  throw(vpException(vpException::fatalError, "Video writer first frame index cannot be negative"));
344  }
345  m_firstFrame = first_frame;
346 }
347 
348 END_VISP_NAMESPACE
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ badValue
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:73
@ notInitialized
Used to indicate that a parameter is not initialized.
Definition: vpException.h:74
@ fatalError
Fatal error.
Definition: vpException.h:72
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:291
unsigned int getWidth() const
Definition: vpImage.h:242
unsigned int getHeight() const
Definition: vpImage.h:181
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:550
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1314
void saveFrame(vpImage< vpRGBa > &I)
virtual ~vpVideoWriter()
void setFileName(const std::string &filename)
void open(vpImage< vpRGBa > &I)
void setFirstFrameIndex(int first_frame)