I'm drawing bitmaps in Direct2D. The bitmaps utilize transparency (alpha channel).
The blending looks wrong.
As a test I loaded a pure black png image with 50% transparency and drew it over a white background. The result is pixels with a Red, Green, and Blue value of 127 (0x7F7F7F). This suggests Direct2D's blend is ignoring gamma and treating the color values as if they were linear.
(Bitmaps use the regular sRGB color space and are at 32 bits per pixel, 8-bits each for Red, Green, Blue and Alpha). They are loaded in GUID_WICPixelFormat32bppPBGRA format.
In sRGB, a blend halfway between black and white is 186 (0xBABABA). This is the ideal result I want.
Can Direct2D display transparency with respect for gamma? How would I do that? Any help appreciated.
Blending is properly done in linear colorspace, so the process for blending sRGB pixels should be
Note that with black or white pixels, steps (1) and (3) are no-ops and can be omitted.
See the alpha channel processing section of the PNG specification. In particular, note this:
The equation for computing a composited sample value is
output = alpha * foreground + (1-alpha) * background
where the alpha value and the input and output sample values are expressed as fractions in the range 0 to 1. This computation should be performed with intensity samples (not gamma-encoded samples)
The section contains sample C code for alpha-channel processing
At the time this question was posed, HWND Render targets (drawing to the screen) did not support linear pixel formats; however, Direct-2D HwndRender targets have now been superseded by interface ID2D1DeviceContext. These are created via IDXGIFactory2::CreateSwapChainForHwnd()
and support more pixel formats like DXGI_FORMAT_B8G8R8A8_UNORM_SRGB which automatically performs the correct color-space conversions when blending (information provided by @Jeff McClintock).