2012-03-06 4 views
11

Sto lavorando con un framegrabber e ho bisogno di recuperare le immagini dalla memoria del computer e salvarle su un file immagine. dopo aver provato per un paio di giorni finisco con le seguenti 2 funzioni, che creano un file e Windows OS è in grado di eseguire il file .bmp, ma il file bitmap è nero (la dimensione dell'immagine è 900KB, 640 * 480). Qualcuno ha qualche idea del perché, l'immagine è in nero? qui sono le due funzioni:C Win32: salva l'immagine .bmp da HBITMAP

LPSTR CreateBMP(HWND hAppWnd, int nImageType) 
{   
    void   * pWinGBits = NULL; 
    int    i; 
    Z_BITMAPINFO zWinGHeader; // bitmapinfo for cerating the DIB 
    // create DC for bitmap. 
    hDCBits = CreateCompatibleDC(ghDCMain); 

    switch (nImageType) 
    { 
     case bayer_filter: 
     zWinGHeader.bmiHeader.biSize   = sizeof(BITMAPINFOHEADER); 
     zWinGHeader.bmiHeader.biPlanes   = 1; 
     zWinGHeader.bmiHeader.biClrImportant = 0; 
     zWinGHeader.bmiHeader.biHeight   = -lYSize; 
     zWinGHeader.bmiHeader.biWidth   = lXSize; 
     zWinGHeader.bmiHeader.biBitCount  = 32; 
     zWinGHeader.bmiHeader.biClrUsed   = 0;//3; 
     zWinGHeader.bmiHeader.biCompression  = BI_BITFIELDS; 
     zWinGHeader.bmiHeader.biSizeImage  = 0; 
     zWinGHeader.bmiColors[0].rgbBlue  = 0x00; 
     zWinGHeader.bmiColors[0].rgbGreen  = 0x00; 
     zWinGHeader.bmiColors[0].rgbRed   = 0xFF; 
     zWinGHeader.bmiColors[0].rgbReserved = 0x00; 

     zWinGHeader.bmiColors[1].rgbBlue  = 0x00; 
     zWinGHeader.bmiColors[1].rgbGreen  = 0xFF; 
     zWinGHeader.bmiColors[1].rgbRed   = 0x00; 
     zWinGHeader.bmiColors[1].rgbReserved = 0x00; 

     zWinGHeader.bmiColors[2].rgbBlue  = 0xFF; 
     zWinGHeader.bmiColors[2].rgbGreen  = 0x00; 
     zWinGHeader.bmiColors[2].rgbRed   = 0x00; 
     zWinGHeader.bmiColors[2].rgbReserved = 0x00; 
     break; 

     case color32: 
     zWinGHeader.bmiHeader.biSize   = sizeof(BITMAPINFOHEADER); 
     zWinGHeader.bmiHeader.biPlanes   = 1; 
     zWinGHeader.bmiHeader.biClrImportant = 0; 
     zWinGHeader.bmiHeader.biHeight   = -lYSize; 
     zWinGHeader.bmiHeader.biWidth   = lXSize/4; 
     zWinGHeader.bmiHeader.biBitCount  = 32; 
     zWinGHeader.bmiHeader.biClrUsed   = 0; 
     zWinGHeader.bmiHeader.biCompression  = BI_BITFIELDS; 
     zWinGHeader.bmiHeader.biSizeImage  = 0; 
     zWinGHeader.bmiColors[0].rgbBlue  = 0x00; 
     zWinGHeader.bmiColors[0].rgbGreen  = 0x00; 
     zWinGHeader.bmiColors[0].rgbRed   = 0xFF; 
     zWinGHeader.bmiColors[0].rgbReserved = 0x00; 

     zWinGHeader.bmiColors[1].rgbBlue  = 0x00; 
     zWinGHeader.bmiColors[1].rgbGreen  = 0xFF; 
     zWinGHeader.bmiColors[1].rgbRed   = 0x00; 
     zWinGHeader.bmiColors[1].rgbReserved = 0x00; 

     zWinGHeader.bmiColors[2].rgbBlue  = 0xFF; 
     zWinGHeader.bmiColors[2].rgbGreen  = 0x00; 
     zWinGHeader.bmiColors[2].rgbRed   = 0x00; 
     zWinGHeader.bmiColors[2].rgbReserved = 0x00; 
     break; 

     case color24: 
     zWinGHeader.bmiHeader.biSize   = sizeof(BITMAPINFOHEADER); 
     zWinGHeader.bmiHeader.biPlanes   = 1; 
     zWinGHeader.bmiHeader.biClrImportant = 0; 
     zWinGHeader.bmiHeader.biHeight   = -lYSize; 
     zWinGHeader.bmiHeader.biWidth   = lXSize/3; 
     zWinGHeader.bmiHeader.biBitCount  = 24; 
     zWinGHeader.bmiHeader.biClrUsed   = 0; 
     zWinGHeader.bmiHeader.biCompression  = BI_RGB; 
     zWinGHeader.bmiHeader.biSizeImage  = 0; 
     break; 

     case color3x16: 
     zWinGHeader.bmiHeader.biSize   = sizeof(BITMAPINFOHEADER); 
     zWinGHeader.bmiHeader.biPlanes   = 1; 
     zWinGHeader.bmiHeader.biClrImportant = 0; 
     zWinGHeader.bmiHeader.biHeight   = -lYSize; 
     zWinGHeader.bmiHeader.biWidth   = lXSize/6; 
     zWinGHeader.bmiHeader.biBitCount  = 32; 
     zWinGHeader.bmiHeader.biClrUsed   = 0; 
     zWinGHeader.bmiHeader.biCompression  = BI_BITFIELDS; 
     zWinGHeader.bmiHeader.biSizeImage  = 0; 
     zWinGHeader.bmiColors[0].rgbBlue  = 0x00; 
     zWinGHeader.bmiColors[0].rgbGreen  = 0x00; 
     zWinGHeader.bmiColors[0].rgbRed   = 0xFF; 
     zWinGHeader.bmiColors[0].rgbReserved = 0x00; 

     zWinGHeader.bmiColors[1].rgbBlue  = 0x00; 
     zWinGHeader.bmiColors[1].rgbGreen  = 0xFF; 
     zWinGHeader.bmiColors[1].rgbRed   = 0x00; 
     zWinGHeader.bmiColors[1].rgbReserved = 0x00; 

     zWinGHeader.bmiColors[2].rgbBlue  = 0xFF; 
     zWinGHeader.bmiColors[2].rgbGreen  = 0x00; 
     zWinGHeader.bmiColors[2].rgbRed   = 0x00; 
     zWinGHeader.bmiColors[2].rgbReserved = 0x00; 
     break; 

     case bw1x10: 
     // create bitmap-infoheader. 
     zWinGHeader.bmiHeader.biSize  = sizeof(BITMAPINFOHEADER); 
     zWinGHeader.bmiHeader.biPlanes  = 1; 
     zWinGHeader.bmiHeader.biBitCount = 8; 
     zWinGHeader.bmiHeader.biCompression = BI_RGB; 
     zWinGHeader.bmiHeader.biSizeImage = 0; 
     zWinGHeader.bmiHeader.biClrUsed  = 256; 
     zWinGHeader.bmiHeader.biClrImportant= 0; 
     zWinGHeader.bmiHeader.biHeight  = -lYSize; 
     zWinGHeader.bmiHeader.biWidth  = lXSize/2; 

     // create colortable fot bitmap (grayvalues). 
     for (i = 0; i < 256; i++) 
     { 
      zWinGHeader.bmiColors[i].rgbGreen = i; 
      zWinGHeader.bmiColors[i].rgbBlue = i; 
      zWinGHeader.bmiColors[i].rgbRed  = i; 

      zWinGHeader.bmiColors[i].rgbReserved = 0; 
     } 
     break; 

     default: 
     case bw8: 
     // create bitmap-infoheader. 
     zWinGHeader.bmiHeader.biSize  = sizeof(BITMAPINFOHEADER); 
     zWinGHeader.bmiHeader.biPlanes  = 1; 
     zWinGHeader.bmiHeader.biBitCount = 8; 
     zWinGHeader.bmiHeader.biCompression = BI_RGB; 
     zWinGHeader.bmiHeader.biSizeImage = 0;   
     zWinGHeader.bmiHeader.biClrUsed  = (1<<8);  
     zWinGHeader.bmiHeader.biClrImportant= 0; 
     zWinGHeader.bmiHeader.biHeight  = -lYSize; 
     zWinGHeader.bmiHeader.biWidth  = lXSize; 
     //zWinGHeader.bmiHeader.biSizeImage = ((zWinGHeader.bmiHeader.biWidth * 8 +31) & ~31) /8 
      //         * zWinGHeader.bmiHeader.biHeight; 

     // create colortable fot bitmap (grayvalues). 
     for (i = 0; i < 256; i++) 
     { 
      zWinGHeader.bmiColors[i].rgbGreen = i;   
      zWinGHeader.bmiColors[i].rgbBlue = i; 
      zWinGHeader.bmiColors[i].rgbRed  = i;    
      zWinGHeader.bmiColors[i].rgbReserved = 0;   
     } 
     break; 
    } 

    // cerate identity palette 
    hPal = CreateIdentityPalette(zWinGHeader.bmiColors); 

    // get new palette into DC and map into physical palette register. 
    hOldPal = SelectPalette(ghDCMain, hPal, FALSE);  
    RealizePalette(ghDCMain); 

    // cerate DIB-Section f黵 direct access of image-data. 
    hBitmap = CreateDIBSection(
     hDCBits,      // handle of device context 
     (BITMAPINFO *)&zWinGHeader,  // address of structure containing 
             // bitmap size, format and color data 
     DIB_RGB_COLORS,     // color data type indicator: RGB values 
             // or palette indices 
     &pWinGBits,      // pointer to variable to receive a pointer 
             // to the bitmap's bit values 
     NULL,       // optional handle to a file mapping object 
     0        // offset to the bitmap bit values within 
             // the file mapping object 
    );  
    // get bitmap into DC . 
    hOldBitmap = (HBITMAP)SelectObject(hDCBits, hBitmap); 

    return pWinGBits;   // return pointer to DIB 
} 

e qui è la funzione per il salvataggio in bmp:

BOOL SaveToFile(HBITMAP hBitmap3, LPCTSTR lpszFileName) 
{ 
    HDC hDC; 
    int iBits; 
    WORD wBitCount; 
    DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0; 
    BITMAP Bitmap0; 
    BITMAPFILEHEADER bmfHdr; 
    BITMAPINFOHEADER bi; 
    LPBITMAPINFOHEADER lpbi; 
    HANDLE fh, hDib, hPal,hOldPal2=NULL; 
    hDC = CreateDC("DISPLAY", NULL, NULL, NULL); 
    iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); 
    DeleteDC(hDC); 
    if (iBits <= 1) 
    wBitCount = 1; 
    else if (iBits <= 4) 
    wBitCount = 4; 
    else if (iBits <= 8) 
    wBitCount = 8; 
    else 
    wBitCount = 24; 
    GetObject(hBitmap3, sizeof(Bitmap0), (LPSTR)&Bitmap0); 
    bi.biSize = sizeof(BITMAPINFOHEADER); 
    bi.biWidth = Bitmap0.bmWidth; 
    bi.biHeight =-Bitmap0.bmHeight; 
    bi.biPlanes = 1; 
    bi.biBitCount = wBitCount; 
    bi.biCompression = BI_RGB; 
    bi.biSizeImage = 0; 
    bi.biXPelsPerMeter = 0; 
    bi.biYPelsPerMeter = 0; 
    bi.biClrImportant = 0; 
    bi.biClrUsed = 256; 
    dwBmBitsSize = ((Bitmap0.bmWidth * wBitCount +31) & ~31) /8 
               * Bitmap0.bmHeight; 
    hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER)); 
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); 
    *lpbi = bi; 

    hPal = GetStockObject(DEFAULT_PALETTE); 
    if (hPal) 
    { 
    hDC = GetDC(NULL); 
    hOldPal2 = SelectPalette(hDC, (HPALETTE)hPal, FALSE); 
    RealizePalette(hDC); 
    } 


    GetDIBits(hDC, hBitmap3, 0, (UINT) Bitmap0.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) 
    +dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS); 

    if (hOldPal2) 
    { 
    SelectPalette(hDC, (HPALETTE)hOldPal2, TRUE); 
    RealizePalette(hDC); 
    ReleaseDC(NULL, hDC); 
    } 

    fh = CreateFile(lpszFileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS, 
    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 

    if (fh == INVALID_HANDLE_VALUE) 
    return FALSE; 

    bmfHdr.bfType = 0x4D42; // "BM" 
    dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize; 
    bmfHdr.bfSize = dwDIBSize; 
    bmfHdr.bfReserved1 = 0; 
    bmfHdr.bfReserved2 = 0; 
    bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize; 

    WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); 

    WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL); 
    GlobalUnlock(hDib); 
    GlobalFree(hDib); 
    CloseHandle(fh); 
    counter=1; 
    return TRUE; 
} 

