avi保存

[戻る]
ロンブー 2008/04/28(月) 21:26:52
avi保存について教えて下さい。
aviファイルは作成できているのに中身が入ってません。

ソースを書きます。
void CAVIMonitorDlg::OnBnClickedButton1()
{
int    nSts;
int    nRet;
BOOL    check;
CString    msg;
DWORD timeCount = 0;
CString sTemp;
char    cWk0[50];
char    cPath[50];
SYSTEMTIME    tm;
long LastFrame1= m_nRecFrame;
UINT Width=1024;
UINT Height=256;
int f;

for(f=0;f<m_nRecFrame; f++){
    int ret=m_cameraControl->TransferFrame(f,image);
        }            

if(m_nRecFrame<=0){
    msg = "保存できる画像が存在しません";
    AfxMessageBox(msg,MB_OK|MB_ICONWARNING);    
    return;
        }
nSts = m_cameraControl->OnLive(FALSE);
if(nSts!=PCC_ERROR_NOERROR){
    msg = "再生モードに変更できませんでした";
    AfxMessageBox(msg,MB_OK|MB_ICONWARNING);    
    return;
        }
if(m_Execute_Live==TRUE){    
::KillTimer(GetSafeHwnd(), TIMER_MODE_LIVE);
    m_Execute_Live = FALSE;    
        }
   BeginWaitCursor();
if(m_nRecFrame>0){
  ::GetLocalTime(&tm);
sprintf(cPath,"c:%4.4d%2.2d%2.2d%",tm.wYear,tm.wMonth,tm.wDay);
CreateDirectory(cPath,NULL);
sprintf(cPath,"c:%4.4d%2.2d%2.2d%\\test.avi",tm.wYear,tm.wMonth,tm.wDay);
                
nRet = m_cameraControl->IsColor((BOOL &)check);
if(check==TRUE){        
    nSts = outavi(cPath,image,LastFrame1,Width,Height);
if(nSts>0){
    msg = "ファイルに保存できませんでした";
         AfxMessageBox(msg,MB_OK|MB_ICONWARNING);
EndWaitCursor();    
    return;
                }
    }        
  Sleep(3);
}
    m_disp_status1.SetWindowText("ファイル保存終了");
    msg = "ファイルに保存しました";
    AfxMessageBox(msg,MB_OK|MB_ICONINFORMATION);
EndWaitCursor();
}            

int CAVIDlg::outavi(char *szFName,unsigned char *out_image,long 
LastFrame1,UINT Width,UINT Height)
{
    CFile file;

    if(!file.Open(szFName, 
CFile::modeCreate|CFile::modeWrite|CFile::typeBinary)){
        return(-1);
    }

    HBITMAP        hbm2;

    BITMAPFILEHEADER bmphdr;
    BITMAPINFOHEADER bmpihdr;
    long nBufferSize = 1024*256*3;

    byte *buffer = (byte*)malloc((sizeof(bmphdr)+sizeof(bmpihdr)
+nBufferSize));

    bmphdr.bfType = ('M' << 8) | 'B';
    bmphdr.bfSize = sizeof(bmphdr) + sizeof(bmpihdr) + nBufferSize;    
    bmphdr.bfReserved1 = 0;
    bmphdr.bfReserved2 = 0;
    bmphdr.bfOffBits = sizeof(bmphdr) + sizeof(bmpihdr);

//BMP情報
    bmpihdr.biSize            = 40L;            
    bmpihdr.biWidth        = Width;        
    bmpihdr.biHeight        = Height;        
    bmpihdr.biPlanes        = 1;            
    bmpihdr.biBitCount     = 24;        
    bmpihdr.biCompression    = 0;            
    bmpihdr.biSizeImage = m_gnSizeBmpImage;
    bmpihdr.biXPelsPerMeter    = 0;    
    bmpihdr.biYPelsPerMeter    = 0;        
    bmpihdr.biClrUsed            = 0;        
    bmpihdr.biClrImportant        = 0;

    memcpy(buffer,&bmphdr,sizeof(bmphdr));
    memcpy(buffer+sizeof(bmphdr),&bmpihdr,sizeof(bmpihdr));
    for(UINT FileNo=0;FileNo<LastFrame1;FileNo++){
    
        memcpy(
            buffer+sizeof(bmphdr)+sizeof(bmpihdr),
            out_image+FileNo*Width*Height*3,
            nBufferSize);

        GetHbitmapFromMemory((BYTE*)buffer,sizeof(bmphdr)+sizeof
(bmpihdr)+nBufferSize,&hbm2);

        ImageRotate(&hbm2,ROTATE180FLIPX);

        file.Write(&bmphdr,sizeof(bmphdr));
        file.Write(&bmpihdr,sizeof(bmpihdr));
    }
    file.Close();
    free(buffer);
    return(0);
}

どこがいけないのでしょうか?
どなたかご教授下さい。

瀬戸っぷ [E-Mail] 2008/04/29(火) 00:29:01
ただのビットマップを書き出すだけでAVIファイルになるのか激しく疑問ではありますが…

>        file.Write(&bmphdr,sizeof(bmphdr));
>        file.Write(&bmpihdr,sizeof(bmpihdr));

BITMAPFILEHEADERとBITMAPINFOHEADERを書き出していますが、肝心のデータはどこで書き
出しているのでしょう?

ロンブー 2008/04/29(火) 18:51:51
瀬戸っぷさん

ありがとうございます。

このソースではAVIにならないってことですか?
データの書き込みはどのようにしたらよいのでしょうか?

