2012-08-17 73 views
0

感謝您的幫助,我是能夠尋找正確的話,利用DirectShow好一點。 我發現了一個教程如何使用SampleGrabber對象的位置: http://msdn.microsoft.com/en-us/library/windows/desktop/dd407288%28v=vs.85%29.aspxC++ Builder的:視頻轉換成PNG快照與DirectShow的

我可以實現它,修改它了一點,所以它不只是保存第一幀,但每幀爲PNG。爲此我使用電暈。 但是,我只是猜對了一些事情,並不知道哪些緩衝區包含我的數據和哪種形式。

所以,我基本上有3個問題:
我使用SavePNG吧?由此產生的圖像顛倒!
我可以使用連接到相機的視頻替換視頻的BaseFilter嗎?
包含pBuffer我的Imagedata,所以我可以通過簡單地鍵入pBuffer [123]來獲得rgb-byte-informations?

我使用Embarcadero公司的C++ - 生成器(XE2 16)。

這裏是我發現在網站上的代碼,有點改進(錯誤處理的更好的視野中刪除的每個小時後= ...有一個失敗的檢查):

void __fastcall TForm1::btn_kameraClick(TObject *Sender) 
{ 
HRESULT hr = S_OK; 
    IGraphBuilder *pGraph = NULL; 
    IMediaControl *pControl = NULL; 
    IMediaEventEx *pEvent = NULL; 
    IBaseFilter *pGrabberF = NULL; 
    ISampleGrabber *pGrabber = NULL; 
    IBaseFilter *pSourceF = NULL; 
    IEnumPins *pEnum = NULL; 
    IPin *pPin = NULL; 
    IBaseFilter *pNullF = NULL; 
    BYTE *pBuffer = NULL; 

    hr = CoCreateInstance(CLSID_FilterGraph, NULL,CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pGraph)); 
    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl)); 
    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pEvent)); 
    hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pGrabberF)); 
    hr = pGraph->AddFilter(pGrabberF, L"Sample Grabber"); 
    hr = pGrabberF->QueryInterface(IID_PPV_ARGS(&pGrabber)); 

    AM_MEDIA_TYPE mt; 
    ZeroMemory(&mt, sizeof(mt)); 
    mt.majortype = MEDIATYPE_Video; 
    mt.subtype = MEDIASUBTYPE_RGB24; 

    hr = pGrabber->SetMediaType(&mt); 
    hr = pGraph->AddSourceFilter(L"C:/Users/Julian/Desktop/homogenität/1,1x_2,7y.mpg", L"Source", &pSourceF); 
    hr = pSourceF->EnumPins(&pEnum); 
    while (S_OK == pEnum->Next(1, &pPin, NULL)) 
    { 
     hr = ConnectFilters(pGraph, pPin, pGrabberF); 
     SafeRelease(&pPin); 
     if (SUCCEEDED(hr))break; 
    } 
    hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pNullF)); 
    hr = pGraph->AddFilter(pNullF, L"Null Filter"); 
    hr = ConnectFilters(pGraph, pGrabberF, pNullF); 
    hr = pGrabber->SetOneShot(TRUE); 
    hr = pGrabber->SetBufferSamples(TRUE); 
    long evCode=0; 
    long cbBuffer=0; 
    hr = pControl->Run(); 
    hr = pEvent->WaitForCompletion(INFINITE, &evCode); 
    hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL); 
    pBuffer = (BYTE*)CoTaskMemAlloc(cbBuffer); 
    hr = pGrabber->GetConnectedMediaType(&mt); 

    CComQIPtr< IMediaSeeking, &IID_IMediaSeeking > pSeeking(pGraph); 


