有没有从XNA中的Bitmap对象创建Texture2D的快速替代方法?

Mat*_*wen 9 c# xna bitmap texture2d

我已经环顾了很多,我发现从Bitmap创建Texture2D的唯一方法是:

using  (MemoryStream s = new  MemoryStream())
{
   bmp.Save(s, System.Drawing.Imaging.ImageFormat.Png);
   s.Seek(0, SeekOrigin.Begin);
   Texture2D tx = Texture2D.FromFile(device, s);
}
Run Code Online (Sandbox Code Playgroud)

Texture2D tx = new Texture2D(device, bmp.Width, bmp.Height,
                        0, TextureUsage.None, SurfaceFormat.Color);
tx.SetData<byte>(rgbValues, 0, rgbValues.Length, SetDataOptions.NoOverwrite);
Run Code Online (Sandbox Code Playgroud)

其中rgbValues是一个字节数组,包含32位ARGB格式的位图像素数据.

我的问题是,我可以尝试更快的方法吗?

我正在编写一个地图编辑器,它必须读取自定义格式图像(地图图块)并将它们转换为Texture2D纹理才能显示.以前版本的编辑器是一个C++实现,它首先将图像转换为位图,然后转换为使用DirectX绘制的纹理.我在这里尝试了相同的方法,但是上述两种方法都非常慢.要加载到内存中,映射所需的所有纹理都需要第一个方法~250秒,而第二个方法在合理的规格计算机上需要110秒(为了比较,C++代码需要大约5秒钟).如果有一种方法可以直接编辑纹理数据(例如使用Bitmap类'

任何帮助将非常感谢.

谢谢

buf*_*erz 10

你想要LockBits吗?你得到了LockBits.

在我的实现中,我从调用者传递了GraphicsDevice,所以我可以使这个方法通用和静态.

public static Texture2D GetTexture2DFromBitmap(GraphicsDevice device, Bitmap bitmap)
{
    Texture2D tex = new Texture2D(device, bitmap.Width, bitmap.Height, 1, TextureUsage.None, SurfaceFormat.Color);

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

    int bufferSize = data.Height * data.Stride;

    //create data 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
    tex.SetData(bytes);

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

    return tex;
}
Run Code Online (Sandbox Code Playgroud)


小智 9

他们在XNA 4.0中将格式从bgra更改为rgba,因此该方法提供了奇怪的颜色,需要切换红色和蓝色通道.这是我写的一种超快速的方法!(在大约3秒内加载1500x 256x256像素纹理).

    private Texture2D GetTexture(GraphicsDevice dev, System.Drawing.Bitmap bmp)
    {
        int[] imgData = new int[bmp.Width * bmp.Height];
        Texture2D texture = new Texture2D(dev, bmp.Width, bmp.Height);

        unsafe
        {
            // lock bitmap
            System.Drawing.Imaging.BitmapData origdata = 
                bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);

            uint* byteData = (uint*)origdata.Scan0;

            // Switch bgra -> rgba
            for (int i = 0; i < imgData.Length; i++)
            {
                byteData[i] = (byteData[i] & 0x000000ff) << 16 | (byteData[i] & 0x0000FF00) | (byteData[i] & 0x00FF0000) >> 16 | (byteData[i] & 0xFF000000);                        
            }                

            // copy data
            System.Runtime.InteropServices.Marshal.Copy(origdata.Scan0, imgData, 0, bmp.Width * bmp.Height);

            byteData = null;

            // unlock bitmap
            bmp.UnlockBits(origdata);
        }

        texture.SetData(imgData);

        return texture;
    }
Run Code Online (Sandbox Code Playgroud)

  • 太好了!但是你不应该修改位图数据,因为你用ReadOnly锁定它?您可以先复制它然后进行转换.或者甚至更简单,只需一步完成转换和复制!(分配给imgData [i]而不是byteData [i],那么根本不需要副本!) (2认同)