5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++でAVIファイル作成してみた

Posted at

今回は、C++でAVIファイルを作成してみました。AVIファイルを作成するには次の手順が必要です。

  1. ストリーム作成
  2. サンプル書き込み
    これが主なAVIファイル作成の手順です。

では、早速やってみたいと思います。

CreateAVI.cpp

#include "stdafx.h"
#include "Win32Project11.h"
#include <windows.h>
#include <vfw.h>
#include <string>
#include <iostream>
#include <stdlib.h>
#include <tchar.h>

#pragma comment (lib, "winmm.lib")
#pragma comment (lib, "vfw32.lib")

#define ID_START 100
#define ID_END 200
#define LENG 1000
#define PIXELS 10
#define WIDTH 160
#define HEIGHT 120
#define LINE ((((WIDTH)*24+31)&~31)/8)
#define SIZEIMAGE (LINE*(HEIGHT))
#define PI 3.1415926535

using namespace std;
HINSTANCE hInst;


LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	TCHAR szWindowClass[] = TEXT("Test");
	
	MSG msg;
	WNDCLASSEX wc;
	HWND hwnd;

	wc.cbClsExtra = 0;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)(COLOR_DESKTOP + 1);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hIcon = NULL;
	wc.hIconSm = NULL;
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = szWindowClass;
	wc.lpszMenuName = NULL;
	wc.style = 0;

	if (!RegisterClassEx(&wc))
	{
		MessageBox(NULL, TEXT("処理に失敗しました!"), NULL, NULL);
	}

	hInst = hInstance;
    hwnd = CreateWindowEx(0, szWindowClass, szWindowClass, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 500, NULL, NULL, hInstance, NULL);
	
	if (!hwnd)
	{
		MessageBox(NULL, TEXT("ウィンドウの作成に失敗しました!"), NULL, NULL);
	}

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	
	return 0;
} 

まずは、必要なヘッダーをインクルードして、WINAPI関数で、Windowを作成します。こちらはC++では基本のコードですので説明は省きます。気になる方はC++ Window作成とかでググってみて下さい。

CreateAVI.cpp

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){

	static HWND hwndButtonStart = NULL;
	static HWND hwndButtonStop = NULL;

	PAVISTREAM PAvistream;
	PAVIFILE PFaile;
    AVISTREAMINFO SInfo;
	BITMAPINFOHEADER BMi;
	BYTE BBit[SIZEIMAGE];
	int i;
	int j;
	int s;

	ZeroMemory(&SInfo, sizeof(AVISTREAMINFO));
	SInfo.fccType = streamtypeVIDEO;
	SInfo.fccHandler = comptypeDIB;
	SInfo.dwScale = 1;
	SInfo.dwRate = 2;
	SInfo.dwLength = 10;
	SInfo.dwQuality = (DWORD)-1;
	SetRect(&SInfo.rcFrame, 0, 0, 32, 32);

	ZeroMemory(&BMi, sizeof(BITMAPINFOHEADER));
	BMi.biSize = sizeof(BITMAPINFOHEADER);
	BMi.biWidth = 32;
	BMi.biHeight = 32;
	BMi.biPlanes = 1;
	BMi.biBitCount = 24;
	BMi.biCompression = BI_RGB;
	
	AVIFileInit();
	
	switch (message)
	{
	case WM_CREATE:
	hwndButtonStart = CreateWindowEx(0, TEXT("BUTTON"), TEXT("キャプチャON"), WS_CHILD | WS_VISIBLE, 10, 20, 130, 30, hwnd, (HMENU)ID_START, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
	hwndButtonStop = CreateWindowEx(0, TEXT("BUTTON"), TEXT("キャプチャOFF"), WS_CHILD | WS_VISIBLE, 10, 70, 130, 30, hwnd, (HMENU)ID_END, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
	break;

	case WM_COMMAND:
  
		if (LOWORD(wParam) == ID_START)
		{
			if (AVIFileOpen(&PFaile, TEXT("TEST.AVI"), OF_CREATE | OF_WRITE, NULL) != 0)
			{
				MessageBox(NULL, TEXT("AVIFILEを開けませんでした!"), NULL, NULL);
			}
			else {


				MessageBox(NULL, TEXT("AVIFILEを開けました!"), NULL, NULL);
			}

			if (AVIFileCreateStream(PFaile, &PAvistream, &SInfo) != 0) {
				MessageBox(NULL, TEXT("ストリームの作成に失敗しました!"), NULL, NULL);
			}
			else {
				MessageBox(NULL, TEXT("ストリームの作成に成功しました!"), NULL, NULL);
			}

			if (AVIStreamSetFormat(PAvistream, 0, &BMi, sizeof(BITMAPINFOHEADER)) != 0)
			{
				MessageBox(NULL, TEXT("ストリームのセットに失敗しました!"), NULL, NULL);
			}
			else {
				MessageBox(NULL, TEXT("ストリームのセットに成功しました!"), NULL, NULL);
			}

			for (i = 0; i < LENG; i++) {
				for (j = 0; j < PIXELS; j++) {
					s = (int)(cos(PI * 2 * j / PIXELS)*min(WIDTH, HEIGHT)*(i*PIXELS + j)
						/ (LENG*PIXELS * 2) + WIDTH / 2) * 3
						+ (int)(sin(PI * 2 * j / PIXELS)*min(WIDTH, HEIGHT)*(i*PIXELS + j)
							/ (LENG*PIXELS * 2) + HEIGHT / 2)*LINE;
					BBit[s] = BBit[s + 1] = BBit[s + 2] = 0xff;
				}

				if (AVIStreamWrite(PAvistream, i, 1, BBit, SIZEIMAGE, AVIIF_KEYFRAME, NULL, NULL) != 0) {
					MessageBox(NULL, TEXT("ストリームの書き込みに失敗しました!"), NULL, NULL);
				}
				else {
					MessageBox(NULL, TEXT("ストリームの書き込みに成功しました!"), NULL, NULL);
					AVIStreamRelease(PAvistream);
					AVIFileRelease(PFaile);
					AVIFileExit();
					return 0;
				}
			   }
			  }

if (LOWORD(wParam) == ID_END){
        MessageBox(NULL, TEXT("オフボタンは実装されていません!"), NULL, NULL);
}
        break;

	   default:
		 return DefWindowProc(hwnd, message, wParam, lParam);
		break;
	}

	return 0;
}

基本的な流れとしては、コールバック関数のWndProc関数に処理をガリガリと書いていく感じです。関数の最初に必要な変数等を書いておきます。次は、AVIFileOpen関数でサンプルを書き込む為のAVIファイルを作成します。次に、AVICreateStream関数で先程作成したAVIファイルと関連付けをしてそのファイルにストリームを出力します。AVICreateStream関数の第一引数で、先程作成したAVIファイルが指定出来ます。次にAVIStreamSetFormatでビットイメージをセットし、AVIStreamWriteで書き込んでいくという内容になります。

#まとめ
本当は、AVIファイルの作成だけではなく、デスクトップを簡単にレコード出来る機能も実装しようと思っていたのですが、仕事が忙しく途中で諦めました(笑)、また、時間があればこの続きをやってみようと思います。それでは!

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?