WebCamStream->Panel Funzt, und wie bekomme ich das in ein Image ?!



  • //---------------------------------------------------------------------------
    #include <vcl.h>
    
    #pragma hdrstop
    
    #include "Unit1.h"
    #include "WDMCap.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //
    // Global data
    //
    PCWDMCapture pcap=NULL;
    PCSampleCallbackSink pbsink=NULL;
    
    CALLBACKINFO cb={0};
    long lWidth;
    long lHeight ;
    
    Graphics::TBitmap *Bitmap3 = new Graphics::TBitmap;
    //Bitmap3->Bpp = 24;
    //B/itmap3->Width = 500;
    //Bitmap3->Height = 500;
    
    //---------------------------------------------------------------------------
       // This function will be called whenever a captured still needs to be
        // displayed in the preview window.  It is called initially within
        // CopyBitmap() to display the captured still, but it is also called
        // whenever the main dialog needs to repaint and when we transition
        // from video capture mode back into still capture mode.
        //
        BOOL DisplayCapturedBits(HWND hwndStill,BYTE *pBuffer, BITMAPINFOHEADER *pbih)
        {
            // put bits into the preview window with StretchDIBits
            //
             RECT rc;
            ::GetWindowRect( hwndStill, &rc );
            long lStillWidth = rc.right - rc.left;
            long lStillHeight = rc.bottom - rc.top;
    
            HDC hdcStill = GetDC( hwndStill );
            PAINTSTRUCT ps;
            BeginPaint(hwndStill, &ps);
    
            SetStretchBltMode(hdcStill, COLORONCOLOR);
            StretchDIBits( 
                hdcStill, 0, 0, 
                lStillWidth, lStillHeight, 
                0, 0, lWidth, lHeight, 
                pBuffer, 
                (BITMAPINFO*) pbih, 
                DIB_RGB_COLORS, 
                SRCCOPY );
    
            EndPaint(hwndStill, &ps);
            ReleaseDC( hwndStill, hdcStill );    
    
            return TRUE;
        }
    //---------------------------------------------------------------------------
       // This is the implementation function that writes the captured video
        // data onto a bitmap on the user's disk.
        //
       BOOL CopyBitmap(HWND hwndStill,double dblSampleTime, BYTE * pBuffer, long lBufferSize)
        {
    
             // figure out where to capture to
            //
        long m_nCapTimes=1;
        TCHAR m_szCapDir[MAX_PATH]="C:\\"; // the directory we want to capture to
        TCHAR m_szSnappedName[MAX_PATH];
        BOOL bFileWritten;
            TCHAR m_ShortName[MAX_PATH];
            wsprintf( m_szSnappedName, TEXT("%sStillCap%4.4ld.bmp"),
                      m_szCapDir, m_nCapTimes );
            wsprintf( m_ShortName, TEXT("StillCap%4.4ld.bmp"),
                      m_nCapTimes);
    
            // write out a BMP file
            //
            HANDLE hf = CreateFile(
                m_szSnappedName, GENERIC_WRITE, 0, NULL,
                CREATE_ALWAYS, NULL, NULL );
    
            if( hf == INVALID_HANDLE_VALUE )
                return 0;
    
            // write out the file header
            //
            BITMAPFILEHEADER bfh;
            memset( &bfh, 0, sizeof( bfh ) );
            bfh.bfType = 'MB';
            bfh.bfSize    = sizeof( bfh ) + lBufferSize + sizeof( BITMAPINFOHEADER );
            bfh.bfOffBits = sizeof( BITMAPINFOHEADER )  + sizeof( BITMAPFILEHEADER );
    
            DWORD dwWritten = 0;
            WriteFile( hf, &bfh, sizeof( bfh ), &dwWritten, NULL );
    
            // and the bitmap format
            //
            BITMAPINFOHEADER bih;
            memset( &bih, 0, sizeof( bih ) );
            bih.biSize = sizeof( bih );
            bih.biWidth = lWidth;
            bih.biHeight = lHeight;
            bih.biPlanes = 1;
            bih.biBitCount = 24;
    
            dwWritten = 0;
            WriteFile( hf, &bih, sizeof( bih ), &dwWritten, NULL );
    
            // and the bits themselves
            //
            dwWritten = 0;
            WriteFile( hf, pBuffer, lBufferSize, &dwWritten, NULL );
            CloseHandle( hf );
            bFileWritten = TRUE;
    
            // Display the bitmap bits on the dialog's preview window
            DisplayCapturedBits(hwndStill,pBuffer, &bih);
    
            // Save bitmap header for later use when repainting the window
            memcpy(&(cb.bih), &bih, sizeof(bih));        
    
            return 0;
        }
    //---------------------------------------------------------------------------
    void FASTCALL DoRenderStream(double dblSampleTime, BYTE * pBuffer, long lBufferSize,long _lWidth,long _lHeight)
    {
       lWidth=_lWidth;
       lHeight=_lHeight;
    
            // Since we can't access Windows API functions in this callback, just
            // copy the bitmap data to a global structure for later reference.
            cb.dblSampleTime = dblSampleTime;
            cb.lBufferSize   = lBufferSize;
    
            // If we haven't yet allocated the data buffer, do it now.
            // Just allocate what we need to store the new bitmap.
            if (!cb.pBuffer)
                cb.pBuffer = new BYTE[lBufferSize];
    
            // Copy the bitmap data into our global buffer
            if (cb.pBuffer)
                memcpy(cb.pBuffer, pBuffer, lBufferSize);
    
            // Post a message to our application, telling it to come back
            // and write the saved data to a bitmap file on the user's disk.
            PostMessage(Form1->Handle, WM_CAPTURE_BITMAP, 0, 0L);
    }
    //---------------------------------------------------------------------------
    void FASTCALL _OnBufferingDataSink(void* pev)
    {
      int ev=(int)&pev;
      MessageBox(0,"",IntToStr(ev).c_str(),0);
      if(1==ev)
          Form1->Caption="WDMUtils test program :Buffering data...";
      else
           Form1->Caption="WDMUtils test program";
       Form1->Repaint();
    }
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
       pcap=CWDMCapture::GetWDMCapClassInstance(Handle,WDM_CAPTURE_STREAM);
         if(NULL!=pcap)
        {
            HRESULT hr;
            pcap->OnDataBuffering =_OnBufferingDataSink;
    
            pbsink=new CSampleCallbackSink();
            pbsink->pCallbackSink=DoRenderStream;
    
            // Create DirectShow graph and start capturing video
            hr = pcap->StartVideo(pbsink,Panel1->Handle);
            if (FAILED (hr))
            {
                pcap->CloseInterfaces();
                DestroyWindow(pcap->Handle());
            }
            else
            {
                // Don't display the main window until the DirectShow
                // preview graph has been created.  Once video data is
                // being received and processed, the window will appear
                // and immediately have useful video data to dispay.
                // Otherwise, it will be black until video data arrives.
                  ShowWindow(pcap->Handle(), TRUE);
           }
        }
    
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::WndProc( Messages::TMessage &Message )
    {
      switch( Message.Msg )
      {
           case WM_GRAPHNOTIFY:
                 if(NULL!=pcap)
                    {
                     pcap->HandleGraphEvent((WPARAM)Message.WParam,(LPARAM)Message.LParam);
                    }
                break;
    
            case WM_SIZE:
                if(NULL!=pcap)
                {
                    pcap->ResizeVideoWindow();
                }
                break;
    
            case WM_WINDOWPOSCHANGED:
                if(NULL!=pcap)
                  {
                    pcap->ChangePreviewState(!(IsIconic(Handle)));
                  }
                break;
    
            case WM_CLOSE:            
                // Hide the main window while the graph is destroyed
                if(NULL!=pcap)
                {
                    ShowWindow(pcap->Handle(), SW_HIDE);
                    pcap->CloseInterfaces();  // Stop capturing and release interfaces
                }
                break;
    
            case WM_DESTROY:
                PostQuitMessage(0);
    
            // Field the message posted by our SampleGrabber callback function.
            case WM_CAPTURE_BITMAP:
                ///    CopyBitmap(Panel2->Handle,cb.dblSampleTime, cb.pBuffer, cb.lBufferSize);
                   CopyBitmap(Form1->Handle,cb.dblSampleTime, cb.pBuffer, cb.lBufferSize);
                //  Image1->Picture->Bitmap =  cb.pBuffer;
                // Image1->Picture->DefaultHandler(Panel2->DefaultHandler());
    
              //  PaintBox1->Canvas->Pixels[ 1 ][ 1 ] = Panel2->;
                     break;
      } // switch
    
      TForm::WndProc( Message );
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
      delete pbsink;
      delete pcap;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormPaint(TObject *Sender)
    {
      if(!IsIconic(Handle))
            // Update the bitmap preview window, if we have
            // already captured bitmap data
            DisplayCapturedBits(Panel2->Handle,cb.pBuffer, &(cb.bih));
    
          //  DisplayCapturedBits(Image1,cb.pBuffer, &(cb.bih));
    
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
    {
        // Free the memory allocated for our bitmap data buffer
        if (cb.pBuffer != 0)
        {
            delete cb.pBuffer;
            cb.pBuffer = 0;
        }
    }
    //---------------------------------------------------------------------------
    

    das teil kopiert den live webcam stream in ein panel, wie bekomme ich jetzt
    die roh daten in ein image ? so das ich mit den pixeln weiter arbeiten kann
    bin ihrgend wie zu dumm das umzuschreiben kann zwar den stream von dem ding in welchem format auch immer zb aufs form oder auf ein memo feld laden etc..
    bekomme aber trozdem net die einzelnen pixel daten 😞

    hilfe !



  • //---------------------------------------------------------------------------
    #ifndef WDMCapH
    #define WDMCapH
    
    //---------------------------------------------------------------------------
    #define __comcat_h__ // EXCLUDE COMCAT.H AS IT COLLIDES WITH QEDIT.H
    //---------------------------------------------------------------------------
    #include <basetsd.h>
    #include <malloc.h>
    #include <dshow.h>
    #include <qedit.h>
    #include <uuids.h>
    #include <amstream.h>
    
    #if defined(WIN32)
    #define FASTCALL  __fastcall
    #define _CLOSURE_ __closure
    #else
    #define FASTCALL  /*__fastcall*/
    #define _CLOSURE_ /*__closure*/
    #endif
    //---------------------------------------------------------------------------
    // Application-defined message to notify application's window (hosting output) of filtergraph events
    #define WM_GRAPHNOTIFY  (WM_APP+15)
    //---------------------------------------------------------------------------
    #ifdef _DLL_BUILD_
     #define _DLL_EXPOSURE_  __declspec(dllexport)
    #else
     #define _DLL_EXPOSURE_  __declspec(dllimport)
    #endif
    
    #ifdef __cpluplus
    extern "C"{
    #endif
    //---------------------------------------------------------------------------
    enum PLAYSTATE {Stopped, Paused, Running, Init};
    //---------------------------------------------------------------------------
    enum WDM_CAPTURE_TYPE {
                           WDM_CAPTURE_PREVIEW,//Preview in window only
                           WDM_CAPTURE_STREAM, //no preview, render to Memory stream
                           WDM_CAPTURE_PREVIEW_STREAM, //preview and render to Memory stream
                           WDM_CAPTURE_AVIFILE,//no preview, capture to avi file
                           WDM_CAPTURE_PREVIEW_AVIFILE //preview and capture to avifile at the same time
                          };
    //---------------------------------------------------------------------------
    typedef void FASTCALL (*PNotificationSink)(void*);
    //---------------------------------------------------------------------------
    typedef void FASTCALL (*PCBUFFERCALLBACKSINK)(double,BYTE*,long,long,long);
    typedef void FASTCALL (*PCDEVICEENUMCALLBACK) (char*);
    //---------------------------------------------------------------------------
    //Buffer sink used when capturing to a stream
    typedef struct tagSampleRenderSink
    {
     PCBUFFERCALLBACKSINK pCallbackSink;
    }CSampleCallbackSink,*PCSampleCallbackSink;
    
    typedef void FASTCALL (*DRAWCALLBACK)(HANDLE);
    //---------------------------------------------------------------------------
    typedef class _DLL_EXPOSURE_ tagWDMCapture
    {
     private:
      HWND ghApp;
      DWORD g_dwGraphRegister;
      WDM_CAPTURE_TYPE captype;
      IVideoWindow  * g_pVW;
      IMediaControl * g_pMC;
      IMediaEventEx * g_pME;
      IAMVfwCaptureDialogs *g_pDlg;
      IGraphBuilder * g_pGraph;
      IBaseFilter* g_pSrcFilter;
      ICaptureGraphBuilder2 * g_pCapture;
      PLAYSTATE g_psCurrent;
      IConfigAviMux *g_pConfigAviMux;
      //stream capture stuff
      IBaseFilter* pGrabberBaseFilter;
      ISampleGrabber *pSampleGrabber;
      char* g_Capturefilename;
      PCSampleCallbackSink g_BufferCallbackSink;
      tagWDMCapture(WDM_CAPTURE_TYPE=WDM_CAPTURE_PREVIEW);
      tagWDMCapture(HWND,WDM_CAPTURE_TYPE=WDM_CAPTURE_PREVIEW);
     protected:
      void Msg(TCHAR *szFormat, ...);
      // Remote graph viewing functions
    #ifdef REGISTER_FILTERGRAPH
      HRESULT FASTCALL AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister);
      void FASTCALL RemoveGraphFromRot(DWORD pdwRegister);
    #endif
      void FASTCALL RegisterForDevChange(void);
      void FASTCALL UnregisterForDevChange(void);
     public:
      static tagWDMCapture* GetWDMCapClassInstance(WDM_CAPTURE_TYPE=WDM_CAPTURE_PREVIEW);
      static tagWDMCapture* GetWDMCapClassInstance(HWND,WDM_CAPTURE_TYPE=WDM_CAPTURE_PREVIEW);
      ~tagWDMCapture(void);
      HRESULT FASTCALL GetInterfaces(void);
      /*
      if capturing to an output file,you can choose to render the file to a MultiMediaStream
      */
    //if ur going to use WDM_CAPTURE_AVIFILE u need to provide a target filename
    //if u r using WDM_CAPTURE_STREAM then the param is a buffer adress
      HRESULT FASTCALL StartVideo(void* psink=NULL,HWND hPreview=NULL);
      HRESULT FASTCALL StopPreview(bool final=true);
      HRESULT FASTCALL PausePreview(void);
      HRESULT FASTCALL ResumePreview(void);
      HRESULT FASTCALL FindCaptureDevice(IBaseFilter ** ppSrcFilter);
      HRESULT FASTCALL SetupVideoWindow(void);
      HRESULT FASTCALL ChangePreviewState(int nShow);
      HRESULT FASTCALL HandleGraphEvent(WPARAM,LPARAM);
      HRESULT FASTCALL CaptureFilterDlg(void);
      HRESULT FASTCALL CapturePinDlg(void);
      const HWND FASTCALL Handle(void)const;
      void FASTCALL CloseInterfaces(void);
      void FASTCALL ResizeVideoWindow(void);
      HRESULT FASTCALL SetFullScreen(BOOL FullScreenMode);
      void FASTCALL setHandle(HWND);
      void FASTCALL EnumCapDevices( PCDEVICEENUMCALLBACK pDeviceCallbackFunc);
      PNotificationSink OnDataBuffering;
    }CWDMCapture,*PCWDMCapture;
    //---------------------------------------------------------------------------
    #ifdef __cpluplus
    }
    #endif
    //---------------------------------------------------------------------------
    #endif
    


  • hmm doof, immer noch keine lösung gefunden, kann mir eventuell wer weiter helfen wenn ich das kompette projekt zum downloaden mal on stelle?

    der webcam stream wird via handle in die panel 1 und 2 geladen, kann den handle auch aufs form oder auf ne memo setzen dann hab ich das bild dort,

    nur wie bekomme ich das in ein image feld ? damit ich dann die einzelnen pixel abgreifen kann !?

    hat einer ne idee? komme einfach net weiter und bin ratlos



  • Also ich denke, das Problem ist, daß du ein Windows-Handle benötigst, aber gleichzeitig die Eigenschaft Canvas benutzen willst.
    Das einzige Control, das dies standardmäßig unterstützt ist TForm.

    Dann kannst du also das Bild von Form->Canvas abgreifen.

    Oder aber du baust dir ein eigenes Control abgeleitet von TCustomControl, da dies sowohl von TWinControl abgeleitet ist als auch die Eigenschaft Canvas besitzt.

    Die anderen Controls (Panel, Memo etc.) unterstützen nicht das direkte Auslesen der Pixel.

    Du kannst dann Canvas->CopyRect(...) benutzen, um die Daten in ein Image zu kopieren und dann abzuspeichern.



  • wenn ichs jetzt aufs tform lade mach mir mal bitte ein beispiel wie es in das image1 dann geht?!



  • Image1->Width = form->Width;  // hier noch passende Breite und Höhe bestimmen
    Image1->Height = form->Height; // falls Form größer als Web-Stream-Image
    Rect r = Image1->ClientRect();
    Rect r2 = Form1->ClientRect();
    
    Image1->CopyRect(r, Form1->Canvas, r2);
    

    Wenn du den letzten Parameter 'r2' veränderst, kannst du den Ausschnitt ändern bzw. das Bild strecken oder stauchen.



  • [C++ Error] Unit2.cpp(24): E2335 Overloaded 'Rect' ambiguous in this context
    [C++ Error] Unit2.cpp(24): E2379 Statement missing ;
    [C++ Error] Unit2.cpp(25): E2335 Overloaded 'Rect' ambiguous in this context
    [C++ Error] Unit2.cpp(25): E2379 Statement missing ;
    [C++ Error] Unit2.cpp(27): E2316 'CopyRect' is not a member of 'TImage'
    [C++ Error] Unit2.cpp(27): E2451 Undefined symbol 'r'
    [C++ Error] Unit2.cpp(27): E2451 Undefined symbol 'r2'

    bei rec meckert er



  • Image1->Width = Form1->Width; // hier noch passende Breite und Höhe bestimmen
    Image1->Height = Form1->Height; // falls Form größer als Web-Stream-Image
    TRect r = Image1->ClientRect();
    TRect r2 = Form1->ClientRect();
    Image1->CopyRect(r, Form1->Canvas, r2);

    ----------------------------------------------------------------

    [C++ Error] Unit2.cpp(23): E2314 Call of nonfunction
    [C++ Error] Unit2.cpp(24): E2314 Call of nonfunction
    [C++ Error] Unit2.cpp(25): E2316 'CopyRect' is not a member of 'TImage'
    [C++ Warning] Unit2.cpp(26): W8004 'r2' is assigned a value that is never used
    [C++ Warning] Unit2.cpp(26): W8004 'r' is assigned a value that is never used



  • Image1->Width = form->Width;  // hier noch passende Breite und Höhe bestimmen
    Image1->Height = form->Height; // falls Form größer als Web-Stream-Image
    TRect r = Image1->ClientRect;
    TRect r2 = Form1->ClientRect;
    
    Image1->Canvas->CopyRect(r, Form1->Canvas, r2);
    

    Warum schreibst du dein Bitmap nich gleich in das Canvas des Images?



  • geht das mit dem quellcode direct ohne rec ?



  • Ja.
    Nimm einfach das ClientRect.



  • funzt hab derzeit nur ne cpu auslastung von ca. 20-35%
    mal gucken ob ich die ihrgend wie runter bekomme dasist noch bissel viel
    gibts ihrgend wie ne möglichkeit die frame rate der cam runter zu bekomme auf 10fps oder so?



  • eins wurmt mich wenn ich die funktion raus nehme die zur speicherung der datei als bmp raus nehme funzt nix mehr

    hab das gefühl das er jedes frame auf hdd speichert und dann wieder ihrgend wie löd oder so?

    kann man den teil mit der hdd speicherung net raus nehmen ? weil den brauch ich mal garnicht..



  • http://www.keksohr.de/index.php?menu=projekt-index-cam-mca-25

    hab hier mal alles drin, quelltexte komme auch die tage 🙂
    bei fragen ins gästebuch oder via mail melden,

    gruß philip


Anmelden zum Antworten