创建,显示,然后访问位图/ DIB数据(没有GetBitmapBits())

时间:2015-03-13 14:23:50

标签: c++ bitmap mfc dib

我继承了一个老式的MFC Windows CE程序,我不得不对它进行一些修改。作为其中的一部分,我必须创建一个带有文本的单色图像,并将其显示在屏幕上,并将每行图像一次发送到一台打印机。

我最初使用了一个位图,并成功使用了DrawText()并获得了一个测试字符串(Hello World)以显示在屏幕上(此代码如图1所示)。但是,在我想要从位图中提取包装数据的阶段,我碰到了一堵墙。我想要得到的是一个代表黑色或白色的1或0的数组。我首先想到我会使用GetBitmapBits()但不幸的是我正在使用的代码太旧了,以至于还不支持该功能。我以为我可以通过使用GetBitmap()然后访问bmBits参数来解决这个问题。但是,这似乎始终为null,当我找到以下链接时确认:Why does GetObject return an BITMAP with null bmBits?

我的下一次尝试是遵循链接中的建议并使用CreateDIBSection()而不是CreateCompatibleBitmap()。这似乎是正确的路径,我应该可以访问我想要的数据,但不幸的是我无法显示DIB(代码如图2所示)。我怀疑我在创建DIB的标题时做错了什么,但我无法弄清楚我的错误是什么。

如果有人建议访问位图中的数据,或者可以看到我在DIB上做错了什么,我将非常感谢您的帮助!

***图1:创建和显示位图的代码

void CRunPage::OnPaint() 
{
    CPaintDC dc(this);          // property page device context for painting
    CBitmap mBmp;               // CBitmap object for displaying built-in bitmaps
    CDC mDCMem;                 // CDC object to handle built-in bitmap
    int iWidth, iHeight;        // dimension to draw on the screen

    int icurLabel,              // current label index of open print file
        iLabelNum;              // number of labels in open print file
    LPBITMAPINFOHEADER pBMIH;   // bitmap header object for current label
    LPBYTE pImage;              // bitmap data for current label
    CSize size;                 // size of label
    int PreviewLeft,PreviewTop,PreviewWidth,PreviewHeight;
    CRect Rect;
    BITMAP bm;
    LPVOID bmBits=NULL;

    // Calculate the preview area
    PreviewLeft=5;
    PreviewTop=5;
    GetDlgItem(IDC_RUN_NEXT)->GetWindowRect(&Rect);
    ScreenToClient(&Rect);
    PreviewWidth=Rect.left-PreviewLeft*2;
    GetDlgItem(IDC_RUN_WRAPTEXT)->GetWindowRect(&Rect);
    ScreenToClient(&Rect);
    PreviewHeight=Rect.top-PreviewTop*2;

    CRect textRect;
    CString testText(_T("Hello World"));

    CBitmap * pOldBitmap;
    CBrush whiteBrush, *pOldBrush;
    CPen blackPen, *pOldPen;


    mDCMem.CreateCompatibleDC(&dc);

    mBmp.CreateCompatibleBitmap(&dc, PreviewWidth+PreviewLeft*2, PreviewHeight+PreviewTop*2);
    //mBmp.CreateCompatibleBitmap(&dc, PreviewWidth, PreviewHeight);
    pOldBitmap = mDCMem.SelectObject(&mBmp);

    blackPen.CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
    whiteBrush.CreateSolidBrush(RGB(255,255,255));

    textRect.SetRect(0,0,PreviewWidth, PreviewHeight);

    // this means behind the text will be a white box w/ a black boarder
    pOldBrush = mDCMem.SelectObject(&whiteBrush);
    pOldPen = mDCMem.SelectObject(&blackPen);

    //these commands draw on the memory-only context (mDCMem)
    mDCMem.Rectangle(&textRect);
    mDCMem.DrawText((LPCTSTR)testText, 11, &textRect, DT_CENTER|DT_VCENTER);

    mDCMem.SelectObject(pOldBrush);
    mDCMem.SelectObject(pOldPen);

    dc.StretchBlt(PreviewLeft,PreviewTop, PreviewWidth, PreviewHeight, & mDCMem, 0, 0, PreviewWidth, PreviewHeight, SRCCOPY);

    mDCMem.SelectObject(pOldBitmap);

}

***图2:尝试使用DIB而不是位图

