Texture2d.SaveAsPng()内存泄漏

时间:2013-10-08 12:42:34

标签: c# windows-phone-7 memory-leaks xna

我发现了方法Texture2d.SaveAsPng()的奇怪问题 每次拨打1.5mb消失。 我使用此方法将纹理保存到隔离存储

public static void SaveTextureToISF(string fileName, Texture2D texture)
        {
            using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (
                    IsolatedStorageFileStream fileStream = new IsolatedStorageFileStream(fileName, FileMode.Create, file)
                    )
                {
                    texture.SaveAsPng(fileStream, texture.Width, texture.Height);
                    fileStream.Close();
                }
            }
        }

我需要保存大量的纹理,并且我有巨大的内存泄漏。 在Windows Phone 8设备上都可以正常工作,这个问题仅限于Windows Phone 7。

2 个答案:

答案 0 :(得分:2)

Texture2D.SaveAsPng()有一个已知的内存泄漏。我注意到这个问题已经有一段时间了,并找到了解决方案。唯一的解决方案是创建自己的纹理保存例程。

public static void Save(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);
    }
}

然后您可以将其称为(如果您将其作为扩展方法保留)texture.SaveAs(texture.Width, texture.Height, ImageFormat.Png, fileName);

答案 1 :(得分:1)

通过在byte阵列中获取纹理数据并将其保存到隔离存储来解决问题。

public static void SaveTextureToISF(string fileName, Texture2D texture)
{
    byte[] textureData = new byte[4 * texture.Width * texture.Height];
    texture.GetData(textureData);
    Save(fileName, textureData); //saving array to IS
}

当需要纹理时,从存储中加载byte数组并将此数据加载到新纹理。

 public static Texture2D LoadTextureFromISF(string fileName, int width, int height)
 {
     Texture2D texture = new Texture2D(GraphicsDevice, width, height);
     byte[] textureData = Load(fileName); //load array from IS
     texture.SetData(textureData);
     return texture;
 }

有一点需要注意,从存储中加载纹理时,您应该确切知道已保存纹理的尺寸,并将其作为参数传递给加载函数。这很容易修改,但我不需要。