file.Write(&bmphdr,sizeof(bmphdr));
file.Write(&bmpihdr,sizeof(bmpihdr));
を書き替えたらできますか?

瀬戸っぷ [E-Mail] 2008/04/30(水) 00:25:29
>このソースではAVIにならないってことですか?

書き出しているのがビットマップファイルの「ヘッダだけ」のようですけど……。
ヘッダだけで画像データは書き出していないですよね?

>データの書き込みはどのようにしたらよいのでしょうか?

AVIの出力に関しては自力で調べてください。
残念ながら私は複数枚のBMPデータからAVIファイルへの出力はやったことがありませんので。
最近(と言ってもここ3ヶ月以内)、どこかで「Webカメラの画像をAVIフアイルとして出力
したい」という内容の書き込みを見た記憶もありますが。

とりあえず、
m_cameraControlがなにものなのか、そのメンバ関数と思われるTransferFrame()の実装とか、
GetHbitmapFromMemory()やImageRotate()がなにをやっているのかも不明ですので。
# 名前から大体の予想ができなくもないですが…。

SSH 2008/05/02(金) 19:23:19
昔テスト用に作ったものです。
適当に修正して使用してください。

#include <stdio.h>
#include <stdlib.h>
#include <vfw.h>

#define LENG 10
#define WIDTH 160
#define HEIGHT 120

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
                    LPSTR lpszCmdLine,int nCmdShow)
{
    char fname[MAX_PATH];
    int nIndex,nTotalHead,nFileSize;
    AVISTREAMINFO si={streamtypeVIDEO,
                    mmioFOURCC('D','I','B',' '),
                    0,0,0,0,1,30,0,LENG,0,0,(DWORD)-
1,0,{0,0,WIDTH,HEIGHT},0,0,"ビデオ"};
    FILE *fp;
    LPBITMAPINFOHEADER pBMIHeader=NULL;
    PAVIFILE pAVIFile;
    PAVISTREAM pAVIStream;

    AVIFileInit();
    if (AVIFileOpen(&pAVIFile,"TEST01.AVI",
                            OF_CREATE | 
OF_WRITE | OF_SHARE_DENY_NONE,NULL)!=0)
    {
        return 0;
    }
    if (AVIFileCreateStream(pAVIFile,&pAVIStream,&si)!=0)
    {
        return 0;
    }
    for (nIndex=0;nIndex<LENG;nIndex++) 
    {
        wsprintf(fname,"TEST%02d.BMP",nIndex);
        if ((fp=fopen(fname,"rb"))==NULL)
        {
            break;
        }
        if (fseek(fp,0,SEEK_END)!=0)
        {
            fclose(fp);
            break;
        }
        if ((nFileSize=ftell(fp))==-1)
        {// サイズが不正
            fclose(fp);
            break;
        }
        if (fseek(fp,sizeof(BITMAPFILEHEADER),SEEK_SET)!=0)
        {//
            fclose(fp);
            break;
        }
        // ヘッダー部分は除外
        nFileSize -= sizeof(BITMAPFILEHEADER);
        // ビットマップヘッダーの取得
        pBMIHeader=(LPBITMAPINFOHEADER)realloc(pBMIHeader,nFileSize);

        if (fread(pBMIHeader,nFileSize,1,fp)!=1)
        {// 取得失敗
            fclose(fp);
            break;
        }
        fclose(fp);
        if (pBMIHeader->biClrUsed==0)
        {
            switch (pBMIHeader->biBitCount) 
            {
                case 1:nTotalHead=8;        
                        break;
                case 4:nTotalHead=64;        
                        break;
                case 8:nTotalHead=1024;        
                        break;
                case 24:nTotalHead=0;        
                        break;
                case 16:
                case 32:nTotalHead=pBMIHeader-
>biCompression==BI_RGB?12:0;break;
                default:return 0;
            }
        }
        else
        {
            nTotalHead=pBMIHeader->biClrUsed*4;
        }
        nTotalHead+=sizeof(BITMAPINFOHEADER);
        if (AVIStreamSetFormat
(pAVIStream,nIndex,pBMIHeader,nTotalHead)!=0)
        {
            break;
        }
        if (AVIStreamWrite(pAVIStream,
                            nIndex,
                            1,
                            (LPBYTE)
pBMIHeader+nTotalHead,
                            nFileSize-
nTotalHead,
                            AVIIF_KEYFRAME,
                            NULL,
                            NULL)!=0)
        {
            break;
        }
    }
    AVIStreamRelease(pAVIStream);
    AVIFileRelease(pAVIFile);
    AVIFileExit();
    if (pBMIHeader!=NULL)
    {
        free(pBMIHeader);
    }
    return 0;
}

PATIO 2008/05/09(金) 11:00:28
> このソースではAVIにならないってことですか?
> データの書き込みはどのようにしたらよいのでしょうか?

AIVファイルのフォーマットをきちんと調べてそれに従って書き出しているなら
再生も出来るはずだと思います。
再生で来ていない時点で間違っていると判断できると思います。
御自身が何処まで調べてやっているのかの説明が全く無いので
わかりませんが、AVIファイルのフォーマットが理解できていないので
あれば、きちんと理解してからプログラムを書くことをお勧めします。

あと、フォーマットの仕様書が英語しかなくても
辞書を片手に頑張れば読めると思います。
この手の技術文書は文法は素直な物しか使いませんし。

ソフトウエアに限らずですけれど、最新の情報は英語で
提供されているケースが結構多いので英語は必須と思ったほうが良いです。

古いスレッドには追加発言できません。