線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:4394
推到 Plurk!
推到 Facebook!

BMP序列影像轉成AVI

 
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-07-09 01:24:13 IP:140.135.xxx.xxx 未訂閱
http://www.wischik.com/lu/programmer/avi_utils.html 內文: avi_utils.h
 
#ifndef _avi_utils_H
#define _avi_utils_H    // AVI utilities -- for creating avi files
// (c) 2002 Lucian Wischik. No restrictions on use.    DECLARE_HANDLE(HAVI);
// An HAVI identifies an avi file that is being created    HAVI CreateAvi(const char *fn, int frameperiod, const WAVEFORMATEX *wfx);
// CreateAvi - call this to start the creation of the avi file.
// The period is the number of ms between each bitmap frame.
// The waveformat can be null if you're not going to add any audio,
// or if you're going to add audio from a file.    HRESULT AddAviFrame(HAVI avi, HBITMAP hbm);
HRESULT AddAviAudio(HAVI avi, void *dat, unsigned long numbytes);
// AddAviFrame - adds this bitmap to the avi file. hbm must point be a DIBSection.
// It is the callers responsibility to free the hbm.
// AddAviAudio - adds this junk of audio. The format of audio was as specified in the
// wfx parameter to CreateAVI. This fails if NULL was given.
// Both return S_OK if okay, otherwise one of the AVI errors.    HRESULT AddAviWav(HAVI avi, const char *wav, DWORD flags);
// AddAviWav - a convenient way to add an entire wave file to the avi.
// The wav file may be in in memory (in which case flags=SND_MEMORY)
// or a file on disk (in which case flags=SND_FILENAME).
// This function requires that either a null WAVEFORMATEX was passed to CreateAvi,
// or that the wave file now being added has the same format as was
// added earlier.    HRESULT SetAviVideoCompression(HAVI avi, HBITMAP hbm, AVICOMPRESSOPTIONS *opts, bool ShowDialog, HWND hparent);
// SetAviVideoCompression - allows compression of the video. If compression is desired,
// then this function must have been called before any bitmap frames had been added.
// The bitmap hbm must be a DIBSection (so that avi knows what format/size you're giving it),
// but won't actually be added to the movie.
// This function can display a dialog box to let the user choose compression. In this case,
// set ShowDialog to true and specify the parent window. If opts is non-NULL and its
// dwFlags property includes AVICOMPRESSF_VALID, then opts will be used to give initial
// values to the dialog. If opts is non-NULL then the chosen options will be placed in it.
// This function can also be used to choose a compression without a dialog box. In this
// case, set ShowDialog to false, and hparent is ignored, and the compression specified
// in 'opts' is used, and there's no need to call GotAviVideoCompression afterwards.    HRESULT CloseAvi(HAVI avi);
// CloseAvi - the avi must be closed with this message.    unsigned int FormatAviMessage(HRESULT code, char *buf,unsigned int len);
// FormatAviMessage - given an error code, formats it as a string.
// It returns the length of the error message. If buf/len points
// to a real buffer, then it also writes as much as possible into there.    #endif
avi_utils.cpp
 
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include 
#include 
#include "avi_utils.h"    // First, we'll define the WAV file format.
#include 
typedef struct
{ char id[4];         //="fmt "
  unsigned long size; //=16
  short wFormatTag;   //=WAVE_FORMAT_PCM=1
  unsigned short wChannels;       //=1 or 2 for mono or stereo
  unsigned long dwSamplesPerSec;  //=11025 or 22050 or 44100
  unsigned long dwAvgBytesPerSec; //=wBlockAlign * dwSamplesPerSec
  unsigned short wBlockAlign;     //=wChannels * (wBitsPerSample==8?1:2)
  unsigned short wBitsPerSample;  //=8 or 16, for bits per sample
} FmtChunk;    typedef struct
{ char id[4];            //="data"
  unsigned long size;    //=datsize, size of the following array
  unsigned char data[1]; //=the raw data goes here
} DataChunk;    typedef struct
{ char id[4];         //="RIFF"
  unsigned long size; //=datsize 8 16 4
  char type[4];       //="WAVE"
  FmtChunk fmt;
  DataChunk dat;
} WavChunk;
#include         // This is the internal structure represented by the HAVI handle:
typedef struct
{ IAVIFile *pfile;    // created by CreateAvi
  WAVEFORMATEX wfx;   // as given to CreateAvi (.nChanels=0 if none was given). Used when audio stream is first created.
  int period;         // specified in CreateAvi, used when the video stream is first created
  IAVIStream *as;     // audio stream, initialised when audio stream is first created
  IAVIStream *ps, *psCompressed;  // video stream, when first created
  unsigned long nframe, nsamp;    // which frame will be added next, which sample will be added next
  bool iserr;         // if true, then no function will do anything
} TAviUtil;    HAVI CreateAvi(const char *fn, int frameperiod, const WAVEFORMATEX *wfx)
{ IAVIFile *pfile;
  AVIFileInit();
  HRESULT hr = AVIFileOpen(&pfile, fn, OF_WRITE|OF_CREATE, NULL);
  if (hr!=AVIERR_OK) {AVIFileExit(); return NULL;}
  TAviUtil *au = new TAviUtil;
  au->pfile = pfile;
  if (wfx==NULL) ZeroMemory(&au->wfx,sizeof(WAVEFORMATEX)); else CopyMemory(&au->wfx,wfx,sizeof(WAVEFORMATEX));
  au->period = frameperiod;
  au->as=0; au->ps=0; au->psCompressed=0;
  au->nframe=0; au->nsamp=0;
  au->iserr=false;
  return (HAVI)au;
}    HRESULT CloseAvi(HAVI avi)
{ if (avi==NULL) return AVIERR_BADHANDLE;
  TAviUtil *au = (TAviUtil*)avi;
  if (au->as!=0) AVIStreamRelease(au->as); au->as=0;
  if (au->psCompressed!=0) AVIStreamRelease(au->psCompressed); au->psCompressed=0;
  if (au->ps!=0) AVIStreamRelease(au->ps); au->ps=0;
  if (au->pfile!=0) AVIFileRelease(au->pfile); au->pfile=0;
  AVIFileExit();
  delete au;
  return S_OK;
}    HRESULT SetAviVideoCompression(HAVI avi, HBITMAP hbm, AVICOMPRESSOPTIONS *opts, bool ShowDialog, HWND hparent)
{ if (avi==NULL) return AVIERR_BADHANDLE;
  if (hbm==NULL) return AVIERR_BADPARAM;
  DIBSECTION dibs; int sbm = GetObject(hbm,sizeof(dibs),&dibs);
  if (sbm!=sizeof(DIBSECTION)) return AVIERR_BADPARAM;
  TAviUtil *au = (TAviUtil*)avi;
  if (au->iserr) return AVIERR_ERROR;
  if (au->psCompressed!=0) return AVIERR_COMPRESSOR;
  //
  if (au->ps==0) // create the stream, if it wasn't there before
  { AVISTREAMINFO strhdr; ZeroMemory(&strhdr,sizeof(strhdr));
    strhdr.fccType = streamtypeVIDEO;// stream type
    strhdr.fccHandler = 0; 
    strhdr.dwScale = au->period;
    strhdr.dwRate = 1000;
    strhdr.dwSuggestedBufferSize  = dibs.dsBmih.biSizeImage;
    SetRect(&strhdr.rcFrame, 0, 0, dibs.dsBmih.biWidth, dibs.dsBmih.biHeight);
    HRESULT hr=AVIFileCreateStream(au->pfile, &au->ps, &strhdr);
    if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
  }
  //
  if (au->psCompressed==0) // set the compression, prompting dialog if necessary
  { AVICOMPRESSOPTIONS myopts; ZeroMemory(&myopts,sizeof(myopts));
    AVICOMPRESSOPTIONS *aopts[1];
    if (opts!=NULL) aopts[0]=opts; else aopts[0]=&myopts;
    if (ShowDialog)
    { BOOL res = (BOOL)AVISaveOptions(hparent,0,1,&au->ps,aopts);
      if (!res) {AVISaveOptionsFree(1,aopts); au->iserr=true; return AVIERR_USERABORT;}
    }
    HRESULT hr = AVIMakeCompressedStream(&au->psCompressed, au->ps, aopts[0], NULL);
    AVISaveOptionsFree(1,aopts);
    if (hr != AVIERR_OK) {au->iserr=true; return hr;}
    DIBSECTION dibs; GetObject(hbm,sizeof(dibs),&dibs);
    hr = AVIStreamSetFormat(au->psCompressed, 0, &dibs.dsBmih, dibs.dsBmih.biSize dibs.dsBmih.biClrUsed*sizeof(RGBQUAD));
    if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
  }
  //
  return AVIERR_OK;
}    HRESULT AddAviFrame(HAVI avi, HBITMAP hbm)
{ if (avi==NULL) return AVIERR_BADHANDLE;
  if (hbm==NULL) return AVIERR_BADPARAM;
  DIBSECTION dibs; int sbm = GetObject(hbm,sizeof(dibs),&dibs);
  if (sbm!=sizeof(DIBSECTION)) return AVIERR_BADPARAM;
  TAviUtil *au = (TAviUtil*)avi;
  if (au->iserr) return AVIERR_ERROR;
  //
  if (au->ps==0) // create the stream, if it wasn't there before
  { AVISTREAMINFO strhdr; ZeroMemory(&strhdr,sizeof(strhdr));
    strhdr.fccType = streamtypeVIDEO;// stream type
    strhdr.fccHandler = 0; 
    strhdr.dwScale = au->period;
    strhdr.dwRate = 1000;
    strhdr.dwSuggestedBufferSize  = dibs.dsBmih.biSizeImage;
    SetRect(&strhdr.rcFrame, 0, 0, dibs.dsBmih.biWidth, dibs.dsBmih.biHeight);
    HRESULT hr=AVIFileCreateStream(au->pfile, &au->ps, &strhdr);
    if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
  }
  //
  // create an empty compression, if the user hasn't set any
  if (au->psCompressed==0)
  { AVICOMPRESSOPTIONS opts; ZeroMemory(&opts,sizeof(opts));
    opts.fccHandler=mmioFOURCC('D','I','B',' '); 
    HRESULT hr = AVIMakeCompressedStream(&au->psCompressed, au->ps, &opts, NULL);
    if (hr != AVIERR_OK) {au->iserr=true; return hr;}
    hr = AVIStreamSetFormat(au->psCompressed, 0, &dibs.dsBmih, dibs.dsBmih.biSize dibs.dsBmih.biClrUsed*sizeof(RGBQUAD));
    if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
  }
  //
  //Now we can add the frame
  HRESULT hr = AVIStreamWrite(au->psCompressed, au->nframe, 1, dibs.dsBm.bmBits, dibs.dsBmih.biSizeImage, AVIIF_KEYFRAME, NULL, NULL);
  if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
  au->nframe  ; return S_OK;
}
      HRESULT AddAviAudio(HAVI avi, void *dat, unsigned long numbytes)
{ if (avi==NULL) return AVIERR_BADHANDLE;
  if (dat==NULL || numbytes==0) return AVIERR_BADPARAM;
  TAviUtil *au = (TAviUtil*)avi;
  if (au->iserr) return AVIERR_ERROR;
  if (au->wfx.nChannels==0) return AVIERR_BADFORMAT;
  unsigned long numsamps = numbytes*8 / au->wfx.wBitsPerSample;
  if ((numsamps*au->wfx.wBitsPerSample/8)!=numbytes) return AVIERR_BADPARAM;
  //
  if (au->as==0) // create the stream if necessary
  { AVISTREAMINFO ahdr; ZeroMemory(&ahdr,sizeof(ahdr));
    ahdr.fccType=streamtypeAUDIO;
    ahdr.dwScale=au->wfx.nBlockAlign;
    ahdr.dwRate=au->wfx.nSamplesPerSec*au->wfx.nBlockAlign; 
    ahdr.dwSampleSize=au->wfx.nBlockAlign;
    ahdr.dwQuality=(DWORD)-1;
    HRESULT hr = AVIFileCreateStream(au->pfile, &au->as, &ahdr);
    if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
    hr = AVIStreamSetFormat(au->as,0,&au->wfx,sizeof(WAVEFORMATEX));
    if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
  }
  //
  // now we can write the data
  HRESULT hr = AVIStreamWrite(au->as,au->nsamp,numsamps,dat,numbytes,0,NULL,NULL);
  if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
  au->nsamp =numsamps; return S_OK;
}        HRESULT AddAviWav(HAVI avi, const char *src, DWORD flags)
{ if (avi==NULL) return AVIERR_BADHANDLE;
  if (flags!=SND_MEMORY && flags!=SND_FILENAME) return AVIERR_BADFLAGS;
  if (src==0) return AVIERR_BADPARAM;
  TAviUtil *au = (TAviUtil*)avi;
  if (au->iserr) return AVIERR_ERROR;
  //
  char *buf=0; WavChunk *wav = (WavChunk*)src;
  if (flags==SND_FILENAME)
  { HANDLE hf=CreateFile(src,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
    if (hf==INVALID_HANDLE_VALUE) {au->iserr=true; return AVIERR_FILEOPEN;}
    DWORD size = GetFileSize(hf,NULL);
    buf = new char[size];
    DWORD red; ReadFile(hf,buf,size,&red,NULL);
    CloseHandle(hf);
    wav = (WavChunk*)buf;
  }
  //
  // check that format doesn't clash
  bool badformat=false;
  if (au->wfx.nChannels==0)
  { au->wfx.wFormatTag=wav->fmt.wFormatTag;
    au->wfx.cbSize=0;
    au->wfx.nAvgBytesPerSec=wav->fmt.dwAvgBytesPerSec;
    au->wfx.nBlockAlign=wav->fmt.wBlockAlign;
    au->wfx.nChannels=wav->fmt.wChannels;
    au->wfx.nSamplesPerSec=wav->fmt.dwSamplesPerSec;
    au->wfx.wBitsPerSample=wav->fmt.wBitsPerSample;
  }
  else
  { if (au->wfx.wFormatTag!=wav->fmt.wFormatTag) badformat=true;
    if (au->wfx.nAvgBytesPerSec!=wav->fmt.dwAvgBytesPerSec) badformat=true;
    if (au->wfx.nBlockAlign!=wav->fmt.wBlockAlign) badformat=true;
    if (au->wfx.nChannels!=wav->fmt.wChannels) badformat=true;
    if (au->wfx.nSamplesPerSec!=wav->fmt.dwSamplesPerSec) badformat=true;
    if (au->wfx.wBitsPerSample!=wav->fmt.wBitsPerSample) badformat=true;
  }
  if (badformat) {if (buf!=0) delete[] buf; return AVIERR_BADFORMAT;}
  //
  if (au->as==0) // create the stream if necessary
  { AVISTREAMINFO ahdr; ZeroMemory(&ahdr,sizeof(ahdr));
    ahdr.fccType=streamtypeAUDIO;
    ahdr.dwScale=au->wfx.nBlockAlign;
    ahdr.dwRate=au->wfx.nSamplesPerSec*au->wfx.nBlockAlign; 
    ahdr.dwSampleSize=au->wfx.nBlockAlign;
    ahdr.dwQuality=(DWORD)-1;
    HRESULT hr = AVIFileCreateStream(au->pfile, &au->as, &ahdr);
    if (hr!=AVIERR_OK) {if (buf!=0) delete[] buf; au->iserr=true; return hr;}
    hr = AVIStreamSetFormat(au->as,0,&au->wfx,sizeof(WAVEFORMATEX));
    if (hr!=AVIERR_OK) {if (buf!=0) delete[] buf; au->iserr=true; return hr;}
  }
  //
  // now we can write the data
  unsigned long numbytes = wav->dat.size;
  unsigned long numsamps = numbytes*8 / au->wfx.wBitsPerSample;
  HRESULT hr = AVIStreamWrite(au->as,au->nsamp,numsamps,wav->dat.data,numbytes,0,NULL,NULL);
  if (buf!=0) delete[] buf;
  if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
  au->nsamp =numsamps; return S_OK;
}        unsigned int FormatAviMessage(HRESULT code, char *buf,unsigned int len)
{ const char *msg="unknown avi result code";
  switch (code)
  { case S_OK: msg="Success"; break;
    case AVIERR_BADFORMAT: msg="AVIERR_BADFORMAT: corrupt file or unrecognized format"; break;
    case AVIERR_MEMORY: msg="AVIERR_MEMORY: insufficient memory"; break;
    case AVIERR_FILEREAD: msg="AVIERR_FILEREAD: disk error while reading file"; break;
    case AVIERR_FILEOPEN: msg="AVIERR_FILEOPEN: disk error while opening file"; break;
    case REGDB_E_CLASSNOTREG: msg="REGDB_E_CLASSNOTREG: file type not recognised"; break;
    case AVIERR_READONLY: msg="AVIERR_READONLY: file is read-only"; break;
    case AVIERR_NOCOMPRESSOR: msg="AVIERR_NOCOMPRESSOR: a suitable compressor could not be found"; break;
    case AVIERR_UNSUPPORTED: msg="AVIERR_UNSUPPORTED: compression is not supported for this type of data"; break;
    case AVIERR_INTERNAL: msg="AVIERR_INTERNAL: internal error"; break;
    case AVIERR_BADFLAGS: msg="AVIERR_BADFLAGS"; break;
    case AVIERR_BADPARAM: msg="AVIERR_BADPARAM"; break;
    case AVIERR_BADSIZE: msg="AVIERR_BADSIZE"; break;
    case AVIERR_BADHANDLE: msg="AVIERR_BADHANDLE"; break;
    case AVIERR_FILEWRITE: msg="AVIERR_FILEWRITE: disk error while writing file"; break;
    case AVIERR_COMPRESSOR: msg="AVIERR_COMPRESSOR"; break;
    case AVIERR_NODATA: msg="AVIERR_READONLY"; break;
    case AVIERR_BUFFERTOOSMALL: msg="AVIERR_BUFFERTOOSMALL"; break;
    case AVIERR_CANTCOMPRESS: msg="AVIERR_CANTCOMPRESS"; break;
    case AVIERR_USERABORT: msg="AVIERR_USERABORT"; break;
    case AVIERR_ERROR: msg="AVIERR_ERROR"; break;
  }
  unsigned int mlen=(unsigned int)strlen(msg);
  if (buf==0 || len==0) return mlen;
  unsigned int n=mlen; if (n 1>len) n=len-1;
  strncpy(buf,msg,n); buf[n]=0;
  return mlen;
}
使用方式(未壓縮AVI)
 
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 const char *fns[] = {"1.bmp","2.bmp","3.bmp","4.bmp","5.bmp"};
 HAVI avi = CreateAvi("test.avi",1000,NULL); // 1000ms is the period between frames
 for (int i=0; i    壓縮AVI
 
const char *fns[] = {"1.bmp","2.bmp","3.bmp","4.bmp","5.bmp"};
HAVI avi = CreateAvi("test.avi",1000,NULL);
for (int i=0; i    感謝RaynorPao提供資料    發表人 - taishyang 於 2003/07/09  01:31:54
        
MilesWamg
一般會員


發表:18
回覆:37
積分:11
註冊:2003-02-07

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-07-10 17:41:24 IP:163.18.xxx.xxx 未訂閱
小弟嘗試以上方法 但於 AddAviFrame(avi,hbm); 與 CloseAvi(avi); 於COMPLIER 時會 Link Error 如下 [Linker Error] Unresolved external 'CloseAvi(void *)' referenced from D:CAPTURE\2CAMERA\USBCAP.OBJ 請問何處有問題? 請前輩指點!!
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-07-10 18:11:04 IP:140.135.xxx.xxx 未訂閱
MilesWamg您好:   我不會有這樣的情況發生耶,您試試先把BMP2AVI獨立出來   就可以知道是哪邊出了問題    順心 <>~我也是在學習的階段,所以請您多多見諒與指教~
MilesWamg
一般會員


發表:18
回覆:37
積分:11
註冊:2003-02-07

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-07-10 18:24:12 IP:163.18.xxx.xxx 未訂閱
可以請您寄此一範例給小弟試試看嗎? thanks!!
MilesWamg
一般會員


發表:18
回覆:37
積分:11
註冊:2003-02-07

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-07-10 19:32:46 IP:163.18.xxx.xxx 未訂閱
太感謝了!!真的是 #include "avi_utils.cpp" 的問題 因為我使用 #include "avi_utils.h"才不行 現在可以轉了!!    但是程式存大bmp的速度不快 故此一方法可以save但可能解析度要下降 才可達每秒30Frame     發表人 -
even
一般會員


發表:12
回覆:17
積分:5
註冊:2003-07-18

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-08-30 20:00:22 IP:210.202.xxx.xxx 未訂閱
請問一下大大們.... 在這個程式中如果要將自已程式中所產的連續的bmp圖放入fns這個陣列中.. 該如何放丫??? 如....... ............. String name=0; name=0+frame_no+".bmp";//frame_no為陣列裡的索引值... bmp->SaveToFile(name); fns[frame_no]=name;//?????該如何放呢< >< >
系統時間:2024-04-27 8:19:30
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!