directx – IDirect3DDevice9_StretchRect changes image contrast

My app uses IDirect3DDevice9Ex_StretchRect to copy image from NV12 surface into D3DFMT_X8R8G8B8 surface. But the result image has lower contrast than the original.

Test setup:
My source image comes from USB webcam, completely covered – it gives me almost black.

  1. Test A: I run the Windows Camera app, take a screenshot and measure the black color in a image editor, I get exact RGB:(9,9,9).
  2. Test B: I open the cam in my cam, it captures YUY2, then converts into NV12. I get a sample of the NV12 image, and run my own conversion code (see below). This way, I get also almost black image, in the test case the pixel colors are again RGB: (9,9,9). So, I think my captured image is the same as from Camera app, and also that my YUV/RGB conversion is correct.
  3. Test C: The same as before, but instead of converting NV12 myself, my code is calling IDirect3DDevice9Ex_StretchRect() to copy the image into the RGB surface. There I access pixel data directly (LockRect) and there I find the pixels with color RGB: (24,24,24), so much brighter – and that I think is incorrect

Here is snipped of my own conversion code (this conversion is in C#):

    var c = y - 16;
    var d = v - 128;
    var e = u - 128;
    c = c < 0 ? 0 : c;

    var r = ((298 * c) + (409 * e) + 128) >> 8;
    var g = ((298 * c) - (100 * d) - (208 * e) + 128) >> 8;
    var b = ((298 * c) + (516 * d) + 128) >> 8;

    *destPtrR = clip(r);
    *destPtrG = clip(g);
    *destPtrB = clip(b);

The entire solution is very complex, there is a .NET/C#/WPF app, GStreamer running the multimedia pipeline is driven by C++ code, there is a custom rendering GST element based on D3D9. It copies the image frames into a swapchain’s backbuffer and that is then presented into D3DImage. Anyway, my tests lead me into conclusion that IDirect3DDevice9Ex_StretchRect does something I am not expecting. Like gamma correction? But the app is windowed (so gamma ramp should not be used) and I am not calling IDirect3DSwapChain9_Present() at all…

Can I change the behavior by changing some flag etc?

Note: I am not author the code around D3D9 and I am a beginner in DirectX programming

Read more here: Source link