2012-01-26 107 views
3

我有一個MFC控件,我將一個句柄傳遞給位圖(HBITMAP)。在控件的OnPaint方法中,我使用BitBlt來渲染位圖。但是這個位圖被顛倒渲染。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); 
} 

編輯* 我是假設,因爲我可以將位圖保存到磁盤在正確的方向,問題是用塊傳送。這是我用來生成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。如果這是一個潛在的問題,我將不得不重新考慮這一點。謝謝

+0

它可能與您創建'_handleBMP'的方式有關,而不是您繪製它的方式。 –

+2

這在創建位圖的代碼中幾乎肯定會出錯。請注意掃描線是顛倒存儲的。順便說一句,EnterCriticalSection是繪畫代碼中的一個原始紅旗,GDI基本上不是線程安全的。 –

回答

5

Windows位圖首先存儲在底線。世界上其他大多數人都首先在頂線上工作,所以我認爲這就是你從相機中獲得的。

您可以在BITMAPINFOHEADER結構中使用負高度來反轉正常順序。

+0

我將BITMAPINFOHEADER對象中的biHeight屬性從480更改爲-480,但這沒有任何作用,它仍然呈現爲顛倒 – mash

+0

@mash,我希望您明白我的意思是在創建位圖的位置進行此更改來自原始數據。對不起,如果我不清楚。 –

+0

是的,我認爲我將它設置得晚了,我從DirectShow圖中獲取原始數據。我的圖由一個源過濾器和樣本採集器組成,我的採樣器將原始數據發佈給訂閱者,其中一個是我的呈現器。我想我需要以某種方式爲我的源過濾器設置屬性?我不知道如何做到這一點 – mash

1

MM_TEXT y軸指向下,而在其他映射模式下它指向。嘗試MM_ISOTROPIC映射模式。要進行更精確的控制,您可能需要在CDC上設置視口和窗口偏移量和範圍。

位圖可以倒過來存儲,這是由BITMAPINFOHEADER結構中的負高度指示的,但這不應該是一個問題。

+0

你總是可以否定結構中的高度,強制它在不修改映射模式的情況下繪製其他方式。 –

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

只需在BITMAPINFOHEADER結構的biHeight字段中使用負值即可。

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