Print transparent bitmaps via regions

This is a modification of Mr Lachand-Robert's BitmapToRegion() function.

The new routine, SetBitmapPixels(), lets you print a CBitmap transparently, even on an HP printer, where you can't use the normal raster operation codes. It is too slow for display, but can be used for printing in place of the normal "blitting" of the bits to the DC.

I have compiled it clean on VC5.0, warning level 4, and have used it in my own code. It has not been thoroughly checked for all pathological logic cases, but does not (seem to) leak any memory.

Here is a sample of calling the routine:

//This sample assumes a mapping mod
//of MM_LOENGLISH (100 pts/inch)
//with the viewport origin in the upper lef
//corner of the DC. It assumes the DC has bee
//built and prepared, and is referenced vi
//a printer DC ptr named pDC
//The bitmap is initialized with a resourc
//built and included in the project workspace
//The bitmap will be drawn into the D
//centered on a point 2" over and 2" down
CBitmap bmStamp;


BOOL bOk = SetBitmapPixels(
	       RGB(255,255,255), // Transparency color = whit

And here is the routine:

//Set pixels in a DC drawing surfac
//which are not transparent in a bitmap
//If you have a CBitmap object, you can us
//this function to print it transparentl
//on an HP printer
//pDC:             DC pointe
//hBmp:            Source bitma
//rgbTransparent:  Color base for the "transparent" pixel
//nXOffset:        Offset to bitmap UL corner, in logical unit
//nYOffset:        Offset to bitmap UL corner, in logical unit
//                 (usually negative
//Returns true if OK, else false
//This code is based on the BitmapToRegion(
//function contributed by Mr. Lachand-Robert
//It is a modification of the original function
//which does the following
//1) Given a DC which is being drawn int
//   (such as a printer), the functio
//   makes sure that the regions draw
//   will be centered on the X,Y offsets
//2) The function then loops thru the bit
//   in the bitmap. When it encounters 
//   block of bits which are all of the sam
//   color, and which are not the transparenc
//   color, it creates a small region an
//   fills it with a brush of the pixel color
//The function assumes a mapping mode othe
//than MM_TEXT for the passed-in Devic
//Context. I used it successfully wit
//MM_ANISOTROPIC, for example, and was abl
//to "zoom" the bitmap correctly
BOOL SetBitmapPixels(CDC*     pDC,
                    HBITMAP  hBmp,
                    COLORREF rgbTransparent,
					int      nXOffset,
					int      nYOffset)
	if (hBmp    == NULL || pDC     == NULL)
		return FALSE;

	// Create a memory DC inside which we will scan the bitmap conten
	HDC hMemDC = CreateCompatibleDC(NULL);

	if (hMemDC)
		// Get bitmap siz
		BITMAP bm;
		GetObject(hBmp, sizeof(bm), &bm);

		//Make sure x and Y offset are relativ
		//to center of the bitmap; thi
		//way the bitmap will appear centere
		//on (nXOffset,nYOffset
		nXOffset -= bm.bmWidth /2;
		nYOffset -= bm.bmHeight/2;

		// Create a 32 bits depth bitmap and select it into the memory DC
			sizeof(BITMAPINFOHEADER),// biSize
			bm.bmWidth,				 // biWidth;
           -bm.bmHeight,			 // biHeight
			1,						 // biPlanes;
			32,						 // biBitCount
			BI_RGB,					 // biCompression;
			0,						 // biSizeImage;
			0,						 // biXPelsPerMeter;
			0,						 // biYPelsPerMeter;
			0,						 // biClrUsed;
			0						 // biClrImportant;

		VOID * pbits32; 

		HBITMAP hbm32 = CreateDIBSection(

		if (hbm32)
			HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hbm32);

			// Create a DC just to copy the bitmap into the memory D
			HDC hDC = CreateCompatibleDC(hMemDC);

			if (hDC)
				// Get how many bytes per row w
				//have for the bitmap bit
				//(rounded up to 32 bits
				BITMAP bm32;
				VERIFY(GetObject(hbm32, sizeof(bm32), &bm32));

				while (bm32.bmWidthBytes % 4)

				// Copy the bitmap into the memory D
				HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp);

				//Scan each bitmap row from bottom to to
				//(the bitmap is inverted vertically
				BYTE *p32 = (BYTE *)bm32.bmBits +
				            (bm32.bmHeight - 1) * bm32.bmWidthBytes;

				//Scan each bitmap pixel from left to right
				//Search for a continuous lin
				//of non transparent pixel
				for (int y = 0; y < bm.bmHeight; y++)
					for (int x = 0; x < bm.bmWidth; x++)
						int  x0 = x; //Ptr to start of region to fil
						LONG *p = (LONG *)p32 + x;

						rgbBase =RGB(GetBValue((DWORD)(*p)),

						COLORREF rgbCurr = rgbBase;

						if (rgbBase != rgbTransparent)
							while(rgbCurr == rgbBase &&
							      x        < bm.bmWidth)
  								rgbCurr = RGB(GetBValue((DWORD)(*p)),

							CRgn rgnTemp;

									  x0 + nXOffset,
									  y  + nYOffset,
									  x  + nXOffset,
									  y+1+ nYOffset);

							CBrush  brTemp(rgbBase);

							x--; //Decrement to account for x for loo
						}	//end if not transparent
					}	//end for 

					// Go to next ro
					//(remember, the bitmap is inverted vertically
					p32 -= bm32.bmWidthBytes;
				}	//end for 

				// Clean u
				SelectObject(hDC, holdBmp);

			DeleteObject(SelectObject(hMemDC, holdBmp));


	return TRUE;


  • adding code

    Posted by Legacy on 12/03/2002 12:00am

    Originally posted by: alexis

    may be i'm in new in this field, but can anyone tell mi how to add this code into the application?should i create another new header and source file?
    or where can i copy this codes?
    thnx alot!

  • My solution

    Posted by Legacy on 10/18/2002 12:00am

    Originally posted by: yang chisheng

    In my project,I also face the problem of printing transparent bitmap,I also want to print some graphic support alpha channel like TGA.My solution is :
    1.create a printer compatible memory dc
    2.create a dib base on the resolution of the priter
    3.blend all text ,shape or image to the dib.
    4.use SetDIBitsToDevice send dib to the printer dc.

    when drawing a image with alpha channel,firstly get the background image(a dib buffer) and do alpha blend on the background then send result dib to the printer compatible memory dc.

    My problem is :create a dib base on the resolution of the printer will cost huge memory some like 30M bytes.

    Any comments will be appreciated.

  • Excellent!

    Posted by Legacy on 09/19/2002 12:00am

    Originally posted by: LavishJack

    Thank you Sir ....
    you guys are great! :)

  • Great!!

    Posted by Legacy on 06/27/2002 12:00am

    Originally posted by: PJ

    I just used your code and works as expected.


  • Thanks, exactly what I needed to print a bitmap to my HP Printer!

    Posted by Legacy on 08/14/2001 12:00am

    Originally posted by: Michael

    It took me two wasted days to find this code which solved my blank printing problems.

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

Top White Papers and Webcasts

  • Live Event Date: May 11, 2015 @ 1:00 p.m. ET / 10:00 a.m. PT One of the languages that have always been supported with the Intel® RealSense™ SDK (Software Developer Kit) is JavaScript, specifically so that web-enabled apps could be created. Come hear from Intel Expert Bob Duffy as he reviews his own little "space shooting" game where the orientation of your face controls the aiming reticle to help teach developers how to write apps and games in JavaScript that can use facial and gesture …

  • Are you truly leading your team or simply managing them? Organizations need leaders and your team needs someone to follow. With some ongoing development, you could become that leader. Learn the top leadership qualities that inspire others to want to follow you and the direction of your company.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date