アルファ イメージをプリンター デバイス コンテキスト (リアルまたは XPS ドキュメント ライター) に印刷する際に問題が発生しています。画面のコンテキストと印刷プレビューではうまく機能しますが、ファイルまたはプリンターに印刷すると、別の画像の上に配置されると黒い四角として表示されます。以前は CImage::Draw を使用していましたが、GDI+ API を直接使用した場合と同様の結果 (黒または透明な四角) が得られました。
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);
デバイスのキャップは、コンテキストがブレンドをサポートしていることを示しているようです
GetDeviceCaps(hDestDC, SB_PIXEL_ALPHA)
画像の性質も問題ではないようです。私が使用している2つの形式は次のとおりです。
PNG image data, 256 x 256, 8-bit/color RGBA, non-interlaced
PNG image data, 192 x 64, 1-bit colormap, non-interlaced
どちらも、GDI+ インターフェイスと CImage データを使用して同じ結果をもたらします。画面上で行うのと同じように印刷コンテキストでアルファ画像を動作させる最良の方法は何ですか? アルファは BitmapMatrix を使用し、画像全体のブレンドを使用して機能するため、デバイスの機能が何かを誤って伝えている可能性はありますか?
編集: 2013 年 3 月 4 日
私の新しいアプローチは、すべてのアルファブレンディングをメモリ内で行うことです。プリンターがアルファブレンディングをサポートしていない場合は、ブレンドするメモリコンテキストを作成し、ブレンドされた結果をコンテキストにコピーするだけです。コードの重要な部分は次のようになります。
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);
...驚いたことに、ほぼ同じ結果が得られました。実際には、すべてが正しく動作していることを確認するためだけに、画面の左側に沿って中間ステップをブリットしました。取得した背景とアルファ ブレンドの結果 (プリンター コンテキストにブリット) の両方が、画面上で見栄えがします。これはバグでしょうか?BitBlt は以前のブレンドのアルファ値をそのまま残していると思いますが、プリンター デバイス コンテキストをスローしているピクセル データの実際のアルファ値ですか? もしそうなら、どうすれば最終的な BitBlt の前にアルファを削除できますか?
編集:2013年3月5日
今、私は次のことを試しました:
1.デバイスに依存しないビットマップを使用してHBITMAP参照を作成します。
2. CreateDiscardableBitmap を使用して HBITMAP を作成します (最も成功しています)。
3. 各ピクセルのアルファ チャネルを手動で 0xFF と 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);
使い捨てビットマップを使用すると、少なくとも画像がレンダリングされますが、アルファが必要な領域は黒になります。