多年来,我经常问自己为什么游戏开发者会将许多小图片放入一个大图片中。但不仅游戏开发者这样做。我还记得好的旧Winamp MP3播放器有一个用户界面设计文件,这只是一个包含许多小图片的巨大图像。
我也看过一些使用这种技术的大型javascript GUI库,比如ext.js。在ext.js中有一个包含许多小图像的大图像。
我注意到的一件事是:无论我的PNG图像有多小,Mac上的Finder总是告诉我它消耗至少4kb。如果你只有10个像素,那就太多了。
这样做是因为将20个或更多的小图像存储到一个大图像中比具有20个单独的文件更加节省内存,每个文件可能都有自己的标题和元数据吗?
是因为在文件系统上定位文件既昂贵又缓慢,因此只需将一个大图像定位,然后将其分割成较小的图像,一旦加载到内存中,就会快得多?
或者它是否是懒惰,因为想到这么多文件名是很乏味的?
这个技术有名吗?那些小图像在运行时如何与大图像分离?
答案 0 :(得分:4)
这称为spriting - 在不同的情况下有各种各样的理由。
对于Web开发,这意味着只需要一个 Web请求来获取图像,这可能比几个单独的请求更有效。由于个别请求的开销较小,效率更高,最终的图像文件总体上可能比其他方式更小。
在其他场景中可以看到可能的相同效果 - 例如,根据文件系统,存储和加载单个大图像文件可能比多个小图像文件更有效。这完全搁置从原始“总文件大小”获得的任何效率,并且是由于每个文件开销(目录条目,块大小等)。这有点像Web场景中的“按请求”开销,但由于因素略有不同。
答案 1 :(得分:2)
4kb的使用是文件存储在磁盘上的副作用。文件系统中存储的最小可寻址位是块,通常是512,1024,2048等固定大小的字节。在Mac的情况下,它使用4k块。这意味着即使一个1字节的文件也需要至少4k字节的物理空间来存储,因为文件系统不可能寻址小于4k的任何存储单元。
这些“大”块的原因各不相同,但最重要的是你的寻址越“细化”(块越小),你在索引上浪费的空间越多,列出哪些块被分配给哪些文件。如果您有1字节大小的块,那么对于存储在文件中的每个数据字节,您还需要在文件系统的元数据中存储1个字节以上的使用信息,并且您最终会浪费至少浪费除了索引之外,你的存储空间只有一半。
反之亦然 - 块越大,您存储的每个小于一块大小的文件浪费的空间就越多,因此最终归结为您愿意接受的权衡。
答案 2 :(得分:2)
这些答案都不对。我们将多个图像打包成一个大的“精灵图”或“纹理图集”的原因是为了避免在渲染过程中交换纹理。
当您从一个图像(纹理)和切换到另一个图像时,OpenGL和Direct-X会受到性能影响,因此我们将多个图像打包成一个大图像然后我们可以绘制几个(或数百个)图像而从不切换纹理。它与4K文件大小无关(或者在15年内没有)。
此外,直到最近,纹理必须通过2(64,128,256)的幂,如果你的游戏有很多奇怪的图像,那就浪费了很多内存。将它们包装在一个纹理中可以节省大量空间。
答案 3 :(得分:1)
不同环境下的原因有点不同。
在网络上,主要原因是减少了对Web服务器的请求数量。每个请求都会产生开销,最明显的是通过网络进行单独的往返。
从良好的机械硬盘驱动器中获取良好的读取性能需要连续的数据。如果您将数据保存在大量文件中,则每个文件都会获得额外的搜索时间。还需要考虑块大小。文件由块组成,在您的情况下为4kB。读取一个字节的文件时,无论如何都需要读取整个块。如果你有许多小图像,你可以在一个磁盘块中填充一大堆图像,并在同一时间内完成它们,就好像你在块中只有一个小图像一样。
答案 4 :(得分:1)
昔日的另一个原因是托盘。
如果您拍摄了一张图片,可以使用一个托盘来设置图片颜色= 14 =浅灰色并带有一丝绿色。
如果你做了很多小图片,你必须确保在设计它们时为每一个使用相同的托盘,或者你得到了各种各样的文物。
如果您有一个托盘,那么您可以操纵它,因此当前绿色的所有东西都可以变成红色,方法是在托盘中翻转一个值,而不是拖过每个图像。
许多简单的动画如火,烟,自来水仍然采用这种方法。