BitBlt drawing bitmap upside down

匿名 (未验证) 提交于 2019-12-03 00:56:02

问题:

I have an MFC control to which I pass a handle to a bitmap (HBITMAP). In the controls OnPaint method I am using BitBlt to render the bitmap. But the bitmap is being rendered upside down.

As a test I created a CBitmap object from this handle and write that out to a file and it created a bitmap that was right side up. So am I doing something wrong with my call to BitBlt?

I've posted my code from OnPaint below. I did try to change the mapping mode of my device context to MM_LOENGLISH and was able to get the bitmap to render right side up but it was very grainy. When I leave the mapping mode at MM_TEXT the quality of the image is perfect but as I said it is upside down. I haven't worked much with bitmaps, blitting etc...so I could be missing something easy. Any other suggestions would be appreciated. For some background I'm grabbing a BYTE* from a video camera driver and creating the HBITMAP to render the video. How can I get this to render properly?? Many thanks

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

edit* I was assuming because I could save the bitmap to disk in the correct orientation that the problem was with bitblt. Here is the code I use to generate the 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; } 

Oh, and I used the critical section because I pass the hbitmap to the control in a property and then access it in the OnPaint. If that's a potential problem I will have to rethink that. Thanks

回答1:

Windows bitmaps are stored with the bottom line first. Most of the rest of the world works top line first, so I presume that's what you're getting from your camera.

You can use a negative height in the BITMAPINFOHEADER structure to reverse the normal order.



回答2:

Just use a Negative value in the biHeight field of BITMAPINFOHEADER struct.

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


回答3:

In MM_TEXT y-axis points down, while in the other mapping modes it points up. Try MM_ISOTROPIC mapping mode. For more precise control, you may need to set viewport and window offset and extents on CDC.

Bitmaps can be stored upside down, that is indicated by negative height in the BITMAPINFOHEADER structure, but this should not be a problem.



回答4:

Ok, I seem to have this working. I ended up changing the mapping mode to MM_LOENGLISH. As I said before this gave me a grainy image but this was corrected by adding the following

dc.SetStretchBltMode(COLORONCOLOR);

I need to do a bit of reading to actually figure out why...but here is my rendering code now.

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!