2

我有一个问题:(否则我不会在这里;)

我正在创建一个具有显示“3D”模型功能的应用程序。这部分实际上是从多个角度拍摄的图像集合,并允许用户“旋转”“模型”。这个想法运行良好,但问题在于图像的加载。

我发现有两种方法:

  1. 将所有图像加载到内存中,然后简单地将它们切换到正确的角度。
  2. 根据需要加载图像 - 我们可以提前加载一些。

然而这些都有问题:

  1. 如果我幸运的话,这些图像会适合记忆,但事实并非如此。它们每个大约 1.5-2MB,每个模型大约有 75-100 张图像。这使总大小至少达到约 115MB。
  2. 如果我幸运的话,图像的加载速度会比用户“旋转”的速度快,但他们不会。用户可以轻松切换到尚未加载的角度,从而导致黑屏几秒钟。

我创建了一个加载器,它允许我简单地将我需要的图像添加到堆栈中,然后加载器将一个接一个地加载图像。如果用户滚动得相当慢,这可以正常工作。我的加载器会在完成后释放内存,所以无论我加载多少图像,只要我指定要存储在内存中的最大图像,应用程序通常不会崩溃。我的加载器可以非常快速地加载图像,但仍有几毫秒(~250ms)的时间将大图像加载到内存中。当然,加载器在不同的线程上,加载绝不会阻碍 UI 响应。这就是为什么如果用户快速来回滑动,实际上不会显示任何图像,因为加载和卸载都在同时工作,导致没有图像:)

所以,我的问题是:如何在不将所有图像加载到内存的情况下提供平滑且用户满意的图像旋转?

4

3 回答 3

4

不要加载(或存储)您不需要的分辨率。如果您的用户需要缩放,内存不足的二进制图像金字塔是一种便宜的方法,可以让您仅加载必要的缩放级别。如果您的用户需要平移大于您的显示区域的图像,您可以将大图像分成较小的图块,并仅加载您需要的图块。

如果你想变得花哨,你可以编写一个 UI 感知缓存管理器来抢先加载你认为你可能很快需要的切片,并标记你很确定很快不需要的切片以进行抢占。

更好的压缩可以将更多的图像数据放入内存,并加快加载时间。所以,要注意个别图片压缩,也不要加载你不需要的图片质量。

作为一项非凡的措施:由于角度略有不同的图像彼此相似,因此您可以通过表示差异来节省时间和空间,而不是 - 查找光场压缩。您仍然需要将压缩形式转换为可以绘制的特定位图,但如果压缩允许数据集保留在内存中,您可能会获得很大的速度。

如果您无法将压缩数据集放入内存,则用户很有可能能够足够快地来回滑动以破坏您的缓存。因此,如果平滑度是您的主要目标,您可以尝试通过将旋转速率(或每次滑动旋转范围?)限制为数据加载器可以遵循的“UI 解决方案”。

于 2012-06-14T19:58:25.463 回答
1

我唯一的建议是有效地加载它们。我假设您正在使用此处描述的技术

如果图像的分辨率高于屏幕,您可以计算要渲染的图像的样本大小,然后您可以加载适合您的屏幕的图像,而不是使用更少内存的全尺寸图像。如果您已经这样做了,那么对我来说,您似乎已经在有效地做这件事了。也许您可以在加载图像时向用户显示某种占位符图形,这样他们就不会只有空白空间。

于 2012-06-14T19:57:27.100 回答
0

感谢您的回答。我自嘲一笑,看完答案就上床睡觉了。让我分享一下我是如何解决这个问题的——它使用了一些答案:

我试图在内存中缓存大图像 - 这是不必要的,为什么不存储较低分辨率的版本,然后在用户停止滚动时加载高分辨率?然后用户可以随心所欲地滚动,并且内存中总会有图像可以快速绘制。当用户停止/减慢滚动时,我们会加载高分辨率图像。

因为他会快速滚动,他将无法看到较低分辨率的较低质量。而且,由于只有一个高分辨率要加载,因此约 250 毫秒的延迟几乎不会引起注意。

这确实结合了两种情况的优点。我可以使用 Android 的方法来加载较低分辨率版本的位图。

于 2012-06-16T22:55:08.573 回答