0

I am working with Direct2D render targets and I have an object of type ID2D1Bitmap. I need to display this bitmap in a WPF Window and I was thinking to host this bitmap into a Image control. In order to do it a solution could be to convert the ID2D1Bitmap object into a System::Windows::Media::ImageSource object, or to save the bitmap into a file which could be loaded afterwards.

I tried to look for different approaches but without any result, because the Direct2D APIs do not offer any solution AFAIK.

Is there any way to do this?

Nick
  • 10,309
  • 21
  • 97
  • 201

2 Answers2

0

Best solution I have found for WPF and UWP apps is SharpDX. See the SharpDX website.

I have tried to use the D2DWrappers in the past (see the Microsoft site), but in my UWP development, I found the SharpDX code easier to use. I would think the same for WPF as well since it is also C# code.

Kory Gill
  • 6,993
  • 1
  • 25
  • 33
0

Direct2D bitmaps are hardware device dependent resources and not generally easily accessible from the CPU side of the system. Getting to the pixels of the ID2D1Bitmap is hence difficult, it is not designed neither is it intended to be used that way. Any mechanism that gets raw bytes out of a Direct2D bitmap usually does so by creating a WIC bitmap out of it to access the byte stream. This way you can write it into a file or even a byte array and use some interop to access it in C#. If you want to write it to a file and reading it in WPF, this mechanism would work. If you have the bitmap data in a IWICBitmapSource object at some time during processing, and if you can cache it, the job would be easier. Converting a System.Drawing.Bitmap to a System.Windows.Media.ImageSource is answered here : Converting Bitmap to ImageSource (Thanks to @MSL who pointed out the above answer in comments).

At this point, the way you use it is a little unclear, a bit more of information on the intended use or a short sample would really help here.

EDIT 1: Take a look at this SO Qn: Save ID2D1Bitmap to file and the comments for a version of code that saves a ID2D1Bitmap into a file. It essentially does the conversion to IWICBitmap and writes it out to a file. At this step, since IWICBitmap inherits from IWICBitmapSource you can even use the CopyPixels() method to dump the bitmap data into a byte array, should you wish to do so.

Now if you are going with the approach of saving it to a file, getting a System.Drawing.Bitmap is as simple as:

bitmap = new Bitmap("<YOUR_BITMAP_FILENAME>")

And you can convert it to a BitmapImage for use in WPF as:

using(MemoryStream memstream = new MemoryStream())
{
    bitmap.Save(memstream, ImageFormat.Bmp);
    memstream.Position = 0;
    BitmapImage bitmapImage = new BitmapImage();
    bitmapImage.BeginInit();
    bitmapImage.StreamSource = memstream;
    bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
    bitmapImage.EndInit();
}
Community
  • 1
  • 1
jester
  • 3,491
  • 19
  • 30
  • How can I create a WIC bitmap out of the ID2D1Bitmap source in order to access its byte stream? Also it would be useful to explain how from a WIC bitmap source I can get the Drawing.Bitmap. – Nick Nov 15 '16 at 15:39
  • I saw your edit, but when I execute the code I get an D2DERR_WRONG_RESOURCE_DOMAIN error (when I draw the bitmap) into the wic render target. – Nick Nov 15 '16 at 19:57
  • Try using rtProps.type = D2D1_RENDER_TARGET_TYPE_SOFTWARE; rtProps.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE; – jester Nov 15 '16 at 20:12
  • Are you using the same settings mentioned above for the source ID2D1RenderTarget and the destination WIC RenderTarget ? I guess that is needed. DEFAULT settings would not work. – jester Nov 15 '16 at 20:23
  • The source render target is a `ID2D1DeviceContext1` created as `D2DDevice->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTITHREADED_OPTIMIZATIONS, &d2dContext)` – Nick Nov 15 '16 at 20:35
  • The reason for the original error is that the source and destination render target are created with default options. And resources cannot be shared between render targets with default options since it is not known where the rendering might happen. Now if you do want to do this sharing, it needs to adhere to what is mentioned here : https://msdn.microsoft.com/en-us/library/windows/desktop/dd756757(v=vs.85).aspx#sharing_render_target_resources. You might have to do some reorg in your code to do that. Hence the ask for a minimal sample of your application code that just shows the intended use. – jester Nov 22 '16 at 06:48