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
42 // Author: Nils Hasler <hasler@mpi-inf.mpg.de>
43 //
44 // Max-Planck-Institut Informatik
45
46 //
47 // capture video from a sequence of images
48 // the filename when opening can either be a printf pattern such as
49 // video%04d.png or the first frame of the sequence i.e. video0001.png
50 //
51
52 #include "precomp.hpp"
53 #include <sys/stat.h>
54
55 #ifdef NDEBUG
56 #define CV_WARN(message)
57 #else
58 #define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
59 #endif
60
61 #ifndef _MAX_PATH
62 #define _MAX_PATH 1024
63 #endif
64
65 class CvCapture_Images : public CvCapture
66 {
67 public:
CvCapture_Images()68 CvCapture_Images()
69 {
70 filename = 0;
71 currentframe = firstframe = 0;
72 length = 0;
73 frame = 0;
74 }
75
~CvCapture_Images()76 virtual ~CvCapture_Images()
77 {
78 close();
79 }
80
81 virtual bool open(const char* _filename);
82 virtual void close();
83 virtual double getProperty(int) const;
84 virtual bool setProperty(int, double);
85 virtual bool grabFrame();
86 virtual IplImage* retrieveFrame(int);
87
88 protected:
89 char* filename; // actually a printf-pattern
90 unsigned currentframe;
91 unsigned firstframe; // number of first frame
92 unsigned length; // length of sequence
93
94 IplImage* frame;
95 };
96
97
close()98 void CvCapture_Images::close()
99 {
100 if( filename )
101 {
102 free(filename);
103 filename = 0;
104 }
105 currentframe = firstframe = 0;
106 length = 0;
107 cvReleaseImage( &frame );
108 }
109
110
grabFrame()111 bool CvCapture_Images::grabFrame()
112 {
113 char str[_MAX_PATH];
114 sprintf(str, filename, firstframe + currentframe);
115
116 cvReleaseImage(&frame);
117 frame = cvLoadImage(str, CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
118 if( frame )
119 currentframe++;
120
121 return frame != 0;
122 }
123
retrieveFrame(int)124 IplImage* CvCapture_Images::retrieveFrame(int)
125 {
126 return frame;
127 }
128
getProperty(int id) const129 double CvCapture_Images::getProperty(int id) const
130 {
131 switch(id)
132 {
133 case CV_CAP_PROP_POS_MSEC:
134 CV_WARN("collections of images don't have framerates\n");
135 return 0;
136 case CV_CAP_PROP_POS_FRAMES:
137 return currentframe;
138 case CV_CAP_PROP_FRAME_COUNT:
139 return length;
140 case CV_CAP_PROP_POS_AVI_RATIO:
141 return (double)currentframe / (double)(length - 1);
142 case CV_CAP_PROP_FRAME_WIDTH:
143 return frame ? frame->width : 0;
144 case CV_CAP_PROP_FRAME_HEIGHT:
145 return frame ? frame->height : 0;
146 case CV_CAP_PROP_FPS:
147 CV_WARN("collections of images don't have framerates\n");
148 return 1;
149 case CV_CAP_PROP_FOURCC:
150 CV_WARN("collections of images don't have 4-character codes\n");
151 return 0;
152 }
153 return 0;
154 }
155
setProperty(int id,double value)156 bool CvCapture_Images::setProperty(int id, double value)
157 {
158 switch(id)
159 {
160 case CV_CAP_PROP_POS_MSEC:
161 case CV_CAP_PROP_POS_FRAMES:
162 if(value < 0) {
163 CV_WARN("seeking to negative positions does not work - clamping\n");
164 value = 0;
165 }
166 if(value >= length) {
167 CV_WARN("seeking beyond end of sequence - clamping\n");
168 value = length - 1;
169 }
170 currentframe = cvRound(value);
171 return true;
172 case CV_CAP_PROP_POS_AVI_RATIO:
173 if(value > 1) {
174 CV_WARN("seeking beyond end of sequence - clamping\n");
175 value = 1;
176 } else if(value < 0) {
177 CV_WARN("seeking to negative positions does not work - clamping\n");
178 value = 0;
179 }
180 currentframe = cvRound((length - 1) * value);
181 return true;
182 }
183 CV_WARN("unknown/unhandled property\n");
184 return false;
185 }
186
icvExtractPattern(const char * filename,unsigned * offset)187 static char* icvExtractPattern(const char *filename, unsigned *offset)
188 {
189 char *name = (char *)filename;
190
191 if( !filename )
192 return 0;
193
194 // check whether this is a valid image sequence filename
195 char *at = strchr(name, '%');
196 if(at)
197 {
198 int dummy;
199 if(sscanf(at + 1, "%ud", &dummy) != 1)
200 return 0;
201 name = strdup(filename);
202 }
203 else // no pattern filename was given - extract the pattern
204 {
205 at = name;
206
207 // ignore directory names
208 char *slash = strrchr(at, '/');
209 if (slash) at = slash + 1;
210
211 #ifdef _WIN32
212 slash = strrchr(at, '\\');
213 if (slash) at = slash + 1;
214 #endif
215
216 while (*at && !isdigit(*at)) at++;
217
218 if(!*at)
219 return 0;
220
221 sscanf(at, "%u", offset);
222
223 int size = (int)strlen(filename) + 20;
224 name = (char *)malloc(size);
225 strncpy(name, filename, at - filename);
226 name[at - filename] = 0;
227
228 strcat(name, "%0");
229
230 int i;
231 char *extension;
232 for(i = 0, extension = at; isdigit(at[i]); i++, extension++)
233 ;
234 char places[10];
235 sprintf(places, "%dd", i);
236
237 strcat(name, places);
238 strcat(name, extension);
239 }
240
241 return name;
242 }
243
244
open(const char * _filename)245 bool CvCapture_Images::open(const char * _filename)
246 {
247 unsigned offset = 0;
248 close();
249
250 filename = icvExtractPattern(_filename, &offset);
251 if(!filename)
252 return false;
253
254 // determine the length of the sequence
255 length = 0;
256 char str[_MAX_PATH];
257 for(;;)
258 {
259 sprintf(str, filename, offset + length);
260 struct stat s;
261 if(stat(str, &s))
262 {
263 if(length == 0 && offset == 0) // allow starting with 0 or 1
264 {
265 offset++;
266 continue;
267 }
268 }
269
270 if(!cvHaveImageReader(str))
271 break;
272
273 length++;
274 }
275
276 if(length == 0)
277 {
278 close();
279 return false;
280 }
281
282 firstframe = offset;
283 return true;
284 }
285
286
cvCreateFileCapture_Images(const char * filename)287 CvCapture* cvCreateFileCapture_Images(const char * filename)
288 {
289 CvCapture_Images* capture = new CvCapture_Images;
290
291 if( capture->open(filename) )
292 return capture;
293
294 delete capture;
295 return 0;
296 }
297
298 //
299 //
300 // image sequence writer
301 //
302 //
303 class CvVideoWriter_Images : public CvVideoWriter
304 {
305 public:
CvVideoWriter_Images()306 CvVideoWriter_Images()
307 {
308 filename = 0;
309 currentframe = 0;
310 }
~CvVideoWriter_Images()311 virtual ~CvVideoWriter_Images() { close(); }
312
313 virtual bool open( const char* _filename );
314 virtual void close();
315 virtual bool writeFrame( const IplImage* );
316
317 protected:
318 char* filename;
319 unsigned currentframe;
320 };
321
writeFrame(const IplImage * image)322 bool CvVideoWriter_Images::writeFrame( const IplImage* image )
323 {
324 char str[_MAX_PATH];
325 sprintf(str, filename, currentframe);
326 int ret = cvSaveImage(str, image);
327
328 currentframe++;
329
330 return ret > 0;
331 }
332
close()333 void CvVideoWriter_Images::close()
334 {
335 if( filename )
336 {
337 free( filename );
338 filename = 0;
339 }
340 currentframe = 0;
341 }
342
343
open(const char * _filename)344 bool CvVideoWriter_Images::open( const char* _filename )
345 {
346 unsigned offset = 0;
347
348 close();
349
350 filename = icvExtractPattern(_filename, &offset);
351 if(!filename)
352 return false;
353
354 char str[_MAX_PATH];
355 sprintf(str, filename, 0);
356 if(!cvHaveImageWriter(str))
357 {
358 close();
359 return false;
360 }
361
362 currentframe = offset;
363 return true;
364 }
365
366
cvCreateVideoWriter_Images(const char * filename)367 CvVideoWriter* cvCreateVideoWriter_Images( const char* filename )
368 {
369 CvVideoWriter_Images *writer = new CvVideoWriter_Images;
370
371 if( writer->open( filename ))
372 return writer;
373
374 delete writer;
375 return 0;
376 }
377