why CreateDIBSection() fails with certian BITMAPINFO? - c++

I am trying to use CreateDIBSection.
Problem:
In Windows XP, I tried to call CreateDIBSection, it returns NULL and GetLastError = 0
When I try to change the screen resolution, for example to 2048 x 1536, it returns correct value.
I have tested this function has some relationship with nMemSize (not necessarily small number).
Question:
Is there any guarantee way to ensure CreateDIBSection returns correct value?
nScreenWidth = 1024;
nScreenHeight= 768;
= nScreenWidth*nScreenHeight*3*7
HDC hdc = ::GetDC(hWnd);
m_hBmpMapFile = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, nMemSize, NULL);
BITMAPINFO bmpInfo = {0};
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = nScreenWidth;
bmpInfo.bmiHeader.biHeight = nScreenHeight;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 24;
bmpInfo.bmiHeader.biCompression = 0;
bmpInfo.bmiHeader.biSizeImage = nMemSize;
bmpInfo.bmiHeader.biXPelsPerMeter = 0;
bmpInfo.bmiHeader.biYPelsPerMeter = 0;
bmpInfo.bmiHeader.biClrUsed = 0;
bmpInfo.bmiHeader.biClrImportant = 0;
bmpInfo.bmiColors[0].rgbBlue = 204;
bmpInfo.bmiColors[0].rgbGreen = 204;
bmpInfo.bmiColors[0].rgbRed = 204;
bmpInfo.bmiColors[0].rgbReserved = 0;
PVOID pvBits;
m_hBmpAllWstDskWallpaper = ::CreateDIBSection(hdc, &bmpInfo, DIB_RGB_COLORS, &pvBits, m_hBmpMapFile, 0);

I suspect the problem might be contained in the section of code that you did not include (in the elipses ...). So I recommend:
Check your Device Context is valid
ZeroMemory
Add the structure size
And bitmap dimensions
Move the GetLastError calls to ensure that the Device Context is valid (perhaps an earlier API call fails)
The code below seems to work after I added the recommendations above, I hope it helps:
HDC hdc = ::GetDC(hWnd);
int nScreenWidth = 1024;
int nScreenHeight= 768;
int nMemSize = nScreenWidth*nScreenHeight*3*7;
HANDLE m_hBmpMapFile = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, nMemSize, NULL);
BITMAPINFO bmpInfo;
//clear the memory
ZeroMemory(&bmpInfo.bmiHeader, sizeof(BITMAPINFOHEADER));
//struct size
bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
//dimensions
bmpInfo.bmiHeader.biWidth = nScreenWidth;
bmpInfo.bmiHeader.biHeight = nScreenHeight;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biSizeImage=nMemSize;
void *pvBits = NULL;
HANDLE m_hBmpAllWstDskWallpaper = ::CreateDIBSection(hdc, &bmpInfo, DIB_RGB_COLORS, &pvBits, m_hBmpMapFile, 0);
int nError = ::GetLastError();

Related

C++ GDI+ SelectPalette

I am playing with GDI+. Trying to use
pDC->SelectPalette(CPalette::FromHandle(hLogPal), FALSE);
pDC->RealizePalette();
instead of
memcpy(newBitmapInfo + sizeof(BITMAPINFO), rgbquad, palettesize);
But it seem that with it's working with memcpy(newBitmapInfo + sizeof(BITMAPINFO), rgbquad, palettesize); but with SelectPalette only black screen.
I thought that information about color can be used from bitmapinfo or from pallet.
All code:
void ConvertTo8BitImage(BYTE** pBitmapInfo, BYTE** imageData)
{
Gdiplus::GdiplusStartupInput tmp;
ULONG_PTR token;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
Gdiplus::Bitmap *source = Gdiplus::Bitmap::FromFile(L"D:/TestImage.bmp");
Gdiplus::Bitmap *destination = source->Clone(0, 0, source->GetWidth(), source->GetHeight(),
PixelFormat8bppIndexed);
int width = source->GetWidth();
int height = source->GetHeight();
HBITMAP hBitmap;
Gdiplus::Color color;
destination->GetHBITMAP(color, &hBitmap);
int palettesize = 256 * sizeof(RGBQUAD);
CLSID clsid_bmp;
CLSIDFromString(L"{557cf400-1a04-11d3-9a73-0000f81ef32e}", &clsid_bmp);
*pBitmapInfo = new BYTE[(sizeof(BITMAPINFO) + palettesize)];
BITMAPINFO* ptr = (BITMAPINFO*)*pBitmapInfo;
ptr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
ptr->bmiHeader.biWidth = width;
ptr->bmiHeader.biHeight = height;
ptr->bmiHeader.biPlanes = 1;
ptr->bmiHeader.biBitCount = 8;
ptr->bmiHeader.biCompression = BI_RGB;
ptr->bmiColors[0].rgbRed = 0;
DWORD size = ((width * 8 + 31) / 32) * 4 * height;
*imageData = new BYTE[size];
HDC hdc = GetDC(0);
GetDIBits(hdc, hBitmap, 0, height, *imageData, (BITMAPINFO*)*pBitmapInfo, DIB_PAL_COLORS);
ReleaseDC(0, hdc);
Gdiplus::GdiplusShutdown(token);
}
void CMFCApplicationColorsView::OnDraw(CDC* pDC)
{
CMFCApplicationColorsDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
BYTE *bitmapInfo = NULL;
BYTE *imageData = NULL;
ConvertTo8BitImage(&bitmapInfo, &imageData);
int palettesize = 256 * sizeof(RGBQUAD);
BYTE *newBitmapInfo = new BYTE[(sizeof(BITMAPINFO) + palettesize)];
ZeroMemory(newBitmapInfo, (sizeof(BITMAPINFO) + palettesize));
BITMAPINFO *ptr = (BITMAPINFO*)newBitmapInfo;
ptr->bmiHeader.biBitCount = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biBitCount;
ptr->bmiHeader.biClrImportant = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biClrImportant;
ptr->bmiHeader.biClrUsed = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biClrUsed;
ptr->bmiHeader.biCompression = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biCompression;
ptr->bmiHeader.biHeight = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biHeight;
ptr->bmiHeader.biPlanes = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biPlanes;
ptr->bmiHeader.biSize = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biSize;
ptr->bmiHeader.biSizeImage = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biSizeImage;
ptr->bmiHeader.biWidth = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biWidth;
ptr->bmiHeader.biXPelsPerMeter = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biXPelsPerMeter;
ptr->bmiHeader.biYPelsPerMeter = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biYPelsPerMeter;
ptr->bmiColors[0] = ((BITMAPINFO*)bitmapInfo)->bmiColors[0];
RGBQUAD rgbquad[256];
memcpy(rgbquad, bitmapInfo + sizeof(BITMAPINFO), palettesize);
//memcpy(newBitmapInfo + sizeof(BITMAPINFO), rgbquad, palettesize);
NPLOGPALETTE pPal = (NPLOGPALETTE)LocalAlloc(LMEM_FIXED,
(sizeof(LOGPALETTE) +
(sizeof(PALETTEENTRY) * (palettesize))));
pPal->palVersion = 0x300;
pPal->palNumEntries = 256;
for (int i = 0; i < 256; i++)
{
pPal->palPalEntry[i].peRed = rgbquad[i].rgbRed;
pPal->palPalEntry[i].peGreen = rgbquad[i].rgbGreen;
pPal->palPalEntry[i].peBlue = rgbquad[i].rgbBlue;
pPal->palPalEntry[i].peFlags = 0;
}
HPALETTE hLogPal = CreatePalette((LPLOGPALETTE)pPal);
pDC->SelectPalette(CPalette::FromHandle(hLogPal), FALSE);
pDC->RealizePalette();
StretchDIBits(pDC->GetSafeHdc(), 0, 0, 1920, 1080, 0, 0, 1920, 1080,
imageData, ptr, DIB_PAL_COLORS, SRCCOPY);
delete[] bitmapInfo;
delete[] imageData;
}
HBITMAP hBitmap;
Gdiplus::Color color;
destination->GetHBITMAP(color, &hBitmap);
You did convert to 8-bit bitmap, however GetHBITMAP will return a bitmap handle compatible with your video card, which is probably 32-bit. GDI+ has already processed the palette and returned a bitmap handle which is turned back in to 32-bit. HBITMAP handle can be painted directly, for example using CreateCompatibleDC and BitBlt. So there is no need to obtaining the palette and passing it to GDI, and no need for 8-bit conversion in the first place.
If this is necessary for some reason, you can get the bits and palette from 32-bit bitmap, put that in 8-bit bitmap, and draw with StretchDIBits
The main issue in your code is that it should use DIB_RGB_COLORS flag for GetDIBits/StretchDIBits, because the device context is most likely 32-bit. There is no need for SelectPalette/RealizePalette either (unless it's 8-bit display from 30 years ago)
It makes more sense to get the bits directly from GDI+ using LockBits, and get the palette directly using GetPalette, as seen in the example below.
Aside, source and destination have to be deleted before exit.
void draw(HDC hdc)
{
Gdiplus::Bitmap *source = Gdiplus::Bitmap::FromFile(L"D:/TestImage.bmp");
if(!source)
return;
int width = source->GetWidth();
int height = source->GetHeight();
Gdiplus::Bitmap *destination = source->Clone(0, 0, width, height,
PixelFormat8bppIndexed);
//get bitmap bits from GDI+
Gdiplus::BitmapData data;
Gdiplus::Rect rect(0, 0, width, height);
destination->LockBits(&rect, Gdiplus::ImageLockModeRead,
destination->GetPixelFormat(), &data);
int bufsize = data.Stride * data.Height;
BYTE *buf = new BYTE[bufsize];
memcpy(buf, data.Scan0, bufsize);
destination->UnlockBits(&data);
//setup BITMAPINFO
int bmpinfo_size = sizeof(BITMAPINFO) + 256 * 4;
BITMAPINFO* bmpinfo = (BITMAPINFO*)new BYTE[bmpinfo_size];
memset(bmpinfo, 0, bmpinfo_size);
bmpinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpinfo->bmiHeader.biWidth = width;
bmpinfo->bmiHeader.biHeight = -height;
bmpinfo->bmiHeader.biPlanes = 1;
bmpinfo->bmiHeader.biBitCount = 8;
bmpinfo->bmiHeader.biCompression = BI_RGB;
bmpinfo->bmiHeader.biSizeImage = bufsize;
//get palette from GDI+
int palsize = destination->GetPaletteSize();
Gdiplus::ColorPalette *palette = (Gdiplus::ColorPalette*)new BYTE[palsize];
destination->GetPalette(palette, palsize);
//set palette for BITMAPINFO
memset(&bmpinfo->bmiColors[0], 0, 256 * 4);
for(int i = 0; i < palette->Count; i++)
{
auto clr = Gdiplus::Color(palette->Entries[i]);
bmpinfo->bmiColors[i].rgbRed = clr.GetR();
bmpinfo->bmiColors[i].rgbGreen = clr.GetG();
bmpinfo->bmiColors[i].rgbBlue = clr.GetB();
bmpinfo->bmiColors[i].rgbReserved = 0;
}
StretchDIBits(hdc, 0, 0, width, height, 0, 0, width, height,
buf, bmpinfo, DIB_RGB_COLORS, SRCCOPY);
delete[] buf;
delete[] bmpinfo;
delete[] palette;
delete destination;
delete source;
}
void CMFCApplicationColorsView::OnDraw(CDC* pDC)
{
CMFCApplicationColorsDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
Gdiplus::GdiplusStartupInput tmp;
ULONG_PTR token;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
draw(pDC->GetSafeHdc());
Gdiplus::GdiplusShutdown(token);
}

How to display image using CreateDIBSection

I want to display a images on window, am giving image data as in buffer &CaptureBuffer to CreateDIBSection, CreateDIBForVideo method is calling from thread on main().
dont know where im going wrong it is showing black window.
void CreateDIBForVideo()
{
// ScreenCaptureProcessorGDI is a class it have initialization for capture window screen
screenObject = new ScreenCaptureProcessorGDI();
screenObject->init();
HDC DisplayDC = CreateDC((LPCWSTR)"DISPLAY", NULL, NULL, NULL);
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biSize= sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = screenObject->lOutputDuplDesc.ModeDesc.Width;
bmpInfo.bmiHeader.biHeight= screenObject->lOutputDuplDesc.ModeDesc.Height;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biSizeImage = (4 * screenObject->lOutputDuplDesc.ModeDesc.Width * screenObject->lOutputDuplDesc.ModeDesc.Height);
bmpInfo.bmiHeader.biXPelsPerMeter = 0;
bmpInfo.bmiHeader.biYPelsPerMeter = 0;
bmpInfo.bmiHeader.biClrUsed = 0;
bmpInfo.bmiHeader.biClrImportant = 0;
CaptureBuffer = NULL;
HDC pXorDC = CreateCompatibleDC(DisplayDC);
HBITMAP hXorDib = CreateDIBSection(DisplayDC, &bmpInfo, DIB_RGB_COLORS, (void**)&CaptureBuffer, NULL, 0);
hXorTemp = (HBITMAP)SelectObject(pXorDC, hXorDib);
// startGrab this thread capture a windows screen after init()
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&startGrab, NULL, 0, NULL);
}
void startGrab()
{
for (int index = 0; index < 100; index++)
{
// grabImage will capture window screen and send image as a buffer to `CaptureBuffer`
screenObject->grabImage();
PaintViewerWindow();
UpdateWindow(global_hWnd);
::Sleep(2000);
}
}
void PaintViewerWindow()
{
HDC paintDC;
PAINTSTRUCT ps;
paintDC = BeginPaint(global_hWnd, &ps);
SetStretchBltMode(paintDC, HALFTONE);
BitBlt(paintDC, 0, 0, 1366, 768, pXorDC, 0, 0, SRCCOPY);
EndPaint(global_hWnd, &ps);
}
I find a solution for the above problem
It because of UCHAR *CaptureBuffer am directly passing CaptureBuffer to the CreateDIBSection now i changed to copying UCHAR *CaptureBuffer to char *DisplayBuffer its working fine now.
UCHAR *CaptureBuffer = NULL;
char *DisplayBuffer = NULL;
long CaptureSize = NULL;
void saveImage(unsigned int frame_num, BITMAPINFO &lBmpInfo, std::unique_ptr<BYTE> pBuf, UCHAR* &CaptureBuffer, long &CaptureSize)
{
BITMAPFILEHEADER bmpFileHeader;
bmpFileHeader.bfReserved1 = 0;
bmpFileHeader.bfReserved2 = 0;
bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + lBmpInfo.bmiHeader.biSizeImage;
bmpFileHeader.bfType = 'MB';
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
CaptureSize = lBmpInfo.bmiHeader.biSizeImage;
CaptureBuffer = (UCHAR*)malloc(CaptureSize);
memcpy(CaptureBuffer, pBuf.get(), lBmpInfo.bmiHeader.biSizeImage);
//Here am copying CaptureBuffer(uchar) to DisplayBuffer(char)
memcpy(DisplayBuffer, CaptureBuffer, CaptureSize);
lresult = 0;
}
void CreateDIBForVideo()
{
// ScreenCaptureProcessorGDI is a class it have initialization for capture window screen
screenObject = new ScreenCaptureProcessorGDI();
screenObject->init();
HDC DisplayDC = CreateDC((LPCWSTR)"DISPLAY", NULL, NULL, NULL);
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biSize= sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = screenObject->lOutputDuplDesc.ModeDesc.Width;
bmpInfo.bmiHeader.biHeight= screenObject->lOutputDuplDesc.ModeDesc.Height;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biSizeImage = (4 * screenObject->lOutputDuplDesc.ModeDesc.Width * screenObject->lOutputDuplDesc.ModeDesc.Height);
bmpInfo.bmiHeader.biXPelsPerMeter = 0;
bmpInfo.bmiHeader.biYPelsPerMeter = 0;
bmpInfo.bmiHeader.biClrUsed = 0;
bmpInfo.bmiHeader.biClrImportant = 0;
CaptureBuffer = NULL;
HDC pXorDC = CreateCompatibleDC(DisplayDC);
HBITMAP hXorDib = CreateDIBSection(DisplayDC, &bmpInfo, DIB_RGB_COLORS, (void**)&DisplayBuffer, NULL, 0);
hXorTemp = (HBITMAP)SelectObject(pXorDC, hXorDib);
// startGrab this thread capture a windows screen after init()
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&startGrab, NULL, 0, NULL);
}

Directx 11 Bitblt Alternative

I have the following function which I am trying to integrate into my directx 11 application. When I am using directx9 everything works fine but when converting to directx 11 I am getting a blue screen of death error at the Bitblt line (I must be doing something wrong with the HDC's?). I was wondering what the best way to convert this code to directx 11 compatible surfaces instead of HDC's would be.
Here is the function:
void CFlashDXPlayer::DrawFrame(HDC dc)
{
if (m_dirtyFlag)
{
IViewObject* pViewObject = NULL;
m_flashInterface->QueryInterface(IID_IViewObject, (LPVOID*) &pViewObject);
if (pViewObject != NULL)
{
// Combine regions
HRGN unionRgn, first, second = NULL;
unionRgn = CreateRectRgnIndirect(&m_dirtyRects[0]);
if (m_dirtyRects.size() >= 2)
second = CreateRectRgn(0, 0, 1, 1);
for (std::vector<RECT>::iterator it = m_dirtyRects.begin() + 1; it != m_dirtyRects.end(); ++it)
{
// Fill combined region
first = unionRgn;
SetRectRgn(second, it->left, it->top, it->right, it->bottom);
unionRgn = CreateRectRgn(0, 0, 1, 1);
CombineRgn(unionRgn, first, second, RGN_OR);
DeleteObject(first);
}
if (second)
DeleteObject(second);
RECT clipRgnRect; GetRgnBox(unionRgn, &clipRgnRect);
RECTL clipRect = { 0, 0, m_width, m_height };
// Fill background
if (m_transpMode != TMODE_FULL_ALPHA)
{
// Set clip region
SelectClipRgn(dc, unionRgn);
COLORREF fillColor = GetBackgroundColor();
HBRUSH fillColorBrush = CreateSolidBrush(fillColor);
FillRgn(dc, unionRgn, fillColorBrush);
DeleteObject(fillColorBrush);
// Draw to main buffer
HRESULT hr = pViewObject->Draw(DVASPECT_TRANSPARENT, 1, NULL, NULL, NULL, dc, &clipRect, &clipRect, NULL, 0);
assert(SUCCEEDED(hr));
}
else
{
if (m_alphaBlackDC == NULL)
{
// Create memory buffers
BITMAPINFOHEADER bih = {0};
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biBitCount = 32;
bih.biCompression = BI_RGB;
bih.biPlanes = 1;
bih.biWidth = LONG(m_width);
bih.biHeight = -LONG(m_height);
m_alphaBlackDC = CreateCompatibleDC(dc);
m_alphaBlackBitmap = CreateDIBSection(m_alphaBlackDC, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&m_alphaBlackBuffer, 0, 0);
SelectObject(m_alphaBlackDC, m_alphaBlackBitmap);
m_alphaWhiteDC = CreateCompatibleDC(dc);
m_alphaWhiteBitmap = CreateDIBSection(m_alphaWhiteDC, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&m_alphaWhiteBuffer, 0, 0);
SelectObject(m_alphaWhiteDC, m_alphaWhiteBitmap);
}
HRESULT hr;
HBRUSH fillColorBrush;
// Render frame twice - against white and against black background to calculate alpha
SelectClipRgn(m_alphaBlackDC, unionRgn);
COLORREF blackColor = 0x00000000;
fillColorBrush = CreateSolidBrush(blackColor);
FillRgn(m_alphaBlackDC, unionRgn, fillColorBrush);
DeleteObject(fillColorBrush);
hr = pViewObject->Draw(DVASPECT_TRANSPARENT, 1, NULL, NULL, NULL, m_alphaBlackDC, &clipRect, &clipRect, NULL, 0);
assert(SUCCEEDED(hr));
// White background
SelectClipRgn(m_alphaWhiteDC, unionRgn);
COLORREF whiteColor = 0x00FFFFFF;
fillColorBrush = CreateSolidBrush(whiteColor);
FillRgn(m_alphaWhiteDC, unionRgn, fillColorBrush);
DeleteObject(fillColorBrush);
hr = pViewObject->Draw(DVASPECT_TRANSPARENT, 1, NULL, NULL, NULL, m_alphaWhiteDC, &clipRect, &clipRect, NULL, 0);
assert(SUCCEEDED(hr));
// Combine alpha
for (LONG y = clipRgnRect.top; y < clipRgnRect.bottom; ++y)
{
int offset = y * m_width * 4 + clipRgnRect.left * 4;
for (LONG x = clipRgnRect.left; x < clipRgnRect.right; ++x)
{
BYTE blackRed = m_alphaBlackBuffer[offset];
BYTE whiteRed = m_alphaWhiteBuffer[offset];
m_alphaBlackBuffer[offset + 3] = 255 - (whiteRed - blackRed);
offset += 4;
}
}
// Blit result to target DC
BitBlt(dc, clipRgnRect.left, clipRgnRect.top,
clipRgnRect.right - clipRgnRect.left,
clipRgnRect.bottom - clipRgnRect.top,
m_alphaBlackDC, clipRgnRect.left, clipRgnRect.top, SRCCOPY);
}
DeleteObject(unionRgn);
pViewObject->Release();
}
m_dirtyFlag = false;
m_dirtyRects.clear();
m_dirtyUnionRect.left = m_dirtyUnionRect.top = LONG_MAX;
m_dirtyUnionRect.right = m_dirtyUnionRect.bottom = -LONG_MAX;
}
}
The HDC I am passing to this function is created in the following manner:
D3D11_TEXTURE2D_DESC textureDesc;
ZeroMemory(&textureDesc, sizeof(textureDesc));
textureDesc.Width = width;
textureDesc.Height = height;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
textureDesc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
HRESULT hr = device->CreateTexture2D(&textureDesc, NULL, &m_flashTexture);
HRESULT hResult;
HDC hDC;
IDXGISurface1 *pSurface = NULL;
hResult = m_flashTexture->QueryInterface(__uuidof(IDXGISurface1), (void**)&pSurface);
hResult = pSurface->GetDC(TRUE, &hDC);
assert(SUCCEEDED(hResult));
m_flashPlayer->DrawFrame(hDC);
Any ideas of what I am doing wrong? I can't seem to figure out what is going on and why this is casuing a blue screen when if I use Directx 9 obejcts it doesn't. Is there a better way to do this?
(Also I've tried updating my drivers and they are all up to date).
Thank you for the help.
Turns out that this was indeed a driver issue. It works without a problem when I run with my graphics card set to the radeon in my latop, but when I have it on switchable for some reason it still crashes even though it should be selecting my radeon. I need to have the graphics mode fixed. Weird, but atleast its not my program I guess.
Can't really tell from code inspection. I haven't noticed anything blatantly wrong. There certainly should not be a any BSOD - that part is a driver bug. What hardware/driver are you running on?
A common reason for driver crashes though is illegally writing to some memory area, often if you're blitting to outside of your DC memory. I'd double check to verify that your regions are not out of bounds and that m_alphaBlackDC is the same size as dc.
I would also highly, highly recommend testing on another non-related GPU (that doesn't share the same hardware architecture).

StretchBlt and filtering alpha channels

I am scaling an image down with StretchBlt().
http://img684.imageshack.us/img684/2152/stretchblt.png
As you can see, it currently looks like I have to choose between quality filtering and transparency. Is there any way to get both? This is the only image operation I need to perform, so I'd prefer to avoid extra libraries.
My code:
HDC srcDC = CreateCompatibleDC(NULL);
SelectObject(srcDC, *phbmp);
HDC destDC = CreateCompatibleDC(srcDC);
HBITMAP NewBMP = CreateCompatibleBitmap(srcDC,NewWidth,NewHeight);
SelectObject(destDC,NewBMP);
SetStretchBltMode(destDC,HALFTONE);
SetBrushOrgEx(destDC,0,0,NULL);
if (StretchBlt(destDC,0,0,NewWidth,NewHeight,srcDC,0,0,width,height,SRCCOPY) == TRUE)
{
DeleteObject(*phbmp);
*phbmp = NewBMP;
hr = S_OK;
}
else
DeleteObject(NewBMP);
DeleteDC(srcDC);
DeleteDC(destDC);
Gave up entirely on GDI in the end. Turns out that the proper way of doing this is, of course, with IWICImagingFactory. Final code:
IWICImagingFactory *pImgFac;
hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImgFac));
IWICBitmap* NewBmp;
hr = pImgFac->CreateBitmapFromHBITMAP(*phbmp,0,WICBitmapUseAlpha,&NewBmp);
BITMAPINFO bmi = {};
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = NewWidth;
bmi.bmiHeader.biHeight = -NewHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
BYTE *pBits;
HBITMAP hbmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0);
hr = hbmp ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
IWICBitmapScaler* pIScaler;
hr = pImgFac->CreateBitmapScaler(&pIScaler);
hr = pIScaler->Initialize(NewBmp,NewWidth,NewHeight,WICBitmapInterpolationModeFant);
WICRect rect = {0, 0, NewWidth, NewHeight};
hr = pIScaler->CopyPixels(&rect, NewWidth * 4, NewWidth * NewHeight * 4, pBits);
if (SUCCEEDED(hr))
*phbmp = hbmp;
else
DeleteObject(hbmp);
pIScaler->Release();
}
NewBmp->Release();
pImgFac->Release();

