AVI (Audio Video Interleave) 是微軟定義的多媒體容器格式,屬於 RIFF 規範。典型 AVI 包含音訊串流與視訊串流,特殊情況下可能含控制軌或 MIDI 軌。雖然播放軟體眾多,但能從視訊串流擷取單一幀並存為 BMP 的工具較少。
操作 AVI 必須成對呼叫:
AVIFileInit() - 程式啟動時初始化 AVI 函式庫AVIFileExit() - 程式結束時釋放資源若未正確初始化,後續 API 呼叫將失效。
封裝 AVI 操作的核心類別:
class CAvi {
public:
int cy; // 影像高度
int cx; // 影像寬度
BYTE* pData; // 影像資料緩衝區
BITMAPINFO* m_pBMI; // BMP 資訊標頭
PAVISTREAM pavi; // 視訊串流介面
PAVIFILE pfile; // AVI 檔案介面
AVIFILEINFO* pfi; // AVI 檔案資訊
BOOL AviRead(int mFrame); // 讀取第 mFrame 幀
CAvi(); // 建構式
CAviCreate(CString& str); // 以檔名初始化
virtual ~CAvi(); // 解構式
};
CAvi::CAvi() {
AVIFileInit(); // 初始化 AVI 庫
cx = cy = 0;
m_pBMI = NULL;
pData = NULL;
pfi = NULL;
}
CAvi::~CAvi() {
AVIFileExit(); // 釋放 AVI 庫
if (pData) { delete[] pData; pData = NULL; }
if (m_pBMI) { delete m_pBMI; m_pBMI = NULL; }
if (pfi) { delete pfi; pfi = NULL; }
}
CAvi::CAviCreate(CString& str) {
HRESULT hr;
pfi = new AVIFILEINFO;
// 開啟 AVI 檔案
hr = AVIFileOpen(&pfile, str, OF_READ, NULL);
// 取得檔案資訊 (寬、高等)
hr = AVIFileInfo(pfile, pfi, sizeof(AVIFILEINFO));
cx = pfi->dwWidth;
cy = pfi->dwHeight;
// 取得視訊串流
hr = AVIFileGetStream(pfile, &pavi, streamtypeVIDEO, 0);
// 建立 BMP 資訊標頭 (24-bit RGB)
m_pBMI = new BITMAPINFO;
m_pBMI->bmiHeader.biBitCount = 24;
m_pBMI->bmiHeader.biCompression = BI_RGB;
m_pBMI->bmiHeader.biWidth = cx;
m_pBMI->bmiHeader.biHeight = cy;
m_pBMI->bmiHeader.biPlanes = 1;
m_pBMI->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
m_pBMI->bmiHeader.biSizeImage = cx * cy * 3;
// 配置影像資料緩衝區
pData = new BYTE[cx * cy * 3];
}
BOOL CAvi::AviRead(int mFrame) {
HRESULT hr = AVIStreamRead(pavi, mFrame, 1, pData, cx * cy * 3, NULL, NULL);
return (hr == 0) ? TRUE : FALSE;
}
取得 pData (像素資料) 與 m_pBMI (標頭) 後,可依 BMP 檔案格式寫入磁碟。需建立 BITMAPFILEHEADER,計算檔案大小與偏移量,依序寫入:檔案標頭、資訊標頭、像素資料。完整儲存邏輯請參考「Visual C++6.0 開發灰度位圖處理」。
| API 函式 | 用途 |
|---|---|
| AVIFileInit / AVIFileExit | 函式庫初始化/釋放 |
| AVIFileOpen | 開啟 AVI 檔案 |
| AVIFileInfo | 取得檔案屬性 (寬、高、幀數等) |
| AVIFileGetStream | 取得指定類型串流 (streamtypeVIDEO) |
| AVIStreamRead | 讀取指定幀資料到緩衝區 |