smourier / DirectN

Direct interop Code for .NET Framework, .NET Core and .NET 5+ : DXGI, WIC, DirectX 9 to 12, Direct2D, Direct Write, Direct Composition, Media Foundation, WASAPI, CodecAPI, GDI, Spatial Audio, DVD, Windows Media Player, UWP DXInterop, WinUI3, etc.
MIT License
311 stars 28 forks source link

Getting pixel data from `ID2D1Bitmap1.Map()` are not correct #34

Closed d2phap closed 1 year ago

d2phap commented 1 year ago

Hi @smourier

I create this method to get the pixel color:

private IComObject<ID2D1Bitmap1>? _imageD2D;
private IComObject<ID2D1DeviceContext6>? _device;

public byte[] GetColor(int x, int y)
{
    var bmpProps = new D2D1_BITMAP_PROPERTIES1()
    {
        bitmapOptions = D2D1_BITMAP_OPTIONS.D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS.D2D1_BITMAP_OPTIONS_CPU_READ,
        pixelFormat = new D2D1_PIXEL_FORMAT()
        {
            alphaMode = D2D1_ALPHA_MODE.D2D1_ALPHA_MODE_PREMULTIPLIED,
            format = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM,
        },
        dpiX = 96.0f,
        dpiY = 96.0f,
    };

    var size = _imageD2D.GetSize().ToD2D_SIZE_U();
    using var bitmap1 = _device.CreateBitmap<ID2D1Bitmap1>(size, bmpProps);
    bitmap1.CopyFromBitmap(_imageD2D);

    var map = bitmap1.Map(D2D1_MAP_OPTIONS.D2D1_MAP_OPTIONS_READ);
    var startIndex = ((y * size.width) + x) * 4;
    var dataSize = (int)(size.width * size.height * 4);

    var bytes = new byte[dataSize];
    Marshal.Copy(map.bits, bytes, 0, dataSize);
    bitmap1.Unmap();

    var b = bytes[startIndex];
    var g = bytes[startIndex + 1];
    var r = bytes[startIndex + 2];
    var a = bytes[startIndex + 3];

    var color = new byte[] { r, g, b, a };

    return color;
}

Problems

When I debug it, with this image (4 x 4 pixels), there are 2 problems:

  1. The bytes only contains the first row of the pixel data, the rest are just 0.
  2. The pixel data with alpha (x=2, y=0) are not correct:
    • Expectation: [b=47, g=196, r=227, a=92]
    • Actual value: [b=17, g=71, r=82, a=92]

Debug data

image

Could you please help? Thank you!

smourier commented 1 year ago

Hi,

DirectN is only a bunch of .NET declarations that directly map to underlying techs, it has very little intelligence on its own, so it seems it's more a D2D issue (if it's an issue, are you sure it's not expected?)

If you have a full reproducing project, and I find some time, I can investigate.

d2phap commented 1 year ago

Thanks @smourier for the reply. I realized I am using WicNet instead of DirectN! So I created a ticket here: https://github.com/smourier/WicNet/issues/4