Direct2D error when building a single-channel bitmap

I am an experienced computer graphics programmer, mainly using Direct3D 9.0c, OpenGL and general algorithms. I am currently evaluating Direct2D as a rendering technology for a professional medical imaging application. As for rendering, this is an x64 desktop application in windowed mode (not in fullscreen mode).

Already with my initial steps, I am struggling with a task that, as I thought, would be no problem: rendering a single-channel bitmap on the screen.

By running Windows 8.1 on the machine, I create an ID2D1DeviceContext with a Direct3D chain buffer surface as the rendering target. A swap chain is created from the HWND format and the DXGI_FORMAT_B8G8R8A8_UNORM buffer. Note: See also code snippets at the end .

Then I create a bitmap with the pixel format DXGI_FORMAT_R8_UNORM and alpha mode D2d1_ALPHA_MODE_IGNORE . When calling DrawBitmap(...) in the device context, the debugging debugging point is "D2d DEBUG ERROR - this operation is incompatible with the pixel format of the bitmap image".

I know that this conclusion is completely clear. Also, when changing the pixel format to DXGI_FORMAT_R8G8B8A8_UNORM using DXGI_ALPHA_MODE_IGNORE everything works well and I see a bitmap. However, I just can't believe it! Graphics cards have supported single-channel textures since then - every 3D graphics application can use them without thinking twice. This happens without talking.

I tried to find something here and on Google without success. The only hint I could find was the MSDN Direct2D page with supported formats ( ). The documentation suggests - not to mention this - that DXGI_FORMAT_R8_UNORM is not really supported in bitmap format. I also find alpha mask messages (using DXGI_FORMAT_A8_UNORM ), but this is not what I need.

What am I missing, that I cannot convince Direct2D to create and draw a bitmap in grayscale? Or is it true that Direct2D does not support drawing bitmaps of R8 or R16?

Any help is really appreciated as I do not know how to solve it. If I cannot get these trivial basics to work, I think I will have to stop digging deeper into Direct2D: - (.

And here are the code fragments of relevance. Note that they may not compile since I have ported this on the fly from my C ++ / CLI code to plain C ++. In addition, I dropped all error checking and other noises:

Creating a device, device context, and creating swap chains (D3D and Direct2D):

 // Direct2D factory creation D2D1_FACTORY_OPTIONS options = {}; options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; ID2D1Factory1* d2dFactory; D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, options, &d2dFactory); // Direct3D device creation const auto type = D3D_DRIVER_TYPE_HARDWARE; const auto flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; ID3D11Device* d3dDevice; D3D11CreateDevice(nullptr, type, nullptr, flags, nullptr, 0, D3D11_SDK_VERSION, &d3dDevice, nullptr, nullptr); // Direct2D device creation IDXGIDevice* dxgiDevice; d3dDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice)); ID2D1Device* d2dDevice; d2dFactory->CreateDevice(dxgiDevice, &d2dDevice); // Swap chain creation DXGI_SWAP_CHAIN_DESC1 desc = {}; desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; desc.SampleDesc.Count = 1; desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; desc.BufferCount = 2; IDXGIAdapter* dxgiAdapter; dxgiDevice->GetAdapter(&dxgiAdapter); IDXGIFactory2* dxgiFactory; dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void **>(&dxgiFactory)); IDXGISwapChain1* swapChain; dxgiFactory->CreateSwapChainForHwnd(d3dDevice, hwnd, &swapChainDesc, nullptr, nullptr, &swapChain); // Direct2D device context creation const auto options = D2D1_DEVICE_CONTEXT_OPTIONS_NONE; ID2D1DeviceContext* deviceContext; d2dDevice->CreateDeviceContext(options, &deviceContext); // create render target bitmap from swap chain IDXGISurface* swapChainSurface; swapChain->GetBuffer(0, __uuidof(swapChainSurface), reinterpret_cast<void **>(&swapChainSurface)); D2D1_BITMAP_PROPERTIES1 bitmapProperties; bitmapProperties.dpiX = 0.0f; bitmapProperties.dpiY = 0.0f; bitmapProperties.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; bitmapProperties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; bitmapProperties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE; bitmapProperties.colorContext = nullptr; ID2D1Bitmap1* swapChainBitmap = nullptr; deviceContext->CreateBitmapFromDxgiSurface(swapChainSurface, &bitmapProperties, &swapChainBitmap); // set swap chain bitmap as render target of D2D device context deviceContext->SetTarget(swapChainBitmap); 

Create a single-channel D2D bitmap:

 const D2D1_SIZE_U size = { 512, 512 }; const UINT32 pitch = 512; D2D1_BITMAP_PROPERTIES1 d2dProperties; ZeroMemory(&d2dProperties, sizeof(D2D1_BITMAP_PROPERTIES1)); d2dProperties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE; d2dProperties.pixelFormat.format = DXGI_FORMAT_R8_UNORM; char* sourceData = new char[512*512]; ID2D1Bitmap1* d2dBitmap; deviceContext->DeviceContextPointer->CreateBitmap(size, sourceData, pitch, d2dProperties, &d2dBitmap); 

Bitmap Image (FAILING):

 deviceContext->BeginDraw(); D2D1_COLOR_F d2dColor = {}; deviceContext->Clear(d2dColor); // THIS LINE FAILS WITH THE DEBUG BREAKPOINT IF SINGLE CHANNELED deviceContext->DrawBitmap(bitmap, nullptr, 1.0f, D2D1_INTERPOLATION_MODE_LINEAR, nullptr); swapChain->Present(1, 0); deviceContext->EndDraw(); 
+5
source share
1 answer

From my little experience, Direct2D is really very limited.

Have you tried Direct2D effects ( ID2D1Effect )? You can write your own [it seems relatively complicated] or use one of the built-in effects [it's pretty simple].

There is one call to the Color Matrix Effect ( CLSID_D2D1ColorMatrix ) . Your DXGI_FORMAT_R8_UNORM (or DXGI_FORMAT_A8_UNORM , any single-channel) can work as an input (the input for the effects ID2D1Image and ID2D1Bitmap are inherited from ID2D1Image ). Then set D2D1_COLORMATRIX_PROP_COLOR_MATRIX to copy the input channel to all output channels. Did not try though.

0
source

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


All Articles