posso disegnare le immagini dalla memoria perfettamente con la seguente funzione, quindi di sicuro io non avere alcun problema per la lettura dei dati immagine:

void DrawPicture(HDC hDC, PBYTE pDest, PBYTE pSrc, LONG lXSize, LONG lYSize) 
{  
LONG lXSizeDiv, lYSizeDiv; 
LONG lX, lY; 
DWORD dwMax; 
RECT rect; 
HDC  hdc; 
PBYTE pTmpDest; 
double fXFactor, fYFactor; 
// HBRUSH hBrush; 
// POINT Point; 


switch(gzMvfgKamDef.iImageType) 
{ 
    case bayer_filter: 
    lXSizeDiv = 1; 
    lYSizeDiv = 1; 
    BayerToRGB((PDWORD) pDest, pSrc, lXSize, lYSize, 
       gzMvfgKamDef.iBayerQuadrant, gzMvfgKamDef.iBayerQuality); 

    break; 

    case color24: 
    lXSizeDiv = 3; 
    lYSizeDiv = 1; 
    memcpy(pDest, pSrc, (size_t)(lXSize * lYSize)); 

break; 

    case color32: 
    lXSizeDiv = 4; 
    lYSizeDiv = 1; 
    memcpy(pDest, pSrc, (size_t)(lXSize * lYSize)); 


    break; 

    case color3x16: 
    lXSizeDiv = 6; 
    lYSizeDiv = 1; 
    Conv3x16To3x8(pDest, pSrc, 4, lXSize, lYSize); 


    break; 

    case bw1x10: 
    lXSizeDiv = 2; 
    lYSizeDiv = 1; 
    Conv1x10To1x8(pDest, pSrc, 2, lXSize, lYSize); 


    break; 

    case bw6Tap: 
    lXSizeDiv = 1; 
    lYSizeDiv = 1; 
    Conv6TapTo1x8(pDest, pSrc, 1, lXSize, lYSize); 

    break; 

    default: 
    case bw8: 
    lXSizeDiv = 1; 
    lYSizeDiv = 1; 
    memcpy(pDest, pSrc, (size_t)(lXSize * lYSize)); 

    break; 

} 


if(gahIniDlg[ NdxHistogramDlg ].hWnd) 
{ 
    memset(gadwHistogram, 0, sizeof(gadwHistogram)); 

    pTmpDest = pDest; 

    for (lY = 0; lY < lYSize; lY++) 
    { 
     for (lX = 0; lX < lXSize; lX++) 
     { 
      gadwHistogram[ *pTmpDest ]++; 
      pTmpDest++; 
     } 
    } 

    GetClientRect (gahIniDlg[ NdxHistogramDlg ].hWnd, &rect) ; 

    hdc = GetDC (gahIniDlg[ NdxHistogramDlg ].hWnd); 

    dwMax = 0; 
    for (lX = 0 ; lX <= 0xff; lX++) 
     dwMax = (gadwHistogram[ lX ] > dwMax) ? gadwHistogram[ lX ] : dwMax; 

    fYFactor = (double) dwMax/(double) rect.bottom; 
    fXFactor = (double) (rect.right - 100)/(double) 0x100; 

/* 
    SelectObject (hdc, GetStockObject (BLACK_PEN)) ; 

    for(lX = 0; lX <= 0xff; lX+=8) 
    { 
     MoveToEx(hdc, lX * fXFactor, rect.bottom, &Point); 
     LineTo(hdc, lX * fXFactor, rect.bottom-10); 
    } 
*/ 
    SelectObject (hdc, GetStockObject (WHITE_PEN)) ; 

//  hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW)); 
//  hBrush = CreateSolidBrush(0xffffff); 
//  SelectObject (hdc, hBrush); 


    Polyline(hdc, gaHistogram, 0x100); 

//  DeleteObject(hBrush); 

    for (lX = 0 ; lX <= 0xff; lX++) 
    { 
     gaHistogram[ lX ].x = (DWORD)(fXFactor * (double)lX); 
     gaHistogram[ lX ].y = rect.bottom - (DWORD)((double) gadwHistogram[ lX ]/fYFactor); 
    } 

    SelectObject (hdc, GetStockObject (BLACK_PEN)) ; 

    Polyline(hdc, gaHistogram, 0x100); 

    ReleaseDC (gahIniDlg[ NdxHistogramDlg ].hWnd , hdc) ; 
} 

// display the bitmap 
StretchBlt(hDC, rcWin.left, rcWin.top, lXSize/lXSizeDiv, lYSize/lYSizeDiv, 
     hDCBits, 0, 0, lXSize/lXSizeDiv, lYSize/lYSizeDiv, SRCCOPY); 
//BitBlt(hDC, rcWin.left, rcWin.top, lXSize/lXSizeDiv, lYSize/lYSizeDiv, 
      //hDCBits, 0, 0, SRCCOPY); 

} 

