我正在为Windows Phone XNA开发,并希望加载尺寸较小的纹理,以减少不需要完整图像的内存影响。
我目前的解决方案是使用rendertarget绘制并返回该rendertarget作为要使用的较小纹理:
public static Texture2D LoadResized(string texturePath, float scale)
{
Texture2D texLoaded = Content.Load<Texture2D>(texturePath);
Vector2 resizedSize = new Vector2(texLoaded.Width * scale, texLoaded.Height * scale);
Texture2D resized = ResizeTexture(texLoaded, resizedSize);
//texLoaded.Dispose();
return resized;
}
public static Texture2D ResizeTexture(Texture2D toResize, Vector2 targetSize)
{
RenderTarget2D renderTarget = new RenderTarget2D(
GraphicsDevice, (int)targetSize.X, (int)targetSize.Y);
Rectangle destinationRectangle = new Rectangle(
0, 0, (int)targetSize.X, (int)targetSize.Y);
GraphicsDevice.SetRenderTarget(renderTarget);
GraphicsDevice.Clear(Color.Transparent);
SpriteBatch.Begin();
SpriteBatch.Draw(toResize, destinationRectangle, Color.White);
SpriteBatch.End();
GraphicsDevice.SetRenderTarget(null);
return renderTarget;
}
这适用于纹理调整大小,但从内存使用看起来像纹理“texLoaded”不会被释放。当使用未注释的Dispose方法时,SpriteBatch.End()将抛出一个已处理的异常。
加载纹理的任何其他方式都会调整大小以减少内存使用量吗?
答案 0 :(得分:0)
您的代码几乎确定。它有一个小错误。
你可能会注意到它只会抛出你为任何给定纹理调用LoadResized
的第二个时间的异常。这是因为ContentManager
保留了它加载的内容的内部缓存 - 它“拥有”它加载的所有内容。这样,如果你加载两次,它只会让你回到缓存的对象。通过调用Dispose
,您将对象放在其缓存中!
然后,解决方案是不使用ContentManager
加载您的内容 - 至少不是默认实现。您可以从ContentManager
继承您自己的类,这些类不会缓存项目,因此(代码基于this blog post):
class FreshLoadContentManager : ContentManager
{
public FreshLoadContentManager(IServiceProvider s) : base(s) { }
public override T Load<T>(string assetName)
{
return ReadAsset<T>(assetName, (d) => { });
}
}
传入Game.Services
创建一个。不要忘记设置RootDirectory
属性。
然后使用此衍生内容管理器加载您的内容。您现在可以安全地(现在应该!)Dispose
自己从中加载的所有内容。
您可能还希望将事件处理程序附加到RenderTarget2D.ContentLost
事件,以便在图形设备“丢失”的情况下重新调整已调整大小的纹理。