Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1085 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  DirectShow - J'ai un buffer, je voudrais un bitmap

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

DirectShow - J'ai un buffer, je voudrais un bitmap

n°512350
haazheel
Posté le 11-09-2003 à 12:49:13  profilanswer
 

Salut,
 
alors dans mes problèmes de DirectShow, je pense (j'espère) voir la lumière:
 
j'arrive à récupérer un buffer de l'image en cours:
 

Code :
  1. char *pBuffer = new char[size];
  2. hr = pGrabber->GetCurrentBuffer(&size, (long *)pBuffer);
  3. if (FAILED(hr))
  4.      ShowMessage("Impossible de récupérer le buffer" );


 
Maintenant, je voudrais transformer ce char en un joli bitmap sur mon disque dur, mais je n'y arrive pas...
 
J'ai essayé plusieurs méthodes, mais aucune ne semble fonctionner...
 
Quelqu'un peut m'aider?
 
Merci d'avance


Message édité par haazheel le 11-09-2003 à 13:59:35

---------------
Another .Net Blog
mood
Publicité
Posté le 11-09-2003 à 12:49:13  profilanswer
 

n°512352
chrisbk
-
Posté le 11-09-2003 à 12:54:47  profilanswer
 

heureusement que tu nous dis quelle methode tu as essayé sinon on pourrait pas t'aider !
 
sauvegarde la en TGA 32bpp non compresse ta broutte, y'en a pour10mn a faire ca

n°512381
VisualC++
J'va y penser ...
Posté le 11-09-2003 à 13:25:23  profilanswer
 

Et chercher ds la MSDN aussi (edit : et google)
 


Storing an Image
Many applications store images permanently as files. For example, drawing applications store pictures, spreadsheet applications store charts, CAD applications store drawings, and so on.  
 
If you are writing an application that stores a bitmap image in a file, you should use the bitmap file format described in Bitmap Storage. To store a bitmap in this format, you must use a BITMAPINFOHEADER, a BITMAPV4HEADER, or a BITMAPV5HEADER structure and an array of RGBQUAD structures, as well as an array of palette indexes.  
 
The following example code defines a function that uses a BITMAPINFO structure and allocates memory for and initializes members within a BITMAPINFOHEADER structure. Note that the BITMAPINFO structure cannot be used with either a BITMAPV4HEADER or a BITMAPV5HEADER structure.
 
PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp)
{  
    BITMAP bmp;  
    PBITMAPINFO pbmi;  
    WORD    cClrBits;  
 
    // Retrieve the bitmap color format, width, and height.  
    if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))  
        errhandler("GetObject", hwnd);  
 
    // Convert the color format to a count of bits.  
    cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);  
    if (cClrBits == 1)  
        cClrBits = 1;  
    else if (cClrBits <= 4)  
        cClrBits = 4;  
    else if (cClrBits <= 8)  
        cClrBits = 8;  
    else if (cClrBits <= 16)  
        cClrBits = 16;  
    else if (cClrBits <= 24)  
        cClrBits = 24;  
    else cClrBits = 32;  
 
    // Allocate memory for the BITMAPINFO structure. (This structure  
    // contains a BITMAPINFOHEADER structure and an array of RGBQUAD  
    // data structures.)  
 
     if (cClrBits != 24)  
         pbmi = (PBITMAPINFO) LocalAlloc(LPTR,  
                    sizeof(BITMAPINFOHEADER) +  
                    sizeof(RGBQUAD) * (1<< cClrBits));  
 
     // There is no RGBQUAD array for the 24-bit-per-pixel format.  
 
     else  
         pbmi = (PBITMAPINFO) LocalAlloc(LPTR,  
                    sizeof(BITMAPINFOHEADER));  
 
    // Initialize the fields in the BITMAPINFO structure.  
 
    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);  
    pbmi->bmiHeader.biWidth = bmp.bmWidth;  
    pbmi->bmiHeader.biHeight = bmp.bmHeight;  
    pbmi->bmiHeader.biPlanes = bmp.bmPlanes;  
    pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;  
    if (cClrBits < 24)  
        pbmi->bmiHeader.biClrUsed = (1<<cClrBits);  
 
    // If the bitmap is not compressed, set the BI_RGB flag.  
    pbmi->bmiHeader.biCompression = BI_RGB;  
 
    // Compute the number of bytes in the array of color  
    // indices and store the result in biSizeImage.  
    // For Windows NT, the width must be DWORD aligned unless  
    // the bitmap is RLE compressed. This example shows this.  
    // For Windows 95/98/Me, the width must be WORD aligned unless the  
    // bitmap is RLE compressed.
    pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
                                  * pbmi->bmiHeader.biHeight;  
    // Set biClrImportant to 0, indicating that all of the  
    // device colors are important.  
     pbmi->bmiHeader.biClrImportant = 0;  
     return pbmi;  
 }  
The following example code defines a function that initializes the remaining structures, retrieves the array of palette indices, opens the file, copies the data, and closes the file.  
 