risposta

6

Ho appena trovato fuori ho avuto uno stupido errore in un'altra parte del mio codice ho usato:

// Convert Image to bitmap and display it 
DrawPicture(ghDCMain, pWinGBitmap, gpbImageData, lXSize, lYSize );  
if(counter!=1) { 
    hBitmap2 = CreateCompatibleBitmap (hDCBits, lXSize, lYSize); 
    SaveToFile(hBitmap2, "c:\\t.bmp"); 
    OutputDebugString("tested !!!!"); 
} 

cancellando la linea hBitmap2 = CreateCompatibleBitmap (hDCBits, lXSize, lYSize);, e cambiando il hBitmap2 al HBITMAP il risultato di CreateDIBSection(), è salvato l'immagine magnificamente. GRAZIE A TUTTI PER IL VOSTRO AIUTO.

+0

Non ho modificato nulla in DrawPicture(); funzione – user261002

2
FORMAT_INFO sFormat; 
mvfg_getparam(MVFGPAR_DATAFORMAT, &sFormat, giCurrentGrabberID); 
long lFrameSize  = sFormat.lFrameSize; 

BYTE *pBitmap = (BYTE*)malloc(FrameSize); 
memcpy(pBitmap, CamGetPicture(), FrameSize); 
writeBitmapToFile(pBitmap, FrameSize, "tmp.bmp"); 

