/* Video for WindowsによるAVIフレームの取得 2005/ 1/ 6 宍戸 輝光 */ #include #include /* BCCでコンパイルする場合は、以下の行をコメントアウトしてください */ #pragma comment(lib, "vfw32.lib") /* 読み込むAVIファイルのパス */ LPCTSTR lpszAviFilePath = "C:\\test.avi"; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL setAVIInfo(LPCTSTR); LPVOID loadFrame(LPCTSTR, int); HWND hwMain; int iAviWidth, iAviHeight, iAviFrames, iAviIndex; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { MSG msg; WNDCLASSEX wndclass; wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = NULL; wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "AVIFRAME"; wndclass.hIconSm = NULL; RegisterClassEx(&wndclass); AVIFileInit(); CreateWindow ("AVIFRAME", NULL, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 568, NULL, NULL, hInstance, NULL); ShowWindow(hwMain, iCmdShow); while (GetMessage(&msg, NULL, 0, 0)) { /* メッセージループ */ TranslateMessage(&msg); DispatchMessage(&msg); } AVIFileExit(); return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; static LPBYTE lpFrame; static LPBITMAPINFOHEADER lpbmiHead; static LPVOID lpPixels; switch (iMsg) { case WM_CREATE: hwMain = hwnd; /* Aviの情報取得 */ if (setAVIInfo(lpszAviFilePath)) { lpFrame = (LPBYTE)loadFrame(lpszAviFilePath, 0); lpbmiHead = (LPBITMAPINFOHEADER)lpFrame; lpPixels = lpFrame + lpbmiHead->biSize; } return 0; /* 右クリックで1フレーム進める */ case WM_RBUTTONDOWN: if (iAviIndex == iAviFrames - 1) { return 0; } if (lpFrame != NULL) { GlobalFree(lpFrame); } /* フレームデータ取得 */ lpFrame = (LPBYTE)loadFrame(lpszAviFilePath, iAviIndex + 1); if (lpFrame != NULL) { /* DIBのポインタ設定 */ lpbmiHead = (LPBITMAPINFOHEADER)lpFrame; lpPixels = lpFrame + lpbmiHead->biSize; iAviIndex++; InvalidateRgn(hwnd, NULL, FALSE); } return 0; /* 左クリックで1フレーム戻す */ case WM_LBUTTONDOWN: if (iAviIndex == 0) { return 0; } if (lpFrame != NULL) { GlobalFree(lpFrame); } /* フレームデータ取得 */ lpFrame = (LPBYTE)loadFrame(lpszAviFilePath, iAviIndex - 1); if (lpFrame != NULL) { /* DIBのポインタ設定 */ lpbmiHead = (LPBITMAPINFOHEADER)lpFrame; lpPixels = lpFrame + lpbmiHead->biSize; iAviIndex--; InvalidateRgn(hwnd, NULL, FALSE); } return 0; case WM_PAINT: hdc = BeginPaint(hwnd,&ps); if (lpFrame != NULL) { StretchDIBits(hdc, 0, 0, lpbmiHead->biWidth, lpbmiHead->biHeight, 0, 0, lpbmiHead->biWidth, lpbmiHead->biHeight, lpPixels, (LPBITMAPINFO)lpbmiHead, DIB_RGB_COLORS, SRCCOPY); } EndPaint(hwnd, &ps); return 0; case WM_DESTROY : /* 終了処理 */ if (lpFrame != NULL) { GlobalFree(lpFrame); } PostQuitMessage(0); return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; } /* AVIの情報(サイズ/フレーム数)設定 */ BOOL setAVIInfo(LPCTSTR lpszAviFilePath) { PAVIFILE pfAvi; AVIFILEINFO afAvi; /* AVIファイルを開く */ if (AVIFileOpen(&pfAvi, lpszAviFilePath, OF_READ, NULL) != 0) { return FALSE; } /* AVIファイルの情報取得 */ AVIFileInfo(pfAvi, &afAvi, sizeof(AVIFILEINFO)); /* フレームのサイズ取得 */ iAviWidth = afAvi.dwWidth; iAviHeight = afAvi.dwHeight; /* 総フレーム数取得 */ iAviFrames = afAvi.dwLength; AVIFileRelease(pfAvi); return TRUE; } /* AVIファイルからフレームを読み込む */ LPVOID loadFrame(LPCTSTR lpszAviFilePath, int iIndex) { PAVIFILE pfAvi; PAVISTREAM psAvi; PGETFRAME pgfFrame; BITMAPINFOHEADER bmiFrame; char aszInfo[256]; LPVOID lpTmp, lpData; /* AVIファイルを開く */ if (AVIFileOpen(&pfAvi, lpszAviFilePath, OF_READ, NULL) != 0) { return NULL; } ZeroMemory(&bmiFrame, sizeof(BITMAPINFOHEADER)); /* 取得するDIBの形式設定 */ bmiFrame.biSize = sizeof(BITMAPINFOHEADER); bmiFrame.biPlanes = 1; bmiFrame.biBitCount = 24; bmiFrame.biWidth = iAviWidth; bmiFrame.biHeight = iAviHeight; /* AVIのビデオストリーム取得 */ AVIFileGetStream(pfAvi, &psAvi, streamtypeVIDEO, 0); pgfFrame = AVIStreamGetFrameOpen(psAvi, &bmiFrame); /* フレームiIndex取得 */ lpTmp = AVIStreamGetFrame(pgfFrame, iIndex); /* フレームデータ用バッファ確保 */ lpData = GlobalAlloc(GPTR, sizeof(BITMAPINFOHEADER) + iAviWidth * iAviHeight * 3); /* フレームデータをバッファにコピー */ CopyMemory(lpData, lpTmp, sizeof(BITMAPINFOHEADER) + iAviWidth * iAviHeight * 3); AVIStreamGetFrameClose(pgfFrame); /* ストリーム解放 */ AVIStreamRelease(psAvi); /* AVIファイル解放 */ AVIFileRelease(pfAvi); /* ウインドウのタイトルバーにフレーム情報を表示 */ wsprintf(aszInfo, "フレーム位置 %d/%d", iIndex + 1, iAviFrames); SetWindowText(hwMain, aszInfo); /* フレームのDIBメモリイメージを返す */ return lpData; }