12

私は多くのことを調べましたが、ビットマップから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);
}

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

ここで、rgbValuesは、32ビットARGB形式のビットマップのピクセルデータを含むバイト配列です。

私の質問は、私が試すことができるより速いアプローチはありますか?

カスタム形式の画像(マップタイル)を読み取り、それらをTexture2Dテクスチャに変換して表示する必要があるマップエディタを作成しています。以前のバージョンのエディターはC++実装でしたが、最初に画像をビットマップに変換し、次にDirectXを使用して描画するテクスチャに変換しました。私はここで同じアプローチを試みましたが、上記のアプローチは両方ともかなり遅すぎます。マップに必要なすべてのテクスチャをメモリにロードするには、妥当な仕様のコンピュータで最初のアプローチに約250秒、2番目のアプローチに約110秒かかります(比較のために、C ++コードには約5秒かかりました)。テクスチャのデータを直接編集するメソッドがある場合(Bitmapクラスなど)

どんな助けでも大歓迎です。

ありがとう

4

4 に答える 4

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;
}
于 2010-05-20T00:52:43.583 に答える
10

彼らは 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;
    }
于 2011-09-12T21:18:07.960 に答える
3

ウェブカメラの画像を取得するために提案されているように、LockBits を使用する場合は、PixelFormat を .Format32bppArgb として指定する必要があることがわかりました。

        BitmapData bmd = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height),
            System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        int bufferSize = bmd.Height * bmd.Stride;
        //create data buffer 
        byte[] bytes = new byte[bufferSize];
        // copy bitmap data into buffer
        Marshal.Copy(bmd.Scan0, bytes, 0, bytes.Length);

        // copy our buffer to the texture
        Texture2D t2d = new Texture2D(_graphics.GraphicsDevice, bmp.Width, bmp.Height, 1, TextureUsage.None, SurfaceFormat.Color);
        t2d.SetData<byte>(bytes);
        // unlock the bitmap data
        bmp.UnlockBits(bmd);
        return t2d;
于 2010-05-20T07:41:42.950 に答える