今回は、C++でAVIファイルを作成してみました。AVIファイルを作成するには次の手順が必要です。
- ストリーム作成
- サンプル書き込み
これが主なAVIファイル作成の手順です。
では、早速やってみたいと思います。
#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作成とかでググってみて下さい。
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ファイルの作成だけではなく、デスクトップを簡単にレコード出来る機能も実装しようと思っていたのですが、仕事が忙しく途中で諦めました(笑)、また、時間があればこの続きをやってみようと思います。それでは!