Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I have a bitmap stored as a BGRA array of bytes. This is the code I've been using to paint the bitmap:
CDC *dispDC = new CDC();
dispDC->CreateCompatibleDC(pDC);
CBitmap *dispBMP = new CBitmap();
dispBMP->CreateCompatibleBitmap(pDC, sourceImage->GetWidth(), sourceImage->GetHeight());
dispDC->SelectObject(this->dispBMP);
The actual copying of the pixels in the translatedImage
array happens with this:
dispBMP->SetBitmapBits(sourceImage->GetArea() * 4, translatedImage);
Then after some more processing I call pDC->StretchBlt
with dispDC
as the source CDC. This works fine when logged in locally because the display is also set to 32bpp.
Once I log in with Remote Desktop, the display goes to 16bpp and the image is mangled. The culprit is SetBitmapBits
; i.e. for it to work, I have to properly fill translatedImage
with the 16bpp version of what I want to show. Rather than do this myself, I searched the documentation and found SetDIBits
which sounds like it does what I want:
The SetDIBits function sets the pixels in a compatible bitmap (DDB) using the color data found in the specified DIB.
In my case, the DIB is the 32bpp RGBA array, and the DDB is dispBMP
which I create with CreateCompatibleBitmap
.
So instead of my call to SetBitmapBits
, this is what I did:
BITMAPINFO info;
ZeroMemory(&info, sizeof(BITMAPINFO));
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info.bmiHeader.biBitCount = 32;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biCompression = BI_RGB;
info.bmiHeader.biSizeImage = sourceImage->GetArea()*4;
info.bmiHeader.biWidth = sourceImage->GetWidth();
info.bmiHeader.biHeight = sourceImage->GetHeight();
info.bmiHeader.biClrUsed = 0;
int r = SetDIBits(pDC->GetSafeHdc(), (HBITMAP)dispBMP,
0, sourceImage->GetHeight(), translatedImage,
&info, DIB_PAL_COLORS);
However, r
is always zero and, naturally, I get nothing but black in my window. What is wrong with the code?
–
The bitmap identified by the hbmp parameter must not be selected into a
device context when the application calls this function.
In your example code you select it into device context after creating it, so presumably that's why SetDIBits
is failing.
–
Ross Ridge was correct in pointing out the code order mistake. However, this didn't solve the problem.
The problem was in the parameters I was passing. I am new to C++ and MFC and often forget all the "operators" which can act on types to automatically convert them.
Previously I had this:
int r = SetDIBits(pDC->GetSafeHdc(), (HBITMAP)dispBMP,
0, sourceImage->GetHeight(), translatedImage,
&info, DIB_PAL_COLORS);
The correct call is this:
int r = SetDIBits(*pDC, *dispBMP,
0, sourceImage->GetHeight(), translatedImage,
&info, DIB_PAL_COLORS);
(Note I pass dereferenced pointers in the first two parameters.) Everything else was correct, including the counter-intuitive DIB_PAL_COLORS
flag for a bitmap which has not palette.
After obviously missing some key points in the documentation I reread it and then found this which has sample code showing that I was simply passing the parameters incorrectly.
–
–
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.