0

XNAゲームでスクリーンショットを作成すると、それぞれがtexture.SaveAsPngある程度のメモリを消費し、ゲームに戻らないようです。だから結局私はメモリを使い果たします。テクスチャデータをFileStreamMemoryStreamに保存してみましたが、そこからとして保存できることを期待してBitmap、結果は同じです。このメモリを強制的に解放する方法や、メモリ不足の例外が発生することなく画像データを取得して別の方法で保存できる回避策はありますか?

sw = GraphicsDevice.Viewport.Width;
sh = GraphicsDevice.Viewport.Height;

int[] backBuffer = new int[sw * sh];
GraphicsDevice.GetBackBufferData(backBuffer);
using(Texture2D texture = new Texture2D(GraphicsDevice, sw, sh, false,
  GraphicsDevice.PresentationParameters.BackBufferFormat))
{
    texture.SetData(backBuffer);
    using(var fs = new FileStream("screenshot.png", FileMode.Create))        
        texture.SaveAsPng(fs, sw, sh);  // ← this line causes memory leak      
}
4

1 に答える 1

2

テクスチャバイトから直接ビットマップを作成し、内部メソッドをバイパスして、がリ​​ークしているかどうかを確認できる場合がSaveAsPngあります。

この拡張メソッドを試してください(残念ながら、テストできません(xnaが機能していません)が、機能するはずです)。

public static class TextureExtensions
{
    public static void TextureToPng(this Texture2D texture, int width, int height, ImageFormat imageFormat, string filename)
    {
        using (Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb))
        {
            byte blue;
            IntPtr safePtr;
            BitmapData bitmapData;
            Rectangle rect = new Rectangle(0, 0, width, height);
            byte[] textureData = new byte[4 * width * height];

            texture.GetData<byte>(textureData);
            for (int i = 0; i < textureData.Length; i += 4)
            {
                blue = textureData[i];
                textureData[i] = textureData[i + 2];
                textureData[i + 2] = blue;
            }
            bitmapData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
            safePtr = bitmapData.Scan0;
            Marshal.Copy(textureData, 0, safePtr, textureData.Length);
            bitmap.UnlockBits(bitmapData);
            bitmap.Save(filename, imageFormat);
        }
    }
}

それは少し粗雑ですが、あなたはそれをきれいにすることができます(それがうまくいくなら)。

最後になりましたが(他のすべての試みが失敗した場合)、自分自身を呼び出すことができGarbageCollectionますが、これはかなり悪い習慣としてお勧めできません。

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

上記のコードは最後の手段にすぎません。

幸運を。

于 2013-01-14T01:27:53.057 に答える