首页  编辑  

AVI文件

Tags: /超级猛料/Multi-Media.多媒体相关/   Date Created:

下面是MSDN中找到的,可以写入一个AVI文件,当初是为了把Bitmap转换成AVI而搜的:)

WRITEAVI.C

/**************************************************************************  *

*  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR  *  PURPOSE.

*  *  Copyright 1992 - 1998 Microsoft Corporation.  All Rights Reserved.

/****************************************************************************

*  *  WRITEAVI.C

* *  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.  *

***************************************************************************/

#define  STRICT  #define  INC_OLE2  #include <windows.h>  #include <windowsx.h>  #include <memory.h>

#include <mmsystem.h>  #include <vfw.h>   #include "writeavi.h"

//---------------------------------------------------------------------------

// Defines

//---------------------------------------------------------------------------

// Our movie is 160x120 and 15 frames long

// #define BITMAP_X160    #define BITMAP_Y120    #define N_FRAMES15   #define TEXT_HEIGHT20  

#define AVIIF_KEYFRAME0x00000010L // this frame is a key frame.    #define BUFSIZE 260  

#define LPLPBILPBITMAPINFOHEADER *  

//---------------------------------------------------------------------------

// Function declarations

//---------------------------------------------------------------------------

static void FreeFrames(LPLPBI) ;

static void MakeFrames(LPLPBI, UINT, UINT, UINT) ;

static HANDLE MakeDib(HBITMAP, UINT);  

//---------------------------------------------------------------------------

// A quick lookup table for Sin and Cos values

//--------------------------------------------------------------------------- //

static int aSin[N_FRAMES] = { 0, 40, 74, 95, 99, 86, 58, 20, -20, -58, -86, -99, -95, -74, -40, } ;  

static int aCos[N_FRAMES] = { 100, 91, 66, 30, -10, -49, -80, -97, -97, -80, -50,-10,30,  66, 91, } ;  

//---------------------------------------------------------------------------- //

// We don't have a window, we just pop up a dialog // box, write the file, and quit //

int PASCAL WinMain(

HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR szCmdLine,

int sw)

