Sunday, 8 June 2008

Copying a Dynamically Created Bitmap to a Texture2D with XNA

I am sure someone has done it before, but I couldn't find any complete example in the web, so I wrote my own code: essentially it allows you to create a texture from a dynamically created Bitmap object. So you don't have to load the Bitmap from a file but you can dynamically create one in memory, do some GDI+ drawing on it (e.g for procedural textures) and then load it to a texture and use it. This can be useful if you want to programmatically create textures. Even though I have not tried it yet, you should be able to even update the texture before every frame using this method. This is the code:

using SD = System.Drawing;
using SDI = System.Drawing.Imaging;

// ...

protected override void LoadContent()
{
// Create Bitmap that we want edit and transfer to a texture
SD.Bitmap bitmap = new SD.Bitmap(100, 100);

// Create Graphics for the bitmap
SD.Graphics bitmapGraphics = SD.Graphics.FromImage(bitmap);

// Do some drawing with GDI+, e.g.
bitmapGraphics.Clear(SD.Color.CornflowerBlue);
// ... what ever you want to do :)

// Get rid of the graphcis object
bitmapGraphics.Dispose();

// Initialize our custom texture (should be defined in the class)
customTexture = new Texture2D(this.GraphicsDevice, bitmap.Width, bitmap.Height, 0, TextureUsage.None, SurfaceFormat.Color);

// Lock the bitmap data
SDI.BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);

// calculate the byte size: for PixelFormat.Format32bppArgb (standard for GDI bitmaps) it's the hight * stride
int bufferSize = data.Height * data.Stride; // stride already incorporates 4 bytes per pixel

// create buffer
byte[] bytes = new byte[bufferSize];

// copy bitmap data into buffer
Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);

// copy our buffer to the texture
customTexture.SetData(bytes);

// unlock the bitmap data
bitmap.UnlockBits(data);
}

4 comments:

jcdickinson said...

Thanks, great stuff. I am trying to make a Liero clone (worth looking up: great game), so this will come in handy when I get to 2D terrain deformation.

Unknown said...

Thanks! I looked for hours for this!

Pereira said...

Thanks! It was very useful.

miser said...

Thanks! Most efficient method I've found!