아래 내용은 인터넷에서 찾은 글인데 출처가 기억나지 않아 따로 명시하지 못했습니다.
================================
Avi처리부
¨ Avi 파일을 여는 부분
Avi파일을 다루는 함수는 기본적으로 Windows API로 제공된다. 이 프로그램에서는 LoadAviFile()함수가 그런 API 를 이용하여 Avi파일을 열고 있다. 먼저 AVIFileOpen()함수를 이용해서 파일의 핸들을 얻고 AVIFileInfo()함수를 통해서 헤더에 해당하는 정보를 얻어온다. 여기서 얻어온 헤더정보를 이용해서 Avi파일을 처리하게 된다.
void CAviDialog::LoadAviFile()
{
int ErrorCode;
gcpavi=0;
m_bSearchArea=false;
m_MouseRect=CRect(-1,-1,-1,-1);
// Avi 파일을 개방한다.
ErrorCode = AVIFileOpen(&ppAviFile, AviFilePath, OF_READ, NULL);
if (ErrorCode == AVIERR_BADFORMAT)
MessageBox("AVIERR_BADFORMAT", NULL, MB_OK);
else if (ErrorCode == AVIERR_MEMORY)
MessageBox("AVIERR_MEMORY", NULL, MB_OK);
else if (ErrorCode == AVIERR_FILEREAD)
MessageBox("AVIERR_FILEREAD", NULL, MB_OK);
else if (ErrorCode == AVIERR_FILEOPEN)
MessageBox("AVIERR_FILEOPEN", NULL, MB_OK);
AVIFileInfo(ppAviFile, &pAviInfo, sizeof(pAviInfo));
AviPlayRate = 1000 / (pAviInfo.dwRate / pAviInfo.dwScale);
// Refresh time
m_sFS.Format("%df/s", pAviInfo.dwRate / pAviInfo.dwScale);
UpdateData(FALSE);
// 파일에 포함된 스트림의 종류를 얻는다. audio, midi, text, video
// 파일에 포함된 스트림의 종류만큼 반복한다.
// pavi값을 배열에 저장해야 한다.
for (int i = 0; i <= MAXNUMSTREAMS; i++)
{
if (AVIFileGetStream(ppAviFile, &pavi, 0L, i) != AVIERR_OK)
break;
if (i == MAXNUMSTREAMS)
{
AVIStreamRelease(pavi);
MessageBox("Exceeded maximum number of streams", NULL, MB_OK);
break;
}
gapavi[i] = pavi;
}
gcpavi = i;
for (i = 0; i < gcpavi; i++)
{
// 스트림헤더의 정보를 얻는다.
AVIStreamInfo(gapavi[i], &avis, sizeof(avis));
switch (avis.fccType)
{
case streamtypeVIDEO:
// 전체 프레임 수를 얻는다.
length = AVIStreamLength(gapavi[i]);
// 전체프레임수를 나타낸다.
m_sFrameRate.Format("%d/%d", 1, length);
UpdateData(FALSE);
l= sizeof(format);
// 비트맵 정보를 읽는다.
AVIStreamReadFormat(gapavi[i], AVIStreamStart(gapavi[i]), &format, &l);
bi = (LPBITMAPINFOHEADER)format;
pgf = AVIStreamGetFrameOpen(gapavi[i], NULL);
// BITMAPINFOHEADER의 정보를 설정한다.
bi = (LPBITMAPINFOHEADER)format;
// BITMAPFILEHEADER의 정보를 설정한다.
bf.bfType = 19778;
// 트루컬러는 RGBQUAD 정보가 없다.
bf.bfSize =
sizeof(BITMAPINFOHEADER) +
sizeof(BITMAPFILEHEADER) +
bi->biWidth * bi->biHeight * 3;
bf.bfOffBits = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER);
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
// 현재 나타낼 프레임을 첫번째로 설정한다.
AviFramePosition = 0;
break;
case streamtypeAUDIO:
LPWAVEFORMAT pwf = (LPWAVEFORMAT)abFormat;
l = sizeof(wf);
length = AVIStreamLength(gapavi[i]);
AVIStreamReadFormat(gapavi[i], AVIStreamStart(gapavi[i]), &wf, &l);
/*fp=fopen("sample.pcm", "wb");
for (pos=0; pos<length; pos++)
{
AVIStreamRead(gapavi[i], (long) pos, 1L, lpAudio, sizeof(lpAudio), &s, NULL);
fwrite(lpAudio, s, 1, fp);
}
fclose(fp);*/
break;
}
}
Invalidate();
}
¨ Avi 파일에서 프레임별로 Bmp파일을 추출하는 부분
AVIStreamGetFrame()함수는 원하는 위치의 프레임을 얻어오는 역할을 수행하는 API함수이다. 일단 이 함수를 통해서 얻어온 프레임은 다시 비트맵의 정보를 가지고 있는 LPBITMAPINFOHEADER구조체를 통해서 비트맵화 된다.
void CAviDialog::GetAviFrame(int AviFramePosition, HDC dc)
{
// 현재 나타낼 이미지의 프레임을 얻는다.
if ((gf = (unsigned char *) AVIStreamGetFrame(pgf, AviFramePosition))==NULL && CameraState==NONACTIVE)
MessageBox("CODEC이 컴퓨터에 설치되어 있지 않습니다.", NULL, MB_OK);
else
{
bi = (LPBITMAPINFOHEADER)gf;
bi->biXPelsPerMeter = 0;
bi->biYPelsPerMeter = 0;
bitmapinfo.bmiHeader.biBitCount = bi->biBitCount;
bitmapinfo.bmiHeader.biClrImportant = bi->biClrImportant;
bitmapinfo.bmiHeader.biClrUsed = bi->biClrUsed;
bitmapinfo.bmiHeader.biCompression = bi->biCompression;
bitmapinfo.bmiHeader.biHeight = bi->biHeight;
bitmapinfo.bmiHeader.biWidth = bi->biWidth;
bitmapinfo.bmiHeader.biPlanes = bi->biPlanes;
bitmapinfo.bmiHeader.biSize = bi->biSize;
bitmapinfo.bmiHeader.biSizeImage = bi->biSizeImage;
bitmapinfo.bmiHeader.biXPelsPerMeter = bi->biXPelsPerMeter;
bitmapinfo.bmiHeader.biYPelsPerMeter = bi->biYPelsPerMeter;
gf += sizeof(BITMAPINFOHEADER);
rect.left = 8;
rect.top = 7;
rect.right = bitmapinfo.bmiHeader.biWidth + 8;
rect.bottom = bitmapinfo.bmiHeader.biHeight + 7;
// 이미지를 다이얼로그에 나타낸다.
if (m_bHSBMode!=TRUE)
{
// 이미지 분석모드가 아닐경우
SetDIBitsToDevice(dc, 8, 7, bitmapinfo.bmiHeader.biWidth, bitmapinfo.bmiHeader.biHeight ,
0 ,0, 0, (WORD)bitmapinfo.bmiHeader.biWidth, gf, &bitmapinfo, DIB_RGB_COLORS);
} else
{
// 이미지 분석모드일 경우
AnalysisImage(gf);
SetDIBitsToDevice(dc, 8, 7, bitmapinfo.bmiHeader.biWidth, bitmapinfo.bmiHeader.biHeight ,
0 ,0, 0, (WORD)bitmapinfo.bmiHeader.biWidth, m_BinImg, &bitmapinfo, DIB_RGB_COLORS);
}
}
}