Printing images with transparent areas

I Love Xbase++ (ILX)
The portal for Xbase++ developers worldwide

Pat France

New member
Staff member
I am here to help you!
Aug 9, 2022
22
3
3
Customer Identifier
E114627
Images loaded into an XbpBitmap support transparency in one of two ways:
  • via an alpha channel incorporated directly into the image data
  • via masking of areas in the image having a certain color (so-called chroma keying)
In both cases, the resulting pixels must be created by combining the pixels in the source image with those of the underlying page. This operation must be performed by the printer driver. Unfortunately, transparency in images is not supported by many printers. Also printer drivers, especially virtual printer drivers such as the ones used for generating PDFs, often report incorrect (virtual) device capabilities to the application. As a result, the transparent areas in an image may print incorrectly (i.e. opaque).

The following is a two-pronged approach for working around this problem. If consists of the following steps:
  1. Create a temporary image that has the transparent areas in the original image replaced with the color white
  2. Combine the pixels in the temporary image with those in the output area using a binary AND operation. This prevents existing pixels from being overwritten in source areas containing the "off"/background color (white)
Note: This approach works best for monochrome prints. The second step only needs to be performed when the source image actually overlaps other imagery on the page!

Step 1 - Creating the temporary image​

Xbase++:
#include "gra.ch"

// Draw bitmaps using per-pixel alpha or chroma keying onto a temporary image
// using a white background for working around issues with printers not supporting
// transparency. If the image passed in <oBmp> has transparent areas, the function
// returns the temporary image to be used for printing. If the image does not have
// transparent areas, return is the original bitmap (<oBmp>)
FUNCTION GetPrintBitmap( oBmp )
 LOCAL oRet
 LOCAL oPS

   IF .NOT. oBmp:hasAlphaChannel .AND. oBmp:transparentClr == GRA_CLR_INVALID
      RETURN oBmp
   ENDIF

   oRet := XbpBitmap():new():create()
   oRet:make( obmp:xSize, oBmp:ySize )
 
   oPS := XbpPresSpace():new():create()
   oRet:presSpace( oPS )

   GraSetColor( oPS, GRA_CLR_WHITE, GRA_CLR_WHITE )
   GraBox( oPS, {0,0}, {obmp:xSize-1,oBmp:ySize-1}, GRA_FILL )
   oBmp:draw( oPS, {0,0,oBmp:xSize-1,oBmp:ySize-1} )
   oPS:destroy()
RETURN oRet

Step 2 - Printing the temporary image​


Xbase++:
(...)
// Create temporary bitmap having transparent areas filled with white. Combine source and destination pixels
// using a binary AND operation to prevent existing pixels from being overwritten
aTargetRect := {...]
oBmp := GetPrintBitmap( oTransparentBmp )
oBmp:draw( oPrinterPS, aTargetRect,, GRA_BLT_ROP_SRCAND )

(...)

 
Last edited by a moderator:
  • Like
Reactions: Dominik Krebs