438 lines
10 KiB
C++
438 lines
10 KiB
C++
/****************************************************************************
|
|
*
|
|
* WRITEAVI.C Modified 2003
|
|
*
|
|
* Creates the file OUTPUT.AVI, an AVI file consisting of a rotating clock
|
|
* face. This program demonstrates using the functions in AVIFILE.DLL
|
|
* to make writing AVI files simple.
|
|
*
|
|
* This is a stripped-down example; a real application would have a user
|
|
* interface and check for errors.
|
|
*
|
|
***************************************************************************/
|
|
#include "stdafx.h"
|
|
#include <windowsx.h>
|
|
#include <memory.h>
|
|
#include <mmsystem.h>
|
|
#include <vfw.h>
|
|
|
|
#include "writeavi.h"
|
|
|
|
CAVIFile::CAVIFile()
|
|
: m_bHasSaveOptionsDialog(TRUE),
|
|
m_nColorNum(8)//256色
|
|
{
|
|
m_pfile = NULL;
|
|
m_ps = NULL;
|
|
m_psCompressed = NULL;
|
|
m_psText = NULL;
|
|
m_pOpts[0] = &m_opts;
|
|
WORD wVer = HIWORD(VideoForWindowsVersion());
|
|
if (wVer < 0x010A)
|
|
{
|
|
// oops, we are too old, blow out of here
|
|
m_bOK = FALSE;
|
|
}
|
|
else
|
|
{
|
|
AVIFileInit();
|
|
}
|
|
|
|
m_hSaveOptionsParentWnd = NULL;
|
|
}
|
|
|
|
CAVIFile::CAVIFile(LPCTSTR lpszFileName, int xdim, int ydim, int rate)
|
|
: m_sFileName(lpszFileName),
|
|
m_nXDim(xdim), m_nYDim(ydim),
|
|
m_bOK(TRUE), m_nFrame(0), m_nRate(rate),
|
|
m_bHasSaveOptionsDialog(TRUE),
|
|
m_nColorNum(8)//256色
|
|
{
|
|
m_pfile = NULL;
|
|
m_ps = NULL;
|
|
m_psCompressed = NULL;
|
|
m_psText = NULL;
|
|
m_pOpts[0] = &m_opts;
|
|
WORD wVer = HIWORD(VideoForWindowsVersion());
|
|
if (wVer < 0x010A)
|
|
{
|
|
// oops, we are too old, blow out of here
|
|
m_bOK = FALSE;
|
|
}
|
|
else
|
|
{
|
|
AVIFileInit();
|
|
}
|
|
}
|
|
|
|
CAVIFile::~CAVIFile()
|
|
{
|
|
if (m_ps)
|
|
AVIStreamClose(m_ps);
|
|
|
|
if (m_psCompressed)
|
|
AVIStreamClose(m_psCompressed);
|
|
|
|
if (m_psText)
|
|
AVIStreamClose(m_psText);
|
|
|
|
if (m_pfile)
|
|
AVIFileClose(m_pfile);
|
|
|
|
WORD wVer = HIWORD(VideoForWindowsVersion());
|
|
if (wVer >= 0x010A)
|
|
{
|
|
AVIFileExit();
|
|
}
|
|
}
|
|
|
|
void CAVIFile::Init(LPCTSTR lpszFileName, int xdim, int ydim, int rate)
|
|
{
|
|
m_sFileName = lpszFileName;
|
|
m_nXDim = xdim;
|
|
m_nYDim = ydim;
|
|
m_bOK = TRUE;
|
|
m_nFrame = 0;
|
|
m_nRate = rate;
|
|
}
|
|
|
|
BOOL CAVIFile::Compress()
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
hr = AVIMakeCompressedStream(&m_psCompressed, m_ps, &m_opts, NULL);
|
|
if (hr != AVIERR_OK)
|
|
return FALSE;
|
|
AVIFileRelease(m_pfile);
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
HANDLE CAVIFile::MakeDib( HBITMAP hbitmap, UINT bits )
|
|
{
|
|
HANDLE hdib ;
|
|
HDC hdc ;
|
|
BITMAP bitmap ;
|
|
UINT wLineLen ;
|
|
DWORD dwSize ;
|
|
DWORD wColSize ;
|
|
LPBITMAPINFOHEADER lpbi ;
|
|
LPBYTE lpBits ;
|
|
|
|
GetObject(hbitmap,sizeof(BITMAP),&bitmap) ;
|
|
|
|
//
|
|
// DWORD align the width of the DIB
|
|
// Figure out the size of the colour table
|
|
// Calculate the size of the DIB
|
|
//
|
|
wLineLen = (bitmap.bmWidth*bits+31)/32 * 4;
|
|
wColSize = sizeof(RGBQUAD)*((bits <= 8) ? 1<<bits : 0);
|
|
dwSize = sizeof(BITMAPINFOHEADER) + wColSize +
|
|
(DWORD)(UINT)wLineLen*(DWORD)(UINT)bitmap.bmHeight;
|
|
|
|
//
|
|
// Allocate room for a DIB and set the LPBI fields
|
|
//
|
|
hdib = GlobalAlloc(GHND,dwSize);
|
|
if (!hdib)
|
|
return hdib ;
|
|
|
|
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib) ;
|
|
|
|
lpbi->biSize = sizeof(BITMAPINFOHEADER) ;
|
|
lpbi->biWidth = bitmap.bmWidth ;
|
|
lpbi->biHeight = bitmap.bmHeight ;
|
|
lpbi->biPlanes = 1 ;
|
|
lpbi->biBitCount = (WORD) bits ;
|
|
lpbi->biCompression = BI_RGB ;
|
|
lpbi->biSizeImage = dwSize - sizeof(BITMAPINFOHEADER) - wColSize ;
|
|
lpbi->biXPelsPerMeter = 0 ;
|
|
lpbi->biYPelsPerMeter = 0 ;
|
|
lpbi->biClrUsed = (bits <= 8) ? 1<<bits : 0;
|
|
lpbi->biClrImportant = 0 ;
|
|
|
|
//
|
|
// Get the bits from the bitmap and stuff them after the LPBI
|
|
//
|
|
lpBits = (LPBYTE)(lpbi+1)+wColSize ;
|
|
|
|
hdc = CreateCompatibleDC(NULL) ;
|
|
|
|
GetDIBits(hdc,hbitmap,0,bitmap.bmHeight,lpBits,(LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
|
|
|
|
// Fix this if GetDIBits messed it up....
|
|
lpbi->biClrUsed = (bits <= 8) ? 1<<bits : 0;
|
|
|
|
DeleteDC(hdc) ;
|
|
GlobalUnlock(hdib);
|
|
|
|
return hdib ;
|
|
}
|
|
|
|
BOOL CAVIFile::AddFrame(CBitmap& bmp)
|
|
{
|
|
HRESULT hr;
|
|
if (!m_bOK)
|
|
return FALSE;
|
|
|
|
LPBITMAPINFOHEADER alpbi =(LPBITMAPINFOHEADER)GlobalLock(MakeDib(bmp, m_nColorNum)); //24为24位真彩
|
|
if (alpbi == NULL)
|
|
return FALSE;
|
|
|
|
//宽和高是否一致
|
|
int nXDim = alpbi->biWidth;
|
|
int nYDim = alpbi->biHeight;
|
|
if (m_nXDim>=0 && m_nXDim != nXDim) {
|
|
GlobalFreePtr(alpbi);
|
|
return FALSE;
|
|
}
|
|
if (m_nYDim>=0 && m_nYDim != nYDim) {
|
|
GlobalFreePtr(alpbi);
|
|
return FALSE;
|
|
}
|
|
m_nXDim = nXDim;
|
|
m_nYDim = nYDim;
|
|
|
|
if (m_nFrame == 0)
|
|
{
|
|
hr = AVIFileOpen(&m_pfile, // returned file pointer
|
|
m_sFileName, // file name
|
|
OF_WRITE | OF_CREATE, // mode to open file with
|
|
NULL); // use handler determined
|
|
// from file extension....
|
|
if (hr != AVIERR_OK)
|
|
{
|
|
GlobalFreePtr(alpbi);
|
|
m_bOK = FALSE;
|
|
return FALSE;
|
|
}
|
|
|
|
_fmemset(&m_strhdr, 0, sizeof(m_strhdr));
|
|
m_strhdr.fccType = streamtypeVIDEO; // stream type
|
|
m_strhdr.fccHandler = 0;
|
|
m_strhdr.dwScale = 1;
|
|
m_strhdr.dwRate = m_nRate; // 80 fps avi rate
|
|
m_strhdr.dwSuggestedBufferSize = alpbi->biSizeImage;
|
|
SetRect(&m_strhdr.rcFrame, 0, 0, // rectangle for stream
|
|
m_nXDim,m_nYDim);
|
|
|
|
// And create the stream;
|
|
hr = AVIFileCreateStream(m_pfile, // file pointer
|
|
&m_ps, // returned stream pointer
|
|
&m_strhdr); // stream header
|
|
if (hr != AVIERR_OK)
|
|
{
|
|
GlobalFreePtr(alpbi);
|
|
m_bOK = FALSE;
|
|
return FALSE;
|
|
}
|
|
|
|
_fmemset(&m_opts, 0, sizeof(m_opts));
|
|
|
|
//是否屏蔽掉属性对话框
|
|
if (m_bHasSaveOptionsDialog) {
|
|
if (!AVISaveOptions(m_hSaveOptionsParentWnd,0,1,
|
|
&m_ps,(LPAVICOMPRESSOPTIONS FAR *)&m_pOpts)) {
|
|
GlobalFreePtr(alpbi);
|
|
m_bOK = FALSE;
|
|
return FALSE;
|
|
}
|
|
}
|
|
hr = AVIMakeCompressedStream(&m_psCompressed, m_ps, &m_opts, NULL);
|
|
if (hr != AVIERR_OK)
|
|
{
|
|
GlobalFreePtr(alpbi);
|
|
m_bOK = FALSE;
|
|
return FALSE;
|
|
}
|
|
|
|
hr = AVIStreamSetFormat(m_psCompressed, 0,
|
|
alpbi, // stream format
|
|
alpbi->biSize + // format size
|
|
alpbi->biClrUsed * sizeof(RGBQUAD));
|
|
if (hr != AVIERR_OK)
|
|
{
|
|
GlobalFreePtr(alpbi);
|
|
m_bOK = FALSE;
|
|
return FALSE;
|
|
}
|
|
|
|
// Fill in the stream header for the text stream....
|
|
|
|
// The text stream is in 60ths of a second....
|
|
|
|
/*_fmemset(&m_strhdr, 0, sizeof(m_strhdr));
|
|
m_strhdr.fccType = streamtypeTEXT;
|
|
m_strhdr.fccHandler = mmioFOURCC('D', 'R', 'A', 'W');
|
|
m_strhdr.dwScale = 1;
|
|
m_strhdr.dwRate = 60;
|
|
m_strhdr.dwSuggestedBufferSize = sizeof(m_szText);
|
|
SetRect(&m_strhdr.rcFrame, 0, (int) alpbi->biHeight,
|
|
(int) alpbi->biWidth, (int) alpbi->biHeight + TEXT_HEIGHT);
|
|
|
|
// ....and create the stream.
|
|
hr = AVIFileCreateStream(m_pfile, &m_psText, &m_strhdr);
|
|
if (hr != AVIERR_OK)
|
|
{
|
|
GlobalFreePtr(alpbi);
|
|
m_bOK = FALSE;
|
|
return FALSE;
|
|
}
|
|
|
|
m_dwTextFormat = sizeof(m_dwTextFormat);
|
|
hr = AVIStreamSetFormat(m_psText, 0, &m_dwTextFormat, sizeof(m_dwTextFormat));
|
|
if (hr != AVIERR_OK)
|
|
{
|
|
GlobalFreePtr(alpbi);
|
|
m_bOK = FALSE;
|
|
return FALSE;
|
|
}*/
|
|
}
|
|
|
|
// Jetzt eigentliches Schreiben
|
|
hr = AVIStreamWrite(m_psCompressed, // stream pointer
|
|
m_nFrame * 10, //10, // time of this frame
|
|
1, // number to write
|
|
(LPBYTE) alpbi + // pointer to data
|
|
alpbi->biSize +
|
|
alpbi->biClrUsed * sizeof(RGBQUAD),
|
|
alpbi->biSizeImage, // size of this frame
|
|
AVIIF_KEYFRAME, // flags....
|
|
NULL,
|
|
NULL);
|
|
if (hr != AVIERR_OK)
|
|
{
|
|
GlobalFreePtr(alpbi);
|
|
m_bOK = FALSE;
|
|
return FALSE;
|
|
}
|
|
|
|
// Make some text to put in the file ...
|
|
//LoadString(hInstance, IDS_TEXTFORMAT, szMessage, BUFSIZE );
|
|
/*
|
|
strcpy(szMessage, "This is frame #%d");
|
|
|
|
int iLen = wsprintf(m_szText, szMessage, (int)(m_nFrame + 1));
|
|
|
|
// ... and write it as well.
|
|
hr = AVIStreamWrite(m_psText,
|
|
m_nFrame * 40,
|
|
1,
|
|
m_szText,
|
|
iLen + 1,
|
|
AVIIF_KEYFRAME,
|
|
NULL,
|
|
NULL);
|
|
if (hr != AVIERR_OK)
|
|
{
|
|
GlobalFreePtr(alpbi);
|
|
m_bOK = FALSE;
|
|
return FALSE;
|
|
}
|
|
*/
|
|
GlobalFreePtr(alpbi);
|
|
|
|
m_nFrame++;
|
|
return TRUE;
|
|
}
|
|
|
|
//******************************************************//
|
|
// 后面的是新添加的函数,前面作了部分修改 //
|
|
//******************************************************//
|
|
|
|
BOOL CAVIFile::AddFrame(XString sBitmapFile)
|
|
{
|
|
if (!FindFile(sBitmapFile))
|
|
return FALSE;
|
|
|
|
CBitmap bitmap;
|
|
if (LoadBMPImage(sBitmapFile,bitmap)) {
|
|
AddFrame(bitmap);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CAVIFile::LoadBMPImage(const TCHAR *filename,CBitmap& bitmap)
|
|
{
|
|
CFile file;
|
|
if (!file.Open(filename, CFile::modeRead))
|
|
return FALSE;
|
|
|
|
BITMAPFILEHEADER bmfHeader;
|
|
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
|
|
return FALSE;
|
|
if (bmfHeader.bfType != ((WORD) ('M' << 8) | 'B'))
|
|
return FALSE;
|
|
|
|
DWORD nPackedDIBLen = file.GetLength() - sizeof(BITMAPFILEHEADER);
|
|
HGLOBAL hDIB = ::GlobalAlloc(GMEM_FIXED, nPackedDIBLen);
|
|
if (hDIB == 0)
|
|
return FALSE;
|
|
|
|
if (file.Read((LPSTR)hDIB, nPackedDIBLen) != nPackedDIBLen){
|
|
::GlobalFree(hDIB);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ;
|
|
BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
|
|
|
|
int nColors = bmiHeader.biClrUsed ? bmiHeader.biClrUsed :
|
|
1 << bmiHeader.biBitCount;
|
|
|
|
LPVOID lpDIBBits;
|
|
if (bmInfo.bmiHeader.biBitCount > 8) {
|
|
lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors + bmInfo.bmiHeader.biClrUsed) +
|
|
((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
|
|
}
|
|
else {
|
|
lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);
|
|
}
|
|
|
|
CClientDC dc(NULL);
|
|
HBITMAP hBmp = CreateDIBitmap(dc.m_hDC, // handle to device context
|
|
&bmiHeader, // pointer to bitmap size and format data
|
|
CBM_INIT, // initialization flag
|
|
lpDIBBits, // pointer to initialization data
|
|
&bmInfo, // pointer to bitmap color-format data
|
|
DIB_RGB_COLORS);// color-data usage
|
|
|
|
bitmap.Attach(hBmp);
|
|
::GlobalFree(hDIB);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CAVIFile::SetHasSaveOptionsDialog(BOOL bFlag)
|
|
{
|
|
m_bHasSaveOptionsDialog = bFlag;
|
|
}
|
|
|
|
BOOL CAVIFile::HasSaveOptionsDialog()
|
|
{
|
|
return m_bHasSaveOptionsDialog;
|
|
}
|
|
|
|
void CAVIFile::SetSaveOptionsParentWnd(HWND hWnd)
|
|
{
|
|
m_hSaveOptionsParentWnd = hWnd;
|
|
}
|
|
|
|
HWND CAVIFile::GetSaveOptionsParentWnd()
|
|
{
|
|
return m_hSaveOptionsParentWnd;
|
|
}
|
|
|
|
void CAVIFile::SetColorNum(UINT nColor)
|
|
{
|
|
m_nColorNum = nColor;
|
|
}
|
|
|
|
UINT CAVIFile::GetColorNum()
|
|
{
|
|
return m_nColorNum;
|
|
}
|