{

LPBITMAPINFOHEADER alpbi[N_FRAMES];

int i;

AVISTREAMINFO strhdr;

PAVIFILE pfile = NULL;

PAVISTREAM ps = NULL, psCompressed = NULL, psText = NULL;

char szText[BUFSIZE];

int iLen;

AVICOMPRESSOPTIONS opts;

AVICOMPRESSOPTIONS FAR * aopts[1] = {&opts};

HRESULT hr;

DWORD dwTextFormat;

WORD wVer;

char szTitle[BUFSIZE];

char szMessage[BUFSIZE];  

/* first let's make sure we are running on 1.1 */

wVer = HIWORD(VideoForWindowsVersion());

if (wVer < 0x010a){

/* oops, we are too old, blow out of here */

LoadString(hInstance, IDS_APPERR, szTitle, BUFSIZE );

LoadString(hInstance, IDS_VFWTOOOLD, szMessage, BUFSIZE );

MessageBeep(MB_ICONHAND);

MessageBox(NULL, szMessage, szTitle, MB_OK|MB_ICONSTOP);

return FALSE;

}  

alpbi[0] = NULL;  

LoadString(hInstance, IDS_APPNAME, szTitle, BUFSIZE );

LoadString(hInstance, IDS_INTRO, szMessage, BUFSIZE );  

if (MessageBox(NULL, szMessage, szTitle, MB_OKCANCEL) == IDCANCEL)

return 0;  

//  Set up the bitmaps for the file in an array  

MakeFrames(alpbi, 8, BITMAP_X, BITMAP_Y);  

AVIFileInit();  

// Open the movie file for writing....  

LoadString(hInstance, IDS_FILENAME, szTitle, BUFSIZE );  

hr = AVIFileOpen(&pfile,    // returned file pointer

      szTitle,            // file name

      OF_WRITE | OF_CREATE,    // mode to open file with

      NULL);    // use handler determined

   // from file extension....

if (hr != AVIERR_OK)

goto error;  

// Fill in the header for the video stream....  

// The video stream will run in 15ths of a second....  

_fmemset(&strhdr, 0, sizeof(strhdr));

strhdr.fccType                = streamtypeVIDEO;// stream type

strhdr.fccHandler             = 0;

strhdr.dwScale                = 1;

strhdr.dwRate                 = 15;    // 15 fps

strhdr.dwSuggestedBufferSize  = alpbi[0]->biSizeImage;

SetRect(&strhdr.rcFrame, 0, 0,    // rectangle for stream

   (int) alpbi[0]->biWidth,

   (int) alpbi[0]->biHeight);

// And create the stream;

hr = AVIFileCreateStream(pfile,    // file pointer

        &ps,    // returned stream pointer

        &strhdr);    // stream header

if (hr != AVIERR_OK) {

goto error;

}  

_fmemset(&opts, 0, sizeof(opts));  

if (!AVISaveOptions(NULL, 0, 1, &ps, (LPAVICOMPRESSOPTIONS FAR *) &aopts))

   goto error;  

hr = AVIMakeCompressedStream(&psCompressed, ps, &opts, NULL);

if (hr != AVIERR_OK) {

goto error;

}  

hr = AVIStreamSetFormat(psCompressed, 0,

      alpbi[0],    // stream format

      alpbi[0]->biSize +   // format size

      alpbi[0]->biClrUsed * sizeof(RGBQUAD));

if (hr != AVIERR_OK) {

goto error;

}  

// Fill in the stream header for the text stream....  

// The text stream is in 60ths of a second....  

_fmemset(&strhdr, 0, sizeof(strhdr));

strhdr.fccType                = streamtypeTEXT;

strhdr.fccHandler             = mmioFOURCC('D', 'R', 'A', 'W');

strhdr.dwScale                = 1;

strhdr.dwRate                 = 60;

strhdr.dwSuggestedBufferSize  = sizeof(szText);

SetRect(&strhdr.rcFrame, 0, (int) alpbi[0]->biHeight,

   (int) alpbi[0]->biWidth, (int) alpbi[0]->biHeight + TEXT_HEIGHT);  

// ....and create the stream.

hr = AVIFileCreateStream(pfile, &psText, &strhdr);

if (hr != AVIERR_OK) {

goto error;

} dwTextFormat = sizeof(dwTextFormat);

hr = AVIStreamSetFormat(psText, 0, &dwTextFormat, sizeof(dwTextFormat));

if (hr != AVIERR_OK) {

goto error;

}

// Now write out each video frame, along with a text label.

// The video frames are 2/3 of a second apart, which is 10

// in the video time scale and 40 in the text stream's time scale.  

for (i = 0; i < N_FRAMES; i++) {

hr = AVIStreamWrite(psCompressed,// stream pointer

i * 10,// time of this frame

1,// number to write

(LPBYTE) alpbi[i] +// pointer to data

alpbi[i]->biSize +

alpbi[i]->biClrUsed * sizeof(RGBQUAD),

alpbi[i]->biSizeImage,// size of this frame

AVIIF_KEYFRAME, // flags....

NULL,

NULL);

if (hr != AVIERR_OK)

break;  

// Make some text to put in the file ...

LoadString(hInstance, IDS_TEXTFORMAT, szMessage, BUFSIZE );  

iLen = wsprintf(szText, szMessage, (int)(i + 1));  

// ... and write it as well.

hr = AVIStreamWrite(psText,

i * 40,

1,

szText,

iLen + 1,

AVIIF_KEYFRAME,

NULL,

NULL);

if (hr != AVIERR_OK)

break;

}

error:

//

// Now close the file

//

if (ps)

AVIStreamClose(ps);  

if (psCompressed)

AVIStreamClose(psCompressed);  

if (psText)

AVIStreamClose(psText);  

if (pfile)

AVIFileClose(pfile);  

AVIFileExit();

FreeFrames(alpbi);  

if (hr != NOERROR) {

LoadString(hInstance, IDS_APPERR, szTitle, BUFSIZE );

LoadString(hInstance, IDS_WRITEERR, szMessage, BUFSIZE );  

MessageBox(NULL, szMessage, szTitle, MB_OK);

}

return 0;

}  

// // Fill an array of LPBI's with the frames for this movie //

static void MakeFrames(LPLPBI alpbi, UINT bits, UINT wXSize,UINT wYSize )

