--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// Intel License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2008, Nils Hasler, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of Intel Corporation may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+// Author: Nils Hasler <hasler@mpi-inf.mpg.de>
+//
+// Max-Planck-Institut Informatik
+
+//
+// capture video from a sequence of images
+// the filename when opening can either be a printf pattern such as
+// video%04d.png or the first frame of the sequence i.e. video0001.png
+//
+
+#include "_highgui.h"
+#include <sys/stat.h>
+
+#ifdef NDEBUG
+#define CV_WARN(message)
+#else
+#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
+#endif
+
+#ifndef _MAX_PATH
+#define _MAX_PATH 1024
+#endif
+
+class CvCapture_Images : public CvCapture
+{
+public:
+ CvCapture_Images()
+ {
+ filename = 0;
+ currentframe = firstframe = 0;
+ length = 0;
+ frame = 0;
+ }
+
+ virtual ~CvCapture_Images()
+ {
+ close();
+ }
+
+ virtual bool open(const char* _filename);
+ virtual void close();
+ virtual double getProperty(int);
+ virtual bool setProperty(int, double);
+ virtual bool grabFrame();
+ virtual IplImage* retrieveFrame(int);
+
+protected:
+ char* filename; // actually a printf-pattern
+ unsigned currentframe;
+ unsigned firstframe; // number of first frame
+ unsigned length; // length of sequence
+
+ IplImage* frame;
+};
+
+
+void CvCapture_Images::close()
+{
+ if( filename )
+ {
+ free(filename);
+ filename = 0;
+ }
+ currentframe = firstframe = 0;
+ length = 0;
+ cvReleaseImage( &frame );
+}
+
+
+bool CvCapture_Images::grabFrame()
+{
+ char str[_MAX_PATH];
+ sprintf(str, filename, firstframe + currentframe);
+
+ cvReleaseImage(&frame);
+ frame = cvLoadImage(str, CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
+ if( frame )
+ currentframe++;
+
+ return frame != 0;
+}
+
+IplImage* CvCapture_Images::retrieveFrame(int)
+{
+ return frame;
+}
+
+double CvCapture_Images::getProperty(int id)
+{
+ switch(id)
+ {
+ case CV_CAP_PROP_POS_MSEC:
+ CV_WARN("collections of images don't have framerates\n");
+ return 0;
+ case CV_CAP_PROP_POS_FRAMES:
+ return currentframe;
+ case CV_CAP_PROP_POS_AVI_RATIO:
+ return (double)currentframe / (double)(length - 1);
+ case CV_CAP_PROP_FRAME_WIDTH:
+ return frame ? frame->width : 0;
+ case CV_CAP_PROP_FRAME_HEIGHT:
+ return frame ? frame->height : 0;
+ case CV_CAP_PROP_FPS:
+ CV_WARN("collections of images don't have framerates\n");
+ return 1;
+ case CV_CAP_PROP_FOURCC:
+ CV_WARN("collections of images don't have 4-character codes\n");
+ return 0;
+ }
+ return 0;
+}
+
+bool CvCapture_Images::setProperty(int id, double value)
+{
+ switch(id)
+ {
+ case CV_CAP_PROP_POS_MSEC:
+ case CV_CAP_PROP_POS_FRAMES:
+ if(value < 0) {
+ CV_WARN("seeking to negative positions does not work - clamping\n");
+ value = 0;
+ }
+ if(value >= length) {
+ CV_WARN("seeking beyond end of sequence - clamping\n");
+ value = length - 1;
+ }
+ currentframe = cvRound(value);
+ return true;
+ case CV_CAP_PROP_POS_AVI_RATIO:
+ if(value > 1) {
+ CV_WARN("seeking beyond end of sequence - clamping\n");
+ value = 1;
+ } else if(value < 0) {
+ CV_WARN("seeking to negative positions does not work - clamping\n");
+ value = 0;
+ }
+ currentframe = cvRound((length - 1) * value);
+ return true;
+ }
+ CV_WARN("unknown/unhandled property\n");
+ return false;
+}
+
+static char* icvExtractPattern(const char *filename, unsigned *offset)
+{
+ char *name = (char *)filename;
+
+ if( !filename )
+ return 0;
+
+ // check whether this is a valid image sequence filename
+ char *at = strchr(name, '%');
+ if(at)
+ {
+ int dummy;
+ if(sscanf(at + 1, "%ud", &dummy) != 1)
+ return 0;
+ name = strdup(filename);
+ }
+ else // no pattern filename was given - extract the pattern
+ {
+ for(at = name; *at && !isdigit(*at); at++)
+ ;
+
+ if(!at)
+ return 0;
+
+ sscanf(at, "%u", offset);
+
+ int size = (int)strlen(filename) + 20;
+ name = (char *)malloc(size);
+ strncpy(name, filename, at - filename);
+ name[at - filename] = 0;
+
+ strcat(name, "%0");
+
+ int i;
+ char *extension;
+ for(i = 0, extension = at; isdigit(at[i]); i++, extension++)
+ ;
+ char places[10];
+ sprintf(places, "%dd", i);
+
+ strcat(name, places);
+ strcat(name, extension);
+ }
+
+ return name;
+}
+
+
+bool CvCapture_Images::open(const char * _filename)
+{
+ unsigned offset = 0;
+ close();
+
+ filename = icvExtractPattern(_filename, &offset);
+ if(!filename)
+ return false;
+
+ // determine the length of the sequence
+ length = 0;
+ char str[_MAX_PATH];
+ for(;;)
+ {
+ sprintf(str, filename, offset + length);
+ struct stat s;
+ if(stat(str, &s))
+ {
+ if(length == 0 && offset == 0) // allow starting with 0 or 1
+ {
+ offset++;
+ continue;
+ }
+ }
+
+ if(!cvHaveImageReader(str))
+ break;
+
+ length++;
+ }
+
+ if(length == 0)
+ {
+ close();
+ return false;
+ }
+
+ firstframe = offset;
+ return true;
+}
+
+
+CvCapture* cvCreateFileCapture_Images(const char * filename)
+{
+ CvCapture_Images* capture = new CvCapture_Images;
+
+ if( capture->open(filename) )
+ return capture;
+
+ delete capture;
+ return 0;
+}
+
+//
+//
+// image sequence writer
+//
+//
+class CvVideoWriter_Images : public CvVideoWriter
+{
+public:
+ CvVideoWriter_Images()
+ {
+ filename = 0;
+ currentframe = 0;
+ }
+ virtual ~CvVideoWriter_Images() { close(); }
+
+ virtual bool open( const char* _filename );
+ virtual void close();
+ virtual bool writeFrame( const IplImage* );
+
+protected:
+ char* filename;
+ unsigned currentframe;
+};
+
+bool CvVideoWriter_Images::writeFrame( const IplImage* image )
+{
+ char str[_MAX_PATH];
+ sprintf(str, filename, currentframe);
+ int ret = cvSaveImage(str, image);
+
+ currentframe++;
+
+ return ret > 0;
+}
+
+void CvVideoWriter_Images::close()
+{
+ if( filename )
+ {
+ free( filename );
+ filename = 0;
+ }
+ currentframe = 0;
+}
+
+
+bool CvVideoWriter_Images::open( const char* _filename )
+{
+ unsigned offset = 0;
+
+ close();
+
+ filename = icvExtractPattern(_filename, &offset);
+ if(!filename)
+ return false;
+
+ char str[_MAX_PATH];
+ sprintf(str, filename, 0);
+ if(!cvHaveImageWriter(str))
+ {
+ close();
+ return false;
+ }
+
+ currentframe = offset;
+ return true;
+}
+
+
+CvVideoWriter* cvCreateVideoWriter_Images( const char* filename )
+{
+ CvVideoWriter_Images *writer = new CvVideoWriter_Images;
+
+ if( writer->open( filename ))
+ return writer;
+
+ delete writer;
+ return 0;
+}