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

請問讀avi檔進來在image上顯示怎麼沒多少記憶體就吃光光了

尚未結案
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-06-02 17:33:20 IP:218.175.xxx.xxx 未訂閱
請問為何使用下面這個讀avi檔案的寫法~讀時間久一點的檔案~例如大概一兩分鐘的檔就會把記憶體都吃光光了~是那裡有寫錯了嗎~請各位大大幫我看一下ㄛ~謝謝各位大大  
//---------------------------------------------------------------------------
#include 
#include 
#pragma hdrstop
#include "Unit1.h"
#include "vfw.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
int i=0;
bool Frame2TImage(PAVISTREAM *gapavi,AVISTREAMINFO *avis,long miniSecond,TImage *Image1);// 從影像串流中取出相對應時間的Frame, 並秀在指定TImage的Canvas 上
bool GetVideoStream(char *szFile,PAVISTREAM *gapavi,AVISTREAMINFO *avis);                //    由 AVI 檔中取出影像串流
//(DWORD)ICQUALITY_DEFAULT;
    PAVISTREAM gapavi;
    AVISTREAMINFO avis;
static long Counter = 0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
bool GetVideoStream(char *szFile,PAVISTREAM *gapavi,AVISTREAMINFO *avis)
{
        //1 Initial the AVI library
        AVIFileInit();               //2 Open an AVI-file                    HRESULT hr;
        PAVIFILE pfile;
                
    // 讀取avi檔案
        hr = AVIFileOpen(&pfile,szFile , 0, 0L);                    if (hr != 0)
                {
            return false;
        }            //3 Getting an AVI stream
        //PAVISTREAM gapavi;  // for storage the frames of AVI
                int gcpavi;
        
        AVIFileGetStream(pfile, gapavi, 0L, 0); // 把得到的 Stream interface放在gapavi中
        
        //4. Get the stream information
                //AVISTREAMINFO avis;
                AVICOMPRESSOPTIONS  gaAVIOptions;
                LPAVICOMPRESSOPTIONS  galpAVIOptions;                                // Stream header的資訊放在 avis中
                        AVIStreamInfo(*gapavi, avis, sizeof(*avis));
                        galpAVIOptions = &gaAVIOptions;
                        // 把 gaAVIOptions的內容清為0
                        _fmemset(galpAVIOptions, 0, sizeof(AVICOMPRESSOPTIONS));
                        // 取出該 stream 的多媒體型態放在相對應的gaAVIOptions陣列中
                        galpAVIOptions->fccType = avis->fccType;                            switch(avis->fccType) {
                                case streamtypeVIDEO:
                                         galpAVIOptions->dwFlags = AVICOMPRESSF_VALID | AVICOMPRESSF_KEYFRAMES | AVICOMPRESSF_DATARATE;
                                         galpAVIOptions->fccHandler = 0;
                                           galpAVIOptions->dwQuality = (DWORD)ICQUALITY_DEFAULT;
                                         galpAVIOptions->dwKeyFrameEvery = (DWORD)-1; // Default
                                         galpAVIOptions->dwBytesPerSecond = 0;
                                         galpAVIOptions->dwInterleaveEvery = 1;                                    break;
                                default:
                                break;
                        }
            return true;
}
//---------------------------------------------------------
bool HBITMAP2TImage(HBITMAP hBitmap,TImage *Image1)
{
        BITMAP bitmap;
        Graphics::TBitmap *Bitmap1=new Graphics::TBitmap();
        Bitmap1->Handle=hBitmap;
        
        // 取得 Bmp 的 Width & Height
        GetObject(hBitmap,sizeof(BITMAP),&bitmap);
        Image1->Width=bitmap.bmWidth;
        Image1->Height=bitmap.bmHeight;            // 把 Bitmap 畫在 Image1上
        Image1->Canvas->Draw(0,0,Bitmap1);
        delete Bitmap1;
        Image1->Visible=true;
        Image1->Repaint();
        return true;
}
//---------------------------------------------------------------------------
bool Frame2TImage (PAVISTREAM *gapavi,AVISTREAMINFO *avis,long miniSecond,TImage *Image1)
{
    PGETFRAME            gapgf; // GetFrame物件            //5. 對指定的 gapavi video stream 進行解壓縮,傳回 GetFrame物件放在gapgf中
                        if (avis->fccType == streamtypeVIDEO) {
                            gapgf = AVIStreamGetFrameOpen(*gapavi, NULL);
                                if (gapgf == NULL)
                                        return false;
                        }
    //6. 對指定的時間(2th) 計算相對應的frame
                LONG lFrame;
        lFrame = AVIStreamTimeToSample(*gapavi, miniSecond);        if(!(lFrame>=AVIStreamStart(*gapavi) && lFrameTimer1->Enabled = false;
     ShowMessage("Over !");
     return false;        }            //8. Get a video frame
                BYTE                    abFormat[1024];                    LPBITMAPINFOHEADER lpbi;            // <----- the frame data
                lpbi = (LPBITMAPINFOHEADER)abFormat; // 指定 lpbi的位址
                // 傳回 Video frame的位址放在 lpbi
        lpbi =  (LPBITMAPINFOHEADER)AVIStreamGetFrame(gapgf,lFrame );            // 10. Paint Video        HBITMAP hBitmap;
    hBitmap=CreateDIBitmap( GetDC(NULL),lpbi,CBM_INIT,(BYTE *)lpbi 40,(BITMAPINFO *)lpbi,DIB_RGB_COLORS);
    HBITMAP2TImage(hBitmap,Image1);        return true;
}
//---------------------------------------------------------------------------    void __fastcall TForm1::Button2Click(TObject *Sender)
{
 Close();
}
//---------------------------------------------------------------------------    void __fastcall TForm1::Button1Click(TObject *Sender)
{        // 取出 Video Stream
    //GetVideoStream("c:\\1.avi",&gapavi,&avis);
    if(OpenDialog1->Execute())
    {
     GetVideoStream(OpenDialog1->FileName.c_str(),&gapavi,&avis);
     Timer1->Enabled = true;
     Counter = 0;
     }
    // 秀出指定的frame
    //Frame2TImage(&gapavi,&avis,5000,Image1);
  /* while(i<10000)
   {
    Frame2TImage(&gapavi,&avis,i,Image1);
    i=i 10;
     }*/
  //for(i=0;i<=6000;i=i 7)
  //{
  // Frame2TImage(&gapavi,&avis,i,Image1);
  // }
}
//---------------------------------------------------------------------------    void __fastcall TForm1::Timer1Timer(TObject *Sender)
{     //Frame2TImage(&gapavi,&avis,Counter,Image1);
 Frame2TImage(&gapavi,&avis,Counter,Image1);
 Counter  = 3 * (1000 / 30); //假設AVI一秒30Frames
}
//---------------------------------------------------------------------------
 
pwipwi
版主


發表:68
回覆:629
積分:349
註冊:2004-04-08

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-06-03 00:37:25 IP:219.84.xxx.xxx 未訂閱
大略看了下一程式碼,其中  
    HBITMAP hBitmap;
    hBitmap=CreateDIBitmap( GetDC(NULL),lpbi,CBM_INIT,(BYTE *)lpbi 40,(BITMAPINFO *)lpbi,DIB_RGB_COLORS);
    HBITMAP2TImage(hBitmap,Image1);
 
hBitmap使用後要呼叫DeleteObject去釋放他,不然記憶體愈用就愈少了。
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-06-03 17:17:47 IP:218.175.xxx.xxx 未訂閱
板主你好~因為我對是第一次接觸讀avi的部份這些程式也都是參考板上的~ 所以還不是很熟~可否教一下呼叫DeleteObject要怎麼寫呢~謝謝你~板主
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-06-03 17:28:59 IP:218.175.xxx.xxx 未訂閱
HBITMAP hBitmap;
    hBitmap=CreateDIBitmap( GetDC(NULL),lpbi,CBM_INIT,(BYTE *)lpbi 40,(BITMAPINFO *)lpbi,DIB_RGB_COLORS);
    HBITMAP2TImage(hBitmap,Image1);
DeleteObject(hBitmap);
 
我將程式改成這樣~但是跑的時候還是一樣記憶體會越來越少然後就被吃光了~請問是我加錯了還是有寫錯呢
Demo99
一般會員


發表:2
回覆:8
積分:2
註冊:2003-06-27

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-06-04 00:12:09 IP:59.112.xxx.xxx 未訂閱
您好 我實測後發現在Frame2TImage函式最後加上 gapgf->Release(); 可以釋放不少記憶體 不過還是會幾kb幾kb的慢慢增加 這部分可能要請其他大大補完了...
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-06-04 11:17:36 IP:218.175.xxx.xxx 未訂閱
嗯~謝謝大大你的幫忙~還是會慢慢吃記憶體~請問各位大大還有辦法修正的嗎~謝謝各位大大ㄛ
u9012021
一般會員


發表:21
回覆:19
積分:23
註冊:2005-01-18

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-06-05 21:25:44 IP:140.125.xxx.xxx 未訂閱
您好!    看了一下你的程式碼後發現你使用下面的SDK函式來開啟資料流  
 
gapgf = AVIStreamGetFrameOpen(*gapavi, NULL);
 
但你結束的時候沒有釋放它~你可以試試加入下面釋放記憶體的程式碼
 
AVIStreamGetFrameClose(gapgf);
 
 
這應該可以解決你的問題! 發表人 - u9012021 於 2005/06/05 21:26:59
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#8 引用回覆 回覆 發表時間:2005-06-07 19:41:35 IP:220.133.xxx.xxx 未訂閱
bool Frame2TImage (PAVISTREAM *gapavi,AVISTREAMINFO *avis,long miniSecond,TImage *Image1)
{
    PGETFRAME            gapgf; // GetFrame物件            //5. 對指定的 gapavi video stream 進行解壓縮,傳回 GetFrame物件放在gapgf中
                        if (avis->fccType == streamtypeVIDEO) {
                            gapgf = AVIStreamGetFrameOpen(*gapavi, NULL);
                                if (gapgf == NULL)
                                        return false;
                        }
    //6. 對指定的時間(2th) 計算相對應的frame
                LONG lFrame;
        lFrame = AVIStreamTimeToSample(*gapavi, miniSecond);        if(!(lFrame>=AVIStreamStart(*gapavi) && lFrameTimer1->Enabled = false;
     ShowMessage("Over !");
     return false;        }            //8. Get a video frame
                BYTE                    abFormat[1024];                    LPBITMAPINFOHEADER lpbi;            // <----- the frame data
                lpbi = (LPBITMAPINFOHEADER)abFormat; // 指定 lpbi的位址
                // 傳回 Video frame的位址放在 lpbi
        lpbi =  (LPBITMAPINFOHEADER)AVIStreamGetFrame(gapgf,lFrame );            // 10. Paint Video        HBITMAP hBitmap;        hBitmap=CreateDIBitmap( GetDC(NULL),lpbi,CBM_INIT,(BYTE *)lpbi 40,(BITMAPINFO *)lpbi,DIB_RGB_COLORS);
    HBITMAP2TImage(hBitmap,Image1);
    DeleteObject(hBitmap);    AVIStreamGetFrameClose(gapgf);        return true;
 
我將這這個部分改成你所說的這樣~不過還是會慢慢吃掉記憶體~大概兩三秒吃掉一m左右~請問是我有改錯嗎~請大大再賜教一下~謝謝你
u9012021
一般會員


發表:21
回覆:19
積分:23
註冊:2005-01-18

發送簡訊給我
#9 引用回覆 回覆 發表時間:2005-06-09 22:19:15 IP:140.125.xxx.xxx 未訂閱
您好! 測試你的程式發現~~下面這段程式有問題~~把這段程式移除測試~~記憶體不會有增加的現象~~你要判斷影片是否結束的判斷式可以用avis的資訊來判斷~~不一定要寫在函式內!!     
  
if(!(lFrame>=AVIStreamStart(*gapavi) && lFrameTimer1->Enabled = false;
       ShowMessage("Over !");
       return false;
    }
 
如果沒移除這一行~~程式好像每兩三秒就增加1K的記憶體~~並沒有像你說的每兩三秒增加1M左右~~你是否打錯字了@@
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#10 引用回覆 回覆 發表時間:2005-06-11 12:26:54 IP:220.133.xxx.xxx 未訂閱
你好~因為我有灌一些記憶體的工具常駐在我的win xp工具列~我是看大約三秒就會減少一m~所以我才說的每兩三秒增加1M左右 我將大大所說的這段code遺除掉還是會有一樣的現象~請問為什麼會這樣呢~ 可是我跑其他程式都不會有像這樣記憶體慢慢變少的情形~請各位大大賜教~謝謝
u9012021
一般會員


發表:21
回覆:19
積分:23
註冊:2005-01-18

發送簡訊給我
#11 引用回覆 回覆 發表時間:2005-06-13 20:04:36 IP:140.125.xxx.xxx 未訂閱
您好! 這個情形我沒有遇過呢~~但在我的電腦跑出來的情形跟你不一樣~~ 你可以檢查一下是否其他支援BCB的軟體是否有問題~~ 再來就要看其他大大有沒有跟你發生同樣的情形而幫解決~~ 抱歉囉~~沒幫到啥麼忙
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#12 引用回覆 回覆 發表時間:2005-06-14 10:54:51 IP:218.175.xxx.xxx 未訂閱
u9012021大大你好~可否請問你~ 你所說的要判斷影片是否結束的判斷式可以用avis的資訊來判斷~~請問該如何判斷呢~因這個程式是參考板上的~所以還不是很懂~所以想請你指教~謝謝你
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#13 引用回覆 回覆 發表時間:2005-06-14 11:01:45 IP:218.175.xxx.xxx 未訂閱
u9012021大大你好~再請問你~ 請問你是怎麼看說記憶體有無減少的呢~因為我是用另外灌的軟體看的所以不知會不會是那個不準 所以想請教你~是如何看記憶體有無減少的呢~謝謝你
u9012021
一般會員


發表:21
回覆:19
積分:23
註冊:2005-01-18

發送簡訊給我
#14 引用回覆 回覆 發表時間:2005-06-14 22:17:39 IP:140.125.xxx.xxx 未訂閱
您好! 你可以由avis.dwLength知道整段AVI可以分成多少個Frame!    至於記憶體的觀察我是使用Windows工作管理員(Ctrl + Alt + Del)效能分頁內的PF使用量來觀察的
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#15 引用回覆 回覆 發表時間:2005-06-14 22:58:27 IP:218.175.xxx.xxx 未訂閱
你好~我後來從xp記憶體管理去看也是一樣~大約兩到三秒就少了一m~還是說我跟你的設定是不一樣的所以看起來不太一樣呢~我讀的檔案是大約兩分鐘~我的timer是設1000然後timer的內部是寫這樣
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{     //Frame2TImage(&gapavi,&avis,Counter,Image1);
 Frame2TImage(&gapavi,&avis,Counter,Image1);
 Counter  = 30 * (1000 / 30); //假設AVI一秒30Frames
}
//-------------------------------------------------------------------
讓它一秒只顯示一個frame~還有大大你說的這個方式該如何做呢~因我是一秒只要一個frame~如果這個avi檔是一秒三十個frame那我是其他都不要~那這樣有辦法用你所說的~你可以由avis.dwLength知道整段AVI可以分成多少個Frame!~來做判斷嗎
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#16 引用回覆 回覆 發表時間:2005-06-15 02:52:58 IP:219.136.xxx.xxx 未訂閱
dragonhippopdc 您好:    我做了些測試後將程式修改了一下,我手邊僅有較小的 AVI 檔案,測試結果是 OK 啦,您試試看吧:
bool Frame2TImage (PAVISTREAM *gapavi,AVISTREAMINFO *avis,long miniSecond,TImage *Image1)
{
    PGETFRAME gapgf; // GetFrame物件        //5. 對指定的 gapavi video stream 進行解壓縮,傳回 GetFrame物件放在gapgf中
    if (avis->fccType == streamtypeVIDEO) {
        gapgf = AVIStreamGetFrameOpen(*gapavi, NULL);
        if (gapgf == NULL)
            return false;
    }        //6. 對指定的時間(2th) 計算相對應的frame
    LONG lFrame;
    lFrame = AVIStreamTimeToSample(*gapavi, miniSecond);        if (!(lFrame>=AVIStreamStart(*gapavi) && lFrameif(gapgf) AVIStreamGetFrameClose(gapgf);
        Form1->Timer1->Enabled = false;
//        ShowMessage("Over !");
        return false;
    }        //8. Get a video frame
    BYTE abFormat[1024];        LPBITMAPINFOHEADER lpbi;            // <----- the frame data
    lpbi = (LPBITMAPINFOHEADER)abFormat; // 指定 lpbi的位址
    // 傳回 Video frame的位址放在 lpbi
    lpbi =  (LPBITMAPINFOHEADER)AVIStreamGetFrame(gapgf,lFrame );        // 10. Paint Video
    HBITMAP hBitmap;
//    hBitmap=CreateDIBitmap( GetDC(NULL),lpbi,CBM_INIT,(BYTE *)lpbi 40,(BITMAPINFO *)lpbi,DIB_RGB_COLORS);
    HDC dc = GetDC(NULL);
    hBitmap=CreateDIBitmap(dc, lpbi, CBM_INIT, (BYTE *)lpbi 40, (BITMAPINFO *)lpbi, DIB_RGB_COLORS);
    ReleaseDC(NULL, dc);
    HBITMAP2TImage(hBitmap,Image1);
    DeleteObject(hBitmap);        AVIStreamGetFrameClose(gapgf);        return true;
}
紅色標示的部份為我修改過的地方,請特別留意一下 DC 的釋放。 7 天天敲鍵盤 v 時時按滑鼠 8
wccheng
一般會員


發表:5
回覆:4
積分:1
註冊:2005-06-11

發送簡訊給我
#17 引用回覆 回覆 發表時間:2005-06-15 12:02:29 IP:61.66.xxx.xxx 未訂閱
各位先進大家好,我用這個程式開啟一個AVI檔,雖然程式編譯沒有錯誤,但是結果還是無法正確看到影像,請問這是什麼原因?謝謝你們的回答!     發表人 - wccheng 於 2005/06/15 12:03:10
u9012021
一般會員


發表:21
回覆:19
積分:23
註冊:2005-01-18

發送簡訊給我
#18 引用回覆 回覆 發表時間:2005-06-15 21:06:42 IP:140.125.xxx.xxx 未訂閱
引言: 你好~我後來從xp記憶體管理去看也是一樣~大約兩到三秒就少了一m~還是說我跟你的設定是不一樣的所以看起來不太一樣呢~我讀的檔案是大約兩分鐘~我的timer是設1000然後timer的內部是寫這樣
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{     //Frame2TImage(&gapavi,&avis,Counter,Image1);
 Frame2TImage(&gapavi,&avis,Counter,Image1);
 Counter  = 30 * (1000 / 30); //假設AVI一秒30Frames
}
//-------------------------------------------------------------------
讓它一秒只顯示一個frame~還有大大你說的這個方式該如何做呢~因我是一秒只要一個frame~如果這個avi檔是一秒三十個frame那我是其他都不要~那這樣有辦法用你所說的~你可以由avis.dwLength知道整段AVI可以分成多少個Frame!~來做判斷嗎
您好! 我是用Timer去控制播放速度~~你可以上傳你讀取的AVI檔嗎~~正常來說應該都可以抓的到你的Frame總數!
 
lpbi =  (LPBITMAPINFOHEADER)AVIStreamGetFrame(gapgf,lFrame );
lFrame就是控制你要抓整段AVI檔的第幾個Frame 例如說你傳入avis.dwLeng的值給它~他應該會抓到你AVI影片的最後一張Frame!!
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#19 引用回覆 回覆 發表時間:2005-06-15 22:05:38 IP:218.175.xxx.xxx 未訂閱
u9012021大大你好~可是我的avi檔很大ㄟ~大約兩分鐘~可是九十幾m~所以應該沒法上傳吧
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#20 引用回覆 回覆 發表時間:2005-06-15 22:20:00 IP:218.175.xxx.xxx 未訂閱
各位大大~目前現在是改成這樣可是好像還是會有問題~真是怪ㄟ  
 
bool GetVideoStream(char *szFile,PAVISTREAM *gapavi,AVISTREAMINFO *avis)
{
        //1 Initial the AVI library
        AVIFileInit();            //2 Open an AVI-file                    HRESULT hr;
        PAVIFILE pfile;        // 讀取avi檔案
        hr = AVIFileOpen(&pfile,szFile , 0, 0L);                    if (hr != 0)
                {
            return false;
        }            //3 Getting an AVI stream
        //PAVISTREAM gapavi;  // for storage the frames of AVI
                int gcpavi;            AVIFileGetStream(pfile, gapavi, 0L, 0); // 把得到的 Stream interface放在gapavi中            //4. Get the stream information
                //AVISTREAMINFO avis;
                AVICOMPRESSOPTIONS  gaAVIOptions;
                LPAVICOMPRESSOPTIONS  galpAVIOptions;                                // Stream header的資訊放在 avis中
                        AVIStreamInfo(*gapavi, avis, sizeof(*avis));
                        galpAVIOptions = &gaAVIOptions;
                        // 把 gaAVIOptions的內容清為0
                        _fmemset(galpAVIOptions, 0, sizeof(AVICOMPRESSOPTIONS));
                        // 取出該 stream 的多媒體型態放在相對應的gaAVIOptions陣列中
                        galpAVIOptions->fccType = avis->fccType;                            switch(avis->fccType) {
                                case streamtypeVIDEO:
                                         galpAVIOptions->dwFlags = AVICOMPRESSF_VALID | AVICOMPRESSF_KEYFRAMES | AVICOMPRESSF_DATARATE;
                                         galpAVIOptions->fccHandler = 0;
                                           galpAVIOptions->dwQuality = (DWORD)ICQUALITY_DEFAULT;
                                         galpAVIOptions->dwKeyFrameEvery = (DWORD)-1; // Default
                                         galpAVIOptions->dwBytesPerSecond = 0;
                                         galpAVIOptions->dwInterleaveEvery = 1;                                    break;
                                default:
                                break;
                        }
           pfile->Release();
           AVIFileExit();
            return true;
}
//---------------------------------------------------------
bool HBITMAP2TImage(HBITMAP hBitmap,TImage *Image1)
{
        BITMAP bitmap;
        Graphics::TBitmap *Bitmap1=new Graphics::TBitmap();
        Bitmap1->Handle=hBitmap;            // 取得 Bmp 的 Width & Height
        GetObject(hBitmap,sizeof(BITMAP),&bitmap);
        Image1->Width=bitmap.bmWidth;
        Image1->Height=bitmap.bmHeight;            // 把 Bitmap 畫在 Image1上
        Image1->Canvas->Draw(0,0,Bitmap1);
        delete Bitmap1;
        //Image1->Visible=true;
        //Image1->Repaint();
        DeleteObject(hBitmap);
        return true;
}
//-------------------------------------------------------------------
bool Frame2TImage (PAVISTREAM *gapavi,AVISTREAMINFO *avis,long miniSecond,TImage *Image1)
{
    PGETFRAME            gapgf; // GetFrame物件            //5. 對指定的 gapavi video stream 進行解壓縮,傳回 GetFrame物件放在gapgf中
                        if (avis->fccType == streamtypeVIDEO) {
                            gapgf = AVIStreamGetFrameOpen(*gapavi, NULL);
                                if (gapgf == NULL)
                                        return false;
                        }
    //6. 對指定的時間(2th) 計算相對應的frame
                LONG lFrame;
        lFrame = AVIStreamTimeToSample(*gapavi, miniSecond);        if(!(lFrame>=AVIStreamStart(*gapavi) && lFrameTimer1->Enabled = false;
     ShowMessage("Over !");
     return false;        }            //8. Get a video frame
                BYTE                    abFormat[1024];                    LPBITMAPINFOHEADER lpbi;            // <----- the frame data
                lpbi = (LPBITMAPINFOHEADER)abFormat; // 指定 lpbi的位址
                // 傳回 Video frame的位址放在 lpbi
        lpbi =  (LPBITMAPINFOHEADER)AVIStreamGetFrame(gapgf,lFrame );            // 10. Paint Video        HBITMAP hBitmap;
    HDC dc = GetDC(NULL);        hBitmap=CreateDIBitmap( dc,lpbi,CBM_INIT,(BYTE *)lpbi 40,(BITMAPINFO *)lpbi,DIB_RGB_COLORS);
    ReleaseDC(NULL, dc);
    HBITMAP2TImage(hBitmap,Image1);
    DeleteObject(hBitmap);      //AVIStreamGetFrameClose(gapgf);        AVIFileExit();
    gapgf->Release();
    return true;    }    void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
 //Frame2TImage(&gapavi,&avis,Counter,Image1);
 Frame2TImage(&gapavi,&avis,Counter,Image1);
 Counter  = 30 * (1000 / 30); //假設AVI一秒30Frames     Graphics::TBitmap *bmp=new Graphics::TBitmap();
 bmp->Assign(Image1->Picture->Bitmap);
 Byte *ptr2;
 int x,y;
 bmp->PixelFormat=pf24bit;
 for ( y = 0; y < ImageHeight; y  )
     {
       ptr2 = (Byte *)bmp->ScanLine[y];
       for ( x = 0; x < ImageWidth; x  )
        {
          ccdBuffer[y*ImageWidth*3 x*3]=ptr2[x*3];
          ccdBuffer[y*ImageWidth*3 x*3 1]=ptr2[x*3 1];
          ccdBuffer[y*ImageWidth*3 x*3 2]=ptr2[x*3 2];
        }
     }      bmp=Form1->Image2->Picture->Bitmap ;
  bmp->PixelFormat=pf24bit;
   for ( y = 0; y < ImageHeight; y  )
     {
       ptr2 = (Byte *)bmp->ScanLine[y];
       for ( x = 0; x < ImageWidth; x  )
        {
          ptr2[x*3]=ccdBuffer[(239-y)*ImageWidth*3 x*3];
          ptr2[x*3 1]=ccdBuffer[(239-y)*ImageWidth*3 x*3 1];
          ptr2[x*3 2]=ccdBuffer[(239-y)*ImageWidth*3 x*3 2];
        }
     }
    bmp->Assign(bmp);    }
不過還是會有吃記憶體的現象~請問各位大大為何會這樣~
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#21 引用回覆 回覆 發表時間:2005-06-15 23:25:20 IP:219.137.xxx.xxx 未訂閱
dragonhippopdc 您好:    請不要一邊要求他人協助解決問題,卻又一邊將程式改成與主題無關的狀態,或是插入與發問原型無關的程式敘述,您要新增功能到程式裡邊,那是另外的事情,請不要在眾人設法協助您解決問題之時,將問題複雜化。    您這次貼上來的程式碼,在 Timer 程序中加入了一大段的圖像處理動作,但是卻未將相關宣告與設定列出來,而且 new 了 TBitmap 卻又沒 delete 掉,記憶體為何不會漸漸被吃光?請您說說看您到底是在協助眾人瞭解問題,以解決 "記憶體吃光" 的問題,還是在製造新的問題?    請調整一下您的作法,否則眾人提供的協助難以追上您製造問題的速度。      7 天天敲鍵盤 v 時時按滑鼠 8
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#22 引用回覆 回覆 發表時間:2005-06-16 14:32:07 IP:218.175.xxx.xxx 未訂閱
抱歉抱歉~我下次會改進~很對不起~ 我只是再再多加了將那個image重新貼在另一個image上面的動作~而那個ImageHeight=240 ImageWidth=320~至於大大你說的那個未刪除的那個 new 了 TBitmap 卻又沒 delete 掉~因為我是用它來將image1被我存到陣列中的值再重新貼到image2上~所以如果刪掉了~那這樣圖不是就顯示不出來了嗎~還是說有其他的方可以將他delete掉呢~謝謝大大你的指教~
taishyang
站務副站長


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

發送簡訊給我
#23 引用回覆 回覆 發表時間:2005-06-16 15:19:39 IP:210.68.xxx.xxx 未訂閱
dragonhippopdc您好:
引言:至於大大你說的那個未刪除的那個 new 了 TBitmap 卻又沒 delete 掉~因為我是用它來將image1被我存到陣列中的值再重新貼到image2上~所以如果刪掉了~那這樣圖不是就顯示不出來了嗎~還是說有其他的方可以將他delete掉呢
我不懂,您已經在http://www.programmer-club.com/pc2020v5/forum/ShowSameTitleN.asp?URL=N&board_pc2020=cb&index=26&id=9713&mode=&type_pc2020=sametitleLevel-2 問過同樣的問題了,且victortom(鬼翼@娃娃魚) 前輩不是也告訴您答案了嗎?
引言: 在Form的Header或者全域變數....
宣告Graphics::TBitmap *preFrame;
然後看是在Form的建構子或開AVI時....
preFrame = new Graphics::TBitmap;    Timer1Timer()
{
    ....影像相減or其他的處理....        preFrame->Assign(Image1->Picture->Bitmap);
}    要更保險一點, 在Assign()前先設定一下....
preFrame->Height = Image1->Picture->Bitmap->Height;
preFrame->Width = Image1->Picture->Bitmap->Width;
不過印象中, 應該不設定也不會有問題啦@_@"
最後, Form的Destory或解構子的地方.... preFrame先前new過就要delete掉.... new出來的東西記得要在適當的地方delete....
arisaka_matsuri
高階會員


發表:25
回覆:205
積分:231
註冊:2003-10-19

發送簡訊給我
#24 引用回覆 回覆 發表時間:2005-06-16 23:07:01 IP:140.113.xxx.xxx 未訂閱
引言: 我不懂,您已經在http://www.programmer-club.com/pc2020v5/forum/ShowSameTitleN.asp?URL=N&board_pc2020=cb&index=26&id=9713&mode=&type_pc2020=sametitleLevel-2 問過同樣的問題了,且victortom(鬼翼@娃娃魚) 前輩不是也告訴您答案了嗎?
副站還真是厲害~ 好久沒看xx了,我是路人,呵呵~^^
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#25 引用回覆 回覆 發表時間:2005-06-16 23:26:16 IP:219.137.xxx.xxx 未訂閱
dragonhippopdc 您好:    您多加了一段程式碼,而該段程序導致了新的記憶體流失問題 (雖然您沒看出來),但是您卻將這種結果歸於他人的建議未解決您原來的問題,這種作法是不妥的,這不但對解決問題沒有幫助,而且也會把您自己搞迷糊了,我個人覺得您應該要在解決問題的過程中,儘量的將有問題的程式過濾、簡化掉,而不是將它膨脹、複雜化。 建議您將新增的部份暫時移除掉,以 "原樣" 配合大家的建議來做修改與測試,並且將測試的結果做個說明,讓提出建議的諸位熱心人知道他們的建議到底是不是解決了您的問題? 您新增的部份以及您前一篇對該段的解說,存在著一些問題與誤區,您可以另開一題來發問,這樣可以讓問題單純些。 7 天天敲鍵盤 v 時時按滑鼠 8
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#26 引用回覆 回覆 發表時間:2005-06-17 12:07:47 IP:218.175.xxx.xxx 未訂閱
RedSnow大大你好~我將多加的部份拿掉變成以下這樣然後我讀一個兩分鐘的avi檔~我的timer是設1000大約吃掉十m左右~真的是我多加的那段的問題~對各位大大說聲抱歉~現在沒吃的那麼多了~請問吃十m這樣算是正常的嗎?
 
TForm1 *Form1;
int i=0;
bool Frame2TImage(PAVISTREAM *gapavi,AVISTREAMINFO *avis,long miniSecond,TImage *Image1);// 從影像串流中取出相對應時間的Frame, 並秀在指定TImage的Canvas 上
bool GetVideoStream(char *szFile,PAVISTREAM *gapavi,AVISTREAMINFO *avis);                //    由 AVI 檔中取出影像串流
//(DWORD)ICQUALITY_DEFAULT;
PAVISTREAM gapavi;
AVISTREAMINFO avis;
static long Counter = 0;
bool GetVideoStream(char *szFile,PAVISTREAM *gapavi,AVISTREAMINFO *avis)
{
        //1 Initial the AVI library
        AVIFileInit();            //2 Open an AVI-file                    HRESULT hr;
        PAVIFILE pfile;        // 讀取avi檔案
        hr = AVIFileOpen(&pfile,szFile , 0, 0L);                    if (hr != 0)
                {
            return false;
        }            //3 Getting an AVI stream
        //PAVISTREAM gapavi;  // for storage the frames of AVI
                int gcpavi;            AVIFileGetStream(pfile, gapavi, 0L, 0); // 把得到的 Stream interface放在gapavi中            //4. Get the stream information
                //AVISTREAMINFO avis;
                AVICOMPRESSOPTIONS  gaAVIOptions;
                LPAVICOMPRESSOPTIONS  galpAVIOptions;                                // Stream header的資訊放在 avis中
                        AVIStreamInfo(*gapavi, avis, sizeof(*avis));
                        galpAVIOptions = &gaAVIOptions;
                        // 把 gaAVIOptions的內容清為0
                        _fmemset(galpAVIOptions, 0, sizeof(AVICOMPRESSOPTIONS));
                        // 取出該 stream 的多媒體型態放在相對應的gaAVIOptions陣列中
                        galpAVIOptions->fccType = avis->fccType;                            switch(avis->fccType) {
                                case streamtypeVIDEO:
                                         galpAVIOptions->dwFlags = AVICOMPRESSF_VALID | AVICOMPRESSF_KEYFRAMES | AVICOMPRESSF_DATARATE;
                                         galpAVIOptions->fccHandler = 0;
                                           galpAVIOptions->dwQuality = (DWORD)ICQUALITY_DEFAULT;
                                         galpAVIOptions->dwKeyFrameEvery = (DWORD)-1; // Default
                                         galpAVIOptions->dwBytesPerSecond = 0;
                                         galpAVIOptions->dwInterleaveEvery = 1;                                    break;
                                default:
                                break;
                        }
           pfile->Release();
           AVIFileExit();
            return true;
}
//---------------------------------------------------------
bool HBITMAP2TImage(HBITMAP hBitmap,TImage *Image1)
{
        BITMAP bitmap;
        Graphics::TBitmap *Bitmap1=new Graphics::TBitmap();
        Bitmap1->Handle=hBitmap;            // 取得 Bmp 的 Width & Height
        GetObject(hBitmap,sizeof(BITMAP),&bitmap);
        Image1->Width=bitmap.bmWidth;
        Image1->Height=bitmap.bmHeight;            // 把 Bitmap 畫在 Image1上
        Image1->Canvas->Draw(0,0,Bitmap1);
        delete Bitmap1;
        //Image1->Visible=true;
        //Image1->Repaint();
        DeleteObject(hBitmap);
        return true;
}
//---------------------------------------------------------------------------
bool Frame2TImage (PAVISTREAM *gapavi,AVISTREAMINFO *avis,long miniSecond,TImage *Image1)
{
    PGETFRAME            gapgf; // GetFrame物件            //5. 對指定的 gapavi video stream 進行解壓縮,傳回 GetFrame物件放在gapgf中
                        if (avis->fccType == streamtypeVIDEO) {
                            gapgf = AVIStreamGetFrameOpen(*gapavi, NULL);
                                if (gapgf == NULL)
                                        return false;
                        }
    //6. 對指定的時間(2th) 計算相對應的frame
                LONG lFrame;
        lFrame = AVIStreamTimeToSample(*gapavi, miniSecond);        if(!(lFrame>=AVIStreamStart(*gapavi) && lFrameTimer1->Enabled = false;
     ShowMessage("Over !");
     return false;        }            //8. Get a video frame
                BYTE                    abFormat[1024];                    LPBITMAPINFOHEADER lpbi;            // <----- the frame data
                lpbi = (LPBITMAPINFOHEADER)abFormat; // 指定 lpbi的位址
                // 傳回 Video frame的位址放在 lpbi
        lpbi =  (LPBITMAPINFOHEADER)AVIStreamGetFrame(gapgf,lFrame );            // 10. Paint Video        HBITMAP hBitmap;
    HDC dc = GetDC(NULL);        hBitmap=CreateDIBitmap( dc,lpbi,CBM_INIT,(BYTE *)lpbi+40,(BITMAPINFO *)lpbi,DIB_RGB_COLORS);
    ReleaseDC(NULL, dc);
    HBITMAP2TImage(hBitmap,Image1);
    DeleteObject(hBitmap);      //AVIStreamGetFrameClose(gapgf);        AVIFileExit();
    gapgf->Release();
    return true;
}
//------------------------------------------------------------------    void __fastcall TForm1::Button2Click(TObject *Sender)
{
 Close();
}
//-------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    if(OpenDialog1->Execute())
    {
     GetVideoStream(OpenDialog1->FileName.c_str(),&gapavi,&avis);
     Timer1->Enabled = true;
     Counter = 0;
     }
}
//-------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
 Frame2TImage(&gapavi,&avis,Counter,Image1);
 Counter += 30 * (1000 / 30); //假設AVI一秒30Frames
}
//-------------------------------------------------------------------
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#27 引用回覆 回覆 發表時間:2005-06-17 12:38:26 IP:218.19.xxx.xxx 未訂閱
dragonhippopdc 您好:    我測試過後與我原先測的結果差不多,但是您竟然會有吃掉 10MB 的問題?因此我猜想可能是您對記憶體佔用流失的認知上有誤區,您看到的大概是那個兩分鐘的 avi 檔案被載入後所佔用的空間變化,您可以換個方式來測試您的程式:另設一個按鈕作重播的動作,例如:
void __fastcall TForm1::Button3Click(TObject *Sender)
{
    Timer1->Enabled = true;
    Button13->Enabled = false;
    Counter = 0;
}
同時您也可以將 ShowMessage("Over !"); 改成 Button13->Enabled = true,以方便操作。 當您第一次使用 Button1 載入檔案併播放完畢之後,請透過工作管理員查看您的程式佔用記憶體的狀態,然後點點擊上述新增按鈕,重複播放 avi 數次,每次都記下記憶體佔用情形,這樣子應該就可以瞭解記憶體是被佔用還是流失掉了,程式佔用記憶體是正常的,程式結束 (或程序結束、或呼叫釋放函數) 後可以正常釋回就 OK 了,但若有流失的情形,那就要抓出臭蟲,然後幹掉它! 7 天天敲鍵盤 v 時時按滑鼠 8 發表人 - RedSnow 於 2005/06/17 12:42:41
dragonhippopdc
一般會員


發表:45
回覆:51
積分:19
註冊:2005-01-15

發送簡訊給我
#28 引用回覆 回覆 發表時間:2005-06-17 18:00:37 IP:218.175.xxx.xxx 未訂閱
謝謝RedSnow大大你的細心解答~真的是avi 檔案被載入後所佔用的空間~我重覆試了兩三次~記憶體都沒有再減少~謝謝各位大大的幫忙
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#29 引用回覆 回覆 發表時間:2005-06-17 18:24:15 IP:218.19.xxx.xxx 未訂閱
dragonhippopdc 您好:    很高興知道您確認了是記憶體的佔用而不是流失,相信再有類似狀況時,您已經知道該如何去驗證了,祝您順心~      7 天天敲鍵盤 v 時時按滑鼠 8
wccheng
一般會員


發表:5
回覆:4
積分:1
註冊:2005-06-11

發送簡訊給我
#30 引用回覆 回覆 發表時間:2005-06-17 23:43:34 IP:61.66.xxx.xxx 未訂閱
各位先進我用同樣的程式,但是我不能開啟AVI檔(編譯沒有錯誤),不知道這到底是什麼原因?謝謝回答,感激。
[<<] [1] [>>]
系統時間:2024-05-19 8:25:53
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!