Use of Bitmap with DirectX11

Started by
6 comments, last by 147 11 years, 6 months ago
I have a problem with using DirectX 11 pixel shaders for image processing.
I am writting a image manipulation program, but I faced a problem.
I need a simple (and fast) way to use a bitmap as texture input for the shader and I need a way to render to a bitmap, or to render to a normal rendertargetview and convert this to a bitmap.
Which way is possible and how can I do this?
Advertisement
What kind of bitmap, a Win32 DIB, a .BMP image file, something else?
I mean the Bitmap Object out of the System.Drawing namespace of the .net framework. I'm sorry that I forgot to write this. But if this would work better with other image objects, supported by the .net framework (4 and higher), this would also be an alternative.
What programming language, and do you use any framework for DX11?
Also, how fast does it need to be?

The following page has information on interoperability between Windows graphics APIs:
http://msdn.microsof...4(v=vs.85).aspx

In general, if you need to move data from system memory to GPU memory, you can copy pixels to a texture by creating a dynamic 2D texture and Map it when you want to update the pixels. Alternatively use UpdateSubresource.
To copy back from a render-target, use CopyResource to copy the pixels to a texture with staging usage, which you can Map for reading and read back the pixels.
For system mem < - > GPU mem there's probably no faster way.

In your case, you might want to look into creating textures using the GDI compatibility flag, which allows you to get a HDC to each texture. Alternatively look into WIC shared surfaces, which might be possible.
If you're using a DX11 framework it might have support already for these things so you don't have to write much yourself.
I'm assuming that you're using either SlimDX or SharpDX? If you're using SlimDX, the easiest option is probably to save the Bitmap to a Stream and then pass that Stream to Texture2D.FromStream. This will perform any necessary format conversions for you (such as going from RGB to RGBA) and can also generate mipmaps. Otherwise you'll have to obtain the pointer to the raw bitmap data using LockBits, loop through the data and convert the format if necessary, then pass your final data to the Texture2D constructor through a DataRectangle. For going back to a bitmap, there's Texture2D.ToStream which will save the texture as a bitmap file in memory. Then you can pass that to when constructing a Bitmap and it will be initialized from the texture data.

I'm not too familiar with SharpDX so I can't give specifics, but it should support similar functionality.
I use something like this (psuedocode)
[source lang="csharp"] System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();
System.Drawing.Image bitmapImage = System.Drawing.Image.FromFile(myFileName);
bitmapImage.Save(memoryStream);
memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
Texture2D texture = Texture2D.FromStream(deviceAccessor.GetCurrentGraphicsDevice(), memoryStream);[/source]
Thanks for this answers. I was not sure if I should use C# (with a wrapper) or C++, but I think I will start with C#, perhaps I will, if it works, try it with C++ for learning purpose.
I will try I out as fast as I can.
---------- UPDATE ---------------------------
The method for building the Texture2D from Stream works. The rest of the problem (converting the Texture2D to a stream) I will also ask in another forum and I will report if I find a way (eventually even without help of another forum) to manage this.
---------------------------------------------------

This method seems to work, but the conversion back to a Stream/File (in the code bellow a file), does not work.Has anyone an idea why? I use SharpDX.
[source lang="csharp"]Bitmap input = (Bitmap)Image.FromFile("Desert.jpg");
BitmapData inputBmpData = input.LockBits(new System.Drawing.Rectangle(0,0,input.Width, input.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppPArgb);

DataRectangle inputDataRectangle = new DataRectangle(inputBmpData.Scan0, inputBmpData.Stride);

inputTex2D = new Texture2D(device, new Texture2DDescription()
{
BindFlags = BindFlags.ShaderResource,
CpuAccessFlags = CpuAccessFlags.None,
Format = Format.B8G8R8A8_UNorm,
OptionFlags = ResourceOptionFlags.None,
MipLevels = 1,
Usage = ResourceUsage.Immutable,
Width = inputBmpData.Width,
Height = inputBmpData.Height,
ArraySize = 1,
SampleDescription = new SampleDescription(1, 0)
}, inputDataRectangle);
Texture2D.ToFile(context, inputTex2D, ImageFileFormat.Jpg, "Hello.jpg");[/source]

This topic is closed to new replies.

Advertisement