{

HDC         hdc ;

HDC         hdcMem ;

HBITMAP     hbitmap,hbitmapOld ;

HPEN        hpen3,hpen1,hpenwhite,hpenOld ;

HFONT       hfont,hfontOld ;

HBRUSH      hbrush,hbrushOld ;

RECT        rc ;

RECT        rcFrameNo ;

int         wXCent,wYCent ;

int         cxPixInch ;

int         cyPixInch ;

int         cxPixels ;

int         cyPixels ;

int         radius ;

int         x0,y0,x1,y1 ;

int         i,j ;

char        szNumber[3] ;

// // Make sure our resources are freed //

FreeFrames(alpbi);  

// // Find the center of the movie //

wXCent = wXSize/2 ;

wYCent = wYSize/2 ;  

hdc = GetDC(NULL) ;

hdcMem = CreateCompatibleDC(NULL) ;

/// We need some gray and white brushes and pens, and a bitmap //

hpen3 = CreatePen(PS_SOLID,3,RGB(128,128,128)) ;

hpen1 = CreatePen(PS_SOLID,1,RGB(64,64,64));

hpenwhite = CreatePen(PS_SOLID,1,RGB(255,255,255));

hpenOld = SelectPen(hdcMem, hpen3);

hbrush = CreateSolidBrush(RGB(192,192,192)) ;

hbrushOld = SelectBrush(hdcMem,hbrush) ;

hbitmap = CreateCompatibleBitmap(hdc,wXSize,wYSize) ;

cxPixInch = GetDeviceCaps(hdc,LOGPIXELSX) ;

cyPixInch = GetDeviceCaps(hdc,LOGPIXELSY) ;

//// What radius of circle can we fit in this frame?  Make sure it's round

// regardless of the aspect ratio //

radius = ( wXSize < wYSize ) ? wXSize : (wYSize*cxPixInch)/cyPixInch ;

radius = ( radius * 95 ) / 200 ;  

// // Make a Rectangle in the center where the number will go //

/* x0 = radius / sqrt(2) */

x0 = (radius*100)/141 ;

y0 = (x0*cyPixInch)/cxPixInch ;

x0 = (x0*9)/10 ;

y0 = (y0*9)/10 ;

SetRect( &rcFrameNo,wXCent-x0,wYCent-y0,wXCent+x0,wYCent+y0 ) ;  

// // Move the rectangle in a little and make a font big enough for it //

x0 = (x0*9)/10 ;

y0 = (y0*9)/10 ;

hfont = CreateFont(

y0*2,

x0,

0,

0,

FW_BOLD,

0,

0,

0,

ANSI_CHARSET,

OUT_DEVICE_PRECIS,

CLIP_DEFAULT_PRECIS,

DEFAULT_QUALITY,

DEFAULT_PITCH|FF_SWISS,

NULL

);  

hfontOld = SelectFont(hdcMem, hfont);  

// // Now walk through and make all the frames //

for ( i=0; i<N_FRAMES; i++ ) {

hbitmapOld = SelectBitmap(hdcMem, hbitmap);

// // Fill the whole frame with white //

SetRect(&rc,0,0,wXSize,wYSize) ;

FillRect(hdcMem,&rc,GetStockBrush(WHITE_BRUSH)) ;  

// // Draw the circle inside the previously calculated radius //

cxPixels = radius ;

cyPixels = (cxPixels*cyPixInch)/cxPixInch ;

SelectPen(hdcMem,hpen3) ;

Ellipse(hdcMem,wXCent-cxPixels,wYCent-cyPixels,wXCent+cxPixels,

wYCent+cyPixels) ;

SelectPen(hdcMem,hpen1) ;

// // Draw the number in the previously calculated area //

wsprintf(szNumber,"%02u",i+1) ;

SetBkColor(hdcMem,RGB(192,192,192)) ;

SetTextColor(hdcMem,RGB(255,255,255)) ;

ExtTextOut(

hdcMem,

rcFrameNo.left,

rcFrameNo.top+(rcFrameNo.bottom-rcFrameNo.top)/20,

ETO_CLIPPED,

&rcFrameNo,

szNumber,

2,

NULL);

// // Draw tic marks around the inside of the circle in equal divisions //

for ( j=0; j<N_FRAMES; j++ ) {

x0 = (radius*aSin[j])/100 ;

y0 = (radius*aCos[j])/100 ;

x1 = (((radius*aSin[j])/100)*11)/12 ;

y1 = (((radius*aCos[j])/100)*11)/12 ;

y0 = -(y0*cyPixInch)/cxPixInch ;

y1 = -(y1*cyPixInch)/cxPixInch ;

MoveToEx(hdcMem,wXCent+x0,wYCent+y0,NULL) ;

LineTo(hdcMem,wXCent+x1,wYCent+y1) ;

}  

// // Now draw the hand of the clock in the appropriate position //

x1 = (((radius*aSin[i])/100)*5)/8 ;

y1 = (((radius*aCos[i])/100)*5)/8 ;

y1 = -(y1*cyPixInch)/cxPixInch ;

MoveToEx(hdcMem,wXCent,wYCent,NULL) ;

LineTo(hdcMem,wXCent+x1,wYCent+y1) ;

SelectBitmap(hdcMem, hbitmapOld);

// // Make this into a DIB and stuff it into the array //

alpbi[i] = (LPBITMAPINFOHEADER)GlobalLock(MakeDib(hbitmap, bits));  

// // For an error, just duplicate the last frame if we can //

if (alpbi[i] == NULL && i )

alpbi[i] = alpbi[i-1] ;

}

//// Select all the old objects back and delete resources //

SelectPen(hdcMem, hpenOld);

SelectBrush(hdcMem,hbrushOld) ;

SelectFont(hdcMem,hfontOld) ;

DeletePen(hpen1) ;

DeletePen(hpen3) ;

DeletePen(hpenwhite) ;

DeleteBrush(hbrush) ;

DeleteBitmap(hbitmap) ;

DeleteFont(hfont) ;

DeleteObject(hdcMem) ;

ReleaseDC(NULL,hdc) ;

}

// // Walk through our array of LPBI's and free them //

static void FreeFrames(LPLPBI alpbi)

{

UINT        w ;

if (!alpbi[0])

return ;

// // Don't free a frame if it's a duplicate of the previous one //

for (w=0; w<N_FRAMES; w++)

if (alpbi[w] && alpbi[w] != alpbi[w-1])

GlobalFreePtr(alpbi[w]);

for (w=0; w<N_FRAMES; w++)

alpbi[w] = NULL;

}

/*

** MakeDib(hbitmap)

**

** Take the given bitmap and transform it into a DIB with parameters:

**

** BitsPerPixel:    8

** Colors:          palette

**

*/

static HANDLE  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 ;

}