void CRunPage::OnPaint() 
{

    CPaintDC dc(this);          // property page device context for painting

    CBitmap mBmp;               // CBitmap object for displaying built-in bitmaps
    CDC mDCMem;                 // CDC object to handle built-in bitmap
    int iWidth, iHeight;        // dimension to draw on the screen

    int icurLabel,              // current label index of open print file
        iLabelNum;              // number of labels in open print file
    LPBITMAPINFOHEADER pBMIH;   // bitmap header object for current label
    LPBYTE pImage;              // bitmap data for current label
    CSize size;                 // size of label
    int PreviewLeft,PreviewTop,PreviewWidth,PreviewHeight;
    CRect Rect;
    BITMAP bm;

    // Calculate the preview area
    PreviewLeft=5;
    PreviewTop=5;
    GetDlgItem(IDC_RUN_NEXT)->GetWindowRect(&Rect);
    ScreenToClient(&Rect);
    PreviewWidth=Rect.left-PreviewLeft*2;
    GetDlgItem(IDC_RUN_WRAPTEXT)->GetWindowRect(&Rect);
    ScreenToClient(&Rect);
    PreviewHeight=Rect.top-PreviewTop*2;

    CRect textRect;
    CString testText(_T("Hello World"));

    CBitmap * pOldBitmap;
    CBrush whiteBrush, *pOldBrush;
    CPen blackPen, *pOldPen;

    LPBYTE pFWandImageMem=NULL, pImageMem=NULL, pTemp=NULL;
    int i=0,j=0, buffSize=0, numBytesPerRow=0, bitmapWidthPix,bitmapHeightPix;

    char *numBytesPerRowString;
    char temp;
    void ** ppvBits;
    BITMAPINFOHEADER bmif;
    BITMAPINFO bmi;
    HBITMAP myDIB, myOldDIB;

    mDCMem.CreateCompatibleDC(&dc);

    //this rect is the area in which I can draw (its x,y location is set by BitBlt or StretchBlt
    //mBmp.CreateCompatibleBitmap(&dc, PreviewWidth+PreviewLeft*2, PreviewHeight+PreviewTop*2);

    bmif.biSize = sizeof(BITMAPINFOHEADER);
    bmif.biWidth = PreviewWidth+PreviewLeft*2;
    bmif.biHeight = -(PreviewHeight+PreviewTop*2);//- means top down (I think? I tried both ways and neither worked)
    bmif.biPlanes = 1;
    bmif.biBitCount = 1;
    bmif.biCompression = BI_RGB; // no compression
    bmif.biSizeImage = 0; // Size (bytes) if image - this can be set to 0 for uncompressed images
    bmif.biXPelsPerMeter = 0;
    bmif.biYPelsPerMeter = 0;
    bmif.biClrUsed =0;
    bmif.biClrImportant = 0;

    bmi.bmiColors[0].rgbBlue=0;
    bmi.bmiColors[0].rgbGreen=0;
    bmi.bmiColors[0].rgbRed=0;
    bmi.bmiColors[0].rgbReserved=0;
    bmi.bmiColors[1].rgbBlue=255;
    bmi.bmiColors[1].rgbGreen=255;
    bmi.bmiColors[1].rgbRed=255;
    bmi.bmiColors[1].rgbReserved=0;

    bmi.bmiHeader=bmif;

    myDIB = CreateDIBSection(dc.GetSafeHdc(), &bmi, DIB_RGB_COLORS, ppvBits, NULL, 0);

    myOldDIB = (HBITMAP)mDCMem.SelectObject(myDIB);//SelectObject(mDCMem, myDIB);
blackPen.CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
whiteBrush.CreateSolidBrush(RGB(255,255,255));

textRect.SetRect(0,0,PreviewWidth, PreviewHeight);

// this means behind the text will be a white box w/ a black boarder
pOldBrush = mDCMem.SelectObject(&whiteBrush);
pOldPen = mDCMem.SelectObject(&blackPen);

//these commands draw on the memory-only context (mDCMem)
mDCMem.Rectangle(&textRect);
mDCMem.DrawText((LPCTSTR)testText, 11, &textRect, DT_CENTER|DT_VCENTER);

mDCMem.SelectObject(pOldBrush);
mDCMem.SelectObject(pOldPen);

dc.StretchBlt(PreviewLeft,PreviewTop, PreviewWidth, PreviewHeight, & mDCMem, 0, 0, PreviewWidth, PreviewHeight, SRCCOPY);

mDCMem.SelectObject(myOldDIB);

}

1 个答案:

答案 0 :(得分:0)

所以我对DIB代码做了两处小改动,现在正确显示图像。

首先,我改变了传递给CreateDIBSection()的指针的方式:

void ** ppvBits;

LPBYTE pBits;

然后我不得不改变将其传递给CreateDIBSection的方式。我还明确地将CreateDIBSection()的返回转换为HBITMAP:

myDIB = CreateDIBSection(dc.GetSafeHdc(), &bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0);

myDIB = (HBITMAP) CreateDIBSection(dc.GetSafeHdc(), &bmi, DIB_RGB_COLORS, ppvBits, NULL, 0);

我没有机会看到我是否可以访问图像数据,但我现在已经过了最初的问题。感谢任何看过这个的人,如果有人知道如何做第一个(设备相关的位图)方法,我很想知道。