Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ID2D1Bitmap1.Map() only returns 1 row of pixel data #4

Closed
d2phap opened this issue Feb 26, 2023 · 2 comments
Closed

ID2D1Bitmap1.Map() only returns 1 row of pixel data #4

d2phap opened this issue Feb 26, 2023 · 2 comments

Comments

@d2phap
Copy link
Contributor

d2phap commented Feb 26, 2023

Hi @smourier,

As my post from smourier/DirectN#34, I modified the function a bit to load all pixel data into a DataGridView.

public void LoadPixelDataIntoDataGrid()
{
    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 dataSize = (int)(size.width * size.height * 4);

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

    // load all pixel data into data grid view
    dt.DataSource = bytes.Select((i, index) => new
    {
        Index = index,
        Value = i.ToString(),
    }).ToList();
}

The problem

It only returns the first row of the pixel data; the rest values are just 0!
In the demo, I used 4x4 PNG image with alpha pixels, and draw 100X onto the window.

image

Full source code:

WinFormsApp1.zip

@d2phap
Copy link
Contributor Author

d2phap commented Feb 26, 2023

I managed to fix it.

- var dataSize = (int)(size.width * size.height * 4);
+ var dataSize = (int)(size.height * map.pitch);

According to https://learn.microsoft.com/en-us/windows/win32/api/d2d1_1/ns-d2d1_1-d2d1_mapped_rect, pitch is the size in bytes of an individual scanline in the bitmap. So the dataSize should be calculated by image height times pitch.

@d2phap d2phap closed this as completed Feb 26, 2023
@smourier
Copy link
Owner

smourier commented Feb 26, 2023

Yes, this is also called the stride, it depends on the bitmap layout in memory, you never want to assume things like "4" https://learn.microsoft.com/en-us/windows/win32/medfound/image-stride

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants