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

DirectShow - J'ai un buffer, je voudrais un bitmap - C++ - Programmation

Marsh Posté le 11-09-2003 à 12:49:13    

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
Reply

Marsh Posté le 11-09-2003 à 12:49:13   

Reply

Marsh Posté le 11-09-2003 à 12:54:47    

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

Reply

Marsh Posté le 11-09-2003 à 13:25:23    

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
Reply

Marsh Posté le 11-09-2003 à 13:54:15    

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
Reply

Marsh Posté le 11-09-2003 à 14:08:27    

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.

Reply

Marsh Posté le 11-09-2003 à 14:28:22    

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
Reply

Marsh Posté le 11-09-2003 à 14:30:57    

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 ??

Reply

Marsh Posté le 11-09-2003 à 14:35:37    

Normalement, c'est du uncompressed 24-bit RGB


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

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

Marsh Posté le 11-09-2003 à 15:00:48    

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

Reply

Marsh Posté le 11-09-2003 à 15:32:19    

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
Reply

Marsh Posté le 11-09-2003 à 15:32:19   

Reply

Marsh Posté le 11-09-2003 à 16:40:30    

Google, MSDN etc

Reply

Marsh Posté le 11-09-2003 à 23:50:55    

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
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed