2012-03-06 3 views
11

Я работаю с фреймграбом и должен получить изображения из памяти компьютера и сохранить их в файле изображения. после попытки в течение нескольких дней я получаю следующие 2 функции, которые создают файл, а ОС Windows может запускать файл .bmp, но растровый файл является черным (размер изображения составляет 900 КБ, 640 * 480). у любого органа есть идея, почему, картина в черном? здесь являются две функции:C Win32: save .bmp image from 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 
} 

и здесь функция для сохранения в .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; 
} 

Я могу рисовать изображения из памяти совершенно с помощью следующей функции, поэтому наверняка я не есть какие-либо проблемы для считывания данных изображения:

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); 

} 

ответ

6

Я просто узнать, что я была глупая ошибка в другой части моего кода, который я использовал:

// 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 !!!!"); 
} 

путем удаления hBitmap2 = CreateCompatibleBitmap (hDCBits, lXSize, lYSize); линии и изменение hBitmap2 на HBitmap результат CreateDIBSection(), его сохранил изображение красиво. СПАСИБО ВАМ ВСЕ ДЛЯ ВАШЕЙ ПОМОЩИ.

+0

Я ничего не менял в DrawPicture(); функция – 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

изменили мой код с помощью вашего гида, который дает мне .bin-файл, можете ли вы сообщить мне, как я могу изменить этот файл на изображение? Thankyou – user261002

+0

@ user261002, попробуйте изменить расширение на bmp и открыть его в виде растрового файла. – perreal

+0

perreal thankyou так много для вашего быстрого ответа. Я изменил fomart на .bmp, а также попытался открыть его с помощью программы просмотра фотографий Windows, но все равно это ничего не показывает мне. как вы думаете, что мне делать? пожалуйста дайте мне знать, спасибо . о, просто чтобы вы знали, у меня есть и смещенный адрес, как вы думаете, я должен добавить смещение? – user261002

2

Вы уверены, что есть правильные данные там?

Я бы попробовал extract the RGB data и сохранил его в очень простом формате «вручную», просто чтобы увидеть, что там находится. Если вы ищете мертвый простой, но все же стандартный формат изображения, посмотрите на PPM images.

+0

спасибо, я собираюсь попробовать сейчас – user261002

+1

привет, спасибо за ваше редактирование, у меня есть RGBQUAD bmicolors [256], в моем заголовочном файле, также используя я для a loor: for (i = 0; i < 256; я ++) \t \t { \t \t \t zWinGHeader.bmiColors [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} для 8bit/pixel image, вы думаете, это правильно? – user261002

2

Из документации для CreateCompatibleDC:

Когда память DC создается, его дисплей поверхность ровно один монохромный пикселей в ширину и один монохромный пиксель высокой. Прежде чем приложение сможет использовать DC для памяти для операций рисования, он должен выбрать растровое изображение правильной ширины и высоты в DC.

Поскольку вы используете CreateDIBSection с этим DC, результирующая секция DIB будет также 1-битной монохромной.