void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi,  
                  HBITMAP hBMP, HDC hDC)  
 {  
     HANDLE hf;                 // file handle  
    BITMAPFILEHEADER hdr;       // bitmap file-header  
    PBITMAPINFOHEADER pbih;     // bitmap info-header  
    LPBYTE lpBits;              // memory pointer  
    DWORD dwTotal;              // total count of bytes  
    DWORD cb;                   // incremental count of bytes  
    BYTE *hp;                   // byte pointer  
    DWORD dwTmp;  
 
    pbih = (PBITMAPINFOHEADER) pbi;  
    lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
 
    if (!lpBits)  
         errhandler("GlobalAlloc", hwnd);  
 
    // Retrieve the color table (RGBQUAD array) and the bits  
    // (array of palette indices) from the DIB.  
    if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi,  
        DIB_RGB_COLORS))  
    {
        errhandler("GetDIBits", hwnd);  
    }
 
    // Create the .BMP file.  
    hf = CreateFile(pszFile,  
                   GENERIC_READ | GENERIC_WRITE,  
                   (DWORD) 0,  
                    NULL,  
                   CREATE_ALWAYS,  
                   FILE_ATTRIBUTE_NORMAL,  
                   (HANDLE) NULL);  
    if (hf == INVALID_HANDLE_VALUE)  
        errhandler("CreateFile", hwnd);  
    hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M"  
    // Compute the size of the entire file.  
    hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +  
                 pbih->biSize + pbih->biClrUsed  
                 * sizeof(RGBQUAD) + pbih->biSizeImage);  
    hdr.bfReserved1 = 0;  
    hdr.bfReserved2 = 0;  
 
    // Compute the offset to the array of color indices.  
    hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +  
                    pbih->biSize + pbih->biClrUsed  
                    * sizeof (RGBQUAD);  
 
    // Copy the BITMAPFILEHEADER into the .BMP file.  
    if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),  
        (LPDWORD) &dwTmp,  NULL))  
    {
       errhandler("WriteFile", hwnd);  
    }
 
    // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.  
    if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)  
                  + pbih->biClrUsed * sizeof (RGBQUAD),  
                  (LPDWORD) &dwTmp, ( NULL))  
        errhandler("WriteFile", hwnd);  
 
    // Copy the array of color indices into the .BMP file.  
    dwTotal = cb = pbih->biSizeImage;  
    hp = lpBits;  
    if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL))  
           errhandler("WriteFile", hwnd);  
 
    // Close the .BMP file.  
     if (!CloseHandle(hf))  
           errhandler("CloseHandle", hwnd);  
 
    // Free memory.  
    GlobalFree((HGLOBAL)lpBits);
}


Message édité par VisualC++ le 11-09-2003 à 13:27:01
n°512403
haazheel
Posté le 11-09-2003 à 13:54:15  profilanswer
 

Merci pour vos réponses
 
J'ai choisi d'utiliser la méthode de la MSDN, seulement je me pose quelques questions:
 
est-ce que je dois utiliser les deux fonctions?
 
dans la deuxième fonction, à quoi correspond HDC hdc? Je ne sais pas quoi mettre dans l'appel de la fonction...


---------------
Another .Net Blog
n°512419
VisualC++
J'va y penser ...
Posté le 11-09-2003 à 14:08:27  profilanswer
 

Euh c t pas pour t'imposer une methode hein le code, jsute que 1 sec de recherche et y a un exemple.
 
HDC = device context (regarde la doc de DC)
 
C juste une exemple je le repete, comem tu nous a mm pas indique le format de ton buffer, dur de dire ce que tu aurais besoin.

n°512440
haazheel
Posté le 11-09-2003 à 14:28:22  profilanswer
 

Voici le code me permettant de récupérer l'image dans le buffer:

Code :
  1. AM_MEDIA_TYPE mt;
  2.                 hr = pGrabber->GetConnectedMediaType(&mt);
  3.                 if (FAILED(hr))
  4.                         ShowMessage("Impossible de se connecter au type du media" );
  5.          // Get a pointer to the video header.
  6.         VIDEOINFOHEADER *pVideoHeader = (VIDEOINFOHEADER*)mt.pbFormat;
  7.          if (pVideoHeader == NULL)
  8.          ShowMessage("Impossible de pointer les données vidéo" );
  9.          // The video header contains the bitmap information.
  10.          // Copy it into a BITMAPINFO structure.
  11.         BITMAPINFO BitmapInfo;
  12.          ZeroMemory(&BitmapInfo, sizeof(BitmapInfo));
  13.         CopyMemory(&BitmapInfo.bmiHeader, &(pVideoHeader->bmiHeader), sizeof(BITMAPINFOHEADER));
  14.                 long size;
  15.                 hr = pGrabber->GetCurrentBuffer(&size, NULL);
  16.                 if (FAILED(hr))
  17.                         ShowMessage("Impossible de récupérer la taille du buffer" );
  18.                 char *pBuffer = new char[size];
  19.                 hr = pGrabber->GetCurrentBuffer(&size, (long *)pBuffer);
  20.                 if (FAILED(hr))
  21.                         ShowMessage("Impossible de récupérer le buffer" );


 
