Open MWstudios opened 3 years ago
Okay, so I've created a fork of this project and tried to get at least a bitmap of the graphic. I seem to be pretty close now, as it actually gets a bitmap of the correct size, but the contents are all black.
Context.cpp:
HBITMAP ContextToHbitmap(HANDLE ctx)
{
RetrieveContext(ctx);
return CreateCompatibleBitmap(CreateCompatibleDC(GetDC(context->renderTarget->GetHwnd())),
context->renderTarget->GetSize().width, context->renderTarget->GetSize().height);
}
D2DGraphics.cs:
public HANDLE GetHBitmap()
{
return D2D.ContextToHbitmap(this.Handle);
}
I'm leaving this here if someone wants to finish it.
Thanks @MWstudios! I'm also working on a task like this. I will let you know if there is any progress.
Similar to #27, #44
Hi @jingwood Any update on this?
Bumping an old thread, but if any contributor out there is reading this, there is a way:
ID2D1Bitmap1::Map()
and ID2D1Bitmap1::Unmap()
Which maps the entire bitmap from GPU to CPU memory. The problem is that it must be ID2D1Bitmap1
from a newer DirectX version (though still available on Windows 7) and the bitmap must be made with the flag D2D1_BITMAP_OPTIONS_CPU_READ
. This would make deep impacts in the library, and I'm unsure if the flag slows down the performance in any way, but it is possible.
When we're at it, it's probably more effective to add Map()
and Unmap()
, rather than GetPixel()
and SetPixel()
and then needlessly map the entire thing on every call.
public static Color GetPixelColor(this IComObject
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 = srcBitmap1.GetSize().ToD2D_SIZE_U();
using var bitmap1 = dc.CreateBitmap<ID2D1Bitmap1>(size, bmpProps);
bitmap1.CopyFromBitmap(srcBitmap1);
var map = bitmap1.Map(D2D1_MAP_OPTIONS.D2D1_MAP_OPTIONS_READ);
var startIndex = (y * map.pitch) + (x * 4);
var bytes = new byte[4];
Marshal.Copy((nint)(map.bits + startIndex), bytes, 0, bytes.Length);
bitmap1.Unmap();
// since pixel data is D2D1_ALPHA_MODE_PREMULTIPLIED,
// we need to re-calculate the color values
var a = bytes[3];
var alphaPremultiplied = a / 255f;
var r = (byte)(bytes[2] / alphaPremultiplied);
var g = (byte)(bytes[1] / alphaPremultiplied);
var b = (byte)(bytes[0] / alphaPremultiplied);
var color = Color.FromArgb(a, r, g, b);
return color;
}
I need to pick a color from a bitmap, but the GetPixel function only exists in the default Bitmap class. Also graphics from image would allow drawing on top of an existing bitmap and not creating a blank one, which Device.CreateBitmapGraphics is doing.
Edit: You can make an empty graphic and draw the bitmap on it, but I meant that you can't directly edit the existing bitmap, just paste it onto the graphic, and there's no way to get the result back.