// for(int i=0;i<10;i++){ 
    bool hui=true;int i=0; 
    while(hui){ 
    REFERENCE_TIME Start = i * UNITS; 
    hr = pSeeking->SetPositions(&Start, AM_SEEKING_AbsolutePositioning,NULL, AM_SEEKING_NoPositioning); 
// Sleep(10); 
    hr = pEvent->WaitForCompletion(INFINITE,&evCode); 
    if(hr!=0)hui=false; 
    hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer); 
    if ((mt.formattype == FORMAT_VideoInfo) &&(mt.cbFormat >= sizeof(VIDEOINFOHEADER)) &&(mt.pbFormat != NULL)) 
    { 
     VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)mt.pbFormat; 

//  hr = WriteBitmap(("hui"+(String)i+".bmp").c_str(), &pVih->bmiHeader, mt.cbFormat - SIZE_PREHEADER, pBuffer, cbBuffer); 
     hr = SavePNG(i,pBuffer, pVih->bmiHeader.biWidth, pVih->bmiHeader.biHeight); 
    } 
    else hr = VFW_E_INVALIDMEDIATYPE; 
    i++; 
    } 
    FreeMediaType(mt); 

done: 
    CoTaskMemFree(pBuffer); 
    SafeRelease(&pPin); 
    SafeRelease(&pEnum); 
    SafeRelease(&pNullF); 
    SafeRelease(&pSourceF); 
    SafeRelease(&pGrabber); 
    SafeRelease(&pGrabberF); 
    SafeRelease(&pControl); 
    SafeRelease(&pEvent); 
    SafeRelease(&pGraph); 

} 
bool SavePNG(int i, Byte* m_pImageData,long m_Width,long m_Height) 
{ 
    // Make sure there is image data 

    if (!m_pImageData) 
     return false; 

    stringstream FilePath; 
    FilePath << "hui"<< i<<".png"; 
    // Create a corona image 
    corona::Image* pImage = corona::CreateImage(m_Width, m_Height, corona::PF_R8G8B8, m_pImageData); 

    // Make sure the image was created 
    if (!pImage) 
     return false; 

    // Save the image to a PNG file 
    corona::SaveImage(FilePath.str().c_str(), corona::FF_PNG, pImage); 

    // Delete the corona image 
    delete pImage; 

    // Nothing went wrong 
    return true; 
} 

希望我沒有做任何可怕的錯誤......我真的試圖研究一切^^ 有人知道我的3個問題嗎? 我在這裏發現了一些非常錯誤的東西,我也很感謝你告訴我,所以我可以修復和改進。

問候, 朱利安

回答

0

現在,當你在24位RGB格式的視頻幀,所有你需要的是壓縮到PNG。你必須選擇在這裏:

可能,C++工具的詳情具有本地類覆蓋PNG爲好。

P.S.您使用的DirectShow API不是DirectX,它是Windows核心SDK的一部分。

+0

好了,我用了libary電暈從這裏:http://corona.sourceforge.net/ 我不能完全的數字,libpng的出來,電暈似乎有點更容易使用... 好,目前我的照片是顛倒的......我希望有人可能知道爲什麼......你知道我的其他2個問題嗎? 也就是說,如果pBuffer中的字節直接表示色值或者我是否可以用連接到相機而不是視頻文件的Basefilter替換pSourceF? – Julian 2012-08-18 20:53:01

+0

您使用'MEDIASUBTYPE_RGB24'。這意味着每個像素都有三個字節:紅色,綠色和藍色。從下到上的順序是Windows中RGB位圖的典型特徵(除非'VIDEOINFOHEADER.bmiHeader.biHeight'爲負值並指示從上到下的位圖)。也許你需要在提交給你使用的庫之前顛倒順序,否則,請指出正確的順序。 – 2012-08-18 21:06:28

+0

非常感謝!是的,似乎有一個TPngImage對象與LoadFromStream方法...也許這也會做...我可能不得不扭轉圖像線的順序...或者是否有可能否定biHeight-Value來翻轉圖像?^^所以,剩下的就是希望我的相機爲這個^^提供一個兼容的輸出順便說一下:我現在真的在抓每一幀嗎?當我用VLC-Player轉換視頻時,我得到的圖片數量略有不同...... – Julian 2012-08-18 21:20:57