Webcam + bmp transparent

mouloudhab - 2 mai 2013 à 14:21
 mouloudhab - 5 mai 2013 à 19:50
Bonjour la communauté,
C’est encore moi. J’ai beaucoup avancé depuis mon dernier post.
Là, je fais un programme sous VC++6, en win32 :
En gros, c’est une fenêtre, avec un bmp, avec une zone transparente. Dans cette zone transparente, je dois faire apparaitre ce que voit une Webcam. J’avour que la partie Webcam était la partie la moins évidente pour moi.

J’ai trouvé un code source sur le forum (exploitation Webcam), très lisible à mon niveau. Il est composé comme suit :
3 classes : CWebCam, BitMap et Pixel
Un fichier Calcul.cpp : pour différents calculs (image miroir, calcul couleur, etc ..-seules quelques fonctions m’intéressent)
Un fichier init.cpp : création de la fenêtre
WebCam.cpp : contient les différentes fonctions de la classe WebCam.
WebCam.h et main.h : différentes déclarations de fonctions utilisées.

Le soft, à l’origine, affiche 4 images dans une fenêtre. Je l’ai modifié pour n’afficher qu’une seule : image brute issue de la Webcam, sans aucun autre calcul.

J’ai crée un autre projet win32 classique :
int APIENTRY WinMain,
LRESULT CALLBACK WndProc

J’ai copié dedans les fichiers WebCam.cpp et WebCam.h. J’ai réussi à compiler le tout, après beaucoup de galères …
int APIENTRY WinMain: Uniquement creation de la fenêtre.

et:
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// c'est là que j’ai  insèré le prog de la WebCam

CWebCam	WebCam;			// Classe WebCam

// Donne les handle
WebCam.hWnd=g_hWndMainFrame;
g_hDC=GetDC(g_hWndMainFrame);
WebCam.hDC=g_hDC;


// Connect la webcam
WebCam.Connect();
// Lance l'affichage de la webcam
WebCam.AfficheWebCam();
WebCam.ChargeCapture(0);
WebCam.AfficheImage(0, 500, 50);

switch(uMsg)
{
case WM_CREATE		: return OnCreate(hWnd);
case WM_DESTROY		: OnDestroy();
return 0;
// Clavier, comme ça je quitte simplement!
    case WM_KEYDOWN:
        switch (wParam)
        {
        case VK_ESCAPE:  // ECHAP = Fin du programme
            PostQuitMessage(0);
            break;
}
break;
case WM_PAINT		: OnPaint(); return 0;
}
//	DestroyWindow (g_hWndMainFrame);
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}


OnCreate : création des objets HBITMAP etc..
OnPaint() : la partie dessin.

Je cherche à comprendre, maintenant que j’ai réussi à ajouter la classe CWebCam, et à compiler sans erreur de LNK1001…
A quel endroit dois-je appeler la webcam ?

J’ai essayé, la connexion et l’affichage dans WndProc mais cela ne marche pas !
J’ai d’abord mes images qui s’affichent, puis disparaissent pour laisser place à la WebCam !

Puis-je faire ces opérations dans OnPaint ?
Ou alors, faire WebCam.Connect(); dans WinMain, et le reste dans WndProc (dans OnPaint ou ailleurs) ?

Je pensais faire l’affichage Webcam dans la clause WM_PAINT, donc dans OnPaint ou juste avant. Est-ce correcte ?

Merci pour toute aide.

1 réponse

Bonjour la communauté,
J'ai reconsidéré le problème, comment fusionner une image Webcam avec un Bitmap. En gros pour avoir ceci:


J’ai modifié un peu ma manière de voir. Je suis parti du code original de la Webcam.
A l’origine, ce programme est composé de WebCam.cpp : les différentes fonctions de la WebCam
WebCam.h : Classe WebCam + struct BitMap et Pixel
Le programme est appelé par main.cpp
//Main.cpp :
//===========================================================================//
// Global pour ce fichier qui seront passé en global pour tous le programme  //
//===========================================================================//
HINSTANCE   g_hInstance;	// hInstance du programme
HWND        g_hWnd;		// Numéro de la fenêtre
HDC         g_hDC;		// Numéro du Device Context 

static void OnDestroy	();
static int  OnCreate	(HWND hWnd);
static void OnPaint		();

//=======================================================================================
// Variables du module.
//static HBITMAP s_hBmpImageA	 NULL;  // bitmap à afficher
static HBITMAP s_hBmpImageAMask	 = NULL;  // masque du bitmap à afficher


static HDC	s_hDCImageA	= NULL; // DC avec le bitmap à afficher
static HDC	s_hDCImageAMask	= NULL; // DC avec le masque du bitmap à afficher


static HBITMAP s_hOldBmpImageA	= NULL; // ancien bitmap de s_hDCImageA
static HBITMAP s_hOldBmpImageAMask = NULL; // ancien bitmap de s_hDCImageAMask

static SIZE s_SizeBmpImageA	= {0, 0}; // taille de s_hBmpSprite

//=================================================================== //Fonction principale du programme      
//===================================================================
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
{
    MSG		msg;		// Pour enregistrer les messages windows
    BOOL	bQuit = FALSE;	// Indique si l'on veut quitter le programme ou pas


   CWebCam	WebCam;			

   srand(time(NULL));		// Initialise le générateur

    // Création d'une fenêtre
    g_hWnd=CreationFenetre(hInstance);

// Donne les handle 
WebCam.hWnd=g_hWnd;
g_hDC=GetDC(g_hWnd);
WebCam.hDC=g_hDC;

// Connect la webcam
WebCam.Connect();       // si je mets ces 2 lignes en commentaire, 
WebCam.AfficheWebCam();  //c'est les bitmaps qui s'affichent

    // Boucle
    while (!bQuit)
    {
        // En cas de message
        if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
        {
            // Si c'est un message pour quitter le mprogramme
            if (msg.message == WM_QUIT)
                bQuit = TRUE;  // Pour la fin de la boucle
            else
            {
                // Extraction des informations messages et exécution
                TranslateMessage (&msg);
                DispatchMessage (&msg);
            }
        }
        else
        {
}
    }
    // Supprime la fenêtre windows
    DestroyWindow (g_hWnd);
    return msg.wParam;
}



