1

我发现方法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 上。

4

2 回答 2

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);

于 2013-10-08T22:12:16.850 回答
0

通过获取数组中的纹理数据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;
 }

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

于 2013-10-15T06:26:47.697 回答