0

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#):

    // https://stackoverflow.com/questions/17678685/nv12-format-support-in-bitmapimage-c-sharp
    //// https://msdn.microsoft.com/en-us/library/windows/desktop/dd206750(v=vs.85).aspx
    //// https://en.wikipedia.org/wiki/YUV
    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

  • 1
    IDirect3DDevice9Ex_StretchRect is documented to support color-space conversion from YUV to RGBA only, so you probably need to convert yourself before stretching. IMHO, if you can, you should review your graphics technology toolchain, DirectX9 is 20y old and WPF won't evolve. – Simon Mourier Sep 04 '22 at 16:34

0 Answers0