I am having a problem making alpha images print to a printer device context (real or XPS document writer). They work great on the screen context and in print preview but when I print to file or to the printer they show up as black squares when they are positioned on top of another image. I was using the CImage::Draw before and had a similar result (black or clear squares) as using thes GDI+ API directly:
Gdiplus::Graphics g(hDestDC) ;
...
// Edit: the image value here was one aquired from a ATL::CImage not
// a Gdiplus::Image (see solution)
g.DrawImage(image,rect,0,0,GetWidth(),GetHeight(),Gdiplus::UnitPixel,0,0,0);
The device caps seem to indicate that the context supports blending via
GetDeviceCaps(hDestDC, SB_PIXEL_ALPHA)
The nature of the images do not seem to matter either, here is the format of the two I am using:
PNG image data, 256 x 256, 8-bit/color RGBA, non-interlaced
PNG image data, 192 x 64, 1-bit colormap, non-interlaced
Both yield the same results using the GDI+ interfaces with CImage data. What is the best way to have alpha images act the same way on the print context as they do on the screen? Could the device capabilities be misrepresenting something because alpha works using a BitmapMatrix and using a blend for the entire image?
Edit: 3/4/2013
My new approach is to do all the alpha blending in memory my thought was if the printer did not support alpha blending I would create a memory context to blend and then just copy the blended result to the context. The important parts of the code look like this:
int width = rectDest.right - rectDest.left;
int height = rectDest.bottom - rectDest.top;
BLENDFUNCTION blendFunction;
blendFunction.BlendOp = AC_SRC_OVER;
blendFunction.BlendFlags = 0;
blendFunction.SourceConstantAlpha = 0xFF;
blendFunction.AlphaFormat = AC_SRC_ALPHA;
HDC memDC = CreateCompatibleDC(hDestDC);
HBITMAP bitmap = CreateCompatibleBitmap(hDestDC,width,height);
SelectBitmap(memDC,bitmap);
//sample the underying area and copy it to memDC
::BitBlt(memDC, 0,0, width, height, hDestDC, rectDest.left, rectDest.top, SRCCOPY);
//now blend the image in memory onto the area.
GdiAlphaBlend(memDC,0,0, width, height,GetDC(), 0, 0, GetWidth(), GetHeight(),blendFunction);
//now just BitBlt the blended data to the context
::BitBlt(hDestDC,rectDest.left, rectDest.top,width,height,memDC,0,0,SRCCOPY);
... to my surprise I get almost the same result. Actually I blit the intermediate steps along the left of the screen just to make sure everything is operating correctly. Both the background it grabs and the alpha blended result (that I blit to the printer context) look great on the screen. Could this be a bug? I guess BitBlt leaves the alpha values intact from the prior blend so is it the actual alpha values in the pixel data that is throwing the printer device context? If so how can I remove the alpha before the final BitBlt?
Edit: 3/5/2013
Now I have tried the following:
1. Using a Device-independent bitmap to create the HBITMAP reference.
2. Using CreateDiscardableBitmap to create the HBITMAP (with the most success).
3. Manually setting the alpha channel for each pixel to 0xFF and 0x00.
BITMAPINFO bitmapInfo;
ZeroMemory(&bitmapInfo, sizeof(BITMAPINFO));
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biSize = sizeof(bitmapInfo.bmiHeader);
bitmapInfo.bmiHeader.biWidth = width;
bitmapInfo.bmiHeader.biHeight = height;
bitmapInfo.bmiHeader.biSizeImage = bitmapSizeBytes;
HDC memDC = CreateCompatibleDC(hDestDC);
//was HBITMAP bitmap = CreateCompatibleBitmap(hDestDC,width,height);
//also tried HBITMAP bitmap = CreateDiscardableBitmap(hDestDC,width, height);
HBITMAP bitmap = CreateDIBSection(memDC, &bitmapInfo,DIB_RGB_COLORS,&imageBits,NULL,0x00);
Using the disposable bitmap at least let the image render but with black for the areas where alpha should be.