/* 
* write our raw data into a bitmap file 
* adding the correct header and put it all 
* together in a single file 
*/ 
int 
writeBitmapToFile(void *data, unsigned long size, const char *filename) 
{ 
    bmpFileHeader_t header; 
    bmpInfoHeader_t info; 
    bmpRGBQuad_t rgb = { 0, 0, 0, 0}; 
    FILE *out; 
    size_t len; 
    int i; 


    header.type = 0x4d42; // magic sequence 'BM' 
    header.size = 0; 
    header.res0 = 0; 
    header.res1 = 0; 
    /* 256 different colors, each is defined by an bmpRBQuad type */ 
    header.offset = 256 * sizeof(bmpRGBQuad_t) + 
        sizeof(bmpInfoHeader_t) + sizeof(bmpFileHeader_t); 
    info.size = sizeof(bmpInfoHeader_t); 
    info.width = WIDTH; 
    info.height = HEIGHT; 
    info.planes = 1; 
    info.cDepth = 8; /* 8 Bit */ 
    info.compression = 0; 
    info.rawSize = size; 
    info.hRes = 0; 
    info.vRes = 0; 
    info.nrColors = 0x100; 
    info.impColors = 0; 

    out = fopen(filename, "wb"); 
    if (out == NULL) { 
     printf("error cannot open %s for writing\n", filename); 
     return -1; 
    } 
    len = fwrite(&header, 1, sizeof(header), out); 
    if (len != sizeof(header)) { 
     printf("error while writing header\n"); 
     return -1; 
    } 
    len = fwrite(&info, 1, sizeof(info), out); 
    if (len != sizeof(info)) { 
     printf("error while writing info header\n"); 
     return -1; 
    } 
    /* stupid try and error programming leads to this */ 
    for (i = 0; i < 256; i++) { 
     rgb.red = i; 
     rgb.green = i; 
     rgb.blue = i; 
     len = fwrite(&rgb, 1, sizeof(rgb), out); 
     if (len != sizeof(rgb)) { 
      printf("error while writing rgb header\n"); 
      return -1; 
     } 
    } 

    len = fwrite(data, 1, size, out); 
    if (len != size) { 
     printf("error while writing bitmap data\n"); 
     return -1; 
    } 
    return 0; 
} 

