2012-03-06 33 views
11

Tôi đang làm việc với một bộ khung và cần lấy hình ảnh từ bộ nhớ máy tính và lưu chúng vào một tệp hình ảnh. sau khi thử vài ngày, tôi kết thúc với 2 chức năng sau, điều này tạo ra một tệp và cửa sổ OS có thể chạy tệp .bmp, nhưng tệp bitmap là màu đen (kích thước hình ảnh là 900KB, 640 * 480). không có bất kỳ cơ thể có bất kỳ ý tưởng tại sao, hình ảnh màu đen? đây là hai chức năng:C Win32: lưu hình ảnh .bmp từ 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 
} 

và đây là chức năng để lưu vào .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; 
} 

TÔI CÓ THỂ Vẽ các hình ảnh từ bộ nhớ hoàn hảo với các chức năng sau đây, vì vậy chắc chắn Tôi không có bất kỳ vấn đề cho việc đọc dữ liệu hình ảnh:

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

} 

Trả lời

6

Tôi chỉ tìm hiểu tôi đã có một sai lầm ngớ ngẩn trong một phần khác của mã của tôi Tôi đã sử dụng:

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

bằng cách xóa dòng hBitmap2 = CreateCompatibleBitmap (hDCBits, lXSize, lYSize);, và thay đổi hBitmap2 để hBitmap kết quả của CreateDIBSection(), nó lưu hình ảnh đẹp. CÁM ƠN SỰ GIÚP ĐỠ TỪ MỌI NGƯỜI.

+0

Tôi không thay đổi gì trong DrawPicture(); chức năng – 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

đã thay đổi mã của tôi bằng hướng dẫn, cung cấp cho tôi tệp .bin, bạn có thể vui lòng cho tôi biết cách tôi có thể thay đổi tệp này thành hình ảnh không? Thankyou – user261002

+0

@ user261002, thử thay đổi phần mở rộng thành bmp và mở nó dưới dạng tệp bitmap. – perreal

+0

perreal thankyou rất nhiều cho phản ứng nhanh chóng của bạn. Tôi đã thay đổi fomart để .bmp và cũng cố gắng để mở nó với cửa sổ xem ảnh, nhưng nó vẫn không hiển thị cho tôi bất cứ điều gì. bạn nghĩ gì, tôi nên làm gì? Xin vui lòng cho tôi biết, cảm ơn . oh, chỉ để cho bạn biết, tôi có một số địa chỉ bù đắp là tốt, bạn có nghĩ rằng tôi sẽ thêm bù đắp? – user261002

2

Bạn có chắc chắn có dữ liệu phù hợp không?

Tôi sẽ thử extract the RGB data và lưu nó ở định dạng rất đơn giản "theo cách thủ công", chỉ để xem nội dung trong đó. Nếu bạn đang tìm kiếm một định dạng hình ảnh đơn giản nhưng vẫn còn tiêu chuẩn, hãy xem PPM images.

+0

cảm ơn bạn, tôi sẽ thử ngay bây giờ – user261002

+1

hi, cảm ơn bạn đã chỉnh sửa, tôi có RGBQUAD bmicolors [256]; trong tệp tiêu đề của tôi, cũng sử dụng tôi có loor: for (i = 0; i < 256; i ++) \t \t { \t \t \t zWinGHeader.bmiColors [i] .rgbGreen \t = i; \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} cho hình ảnh 8 bit/pixel, bạn có nghĩ điều này đúng không? – user261002

2

Từ tài liệu cho CreateCompatibleDC:

Khi bộ nhớ DC được tạo ra, bề mặt hiển thị của nó là chính xác một đơn sắc rộng pixel và một đơn sắc điểm ảnh cao. Trước khi một ứng dụng có thể sử dụng bộ nhớ DC cho hoạt động vẽ, nó phải chọn một bitmap có chiều rộng và chiều cao chính xác vào DC.

Vì bạn đang sử dụng CreateDIBSection với DC đó, phần DIB kết quả cũng sẽ là đơn sắc 1 bit.