J'ai rajouté WM_PAINT et WM_CREATE, comme ceci:
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CLOSE:
        PostQuitMessage (0);
        break;
   case WM_DESTROY	:	OnDestroy();					return 0;
   case WM_CREATE	:	return OnCreate(hWnd);
   case WM_PAINT	:	OnPaint();					return 0;
   default:
        return DefWindowProc (hWnd, message, wParam, lParam);
    }
return 0;
}




OnCreate: Création des objets HBITMAP etc ...
int OnCreate(HWND hWnd)
{
// chargement des bitmaps
s_hBmpImageA = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_IMAGEA));
s_hBmpImageAMask = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_IMAGEAMASK));

// création de DCs pour ces bitmap
HDC hdc = GetDC(hWnd);
s_hDCImageA = CreateCompatibleDC(hdc);
s_hDCImageAMask = CreateCompatibleDC(hdc);
ReleaseDC(hWnd, hdc);
// sélection des bitmaps dans les DCs et savegarde des anciens
s_hOldBmpImageA = (HBITMAP) SelectObject(s_hDCImageA, s_hBmpImageA);
s_hOldBmpImageAMask = (HBITMAP) SelectObject(s_hDCImageAMask, s_hBmpImageAMask);
// récupération de la taille des bitmaps
BITMAP bmpInfo;
GetObject(s_hBmpImageA, sizeof(BITMAP), &bmpInfo);
s_SizeBmpImageA.cx = bmpInfo.bmWidth;
s_SizeBmpImageA.cy = bmpInfo.bmHeight;
// création réussie
return 0;
}



et OnPaint, en principe pour déssiner mes Bitmaps, avec la transparence!
void OnPaint()
{
// début du dessin
PAINTSTRUCT ps;
HDC hdc = BeginPaint(g_hWnd, &ps);
// taille zone cliente
RECT rcClient;
GetClientRect(g_hWnd, &rcClient);
int cxClient = rcClient.right-rcClient.left;
int cyClient = rcClient.bottom-rcClient.top;
// création de bitmaps et DCs pour l'affichage final et les opérations
// intermédiaires
HDC hDCFinal = CreateCompatibleDC(hdc);
HDC hDCTemp = CreateCompatibleDC(hdc);
HBITMAP hBmpFinal = CreateCompatibleBitmap(hdc, cxClient, cyClient);
HBITMAP hBmpTemp = CreateCompatibleBitmap(hdc, s_SizeBmpImageA.cx, s_SizeBmpImageA.cy);
HBITMAP hOldBmpFinal = (HBITMAP) SelectObject(hDCFinal, hBmpFinal);
HBITMAP hOldBmpTemp = (HBITMAP) SelectObject(hDCTemp, hBmpTemp);

// effacement du fond du DC final
HBRUSH hWhiteBrush = CreateSolidBrush(RGB(0xFF, 0x00, 0xFF));
FillRect(hDCFinal, &rcClient, hWhiteBrush);
DeleteObject(hWhiteBrush);

// temp = NOT mask
BitBlt(hDCTemp, 0, 0, s_SizeBmpImageA.cx, s_SizeBmpImageA.cy,
s_hDCImageAMask, 0, 0, NOTSRCCOPY);
// temp = temp AND bitmap
BitBlt(hDCTemp, 0, 0, s_SizeBmpImageA.cx, s_SizeBmpImageA.cy,
s_hDCImageA, 0, 0, SRCAND);
// final = final AND mask (à la position finale du sprite)
BitBlt(hDCFinal, 3, 3, s_SizeBmpImageA.cx, s_SizeBmpImageA.cy,
s_hDCImageAMask, 0, 0, SRCAND);
// final = final OR temp (à la position finale du sprite)
BitBlt(hDCFinal, 0, 0, s_SizeBmpImageA.cx, s_SizeBmpImageA.cy,
hDCTemp, 0, 0, SRCPAINT);
// recopie à l'écran
BitBlt(hdc, 0, 0, cxClient, cyClient, hDCFinal, 0, 0, SRCCOPY);

// libération des ressources
SelectObject(hDCFinal, hOldBmpFinal);
SelectObject(hDCTemp, hOldBmpTemp);
DeleteDC(hDCFinal);
DeleteDC(hDCTemp);
DeleteObject(hBmpFinal);
DeleteObject(hBmpTemp);
// fin du dessin
EndPaint(g_hWnd, &ps);
}



Donc, si je mets en commentaire les lignes:
WebCam.Connect(); // si je mets ces 2 lignes en commentaire, c'est les bitmaps qui s'affichent
WebCam.AfficheWebCam();
dans la fonction WinMain:

Se sont les Bitmaps qui s'affichent, sinon, juste l'image issue de la Webcam. J'ai inséré ces fonctions dans WndProc, dans WM_PAINT, et toujours sans succès.
J'ai l'impression de tourner en rond. En desespoir de cause, j'ai mis des Invalidates dans OnPaint, etc ..toujours sans succès. En gros, je ne sais plus quoi faire au juste

Mille merci pour toute aide la communauté!
0
Rejoignez-nous