AVI ファイルを画像に分解するプログラム

名前は avi2png だけど,出力は PNG に限らない.OpenCV が対応している形式ならなんとかなる.

#include "opencv/highgui.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#pragma comment(lib, "cv120.lib")
#pragma comment(lib, "cxcore120.lib")
#pragma comment(lib, "highgui120.lib")

#define STRING_MARGIN (10) // malloc() するときの余裕
#define FILE_UNIT (1000) // フォルダ当たりのファイル数

int frame_count = 0;

void printVar(int argc, char **argv)
{
	printf("入力映像       : \n  %s\n", argv[1]);
	printf("出力先         : \n  %s\n", argv[2]);
	printf("ファイル拡張子 : \n  %s\n", argv[3]);
}

void printUsage(void)
{
	puts("==========================================================");
	puts("              avi2png.exe             Usage               ");
	puts("==========================================================");
	puts("  AVI ファイルを静止画像に分解します.");
	puts("  1,000 個を超える場合,1,000 単位に別フォルダに分けます.");
	puts("  100,000 個を超える場合,100,000 で処理を終了します.");
	puts("--------------------------------------------------------");
	puts("  avi2png.exe <in-filename> <out-directory> <out-type>");
	puts("    in-filename   : ");
	puts("      画像に分解したい映像ファイル.AVI 形式.");
	puts("    out-directory : ");
	puts("      静止画像を保存するディレクトリ.");
	puts("      存在しないとき mkdir を試行.");
	puts("    out-type      : ");
	puts("      画像ファイル形式.png | bmp | jpg");
}

void printVideoInfo(CvCapture *cap)
{
	printf("入力映像情報\n");
	printf("FRAME_WIDTH    : \n");
	printf("  %lf\n", cvGetCaptureProperty( cap, CV_CAP_PROP_FRAME_WIDTH ));
	printf("FRAME_HEIGHT   : \n");
	printf("  %lf\n", cvGetCaptureProperty( cap, CV_CAP_PROP_FRAME_HEIGHT ));
	printf("FPS            : \n");
	printf("  %lf\n", cvGetCaptureProperty( cap, CV_CAP_PROP_FPS ));
	printf("FOURCC         : \n");
	printf("  %lf\n", cvGetCaptureProperty( cap, CV_CAP_PROP_FOURCC ));
	printf("FRAME_COUNT    : \n");
	printf("  %d\n", 
		frame_count = (int) cvGetCaptureProperty( cap, CV_CAP_PROP_FRAME_COUNT ));
}

int mkdir(const char *directory_name)
{
	char *buf = (char *) malloc( strlen( directory_name ) + STRING_MARGIN );
	sprintf(buf, "mkdir %s", directory_name);
	printf("mkdir 実行     : \n  %s\n", directory_name );
	return system(buf);
}

void saveImages(CvCapture *cap,
				const char *out_directory,
				const char *ext,
				int loop_counter = 0)
{
	IplImage *img;
	char *buf = (char *)malloc( strlen( out_directory ) + STRING_MARGIN );
	for ( int i = 0; i < FILE_UNIT; i++)
	{
		img = cvQueryFrame( cap );
		if ( img == NULL )
		{
			break;
		}
		sprintf( buf, "%s\\%d.%s",
			out_directory,
			loop_counter * FILE_UNIT + i,
			ext);
		cvSaveImage( buf, img );
	}
}

int main(int argc, char **argv)
{
	CvCapture *cap;

	if ( argc < 4 )
	{
		printUsage();
		return 0;
	}

	printVar(argc, argv);

	cap  = cvCaptureFromAVI( argv[1] );
	if( cap == NULL )
	{
		puts("入力映像を読み込めません.");
		return 0;
	}
	printVideoInfo(cap);
	
	if ( frame_count < FILE_UNIT )
	{
		saveImages( cap, argv[2], argv[3] );
	}else{
		char *out_directory = (char *)malloc( strlen(argv[2]) + STRING_MARGIN );
		for ( int i = 0; i <= frame_count / FILE_UNIT; i++ )
		{
			sprintf(out_directory, "%s\\%d-%d",
				argv[2],
				i * FILE_UNIT,
				i * FILE_UNIT + FILE_UNIT);
			mkdir( out_directory );
			saveImages( cap, out_directory, argv[3], i );
		}
	}
	
	cvReleaseCapture( &cap );

	return 0;
}