GDI rendering for direct2D ID2D1BitmapRenderTarget is always transparent

I want to port my movie rendering software from DirectDraw to Direct2D. Due to compatibility issues, GDI rendering must be done on top of the image. In order to optimize performance, I want to implement some kind of backbuffer mechanism, but there seems to be a problem with alpha channel information, all GDI drawings look somehow transparent .

I am creating an ID2D1HwndRenderTarget for my window handle and ID2D1Bitmap to copy the images. The pixel format of the bitmap is DXGI_FORMAT_B8G8R8A8_UNORM , alpha mode is D2D1_ALPHA_MODE_IGNORE . HwdRenderTarget is GDI compatible, so my render function looks something like this:

HwdRenderTarget.BeginDraw; HwdRenderTarget.DrawBitMap(myBitMap); HwdRenderTarget.GetDC(dc); ... do GDI drawing here ... HwdRenderTarget.ReleaseDC(); HwdRenderTarget.EndDraw; 

This version works fine: GDI objects are solid colors, DrawTextEx-Text has a transparent background.

To optimize performance, I want to make a GDI drawing in a "backbuffer", so it needs to be done only when something changes. Otherwise, I can just display the cached bitmap. The bitmap is empty and transparent, so only objects drawn should be visible.

So, I create a CompatibleRenderTarget ID2D1BitmapRenderTarget , alpha mode D2D1_ALPHA_MODE_PREMULTIPLIED :

  HwdRenderTarget.CreateCompatibleRenderTarget(nil, nil, nil, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_GDI_COMPATIBLE, CompatibleRenderTarget); 

Now I am doing GDI rendering in CompatibleRenderTarget:

 CompatibleRenderTarget.BeginDraw; if Supports(CompatibleRenderTarget, ID2D1GdiInteropRenderTarget, GdiInteropRenderTarget) then begin GdiInteropRenderTarget.GetDC(D2D1_DC_INITIALIZE_MODE_CLEAR, dc); ... do GDI drawing here ... GdiInteropRenderTarget.ReleaseDC(fDstSize); end; GdiInteropRenderTarget := nil; CompatibleRenderTarget.EndDraw; CompatibleRenderTarget.GetBitmap(BackBuffer); // save the bitmap for drawing 

and my rendering function now looks like this:

 HwdRenderTarget.BeginDraw; HwdRenderTarget.DrawBitMap(myBitMap); HwdRenderTarget.DrawBitmap(BackBuffer); HwdRenderTarget.EndDraw; 

Now the problem is that all the GDI drawings are somehow transparent , and the degree of transparency depends on the values ​​of the basic pixels of the image. Dark text appears dark against a dark image, but turns white on a white background. But the alpha channel is not used in GDI, and myBitmap also does not have alpha information.

So where did the alpha info come from? Does anyone have an idea? Thanks in advance!

Btw using Direct2D drawing on CompatibleRenderTarget also works fine.

+4
source share
2 answers

I had the same problem. The following worked for me (you need to create a rendering target using D2D1_ALPHA_MODE_IGNORE, not D2D1_ALPHA_MODE_PREMULTIPLIED).

 ID2D1HwndRenderTarget* pRenderTarget; // render target created sometime earlier D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat( DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE); ID2D1BitmapRenderTarget* pOffscreenRT = NULL; pRenderTarget->CreateCompatibleRenderTarget(NULL, NULL, &pixelFormat, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_GDI_COMPATIBLE, &pOffscreenRT); 
+2
source

There's a dirty little secret about rendering with GDI: it will always be a clobber alpha channel. Everything you draw with it will set the alpha values ​​in this area. I suspect this because it was never intended to work with an alpha channel or any type of compositing. It was intended for direct transmission to the screen and to printers where alpha channels do not exist.

+1
source

Source: https://habr.com/ru/post/1334369/


All Articles