Donc le buffer est contenu dans un char*, si je ne m'abuse...
 
Mais le problème est que CreateDIBSection demande non pas un char*, mais un void*
 
Alors j'ai fait comme ça à la suite, pour voir ce qui est récupéré:
 

Code :
  1. void * vBuffer = pBuffer;
  2.                 HDC hdc = GetDC(0);
  3.                 HDC hdc1 = GetDC(this->Handle);
  4.                 HBITMAP hBitmap = CreateDIBSection(
  5.                                         hdc,
  6.                                         &BitmapInfo,
  7.                                         DIB_RGB_COLORS,
  8.                                         &vBuffer,
  9.                                         NULL,
  10.                                         0);
  11.          GdiFlush();
  12.                 BitBlt(hdc1,0,0,356,240,hdc,0,0,SRCPAINT);


 
Mais là je ne vois pas les images de la vidéo, mais un screen shot d'une fenêtre d'Internet Explorer...
 
Alors voilà le problème: récupérer l'image de la vidéo correctement...


---------------
Another .Net Blog
n°512442
VisualC++
J'va y penser ...
Posté le 11-09-2003 à 14:30:57  profilanswer
 

Par format de ton buffer, c'est vis a vis de ton premier post, et du fait que ok tu as un buffer mais dedans y a koi du RGB, compresse, etc ??

n°512448
haazheel
Posté le 11-09-2003 à 14:35:37  profilanswer
 

Normalement, c'est du uncompressed 24-bit RGB


Message édité par haazheel le 11-09-2003 à 14:35:48

---------------
Another .Net Blog
n°512475
VisualC++
J'va y penser ...
Posté le 11-09-2003 à 15:00:48  profilanswer
 

Ben un truc du genre et tu sauves tel quel en ayant rempli les headers
 

Code :
  1. typedef struct {
  2.    unsigned short int type;                 /* Magic identifier            */
  3.    unsigned int size;                       /* File size in bytes          */
  4.    unsigned short int reserved1, reserved2;
  5.    unsigned int offset;                     /* Offset to image data, bytes */
  6. } HEADER;
  7. typedef struct {
  8.    unsigned int size;               /* Header size in bytes      */
  9.    int width,height;                /* Width and height of image */
  10.    unsigned short int planes;       /* Number of colour planes   */
  11.    unsigned short int bits;         /* Bits per pixel            */
  12.    unsigned int compression;        /* Compression type          */
  13.    unsigned int imagesize;          /* Image size in bytes       */
  14.    int xresolution,yresolution;     /* Pixels per meter          */
  15.    unsigned int ncolours;           /* Number of colours         */
  16.    unsigned int importantcolours;   /* Important colours         */
  17. } INFOHEADER;


 
Tu mets entre autre choses :
- type = "BM"
- offset = taile des 2 headers (= debut de l'image reelement ds le fichier)
- compression a 0
- planes =  1
- bits = 8
 
Et tu sauves en BGR et pas RGB
 
Voila en gros

n°512533
haazheel
Posté le 11-09-2003 à 15:32:19  profilanswer
 

Bon, j'arrive à enregistrer le bitmap sur le disque...
 
Le problème est que l'image est toute noire...
 
Les données d'en-tête sont bien copiées, puisque je peux afficher ce bitmap... C'est donc que je n'arrive pas à copier correctement le contenu de l'image...
 
Ca serait pas un problème typique ça?


---------------
Another .Net Blog
mood
Publicité
Posté le 11-09-2003 à 15:32:19  profilanswer
 

n°512630
VisualC++
J'va y penser ...
Posté le 11-09-2003 à 16:40:30  profilanswer
 

Google, MSDN etc

n°512934
haazheel
Posté le 11-09-2003 à 23:50:55  profilanswer
 

Ouais, depuis 2 jours que Google et MSDN, j'ai enfin trouvé ce que je cherchais, et ça marche, plutôt bien même...


---------------
Another .Net Blog

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  DirectShow - J'ai un buffer, je voudrais un bitmap

 

Sujets relatifs
DirectShow => J'arrive pas à utiliser SampleGrabber!!!Copie de buffer dans formulaire de saisie de msg
DirectShow + Builder 6 => Problème de lieur avec TIME_FORMAT_FRAMEcomment vider le buffer d'évenement ListSelectionEvent
Afficher un bitmap sur un bouton[open gl] Enlevement de matiere avec Z buffer en temps réel
Impossible d'afficher un bitmap transparent dans un DC memoire...Buffer, fichier, read et fread
je voudrais juste apprendre!Enregistrement bitmap
Plus de sujets relatifs à : DirectShow - J'ai un buffer, je voudrais un bitmap


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR