Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

StretchBlt DirectDrawSurface to a memory image DC gives me a Black n White image

23 views
Skip to first unread message

Gishu....@gmail.com

unread,
Jul 19, 2007, 11:29:44 AM7/19/07
to
Hi,
I have a Direct 3D Retained Mode application for which I need to add
print support.

What I have done is similar to
http://groups.google.com/group/microsoft.public.win32.programmer.directx/browse_thread/thread/79faf1222abafdce/08ee4eb61ed97ce1?lnk=gst&q=printing&rnum=58#08ee4eb61ed97ce1

1. Get the hDC from the BackSurface
2. Create a compatible memory image DC
3. StretchBlt the BackSurface contents to the memory image whose size
I have determined from the print page's size
4. Next BitBlt to printer DC (The memory image was needed coz you
can't StretchBlt to a printer DC)

PROBLEM : I am losing all color information on the printed image !
-------------------------------------------------------------------------------------------------

I tried a few things
- BitBlt directly from DD Surface DC to Printer DC
Result : Get a miniscule image but with color when printed
- BitBlt from DD Surface DC to Memory Image of same size as surface
and then BitBlt to Printer
Result : Get a miniscule image but all black n white
- BitBlt from DD Surface DC to Memory image (scaled up so as to best
fit the page) and then BitBlt to printer DC
Result : Get a properly scaled image but all black n white

This leads me to believe that the middle step of transferring onto a
Memory Image is losing all the Color.
Any ideas / pointers / suggestions most welcome..

Thanks,
Gishu


Code - Last approach:

HDC hDC_BackSurface;
hrRetVal = m_DDSBack->GetDC(&hDC_BackSurface);

CDC* pobSurfaceDC = CDC::FromHandle(hDC_BackSurface);
CDC* pobPrinterDC = CDC::FromHandle(hDC_Printer);

HDC hDC_TempMemImage = ::CreateCompatibleDC(hDC_BackSurface);
HBITMAP hBmp_MemImage = ::CreateCompatibleBitmap(hDC_TempMemImage,
iPrintableAreaWidth, iPrintableAreaHeight);
HGDIOBJ hOldGDIObj = ::SelectObject(hDC_TempMemImage, (HGDIOBJ)
hBmp_MemImage);

if (!::StretchBlt(hDC_TempMemImage,
0,0, iPrintableAreaWidth, iPrintableAreaHeight,
hDC_BackSurface,
0, 0, obSurfaceDesc.dwWidth, obSurfaceDesc.dwHeight,
SRCCOPY))
{
OutputDebugString( _T("StretchBlt to memory image failed!"));
}

if (!pobPrinterDC->BitBlt(
rectPrintArea.left, rectPrintArea.top, iPrintableAreaWidth,
iPrintableAreaHeight,
CDC::FromHandle(hDC_TempMemImage),
0, 0, // Source top-left corner
SRCCOPY))
{
OutputDebugString(_T("BitBlt to Printer failed!"));
}

SelectObject(hDC_TempMemImage, hOldGDIObj);
DeleteDC(hDC_TempMemImage);
m_DDSBack->ReleaseDC(hDC_BackSurface);

Gishu....@gmail.com

unread,
Jul 23, 2007, 1:58:45 AM7/23/07
to
Resolved... silly mistake on my end.

HBITMAP hBmp_MemImage = ::CreateCompatibleBitmap(hDC_TempMemImage,
iPrintableAreaWidth, iPrintableAreaHeight);

should be
HBITMAP hBmp_MemImage = ::CreateCompatibleBitmap( hDC_BackSurface,
iPrintableAreaWidth, iPrintableAreaHeight);
to create a bitmap with the same attributes as the Rendered Viewport.

Posting so that it helps the next guy.
-- Gishu

Gishu....@gmail.com

unread,
Jul 24, 2007, 8:06:32 AM7/24/07
to
Seems like Device Indepent Bitmaps and StretchDIBits are a better way
to achieve consistent results across printers

void CView::PrintBackSurfaceContents(HDC hDC_Printer, RECT
rectPrintArea)
{
HDC hDC_BackSurface;
HRESULT hrRetVal = m_DDSBack->GetDC(&hDC_BackSurface);

// get surface dimensions
DDSURFACEDESC obSurfaceDesc;
ZeroMemory(&obSurfaceDesc, sizeof(obSurfaceDesc));
obSurfaceDesc.dwSize = sizeof(obSurfaceDesc);
hrRetVal = m_DDSBack->GetSurfaceDesc(&obSurfaceDesc);
if (FAILED(hrRetVal))
{ return; }

// create 24 bit color Bitmap
BITMAPINFO obBmpInfo;
ZeroMemory(&obBmpInfo, sizeof(BITMAPINFO));

obBmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
obBmpInfo.bmiHeader.biWidth = obSurfaceDesc.dwWidth;
obBmpInfo.bmiHeader.biHeight = obSurfaceDesc.dwHeight;
obBmpInfo.bmiHeader.biPlanes = 1;
obBmpInfo.bmiHeader.biBitCount = 24;
obBmpInfo.bmiHeader.biCompression = BI_RGB;

LPBYTE pBits;
HBITMAP hBmpMemImage = CreateDIBSection(hDC_BackSurface,
&obBmpInfo, DIB_RGB_COLORS, (void**)&pBits, NULL, 0);

// Select bitmap to a DC compatible with back surface
HDC hDC_MemImage = ::CreateCompatibleDC(hDC_BackSurface);
::SelectObject(hDC_MemImage, hBmpMemImage);

// create Palette and apply to both source and dest
if (!(GetDeviceCaps(hDC_BackSurface, RASTERCAPS) & RC_PALETTE))
{
goto FunctionExit;
}
LPLOGPALETTE lpLogPal = (LPLOGPALETTE) ::GlobalAlloc(GPTR,
sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY));
if (!lpLogPal)
{
goto FunctionExit;
}

lpLogPal->palVersion = 0x300;
lpLogPal->palNumEntries = 256;
::GetSystemPaletteEntries(hDC_BackSurface, 0 , 256, lpLogPal-
>palPalEntry);

HPALETTE hPalette = ::CreatePalette(lpLogPal);
::GlobalFree(lpLogPal);

if (hPalette)
{
::SelectPalette(hDC_BackSurface, hPalette, FALSE);
::RealizePalette(hDC_BackSurface);

::SelectPalette(hDC_MemImage, hPalette, FALSE);
::RealizePalette(hDC_MemImage);
}

// Blit bits from Back Buffer to Temp Memory Bitmap
::BitBlt(hDC_MemImage,
0,0, obSurfaceDesc.dwWidth, obSurfaceDesc.dwHeight,
hDC_BackSurface,
0,0,
SRCCOPY);

DIBSECTION obDIBSection;
::GetObject(hBmpMemImage, sizeof(DIBSECTION), &obDIBSection );

// Stretch Memory Bitmap to Scaled up Print dimensions
RECT rectBestFit = GetBestFitArea(rectPrintArea,
obSurfaceDesc.dwWidth, obSurfaceDesc.dwHeight);
::StretchDIBits(hDC_Printer,
rectBestFit.left,rectBestFit.top, (rectBestFit.right-
rectBestFit.left), (rectBestFit.bottom-rectBestFit.top),
0,0, obSurfaceDesc.dwWidth, obSurfaceDesc.dwHeight,
obDIBSection.dsBm.bmBits,
(LPBITMAPINFO) &obDIBSection.dsBmih,
DIB_RGB_COLORS,
SRCCOPY);

FunctionExit:
// CleanUp
if (0 != hDC_MemImage)
{
::DeleteDC( hDC_MemImage );
}
if (0 != hBmpMemImage)
{
::DeleteObject(hBmpMemImage);
}
if (0 != hPalette)
{
::DeleteObject(hPalette);
}
m_DDSBack->ReleaseDC(hDC_BackSurface);
}

0 new messages