哪种图像格式的存储效率更高:PNG,JPEG或GIF?


Answers:


153

“记忆”和“效率”通常是误用的术语,因此,我将为您解答可能影响游戏性能的四个不同要素。

为了简化和简洁起见,我将简化太多的事情,但是下面的文本中有很多错误之处,因此请捏一些盐。但是,主要概念应该是可以理解的。

存储

这是图像在软件发行版中消耗的大小。资源消耗的空间越多,下载(例如从您的网站下载)的时间就越长。如果要分发CD或DVD等物理介质,则可能必须在这方面进行一些认真的优化。

通常,JPEG对没有锐利边框的照片和图像进行最佳压缩。但是,由于JPEG使用有损压缩,因此图像的质量会下降(在将图像导出为JPEG时可以微调压缩级别/降级。有关更多信息,请参阅成像软件的文档)。

但是,虽然可能与JPEG一样好,但它不支持透明度。如果您要使图像可以通过其他人显示,或者想要具有不规则形状的图像,这就至关重要。GIF是一个不错的选择,但是它已被PNG所取代(GIF支持的几件事PNG不支持,但它们在游戏编程中基本上无关紧要)。

PNG支持透明性(和半透明性),在不降低质量的情况下压缩数据(即,使用无损压缩),并且压缩效果相当好,但不及JPG。

当您需要良好的压缩以及透明度时,就会出现问题。如果您不介意图像质量稍有下降,可以使用PNG量化程序(如pngquant),您可以在TinyPNG上在线对其进行测试。请记住,量化本身导致的图像质量下降与JPEG(包括量化以及其他主动技术)所造成的图像质量下降有所不同,因此请务必在多种设置下尝试两者。

如果您想最大程度地减小分发大小,则可以手动处理每个图像,如下所示:

if the image has transparency then
    try pngquant on the image
    if the results are not satisfactory then
        revert to the non-quantized image
    end
    store as PNG
else
    try storing it as JPG with different quality settings
    if no single setting yields an image of an acceptable quality then
        try pngquant on the image
        if the results are not satisfactory then
            revert to the non-quantized image
        end
        store as PNG
    else
        store as JPG
    end
end

提示:可以以一种格式存储一些图像,而以另一种格式存储其他图像。

