PageRenderTime 95ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/videoio/src/cap_images.cpp

https://gitlab.com/generic-library/opencv
C++ | 396 lines | 274 code | 65 blank | 57 comment | 40 complexity | 0f2b68bb16930d78461d3898b907f62a MD5 | raw file
  1. /*M///////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
  4. //
  5. // By downloading, copying, installing or using the software you agree to this license.
  6. // If you do not agree to this license, do not download, install,
  7. // copy or use the software.
  8. //
  9. //
  10. // Intel License Agreement
  11. // For Open Source Computer Vision Library
  12. //
  13. // Copyright (C) 2008, Nils Hasler, all rights reserved.
  14. // Third party copyrights are property of their respective owners.
  15. //
  16. // Redistribution and use in source and binary forms, with or without modification,
  17. // are permitted provided that the following conditions are met:
  18. //
  19. // * Redistribution's of source code must retain the above copyright notice,
  20. // this list of conditions and the following disclaimer.
  21. //
  22. // * Redistribution's in binary form must reproduce the above copyright notice,
  23. // this list of conditions and the following disclaimer in the documentation
  24. // and/or other materials provided with the distribution.
  25. //
  26. // * The name of Intel Corporation may not be used to endorse or promote products
  27. // derived from this software without specific prior written permission.
  28. //
  29. // This software is provided by the copyright holders and contributors "as is" and
  30. // any express or implied warranties, including, but not limited to, the implied
  31. // warranties of merchantability and fitness for a particular purpose are disclaimed.
  32. // In no event shall the Intel Corporation or contributors be liable for any direct,
  33. // indirect, incidental, special, exemplary, or consequential damages
  34. // (including, but not limited to, procurement of substitute goods or services;
  35. // loss of use, data, or profits; or business interruption) however caused
  36. // and on any theory of liability, whether in contract, strict liability,
  37. // or tort (including negligence or otherwise) arising in any way out of
  38. // the use of this software, even if advised of the possibility of such damage.
  39. //
  40. //M*/
  41. // Author: Nils Hasler <hasler@mpi-inf.mpg.de>
  42. //
  43. // Max-Planck-Institut Informatik
  44. //
  45. // capture video from a sequence of images
  46. // the filename when opening can either be a printf pattern such as
  47. // video%04d.png or the first frame of the sequence i.e. video0001.png
  48. //
  49. #include "precomp.hpp"
  50. #include <sys/stat.h>
  51. #ifdef NDEBUG
  52. #define CV_WARN(message)
  53. #else
  54. #define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
  55. #endif
  56. #ifndef _MAX_PATH
  57. #define _MAX_PATH 1024
  58. #endif
  59. class CvCapture_Images : public CvCapture
  60. {
  61. public:
  62. CvCapture_Images()
  63. {
  64. filename = NULL;
  65. currentframe = firstframe = 0;
  66. length = 0;
  67. frame = NULL;
  68. grabbedInOpen = false;
  69. }
  70. virtual ~CvCapture_Images()
  71. {
  72. close();
  73. }
  74. virtual bool open(const char* _filename);
  75. virtual void close();
  76. virtual double getProperty(int) const;
  77. virtual bool setProperty(int, double);
  78. virtual bool grabFrame();
  79. virtual IplImage* retrieveFrame(int);
  80. protected:
  81. char* filename; // actually a printf-pattern
  82. unsigned currentframe;
  83. unsigned firstframe; // number of first frame
  84. unsigned length; // length of sequence
  85. IplImage* frame;
  86. bool grabbedInOpen;
  87. };
  88. void CvCapture_Images::close()
  89. {
  90. if( filename )
  91. {
  92. free(filename);
  93. filename = NULL;
  94. }
  95. currentframe = firstframe = 0;
  96. length = 0;
  97. cvReleaseImage( &frame );
  98. }
  99. bool CvCapture_Images::grabFrame()
  100. {
  101. char str[_MAX_PATH];
  102. sprintf(str, filename, firstframe + currentframe);
  103. if (grabbedInOpen)
  104. {
  105. grabbedInOpen = false;
  106. ++currentframe;
  107. return frame != NULL;
  108. }
  109. cvReleaseImage(&frame);
  110. frame = cvLoadImage(str, CV_LOAD_IMAGE_UNCHANGED);
  111. if( frame )
  112. currentframe++;
  113. return frame != NULL;
  114. }
  115. IplImage* CvCapture_Images::retrieveFrame(int)
  116. {
  117. return grabbedInOpen ? NULL : frame;
  118. }
  119. double CvCapture_Images::getProperty(int id) const
  120. {
  121. switch(id)
  122. {
  123. case CV_CAP_PROP_POS_MSEC:
  124. CV_WARN("collections of images don't have framerates\n");
  125. return 0;
  126. case CV_CAP_PROP_POS_FRAMES:
  127. return currentframe;
  128. case CV_CAP_PROP_FRAME_COUNT:
  129. return length;
  130. case CV_CAP_PROP_POS_AVI_RATIO:
  131. return (double)currentframe / (double)(length - 1);
  132. case CV_CAP_PROP_FRAME_WIDTH:
  133. return frame ? frame->width : 0;
  134. case CV_CAP_PROP_FRAME_HEIGHT:
  135. return frame ? frame->height : 0;
  136. case CV_CAP_PROP_FPS:
  137. CV_WARN("collections of images don't have framerates\n");
  138. return 1;
  139. case CV_CAP_PROP_FOURCC:
  140. CV_WARN("collections of images don't have 4-character codes\n");
  141. return 0;
  142. }
  143. return 0;
  144. }
  145. bool CvCapture_Images::setProperty(int id, double value)
  146. {
  147. switch(id)
  148. {
  149. case CV_CAP_PROP_POS_MSEC:
  150. case CV_CAP_PROP_POS_FRAMES:
  151. if(value < 0) {
  152. CV_WARN("seeking to negative positions does not work - clamping\n");
  153. value = 0;
  154. }
  155. if(value >= length) {
  156. CV_WARN("seeking beyond end of sequence - clamping\n");
  157. value = length - 1;
  158. }
  159. currentframe = cvRound(value);
  160. if (currentframe != 0)
  161. grabbedInOpen = false; // grabbed frame is not valid anymore
  162. return true;
  163. case CV_CAP_PROP_POS_AVI_RATIO:
  164. if(value > 1) {
  165. CV_WARN("seeking beyond end of sequence - clamping\n");
  166. value = 1;
  167. } else if(value < 0) {
  168. CV_WARN("seeking to negative positions does not work - clamping\n");
  169. value = 0;
  170. }
  171. currentframe = cvRound((length - 1) * value);
  172. if (currentframe != 0)
  173. grabbedInOpen = false; // grabbed frame is not valid anymore
  174. return true;
  175. }
  176. CV_WARN("unknown/unhandled property\n");
  177. return false;
  178. }
  179. static char* icvExtractPattern(const char *filename, unsigned *offset)
  180. {
  181. char *name = (char *)filename;
  182. if( !filename )
  183. return 0;
  184. // check whether this is a valid image sequence filename
  185. char *at = strchr(name, '%');
  186. if(at)
  187. {
  188. int dummy;
  189. if(sscanf(at + 1, "%ud", &dummy) != 1)
  190. return 0;
  191. name = strdup(filename);
  192. }
  193. else // no pattern filename was given - extract the pattern
  194. {
  195. at = name;
  196. // ignore directory names
  197. char *slash = strrchr(at, '/');
  198. if (slash) at = slash + 1;
  199. #ifdef _WIN32
  200. slash = strrchr(at, '\\');
  201. if (slash) at = slash + 1;
  202. #endif
  203. while (*at && !isdigit(*at)) at++;
  204. if(!*at)
  205. return 0;
  206. sscanf(at, "%u", offset);
  207. int size = (int)strlen(filename) + 20;
  208. name = (char *)malloc(size);
  209. strncpy(name, filename, at - filename);
  210. name[at - filename] = 0;
  211. strcat(name, "%0");
  212. int i;
  213. char *extension;
  214. for(i = 0, extension = at; isdigit(at[i]); i++, extension++)
  215. ;
  216. char places[10];
  217. sprintf(places, "%dd", i);
  218. strcat(name, places);
  219. strcat(name, extension);
  220. }
  221. return name;
  222. }
  223. bool CvCapture_Images::open(const char * _filename)
  224. {
  225. unsigned offset = 0;
  226. close();
  227. filename = icvExtractPattern(_filename, &offset);
  228. if(!filename)
  229. return false;
  230. // determine the length of the sequence
  231. length = 0;
  232. char str[_MAX_PATH];
  233. for(;;)
  234. {
  235. sprintf(str, filename, offset + length);
  236. struct stat s;
  237. if(stat(str, &s))
  238. {
  239. if(length == 0 && offset == 0) // allow starting with 0 or 1
  240. {
  241. offset++;
  242. continue;
  243. }
  244. }
  245. if(!cvHaveImageReader(str))
  246. break;
  247. length++;
  248. }
  249. if(length == 0)
  250. {
  251. close();
  252. return false;
  253. }
  254. firstframe = offset;
  255. // grab frame to enable properties retrieval
  256. bool grabRes = grabFrame();
  257. grabbedInOpen = true;
  258. currentframe = 0;
  259. return grabRes;
  260. }
  261. CvCapture* cvCreateFileCapture_Images(const char * filename)
  262. {
  263. CvCapture_Images* capture = new CvCapture_Images;
  264. if( capture->open(filename) )
  265. return capture;
  266. delete capture;
  267. return NULL;
  268. }
  269. //
  270. //
  271. // image sequence writer
  272. //
  273. //
  274. class CvVideoWriter_Images : public CvVideoWriter
  275. {
  276. public:
  277. CvVideoWriter_Images()
  278. {
  279. filename = 0;
  280. currentframe = 0;
  281. }
  282. virtual ~CvVideoWriter_Images() { close(); }
  283. virtual bool open( const char* _filename );
  284. virtual void close();
  285. virtual bool writeFrame( const IplImage* );
  286. protected:
  287. char* filename;
  288. unsigned currentframe;
  289. };
  290. bool CvVideoWriter_Images::writeFrame( const IplImage* image )
  291. {
  292. char str[_MAX_PATH];
  293. sprintf(str, filename, currentframe);
  294. int ret = cvSaveImage(str, image);
  295. currentframe++;
  296. return ret > 0;
  297. }
  298. void CvVideoWriter_Images::close()
  299. {
  300. if( filename )
  301. {
  302. free( filename );
  303. filename = 0;
  304. }
  305. currentframe = 0;
  306. }
  307. bool CvVideoWriter_Images::open( const char* _filename )
  308. {
  309. unsigned offset = 0;
  310. close();
  311. filename = icvExtractPattern(_filename, &offset);
  312. if(!filename)
  313. return false;
  314. char str[_MAX_PATH];
  315. sprintf(str, filename, 0);
  316. if(!cvHaveImageWriter(str))
  317. {
  318. close();
  319. return false;
  320. }
  321. currentframe = offset;
  322. return true;
  323. }
  324. CvVideoWriter* cvCreateVideoWriter_Images( const char* filename )
  325. {
  326. CvVideoWriter_Images *writer = new CvVideoWriter_Images;
  327. if( writer->open( filename ))
  328. return writer;
  329. delete writer;
  330. return 0;
  331. }