我有一个问题:(否则我不会在这里;(
我正在创建一个具有显示"3D"模型功能的应用程序。这部分实际上是从多个角度拍摄的图像的集合,并允许用户"旋转"模型"。这个想法很好,但问题在于图像的加载。
我发现有两种方法:
- 将所有图像加载到内存中,然后简单地将它们切换到正确的角度
- 根据需要加载图像-我们可以提前加载一些
然而,这些都有问题:
- 如果我运气好的话,这些图像会进入记忆,但事实并非如此。它们每个大约是1.5-2MB,并且每个模型大约有75-100个图像。这使得总大小至少达到约115MB
- 如果幸运的话,图像加载速度会比用户"旋转"的速度快,但他们没有。用户可以很容易地切换到尚未加载的角度,从而导致几秒钟的黑屏
我创建了一个加载器,它允许我简单地将我需要的图像添加到堆栈中,然后加载器将逐个加载图像。如果用户滚动速度相当慢,则可以正常工作。我的加载程序负责在加载完成后释放内存,所以无论我加载多少图像,只要我指定要存储在内存中的最大图像,应用程序通常都不会崩溃。我的加载程序可以很快加载图像,但仍有几毫秒(~250ms(的时间将大图像加载到内存中。当然,加载程序在不同的线程上,加载不会阻碍UI响应。这就是为什么如果用户快速来回滑动,实际上不会显示任何图像,因为加载和卸载都在同一时间工作,导致没有图像:(
所以,我的问题是:如何在不将所有图像加载到内存中的情况下,提供平滑且用户满意的图像旋转?
不要加载(或存储(您不需要的分辨率。如果您的用户需要缩放,内存不足的二进制图像金字塔是一种廉价的方法,可以让您只加载所需的缩放级别。如果用户需要平移大于显示区域的图像,则可以将大图像拆分为较小的平铺,只加载所需的平铺。
如果你想玩得开心,你可以编写一个UI感知缓存管理器来抢先加载你认为可能很快就需要的磁贴,并标记你很确定不会很快需要的磁片进行抢先。
更好的压缩可以将更多的图像数据放入内存,并加快加载时间。所以,要注意单独的图像压缩,也不要加载你不需要的图像质量。
作为一项非同寻常的措施:由于角度略有不同的图像彼此相似,因此您可以通过表示差异来节省时间和空间,而不是查找光场压缩。您仍然需要从压缩形式转换为可以绘制的特定位图,但如果压缩允许数据集保留在内存中,则可能会获得很大的速度。
如果你不能将压缩的数据集放入内存,那么用户很有可能能够快速来回滑动,从而破坏你的缓存。因此,如果平滑度是你的主要目标,你可以尝试一种"UI解决方案",将旋转速率(或每次滑动的旋转范围?(限制在数据加载程序可以遵循的范围内。
我唯一的建议是有效地加载它们。我假设你正在使用这里描述的技术
如果图像的分辨率高于屏幕,则可以计算要渲染的图像的样本大小,然后可以加载适合屏幕的图像,而不是使用更少内存的全尺寸图像。如果你已经在做了,那么在我看来,你似乎已经在高效地做了。也许你可以在加载图像时向用户显示某种占位符图形,这样他们就不会只有空白了。
感谢您的回答。我自嘲,看完答案就上床睡觉了。让我分享一下我是如何解决这个问题的——它使用了一些答案:
我试图将大图像缓存在内存中——这是不必要的,为什么不存储一个较低分辨率的版本,然后在用户停止滚动时加载高分辨率?然后用户可以随心所欲地快速滚动,记忆中总会有图像可以快速绘制。当用户停止/减慢滚动速度时,我们加载高分辨率图像。
因为他将快速滚动,他将无法看到较低分辨率的较低质量。而且,由于只需要加载一个高分辨率,因此约250毫秒的延迟几乎不明显。
这确实结合了两种情况中最好的一种。我可以使用Android的方法加载较低分辨率版本的位图。