BitBlt绘制位图颠倒

时间:2012-01-26 17:48:45

标签: c++ mfc gdi

我有一个MFC控件,我将句柄传递给位图(HBITMAP)。在控件OnPaint方法中,我使用BitBlt来渲染位图。但是位图正在颠倒过来。

作为测试,我从这个句柄创建了一个CBitmap对象并将其写入文件,并创建了一个正面朝上的位图。我对BitBlt的调用是否有问题?

我在下面的OnPaint上发布了我的代码。我确实尝试将设备上下文的映射模式更改为MM_LOENGLISH,并且能够使位图正面向上渲染,但它非常粗糙。当我在MM_TEXT离开映射模式时,图像的质量是完美的,但正如我所说它是颠倒的。我没有使用位图,blitting等...因此我可能会遗漏一些简单的东西。任何其他建议将不胜感激。对于某些背景,我从摄像机驱动程序中获取BYTE *并创建HBITMAP来渲染视频。 我怎样才能正确渲染?非常感谢

void BitmapControl::OnPaint()
{
EnterCriticalSection (&CriticalSection);

if (_handleBMP)
{

    CPaintDC dc(this);
    //dc.SetMapMode(MM_LOENGLISH);
    CDC dcMem;
    dcMem.CreateCompatibleDC(&dc);

    CRect rect;
    GetClientRect(&rect);
    dc.DPtoLP(&rect);


    CBitmap* pBmpOld = dcMem.SelectObject(CBitmap::FromHandle(_handleBMP));
    BitBlt(dc,rect.left,rect.top,rect.Width(),rect.Height(),dcMem,rect.left,rect.top,SRCCOPY); //works with MM_TEXT but upsidedown
    //BitBlt(dc,0,rect.bottom,rect.Width(),-rect.Height(),dcMem,0,0,SRCCOPY); //works with MM_LOENGLISH
    dcMem.SelectObject(pBmpOld);
    DeleteDC(dc);
    DeleteDC(dcMem);
    DeleteObject(_handleBMP);
    DeleteObject(pBmpOld);
    _handleBMP = NULL;

}
LeaveCriticalSection (&CriticalSection);
}

编辑* 我假设是因为我可以将位图以正确的方向保存到磁盘,问题出在bitblt上。这是我用来生成HBITMAP的代码。

 HBITMAP BitmapWriter::CreateBitmapFromFrame(BYTE* frame)
{
BITMAPFILEHEADER* bmfh;
bmfh = (BITMAPFILEHEADER*)frame;

BITMAPINFOHEADER* bmih = &_bmi;

BITMAPINFO* bmpInfo = (BITMAPINFO*)bmih;

HBITMAP hbmp = CreateDIBSection(_hdc,bmpInfo,DIB_RGB_COLORS,NULL,NULL,0);
SetBitmapBits(hbmp,_bmi.biSizeImage,frame);


return hbmp;
}

哦,我使用了临界区,因为我将hbitmap传递给属性中的控件,然后在OnPaint中访问它。如果这是一个潜在的问题,我将不得不重新考虑。谢谢

4 个答案:

答案 0 :(得分:5)

Windows位图首先存储在底线。世界上其他大多数人都是排在第一位的,所以我认为这是你从相机中得到的。

您可以在BITMAPINFOHEADER结构中使用负高度来反转正常顺序。

答案 1 :(得分:3)

只需在BITMAPINFOHEADER结构的biHeight字段中使用负值。

bi.biHeight = -height;  //this is the line that makes it draw upside down or not

答案 2 :(得分:1)

MM_TEXT y轴向下指向,而在其他映射模式中指向它。尝试MM_ISOTROPIC映射模式。要获得更精确的控制,您可能需要在CDC上设置视口和窗口偏移量和范围。

位图可以颠倒存储,由BITMAPINFOHEADER结构中的负高度表示,但这应该不是问题。

答案 3 :(得分:1)

好吧,我似乎有这个工作。我最终将映射模式更改为MM_LOENGLISH。正如我之前所说,这给了我一个颗粒状的图像,但通过添加以下

来纠正这个问题

dc.SetStretchBltMode(COLORONCOLOR);

我需要做一些阅读才能真正找出原因......但现在这里是我的渲染代码。

void BitmapControl::OnPaint()
{
EnterCriticalSection (&CriticalSection);

if (_handleBMP)
{

    CPaintDC dc(this);
    //dc.SetMapMode(MM_ISOTROPIC);
    dc.SetMapMode(MM_LOENGLISH);
    CDC dcMem;
    dcMem.CreateCompatibleDC(&dc);

    CRect rect;
    GetClientRect(&rect);
    dc.DPtoLP(&rect);

    CBitmap* pBmpOld = dcMem.SelectObject(CBitmap::FromHandle(_handleBMP));

    //tst
    dc.SetStretchBltMode(COLORONCOLOR);

    //BitBlt(dc,rect.left,-0,rect.Width(),rect.Height(),dcMem,rect.left,rect.top,SRCCOPY); //works with MM_TEXT but upsidedown
    BitBlt(dc,0,rect.bottom,rect.Width(),-rect.Height(),dcMem,0,0,SRCCOPY); //works with MM_LOENGLISH
    dcMem.SelectObject(pBmpOld);
    DeleteDC(dc);
    DeleteDC(dcMem);
    DeleteObject(_handleBMP);
    DeleteObject(pBmpOld);
    _handleBMP = NULL;

}
LeaveCriticalSection (&CriticalSection);
}