How can I create a Gaussian blur with a printer render target using Direct2D?

simonx 126 Reputation points
2024-12-16T17:04:06.37+00:00

I am using Direct2D to generate diagrams. I want to create a glow-effect around diagram boxes, using Gaussian blur. In order to do this, I paint a rectangle to an off-screen render target, blur it, and then get the off-screen render target's bitmap and call DrawImage on the normal render target to paint it back into the main window. Finally I paint the standard rectangle on top of the blurred one, and this gives a pleasing glow effect. This works fine when painting to a window. Unfortunately it doesn't work when painting to a printer. The problem is these lines of code:

CComPtr<ID2D1BitmapRenderTarget> pOffscreenRenderTarget;

HRESULT hr = pRenderTarget->CreateCompatibleRenderTarget(&pOffscreenRenderTarget);

The latter call fails. I get "DXGI_FORMAT_UNKNOWN is not allowed as a parameter to this API when the target is set to NULL or is a command list." It is true that when I print, I create a command list, and call "SetTarget" on the device context, to output to this (my render target is an ID2D1DeviceContext5). My users frequently "print" to a PDF file and you get smaller PDF files if I output to a command list.

So my question is: how can I continue to output to a command list, while also generating a Gaussian blur?

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,699 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,804 questions
{count} votes

1 answer

Sort by: Most helpful
  1. simonx 126 Reputation points
    2024-12-21T12:12:19.7966667+00:00

    Thanks Castorix31. I found the same thing. If I set desiredFormat in the CreateCompatibleRenderTarget call (DXGI_FORMAT_B8G8R8A8_UNORM and D2D1_ALPHA_MODE_PREMULTIPLIED), the call does not fail, but I don't get a blur in the printed output. Also, in direct2d debug mode I see a debug warning message which says: "D2D DEBUG INFO - An image drawn to a command list has just been changed. This may produce unintended consequences. The command list will now contain the changed image rather than the contents of image at the time that it was drawn." This happens presumably because I am trying to blur all of the diagram boxes. I tried releasing and re-creating the compatible render target for each box, but still got this debug warning message. However, as I say, in practice I can't see any blur anywhere anyway.

    Any more suggestions as to how I can create a good quality blur that will actually print? I tried 'manually' creating a blur using a number of overlapping, expanding filled rectangles with ever-increasing transparency. And that sort of works, but it doesn't look very good. So all suggestions very welcome. I'm open to anything.

    In summary, to initialize the print job (following the documentation for Direct2D) I use these calls (much simplified):

    • D3D11CreateDeviceAndSwapChain(... D3D11_CREATE_DEVICE_BGRA_SUPPORT .... DXGI_FORMAT_B8G8R8A8_UNORM ... DXGI_USAGE_RENDER_TARGET_OUTPUT, ... &m_swapChain, &d3dDevice)
    • d3dDevice->QueryInterface(&dxgiDevice);
    • pD2dFactory->CreateDevice(dxgiDevice, &m_d2dDevice )
    • m_d2dDevice->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &m_pD2dDeviceContext
    • CoCreateInstance( __uuidof(PrintDocumentPackageTargetFactory), nullptr,CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&documentTargetFactory)
    • documentTargetFactory->CreateDocumentPackageTargetForPrintJob(printerName, <printer job name>,nullptr,m_jobPrintTicketStream,&m_documentTarget
    • d2dDevice->CreatePrintControl(pWICFactory, m_documentTarget, nullptr, &m_printControl);

    And to generate each page, I have a loop with these calls (again, simplified):

    • <prepare render target with appropriate SetTransform calls>
    • m_pD2dDeviceContext->CreateCommandList(&commandList);
    • m_pD2dDeviceContext->SetTarget(commandList);
    • m_pD2dDeviceContext->BeginDraw();
    • <paint calls, including numerous diagram boxes with gaussian blur>
    • m_pD2dDeviceContext->EndDraw();
    • commandList->Close();
    • m_printControl->AddPage(commandList, D2D1::SizeF(fPageWidth_Dips, fPageHeight_Dips), nullptr);

    And I finally close the print control (m_printControl->Close();).

    That all works fine for printing diagrams generally - except that I don't get any blur.


    Jeanine Zhang: can you say a little more about what you're suggesting please. How do your suggestions apply to what I'm doing? Thanks.


    And finally, as I say, any suggestions of any kind welcome. Thanks.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.