How do I create a bitmap using the BITMAPV5HEADER header?

This is my current code, but it causes an error when casting to BITMAPINFOHEADER:
/* Create the bitmap */
BITMAPINFO bmpinfo;
ZeroMemory(&bmpinfo, sizeof(bmpinfo));
BITMAPV5HEADER bmpheader;
ZeroMemory(&bmpheader, sizeof(bmpheader));
bmpheader.bV5Size = sizeof(BITMAPV5HEADER);
bmpheader.bV5Width = width;
bmpheader.bV5Height = height;
bmpheader.bV5Planes = 1;
bmpheader.bV5BitCount = 32;
bmpheader.bV5Compression = BI_BITFIELDS;
bmpheader.bV5SizeImage = width*height*4;
bmpheader.bV5RedMask = 0x00FF0000;
bmpheader.bV5GreenMask = 0x0000FF00;
bmpheader.bV5BlueMask = 0x000000FF;
bmpheader.bV5AlphaMask = 0xFF000000;
bmpheader.bV5CSType = 0x57696e20; // LCS_WINDOWS_COLOR_SPACE
bmpheader.bV5Intent = LCS_GM_BUSINESS;
bmpinfo.bmiHeader = reinterpret_cast<BITMAPINFOHEADER>(bmpheader);
void* converted = NULL;
HDC screen = GetDC(NULL);
HBITMAP result = CreateDIBSection(screen, &bmpinfo, DIB_RGB_COLORS, &converted, NULL, 0);
ReleaseDC(NULL, screen);
// Image data filled here
How will I be able to do this successfully?
BITMAPINFO isn't a true structure, it's more just documentation about how the color map follows the header. Just pass your BITMAPV5HEADER directly to CreateDIBSection:
HBITMAP result = CreateDIBSection(screen, reinterpret_cast<BITMAPINFO *>(&bmpheader), DIB_RGB_COLORS, &converted, NULL, 0);