Stream übermalen / überschreiben



  • Hallo,

    würde gerne nen TExt über meinen WebCam-Stream schreiben ... das Problem ist nur, dass wenn ich DrawText verwende, der TExt unter dem Stream liegt und man ihn deshalb nicht sehen kann.

    Wie kann ich die Hierachy ändern ??? Oder geht das nur mit OpenGL bzw. DirectX vernünftig ???

    Danke euch.
    Romeo-G ...

    P.S.: Würde uach gerne irgendwelche geometrische Formen drüber malen ... geht das auch anders als mit OpenGL oder DirectX



  • Geht es direkt um die Anzeige? Wie zeigst du die Bilder der WebCam an?



  • Ich verweise auf den Thread "WebCam die 2." ... die Bilder werden in nem ganz normalen Win32-Anwendungs-Fenster dargestellt ... Ja nochmal, das Problem ist, dass in dem gleichen FEnster (praktisch wie bei Photoshop LAyern) der Text unter dem Strem liegt und man deshalb nichts sieht ... er wird ja schließlich verdeckt.



  • Du hast aber schon direkt das Handle des CaptureWnds angegeben, oder?
    Falls das Capture direkt als Overlay (siehst du das Bild auf einem ScreenShot noch?) angezeigt werden wird es wohl schwierig - habe in diesem Gebiet aber keine Erfahrung. Also kann auch nur Müll sein, was ich geschrieben habe 🤡



  • Also, dann will ich mal den Code veröffentlichen:

    #include<stdio.h>  
    #include <windows.h> 
    #include <vfw.h> 
    
    #include <gl/glu.h>        
    #include<gl/gl.h>           
    #include<gl/glaux.h>         
    
    #define WIN32_LEAN_AND_MEAN
    #define VC_LEANMEAN              
    #define ID_BUTTON_FOTO    1 
    #define ID_BUTTON_CLOSE    2 
    #define ID_VIDEO_WINDOW    3 
    #define BUTTON_BREITE    60 
    #define BUTTON_HOHE        20 
    #define FENSTER_BREITE  350 
    #define FENSTER_HOHE    320 
    #define P_FILM            0 
    #define P_FOTO            1 
    
    void RenderScene();
    void SetupPixelFormat(HDC hDC); 
    bool InitializeGL();
    
    unsigned int listBase;
    
    unsigned int CreateFont(char *fontName, int fontSize);
    void PrintText(unsigned int base, char *string);
    void ClearGLFont(unsigned int base);
    
    HDC g_HDC; 
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 
    BOOL                FensterSkalieren    (HWND) ; 
    BOOL                ButtonsSkalieren    (HWND, int, int) ; 
    
    const char	szAppName[]	= "Informatik Facharbeit - Semester 12.2 - Michael Hecker - Johannes Lier";
    OPENFILENAME    ofn ; 
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ 
        HWND            hwnd ; 
        MSG             msg ; 
        WNDCLASSEX        wndclassex ; 
        bool isFinished;  
    
        wndclassex.cbSize            = sizeof (WNDCLASSEX) ; 
        wndclassex.style            = CS_HREDRAW | CS_VREDRAW ; 
        wndclassex.lpfnWndProc        = WndProc ; 
        wndclassex.cbClsExtra        = 0 ; 
        wndclassex.cbWndExtra        = 0 ; 
        wndclassex.hInstance        = hInstance ; 
        wndclassex.hIcon            = LoadIcon (hInstance, MAKEINTRESOURCE (101)) ; 
        wndclassex.hCursor            = LoadCursor (NULL, IDC_ARROW) ; 
        wndclassex.hbrBackground    = CreateSolidBrush(RGB(200,200,255));
        wndclassex.lpszMenuName        = szAppName ; 
        wndclassex.lpszClassName    = szAppName ;  
        wndclassex.hIconSm            = NULL ; 
    
        RegisterClassEx (&wndclassex) ; 
        hwnd = CreateWindowEx (NULL , 
                                szAppName, szAppName, 
                                WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 
                                300, 300 , 
                                FENSTER_BREITE, FENSTER_HOHE, 
                                NULL, LoadMenu (hInstance, MAKEINTRESOURCE (102)), hInstance, NULL) ; 
        ShowWindow (hwnd, iCmdShow) ; 
        UpdateWindow (hwnd) ; 
    isFinished = false;
    if(!InitializeGL())
    isFinished = true;
    
       while(!isFinished)
          {
             PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE);
    
            if(msg.message == WM_QUIT)
                {
                   isFinished = true; 
                }
             else                   
                {
                   RenderScene();
                   TranslateMessage(&msg);
                   DispatchMessage(&msg);
                }
          }
      return msg.wParam;
    }
    
    bool InitializeGL()
    {
       glClearColor(0.0, 0.0, 0.0, 1.0);
       glShadeModel(GL_SMOOTH);
       glEnable(GL_DEPTH_TEST);
    
       listBase = CreateFont("Arial", 24);
       return true;
    }
    
    unsigned int CreateFont(char *fontName, int Size)
    {
       // windows font
       HFONT hFont;
       unsigned int base;
    
       // Create space for 96 characters.
       base = glGenLists(96);
    
       if(stricmp(fontName, "symbol")==0)
          {
             hFont = CreateFont(Size, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
                                SYMBOL_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
                                ANTIALIASED_QUALITY, FF_DONTCARE | DEFAULT_PITCH, fontName);
          }
       else
          {
             hFont = CreateFont(Size, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
                                ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
                                ANTIALIASED_QUALITY, FF_DONTCARE | DEFAULT_PITCH, fontName);
          }
    
       if(!hFont)
          return 0;
    
       SelectObject(g_HDC, hFont);
       wglUseFontBitmaps(g_HDC, 32, 96, base);
    
       return base;
    }
    
    void PrintText(unsigned int base, char *string)
    {
       if((base == 0 || string == NULL))
          return;
    
       glPushAttrib(GL_LIST_BIT);
          glListBase(base - 32);
          glCallLists(strlen(string), GL_UNSIGNED_BYTE, string);
       glPopAttrib();
    }
    
    void ClearGLFont(unsigned int base)
    {
       if(base != 0)
          glDeleteLists(base, 96);
    }
    
    void RenderScene()
    {
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       glLoadIdentity();      
       glColor3f(1.0f, 1.0f, 1.0f);
       glTranslatef(0.0f, 0.0f, -2.0f);
       glBegin(GL_LINES);
    
          glVertex3f(1.0f, 1.0f, -2.0f);
          glVertex3f(-1.0f, 1.0f, -2.0f);
    
          glVertex3f(-1.0f, 1.0f, -2.0f);
          glVertex3f(-1.0f, -1.0f, -2.0f);
    
          glVertex3f(-1.0f, -1.0f, -2.0f);
          glVertex3f(1.0f, -1.0f, -2.0f);
    
          glVertex3f(1.0f, -1.0f, -2.0f);
          glVertex3f(1.0f, 1.0f, -2.0f);
       glEnd();
    
       glColor3f(1.0f, 1.0f, 1.0f);
       glRasterPos2f(-0.35f, +0.7f);
    
       PrintText(listBase,"Informatik Facharbeit");
    
       SwapBuffers(g_HDC);
    }
    
    void SetupPixelFormat(HDC hDC)
    {
       int nPixelFormat;
    
       static PIXELFORMATDESCRIPTOR pfd = {
             sizeof(PIXELFORMATDESCRIPTOR),  
             1,                            
             PFD_DRAW_TO_WINDOW |        
             PFD_SUPPORT_OPENGL |        
             PFD_DOUBLEBUFFER,               
             PFD_TYPE_RGBA,                
             16,                            
             0, 0, 0, 0, 0, 0,             
             0,                             
             0,                           
             0,                          
             0, 0, 0, 0,                    
             32,                       
             0,                     
             0,                             
             PFD_MAIN_PLANE,                
             0,                             
             0, 0, 0 };                       
    
       nPixelFormat = ChoosePixelFormat(hDC, &pfd);
       SetPixelFormat(hDC, nPixelFormat, &pfd);
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ 
    
    	static HGLRC hRC; 
        static HDC hDC;     
        int width, height;  
    
        static    HINSTANCE        hInstance ; 
        static    HWND            hwndVideo ; 
        static    int                iIndex = 0 ; 
        char                    szDeviceName[80], 
                                szDeviceVersion[80], 
                                str[161]; 
        static    int           iBreite = 0, 
                                iHoche = 0, 
                                iPruef = P_FOTO ; 
    	static RECT	rect;
    
        switch (message){ 
        case WM_CREATE : 
                hInstance = ((LPCREATESTRUCT) lParam) -> hInstance ; 
                hwndVideo = capCreateCaptureWindow(
    				            (LPSTR) "WebCam", 
                                WS_CHILD | WS_VISIBLE, 
                                /*183, 90,*/0,28, 100, 100, 
                                (HWND) hwnd, (int) ID_VIDEO_WINDOW) ;  
    
                if (!capDriverConnect (hwndVideo, iIndex)) { 
                    MessageBox (hwnd, "Treiber für die Webcam kann nicht geladen werden...", "Fehler", MB_ICONERROR) ; 
                    SendMessage (hwnd, WM_DESTROY, 0, 0) ; 
                    return 0; 
                }       
    
                capPreviewRate (hwndVideo, 1) ; 
                capPreviewScale(hwnd, TRUE);
    			capPreview (hwndVideo, TRUE) ; 
    
                capGetDriverDescription (iIndex, szDeviceName, sizeof (szDeviceName), 
                                            szDeviceVersion, sizeof (szDeviceVersion)) ; 
                wsprintf (str, "%s, %s", szDeviceName, szDeviceVersion) ; 
                MessageBox (NULL, str, "Verbunden über...", NULL) ; 
                FensterSkalieren (hwnd) ; 
                ButtonsSkalieren (hwnd, iBreite, iHoche) ; 
    
    			hDC = GetDC(hwnd);         
                g_HDC = hDC;                
                SetupPixelFormat(hDC);       
    
                hRC = wglCreateContext(hDC); 
                wglMakeCurrent(hDC, hRC);  
    
                return 0 ;
    			break;
    
            case WM_SIZE : 
    
                height = HIWORD(lParam);    
                width = LOWORD(lParam);      
    
                if(height==0)                 
                   {                        
                      height = 1;
                   }
    
                glViewport(0, 0, width, height);
                glMatrixMode(GL_PROJECTION); 
                glLoadIdentity();     
    
                gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 1000.0f);
                glMatrixMode(GL_MODELVIEW);     
                glLoadIdentity();              
    
    			rect.left	= 0;
    			rect.top	= 0;
    			rect.right	= LOWORD(lParam);
    			rect.bottom = HIWORD(lParam);
    
                iBreite = LOWORD (lParam) ; 
                iHoche = HIWORD (lParam) ; 
                return 0 ; 
    
    		case WM_KEYDOWN:
    		 switch(wParam)
                   { 
    		       case VK_ESCAPE:
    			   PostQuitMessage(0);
    			   break;
                   }
                break;
    
    		case WM_COMMAND : 
                switch (LOWORD (wParam)){ 
    
                    case ID_BUTTON_CLOSE : 
                        SendMessage (hwnd, WM_DESTROY, 0, 0) ; 
                        break ; 
    
                } 
                return 0 ; 
    
             case WM_DESTROY:
                wglMakeCurrent(hDC, NULL);
                wglDeleteContext(hRC);
    
                capPreview (hwndVideo, FALSE) ; 
                capDriverDisconnect (hwndVideo) ; 
                PostQuitMessage (0) ; 
                return 0 ; 
    
    			case WM_PAINT:
    			{
    			PAINTSTRUCT		ps;
    			HDC				hDC;
    
    			const char		szUeberschrift[] = "Cam_Einbindung_v01";
    
    			hDC = BeginPaint(hwnd, &ps);
    			{
    				int		iStrLen = 0;
    				DrawText(hDC, szUeberschrift, lstrlen(szUeberschrift), &rect , DT_SINGLELINE | DT_CENTER | DT_TOP );
    
    			}
    
    			EndPaint(hwnd, &ps);
    			return 0;
    			}
    
    	  } 
        return DefWindowProc (hwnd, message, wParam, lParam) ; 
    } 
    
    BOOL ButtonsSkalieren (HWND hwndParent, int iBreite, int iHoche){ 
        MoveWindow (GetDlgItem (hwndParent, ID_BUTTON_CLOSE),  
                    iBreite - BUTTON_BREITE, iHoche - BUTTON_HOHE, 
                    BUTTON_BREITE, BUTTON_HOHE, TRUE) ; 
        MoveWindow (GetDlgItem (hwndParent, ID_BUTTON_FOTO),  
                    iBreite - (2 * BUTTON_BREITE) - 5, iHoche - BUTTON_HOHE, 
                    BUTTON_BREITE, BUTTON_HOHE, TRUE) ; 
        return TRUE ; 
    } 
    
    BOOL FensterSkalieren (HWND hParent){ 
        CAPSTATUS    CS ; 
        capGetStatus (GetDlgItem (hParent, ID_VIDEO_WINDOW), &CS, sizeof (CAPSTATUS)) ; 
        SetWindowPos (GetDlgItem (hParent, ID_VIDEO_WINDOW), NULL, 0, 0, CS.uiImageWidth, CS.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE) ; 
        SetWindowPos (hParent, NULL, CW_USEDEFAULT, CW_USEDEFAULT, CS.uiImageWidth, CS.uiImageHeight /*+ 75*/, SWP_NOZORDER | SWP_NOMOVE) ; 
        return TRUE ; 
    }
    

    Wie ihr seht wird der WebCam-Stream gezeichnet und darunter ein mit OpenGL geschriebene grafische Anzeige eines Strings und eines 4-Ecks.

    Allerdings werden das 4-Eck und der String unter dem Stream gemalt ... ich will aber das das 4-Eck und der Text über dem Stream liegen, damit ich ich einen bestimmten BEreich des Strems makieren bzw. umrahmen könnte.

    Schauts euch doch mal an...

    Danke
    Romeo-G



  • Ich habe heute erfahren, dass man mit der API auch direkt einfache geometrische Funktionen zeichnen kann, was ich inzwischen auch in meinem Projekt realisiert habe und weshalb ca 50% des Codes rausgeworfen wurden.

    Also... vielleicht steigt ja jetzt einer durch:

    #include <windows.h> 
    #include <vfw.h> 
    
    #define ID_BUTTON_FOTO    1 
    #define ID_BUTTON_CLOSE    2 
    #define ID_VIDEO_WINDOW    3 
    #define BUTTON_BREITE    60 
    #define BUTTON_HOHE        20 
    #define FENSTER_BREITE  350 
    #define FENSTER_HOHE    320 
    #define P_FILM            0 
    #define P_FOTO            1 
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 
    BOOL                FensterSkalieren    (HWND) ; 
    BOOL                ButtonsSkalieren    (HWND, int, int) ; 
    
    const char	szAppName[]	= "Informatik Facharbeit - Semester 12.2 - Michael Hecker - Johannes Lier";
    OPENFILENAME    ofn ; 
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ 
        HWND            hwnd ; 
        MSG             msg ; 
        WNDCLASSEX        wndclassex ; 
        wndclassex.cbSize            = sizeof (WNDCLASSEX) ; 
        wndclassex.style            = CS_HREDRAW | CS_VREDRAW ; 
        wndclassex.lpfnWndProc        = WndProc ; 
        wndclassex.cbClsExtra        = 0 ; 
        wndclassex.cbWndExtra        = 0 ; 
        wndclassex.hInstance        = hInstance ; 
        wndclassex.hIcon            = LoadIcon (hInstance, MAKEINTRESOURCE (101)) ; 
        wndclassex.hCursor            = LoadCursor (NULL, IDC_ARROW) ; 
        wndclassex.hbrBackground    = CreateSolidBrush(RGB(0,0,0));
        wndclassex.lpszMenuName        = szAppName ; 
        wndclassex.lpszClassName    = szAppName ;  
        wndclassex.hIconSm            = NULL ; 
        RegisterClassEx (&wndclassex) ; 
        hwnd = CreateWindowEx (NULL , 
                                szAppName, szAppName, 
                                WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION, 
                                CW_USEDEFAULT , CW_USEDEFAULT , 
                                FENSTER_BREITE, FENSTER_HOHE, 
                                NULL, LoadMenu (hInstance, MAKEINTRESOURCE (102)), hInstance, NULL) ; 
    
        ShowWindow (hwnd, iCmdShow) ; 
        UpdateWindow (hwnd) ; 
    
        while (GetMessage (&msg, NULL, 0, 0)) 
        { 
             TranslateMessage (&msg) ; 
             DispatchMessage (&msg) ; 
        } 
        return msg.wParam ; 
    } 
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ 
    
        static    HINSTANCE        hInstance ; 
        static    HWND            hwndVideo ; 
        static    int                iIndex = 0 ; 
        char                    szDeviceName[80], 
                                szDeviceVersion[80], 
                                str[161]; 
        static    int           iBreite = 0, 
                                iHoche = 0, 
                                iPruef = P_FOTO ; 
    	static RECT	rect;
    
        switch (message){ 
        case WM_CREATE : 
                hInstance = ((LPCREATESTRUCT) lParam) -> hInstance ; 
                hwndVideo = capCreateCaptureWindow((LPSTR) "WebCam",WS_CHILD | WS_VISIBLE,0, 10, 0, 0,(HWND) hwnd, (int) ID_VIDEO_WINDOW) ;  
    
                if (!capDriverConnect (hwndVideo, iIndex)) { 
                    MessageBox (hwnd, "Treiber für die Webcam kann nicht geladen werden...", "Fehler", MB_ICONERROR) ; 
                    SendMessage (hwnd, WM_DESTROY, 0, 0) ; 
                    return 0; 
                }             
                capPreviewRate (hwndVideo, 33.3) ; 
                capPreview (hwndVideo, TRUE) ; 
                capGetDriverDescription (iIndex, szDeviceName, sizeof (szDeviceName), 
                                            szDeviceVersion, sizeof (szDeviceVersion)) ; 
                wsprintf (str, "%s, %s", szDeviceName, szDeviceVersion) ; 
                MessageBox (NULL, str, "Verbunden über...", NULL) ; 
                FensterSkalieren (hwnd) ; 
                ButtonsSkalieren (hwnd, iBreite, iHoche) ; 
                return 0 ; 
    
            case WM_SIZE : 
    			rect.left	= 0;
    			rect.top	= 0;
    			rect.right	= LOWORD(lParam);
    			rect.bottom = HIWORD(lParam);
    
                iBreite = LOWORD (lParam) ; 
                iHoche = HIWORD (lParam) ; 
                return 0 ; 
    
    		case WM_COMMAND : 
                switch (LOWORD (wParam)){ 
    
                    case ID_BUTTON_CLOSE : 
                        SendMessage (hwnd, WM_DESTROY, 0, 0) ; 
                        break ; 
    
                } 
                return 0 ; 
    
    			case WM_DESTROY : 
                capPreview (hwndVideo, FALSE) ; 
                capDriverDisconnect (hwndVideo) ; 
                PostQuitMessage (0) ; 
                return 0 ; 
    
    			case WM_PAINT:
    			{
    			PAINTSTRUCT		ps;
    			HDC				hDC;
    
    			const char		szUeberschrift[] = "Cam_Einbindung_v01";
    
    			hDC = BeginPaint(hwnd, &ps);
    			{
    				int		iStrLen = 0;
    
    				//DrawText(hDC, szUeberschrift, lstrlen(szUeberschrift), &rect , DT_SINGLELINE | DT_CENTER | DT_TOP );
    				for(int i=0; i<1024; i++) SetPixel(hDC, i, 5, RGB(255,0,0) );
    				for(i=0; i<1024; i++) SetPixel(hDC, i, 5, RGB(255,0,0) );
    			}
    
    			EndPaint(hwnd, &ps);
    			return 0;
    			}
    
    	  } 
        return DefWindowProc (hwnd, message, wParam, lParam) ; 
    } 
    
    BOOL ButtonsSkalieren (HWND hwndParent, int iBreite, int iHoche){ 
        MoveWindow (GetDlgItem (hwndParent, ID_BUTTON_CLOSE),  
                    iBreite - BUTTON_BREITE, iHoche - BUTTON_HOHE, 
                    BUTTON_BREITE, BUTTON_HOHE, TRUE) ; 
        MoveWindow (GetDlgItem (hwndParent, ID_BUTTON_FOTO),  
                    iBreite - (2 * BUTTON_BREITE) - 5, iHoche - BUTTON_HOHE, 
                    BUTTON_BREITE, BUTTON_HOHE, TRUE) ; 
        return TRUE ; 
    } 
    
    BOOL FensterSkalieren (HWND hParent){ 
        CAPSTATUS    CS ; 
        capGetStatus (GetDlgItem (hParent, ID_VIDEO_WINDOW), &CS, sizeof (CAPSTATUS)) ; 
        SetWindowPos (GetDlgItem (hParent, ID_VIDEO_WINDOW), NULL, 0, 0, CS.uiImageWidth, 
                        CS.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE) ; 
        SetWindowPos (hParent, NULL, CW_USEDEFAULT, CW_USEDEFAULT, CS.uiImageWidth, 
                        CS.uiImageHeight /*+ 75*/, SWP_NOZORDER | SWP_NOMOVE) ; 
        return TRUE ; 
    }
    

    Also ... ich male 2 linien ... die eine sieht man weil sie über dem Strem ist ... und die andere sieht man nicht, weil sie zwar auf gleicher Ebene mit der 1. ist aber vom Stream verdeckt wird.

    Wie kriege ich das hin ???

    also theoretisch ... welche Stelle muss ich ändern damit erst das Bild der Cam und dann das was in der WM_Paint gezeichnet wird.



  • das mit "Informatik Facharbeit - Semester 12.2 - Michael Hecker - Johannes Lier" ist nur ein scherz, oder?!



  • Versuche mal direkt in das Child (hwndVideo) zu zeichnen



  • SetPixel((HDC) hwndVideo, i, 100, RGB(255,0,0)

    Das hat leider nicht geklappt...



  • Du darfst das hWnd natürlich nicht einfach in einen HDC casten - du musst dir diesen mit GetDC besorgen (ReleaseDC nicht vergessen).
    Aber wie in dem anderen Thread bereits geschrieben, wirst du wohl kaum um subclassing herumkommen, da das Child ja ständig neu gezeichnet wird 🙄


Anmelden zum Antworten