还有其他专用格式,例如DXT,ETC和PVRTC。它们支持压缩,也可以压缩后加载到内存中,但是它们仅受特定的GPU支持,并且这些GPU中的大多数仅支持其中一个,因此除非您知道目标硬件的确切硬件规格(值得注意的情况是(支持PVRTC纹理的iPhone / iPad),则应避免使用这些格式。

程序记忆

我将其包含在此处,因为这就是“内存”的通常名称。但是,如果您的游戏使用图形加速(并且很可能是在1998年以后制作游戏),那么唯一会消耗内存的是纹理描述符(每个图像只有几个字节),这仅取决于图像的数量,而不是图像的大小或格式(这有一些警告,但大多数是无关紧要的)。

如果您的平台没有专用视频内存,没有硬件加速或其他不常见的情况,则有关VRAM的下一部分将完全或部分在RAM中发生,但主要原理相同。

显存

程序运行后,将在此处存储图像。通常,这里存储它们的格式没有什么区别,因为所有图像在加载到视频存储器之前都已解压缩。

现在,映像消耗的VRAM大致是width * height * bitdepth 针对 VRAM中加载的每个映像。这里有几件事要注意:

  1. 在VRAM中存储图像的宽度和高度不一定与原始图像的宽度和高度匹配。某些GPU只能处理大小为2的幂的纹理,因此您的320x240图像实际上可能存储在VRAM的512x256空间中,有效地浪费了未使用的内存。有时甚至不允许加载大小不是2的幂的纹理(例如在GLES 1.1中)。

    因此,如果要最大程度地减少VRAM的使用,则可能需要考虑对图像进行地图集处理,并以2的幂进行调整大小,这还具有在渲染时减少渲染状态更改的优点。稍后再详细介绍。

  2. 位深度非常重要。通常,纹理以32位ARGB或32位XRGB的形式加载到VRAM中,但是如果您的硬件可以支持16位深度,并且您不介意位深度较低,则可以将每个图像消耗的VRAM数量减少一半,这可能是一件有趣的事情。

  3. 但是无论您做什么,考虑游戏使用的VRAM数量时,最重要的因素是给定时间VRAM中的图像数量。如果您想要一款性能出色的游戏,那么您最有可能希望将其保持在最低水平。将纹理加载和卸载到VRAM中非常昂贵,因此,在使用每一个图像时都不能仅仅加载它。您必须在预加载您最有可能使用的图像与确定您不再要使用它们的图像之间卸载之间找到平衡。做到这一点并非易事,您必须考虑自己针对特定游戏的策略。

执行速度

即使不是“内存”,它也与游戏性能密切相关。绘制图像非常昂贵,并且您要确保渲染运行尽可能快。当然,在这里,格式无关紧要,但是其他事情却可以:

  1. 图像尺寸(实际上是“采样尺寸”):要绘制的图像区域越大,则绘制图像所花费的时间就越多。在屏幕的一小部分中渲染大图像效果不是很好,因此存在一种称为mipmapping的技术,该技术包括通过交易VRAM来提高渲染速度,方法是将图像以多种分辨率存储几次,并使用最小的分辨率在任何给定时间为您提供所需的质量。可以在加载映像时执行Mipmapping,这会影响加载速度和VRAM的使用,或者在预处理时(通过手动存储同一映像的不同版本,或使用本机支持mipmapping的格式(例如DDS))会影响存储。和VRAM的使用,但对加载速度几乎没有影响。

  2. 渲染状态更改。您很可能希望同时在屏幕上绘制几个不同的图像。但是,GPU在任何给定时间只能使用一个源图像(这是不正确的,但请在这里与我联系)。当前用于渲染的图像是许多渲染状态之一,并且价格昂贵。因此,如果您打算多次使用同一张图片(还记得我提到的纹理地图集吗?),如果您在更改渲染状态并开始使用a之前尽可能多地重复使用图片,则会发现性能获得了巨大的提升。不同的图像(除此之外还有其他渲染状态,在增强游戏性能时,微调绘制对象的顺序以最小化渲染状态变化是很常见的活动)

但是,图像使用优化是一个非常复杂的主题,我在这里写的内容是对编写游戏时必须考虑的一些因素的广泛而过分简化的概述,因此,我认为最好保持简洁是最好的选择,并且仅在真正需要的时候进行优化。在大多数情况下,过早的优化是不必要的(有时甚至是有害的),因此请放轻松。


25
+1。这是一个非常全面的答案,涉及很多领域。我不确定纹理描述符的大小是否需要足够的空间,并且DXT / ETC / PVRTC提及的内容确实应该包括每个仅在某些平台上有效的-它们不是跨平台开放的JPEG,PNG和GIF的使用方式随处可见。但总体而言,印象非常深刻。这不仅仅是我的答案上方的“一个小注释”!:D
特雷弗·鲍威尔

9
@PandaPajama:也许不是,但这是一个比这个问题应有的好得多的答案。
马克·托马斯

1
+1,如果可以的话。这是一个了不起的答案,应该成为任何有关“内存效率”问题的标准参考,因为它有效地揭穿了一个常识,即使用更少的内存永远是最好的方法,而不仅仅是图像。我建议添加的一项内容是,在非加速情况下,如果在绘制时需要即时解压缩,则可能会导致性能开销不可接受。
Maximus Minimus 2013年

2
我想建议PNGGauntlet。它可以对PNG文件大小进行大量的无损优化,这些优化可能加起来,尤其是当您有很多精灵时。可悲的是,它仅适用于Windows,但其他操作系统的替代方案已列在主页上。
orlp

1
@DavidDimalanta我没有libgdx的经验,但是正如我从的文档中可以看到的那样setEnforcePotImages,它禁用了OpenGLES 1.0的2种大小纹理的增强功能。这不是一个好主意,因为并非所有硬件都支持非2幂幂纹理。OpenGLES 2.0需要支持非2次幂纹理,因此,如果您的目标是2.0,则可以使用任何大小的纹理。有关更多信息,请参考libgdx文档。
2013年

26

一旦将图像从磁盘上加载并格式化以进行渲染,它将使用相同数量的内存,而不管该图像是使用PNG,JPEG还是GIF保存到磁盘的。

一般经验法则:JPEG是一种有损格式,会降低图像质量,从而使磁盘上的图像变小。另一方面,PNG是无损图像格式,因此通常会导致磁盘上的文件更大。从技术上讲,GIF也是一种无损格式,但是每个图像最多支持256种颜色,因此如果将彩色图像另存为GIF,则通常会导致质量下降。

但是,这仅用于磁盘上的表示。在内存中,无论您将它们以PNG,JPEG还是GIF格式保存到磁盘上,它们都将使用相同的内存量扩展为相同的纹理格式。


因此,改变文件大小的不是文件扩展而是文件大小?
Tredecies Nocturne

都不行 内存中的大小取决于图像尺寸和位深度。将图像加载到内存中以绘制到屏幕时,将删除图像文件上的所有压缩。(因为GPU无法渲染PNG或JPEG等。图像被扩展为通用像素图,以便GPU可以处理它们。)
Trevor Powell

2
这不是100%正确。大多数现代GPU(包括嵌入式GPU)都支持将压缩纹理加载并存储在图形内存中,其中DXT,ETC和PVRTC等格式是嵌入式世界中最常见的格式。当然,您必须首先以这些格式存储纹理,而不是PNG / JPG / GIF。
2013年

6
这个问题是在PNG / JPG / GIF之间的一个明确选择,我所知道的任何GPU本身都不支持它们。最初的提问者在区分磁盘上的文件大小和RAM中占用的空间方面遇到了很多麻烦,我觉得添加更多文件格式只会使基本问题感到困惑。不过,请随意提供您自己的答案。
Trevor Powell,

2
我的评论只是一个注释。如果我要提供答案,我很可能会写出与您相同的文字,加上我的评论作为最后的闭幕词。我没有其他要添加的内容,因此我将通过提供自己的答案来避免重复。
熊猫睡衣

3

这取决于。

Jpeg对照片最有效。它不是无损的,但是在此用例中,压缩引入的工件最少可见。

对于具有锐利线条和少量颜色的像素艺术,PNG是无损且最有效的。它还支持Alpha透明度。

GIF不能做任何事情,PNG不能做的更好,除了能够存储动画。但这仅与Web应用程序相关。在游戏开发中,通常使用Spritesheet来创建动画。

请注意,当您使用诸如Libgdx之类的图形引擎时,很有可能会在加载图像后立即解压缩图像,然后将它们作为未压缩的RGBA值保留在内存中。因此,图像格式仅与加载速度有关,并且具有驱动器空间(或通过网络发送图像时占用的带宽)。


2

我对libgdx不太了解,但是对图像格式和图形了解不多:

JPEG在真实照片中非常好。它们是有损的,但是除非您用清晰的彩色空间(如书面文字或漫画)拍摄锐利边缘的照片,否则您不会在照片上看到人工痕迹。将它们用于大型背景图形。

GIF已过时,它只能存储具有一种专用颜色的调色板颜色(每个像素最多8位),以实现完全透明。它允许基于帧的小动画。曾经有一种关于其打包算法的专利,因此不能合法地在任何地方使用它。由于该专利,开发了PNG。

PNG或多或少是可以存储RGB + alpha(最大32bit)和其他像素格式的压缩位图。它专门用于快速解压缩图片的一小部分,这对于非常小的和慢速的设备(例如10岁的手机)来说很方便,但是今天的库在加载时只是将它们解压缩为位图。

PNG在大小,速度和功能方面比GIF更好,但是,如果您想有效地存储位图,我建议:.PNM.BZ2([由于不同的打包方法,.PNM.BZ2并不总是效率更高比.PNG。[/ edit])

PNM / PBM / PGM / PAM是具有纯文本KISS标题的纯位图格式。在这些文件上使用gzip将导致文件大小类似于PNG,因此bzip2是更好的解决方案。如果要在程序内部使用位图,则可能要在.tar或.zip容器中使用bzip2压缩的位图。如果没有bzip2,则在zip容器(压缩程度最高的zip)中使用PNM可能与使用PNG相似。–因此,将PNG存储在ZIP文件中可能只会带来很小的好处,或者没有任何好处–很可能只会增加加载图像的时间。

除此之外,将多个小图片/图片存储在一个位图中是一个不错的选择,尤其是当您在相同的情况下都需要它们时。


PNM文件是否可用于所有智能手机操作系统和台式计算机操作系统?
大卫·迪玛兰塔

1
@David Dimalanta:我不知道在哪里支持它,在哪里不支持。如果要使用PNM编程,则很少使用任何库,因为该格式太简单了,无法选择任何API。因此,它可以使用支持读写二进制文件的所有现有编程语言进行读写。当然,您可以在任何操作系统上使用Netpbm,不仅限于Unix。另一方面,我不知道哪些通用图像库不支持此功能。它不是压缩格式,因此无论如何很少用于将图像存储在磁盘上。参见en.wikipedia.org/wiki/Netpbm_format
2013年

1

作为存储格式,JPEG可能是草木或墙壁等某些纹理的最佳选择,在这些纹理中信息丢失可能是无法检测到的。当您需要透明性或无法在信息丢失的情况下付款(例如2D游戏中的精灵(玩家,敌人,宝库))时,紧随其后的是PNG,您可能希望对图像使用PNG。

在谈到内存成本时,用于在文件系统中存储游戏图形的格式根本不相关。如果将像素缓冲区存储在VRAM或RAM(软件渲染器)中,则可能会将它们存储为未压缩状态,因为游戏倾向于快速读取像素而不是每个像素缓冲区所使用的内存。

将压缩数据存储在内存中没有任何意义,除非您维护某种缓存以保存磁盘读取,但是对于游戏中给定时间使用的图像,您可能必须从该缓存读取到未压缩状态。

如果可以进行快速的硬件解码,则压缩后的图像数据更具意义。至少对于法线贴图,我记得这个http://en.wikipedia.org/wiki/3Dc。这样,您可以保存一些VRAM。我还不知道其他硬件解码示例。

在简历中:无论您的游戏将图形存储在永久性存储中的格式是什么,您都必须对其进行解码并在动态内存,视频内存或两者中保持未压缩的版本,以便能够在需要时快速渲染它们。

最后:我是桌面专家。当我说“内存”时,我总是指动态内存。当我说“磁盘”,“文件系统”或“永久性存储”时,我总是指您的设备用作永久性存储的任何东西,通常我认为是在硬盘中。当您说“内存效率”时,我将其用于“动态内存”而不是“持久存储”。最近,我看到很多人使用“内存”一词来指代“永久存储”(也许是移动设备的术语?)。


是否可能不是JPEG也不影响PNG而是影响文件大小?
Tredecies Nocturne

是。您可以考虑节省磁盘空间或带宽来选择任何讨论的格式。当将图像加载到游戏中时,我知道的任何库/引擎都会将其解码为未压缩的像素缓冲区(将像素缓冲区视为RGB或RGBA值的数组,如果每个通道使用32位,则每个通道通常在RAM / VRAM中占用1字节)像素,这可能是每个人都在做的事情)。
Hatoru Hansou 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.