Reference - mikrotron

Reference - write bitmap

+0

ho modificato il mio codice usando la tua guida, che mi dà il file .bin, puoi per favore fammi sapere come posso cambiare questo file in un'immagine? Grazie – user261002

+0

@ user261002, prova a cambiare l'estensione in bmp e aprirlo come un file bitmap. – perreal

+0

perreal grazie tanto per la tua risposta rapida. Ho cambiato il fomart in .bmp e ho anche provato ad aprirlo con Windows Photo Viewer, ma ancora non mi mostra nulla. cosa pensi, cosa dovrei fare? Per favore fammi sapere, grazie . oh, solo per farti sapere, ho anche qualche indirizzo di offset, credi che dovrei aggiungere l'offset? – user261002

2

Sei sicuro ci sono dati adeguati dentro?

Vorrei provare extract the RGB data e salvarlo in un formato molto semplice "manualmente", solo per vedere cosa c'è dentro. Se stai cercando un formato immagine semplice ma ancora standard, consulta PPM images.

+0

grazie, ho intenzione di provarlo ora – user261002

+1

ciao, grazie per la tua modifica, ho il RGBQUAD bmicolors [256], nel mio file di intestazione, anche usando ho un per loor: for (i = 0; i < 256; i ++) \t \t { \t \t \t zWinGHeader.bmiColors [i] = i .rgbGreen \t; \t \t \t \t \t zWinGHeader.bmiColors [i] .rgbBlue \t = i; \t \t \t zWinGHeader.bmiColors [i] .rgbRed \t \t = i; \t \t \t \t \t \t zWinGHeader.bmiColors [i] .rgbReserved = 0; \t \t \t \t \t} per immagine a 8 bit/pixel, pensi sia corretto? – user261002

2

Dalla documentazione per CreateCompatibleDC:

Quando la memoria viene creata DC, la sua superficie del display è esattamente un pixel bianco e nero di larghezza e un pixel bianco e nero. Prima che un'applicazione possa utilizzare una memoria DC per le operazioni di disegno, è necessario selezionare una bitmap con larghezza e altezza corrette nella DC.

Dal momento che si sta utilizzando CreateDIBSection con quella DC, la sezione DIB risultante sarà a 1 bit in bianco e nero pure.