Printing with OpenGL - Another method

One of the largest problems I have encountered using OpenGL is that it is very difficult to print a rendered scene. I have only found one other sample on how to do this, however, there was no sample code and I was unable to actually print (let alone print preview a scene!).

What I have done is create a class, CCaptureImage, out of code snippets found on this site. CCaptureImage will capture an bitmap using a device context and the rect of the image you want. From there, you can paint it to a device or save it to a bmp file. Usage of the CCaptureImage class with respect to printing is shown below in the sample code.

OnPreparePrinting captures the bitmap for printing. For Print Preview, the bitmap is captured in the override of OnFilePrintPreview(). This is done in separate places as the Client rect size may be different if it is found in OnPreparePrinting (if you use dockable toolbars attached, for instance).

BOOL CPrintGLView::OnPreparePrinting(CPrintInfo* pInfo) 
		CRect rcDIB;
		CapturedImage.Capture(GetCDC(), rcDIB);
	return DoPreparePrinting(pInfo);

void CPrintGLView::OnFilePrintPreview()
	CRect rcDIB;
	CapturedImage.Capture(GetCDC(), rcDIB);


void CPrintGLView::OnEndPrinting(CDC* pDC, CPrintInfo* pInfo) 
	CView::OnEndPrinting(pDC, pInfo);

Once the bitmap is captured and stored, it can bu used by the OnDraw method to print it to the printer DC or the print preview DC.
void CPrintGLView::OnDraw(CDC* pDC)
	CPrintGLDoc* pDoc = GetDocument();

	if (pDC->IsPrinting()) 
		CRect rcDIB;

		rcDIB.right = rcDIB.Width();
		rcDIB.bottom = rcDIB.Height();

		// get size of printer page (in pixels)
		int cxPage = pDC->GetDeviceCaps(HORZRES);
		int cyPage = pDC->GetDeviceCaps(VERTRES);
		// get printer pixels per inch
		int cxInch = pDC->GetDeviceCaps(LOGPIXELSX);
		int cyInch = pDC->GetDeviceCaps(LOGPIXELSY);

		CRect rcDest; = rcDest.left = 0;
		rcDest.bottom = (int)(((double)rcDIB.Height() * cxPage * cyInch)
				/ ((double)rcDIB.Width() * cxInch));
		rcDest.right = cxPage;

		CapturedImage.OnDraw(pDC->m_hDC, &rcDest, &rcDIB);

	else // not printer DC

This method may not be the most elegant, however, it works. The following source has been updated to fix 2 bugs: resize crash when compiled with VC++6.0, and saving as a bitmap with more than 256 colours. Thanks for the replies and suggestions.

Download demo project with source - 41 KB

Date Updated: December 14, 1998


  • OpenGL Printing; Better to render directly to a DIB

    Posted by Legacy on 02/01/1999 12:00am

    Originally posted by: David Calkins

    I think that the method presented for printing an OpenGL scene is good if you want something quick-and-dirty, but it has some drawbacks. The method basically, copys the window contents to the printer. So, you're limited by the screen resolution (window size, actually).

    Most printers have a much higher resolution than the screen, and you should really try and take advantage of this when printing OpenGL scenes. The better method is to make OpenGL render directly to a DIB section. This DIB section can be huge (sized for the printers resolution not the screens). Then, you can blit the DIB to the printer.

    1. create a DIB, using CreateDIBSection() the size of the printer page
    2. select the DIB into a DC.
    3. set up GL to render to this DC.
    4. when GL is done, you can blit the image to the printer.

    I was told that this was the best way by a Microsoft GL guru. It does make more sense than simply rendering to a window, and then blitting the low-res image (or worse, stretching it) to the printer.

    Having said this, there are some drawbacks to this method. Creating huge DIBs requires more resources than simply blitting the window out, and for some applications you would certainly have fewer headaches if you just use the method described above. You won't take advantage of the high-res of your printer though.

    There is an excellent example of printing from GL on Microsoft's ftp site. This example does all GL rendering directly to a DIB. Then to display the image you can blit to the window, and to print it, you can blit to the printer. Of course, if you want you can make a larger DIB for printing to accomodate high printer resolution.

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • 10 Rules that Make or Break Enterprise App Development Projects In today's app-driven world, application development is a top priority. Even so, 68% of enterprise application delivery projects fail. Designing and building applications that pay for themselves and adapt to future needs is incredibly difficult. Executing one successful project is lucky, but making it a repeatable process and strategic advantage? That's where the money is. With help from our most experienced project leads and software engineers, …

  • As everyone scrambles to protect customers and consumers from the Heartbleed virus, there will be a variety of mitigating solutions offered up to address this pesky bug. There are a variety of points within the data path where solutions could be put into place to mitigate this (and similar) vulnerabilities and customers must choose the most strategic point in the network at which to deploy their selected mitigation. Read this white paper to learn the ins and outs of mitigating the risk of Heartbleed and the …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds