I reduced program boot time (when running from within the IDE) from 12 seconds to less than 1 second by re-writing Texture.FromBitmap using unsafe code. For me it was easy because I'm only using 32 bit textures and 32 bit bitmaps. It would be nice to see this function optimized in future releases of the SDK. BTW, Texture.FromStream has the same problem.
-Jeremy

Performance problem with Texture.FromBitmap
JeffEngel
Kevin Lew
I actually wrapped System.Drawing.Bitmap in my own class, which caches Width and Height, so I'm never tempted to call those properties more than once.
jagilbert
Chitza
It was recommended that a bug was raised. If you want to follow this bug, or add your validation or vote then you can find it here:
http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx feedbackid=0dda86da-a83f-475d-8610-d3a08a14cc7f
Geetanjali
Here's what I used:
Texture texture = new Texture(dx, bitmap.Width, bitmap.Height, 1,
Usage.AutoGenerateMipMap, Format.A8R8G8B8, Pool.Managed);
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int pitch;
GraphicsStream textureData = texture.LockRectangle(0, LockFlags.None, out pitch);
Debug.Assert(bitmap.PixelFormat == PixelFormat.Format32bppArgb);
Debug.Assert(sizeof(int) == 4 && (bitmapData.Stride & 3) == 0 && (pitch & 3) == 0);
unsafe
{
int *texturePointer = (int*)textureData.InternalDataPointer;
for (int y = 0; y < bitmap.Height; y++)
{
int *bitmapLinePointer = (int*)bitmapData.Scan0 + y*(bitmapData.Stride/sizeof(int));
int *textureLinePointer = texturePointer + y*(pitch/sizeof(int));
int length = bitmap.Width;
while (--length >= 0)
*textureLinePointer++ = *bitmapLinePointer++;
}
}
bitmap.UnlockBits(bitmapData);
texture.UnlockRectangle(0);
Yuelin49124
The bug
http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx feedbackid=0dda86da-a83f-475d-8610-d3a08a14cc7f
now has 2 workarounds added, I've not tried them yet myself.
icesun
This one works for me:
texture = new Texture(device, bitmap.Width, bitmap.Height, 1, Usage.Dynamic, Format.A8R8G8B8, Pool.Default);
int pitch;
Microsoft.DirectX.GraphicsStream a = texture.LockRectangle(0, LockFlags.None, out pitch);
System.Drawing.Imaging.BitmapData bd = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
unsafe
{
byte* to = (byte*) a.InternalDataPointer;
byte* from = (byte*) bd.Scan0.ToPointer();
for (int y = 0; y < bd.Height; ++y)
for (int x = 0; x < bd.Width * 4; ++x)
to[pitch * y + x] = from[y * bd.Stride + x];
}
texture.UnlockRectangle(0);
bitmap.UnlockBits(bd);
Sheena192783
texture = new Texture(device, bitmap.Width, bitmap.Height, 1, Usage.Dynamic, Format.A8R8G8B8, Pool.Default);
Microsoft.DirectX.GraphicsStream a = texture.LockRectangle(0, LockFlags.None);
System.Drawing.Imaging.BitmapData bd = bitmapitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
unsafe
{
uint* to = (uint*) a.InternalDataPointer;
uint* from = (uint*) bd.Scan0.ToPointer();
for (int i = 0; i < bd.Height * bd.Width; ++i) to[ i] = from[ i];
}
texture.UnlockRectangle(0);
bitmap.UnlockBits(bd);
Doesn't work for all textures though, but I'm sure somebody around here can correct that.
Albert C
It's essentially the same of course...but mine is much faster, at least in VS2005's debug mode. You're using bitmap.Width and bitmap.Height in a loop. Don't do that, it's just as slow as everything else you can do with the Bitmap. Please don't ask me why.
Bosse A
From the MDX perspective, Texture from bitmap calls bitmap.GetPixel X*Y times, and as RoKo has shown there is some perf degredation when you run with the debugger attached. But its not an MDX problem directly, we are just seeing the effects.
mkfl
crim
It's only really slow, when you run with debugging. That was not the case in VS2003 though.
Markis_au
-Jeremy
Renate
-Jeremy