jingwood / d2dlib

A .NET library for hardware-accelerated, high performance, immediate mode rendering via Direct2D.
MIT License
244 stars 44 forks source link

Is it possible to create a graphics object from a bitmap? #1

Closed ghost closed 6 years ago

ghost commented 6 years ago

Hey there man!

Been studying your code a bit and I've cleaned a lot up (for instance, the control can now be dragged and dropped into the forms.) I'm using your code to create a control that has multiple layers like you would have in photoshop or other editing software, the only issue is that I can not create a graphics object from a bitmap.

var IntPtr = _Canvas.GetHbitmap(); var Device = D2DDevice.FromHwnd(IntPtr); CanvasGraphics = Device.CreateBitmapGraphics();

` System.AccessViolationException HResult=0x80004003 Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt. Source= StackTrace:

` So before I rewrite the layers to be D2DControls instead of Bitmaps I'd like to ask if you could help out enabling me to create this feature for bitmaps (if that's even possible.) This makes an absolutely amazing alternative to graphics and I'd have no problem slowly piecing it together until it is. Provided is my copy of your source code - including "DrawingPanel.cs" which will eventually be the layered panel. If this project is too old and you wish to not continue it I'd be glad to take it over from you. [Snipper DirectDraw.zip](https://github.com/jingwood/d2dlib/files/2257780/Snipper.DirectDraw.zip)
jingwood commented 6 years ago

It's possible to create a memory graphics context, but is not from a bitmap object, this D2DBitmapGraphics doesn't require a GDI bitmap, it automatically creates empty built-in memory bitmap in direct2d context.

So just call this function and it will be done.

var myMemoryGraphics = Device.CreateBitmapGraphics()

The exception System.AccessViolationException comes from D2DDevice.FromHwnd method because D2DDevice.FromHwnd can only receive a window handle - HWND, not a HBITMAP.


I modified your code and finished an example that has 2 drawing layers. Snipper DirectDraw-modified.zip

drawing_layers_example

Some code in this example:

// create a drawing layer
var layer1 = panel.AddLayer();

// get the graphics context from layer1
var g1 = layer1.CanvasGraphics;

// draw a text on layer 1
g1.BeginRender(D2DColor.Transparent);
g1.DrawText("Hello Layer1", D2DColor.Green, this.Font, 100, 100);
g1.EndRender();

It is necessary to pass a D2DColor.Transparent color when calling BeginRender method, it makes the memory bitmap transparent since your program drawing multiple layers.

ghost commented 6 years ago

Wow! Thank you for your great response with an included example!

ghost commented 6 years ago

Setting the opacity of a layer does not affect the opacity of the drawn graphics.

[DllImport("d2dlib.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void DrawBitmapRenderTarget([In] HANDLE context, HANDLE bitmapRenderTarget, ref D2DRect rect, float opacity = 1, D2DBitmapInterpolationMode interpolationMode = D2DBitmapInterpolationMode.Linear);

public void DrawBitmap(D2DBitmapGraphics bg, ref D2DRect rect, float opacity = 1, D2DBitmapInterpolationMode interpolationMode = D2DBitmapInterpolationMode.Linear) { D2D.DrawBitmapRenderTarget(DeviceHandle, bg.DeviceHandle, ref rect, opacity, interpolationMode); }

If you change the opacity to 0.5f, nothing appears to change in transparency. Is this a bug?

jingwood commented 6 years ago

You're welcome. Yes opacity is a bug and has been fixed. You may need to get the latest code and rebuild a new d2dlib.dll.