Path: blob/master/modules/videoio/src/cap_images.cpp
16354 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// Intel License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2008, Nils Hasler, all rights reserved.13// Third party copyrights are property of their respective owners.14//15// Redistribution and use in source and binary forms, with or without modification,16// are permitted provided that the following conditions are met:17//18// * Redistribution's of source code must retain the above copyright notice,19// this list of conditions and the following disclaimer.20//21// * Redistribution's in binary form must reproduce the above copyright notice,22// this list of conditions and the following disclaimer in the documentation23// and/or other materials provided with the distribution.24//25// * The name of Intel Corporation may not be used to endorse or promote products26// derived from this software without specific prior written permission.27//28// This software is provided by the copyright holders and contributors "as is" and29// any express or implied warranties, including, but not limited to, the implied30// warranties of merchantability and fitness for a particular purpose are disclaimed.31// In no event shall the Intel Corporation or contributors be liable for any direct,32// indirect, incidental, special, exemplary, or consequential damages33// (including, but not limited to, procurement of substitute goods or services;34// loss of use, data, or profits; or business interruption) however caused35// and on any theory of liability, whether in contract, strict liability,36// or tort (including negligence or otherwise) arising in any way out of37// the use of this software, even if advised of the possibility of such damage.38//39//M*/4041// Author: Nils Hasler <[email protected]>42//43// Max-Planck-Institut Informatik4445//46// capture video from a sequence of images47// the filename when opening can either be a printf pattern such as48// video%04d.png or the first frame of the sequence i.e. video0001.png49//5051#include "precomp.hpp"52#include <sys/stat.h>5354#ifdef NDEBUG55#define CV_WARN(message)56#else57#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)58#endif5960#ifndef _MAX_PATH61#define _MAX_PATH 102462#endif6364class CvCapture_Images : public CvCapture65{66public:67CvCapture_Images()68{69filename = NULL;70currentframe = firstframe = 0;71length = 0;72frame = NULL;73grabbedInOpen = false;74}7576virtual ~CvCapture_Images() CV_OVERRIDE77{78close();79}8081virtual bool open(const char* _filename);82virtual void close();83virtual double getProperty(int) const CV_OVERRIDE;84virtual bool setProperty(int, double) CV_OVERRIDE;85virtual bool grabFrame() CV_OVERRIDE;86virtual IplImage* retrieveFrame(int) CV_OVERRIDE;8788int getCaptureDomain() /*const*/ CV_OVERRIDE { return cv::CAP_IMAGES; }89protected:90char* filename; // actually a printf-pattern91unsigned currentframe;92unsigned firstframe; // number of first frame93unsigned length; // length of sequence9495IplImage* frame;96bool grabbedInOpen;97};9899100void CvCapture_Images::close()101{102if( filename )103{104free(filename);105filename = NULL;106}107currentframe = firstframe = 0;108length = 0;109cvReleaseImage( &frame );110}111112113bool CvCapture_Images::grabFrame()114{115char str[_MAX_PATH];116sprintf(str, filename, firstframe + currentframe);117118if (grabbedInOpen)119{120grabbedInOpen = false;121++currentframe;122123return frame != NULL;124}125126cvReleaseImage(&frame);127frame = cvLoadImage(str, CV_LOAD_IMAGE_UNCHANGED);128if( frame )129currentframe++;130131return frame != NULL;132}133134IplImage* CvCapture_Images::retrieveFrame(int)135{136return grabbedInOpen ? NULL : frame;137}138139double CvCapture_Images::getProperty(int id) const140{141switch(id)142{143case CV_CAP_PROP_POS_MSEC:144CV_WARN("collections of images don't have framerates\n");145return 0;146case CV_CAP_PROP_POS_FRAMES:147return currentframe;148case CV_CAP_PROP_FRAME_COUNT:149return length;150case CV_CAP_PROP_POS_AVI_RATIO:151return (double)currentframe / (double)(length - 1);152case CV_CAP_PROP_FRAME_WIDTH:153return frame ? frame->width : 0;154case CV_CAP_PROP_FRAME_HEIGHT:155return frame ? frame->height : 0;156case CV_CAP_PROP_FPS:157CV_WARN("collections of images don't have framerates\n");158return 1;159case CV_CAP_PROP_FOURCC:160CV_WARN("collections of images don't have 4-character codes\n");161return 0;162}163return 0;164}165166bool CvCapture_Images::setProperty(int id, double value)167{168switch(id)169{170case CV_CAP_PROP_POS_MSEC:171case CV_CAP_PROP_POS_FRAMES:172if(value < 0) {173CV_WARN("seeking to negative positions does not work - clamping\n");174value = 0;175}176if(value >= length) {177CV_WARN("seeking beyond end of sequence - clamping\n");178value = length - 1;179}180currentframe = cvRound(value);181if (currentframe != 0)182grabbedInOpen = false; // grabbed frame is not valid anymore183return true;184case CV_CAP_PROP_POS_AVI_RATIO:185if(value > 1) {186CV_WARN("seeking beyond end of sequence - clamping\n");187value = 1;188} else if(value < 0) {189CV_WARN("seeking to negative positions does not work - clamping\n");190value = 0;191}192currentframe = cvRound((length - 1) * value);193if (currentframe != 0)194grabbedInOpen = false; // grabbed frame is not valid anymore195return true;196}197CV_WARN("unknown/unhandled property\n");198return false;199}200201static char* icvExtractPattern(const char *filename, unsigned *offset)202{203char *name = (char *)filename;204205if( !filename )206return 0;207208// check whether this is a valid image sequence filename209char *at = strchr(name, '%');210if(at)211{212unsigned int dummy;213if(sscanf(at + 1, "%ud", &dummy) != 1)214return 0;215name = strdup(filename);216}217else // no pattern filename was given - extract the pattern218{219at = name;220221// ignore directory names222char *slash = strrchr(at, '/');223if (slash) at = slash + 1;224225#ifdef _WIN32226slash = strrchr(at, '\\');227if (slash) at = slash + 1;228#endif229230while (*at && !isdigit(*at)) at++;231232if(!*at)233return 0;234235sscanf(at, "%u", offset);236237int size = (int)strlen(filename) + 20;238name = (char *)malloc(size);239CV_Assert(name != NULL);240strncpy(name, filename, at - filename);241name[at - filename] = 0;242243strcat(name, "%0");244245int i;246char *extension;247for(i = 0, extension = at; isdigit(at[i]); i++, extension++)248;249char places[13] = {0};250sprintf(places, "%dd", i);251252strcat(name, places);253strcat(name, extension);254}255256return name;257}258259260bool CvCapture_Images::open(const char * _filename)261{262unsigned offset = 0;263close();264265filename = icvExtractPattern(_filename, &offset);266if(!filename)267return false;268269// determine the length of the sequence270length = 0;271char str[_MAX_PATH];272for(;;)273{274sprintf(str, filename, offset + length);275struct stat s;276if(stat(str, &s))277{278if(length == 0 && offset == 0) // allow starting with 0 or 1279{280offset++;281continue;282}283}284285if(!cvHaveImageReader(str))286break;287288length++;289}290291if(length == 0)292{293close();294return false;295}296297firstframe = offset;298299// grab frame to enable properties retrieval300bool grabRes = grabFrame();301grabbedInOpen = true;302currentframe = 0;303304return grabRes;305}306307308CvCapture* cvCreateFileCapture_Images(const char * filename)309{310CvCapture_Images* capture = new CvCapture_Images;311312if( capture->open(filename) )313return capture;314315delete capture;316return NULL;317}318319//320//321// image sequence writer322//323//324class CvVideoWriter_Images CV_FINAL : public CvVideoWriter325{326public:327CvVideoWriter_Images()328{329filename = 0;330currentframe = 0;331}332virtual ~CvVideoWriter_Images() { close(); }333334virtual bool open( const char* _filename );335virtual void close();336virtual bool setProperty( int, double ); // FIXIT doesn't work: IVideoWriter interface only!337virtual bool writeFrame( const IplImage* ) CV_OVERRIDE;338339int getCaptureDomain() const CV_OVERRIDE { return cv::CAP_IMAGES; }340protected:341char* filename;342unsigned currentframe;343std::vector<int> params;344};345346bool CvVideoWriter_Images::writeFrame( const IplImage* image )347{348char str[_MAX_PATH];349sprintf(str, filename, currentframe);350std::vector<int> image_params = params;351image_params.push_back(0); // append parameters 'stop' mark352image_params.push_back(0);353int ret = cvSaveImage(str, image, &image_params[0]);354355currentframe++;356357return ret > 0;358}359360void CvVideoWriter_Images::close()361{362if( filename )363{364free( filename );365filename = 0;366}367currentframe = 0;368params.clear();369}370371372bool CvVideoWriter_Images::open( const char* _filename )373{374unsigned offset = 0;375376close();377378filename = icvExtractPattern(_filename, &offset);379if(!filename)380return false;381382char str[_MAX_PATH];383sprintf(str, filename, 0);384if(!cvHaveImageWriter(str))385{386close();387return false;388}389390currentframe = offset;391params.clear();392return true;393}394395396bool CvVideoWriter_Images::setProperty( int id, double value )397{398if (id >= cv::CAP_PROP_IMAGES_BASE && id < cv::CAP_PROP_IMAGES_LAST)399{400params.push_back( id - cv::CAP_PROP_IMAGES_BASE );401params.push_back( static_cast<int>( value ) );402return true;403}404return false; // not supported405}406407408CvVideoWriter* cvCreateVideoWriter_Images( const char* filename )409{410CvVideoWriter_Images *writer = new CvVideoWriter_Images;411412if( writer->open( filename ))413return writer;414415delete writer;416return 0;417}418419420