I intend to develop an application to get an image from a file and show it with Directx9
. I have used this code but I got the Error on SetBackBuffer
Method!!
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
private void d3dImage_IsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (d3dImage.IsFrontBufferAvailable)
{
// (Re)initialization:
Bitmap b = new Bitmap(@"C:\Users\newuser\Desktop\3.jpg");
IntPtr Mysurface = b.GetHbitmap();
if (Mysurface != IntPtr.Zero)
{
d3dImage.Lock();
//Error occurred this line
d3dImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, Mysurface);
d3dImage.Unlock();
CompositionTarget.Rendering += CompositionTarget_Rendering;
}
}
else
{
// Cleanup:
CompositionTarget.Rendering -= CompositionTarget_Rendering;
//Sample.Cleanup();
}
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
// Now that we can get an HWND for the Window, force the initialization
// that is otherwise done when the front buffer becomes available:
d3dImage_IsFrontBufferAvailableChanged(this,
new DependencyPropertyChangedEventArgs());
}
private void CompositionTarget_Rendering(object sender, EventArgs e)
{
if (d3dImage.IsFrontBufferAvailable)
{
d3dImage.Lock();
//Sample.Render();
// Invalidate the whole area:
d3dImage.AddDirtyRect(new Int32Rect(0, 0,
d3dImage.PixelWidth, d3dImage.PixelHeight));
d3dImage.Unlock();
}
}
actually I want show an image in d3dimage
in a WPF
project. Can any one help me? I could not find good resources about Directx
and C#!!!
Edited Using Sharpdx
and Got new Error "'HRESULT: [0x8876086C], Module: [SharpDX.Direct3D9], ApiCode: [D3DERR_INVALIDCALL/InvalidCall]
, "
s = new SharpDX.Direct3D9.Surface(IntPtr.Zero);
SharpDX.Direct3D9.Surface.FromFile(s, @"C:\Users\newuser\Desktop\3.jpg", SharpDX.Direct3D9.Filter.None, 1);
You're setting the back buffer to a Bitmap
. You cannot do this. The back buffer must be of type IDirect3DSurface9
. This is noted in the documentation for the SetBackBuffer method.
In order to use DirectX9
(unmanaged) from C# (managed), you need to use a wrapper library. Are you using one? If not, there are several available. SlimDX and SharpDX seem to be the most popular. Using any of the wrapper libraries, you can create a IDirect3DSurface9
that you render to with a IDirect3DDevice9
, and attach that surface to your WPF control. Your rendered content will then appear in the control.
I think using DirectX
may be overkill for what you need, but I'm not sure what the entire scope of your project is.
I put together a working example that uses SharpDX to display an image within a D3DImage
. This is very basic and doesn't include proper error handling. It's just meant to get you going in the right direction.
To create the necessary surfaces, you will need a Direct3D 9 Device
. The following code will create a Device
using SharpDX.
//Create the d3d interface.
Direct3D d3d = new Direct3D();
//Get a handle to the WPF window. This is required to create a device.
IntPtr windowHandle = new WindowInteropHelper(this).Handle;
//Create a device. Using standard creation param.
//Width and height have been set to 1 because we wont be using the backbuffer.
//Adapter 0 = default adapter.
PresentParameters presentationParams = new PresentParameters(1,1);
Device d3dDevice = new Device(d3d, 0, DeviceType.Hardware, windowHandle, CreateFlags.HardwareVertexProcessing, presentationParams);
Create a surface to hold the image data.
//Create an empty offscreen surface. Use SystemMemory to allow for surface copying.
Surface imageSurface = Surface.CreateOffscreenPlain(d3dDevice, ImageWidthPixels, ImageHeightPixels, Format.A8R8G8B8, Pool.SystemMemory);
//Fill the surface with the image data.
Surface.FromFile(imageSurface, "dx.jpg", Filter.None, 0);
Create the surface that acts as a render target. This is the type of surface required by D3DImage
.
//Create the surface that will act as the render target.
//Set as lockable (required for D3DImage)
Surface target = Surface.CreateRenderTarget(d3dDevice, ImageWidthPixels, ImageHeightPixels, Format.A8R8G8B8, MultisampleType.None, 0, true);
The image surface can be copied into the render target surface using the Device.UpdateSurfaces
method. Note that in the previous steps, both surfaces were created with the same format (A8R8G8B). Watch out for this. It's necessary for surface copies.
//Copy the image surface contents into the target surface.
d3dDevice.UpdateSurface(imageSurface, target);
You now have a surface that contains your image and that can be used with 'D3DImage`. Make sure you use the target surface, not the image source surface.
this.wpfImageSource.Lock();
this.wpfImageSource.SetBackBuffer(D3DResourceType.IDirect3DSurface9, target.NativePointer);
this.wpfImageSource.AddDirtyRect(new Int32Rect(0, 0, wpfImageSource.PixelWidth, wpfImageSource.PixelHeight));
this.wpfImageSource.Unlock();
The image appears!